BDOS.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /* Bart's Drive Operating System(BDOS)
  2. * A relatively simple OS that allows for some basic features including:
  3. * - Running a single user program with full hardware control
  4. * - Some system calls
  5. * - A basic shell
  6. * - Network loaders for sending data and controlling the FPGC
  7. * - HID fifo including USB keyboard driver
  8. */
  9. /* List of reserved stuff:
  10. - Timer2 is used for USB keyboard polling, even when a user program is running
  11. - Socket 7 is used for netHID
  12. */
  13. /*
  14. * Defines (also might be used by included libraries below)
  15. */
  16. // As of writing, BCC assigns 4 memory addresses to ints, so we should use chars instead
  17. // However, this is confusing, so we typedef it to word, since that is what it basically is
  18. #define word char
  19. #define SYSCALL_RETVAL_ADDR 0x200000 // address for system call communication with user program
  20. #define FS_LDIR_FNAME_ADDR 0x210000 // address for filename list in ldir command
  21. #define FS_LDIR_FSIZE_ADDR 0x218000 // address for filesize list in ldir command
  22. #define TEMP_ADDR 0x220000 // address for (potentially) large temporary outputs/buffers
  23. #define RUN_ADDR 0x400000 // address of loaded user program
  24. #define FS_PATH_MAX_LENGHT 256 // max length of a path
  25. // Interrupt IDs for interrupt handler
  26. #define INTID_TIMER1 0x1
  27. #define INTID_TIMER2 0x2
  28. #define INTID_UART0 0x3
  29. #define INTID_GPU 0x4
  30. #define INTID_TIMER3 0x5
  31. #define INTID_PS2 0x6
  32. #define INTID_UART1 0x7
  33. #define INTID_UART2 0x8
  34. // System call IDs
  35. #define SYSCALL_FIFO_AVAILABLE 1
  36. #define SYSCALL_FIFO_READ 2
  37. #define SYSCALL_PRINT_C_CONSOLE 3
  38. #define SYSCALL_GET_ARGS 4 // get arguments for executed program
  39. #define SYSCALL_GET_PATH 5 // get OS path
  40. #define SYSCALL_GET_USB_KB_BUF 6 // get the 8 bytes of the USB keyboard buffer
  41. /*
  42. * Global vars (also might be used by included libraries below)
  43. */
  44. // Flag that indicates whether a user program is running
  45. word BDOS_userprogramRunning = 0;
  46. // Path variable and its backup variable
  47. char SHELL_path[FS_PATH_MAX_LENGHT];
  48. char SHELL_pathBackup[FS_PATH_MAX_LENGHT];
  49. /*
  50. * Function prototypes, so they can be called in all libraries below
  51. */
  52. // These functions are used by some of the other libraries
  53. void BDOS_Backup();
  54. void BDOS_Restore();
  55. void SHELL_clearCommand();
  56. /*
  57. * Included libraries
  58. */
  59. // Data includes
  60. #include "data/ASCII_BW.c"
  61. #include "data/PS2SCANCODES.c"
  62. #include "data/USBSCANCODES.c"
  63. // Code includes
  64. #include "lib/stdlib.c"
  65. #include "lib/math.c"
  66. #include "lib/gfx.c"
  67. #include "lib/hidfifo.c"
  68. #include "lib/ps2.c"
  69. #include "lib/usbkeyboard.c"
  70. #include "lib/fs.c"
  71. #include "lib/wiz5500.c"
  72. #include "lib/netloader.c"
  73. #include "lib/nethid.c"
  74. #include "lib/shell.c"
  75. /*
  76. * Functions
  77. */
  78. // Initializes CH376 and mounts drive
  79. // returns 1 on success
  80. word BDOS_Init_FS()
  81. {
  82. if (FS_init() != FS_ANSW_RET_SUCCESS)
  83. {
  84. GFX_PrintConsole("Error initializing CH376 for FS");
  85. return 0;
  86. }
  87. delay(10);
  88. if (FS_connectDrive() != FS_ANSW_USB_INT_SUCCESS)
  89. {
  90. GFX_PrintConsole("Could not mount drive");
  91. return 0;
  92. }
  93. return 1;
  94. }
  95. // Clears all VRAM
  96. // and copies the default ASCII pattern table and palette table
  97. // also resets the cursor
  98. void BDOS_Reinit_VRAM()
  99. {
  100. GFX_initVram();
  101. GFX_copyPaletteTable((word)DATA_PALETTE_DEFAULT);
  102. GFX_copyPatternTable((word)DATA_ASCII_DEFAULT);
  103. GFX_cursor = 0;
  104. }
  105. // Initialize the W5500
  106. void BDOS_initNetwork()
  107. {
  108. word ip_addr[4] = {192, 168, 0, 213};
  109. word gateway_addr[4] = {192, 168, 0, 1};
  110. word mac_addr[6] = {0xDE, 0xAD, 0xBE, 0xEF, 0x24, 0x64};
  111. word sub_mask[4] = {255, 255, 255, 0};
  112. wiz_Init(ip_addr, gateway_addr, mac_addr, sub_mask);
  113. }
  114. // Backup important things before running a user program
  115. void BDOS_Backup()
  116. {
  117. // TODO look into what to backup
  118. }
  119. // Restores certain things when returning from a user program
  120. void BDOS_Restore()
  121. {
  122. // restore graphics (trying to keep text in window plane)
  123. GFX_copyPaletteTable((word)DATA_PALETTE_DEFAULT);
  124. GFX_copyPatternTable((word)DATA_ASCII_DEFAULT);
  125. GFX_clearBGtileTable();
  126. GFX_clearBGpaletteTable();
  127. GFX_clearWindowpaletteTable();
  128. GFX_clearSprites();
  129. // restore netloader
  130. NETLOADER_init(NETLOADER_SOCKET);
  131. }
  132. // Main BDOS code
  133. int main()
  134. {
  135. // all kinds of initialisations
  136. uprintln("BDOS_INIT"); // extra message over UART for debugging
  137. BDOS_userprogramRunning = 0; // indicate that no user program is running
  138. BDOS_Reinit_VRAM(); // start with loading ASCII table and set palette
  139. GFX_PrintConsole("Starting BDOS\n"); // print welcome message
  140. GFX_PrintConsole("Init network...");
  141. BDOS_initNetwork();
  142. GFX_PrintConsole("DONE\n");
  143. GFX_PrintConsole("Init netloader...");
  144. NETLOADER_init(NETLOADER_SOCKET);
  145. GFX_PrintConsole("DONE\n");
  146. GFX_PrintConsole("Init netHID...");
  147. NETHID_init(NETHID_SOCKET);
  148. GFX_PrintConsole("DONE\n");
  149. GFX_PrintConsole("Init USB keyboard...");
  150. USBkeyboard_init();
  151. GFX_PrintConsole("DONE\n");
  152. GFX_PrintConsole("Init filesystem...");
  153. if (!BDOS_Init_FS())
  154. return 0;
  155. GFX_PrintConsole("DONE\n");
  156. // init shell
  157. SHELL_init();
  158. // main loop
  159. while (1)
  160. {
  161. SHELL_loop(); // update the shell state
  162. NETLOADER_loop(NETLOADER_SOCKET); // update the netloader state
  163. }
  164. return 1;
  165. }
  166. // System call handler
  167. // Returns at the same address it reads the command from
  168. void syscall()
  169. {
  170. word* p = (word*) SYSCALL_RETVAL_ADDR;
  171. word ID = p[0];
  172. switch(ID)
  173. {
  174. case SYSCALL_FIFO_AVAILABLE:
  175. p[0] = HID_FifoAvailable();
  176. break;
  177. case SYSCALL_FIFO_READ:
  178. p[0] = HID_FifoRead();
  179. break;
  180. case SYSCALL_PRINT_C_CONSOLE:
  181. GFX_PrintcConsole(p[1]);
  182. p[0] = 0;
  183. break;
  184. case SYSCALL_GET_ARGS:
  185. p[0] = SHELL_command;
  186. break;
  187. case SYSCALL_GET_PATH:
  188. p[0] = SHELL_pathBackup;
  189. break;
  190. case SYSCALL_GET_USB_KB_BUF:
  191. p[0] = USBkeyboard_buffer_parsed;
  192. break;
  193. default:
  194. p[0] = 0;
  195. break;
  196. }
  197. }
  198. // Interrupt handler
  199. void interrupt()
  200. {
  201. // handle all interrupts
  202. int i = getIntID();
  203. switch(i)
  204. {
  205. case INTID_TIMER1:
  206. timer1Value = 1; // notify ending of timer1
  207. break;
  208. case INTID_TIMER2:
  209. USBkeyboard_HandleInterrupt(); // handle USB keyboard interrupt
  210. break;
  211. case INTID_UART0:
  212. break;
  213. case INTID_GPU:
  214. if (NETHID_isInitialized == 1)
  215. {
  216. // check using CS if we are not interrupting any critical access to the W5500
  217. word* spi3ChipSelect = (word*) 0xC02732;
  218. if (*spi3ChipSelect == 1)
  219. {
  220. NETHID_loop(NETHID_SOCKET); // look for an input sent to netHID
  221. }
  222. }
  223. break;
  224. case INTID_TIMER3:
  225. break;
  226. case INTID_PS2:
  227. PS2_HandleInterrupt(); // handle PS2 interrupt
  228. break;
  229. case INTID_UART1:
  230. break;
  231. case INTID_UART2:
  232. break;
  233. }
  234. // check if a user program is running
  235. if (BDOS_userprogramRunning)
  236. {
  237. // call interrupt() of user program
  238. asm(
  239. "; backup registers\n"
  240. "push r1\n"
  241. "push r2\n"
  242. "push r3\n"
  243. "push r4\n"
  244. "push r5\n"
  245. "push r6\n"
  246. "push r7\n"
  247. "push r8\n"
  248. "push r9\n"
  249. "push r10\n"
  250. "push r11\n"
  251. "push r12\n"
  252. "push r13\n"
  253. "push r14\n"
  254. "push r15\n"
  255. "savpc r1\n"
  256. "push r1\n"
  257. "jump 0x400001\n"
  258. "; restore registers\n"
  259. "pop r15\n"
  260. "pop r14\n"
  261. "pop r13\n"
  262. "pop r12\n"
  263. "pop r11\n"
  264. "pop r10\n"
  265. "pop r9\n"
  266. "pop r8\n"
  267. "pop r7\n"
  268. "pop r6\n"
  269. "pop r5\n"
  270. "pop r4\n"
  271. "pop r3\n"
  272. "pop r2\n"
  273. "pop r1\n"
  274. );
  275. return;
  276. }
  277. else // code to only run when not running a user program
  278. {
  279. }
  280. }