Advertisement
Astranome

AlTair9

Jul 28th, 2020
321
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.41 KB | None | 0 0
  1. /*
  2.   Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - www.fabgl.com
  3.   Copyright (c) 2019-2020 Fabrizio Di Vittorio.
  4.   All rights reserved.
  5.  
  6.   This file is part of FabGL Library.
  7.  
  8.   FabGL is free software: you can redistribute it and/or modify
  9.   it under the terms of the GNU General Public License as published by
  10.   the Free Software Foundation, either version 3 of the License, or
  11.   (at your option) any later version.
  12.  
  13.   FabGL is distributed in the hope that it will be useful,
  14.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.   GNU General Public License for more details.
  17.  
  18.   You should have received a copy of the GNU General Public License
  19.   along with FabGL.  If not, see <http://www.gnu.org/licenses/>.
  20.  */
  21.  
  22.  
  23.  
  24.  /*
  25.   * Optional SD Card connections:
  26.   *   MISO => GPIO 16
  27.   *   MOSI => GPIO 17
  28.   *   CLK  => GPIO 14
  29.   *   CS   => GPIO 13
  30.   *
  31.   * To change above assignment fill other paramaters of FileBrowser::mountSDCard().
  32.   */
  33.  
  34.  
  35.  
  36. #include <Preferences.h>
  37.  
  38. #include "fabgl.h"
  39. #include "fabutils.h"
  40.  
  41. #include "src/machine.h"
  42.  
  43.  
  44.  
  45. // Flash and SDCard configuration
  46. #define FORMAT_ON_FAIL     true
  47. #define SPIFFS_MOUNT_PATH  "/flash"
  48. #define SDCARD_MOUNT_PATH  "/SD"
  49.  
  50.  
  51. // Display controller (textual or bitmapped)
  52. #define USE_TEXTUAL_DISPLAYCONTROLLER
  53.  
  54.  
  55. //////////////////////////////////////////////////////////////////////////////////
  56. // 8'' disk images (338K)
  57.  
  58. // CP/M 2.2
  59. #include "disks/CPM22/cpm22_dsk.h"
  60. #include "disks/CPM22/games_dsk.h"
  61. #include "disks/CPM22/turbopascal3_dsk.h"
  62. #include "disks/CPM22/wordstar3_dsk.h"
  63. #include "disks/CPM22/wordstar4_dsk.h"
  64. #include "disks/CPM22/multiplan_dsk.h"
  65. #include "disks/CPM22/dbaseii_dsk.h"
  66. #include "disks/CPM22/BDSC_dsk.h"
  67. #include "disks/CPM22/langs_dsk.h"
  68.  
  69. // CP/M 1.4
  70. #include "disks/CPM14/cpm141_dsk.h"
  71.  
  72. // CP/M 3
  73. #include "disks/CPM3/cpm3_disk1_dsk.h"
  74. #include "disks/CPM3/cpm3_disk2_dsk.h"
  75. #include "disks/CPM3/cpm3_build_dsk.h"
  76.  
  77. // Altair DOS
  78. //   MEMORY SIZE? [insert "64"]
  79. //   INTERRUPTS? [press ENTER]
  80. //   HIGHEST DISK NUMBER? [insert "1"]
  81. //   HOW MANY DISK FILES? [insert "4"]
  82. //   HOW MANY RANDOM FILES? [insert "4"]
  83. #include "disks/AltairDOS/DOS_1_dsk.h"
  84. #include "disks/AltairDOS/DOS_2_dsk.h"
  85.  
  86. // Basic
  87. //    MEMORY SIZE? [press ENTER]
  88. //    LINEPRINTER? [insert "C"]
  89. //    HIGHEST DISK NUMBER? [press ENTER]
  90. //    HOW MANY FILES? [press ENTER]
  91. //    HOW MANY RANDOM FILES? [press ENTER]
  92. #include "disks/basic/basic5_dsk.h"
  93.  
  94. //////////////////////////////////////////////////////////////////////////////////
  95.  
  96.  
  97.  
  98. //////////////////////////////////////////////////////////////////////////////////
  99. // Mini disk images (76K)
  100.  
  101. // CP/M 2.2
  102. #include "minidisks/CPM22/cpm22_disk1_minidsk.h"
  103. #include "minidisks/CPM22/cpm22_disk2_minidsk.h"
  104.  
  105. // Basic (need i8080 CPU)
  106. //   MEMORY SIZE? [press ENTER]
  107. //   LINEPRINTER? [insert "C"]
  108. //   HIGHEST DISK NUMBER? [insert "0"]
  109. //   HOW MANY FILES? [insert "3"]
  110. //   HOW MANY RANDOM FILES? [insert "2"]
  111. #include "minidisks/basic/basic300_5F_minidisk.h"
  112.  
  113. //////////////////////////////////////////////////////////////////////////////////
  114.  
  115.  
  116.  
  117. //////////////////////////////////////////////////////////////////////////////////
  118. // Disks configuration
  119.  
  120.  
  121. // Enable this when using 8'' disk images ("disks" folder)
  122. #define DISKFORMAT Disk_338K
  123.  
  124. // Enable this when using minidisk images ("minidisk" folder)
  125. //#define DISKFORMAT MiniDisk_76K
  126.  
  127. // Specify which disk image or file name assign to drives
  128. #define DRIVE_A cpm22_dsk     // A: read only
  129. #define DRIVE_B games_dsk     // B: read only
  130. #define DRIVE_C "diskC.dsk"   // C: read/write
  131. #define DRIVE_D "diskD.dsk"   // D: read/write
  132.  
  133. //////////////////////////////////////////////////////////////////////////////////
  134.  
  135.  
  136.  
  137. // consts
  138.  
  139. constexpr int DefaultCPU         = 1;   // 0 = i8080, 1 = Z80
  140.  
  141. constexpr int DefaultTermIndex   = 2;   // Default: "ADM-31"
  142. constexpr int MaxTermIndex       = 7;   // Max: "Legacy ANSI"
  143.  
  144. constexpr int DefaultKbdLayIndex = 2;   // Default: "UK"
  145.  
  146. const char * ColorsStr[] = { "Green/Black", "Yellow/Black", "White/Black", "Black/White", "Yellow/Blue", "Black/Yellow" };
  147. const Color TextColors[] = { Color::BrightGreen, Color::BrightYellow, Color::BrightWhite, Color::Black,       Color::BrightYellow, Color::Black };
  148. const Color BackColors[] = { Color::Black,       Color::Black,        Color::Black,       Color::BrightWhite, Color::Blue,         Color::BrightYellow };
  149. constexpr int DefaultColorsIndex = 0;   // Default: Green/Black
  150. constexpr int MaxColorsIndex     = 5;
  151.  
  152.  
  153. // globals
  154.  
  155. #ifdef USE_TEXTUAL_DISPLAYCONTROLLER
  156. //fabgl::VGATextController DisplayController;
  157. fabgl::ILI9341Controller DisplayController;
  158. #else
  159. fabgl::VGAVGAController  DisplayController;
  160. #endif
  161. fabgl::PS2Controller     PS2Controller;
  162. fabgl::Terminal          Terminal;
  163.  
  164. #define TFT_SCK    18
  165. #define TFT_MOSI   23
  166. #define TFT_CS     5
  167. #define TFT_DC     22
  168. #define TFT_RESET  21
  169. #define TFT_SPIBUS VSPI_HOST
  170.  
  171. Machine              altair;
  172. Mits88Disk           diskDrive(&altair, DISKFORMAT);
  173. SIO                  SIO0(&altair, 0x00);
  174. SIO                  SIO1(&altair, 0x10);
  175. SIO                  SIO2(&altair, 0x12);
  176. Preferences          preferences;
  177.  
  178.  
  179. // base path (can be SPIFFS_MOUNT_PATH or SDCARD_MOUNT_PATH depending from what was successfully mounted first)
  180. char const * basepath = nullptr;
  181.  
  182.  
  183.  
  184.  
  185. void setTerminalColors()
  186. {
  187.   int colorsIndex = preferences.getInt("colors", DefaultColorsIndex);
  188.   Terminal.setForegroundColor(TextColors[colorsIndex]);
  189.   Terminal.setBackgroundColor(BackColors[colorsIndex]);
  190. }
  191.  
  192.  
  193. // shown pressing PAUSE
  194. void emulator_menu()
  195. {
  196.   bool resetRequired = false;
  197.   for (bool loop = true; loop; ) {
  198.  
  199.     diskDrive.flush();
  200.  
  201.     Terminal.write("\r\n\n\e[97m\e[40m                            ** Emulator Menu **\e[K\r\n\e[K\n");
  202.     Terminal.write( "\e[93m Z \e[37m Reset\e[K\n\r");
  203.     Terminal.write( "\e[93m S \e[37m Send Disk to Serial\e[K\n\r");
  204.     Terminal.write( "\e[93m R \e[37m Get Disk from Serial\e[K\n\r");
  205.     Terminal.write( "\e[93m F \e[37m Format FileSystem\e[K\n\r");
  206.     Terminal.printf("\e[93m U \e[37m CPU: \e[33m%s\e[K\n\r", preferences.getInt("CPU", DefaultCPU) == 1 ? "Z80" : "i8080");
  207.     Terminal.printf("\e[93m P \e[37m Real CPU Speed: \e[33m%s\e[K\n\r", preferences.getBool("realSpeed", false) ? "YES" : "NO");
  208.     Terminal.write("\e[6A");  // cursor UP
  209.     Terminal.printf("\t\t\t\t\t\e[93m T \e[37m Terminal: \e[33m%s\e[K\n\r", SupportedTerminals::names()[preferences.getInt("termEmu", DefaultTermIndex)] );
  210.     Terminal.printf("\t\t\t\t\t\e[93m K \e[37m Keyboard Layout: \e[33m%s\e[K\n\r", SupportedLayouts::names()[preferences.getInt("kbdLay", DefaultKbdLayIndex)] );
  211.     #ifndef USE_TEXTUAL_DISPLAYCONTROLLER
  212.     Terminal.printf("\t\t\t\t\t\e[93m G \e[37m CRT Mode: \e[33m%s\e[K\n\r", preferences.getBool("emuCRT", false) ? "YES" : "NO");
  213.     #endif
  214.     Terminal.printf("\t\t\t\t\t\e[93m C \e[37m Colors: \e[33m%s\e[K\n\r", ColorsStr[preferences.getInt("colors", DefaultColorsIndex)] );
  215.     Terminal.write( "\t\t\t\t\t\e[93m O \e[37m Reset Configuration\e[K\n\r");
  216.  
  217.     Terminal.write("\n\n\e[97mPlease select an option (ENTER to exit): \e[K\e[92m");
  218.     int ch = toupper(Terminal.read());
  219.     Terminal.write(ch);
  220.     Terminal.write("\n\r");
  221.     switch (ch) {
  222.  
  223.       // 1. Send a disk image to Serial Port
  224.       // 2. Receive a disk image from Serial Port
  225.       case 'S':
  226.       case 'R':
  227.       {
  228.         Terminal.write("Select a drive (A, B, C, D...): ");
  229.         char drive = toupper(Terminal.read());
  230.         if (ch == 'S') {
  231.           Terminal.printf("\n\rSending drive %c...\n\r", drive);
  232.           diskDrive.sendDiskImageToStream(drive - 'A', &Serial);
  233.         } else if (ch == 'R') {
  234.           Terminal.printf("\n\rReceiving drive %c...\n\r", drive);
  235.           diskDrive.receiveDiskImageFromStream(drive - 'A', &Serial);
  236.         }
  237.         break;
  238.       }
  239.  
  240.       // Format FileSystem
  241.       case 'F':
  242.         Terminal.write("Formatting filesystem removes RW disks and resets the Altair. Are you sure? (Y/N)");
  243.         if (toupper(Terminal.read()) == 'Y') {
  244.           Terminal.write("\n\rFormatting...");
  245.           Terminal.flush();
  246.           FileBrowser::format(FileBrowser::getDriveType(basepath), 0);
  247.           resetRequired = true;
  248.         }
  249.         break;
  250.  
  251.       // Reset
  252.       case 'Z':
  253.         Terminal.write("Resetting the Altair. Are you sure? (Y/N)");
  254.         if (toupper(Terminal.read()) == 'Y')
  255.           ESP.restart();
  256.         break;
  257.  
  258.       // Real CPU speed
  259.       case 'P':
  260.         preferences.putBool("realSpeed", !preferences.getBool("realSpeed", false));
  261.         altair.setRealSpeed(preferences.getBool("realSpeed", false));
  262.         break;
  263.  
  264.       // Emulate CRT
  265.       case 'G':
  266.         preferences.putBool("emuCRT", !preferences.getBool("emuCRT", false));
  267.         resetRequired = true;
  268.         break;
  269.  
  270.       // CPU
  271.       case 'U':
  272.         preferences.putInt("CPU", preferences.getInt("CPU", DefaultCPU) ^ 1);
  273.         resetRequired = true;
  274.         break;
  275.  
  276.       // Terminal emulation
  277.       case 'T':
  278.       {
  279.         int termIndex = preferences.getInt("termEmu", DefaultTermIndex) + 1;
  280.         if (termIndex > MaxTermIndex)
  281.           termIndex = 0;
  282.         preferences.putInt("termEmu", termIndex);
  283.         Terminal.setTerminalType((TermType)termIndex);
  284.         break;
  285.       }
  286.  
  287.       // Keyboard layout
  288.       case 'K':
  289.       {
  290.         int kbdLayIndex = preferences.getInt("kbdLay", DefaultKbdLayIndex) + 1;
  291.         if (kbdLayIndex >= SupportedLayouts::count())
  292.           kbdLayIndex = 0;
  293.         preferences.putInt("kbdLay", kbdLayIndex);
  294.         PS2Controller.keyboard()->setLayout(SupportedLayouts::layouts()[kbdLayIndex]);
  295.         break;
  296.       }
  297.  
  298.       // Colors
  299.       case 'C':
  300.       {
  301.         int colorsIndex = preferences.getInt("colors", DefaultColorsIndex) + 1;
  302.         if (colorsIndex > MaxColorsIndex)
  303.           colorsIndex = 0;
  304.         preferences.putInt("colors", colorsIndex);
  305.         break;
  306.       }
  307.  
  308.       // Reset configuration
  309.       case 'O':
  310.         preferences.clear();
  311.         resetRequired = true;
  312.         break;
  313.  
  314.       default:
  315.         loop = false;
  316.         break;
  317.  
  318.     }
  319.   }
  320.   if (resetRequired) {
  321.     Terminal.write("Reset required. Reset now? (Y/N)");
  322.     if (toupper(Terminal.read()) == 'Y') {
  323.       diskDrive.detachAll();
  324.       ESP.restart();
  325.     }
  326.   }
  327.   Terminal.localWrite("\n");
  328.   setTerminalColors();
  329. }
  330.  
  331.  
  332. void setup()
  333. {
  334.   preferences.begin("altair8800", false);
  335.  
  336.   Serial.begin(115200);
  337.  
  338.   // setup Keyboard (default configuration)
  339.   PS2Controller.begin(PS2Preset::KeyboardPort0);
  340.  
  341.   // setup VGA (default configuration with 64 colors)
  342.  // DisplayController.begin();
  343.  
  344.  // if (preferences.getBool("emuCRT", false))
  345.   //  DisplayController.setResolution(VGA_640x200_70HzRetro);
  346. //  else
  347.  //   DisplayController.setResolution(VGA_640x200_70Hz);
  348.   DisplayController.begin(TFT_SCK, TFT_MOSI, TFT_DC, TFT_RESET, TFT_CS, TFT_SPIBUS);
  349.   DisplayController.setResolution(TFT_240x320);
  350.   DisplayController.setOrientation(fabgl::TFTOrientation::Rotate90);
  351.   // uncomment to adjust screen alignment and size
  352.   //DisplayController.shrinkScreen(5, 0);
  353.   //DisplayController.moveScreen(-1, 0);
  354.  
  355.   Terminal.begin(&DisplayController);
  356.   Terminal.connectLocally();      // to use Terminal.read(), available(), etc..
  357.  
  358.   Terminal.setBackgroundColor(Color::Black);
  359.   Terminal.setForegroundColor(Color::BrightGreen);
  360.   Terminal.loadFont(&fabgl::FONT_6x10);
  361.   Terminal.clear();
  362.  
  363.   Terminal.enableCursor(true);
  364. }
  365.  
  366.  
  367. void loop()
  368. {
  369.   Terminal.write("Initializing filesystem...\r");
  370.   Terminal.flush();
  371.  
  372.   if (FileBrowser::mountSDCard(FORMAT_ON_FAIL, SDCARD_MOUNT_PATH))
  373.     basepath = SDCARD_MOUNT_PATH;
  374.   else if (FileBrowser::mountSPIFFS(FORMAT_ON_FAIL, SPIFFS_MOUNT_PATH))
  375.     basepath = SPIFFS_MOUNT_PATH;
  376.  
  377.   // setup disk drives
  378.  
  379.   diskDrive.attachReadOnlyBuffer(0, DRIVE_A);
  380.   diskDrive.attachReadOnlyBuffer(1, DRIVE_B);
  381.  
  382.   Terminal.write("Creating Disk C...        \r");
  383.   Terminal.flush();
  384.   diskDrive.attachFile(2, (String(basepath) + String("/") + String(DRIVE_C)).c_str());
  385.  
  386.   Terminal.write("Creating Disk D...        \r");
  387.   Terminal.flush();
  388.   diskDrive.attachFile(3, (String(basepath) + String("/") + String(DRIVE_D)).c_str());
  389.  
  390.   // setup SIOs (Serial I/O)
  391.  
  392.   // TTY
  393.   SIO0.attachStream(&Terminal);
  394.  
  395.   // CRT/Keyboard
  396.   SIO1.attachStream(&Terminal);
  397.  
  398.   // Serial
  399.   SIO2.attachStream(&Serial);
  400.  
  401.   // RAM
  402.   altair.attachRAM(65536);
  403.  
  404.   // boot ROM
  405.   altair.load(Altair88DiskBootROMAddr, Altair88DiskBootROM, sizeof(Altair88DiskBootROM));
  406.  
  407.   // menu callback (pressing PAUSE)
  408.   altair.setMenuCallback(emulator_menu);
  409.  
  410.   setTerminalColors();
  411.   Terminal.clear();
  412.  
  413.   // scrolling region (24 rows)
  414.   Terminal.write("\e[1;24r");
  415.  
  416.   Terminal.write("\e[97m\e[44m");
  417.   Terminal.write("                    /* * * * * * * * * * * * * * * * * * * *\e[K\r\n");
  418.   Terminal.write("                             A L T A I R     8 8 0 0 \e[K\r\n");
  419.   Terminal.write("                     \e[37mby Fabrizio Di Vittorio - www.fabgl.com\e[97m\e[K\r\n");
  420.   Terminal.write("                     * * * * * * * * * * * * * * * * * * * */\e[K\r\n\e[K\n");
  421.  
  422.   Terminal.printf("\e[33mFree Memory :\e[32m %d bytes\e[K\r\n", heap_caps_get_free_size(MALLOC_CAP_32BIT));
  423.  
  424.   int64_t total, used;
  425.   FileBrowser::getFSInfo(FileBrowser::getDriveType(basepath), 0, &total, &used);
  426.   Terminal.printf("\e[33mFile System :\e[32m %lld KiB used, %lld KiB free\e[K\r\n", used / 1024, (total - used) / 1024);
  427.  
  428.   Terminal.printf("\e[33mKbd Layout  : \e[32m%s\e[K\r\n", SupportedLayouts::names()[preferences.getInt("kbdLay", DefaultKbdLayIndex)] );
  429.   Terminal.printf("\e[33mCPU         : \e[32m%s\e[92m\e[K\r\n\e[K\n", preferences.getInt("CPU", DefaultCPU) == 1 ? "Z80" : "i8080");
  430.  
  431.   Terminal.printf("Press \e[93mPAUSE\e[92m to display emulator menu\e[K\r\n");
  432.  
  433.   setTerminalColors();
  434.  
  435.   // setup keyboard layout
  436.   int kbdLayIndex = preferences.getInt("kbdLay", DefaultKbdLayIndex);
  437.   PS2Controller.keyboard()->setLayout(SupportedLayouts::layouts()[kbdLayIndex]);
  438.  
  439.   // setup terminal emulation
  440.   int termIndex = preferences.getInt("termEmu", DefaultTermIndex);
  441.   Terminal.setTerminalType((TermType)termIndex);
  442.  
  443.   // CPU speed
  444.   altair.setRealSpeed(preferences.getBool("realSpeed", false));
  445.  
  446.   CPU cpu = (preferences.getInt("CPU", DefaultCPU) == 1 ? CPU::Z80 : CPU::i8080);
  447.   altair.run(cpu, Altair88DiskBootROMRun);
  448. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement