├── .gitignore ├── LICENSE.md ├── README.md ├── board.jpg ├── examples ├── README.md ├── bdos.asm ├── bdos.bin ├── filecopy.asm ├── filedma.asm ├── graphclk.bas ├── hello.asm ├── hello.hex ├── ioxblink.bas ├── lcd.bas ├── lcdclock.asm ├── rtc.bas └── z80ops.asm ├── firmware ├── .vscode │ ├── c_cpp_properties.json │ └── tasks.json ├── Doxyfile ├── Makefile ├── Makefile.jbl ├── cli │ ├── benchmark.c │ ├── cli.c │ ├── cli.h │ ├── coleco.c │ ├── cpm.c │ ├── file.c │ ├── hardware.c │ ├── impl.h │ ├── io.c │ ├── memory.c │ ├── term.c │ └── z80.c ├── emulation │ ├── bdos.c │ ├── bdos.h │ ├── disk.c │ ├── disk.h │ ├── filedma.c │ ├── filedma.h │ ├── msxkey.c │ ├── msxkey.h │ ├── simhboot.h │ ├── sio.c │ └── sio.h ├── fatfs │ ├── diskio.c │ ├── diskio.h │ ├── ff.c │ ├── ff.h │ ├── ffconf.h │ ├── ffsystem.c │ └── ffunicode.c ├── hardware │ ├── bus.c │ ├── bus.h │ ├── font.h │ ├── hardware.c │ ├── hardware.h │ ├── io.c │ ├── io.h │ ├── mcp23s17.c │ ├── mcp23s17.h │ ├── memory.c │ ├── memory.h │ ├── mmc.c │ ├── mmc.h │ ├── rtc.h │ ├── rtc_ds1302.c │ ├── rtc_ds1302.h │ ├── rtc_ds1306.c │ ├── rtc_ds1306.h │ ├── sn76489.c │ ├── sn76489.h │ ├── spi.c │ ├── spi.h │ ├── sst39sf0x0.c │ ├── sst39sf0x0.h │ ├── term.c │ ├── term.h │ ├── timer.c │ ├── timer.h │ ├── tms9918.c │ ├── tms9918.h │ ├── uart.c │ ├── uart.h │ ├── z80.c │ └── z80.h ├── util │ ├── disasm.c │ ├── disasm.h │ ├── ffwrap.c │ ├── ffwrap.h │ ├── ihex.c │ ├── ihex.h │ ├── pgmspace.h │ ├── string.c │ ├── string.h │ ├── xmodem.c │ └── xmodem.h └── z80ctrl.c └── hardware ├── classic ├── z80ctrl.kicad_pcb ├── z80ctrl.kicad_pro ├── z80ctrl.kicad_sch ├── z80ctrl_schematic_REV4.pdf └── z80ctrl_schematic_REV6.pdf ├── iox ├── README.md ├── board.jpg ├── z80ctrl-iox.kicad_pcb ├── z80ctrl-iox.kicad_pro ├── z80ctrl-iox.kicad_sch └── z80ctrl-iox.pdf ├── nextgen ├── LUTS.md ├── README.md ├── battery-half.svg ├── brain.svg ├── oshw-logo.svg ├── peripherals.kicad_sch ├── qwiic.svg ├── usb-symbol.svg ├── watch.svg ├── z80ctrlng-back.png ├── z80ctrlng-front.png ├── z80ctrlng.kicad_pcb ├── z80ctrlng.kicad_pro ├── z80ctrlng.kicad_sch └── z80ctrlng.pdf ├── z80blinken ├── activity.svg ├── lightbulb-fill.svg ├── lightbulb-off.svg ├── stoplights.svg ├── z80blinken-back.png ├── z80blinken-front.png ├── z80blinken.kicad_pcb ├── z80blinken.kicad_pro ├── z80blinken.kicad_sch ├── z80blinken.pdf └── zilog.svg └── z80ram ├── board.jpg ├── z80ram.kicad_pcb ├── z80ram.kicad_pro ├── z80ram.kicad_sch └── z80ram_schematic_REV2.pdf /.gitignore: -------------------------------------------------------------------------------- 1 | # project files 2 | *.X 3 | .vscode 4 | 5 | # archives 6 | *.zip 7 | 8 | # Compiler output 9 | *.o 10 | *.su 11 | *.elf 12 | *.hex 13 | *.bin 14 | 15 | # Assembler output 16 | *.lst 17 | *.out 18 | *.err 19 | 20 | # For PCBs designed using KiCad: http://www.kicad-pcb.org/ 21 | # Format documentation: http://kicad-pcb.org/help/file-formats/ 22 | 23 | # Temporary files 24 | *.000 25 | *.bak 26 | *.bck 27 | *.lck 28 | *.kicad_pcb-bak 29 | *.kicad_sch-bak 30 | *-backups 31 | *.kicad_prl 32 | *.sch-bak 33 | *~ 34 | _autosave-* 35 | *.tmp 36 | *-save.pro 37 | *-save.kicad_pcb 38 | fp-info-cache 39 | 40 | # Netlist files (exported from Eeschema) 41 | *.net 42 | 43 | # Autorouter files (exported from Pcbnew) 44 | *.dsn 45 | *.ses 46 | 47 | # Exported BOM files 48 | *.xml 49 | *.csv 50 | 51 | # MacOS Artifacts 52 | .DS_Store 53 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # z80ctrl Credits 2 | 3 | ## [z80ctrl](https://github.com/jblang/z80ctrl) (MIT License) 4 | > Copyright 2018-2023 J.B. Langston 5 | > 6 | > Permission is hereby granted, free of charge, to any person obtaining a 7 | > copy of this software and associated documentation files (the "Software"), 8 | > to deal in the Software without restriction, including without limitation 9 | > the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | > and/or sell copies of the Software, and to permit persons to whom the 11 | > Software is furnished to do so, subject to the following conditions: 12 | > 13 | > The above copyright notice and this permission notice shall be included in 14 | > all copies or substantial portions of the Software. 15 | > 16 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | > FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | > DEALINGS IN THE SOFTWARE. 23 | 24 | 25 | ## [FatFS](http://elm-chan.org/fsw/ff/) (FatFS License) 26 | > Copyright (C) 2022, ChaN, all right reserved. 27 | > 28 | > FatFs module is an open source software. Redistribution and use of FatFs in 29 | > source and binary forms, with or without modification, are permitted provided 30 | > that the following condition is met: 31 | > 32 | > 1. Redistributions of source code must retain the above copyright notice, 33 | > this condition and the following disclaimer. 34 | > 35 | > This software is provided by the copyright holder and contributors "AS IS" 36 | > and any warranties related to this software are DISCLAIMED. 37 | > The copyright owner or contributors be NOT LIABLE for any damages caused 38 | > by use of this software. 39 | 40 | 41 | ## [Altair Disk Emulation](https://github.com/open-simh/simh/blob/master/AltairZ80/altairz80_dsk.c) (MIT License) 42 | > Copyright (c) 2018-2023, J.B. Langston 43 | > 44 | > Copyright (c) 2002-2014, Peter Schorn 45 | > 46 | > Copyright (c) 1997-2010, Charles E. Owen 47 | > 48 | > Permission is hereby granted, free of charge, to any person obtaining a 49 | > copy of this software and associated documentation files (the "Software"), 50 | > to deal in the Software without restriction, including without limitation 51 | > the rights to use, copy, modify, merge, publish, distribute, sublicense, 52 | > and/or sell copies of the Software, and to permit persons to whom the 53 | > Software is furnished to do so, subject to the following conditions: 54 | > 55 | > The above copyright notice and this permission notice shall be included in 56 | > all copies or substantial portions of the Software. 57 | > 58 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 61 | > ROBERT M SUPNIK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 62 | > IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63 | > CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 | > 65 | > Except as contained in this notice, the names of the authors shall not be 66 | > used in advertising or otherwise to promote the sale, use or other dealings 67 | > in this Software without prior written authorization from the authors. 68 | 69 | 70 | ## [X/Ymodem Protocol](https://www.menie.org/georges/embedded/#xmodem) (3-clause BSD License) 71 | > Copyright 2001-2010 Georges Menie (www.menie.org) 72 | > 73 | > All rights reserved. 74 | > 75 | > Ymodem support Copyright 2018-2023 J.B. Langston 76 | > 77 | > Redistribution and use in source and binary forms, with or without 78 | > modification, are permitted provided that the following conditions are met: 79 | > 80 | > * Redistributions of source code must retain the above copyright 81 | > notice, this list of conditions and the following disclaimer. 82 | > * Redistributions in binary form must reproduce the above copyright 83 | > notice, this list of conditions and the following disclaimer in the 84 | > documentation and/or other materials provided with the distribution. 85 | > * Neither the name of the University of California, Berkeley nor the 86 | > names of its contributors may be used to endorse or promote products 87 | > derived from this software without specific prior written permission. 88 | > 89 | > THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY 90 | > EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 91 | > WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 92 | > DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 93 | > DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 94 | > (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 95 | > LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 96 | > ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 97 | > (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 98 | > SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 99 | 100 | ## PCB Artwork 101 | 102 | - [Machine learning icons created by Freepik - Flaticon](https://www.flaticon.com/free-icons/machine-learning). Attribution required. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # z80ctrl 2 | 3 | z80ctrl is an AVR-based bootloader, debugger, and I/O device for a Z80 retrocomputer with the following features: 4 | 5 | - Plug-in module for [RC2014](https://rc2014.co.uk/) retrocomputer replaces the clock, serial, ROM, and CF boards 6 | - Runs CP/M software directly from FAT32-formatted SD Card 7 | - Boots unmodified disk images from the [AltairZ80](https://schorn.ch/altair.html) emulator 8 | - Monitor with file management, memory inspector, and built-in Z80 disassembler 9 | - Single-step debugging, breakpoints, and watchpoints to trace Z80 bus activity in real-time 10 | - Expandable SPI bus allows bridging other SPI peripherals to the Z80 11 | - Flexible MIT-licensed firmware can be the basis of your own SBC or breadboard computer 12 | 13 | [![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/sVV1PYWX18A/0.jpg)](https://www.youtube.com/watch?v=sVV1PYWX18A) 14 | 15 | ## Documentation 16 | 17 | Much of the information that was previously here has been moved to separate wiki pages: 18 | 19 | - [Board Assembly Instructions](https://github.com/jblang/z80ctrl/wiki/Board-Assembly-Instructions) 20 | - [Monitor User Guide](https://github.com/jblang/z80ctrl/wiki/Monitor-User-Guide) 21 | - [Known Issues](https://github.com/jblang/z80ctrl/wiki/Known-Issues) 22 | - [Hardware Design Notes](https://github.com/jblang/z80ctrl/wiki/Hardware-Design-Notes) 23 | - [Software Design Notes](https://github.com/jblang/z80ctrl/wiki/Software-Design-Notes) 24 | - [IO Expander Board](https://github.com/jblang/z80ctrl/wiki/IO-Expander-Board) 25 | - Check the [Wiki Index](https://github.com/jblang/z80ctrl/wiki) for other topics. 26 | 27 | 28 | ## Off-Site Resources 29 | 30 | - [Hackaday Project Page](https://hackaday.io/project/158338-z80ctrl) with blog articles about various features. 31 | - [YouTube Playlist](https://www.youtube.com/watch?v=M8EIAxMpA-o&list=PLwP_dSEH4Oi_jAljWQ1H-TBiBL34LqYYm) 32 | - [RC2014 Google Group](https://groups.google.com/forum/#!forum/rc2014-z80). Search for z80ctrl to find previous discussion threads. 33 | - [retro-comp Google Group](https://groups.google.com/g/retro-comp) 34 | 35 | ## License 36 | 37 | Copyright 2018-2020 J.B. Langston 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 40 | 41 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 42 | 43 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 44 | -------------------------------------------------------------------------------- /board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/board.jpg -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # z80ctrl Example Programs 2 | 3 | These are some example programs that demonstrate features of the z80ctrl and the I/O expander add-on card. 4 | 5 | ## Assembling 6 | 7 | I have tried to stick to a common subset of assembler features that will work with any of the following cross-assemblers: 8 | 9 | - [Sjasm](http://www.xl2s.tk/): Windows binaries available for download. Compiles on Linux using sources on [Github](https://github.com/Konamiman/Sjasm). 10 | - [SjasmPlus](https://sourceforge.net/projects/sjasmplus/): Windows binaries available for download. Compiles on Linux using sources on [Github](https://github.com/sjasmplus/sjasmplus). 11 | - [z80asm](https://www.nongnu.org/z80asm/): Binaries available in the Debian repository. Mac binaries on [Homebrew](https://brew.sh/). Compiles on Windows. 12 | - [z88dk](https://github.com/z88dk/z88dk)'s z80asm (not to be confused with above). Windows and Mac binaries available for download. Compiles on Linux. 13 | - [pasmo](http://pasmo.speccy.org/): Windows and Mac binaries available for download. Binaries available in the Debain repository. 14 | 15 | My preferred assembler is sjasm. I try to maintain compatibility with all of the above, but may not always test every change against the others. If you have trouble assembling with any of the above, please try sjasm, and file a bug to let me know about the problem. 16 | 17 | ## About the Programs 18 | 19 | - `graphclk.bas`: MSX-BASIC program draws a graphical clock on TMS9918A with time read from RTC. 20 | - `hello.asm`: Simple hello world assembly program that uses the Altair UART emulation. 21 | - `ioxblink.bas` MBASIC program that blinks an LED using the I/O expander. 22 | - `lcd.bas`: MBASIC program that prompts for a string and prints it on an LCD hooked up to the I/O expander. 23 | - `lcdclock.asm`: Assembly program that reads date/time from RTC and displays it on an LCD hooked up to the I/O expander. 24 | - `rtc.bas`: MBASIC program that reads the date/time from RTC and prints it on the console. 25 | - `z80ops.asm`: Assembly program with all Z80 opcodes, for testing disassembler. -------------------------------------------------------------------------------- /examples/bdos.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/examples/bdos.bin -------------------------------------------------------------------------------- /examples/filecopy.asm: -------------------------------------------------------------------------------- 1 | ; z80ctrl (https://github.com/jblang/z80ctrl) 2 | ; Copyright 2018 J.B. Langston 3 | ; 4 | ; Permission is hereby granted, free of charge, to any person obtaining a 5 | ; copy of this software and associated documentation files (the "Software"), 6 | ; to deal in the Software without restriction, including without limitation 7 | ; the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | ; and/or sell copies of the Software, and to permit persons to whom the 9 | ; Software is furnished to do so, subject to the following conditions: 10 | ; 11 | ; The above copyright notice and this permission notice shall be included in 12 | ; all copies or substantial portions of the Software. 13 | ; 14 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | ; DEALINGS IN THE SOFTWARE. 21 | 22 | org 100h 23 | 24 | ramtop: equ 0ffffh 25 | uarts: equ 10h 26 | uartd: equ 11h 27 | lf: equ 0ah 28 | cr: equ 0dh 29 | buflen: equ 32*1024 30 | 31 | jp start 32 | 33 | include "filedma.asm" 34 | 35 | start: 36 | ld hl, ramtop ; set up stack 37 | ld sp, hl 38 | 39 | call f_init ; initialize file DMA mailbox 40 | 41 | f_setw f_outaddr, filebuf ; set up file buffer 42 | f_setw f_maxlen, buflen 43 | 44 | call f_cli_first ; get command-line arguments 45 | cp 3 ; verify that there are at least 2 params 46 | jp c, usage ; if not, show usage 47 | 48 | call f_cli_next ; get pointer to first filename 49 | ld (f_inaddr), de 50 | 51 | f_setw f_fpaddr, sourcefp ; open source file for reading 52 | f_setb f_mode, FA_READ 53 | f_call F_OPEN 54 | jp nz, error 55 | 56 | call f_cli_next ; get pointer to second filename 57 | ld (f_inaddr), de 58 | 59 | f_setw f_fpaddr, destfp ; open destination file for writing 60 | f_setb f_mode, FA_WRITE | FA_CREATE_NEW 61 | f_call F_OPEN 62 | jp nz, error 63 | 64 | f_setw f_inaddr, filebuf ; set input address back to beginning of buffer 65 | 66 | loop: 67 | f_setw f_fpaddr, sourcefp ; fill buffer with bytes from source 68 | f_call F_READ 69 | jp nz, error 70 | 71 | f_setw f_fpaddr, destfp ; write bytes from buffer to destination 72 | f_cpyw f_maxlen, f_retlen ; copy number of bytes returned by read 73 | f_call F_WRITE 74 | jp nz, error 75 | 76 | ld hl, buflen ; check whether last read was less than full buffer 77 | ld de, (f_maxlen) 78 | or a 79 | sbc hl, de 80 | add hl, de 81 | jp z, loop ; if not, go again 82 | jp close 83 | 84 | usage: 85 | ld hl, usage_text ; print usage 86 | call strout 87 | jp close 88 | 89 | error: 90 | call f_error ; print error message 91 | ex de, hl 92 | call strout 93 | ld hl, crlf 94 | call strout 95 | 96 | close: 97 | f_setw f_fpaddr, sourcefp 98 | f_call F_CLOSE ; close the source file 99 | f_setw f_fpaddr, destfp 100 | f_call F_CLOSE ; close the file 101 | 102 | halt 103 | 104 | ; output null-terminated string 105 | ; HL = pointer to string 106 | strout: ld a, (hl) ; get next character 107 | and a ; check if it's null 108 | ret z ; if so, we're done 109 | call chrout ; otherwise output character 110 | inc hl ; point to next character 111 | jr strout ; repeat 112 | 113 | ; output character 114 | chrout: push af ; save character 115 | rdylp: in a, (uarts) ; check if uart is ready to receive 116 | bit 1,a 117 | jr z, rdylp ; if not, wait until it is 118 | pop af ; restore character 119 | out (uartd), a ; output it 120 | ret 121 | 122 | usage_text db "usage: filecopy " 123 | crlf db cr, lf, 0 124 | colon db ": ", 0 125 | 126 | sourcefp ds fplen ; file pointers for fatfs 127 | destfp ds fplen 128 | 129 | filebuf equ $ 130 | -------------------------------------------------------------------------------- /examples/graphclk.bas: -------------------------------------------------------------------------------- 1 | 10 REM GRAPHICAL CLOCK FOR MSX-BASIC 2 | 20 FG=15: BG=4: REM FOREGROUND/BACKGROUND COLORS 3 | 30 CX=128: CY=96: R=95: REM CENTER AND RADIUS 4 | 40 SL=R*0.72: ML=R*0.60: HL=R*0.50: REM HAND LENGTHS 5 | 50 TE=R*0.95: TS=R*0.90: TL=R*0.80: REM TICK LENGTHS 6 | 7 | 100 REM ONE-TIME SETUP 8 | 100 S=99: M=99: H=99 9 | 110 SX=CX: SY=CY: MX=CX: MY=CY: HX=CX: HY=CY 10 | 120 OUT 0,0: REM SELECT RTC CHIP 11 | 130 DEF FNBCD(V)=(V AND &HF0)/16*10+(V AND &HF): REM BCD TO BINARY 12 | 140 INPUT "DS1306+ or DS1302+ (enter 6 or 2)"; CT 13 | 150 IF CT=6 THEN RH=2:RM=1:RS=0: GOTO 180 14 | 160 IF CT=2 THEN RH=&H85:RM=&H83:RS=&H81: GOTO 180 15 | 170 GOTO 140 16 | 180 GOSUB 700 17 | 18 | 200 REM MAIN LOOP 19 | 210 GOSUB 300 20 | 220 IF INKEY$="" THEN 210 21 | 230 END 22 | 23 | 300 REM UPDATE SECOND HAND 24 | 310 LS=S: OUT 1,RS: S=FNBCD(INP(2)) 25 | 320 IF S=LS THEN RETURN 26 | 330 LX=SX: LY=SY 27 | 340 SA=S/60*6.28-1.57: SX=CX+COS(SA)*SL: SY=CY+SIN(SA)*SL 28 | 350 GOSUB 600 29 | 30 | 400 REM UPDATE MINUTE HAND 31 | 410 LM=M: OUT 1,RM: M=FNBCD(INP(2)) 32 | 420 IF M=LM THEN RETURN 33 | 430 LX=MX: LY=MY 34 | 440 MA=M/60*6.28-1.57: MX=CX+COS(MA)*ML: MY=CY+SIN(MA)*ML 35 | 450 GOSUB 600 36 | 37 | 500 REM UPDATE HOUR HAND 38 | 510 LH=H: OUT 1,RH: H=INP(2) 39 | 520 IF (H AND &H40) THEN H=H AND &H1F: REM GET RID OF AM/PM BITS 40 | 530 H=FNBCD(H) 41 | 540 IF H>12 THEN H=H-12 42 | 550 IF H=LH THEN RETURN 43 | 560 LX=HX: LY=HY 44 | 570 HA=H/12*6.28-1.57: HX=CX+COS(HA)*HL: HY=CY+SIN(HA)*HL 45 | 580 GOSUB 600 46 | 590 RETURN 47 | 48 | 600 REM DRAW CLOCK HANDS 49 | 610 COLOR BG 50 | 620 LINE(CX,CY)-(LX,LY) 51 | 630 COLOR FG 52 | 640 LINE(CX,CY)-(SX,SY) 53 | 650 LINE(CX,CY)-(MX,MY) 54 | 660 LINE(CX,CY)-(HX,HY) 55 | 670 RETURN 56 | 57 | 700 REM DRAW CLOCK FACE 58 | 710 SCREEN 2: COLOR FG,BG,BG: CLS 59 | 720 CIRCLE(CX,CY),R 60 | 730 FOR H = 1 TO 24 61 | 740 HA=H/24*6.28-1.57: CH=COS(HA): SH=SIN(HA) 62 | 750 IF H MOD 2 THEN TB=TS ELSE TB=TL 63 | 760 LINE(CX+CH*TB,CY+SH*TB)-(CX+CH*TE,CY+SH*TE) 64 | 770 NEXT 65 | 780 RETURN -------------------------------------------------------------------------------- /examples/hello.asm: -------------------------------------------------------------------------------- 1 | ; z80ctrl (https://github.com/jblang/z80ctrl) 2 | ; Copyright 2018 J.B. Langston 3 | ; 4 | ; Permission is hereby granted, free of charge, to any person obtaining a 5 | ; copy of this software and associated documentation files (the "Software"), 6 | ; to deal in the Software without restriction, including without limitation 7 | ; the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | ; and/or sell copies of the Software, and to permit persons to whom the 9 | ; Software is furnished to do so, subject to the following conditions: 10 | ; 11 | ; The above copyright notice and this permission notice shall be included in 12 | ; all copies or substantial portions of the Software. 13 | ; 14 | ; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | ; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | ; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | ; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | ; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | ; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | ; DEALINGS IN THE SOFTWARE. 21 | 22 | ; @file hello.asm: hello world example program 23 | 24 | org 100h 25 | 26 | lf: equ 0ah 27 | cr: equ 0dh 28 | ramtop: equ 0ffffh 29 | uarts: equ 10h 30 | uartd: equ 11h 31 | 32 | ld sp, ramtop 33 | ld hl, msg 34 | call strout 35 | halt 36 | 37 | strout: ld a, (hl) 38 | and a 39 | ret z 40 | call chrout 41 | inc hl 42 | jr strout 43 | 44 | chrout: push af 45 | rdylp: in a, (uarts) 46 | bit 1,a 47 | jr z, rdylp 48 | pop af 49 | out (uartd), a 50 | ret 51 | 52 | msg: defb "hello, world", cr, lf, 0 53 | -------------------------------------------------------------------------------- /examples/hello.hex: -------------------------------------------------------------------------------- 1 | :1001000031FFFF211E01CD0A01767EA7C8CD130164 2 | :100110002318F7F5DB10CB4F28FAF1D311C9686526 3 | :0D0120006C6C6F2C20776F726C640D0A0000 4 | :00000001FF 5 | -------------------------------------------------------------------------------- /examples/ioxblink.bas: -------------------------------------------------------------------------------- 1 | 10 OUT 0, 1: REM select chip address 1 2 | 20 OUT 1, 0: REM select register IODIRA0 (0x00) 3 | 30 OUT 2, 0: REM set register value to 0 (all pins outputs) 4 | 40 OUT 1, &H12: REM select register GPIOA0 (0x12) 5 | 50 FOR I = 1 TO 10 6 | 60 OUT 2, 0: REM turn all pins on GPIOA off 7 | 70 FOR J = 1 TO 1000:NEXT 8 | 80 OUT 2, &HFF: REM turn all pins on GPIOA on 9 | 90 FOR J = 1 TO 1000:NEXT 10 | 100 NEXT -------------------------------------------------------------------------------- /examples/lcd.bas: -------------------------------------------------------------------------------- 1 | 10 GOSUB 1000 2 | 50 C=&H33:GOSUB 3000: REM RESET SEQUENCE, PART 1 3 | 60 C=&H32:GOSUB 3000: REM RESET SEQUENCE, PART 2 4 | 70 C=&H28:GOSUB 3000: REM 4-BIT MODE, 2 LINES, 5x8 CHARS 5 | 80 C=&HD:GOSUB 3000: REM DISPLAY ON, BLINKING BLOCK CURSOR 6 | 90 C=&H1:GOSUB 3000: REM CLEAR DISPLAY 7 | 100 INPUT "STRING TO PRINT"; S$ 8 | 110 GOSUB 5000 9 | 120 END 10 | 11 | 1000 REM INITIALIZE GPIO PORT 12 | 1010 OUT 0, 1: REM GPIO CHIP 1 13 | 1020 OUT 1, 0: REM DATA DIRECTION REGISTER A 14 | 1030 OUT 2, 0: REM ALL OUTPUT 15 | 1040 OUT 1, &H12: REM GPIO REGISTER A 16 | 1050 RETURN 17 | 18 | 2000 REM SEND BYTE IN C TO LCD 19 | 2010 OUT 2, &H40 OR M OR (C\16) : REM TOP NYBBLE WITH ENABLE HIGH 20 | 2020 OUT 2, M OR (C\16) : REM TOP NYBBLE WITH ENABLE LOW 21 | 2030 OUT 2, &H40 OR M OR (C AND &HF): REM BOTTOM NYBBLE WITH ENABLE HIGH 22 | 2040 OUT 2, M OR (C AND &HF): REM BOTTOM NYBBLE WITH ENABLE LOW 23 | 2050 RETURN 24 | 25 | 3000 REM SEND COMMAND IN C TO LCD 26 | 3010 M=0 27 | 3020 GOSUB 2000 28 | 3030 RETURN 29 | 30 | 4000 REM SEND CHAR IN C TO LCD 31 | 4010 M=&H10 32 | 4020 GOSUB 2000 33 | 4030 RETURN 34 | 35 | 5000 REM SEND STRING IN S$ TO LCD 36 | 5010 FOR I = 1 TO LEN(S$) 37 | 5020 C=ASC(MID$(S$,I,1)) 38 | 5030 GOSUB 4000 39 | 5040 NEXT 40 | 5050 RETURN -------------------------------------------------------------------------------- /examples/rtc.bas: -------------------------------------------------------------------------------- 1 | 10 REM CONVERT VALUES FROM BCD 2 | 20 DEF FNBCD(V)=(V AND &HF0)/16*10+(V AND &HF) 3 | 30 INPUT "DS1306+ or DS1302+ (enter 6 or 2)"; CH 4 | 40 IF CH=6 THEN RY=6:RM=5:RD=4:RH=2:RN=1:RS=0: GOTO 70 5 | 50 IF CH=2 THEN RY=&H8D:RM=&H89:RD=&H87:RH=&H85:RN=&H83:RS=&H81: GOTO 70 6 | 60 GOTO 30 7 | 70 OUT 0,0: REM SELECT RTC CHIP 8 | 80 REM READ RTC REGISTERS 9 | 90 OUT 1,RY: YR=FNBCD(INP(2))+2000 10 | 100 OUT 1,RM: MO=FNBCD(INP(2)) 11 | 110 OUT 1,RD: DY=FNBCD(INP(2)) 12 | 120 OUT 1,RH: HR=INP(2) 13 | 130 OUT 1,RN: MI=FNBCD(INP(2)) 14 | 140 OUT 1,RS: S=FNBCD(INP(2)) 15 | 150 REM HANDLE AM/PM 16 | 160 AMPM$="" 17 | 170 IF (HR AND &H40)=0 THEN 200: REM SKIP IF 24-HR FORMAT 18 | 180 IF HR AND &H20 THEN AMPM$="PM" ELSE AMPM$="AM" 19 | 190 HR=HR AND &H1F: REM GET RID OF AM/PM AND 12-HR BITS 20 | 200 HR=FNBCD(HR) 21 | 210 PRINT USING "The time is ##:##:##& on ##/##/####"; HR, MI, S, AMPM$, MO, DY, YR -------------------------------------------------------------------------------- /firmware/.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "AVR", 5 | "includePath": ["C:/msys64/ucrt64/avr/include", "."], 6 | "compilerPath": "C:/msys64/ucrt64/bin/avr-gcc.exe", 7 | "compilerArgs": ["-mmcu=atmega1284p", "-DF_CPU=20000000UL", "-DBOARD_REV=6", "-Os"], 8 | "browse" : { 9 | "limitSymbolsToIncludedHeaders" : true, 10 | "databaseFilename" : "" 11 | } 12 | } 13 | ], 14 | "version": 4 15 | } -------------------------------------------------------------------------------- /firmware/.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "cppbuild", 6 | "label": "C/C++: avr-gcc.exe build active file", 7 | "command": "C:/msys64/ucrt64/bin/avr-gcc.exe", 8 | "args": [ 9 | "-fdiagnostics-color=always", 10 | "-g", 11 | "${file}", 12 | "-o", 13 | "${fileDirname}\\${fileBasenameNoExtension}.exe", 14 | "-mmcu=atmega1284pp", 15 | "-DF_CPU=20000000UL", 16 | "-Os" 17 | ], 18 | "options": { 19 | "cwd": "C:/msys64/ucrt64/bin" 20 | }, 21 | "problemMatcher": [ 22 | "$gcc" 23 | ], 24 | "group": "build", 25 | "detail": "compiler: C:/msys64/ucrt64/bin/avr-gcc.exe" 26 | } 27 | ] 28 | } -------------------------------------------------------------------------------- /firmware/Makefile: -------------------------------------------------------------------------------- 1 | # All build variables can be set on command line. Build with a 2 | # command of this form: 3 | # 4 | # TMS_BASE=0xBE SN76489_PORT=0xFF BOARD_REV=4 MSX_KEY_BASE=0xA9 PORT=/dev/tty.usbserial-00000000 make install 5 | # 6 | 7 | # Hardware revision (Important: must be set to correct value) 8 | # BOARD_REV?=6 9 | 10 | # Bank address for z80ctrl-style banked RAM; comment out to disable support 11 | # BANK_PORT=0x78 12 | 13 | # Base address for RomWBW-style banked RAM; comment out to disable support 14 | # BANK_BASE=0x78 15 | 16 | # Uncomment to enable support for SST39F0x0 flash chips on RomWBW boards 17 | # SST_FLASH=1 18 | 19 | # Uncomment to enable DS1306 RTC support (used on IOX board) 20 | # DS1306_RTC=1 21 | 22 | # Uncomment to enable DS1302 RTC support (used on CPU/RAM/RTC board) 23 | # DS1302_RTC=1 24 | 25 | # Base address TMS9918A chip; comment out to disable support 26 | # TMS_BASE=0xBE 27 | 28 | # Port assigned to SN76489 sound chip 29 | # SN76489_PORT=0xFF 30 | 31 | # Base port for MSX keyboard 32 | # MSX_KEY_BASE=0xA9 33 | 34 | # SD Card Adapter - Set set 1 for the AdaFruit adapter, leave commented out for the Polulu adapter. 35 | # SD_CARD_ADAFRUIT = 1 36 | 37 | # Current git hash 38 | GITVERSION:= $(shell git log -1 --pretty='%h') 39 | 40 | # MCU type and frequency 41 | MCU?=atmega1284p 42 | F_CPU?=20000000L 43 | 44 | # Programmer options 45 | PROGRAMMER?=arduino 46 | PORT?=COM3 47 | BAUD?=115200 48 | 49 | AVRCC?=avr-gcc 50 | OBJCOPY?=avr-objcopy 51 | AVRDUDE?=avrdude 52 | 53 | CLEAN?=rm -rf 54 | 55 | BIN=z80ctrl 56 | 57 | CLI_OBJS= \ 58 | cli/cli.o \ 59 | cli/benchmark.o \ 60 | cli/coleco.o \ 61 | cli/cpm.o \ 62 | cli/file.o \ 63 | cli/hardware.o \ 64 | cli/io.o \ 65 | cli/memory.o \ 66 | cli/term.o \ 67 | cli/z80.o 68 | 69 | EMULATION_OBJS= \ 70 | emulation/bdos.o \ 71 | emulation/disk.o \ 72 | emulation/filedma.o \ 73 | emulation/sio.o 74 | 75 | FATFS_OBJS= \ 76 | fatfs/ff.o \ 77 | fatfs/diskio.o \ 78 | 79 | HARDWARE_OBJS= \ 80 | hardware/hardware.o \ 81 | hardware/bus.o \ 82 | hardware/z80.o \ 83 | hardware/io.o \ 84 | hardware/mcp23s17.o \ 85 | hardware/memory.o \ 86 | hardware/mmc.o \ 87 | hardware/sn76489.o \ 88 | hardware/spi.o \ 89 | hardware/term.o \ 90 | hardware/timer.o \ 91 | hardware/uart.o \ 92 | hardware/z80.o 93 | 94 | UTIL_OBJS= \ 95 | util/disasm.o \ 96 | util/ffwrap.o \ 97 | util/ihex.o \ 98 | util/string.o \ 99 | util/xmodem.o 100 | 101 | OBJS= \ 102 | $(CLI_OBJS) \ 103 | $(EMULATION_OBJS) \ 104 | $(FATFS_OBJS) \ 105 | $(HARDWARE_OBJS) \ 106 | $(UTIL_OBJS) \ 107 | z80ctrl.o 108 | 109 | ifdef BOARD_REV 110 | FEATURE_DEFINES += -DBOARD_REV=$(BOARD_REV) 111 | endif 112 | ifdef SST_FLASH 113 | FEATURE_DEFINES +=-DSST_FLASH 114 | OBJS += hardware/sst39f0x0.o 115 | endif 116 | ifdef TMS_BASE 117 | FEATURE_DEFINES += -DTMS_BASE=$(TMS_BASE) 118 | OBJS += hardware/tms9918.o 119 | endif 120 | ifdef SN76489_PORT 121 | FEATURE_DEFINES += -DSN76489_PORT=$(SN76489_PORT) 122 | endif 123 | ifdef BANK_BASE 124 | FEATURE_DEFINES += -DBANK_BASE=$(BANK_BASE) 125 | endif 126 | ifdef BANK_PORT 127 | FEATURE_DEFINES += -DBANK_PORT=$(BANK_PORT) 128 | endif 129 | ifdef DS1306_RTC 130 | FEATURE_DEFINES += -DDS1306_RTC -DUSE_RTC 131 | OBJS += hardware/rtc_ds1306.o 132 | endif 133 | ifdef DS1302_RTC 134 | FEATURE_DEFINES += -DDS1302_RTC -DUSE_RTC 135 | OBJS += hardware/rtc_ds1302.o 136 | endif 137 | ifdef RTC_BASE 138 | FEATURE_DEFINES += -DRTC_BASE=$(RTC_BASE) 139 | endif 140 | ifdef MSX_KEY_BASE 141 | FEATURE_DEFINES += -DMSX_KEY_BASE=$(MSX_KEY_BASE) 142 | OBJS += emulation/msxkey.o 143 | endif 144 | ifdef SD_CARD_ADAFRUIT 145 | FEATURE_DEFINES += -DMISO_INPUT_PULLUP 146 | endif 147 | 148 | CFLAGS=-std=c99 -flto -Os $(FEATURE_DEFINES) -DF_CPU=$(F_CPU) -DGITVERSION="\"${GITVERSION}\"" -mmcu=$(MCU) -I. 149 | 150 | 151 | %.o: %.c 152 | $(AVRCC) $(CFLAGS) $(LDFLAGS) -c -o $@ $< 153 | 154 | $(BIN).hex: $(BIN).elf 155 | $(OBJCOPY) -j .text -j .data -O ihex $< $@ 156 | 157 | $(BIN).elf: $(OBJS) 158 | $(AVRCC) $(CFLAGS) $(LDFLAGS) -o $@ $^ 159 | 160 | install: $(BIN).hex 161 | $(AVRDUDE) -c $(PROGRAMMER) -p $(MCU) -P $(PORT) -b $(BAUD) -U flash:w:$< 162 | 163 | clean: 164 | $(CLEAN) $(BIN).elf $(BIN).hex $(OBJS) 165 | -------------------------------------------------------------------------------- /firmware/Makefile.jbl: -------------------------------------------------------------------------------- 1 | # All build variables can be set on command line. Build with a 2 | # command of this form: 3 | # 4 | # TMS_BASE=0xBE SN76489_PORT=0xFF BOARD_REV=4 MSX_KEY_BASE=0xA9 PORT=/dev/tty.usbserial-00000000 make install 5 | # 6 | 7 | # Hardware revision (Important: must be set to correct value) 8 | BOARD_REV?=6 9 | 10 | # Bank address for z80ctrl-style banked RAM; comment out to disable support 11 | BANK_PORT=0x78 12 | 13 | # Base address for RomWBW-style banked RAM; comment out to disable support 14 | # BANK_BASE=0x78 15 | 16 | # Uncomment to enable support for SST39F0x0 flash chips on RomWBW boards 17 | # SST_FLASH=1 18 | 19 | # Uncomment to enable DS1306 RTC support (used on IOX board) 20 | # DS1306_RTC=1 21 | 22 | # Uncomment to enable DS1302 RTC support (used on CPU/RAM/RTC board) 23 | DS1302_RTC=1 24 | 25 | # Base address TMS9918A chip; comment out to disable support 26 | TMS_BASE=0xBE 27 | 28 | # Port assigned to SN76489 sound chip 29 | SN76489_PORT=0xFF 30 | 31 | # Base port for MSX keyboard 32 | MSX_KEY_BASE=0xA9 33 | 34 | # SD Card Adapter - Set set 1 for the AdaFruit adapter, leave commented out for the Polulu adapter. 35 | # SD_CARD_ADAFRUIT = 1 36 | 37 | # Current git hash 38 | GITVERSION:= $(shell git log -1 --pretty='%h') 39 | 40 | # MCU type and frequency 41 | MCU?=atmega1284p 42 | F_CPU?=20000000L 43 | 44 | # Programmer options 45 | PROGRAMMER?=arduino 46 | PORT?=COM8 47 | BAUD?=115200 48 | 49 | AVRCC?=avr-gcc 50 | OBJCOPY?=avr-objcopy 51 | AVRDUDE?=avrdude 52 | 53 | CLEAN?=rm -rf 54 | 55 | BIN=z80ctrl 56 | 57 | CLI_OBJS= \ 58 | cli/cli.o \ 59 | cli/benchmark.o \ 60 | cli/coleco.o \ 61 | cli/cpm.o \ 62 | cli/file.o \ 63 | cli/hardware.o \ 64 | cli/io.o \ 65 | cli/memory.o \ 66 | cli/term.o \ 67 | cli/z80.o 68 | 69 | EMULATION_OBJS= \ 70 | emulation/bdos.o \ 71 | emulation/disk.o \ 72 | emulation/filedma.o \ 73 | emulation/sio.o 74 | 75 | FATFS_OBJS= \ 76 | fatfs/ff.o \ 77 | fatfs/diskio.o \ 78 | 79 | HARDWARE_OBJS= \ 80 | hardware/hardware.o \ 81 | hardware/bus.o \ 82 | hardware/z80.o \ 83 | hardware/io.o \ 84 | hardware/mcp23s17.o \ 85 | hardware/memory.o \ 86 | hardware/mmc.o \ 87 | hardware/sn76489.o \ 88 | hardware/spi.o \ 89 | hardware/term.o \ 90 | hardware/timer.o \ 91 | hardware/uart.o \ 92 | hardware/z80.o 93 | 94 | UTIL_OBJS= \ 95 | util/disasm.o \ 96 | util/ffwrap.o \ 97 | util/ihex.o \ 98 | util/string.o \ 99 | util/xmodem.o 100 | 101 | OBJS= \ 102 | $(CLI_OBJS) \ 103 | $(EMULATION_OBJS) \ 104 | $(FATFS_OBJS) \ 105 | $(HARDWARE_OBJS) \ 106 | $(UTIL_OBJS) \ 107 | z80ctrl.o 108 | 109 | ifdef BOARD_REV 110 | FEATURE_DEFINES += -DBOARD_REV=$(BOARD_REV) 111 | endif 112 | ifdef SST_FLASH 113 | FEATURE_DEFINES +=-DSST_FLASH 114 | OBJS += hardware/sst39f0x0.o 115 | endif 116 | ifdef TMS_BASE 117 | FEATURE_DEFINES += -DTMS_BASE=$(TMS_BASE) 118 | OBJS += hardware/tms9918.o 119 | endif 120 | ifdef SN76489_PORT 121 | FEATURE_DEFINES += -DSN76489_PORT=$(SN76489_PORT) 122 | endif 123 | ifdef BANK_BASE 124 | FEATURE_DEFINES += -DBANK_BASE=$(BANK_BASE) 125 | endif 126 | ifdef BANK_PORT 127 | FEATURE_DEFINES += -DBANK_PORT=$(BANK_PORT) 128 | endif 129 | ifdef DS1306_RTC 130 | FEATURE_DEFINES += -DDS1306_RTC -DUSE_RTC 131 | OBJS += hardware/rtc_ds1306.o 132 | endif 133 | ifdef DS1302_RTC 134 | FEATURE_DEFINES += -DDS1302_RTC -DUSE_RTC 135 | OBJS += hardware/rtc_ds1302.o 136 | endif 137 | ifdef RTC_BASE 138 | FEATURE_DEFINES += -DRTC_BASE=$(RTC_BASE) 139 | endif 140 | ifdef MSX_KEY_BASE 141 | FEATURE_DEFINES += -DMSX_KEY_BASE=$(MSX_KEY_BASE) 142 | OBJS += emulation/msxkey.o 143 | endif 144 | ifdef SD_CARD_ADAFRUIT 145 | FEATURE_DEFINES += -DMISO_INPUT_PULLUP 146 | endif 147 | 148 | CFLAGS=-std=c99 -flto -Os $(FEATURE_DEFINES) -DF_CPU=$(F_CPU) -DGITVERSION="\"${GITVERSION}\"" -mmcu=$(MCU) -I. 149 | 150 | 151 | %.o: %.c 152 | $(AVRCC) $(CFLAGS) $(LDFLAGS) -c -o $@ $< 153 | 154 | $(BIN).hex: $(BIN).elf 155 | $(OBJCOPY) -j .text -j .data -O ihex $< $@ 156 | 157 | $(BIN).elf: $(OBJS) 158 | $(AVRCC) $(CFLAGS) $(LDFLAGS) -o $@ $^ 159 | 160 | install: $(BIN).hex 161 | $(AVRDUDE) -c $(PROGRAMMER) -p $(MCU) -P $(PORT) -b $(BAUD) -U flash:w:$< 162 | 163 | clean: 164 | $(CLEAN) $(BIN).elf $(BIN).hex $(OBJS) 165 | -------------------------------------------------------------------------------- /firmware/cli/benchmark.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file benchmark.c bench command 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include 32 | #include 33 | 34 | #include "fatfs/ff.h" 35 | 36 | #include "hardware/bus.h" 37 | #include "hardware/memory.h" 38 | #include "hardware/timer.h" 39 | #include "hardware/uart.h" 40 | 41 | #include "util/pgmspace.h" 42 | 43 | /** 44 | * Run a benchmark 45 | */ 46 | // #ifdef BENCHMARK 47 | void cli_bench(int argc, char* argv[]) 48 | { 49 | uint32_t count = 1; 50 | if (argc == 2) 51 | count = strtoul(argv[1], NULL, 16); 52 | for (uint32_t i = 0; i < count; i++) { 53 | uint8_t sreg = SREG; 54 | cli(); 55 | config_timer(1, CLKDIV1); 56 | 57 | TCNT1 = 0; 58 | uint8_t rd = GET_RD; 59 | uint16_t rdt = TCNT1; 60 | 61 | TCNT1 = 0; 62 | uint8_t m1 = GET_M1; 63 | uint16_t m1t = TCNT1; 64 | 65 | TCNT1 = 0; 66 | uint8_t addrlo = GET_ADDRLO; 67 | uint16_t addrlot = TCNT1; 68 | 69 | TCNT1 = 0; 70 | uint8_t addrhi = GET_ADDRHI; 71 | uint16_t addrhit = TCNT1; 72 | 73 | TCNT1 = 0; 74 | bus_stat bus = bus_status(); 75 | uint16_t bust = TCNT1; 76 | 77 | TCNT1 = 0; 78 | bus_stat busfast = bus_status_fast(); 79 | uint16_t busfastt = TCNT1; 80 | 81 | TCNT1 = 0; 82 | bus_release(); 83 | uint16_t busreleaset = TCNT1; 84 | 85 | TCNT1 = 0; 86 | bus_request(); 87 | uint16_t busrequestt = TCNT1; 88 | 89 | uint8_t buf[1024]; 90 | 91 | TCNT1 = 0; 92 | mem_read_banked(0, buf, 1024); 93 | uint16_t memreadbare1kt = TCNT1; 94 | 95 | TCNT1 = 0; 96 | mem_read_banked(0, buf, 32); 97 | uint16_t memreadbare32t = TCNT1; 98 | 99 | TCNT1 = 0; 100 | mem_read_banked(0xf0, buf, 32); 101 | uint16_t memreadbare32ct = TCNT1; 102 | 103 | TCNT1 = 0; 104 | mem_read_banked(0, buf, 256); 105 | uint16_t memreadt = TCNT1; 106 | 107 | FIL fp; 108 | UINT br; 109 | TCNT1 = 0; 110 | f_open(&fp, "/cpm2.dsk", FA_READ); 111 | uint16_t fopent = TCNT1; 112 | 113 | TCNT1 = 0; 114 | f_read(&fp, buf, 256, &br); 115 | uint16_t freadt = TCNT1; 116 | 117 | TCNT1 = 0; 118 | f_lseek(&fp, 4096); 119 | uint16_t fseekt = TCNT1; 120 | 121 | TCNT1 = 0; 122 | f_close(&fp); 123 | uint16_t fcloset = TCNT1; 124 | 125 | config_timer(1, CLKOFF); 126 | SREG = sreg; 127 | 128 | printf_P(PSTR("Operation Times:\n")); 129 | printf_P(PSTR("\tget_rd %d us\n"), TCNT_TO_US(rdt, F_CPU)); 130 | printf_P(PSTR("\tget_m1 %d us\n"), TCNT_TO_US(m1t, F_CPU)); 131 | printf_P(PSTR("\tget_addrlo %d us\n"), TCNT_TO_US(addrlot, F_CPU)); 132 | printf_P(PSTR("\tget_addrhi %d us\n"), TCNT_TO_US(addrhit, F_CPU)); 133 | printf_P(PSTR("\tbus_status %d us\n"), TCNT_TO_US(bust, F_CPU)); 134 | printf_P(PSTR("\tbus_status_fast %d us\n"), TCNT_TO_US(busfastt, F_CPU)); 135 | printf_P(PSTR("\tbus_request %d us\n"), TCNT_TO_US(busrequestt, F_CPU)); 136 | printf_P(PSTR("\tbus_release %d us\n"), TCNT_TO_US(busreleaset, F_CPU)); 137 | printf_P(PSTR("\tmem_read_banked %d us (1KB)\n"), TCNT_TO_US(memreadbare1kt, F_CPU)); 138 | printf_P(PSTR("\tmem_read_banked %d us (32 bytes)\n"), TCNT_TO_US(memreadbare32t, F_CPU)); 139 | printf_P(PSTR("\tmem_read_banked %d us (32 bytes, cross-page)\n"), TCNT_TO_US(memreadbare32ct, F_CPU)); 140 | printf_P(PSTR("\tmem_read_banked %d us\n"), TCNT_TO_US(memreadt, F_CPU)); 141 | printf_P(PSTR("\tf_open %d us\n"), TCNT_TO_US(fopent, F_CPU)); 142 | printf_P(PSTR("\tf_read %d us\n"), TCNT_TO_US(freadt, F_CPU)); 143 | printf_P(PSTR("\tf_lseek %d us\n"), TCNT_TO_US(fseekt, F_CPU)); 144 | printf_P(PSTR("\tf_close %d us\n\n"), TCNT_TO_US(fcloset, F_CPU)); 145 | 146 | printf_P(PSTR("Data Structure Sizes:\n")); 147 | printf_P(PSTR("\tFIL: %d bytes\n"), sizeof(FIL)); 148 | printf_P(PSTR("\tDIR: %d bytes\n"), sizeof(DIR)); 149 | printf_P(PSTR("\tFILINFO: %d bytes\n"), sizeof(FILINFO)); 150 | printf_P(PSTR("\tFSIZE_t: %d bytes\n"), sizeof(FSIZE_t)); 151 | uart_flush(); 152 | } 153 | } 154 | // #endif -------------------------------------------------------------------------------- /firmware/cli/cli.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file cli.c public command-line functions 25 | */ 26 | 27 | #ifndef CLI_H 28 | #define CLI_H 29 | #include 30 | void cli_start(void); 31 | extern const char z80ctrl_banner[]; 32 | extern const char z80ctrl_copyright[]; 33 | #endif -------------------------------------------------------------------------------- /firmware/cli/coleco.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file coleco.c coleco command 25 | */ 26 | #include 27 | #include 28 | #include 29 | 30 | #include "fatfs/ff.h" 31 | 32 | #include "hardware/bus.h" 33 | #include "hardware/memory.h" 34 | #include "hardware/z80.h" 35 | 36 | #include "util/ffwrap.h" 37 | #include "util/pgmspace.h" 38 | 39 | /** 40 | * Load and run a coleco ROM 41 | */ 42 | void cli_coleco(int argc, char* argv[]) 43 | { 44 | uint8_t prevdiv = get_clkdiv(); 45 | uint8_t prevmask = get_haltmask(); 46 | char* coleco_rom = "coleco.rom"; 47 | char* game_rom; 48 | if (argc > 2) 49 | coleco_rom = argv[2]; 50 | if (argc > 1) { 51 | game_rom = argv[1]; 52 | } else { 53 | printf_P(PSTR("usage: coleco game.rom [coleco.rom]\n")); 54 | return; 55 | } 56 | if (f_stat(game_rom, NULL) != FR_OK) { 57 | printf_P(PSTR("file not found: %s\n"), game_rom); 58 | return; 59 | } else if (f_stat(coleco_rom, NULL) != FR_OK) { 60 | printf_P(PSTR("file not found: %s\n"), coleco_rom); 61 | return; 62 | } 63 | mem_loadbin(mem_write_banked, coleco_rom, 0, 0, 0); 64 | mem_loadbin(mem_write_banked, game_rom, 0x8000, 0, 0); 65 | set_clkdiv(5); 66 | set_haltmask(RESET); 67 | z80_reset(0); 68 | z80_run(); 69 | set_haltmask(prevmask); 70 | set_clkdiv(prevdiv); 71 | } -------------------------------------------------------------------------------- /firmware/cli/cpm.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file cpm.c CP/M-related commands 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "fatfs/ff.h" 33 | 34 | #include "emulation/bdos.h" 35 | #include "emulation/disk.h" 36 | #include "emulation/sio.h" 37 | 38 | #include "hardware/memory.h" 39 | #include "hardware/z80.h" 40 | 41 | #include "util/ffwrap.h" 42 | #include "util/pgmspace.h" 43 | #include "util/string.h" 44 | 45 | #include "cli.h" 46 | 47 | /** 48 | * Boot from a disk 49 | */ 50 | void cli_boot(int argc, char* argv[]) 51 | { 52 | if (argc == 2) { 53 | drive_mount(0, argv[1]); 54 | } 55 | if (drive_bootload()) { 56 | z80_reset(0); 57 | z80_run(); 58 | } 59 | } 60 | 61 | /** 62 | * Attach a virtual UART to a physical one 63 | */ 64 | void cli_attach(int argc, char* argv[]) 65 | { 66 | uint8_t dir; 67 | uint8_t mode = SIO_UNATTACHED; 68 | char* filename = NULL; 69 | if (argc != 4) { 70 | printf_P(PSTR("usage: attach [0|1] [read|write] [uart0|uart1|filename]\n")); 71 | return; 72 | } 73 | if (strcmp_P(argv[2], PSTR("read")) == 0) 74 | dir = SIO_INPUT; 75 | else 76 | dir = SIO_OUTPUT; 77 | 78 | uint8_t virtual = strtoul(argv[1], NULL, 10) & 1; 79 | if (strcmp_P(argv[3], PSTR("uart0")) == 0) 80 | mode = SIO_UART0; 81 | else if (strcmp_P(argv[3], PSTR("uart1")) == 0) 82 | mode = SIO_UART1; 83 | else { 84 | mode = SIO_FILE; 85 | filename = argv[3]; 86 | } 87 | sio_attach(virtual, dir, mode, filename); 88 | } 89 | 90 | /** 91 | * Mount a disk image 92 | */ 93 | void cli_mount(int argc, char* argv[]) 94 | { 95 | if (argc != 3) { 96 | printf_P(PSTR("usage: mount \n")); 97 | return; 98 | } 99 | uint8_t drv = strtoul(argv[1], NULL, 10); 100 | char* filename = argv[2]; 101 | drive_mount(drv, filename); 102 | } 103 | 104 | /** 105 | * Unmount a disk image 106 | */ 107 | void cli_unmount(int argc, char* argv[]) 108 | { 109 | if (argc != 2) { 110 | printf_P(PSTR("usage: unmount \n")); 111 | return; 112 | } 113 | uint8_t drv = strtoul(argv[1], NULL, 10); 114 | drive_unmount(drv); 115 | } 116 | 117 | /** 118 | * Enable/disable BDOS debug messages 119 | */ 120 | void cli_bdosdbg(int argc, char* argv[]) 121 | { 122 | if (argc == 2) { 123 | if (strcmp_P(argv[1], PSTR("on")) == 0) 124 | bdos_debug = 1; 125 | else if (strcmp_P(argv[1], PSTR("off")) == 0) 126 | bdos_debug = 0; 127 | } 128 | if (bdos_debug) 129 | printf("bdos debug is enabled\n"); 130 | else 131 | printf("bdos debug is disabled\n"); 132 | } 133 | 134 | /** 135 | * Run a CP/M .COM file 136 | */ 137 | uint8_t cli_runcom(int argc, char* argv[]) 138 | { 139 | char filename[256]; 140 | strcpy(filename, argv[0]); 141 | if (!endswith(filename, PSTR(".com"))) 142 | strcat_P(filename, PSTR(".com")); 143 | if (f_stat(filename, NULL) == FR_OK) { 144 | // Look for BDOS runtime file in current directory then root directory 145 | uint16_t start; 146 | if (f_stat("bdos.bin", NULL) == FR_OK) { 147 | start = mem_loadbin(mem_write_banked, "bdos.bin", -1, 0, 0); 148 | } else if (f_stat("/bdos.bin", NULL) == FR_OK) { 149 | start = mem_loadbin(mem_write_banked, "/bdos.bin", -1, 0, 0); 150 | } else { 151 | // Last resort: warn and try to run the program without bdos loaded 152 | printf_P(PSTR("warning: bdos.bin not found in current or root directory.\n")); 153 | start = 0x100; 154 | } 155 | bdos_init(argc, argv); 156 | mem_loadbin(mem_write_banked, filename, 0x100, 0, 0); 157 | z80_reset(start); 158 | z80_run(); 159 | putchar('\n'); 160 | return 1; 161 | } else { 162 | return 0; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /firmware/cli/hardware.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file hardware.c commands for interacting with hardware 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "hardware/mcp23s17.h" 33 | #include "hardware/rtc.h" 34 | #include "hardware/uart.h" 35 | 36 | #include "util/pgmspace.h" 37 | 38 | /** 39 | * Set the baud rate for the UART 40 | */ 41 | void cli_baud(int argc, char* argv[]) 42 | { 43 | if (argc != 3) { 44 | printf_P(PSTR("usage: baud \n")); 45 | return; 46 | } 47 | uint8_t uart = strtoul(argv[1], NULL, 10) & 1; 48 | uint32_t requested = strtoul(argv[2], NULL, 10); 49 | uint16_t ubrr = 0; 50 | uint32_t actual = 0; 51 | // Find closest possible actual baud rate 52 | for (;;) { 53 | actual = (uint32_t)F_CPU / ((uint32_t)16 * ((uint32_t)ubrr + (uint32_t)1)); 54 | if (actual <= requested) 55 | break; 56 | ubrr++; 57 | // stop if we have maxed out UBRR 58 | if (ubrr == 0) 59 | break; 60 | } 61 | printf_P(PSTR("UART %u: requested: %lu, actual: %lu\n"), uart, requested, actual); 62 | uart_flush(); 63 | uart_init(uart, ubrr); 64 | } 65 | 66 | #ifdef USE_RTC 67 | /** 68 | * Display or set the date on the RTC 69 | */ 70 | void cli_date(int argc, char* argv[]) 71 | { 72 | struct tm date; 73 | char datestr[30]; 74 | if (argc < 8) { 75 | rtc_get_date(&date); 76 | printf_P(PSTR("The time is %d:%02d:%02d on %d/%d/%02d\n"), date.tm_hour, date.tm_min, date.tm_sec, date.tm_mon, date.tm_mday, date.tm_year); 77 | printf_P(PSTR("usage: date \n")); 78 | return; 79 | } 80 | 81 | date.tm_year = strtoul(argv[1], NULL, 10); 82 | date.tm_mon = strtoul(argv[2], NULL, 10); 83 | date.tm_mday = strtoul(argv[3], NULL, 10); 84 | date.tm_wday = strtoul(argv[4], NULL, 10); 85 | date.tm_hour = strtoul(argv[5], NULL, 10); 86 | date.tm_min = strtoul(argv[6], NULL, 10); 87 | date.tm_sec = strtoul(argv[7], NULL, 10); 88 | rtc_set_date(&date); 89 | } 90 | #endif 91 | 92 | void cli_ioxread(int argc, char* argv[]) 93 | { 94 | if (argc != 3) { 95 | printf_P(PSTR("usage: ioxread \n")); 96 | return; 97 | } 98 | uint8_t addr = strtoul(argv[1], NULL, 16) & 0x7; 99 | if (addr < 1 || addr > 7) { 100 | printf_P(PSTR("invalid address. must be between 1 and 7\n")); 101 | return; 102 | } 103 | uint8_t reg = strtoul(argv[2], NULL, 16) & 0x1F; 104 | uint8_t value = iox_read(addr, reg); 105 | printf_P(PSTR("Read %02x from io expander %x register %02x\n"), value, addr, reg); 106 | } 107 | 108 | void cli_ioxwrite(int argc, char* argv[]) 109 | { 110 | if (argc != 4) { 111 | printf_P(PSTR("usage: ioxwrite \n")); 112 | return; 113 | } 114 | uint8_t addr = strtoul(argv[1], NULL, 16) & 0x7; 115 | if (addr < 1 || addr > 7) { 116 | printf_P(PSTR("invalid address. must be between 1 and 7\n")); 117 | return; 118 | } 119 | uint8_t reg = strtoul(argv[2], NULL, 16) & 0x1F; 120 | uint8_t value = strtoul(argv[3], NULL, 16); 121 | iox_write(addr, reg, value); 122 | } 123 | -------------------------------------------------------------------------------- /firmware/cli/impl.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file cli_impl.h CLI internal implementation 25 | */ 26 | 27 | #ifndef CLI_IMPL_H 28 | #define CLI_IMPL_H 29 | #include 30 | 31 | #define WHITESPACE " \t\r\n" 32 | #define MAXBUF 256 33 | #define MAXARGS 256 34 | #define AUTOEXEC "autoexec.z8c" 35 | 36 | /* bench.c */ 37 | void cli_bench(int argc, char* argv[]); 38 | 39 | /* cli.c */ 40 | void cli_dispatch(char* buf); 41 | void cli_about(int argc, char *argv[]); 42 | void cli_help(int argc, char *argv[]); 43 | 44 | /* coleco.c */ 45 | void cli_coleco(int argc, char* argv[]); 46 | 47 | /* cpm.c */ 48 | void cli_boot(int argc, char* argv[]); 49 | void cli_attach(int argc, char* argv[]); 50 | void cli_mount(int argc, char* argv[]); 51 | void cli_unmount(int argc, char* argv[]); 52 | void cli_bdosdbg(int argc, char* argv[]); 53 | uint8_t cli_runcom(int argc, char* argv[]); 54 | 55 | extern uint8_t clibuf[256]; 56 | 57 | /* file.c */ 58 | void cli_chdir(int argc, char* argv[]); 59 | void cli_mkdir(int argc, char* argv[]); 60 | void cli_dir(int argc, char* argv[]); 61 | void cli_copy(int argc, char* argv[]); 62 | void cli_ren(int argc, char* argv[]); 63 | void cli_del(int argc, char* argv[]); 64 | void cli_loadhex(int argc, char* argv[]); 65 | void cli_savehex(int argc, char* argv[]); 66 | void cli_loadbin(int argc, char* argv[]); 67 | void cli_savebin(int argc, char* argv[]); 68 | void cli_xmrx(int argc, char* argv[]); 69 | void cli_xmtx(int argc, char* argv[]); 70 | void cli_exec(char* filename); 71 | void cli_do(int argc, char* argv[]); 72 | 73 | /* io.c */ 74 | void cli_assign(int argc, char* argv[]); 75 | void cli_out(int argc, char* argv[]); 76 | void cli_in(int argc, char* argv[]); 77 | void cli_tmsreg(int argc, char* argv[]); 78 | 79 | /* hardware.c */ 80 | void cli_baud(int argc, char* argv[]); 81 | void cli_date(int argc, char* argv[]); 82 | void cli_ioxread(int argc, char* argv[]); 83 | void cli_ioxwrite(int argc, char* argv[]); 84 | 85 | /* memory.c */ 86 | void cli_base(int argc, char* argv[]); 87 | void cli_dump(int argc, char* argv[]); 88 | void cli_fill(int argc, char* argv[]); 89 | void cli_poke(int argc, char* argv[]); 90 | void cli_erase(int argc, char* argv[]); 91 | 92 | /* term.c */ 93 | void cli_screen(int argc, char* argv[]); 94 | void cli_cls(int argc, char* argv[]); 95 | void cli_esc(int argc, char* argv[]); 96 | void cli_ascii(int argc, char* argv[]); 97 | void cli_haltkey(int argc, char* argv[]); 98 | 99 | extern uint8_t screenwidth; 100 | extern uint8_t screenheight; 101 | 102 | /* z80.c */ 103 | void cli_disasm(int argc, char* argv[]); 104 | void cli_clkdiv(int argc, char* argv[]); 105 | void cli_reset(int argc, char* argv[]); 106 | void cli_run(int argc, char* argv[]); 107 | void cli_debug(int argc, char* argv[]); 108 | void cli_step(int argc, char* argv[]); 109 | void cli_bus(int argc, char* argv[]); 110 | void cli_halt(int argc, char* argv[]); 111 | void cli_breakwatch(int argc, char* argv[]); 112 | 113 | #endif -------------------------------------------------------------------------------- /firmware/cli/io.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file cpm.c I/O-related commands 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "hardware/io.h" 32 | #include "hardware/tms9918.h" 33 | 34 | #include "util/pgmspace.h" 35 | 36 | /** 37 | * Assign a device to a port 38 | */ 39 | void cli_assign(int argc, char* argv[]) 40 | { 41 | if (argc < 3) { 42 | iorq_list(); 43 | printf_P(PSTR("\n\nusage: %s \n"), argv[0]); 44 | return; 45 | } 46 | uint8_t port = strtoul(argv[1], NULL, 16) & 0xff; 47 | uint8_t mode; 48 | if (strcmp_P(argv[2], PSTR("r")) == 0) 49 | mode = IORQ_READ; 50 | else if (strcmp_P(argv[2], PSTR("w")) == 0) 51 | mode = IORQ_WRITE; 52 | else if (strcmp_P(argv[2], PSTR("rw")) == 0) 53 | mode = IORQ_RW; 54 | else { 55 | printf_P(PSTR("usage: %s \n"), argv[0]); 56 | return; 57 | } 58 | uint8_t device = iorq_deviceid(argv[3]); 59 | if (device == DEV_INVALID) { 60 | printf_P(PSTR("error: invalid device name\n")); 61 | return; 62 | } 63 | 64 | if (iorq_assign(port, mode, device) != device) 65 | printf_P(PSTR("error: port in use by external device\n")); 66 | } 67 | 68 | /** 69 | * Output value to an IO register 70 | */ 71 | void cli_out(int argc, char* argv[]) 72 | { 73 | if (argc < 2) { 74 | printf_P(PSTR("usage: out [value...]\n")); 75 | return; 76 | } 77 | uint8_t addr = strtoul(argv[1], NULL, 16) & 0xff; 78 | for (uint8_t i = 2; i < argc; i++) { 79 | uint8_t value = strtoul(argv[i], NULL, 16) & 0xff; 80 | io_out(addr, value); 81 | } 82 | } 83 | 84 | /** 85 | * Input value from an IO register 86 | */ 87 | void cli_in(int argc, char* argv[]) 88 | { 89 | if (argc < 2) { 90 | printf_P(PSTR("usage: in \n")); 91 | return; 92 | } 93 | uint8_t addr = strtoul(argv[1], NULL, 16) & 0xff; 94 | printf_P(PSTR("Read %02x from %02x\n"), io_in(addr), addr); 95 | } 96 | 97 | /** 98 | * Report the status of the TMS9918A 99 | */ 100 | #ifdef TMS_BASE 101 | void cli_tmsreg(int argc, char* argv[]) 102 | { 103 | tms_report(); 104 | } 105 | #endif -------------------------------------------------------------------------------- /firmware/cli/term.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file term.c terminal-related commands 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "hardware/uart.h" 31 | 32 | #include "util/pgmspace.h" 33 | 34 | uint8_t screenwidth = 80; 35 | uint8_t screenheight = 24; 36 | 37 | /** 38 | * Set screen size 39 | */ 40 | void cli_screen(int argc, char* argv[]) 41 | { 42 | uint8_t tmpwidth = 0, tmpheight = 0; 43 | if (argc >= 2) 44 | tmpwidth = strtoul(argv[1], NULL, 10); 45 | if (argc >= 3) 46 | tmpheight = strtoul(argv[2], NULL, 10); 47 | if (tmpwidth >= 40) 48 | screenwidth = tmpwidth; 49 | if (tmpheight >= 24) 50 | screenheight = tmpheight; 51 | printf_P(PSTR("usage: screen \n")); 52 | printf_P(PSTR("current screen size is %dx%d\n"), screenwidth, screenheight); 53 | } 54 | 55 | /** 56 | * Clear the screen 57 | */ 58 | void cli_cls(int argc, char* argv[]) 59 | { 60 | printf_P(PSTR("\e[0m\e[;H\e[2J")); 61 | } 62 | 63 | /** 64 | * Send an escape sequence 65 | */ 66 | void cli_esc(int argc, char* argv[]) 67 | { 68 | if (argc < 2) { 69 | printf_P(PSTR("usage: %s ...\n"), argv[0]); 70 | } 71 | for (uint8_t i = 1; i < argc; i++) 72 | printf_P(PSTR("\e%s"), argv[i]); // undocumented feature to send escape code 73 | } 74 | 75 | /** 76 | * Send an ascii character 77 | */ 78 | void cli_ascii(int argc, char* argv[]) 79 | { 80 | if (argc < 2) { 81 | printf_P(PSTR("usage: %s ...\n"), argv[0]); 82 | } 83 | for (uint8_t i = 1; i < argc; i++) { 84 | char c = strtoul(argv[i], NULL, 16); 85 | printf_P(PSTR("%c"), c); 86 | } 87 | } 88 | 89 | /** 90 | * Enable or disable halt 91 | */ 92 | void cli_haltkey(int argc, char* argv[]) 93 | { 94 | if (argc == 2) { 95 | if (strcmp_P(argv[1], PSTR("off")) == 0) 96 | watch_key = 0; 97 | else if (argv[1][0] == '^' && argv[1][1] <= '_' && argv[1][1] >= '@') 98 | watch_key = argv[1][1] - 64; 99 | else if (argv[1][0] == '^' && argv[1][1] <= 'z' && argv[1][1] >= 'a') 100 | watch_key = argv[1][1] - 96; 101 | else 102 | watch_key = strtoul(argv[1], NULL, 16) & 0xff; 103 | } 104 | if (watch_key == 0) 105 | printf_P(PSTR("halt key is disabled\n")); 106 | else { 107 | printf_P(PSTR("halt key is %02x "), watch_key); 108 | if (watch_key <= 74) 109 | printf_P(PSTR("(^%c)\n"), watch_key + 64); 110 | else if (watch_key >= 33 && watch_key <= 126) 111 | printf_P(PSTR("(%c)\n"), watch_key); 112 | else 113 | printf_P(PSTR("\n")); 114 | } 115 | } -------------------------------------------------------------------------------- /firmware/emulation/bdos.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file bdos.h BDOS disk emulation on FatFS 25 | */ 26 | 27 | #ifndef EMULATION_BDOS_H 28 | #define EMULATION_BDOS_H 29 | #include 30 | 31 | #ifndef BDOS_DMA 32 | #define BDOS_DMA 0xC 33 | #endif 34 | 35 | uint8_t bdos_dma_reset(); 36 | void bdos_dma_command(uint8_t data); 37 | void bdos_dma_execute(); 38 | void bdos_init(int argc, char* argv[]); 39 | 40 | extern uint8_t bdos_debug; 41 | 42 | #endif -------------------------------------------------------------------------------- /firmware/emulation/disk.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2003 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file disk.h MITS Altair 88-DISK Simulator 25 | */ 26 | 27 | #ifndef EMULATION_DISK_H 28 | #define EMULATION_DISK_H 29 | 30 | #include 31 | 32 | #define DRIVE_STATUS 0x8 33 | #define DRIVE_CONTROL 0x9 34 | #define DRIVE_DATA 0xA 35 | 36 | int drive_bootload(); 37 | void drive_unmount(uint8_t drv); 38 | void drive_mount(uint8_t drv, char* filename); 39 | void drive_select(uint8_t newdrv); 40 | uint8_t drive_status(); 41 | void drive_control(uint8_t cmd); 42 | uint8_t drive_sector(void); 43 | void drive_write(uint8_t data); 44 | uint8_t drive_read(void); 45 | 46 | #endif -------------------------------------------------------------------------------- /firmware/emulation/filedma.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file filedma.h FatFS file DMA interface 25 | */ 26 | 27 | #ifndef EMULATION_FILEDMA_H 28 | #define EMULATION_FILEDMA_H 29 | 30 | #ifndef FILE_DMA 31 | #define FILE_DMA 0xB 32 | #endif 33 | 34 | uint8_t file_dma_reset(); 35 | void file_dma_command(uint8_t data); 36 | void file_dma_execute(); 37 | void file_dma_save_cli(int argc, char* argv[]); 38 | 39 | extern uint8_t clibuf[256]; 40 | 41 | #endif -------------------------------------------------------------------------------- /firmware/emulation/msxkey.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file msxkey.c MSX keyboard emulation 25 | */ 26 | 27 | #include 28 | 29 | #include "hardware/uart.h" 30 | 31 | #include "util/pgmspace.h" 32 | 33 | #include "msxkey.h" 34 | 35 | // Table to translate ASCII to MSX keyboard matrix 36 | // Upper nybble is row; lower nybble is column 37 | // Bit 4 set in lower nybble means key is shifted (|8) 38 | // 0xFF means the character is not supported by the MSX keyboardc 39 | const uint8_t msx_key_matrix[128] PROGMEM = { 40 | 0xFF, 0xFF, 0x30 | 8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 00-07 41 | 0x75, 0x73, 0xFF, 0xFF, 0xFF, 0x77, 0xFF, 0xFF, // 08-0F 42 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 10-17 43 | 0xFF, 0xFF, 0xFF, 0xFF, 0x72, 0xFF, 0xFF, 0xFF, // 18-1F 44 | 0x80 | 8, 0x01 | 8, 0x20 | 8, 0x03 | 8, 0x04 | 8, 0x05 | 8, 0x07 | 8, 0x20, // 20-27 45 | 0x11 | 8, 0x00 | 8, 0x10 | 8, 0x13 | 8, 0x22, 0x12, 0x23, 0x24, // 28-2F 46 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 30-37 47 | 0x10, 0x11, 0x17 | 8, 0x17, 0x22 | 8, 0x13, 0x23 | 8, 0x24 | 8, // 38-3F 48 | 0x02 | 8, 0x26 | 8, 0x27 | 8, 0x30 | 8, 0x31 | 8, 0x32 | 8, 0x33 | 8, 0x34 | 8, // 40-47 49 | 0x35 | 8, 0x36 | 8, 0x37 | 8, 0x40 | 8, 0x41 | 8, 0x42 | 8, 0x43 | 8, 0x44 | 8, // 48-4F 50 | 0x45 | 8, 0x46 | 8, 0x47 | 8, 0x50 | 8, 0x51 | 8, 0x52 | 8, 0x53 | 8, 0x54 | 8, // 50-57 51 | 0x55 | 8, 0x56 | 8, 0x57 | 8, 0x15, 0x14, 0x16, 0x06 | 8, 0x12 | 8, // 58-5F 52 | 0x21, 0x26, 0x27, 0x30, 0x31, 0x32, 0x33, 0x34, // 60-67 53 | 0x35, 0x36, 0x37, 0x40, 0x41, 0x42, 0x43, 0x44, // 68-6F 54 | 0x45, 0x46, 0x47, 0x50, 0x51, 0x52, 0x53, 0x54, // 70-77 55 | 0x55, 0x56, 0x57, 0x15 | 8, 0x14 | 8, 0x16 | 8, 0x21 | 8, 0x83 // 78-7F 56 | }; 57 | 58 | #define NO_KEY 0xFF 59 | #define SHIFT_KEY 0x60 60 | #define CTRL_KEY 0x61 61 | 62 | #define ROW(s) (s >> 4) 63 | #define SHIFTED(s) (s & 8) 64 | #define BITS(s) ~(1 << (s & 7)) 65 | 66 | static uint8_t current_row = 0; 67 | static uint8_t shift_step = 0; 68 | 69 | uint8_t msx_scanrow(void) 70 | { 71 | if (uart_testrx(0) == 0) 72 | return NO_KEY; 73 | 74 | uint8_t c = uart_peek(0) & 0x7F; 75 | uint8_t scancode = pgm_read_byte(&msx_key_matrix[c]); 76 | uint8_t modkey = (c < 0x20) ? CTRL_KEY : SHIFT_KEY; 77 | 78 | if (scancode == NO_KEY) { 79 | uart_getc(0); 80 | return NO_KEY; 81 | } else if (!SHIFTED(scancode) && current_row == ROW(scancode)) { 82 | uart_getc(0); 83 | return BITS(scancode); 84 | } else if (SHIFTED(scancode)) { 85 | if (shift_step == 0 && current_row == ROW(modkey)) { 86 | shift_step = 1; 87 | return BITS(modkey); 88 | } else if (shift_step == 1 && current_row == ROW(scancode)) { 89 | shift_step = 2; 90 | return BITS(scancode); 91 | } else if (shift_step == 2 && current_row == ROW(modkey)) { 92 | shift_step = 0; 93 | uart_getc(0); 94 | return BITS(modkey); 95 | } 96 | } 97 | return NO_KEY; 98 | } 99 | 100 | uint8_t msx_setrow(uint8_t row) 101 | { 102 | current_row = row & 0xF; 103 | } -------------------------------------------------------------------------------- /firmware/emulation/msxkey.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file msxkey.h MSX keyboard emulation 25 | */ 26 | 27 | #ifndef EMULATION_MSXKEY_H 28 | #define EMULATION_MSXKEY_H 29 | 30 | #define MSX_KEY_COL MSX_KEY_BASE 31 | #define MSX_KEY_ROW MSX_KEY_BASE + 1 32 | 33 | uint8_t msx_scanrow(void); 34 | uint8_t msx_setrow(uint8_t row); 35 | 36 | #endif -------------------------------------------------------------------------------- /firmware/emulation/simhboot.h: -------------------------------------------------------------------------------- 1 | /* altairz80_dsk.c: MITS Altair 88-DISK Simulator 2 | Copyright (c) 2002-2014, Peter Schorn 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the "Software"), 5 | to deal in the Software without restriction, including without limitation 6 | the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 | and/or sell copies of the Software, and to permit persons to whom the 8 | Software is furnished to do so, subject to the following conditions: 9 | The above copyright notice and this permission notice shall be included in 10 | all copies or substantial portions of the Software. 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 14 | PETER SCHORN BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 15 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 17 | Except as contained in this notice, the name of Peter Schorn shall not 18 | be used in advertising or otherwise to promote the sale, use or other dealings 19 | in this Software without prior written authorization from Peter Schorn. 20 | Based on work by Charles E Owen (c) 1997 21 | */ 22 | 23 | /** 24 | * @file simhboot.h SIMH AltairZ80 bootloader 25 | * 26 | * Assembled version of simhboot.asm 27 | */ 28 | 29 | #ifndef EMULATION_SIMHBOOT_H 30 | #define EMULATION_SIMHBOOT_H 31 | 32 | #include "util/pgmspace.h" 33 | 34 | unsigned const char simhboot_bin[] PROGMEM = { 35 | 0xf3, 0x06, 0x80, 0x3e, 0x0e, 0xd3, 0xfe, 0x05, /* ff00-ff07 */ 36 | 0xc2, 0x05, 0xff, 0x3e, 0x16, 0xd3, 0xfe, 0x3e, /* ff08-ff0f */ 37 | 0x12, 0xd3, 0xfe, 0xdb, 0xfe, 0xb7, 0xca, 0x20, /* ff10-ff17 */ 38 | 0xff, 0x3e, 0x0c, 0xd3, 0xfe, 0xaf, 0xd3, 0xfe, /* ff18-ff1f */ 39 | 0x21, 0x00, 0x5c, 0x11, 0x33, 0xff, 0x0e, 0x88, /* ff20-ff27 */ 40 | 0x1a, 0x77, 0x13, 0x23, 0x0d, 0xc2, 0x28, 0xff, /* ff28-ff2f */ 41 | 0xc3, 0x00, 0x5c, 0x31, 0x21, 0x5d, 0x3e, 0x00, /* ff30-ff37 */ 42 | 0xd3, 0x08, 0x3e, 0x04, 0xd3, 0x09, 0xc3, 0x19, /* ff38-ff3f */ 43 | 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, 0x0e, 0x5c, /* ff40-ff47 */ 44 | 0x3e, 0x02, 0xd3, 0x09, 0xdb, 0x08, 0xe6, 0x40, /* ff48-ff4f */ 45 | 0xc2, 0x0e, 0x5c, 0x11, 0x00, 0x00, 0x06, 0x08, /* ff50-ff57 */ 46 | 0xc5, 0xd5, 0x11, 0x86, 0x80, 0x21, 0x88, 0x5c, /* ff58-ff5f */ 47 | 0xdb, 0x09, 0x1f, 0xda, 0x2d, 0x5c, 0xe6, 0x1f, /* ff60-ff67 */ 48 | 0xb8, 0xc2, 0x2d, 0x5c, 0xdb, 0x08, 0xb7, 0xfa, /* ff68-ff6f */ 49 | 0x39, 0x5c, 0xdb, 0x0a, 0x77, 0x23, 0x1d, 0xc2, /* ff70-ff77 */ 50 | 0x39, 0x5c, 0xd1, 0x21, 0x8b, 0x5c, 0x06, 0x80, /* ff78-ff7f */ 51 | 0x7e, 0x12, 0x23, 0x13, 0x05, 0xc2, 0x4d, 0x5c, /* ff80-ff87 */ 52 | 0xc1, 0x21, 0x00, 0x5c, 0x7a, 0xbc, 0xc2, 0x60, /* ff88-ff8f */ 53 | 0x5c, 0x7b, 0xbd, 0xd2, 0x80, 0x5c, 0x04, 0x04, /* ff90-ff97 */ 54 | 0x78, 0xfe, 0x20, 0xda, 0x25, 0x5c, 0x06, 0x01, /* ff98-ff9f */ 55 | 0xca, 0x25, 0x5c, 0xdb, 0x08, 0xe6, 0x02, 0xc2, /* ffa0-ffa7 */ 56 | 0x70, 0x5c, 0x3e, 0x01, 0xd3, 0x09, 0x06, 0x00, /* ffa8-ffaf */ 57 | 0xc3, 0x25, 0x5c, 0x3e, 0x80, 0xd3, 0x08, 0xfb, /* ffb0-ffb7 */ 58 | 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffb8-ffbf */ 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc0-ffc7 */ 60 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffc8-ffcf */ 61 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd0-ffd7 */ 62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffd8-ffdf */ 63 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe0-ffe7 */ 64 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* ffe8-ffef */ 65 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff0-fff7 */ 66 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* fff8-ffff */ 67 | }; 68 | unsigned int simhboot_bin_len = 256; 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /firmware/emulation/sio.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file sio.c Serial I/O emulation 25 | */ 26 | 27 | #include 28 | 29 | #include "fatfs/ff.h" 30 | 31 | #include "hardware/uart.h" 32 | 33 | #include "util/ffwrap.h" 34 | #include "util/pgmspace.h" 35 | 36 | #include "sio.h" 37 | 38 | /** 39 | * Physical to virtual UART mapping. 40 | */ 41 | 42 | static FIL sio_writefile[2]; 43 | static FIL sio_readfile[2]; 44 | 45 | static uint8_t sio_writemode[2] = { SIO_UART0, SIO_UART1 }; 46 | static uint8_t sio_readmode[2] = { SIO_UART0, SIO_UART1 }; 47 | 48 | #define SIO_EOF 0x1A 49 | 50 | void sio_unattach(uint8_t port, uint8_t dir) 51 | { 52 | FRESULT fr; 53 | if (port > 1) { 54 | printf_P(PSTR("error: valid port numbers are 0-1\n")); 55 | return; 56 | } 57 | 58 | uint8_t* sio_mode = sio_readmode; 59 | FIL* sio_file = sio_readfile; 60 | 61 | if (dir == SIO_OUTPUT) { 62 | sio_mode = sio_writemode; 63 | sio_file = sio_writefile; 64 | } 65 | 66 | if (sio_mode[port] == SIO_FILE) 67 | ffw_close(&sio_file[port]); 68 | sio_mode[port] = SIO_UNATTACHED; 69 | } 70 | 71 | /** 72 | * Attach a file to serial port 73 | */ 74 | void sio_attach(uint8_t port, uint8_t dir, uint8_t mode, char* filename) 75 | { 76 | if (port > 1) { 77 | printf_P(PSTR("error: valid port numbers are 0-1\n")); 78 | return; 79 | } 80 | uint8_t* sio_mode = sio_readmode; 81 | FIL* sio_file = sio_readfile; 82 | 83 | if (dir == SIO_OUTPUT) { 84 | sio_mode = sio_writemode; 85 | sio_file = sio_writefile; 86 | } 87 | 88 | if (sio_mode[port] == SIO_FILE) 89 | sio_unattach(port, dir); 90 | 91 | FRESULT fr; 92 | sio_mode[port] = mode; 93 | if (mode == SIO_FILE) { 94 | if ((fr = ffw_open(&sio_file[port], NULL, filename, (dir == SIO_INPUT ? FA_READ : FA_WRITE) | FA_OPEN_ALWAYS)) != FR_OK) 95 | sio_mode[port] = SIO_UNATTACHED; 96 | } 97 | } 98 | 99 | /** 100 | * Read from serial port 101 | */ 102 | uint8_t sio_read(uint8_t port) 103 | { 104 | UINT br; 105 | FRESULT fr; 106 | uint8_t data; 107 | if (port > 1) { 108 | printf_P(PSTR("error: valid port numbers are 0-1\n")); 109 | return 0; 110 | } 111 | if (sio_readmode[port] == SIO_FILE) { 112 | if ((fr = ffw_read(&sio_readfile[port], &data, 1, &br)) != FR_OK) 113 | return 0; 114 | if (br == 0) 115 | return SIO_EOF; 116 | return data; 117 | } else if (sio_readmode[port] != SIO_UNATTACHED) { 118 | return uart_getc(sio_readmode[port]); 119 | } 120 | return 0; 121 | } 122 | uint8_t sio0_read() 123 | { 124 | return sio_read(0); 125 | } 126 | uint8_t sio1_read() 127 | { 128 | return sio_read(1); 129 | } 130 | 131 | /** 132 | * Write to serial port 133 | */ 134 | void sio_write(uint8_t port, uint8_t data) 135 | { 136 | UINT bw; 137 | FRESULT fr; 138 | if (port > 1) { 139 | printf_P(PSTR("error: valid port numbers are 0-1\n")); 140 | return; 141 | } 142 | if (sio_writemode[port] == SIO_FILE) { 143 | if ((fr = ffw_write(&sio_writefile[port], &data, 1, &bw)) != FR_OK) 144 | return; 145 | } else if (sio_writemode[port] != SIO_UNATTACHED) { 146 | uart_putc(sio_writemode[port], data); 147 | } 148 | } 149 | 150 | void sio0_write(uint8_t data) 151 | { 152 | sio_write(0, data); 153 | } 154 | 155 | void sio1_write(uint8_t data) 156 | { 157 | sio_write(1, data); 158 | } 159 | 160 | /** 161 | * Get serial port status 162 | */ 163 | uint8_t sio_status(uint8_t port) 164 | { 165 | UINT bw; 166 | FRESULT fr; 167 | uint8_t status = 0; 168 | if (port > 1) { 169 | printf_P(PSTR("error: valid port numbers are 0-1\n")); 170 | return 0; 171 | } 172 | if (sio_writemode[port] == SIO_FILE) 173 | status |= (1 << 1); 174 | else if (sio_writemode[port] != SIO_UNATTACHED) 175 | status |= ((uart_testtx(sio_writemode[port]) == 0)) << 1; 176 | 177 | if (sio_readmode[port] == SIO_FILE) 178 | status |= 1; 179 | else if (sio_readmode[port] != SIO_UNATTACHED) 180 | status |= (uart_testrx(sio_readmode[port]) > 0); 181 | return status; 182 | } 183 | uint8_t sio0_status() 184 | { 185 | return sio_status(0); 186 | } 187 | 188 | uint8_t sio1_status() 189 | { 190 | return sio_status(1); 191 | } -------------------------------------------------------------------------------- /firmware/emulation/sio.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file sio.h Serial I/O emulation 25 | */ 26 | 27 | #ifndef EMULATION_SIO_H 28 | #define EMULATION_SIO_H 29 | 30 | #include 31 | 32 | #ifndef SIO_BASE 33 | #define SIO_BASE 0x10 34 | #endif 35 | 36 | #define SIO0_STATUS SIO_BASE 37 | #define SIO0_DATA SIO_BASE + 1 38 | #define SIO1_STATUS SIO_BASE + 2 39 | #define SIO1_DATA SIO_BASE + 3 40 | 41 | #define SIO_UART0 0 42 | #define SIO_UART1 1 43 | #define SIO_FILE 0xfe 44 | #define SIO_UNATTACHED 0xff 45 | 46 | #define SIO_OUTPUT 0 47 | #define SIO_INPUT 1 48 | 49 | void sio_attach(uint8_t port, uint8_t dir, uint8_t mode, char* filename); 50 | uint8_t sio0_read(); 51 | uint8_t sio1_read(); 52 | void sio0_write(uint8_t data); 53 | void sio1_write(uint8_t data); 54 | uint8_t sio0_status(); 55 | uint8_t sio1_status(); 56 | 57 | #endif -------------------------------------------------------------------------------- /firmware/fatfs/diskio.c: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /** @file diskio.c Low level disk I/O module glue functions */ 3 | /* (C)ChaN, 2016 */ 4 | /*-----------------------------------------------------------------------*/ 5 | /* If a working storage control module is available, it should be */ 6 | /* attached to the FatFs via a glue function rather than modifying it. */ 7 | /* This is an example of glue functions to attach various exsisting */ 8 | /* storage control modules to the FatFs module with a defined API. */ 9 | /*-----------------------------------------------------------------------*/ 10 | 11 | #include "diskio.h" /* FatFs lower layer API */ 12 | #ifdef DRV_MMC 13 | #include "hardware/mmc.h" /* Header file of existing SD control module */ 14 | #endif 15 | 16 | /** 17 | * Get Drive Status 18 | */ 19 | DSTATUS disk_status( 20 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 21 | ) 22 | { 23 | switch (pdrv) { 24 | #ifdef DRV_CFC 25 | case DRV_CFC: 26 | return cf_disk_status(); 27 | #endif 28 | #ifdef DRV_MMC 29 | case DRV_MMC: 30 | return mmc_disk_status(); 31 | #endif 32 | } 33 | return STA_NOINIT; 34 | } 35 | 36 | /** 37 | * Initialize a Drive 38 | */ 39 | DSTATUS disk_initialize( 40 | BYTE pdrv /* Physical drive nmuber to identify the drive */ 41 | ) 42 | { 43 | switch (pdrv) { 44 | #ifdef DRV_CFC 45 | case DRV_CFC: 46 | return cf_disk_initialize(); 47 | #endif 48 | #ifdef DRV_MMC 49 | case DRV_MMC: 50 | return mmc_disk_initialize(); 51 | #endif 52 | } 53 | return STA_NOINIT; 54 | } 55 | 56 | /** 57 | * Read Sector(s) 58 | */ 59 | DRESULT disk_read( 60 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 61 | BYTE* buff, /* Data buffer to store read data */ 62 | DWORD sector, /* Sector address in LBA */ 63 | UINT count /* Number of sectors to read */ 64 | ) 65 | { 66 | switch (pdrv) { 67 | #ifdef DRV_CFC 68 | case DRV_CFC: 69 | return cf_disk_read(buff, sector, count); 70 | #endif 71 | #ifdef DRV_MMC 72 | case DRV_MMC: 73 | return mmc_disk_read(buff, sector, count); 74 | #endif 75 | } 76 | return RES_PARERR; 77 | } 78 | 79 | /** 80 | * Write Sector(s) 81 | */ 82 | #if _USE_WRITE 83 | DRESULT disk_write( 84 | BYTE pdrv, /* Physical drive nmuber to identify the drive */ 85 | const BYTE* buff, /* Data to be written */ 86 | DWORD sector, /* Sector address in LBA */ 87 | UINT count /* Number of sectors to write */ 88 | ) 89 | { 90 | switch (pdrv) { 91 | #ifdef DRV_CFC 92 | case DRV_CFC: 93 | return cf_disk_write(buff, sector, count); 94 | #endif 95 | #ifdef DRV_MMC 96 | case DRV_MMC: 97 | return mmc_disk_write(buff, sector, count); 98 | #endif 99 | } 100 | return RES_PARERR; 101 | } 102 | #endif 103 | 104 | /** 105 | * Miscellaneous Functions 106 | */ 107 | #if _USE_IOCTL 108 | DRESULT disk_ioctl( 109 | BYTE pdrv, /* Physical drive nmuber (0..) */ 110 | BYTE cmd, /* Control code */ 111 | void* buff /* Buffer to send/receive control data */ 112 | ) 113 | { 114 | switch (pdrv) { 115 | #ifdef DRV_CFC 116 | case DRV_CFC: 117 | return cf_disk_ioctl(cmd, buff); 118 | #endif 119 | #ifdef DRV_MMC 120 | case DRV_MMC: 121 | return mmc_disk_ioctl(cmd, buff); 122 | #endif 123 | } 124 | return RES_PARERR; 125 | } 126 | #endif 127 | 128 | /** 129 | * Timer driven procedure 130 | */ 131 | void disk_timerproc(void) 132 | { 133 | #ifdef DRV_CFC 134 | cf_disk_timerproc(); 135 | #endif 136 | #ifdef DRV_MMC 137 | mmc_disk_timerproc(); 138 | #endif 139 | } 140 | -------------------------------------------------------------------------------- /firmware/fatfs/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /** @file diskio.h Low level disk interface modlue include file */ 3 | /* (C)ChaN, 2014 */ 4 | /*-----------------------------------------------------------------------*/ 5 | 6 | #ifndef _DISKIO_DEFINED 7 | #define _DISKIO_DEFINED 8 | 9 | #ifdef __cplusplus 10 | extern "C" { 11 | #endif 12 | 13 | #define DRV_MMC 0 /**< SD card is drive 0 */ 14 | 15 | #define _USE_WRITE 1 /**< 1: Enable disk_write function */ 16 | #define _USE_IOCTL 1 /**< 1: Enable disk_ioctl fucntion */ 17 | #define _USE_ISDIO 1 /**< 1: Enable iSDIO controls via disk_ioctl */ 18 | 19 | #include "ff.h" 20 | 21 | /* Status of Disk Functions */ 22 | typedef BYTE DSTATUS; 23 | 24 | /* Results of Disk Functions */ 25 | typedef enum { 26 | RES_OK = 0, /**< 0: Successful */ 27 | RES_ERROR, /**< 1: R/W Error */ 28 | RES_WRPRT, /**< 2: Write Protected */ 29 | RES_NOTRDY, /**< 3: Not Ready */ 30 | RES_PARERR /**< 4: Invalid Parameter */ 31 | } DRESULT; 32 | 33 | /* Command structure for iSDIO ioctl command */ 34 | typedef struct { 35 | BYTE func; /**< Function number: 0..7 */ 36 | WORD ndata; /**< Number of bytes to transfer: 1..512, or mask + data */ 37 | DWORD addr; /**< Register address: 0..0x1FFFF */ 38 | void* data; /**< Pointer to the data (to be written | read buffer) */ 39 | } SDIO_CTRL; 40 | 41 | /*---------------------------------------*/ 42 | /* Prototypes for disk control functions */ 43 | 44 | DSTATUS disk_initialize(BYTE pdrv); 45 | DSTATUS disk_status(BYTE pdrv); 46 | DRESULT disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count); 47 | DRESULT disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); 48 | DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff); 49 | void disk_timerproc(void); 50 | 51 | /* Disk Status Bits (DSTATUS) */ 52 | #define STA_NOINIT 0x01 /**< Drive not initialized */ 53 | #define STA_NODISK 0x02 /**< No medium in the drive */ 54 | #define STA_PROTECT 0x04 /**< Write protected */ 55 | 56 | /* Command code for disk_ioctrl fucntion */ 57 | 58 | /* Generic command (Used by FatFs) */ 59 | #define CTRL_SYNC 0 /**< Complete pending write process (needed at _FS_READONLY == 0) */ 60 | #define GET_SECTOR_COUNT 1 /**< Get media size (needed at _USE_MKFS == 1) */ 61 | #define GET_SECTOR_SIZE 2 /**< Get sector size (needed at _MAX_SS != _MIN_SS) */ 62 | #define GET_BLOCK_SIZE 3 /**< Get erase block size (needed at _USE_MKFS == 1) */ 63 | #define CTRL_TRIM 4 /**< Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ 64 | 65 | /* Generic command (Not used by FatFs) */ 66 | #define CTRL_FORMAT 5 /**< Create physical format on the media */ 67 | #define CTRL_POWER_IDLE 6 /**< Put the device idle state */ 68 | #define CTRL_POWER_OFF 7 /**< Put the device off state */ 69 | #define CTRL_LOCK 8 /**< Lock media removal */ 70 | #define CTRL_UNLOCK 9 /**< Unlock media removal */ 71 | #define CTRL_EJECT 10 /**< Eject media */ 72 | 73 | /* MMC/SDC specific command (Not used by FatFs) */ 74 | #define MMC_GET_TYPE 50 /**< Get card type */ 75 | #define MMC_GET_CSD 51 /**< Get CSD */ 76 | #define MMC_GET_CID 52 /**< Get CID */ 77 | #define MMC_GET_OCR 53 /**< Get OCR */ 78 | #define MMC_GET_SDSTAT 54 /**< Get SD status */ 79 | #define ISDIO_READ 55 /**< Read data form SD iSDIO register */ 80 | #define ISDIO_WRITE 56 /**< Write data to SD iSDIO register */ 81 | #define ISDIO_MRITE 57 /**< Masked write data to SD iSDIO register */ 82 | 83 | /* ATA/CF specific command (Not used by FatFs) */ 84 | #define ATA_GET_REV 60 /**< Get F/W revision */ 85 | #define ATA_GET_MODEL 61 /**< Get model name */ 86 | #define ATA_GET_SN 62 /**< Get serial number */ 87 | 88 | /* MMC card type flags (MMC_GET_TYPE) */ 89 | #define CT_MMC 0x01 /**< MMC ver 3 */ 90 | #define CT_SD1 0x02 /**< SD ver 1 */ 91 | #define CT_SD2 0x04 /**< SD ver 2 */ 92 | #define CT_SDC (CT_SD1 | CT_SD2) /**< SD */ 93 | #define CT_BLOCK 0x08 /**< Block addressing */ 94 | 95 | #ifdef __cplusplus 96 | } 97 | #endif 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /firmware/fatfs/ffsystem.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------*/ 2 | /* A Sample Code of User Provided OS Dependent Functions for FatFs */ 3 | /*------------------------------------------------------------------------*/ 4 | 5 | #include "ff.h" 6 | 7 | #if FF_USE_LFN == 3 /* Use dynamic memory allocation */ 8 | 9 | /*------------------------------------------------------------------------*/ 10 | /* Allocate/Free a Memory Block */ 11 | /*------------------------------------------------------------------------*/ 12 | 13 | #include /* with POSIX API */ 14 | 15 | void* ff_memalloc(/* Returns pointer to the allocated memory block (null if not enough core) */ 16 | UINT msize /* Number of bytes to allocate */ 17 | ) 18 | { 19 | return malloc((size_t)msize); /* Allocate a new memory block */ 20 | } 21 | 22 | void ff_memfree( 23 | void* mblock /* Pointer to the memory block to free (no effect if null) */ 24 | ) 25 | { 26 | free(mblock); /* Free the memory block */ 27 | } 28 | 29 | #endif 30 | 31 | #if FF_FS_REENTRANT /* Mutal exclusion */ 32 | /*------------------------------------------------------------------------*/ 33 | /* Definitions of Mutex */ 34 | /*------------------------------------------------------------------------*/ 35 | 36 | #define OS_TYPE 0 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */ 37 | 38 | #if OS_TYPE == 0 /* Win32 */ 39 | #include 40 | static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */ 41 | 42 | #elif OS_TYPE == 1 /* uITRON */ 43 | #include "itron.h" 44 | #include "kernel.h" 45 | static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */ 46 | 47 | #elif OS_TYPE == 2 /* uc/OS-II */ 48 | #include "includes.h" 49 | static OS_EVENT* Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */ 50 | 51 | #elif OS_TYPE == 3 /* FreeRTOS */ 52 | #include "FreeRTOS.h" 53 | #include "semphr.h" 54 | static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */ 55 | 56 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 57 | #include "cmsis_os.h" 58 | static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */ 59 | 60 | #endif 61 | 62 | /*------------------------------------------------------------------------*/ 63 | /* Create a Mutex */ 64 | /*------------------------------------------------------------------------*/ 65 | /* This function is called in f_mount function to create a new mutex 66 | / or semaphore for the volume. When a 0 is returned, the f_mount function 67 | / fails with FR_INT_ERR. 68 | */ 69 | 70 | int ff_mutex_create(/* Returns 1:Function succeeded or 0:Could not create the mutex */ 71 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 72 | ) 73 | { 74 | #if OS_TYPE == 0 /* Win32 */ 75 | Mutex[vol] = CreateMutex(NULL, FALSE, NULL); 76 | return (int)(Mutex[vol] != INVALID_HANDLE_VALUE); 77 | 78 | #elif OS_TYPE == 1 /* uITRON */ 79 | T_CMTX cmtx = { TA_TPRI, 1 }; 80 | 81 | Mutex[vol] = acre_mtx(&cmtx); 82 | return (int)(Mutex[vol] > 0); 83 | 84 | #elif OS_TYPE == 2 /* uC/OS-II */ 85 | OS_ERR err; 86 | 87 | Mutex[vol] = OSMutexCreate(0, &err); 88 | return (int)(err == OS_NO_ERR); 89 | 90 | #elif OS_TYPE == 3 /* FreeRTOS */ 91 | Mutex[vol] = xSemaphoreCreateMutex(); 92 | return (int)(Mutex[vol] != NULL); 93 | 94 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 95 | osMutexDef(cmsis_os_mutex); 96 | 97 | Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex)); 98 | return (int)(Mutex[vol] != NULL); 99 | 100 | #endif 101 | } 102 | 103 | /*------------------------------------------------------------------------*/ 104 | /* Delete a Mutex */ 105 | /*------------------------------------------------------------------------*/ 106 | /* This function is called in f_mount function to delete a mutex or 107 | / semaphore of the volume created with ff_mutex_create function. 108 | */ 109 | 110 | void ff_mutex_delete(/* Returns 1:Function succeeded or 0:Could not delete due to an error */ 111 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 112 | ) 113 | { 114 | #if OS_TYPE == 0 /* Win32 */ 115 | CloseHandle(Mutex[vol]); 116 | 117 | #elif OS_TYPE == 1 /* uITRON */ 118 | del_mtx(Mutex[vol]); 119 | 120 | #elif OS_TYPE == 2 /* uC/OS-II */ 121 | OS_ERR err; 122 | 123 | OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err); 124 | 125 | #elif OS_TYPE == 3 /* FreeRTOS */ 126 | vSemaphoreDelete(Mutex[vol]); 127 | 128 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 129 | osMutexDelete(Mutex[vol]); 130 | 131 | #endif 132 | } 133 | 134 | /*------------------------------------------------------------------------*/ 135 | /* Request a Grant to Access the Volume */ 136 | /*------------------------------------------------------------------------*/ 137 | /* This function is called on enter file functions to lock the volume. 138 | / When a 0 is returned, the file function fails with FR_TIMEOUT. 139 | */ 140 | 141 | int ff_mutex_take(/* Returns 1:Succeeded or 0:Timeout */ 142 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 143 | ) 144 | { 145 | #if OS_TYPE == 0 /* Win32 */ 146 | return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0); 147 | 148 | #elif OS_TYPE == 1 /* uITRON */ 149 | return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK); 150 | 151 | #elif OS_TYPE == 2 /* uC/OS-II */ 152 | OS_ERR err; 153 | 154 | OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err)); 155 | return (int)(err == OS_NO_ERR); 156 | 157 | #elif OS_TYPE == 3 /* FreeRTOS */ 158 | return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE); 159 | 160 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 161 | return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK); 162 | 163 | #endif 164 | } 165 | 166 | /*------------------------------------------------------------------------*/ 167 | /* Release a Grant to Access the Volume */ 168 | /*------------------------------------------------------------------------*/ 169 | /* This function is called on leave file functions to unlock the volume. 170 | */ 171 | 172 | void ff_mutex_give( 173 | int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ 174 | ) 175 | { 176 | #if OS_TYPE == 0 /* Win32 */ 177 | ReleaseMutex(Mutex[vol]); 178 | 179 | #elif OS_TYPE == 1 /* uITRON */ 180 | unl_mtx(Mutex[vol]); 181 | 182 | #elif OS_TYPE == 2 /* uC/OS-II */ 183 | OSMutexPost(Mutex[vol]); 184 | 185 | #elif OS_TYPE == 3 /* FreeRTOS */ 186 | xSemaphoreGive(Mutex[vol]); 187 | 188 | #elif OS_TYPE == 4 /* CMSIS-RTOS */ 189 | osMutexRelease(Mutex[vol]); 190 | 191 | #endif 192 | } 193 | 194 | #endif /* FF_FS_REENTRANT */ 195 | -------------------------------------------------------------------------------- /firmware/hardware/bus.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file bus.c Low-level control of the Z80 bus 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "util/pgmspace.h" 33 | #include "util/string.h" 34 | 35 | #include "bus.h" 36 | #include "mcp23s17.h" 37 | 38 | /** 39 | * Run the clock for a specified number of cycles 40 | */ 41 | void clk_cycle(uint8_t cycles) 42 | { 43 | uint8_t i; 44 | for (i = 0; i < cycles; i++) { 45 | CLK_HI; 46 | CLK_LO; 47 | } 48 | } 49 | 50 | uint8_t clkdiv = 2; 51 | 52 | /** 53 | * Set clock divider 54 | */ 55 | void set_clkdiv(uint8_t div) 56 | { 57 | clkdiv = div; 58 | } 59 | 60 | /** 61 | * Get clock divider 62 | */ 63 | uint8_t get_clkdiv(void) 64 | { 65 | return clkdiv; 66 | } 67 | 68 | /** 69 | * Run the Z80's clock 70 | */ 71 | void clk_run(void) 72 | { 73 | // Fast PWM mode with adjustable top and no prescaler 74 | TCCR2A |= (1 << COM2B1) | (1 << WGM21) | (1 << WGM20); 75 | TCCR2B |= (1 << WGM22) | (1 << CS20); 76 | OCR2A = (clkdiv - 1); 77 | OCR2B = (clkdiv - 1) >> 1; 78 | } 79 | 80 | /** 81 | * Stop the Z80's clock 82 | */ 83 | void clk_stop() 84 | { 85 | TCCR2A = 0; 86 | TCCR2B = 0; 87 | OCR2A = 0; 88 | OCR2B = 0; 89 | } 90 | 91 | /** 92 | * Request control of the bus from the Z80 93 | */ 94 | uint8_t bus_request(void) 95 | { 96 | uint8_t i = 255; 97 | 98 | BUSRQ_LO; // request bus 99 | // Clock the Z80 until it releases control of the bus 100 | while (GET_BUSACK) { 101 | CLK_TOGGLE; 102 | if (i-- == 0) { 103 | BUSRQ_HI; 104 | return 0; 105 | } 106 | } 107 | IOMR_HI; 108 | RDWR_HI; 109 | IOMR_OUTPUT; 110 | RDWR_OUTPUT; 111 | ADDR_OUTPUT; 112 | DATA_INPUT; 113 | return 1; 114 | } 115 | 116 | /** 117 | * Return control of the bus to the Z80 118 | */ 119 | uint8_t bus_release(void) 120 | { 121 | uint8_t i = 255; 122 | 123 | IOMR_INPUT; 124 | RDWR_INPUT; 125 | ADDR_INPUT; 126 | DATA_INPUT; 127 | SET_DATA(0); // Disable pullups on data and address lines 128 | SET_ADDRLO(0); 129 | BUSRQ_HI; 130 | 131 | // Clock the Z80 until it takes back control of the bus 132 | while (!GET_BUSACK) { 133 | CLK_TOGGLE; 134 | if (i-- == 0) { 135 | return 0; 136 | } 137 | } 138 | return 1; 139 | } 140 | 141 | /** 142 | * Retrieve the current bus status 143 | */ 144 | bus_stat bus_status(void) 145 | { 146 | bus_stat status; 147 | uint16_t iox = iox0_read16(ADDRHI_GPIO); 148 | status.flags = (PINB & CTRLB_MASK) | (PIND & CTRLD_MASK); 149 | status.xflags = iox >> 8; 150 | status.data = DATA_PIN; 151 | status.addr = ADDRLO_PIN | ((iox & 0xFF) << 8); 152 | return status; 153 | } 154 | 155 | /** 156 | * Retrieve only the bus signals that can be retrieved quickly 157 | */ 158 | bus_stat bus_status_fast(void) 159 | { 160 | bus_stat status; 161 | status.flags = (PINB & CTRLB_MASK) | (PIND & CTRLD_MASK); 162 | status.xflags = 0xFF; 163 | status.data = GET_DATA; 164 | status.addr = GET_ADDRLO; 165 | return status; 166 | } 167 | 168 | /** 169 | * Log the bus status 170 | */ 171 | void bus_log(bus_stat status) 172 | { 173 | printf_P( 174 | PSTR("\t%04x %02x %c %s %s %s %s %s %s %s %s %s %s\n"), 175 | status.addr, 176 | status.data, 177 | 0x20 <= status.data && status.data <= 0x7e ? status.data : ' ', 178 | !MREQ_STATUS ? "mreq" : !IORQ_STATUS ? "iorq " 179 | : " ", 180 | !RD_STATUS ? "rd " : !WR_STATUS ? "wr " 181 | : !RFSH_STATUS ? "rfsh" 182 | : " ", 183 | !M1_STATUS ? "m1" : " ", 184 | !BUSRQ_STATUS ? "busrq" : " ", 185 | !BUSACK_STATUS ? "busack" : " ", 186 | !WAIT_STATUS ? "wait" : " ", 187 | !HALT_STATUS ? "halt" : " ", 188 | !INT_STATUS ? "int" : " ", 189 | !NMI_STATUS ? "nmi" : " ", 190 | !RESET_STATUS ? "reset" : " "); 191 | } 192 | 193 | /** 194 | * Initialize the bus 195 | */ 196 | void bus_init(void) 197 | { 198 | // Initialize I/O expander 199 | iox_init(); 200 | 201 | // Initialize control signals 202 | CTRLB_OUTPUT_INIT; 203 | CTRLD_OUTPUT_INIT; 204 | CTRLX_OUTPUT_INIT; 205 | CTRLX_PULLUP_INIT; 206 | 207 | // Reset the processor 208 | BUSRQ_HI; 209 | RESET_OUTPUT; 210 | clk_cycle(3); 211 | RESET_INPUT; 212 | 213 | // Start out in control of the bus 214 | if (!bus_request()) 215 | printf_P(PSTR("bus request timed out")); 216 | } -------------------------------------------------------------------------------- /firmware/hardware/hardware.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file hardware.c Hardware initialization 25 | */ 26 | 27 | #include "bus.h" 28 | #include "io.h" 29 | #include "sn76489.h" 30 | #include "tms9918.h" 31 | 32 | void hardware_init() 33 | { 34 | bus_init(); 35 | iorq_init(); 36 | #ifdef TMS_BASE 37 | tms_init(TMS_TEXT); 38 | #endif 39 | #ifdef SN76489_PORT 40 | sn76489_mute(); 41 | #endif 42 | } -------------------------------------------------------------------------------- /firmware/hardware/hardware.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file hardware.c Hardware initialization 25 | */ 26 | 27 | #ifndef HARDWARE_H 28 | #define HARDWARE_H 29 | void hardware_init(); 30 | #endif -------------------------------------------------------------------------------- /firmware/hardware/io.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file io.c I/O request handler 25 | */ 26 | 27 | #ifndef HARDWARE_IO_H 28 | #define HARDWARE_IO_H 29 | 30 | #include 31 | 32 | #include "bus.h" 33 | 34 | typedef enum { 35 | DEV_UNASSIGNED, 36 | 37 | EMU_ACIA0_STATUS, 38 | EMU_ACIA0_DATA, 39 | EMU_ACIA1_STATUS, 40 | EMU_ACIA1_DATA, 41 | 42 | EMU_88DSK_STATUS, 43 | EMU_88DSK_CONTROL, 44 | EMU_88DSK_DATA, 45 | 46 | #ifdef MSX_KEY_BASE 47 | EMU_MSXKEY_COL, 48 | EMU_MSXKEY_ROW, 49 | #endif 50 | 51 | Z80CTRL_DEV, 52 | Z80CTRL_REG, 53 | Z80CTRL_LO, 54 | Z80CTRL_HI, 55 | Z80CTRL_FATFS_DMA, 56 | Z80CTRL_BDOS_EMU, 57 | 58 | EXT_UNKNOWN, 59 | 60 | #ifdef BANK_BASE 61 | EXT_WBW_RAM, 62 | #endif 63 | 64 | #ifdef TMS_BASE 65 | EXT_TMS_RAM, 66 | EXT_TMS_REG, 67 | #endif 68 | 69 | #ifdef SN76489_PORT 70 | EXT_SN76489, 71 | #endif 72 | 73 | DEV_INVALID 74 | } device_type; 75 | 76 | typedef enum { 77 | IORQ_READ = 1, 78 | IORQ_WRITE, 79 | IORQ_RW 80 | } device_mode; 81 | 82 | void iorq_init(); 83 | void iorq_list(); 84 | uint8_t iorq_dispatch(); 85 | uint8_t iorq_deviceid(char* name); 86 | uint8_t iorq_assign(uint8_t port, device_mode mode, device_type device); 87 | 88 | uint8_t io_out(uint8_t addr, uint8_t value); 89 | uint8_t io_in(uint8_t addr); 90 | 91 | typedef enum { 92 | DMA_MAILBOX_UNSET = 0, 93 | DMA_MAILBOX_HALFSET, 94 | DMA_MAILBOX_SET 95 | } dma_status_t; 96 | 97 | extern void (*dma_function)(void); 98 | 99 | #endif -------------------------------------------------------------------------------- /firmware/hardware/mcp23s17.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file mcp23s17.c MCP23S17 convenience functions 25 | */ 26 | 27 | #include 28 | 29 | #include "util/pgmspace.h" 30 | 31 | #include "mcp23s17.h" 32 | #include "rtc.h" 33 | #include "spi.h" 34 | 35 | // translation table from bank 0 to bank 1 addresses 36 | const uint8_t iox_bank1[] PROGMEM = { 37 | 0x00, 0x10, // IODIR 38 | 0x01, 0x11, // IPOL 39 | 0x02, 0x12, // GPINTEN 40 | 0x03, 0x13, // DEFVAL 41 | 0x04, 0x14, // INTCON 42 | 0x05, 0x15, // IOCON 43 | 0x06, 0x16, // GPPU 44 | 0x07, 0x17, // INTF 45 | 0x08, 0x18, // INTCAP 46 | 0x09, 0x19, // GPIO 47 | 0x0a, 0x1a // OLAT 48 | }; 49 | 50 | #define IOX_SIGNATURE 0x40 51 | #define IOX_WRITE 0 52 | #define IOX_READ 1 53 | #define IOX_END AUX2_SEL 54 | 55 | // local copy of register values 56 | uint8_t iox0_registers[] = { 57 | 0xff, 0xff, // IODIR 58 | 0x00, 0x00, // IPOL 59 | 0x00, 0x00, // GPINTEN 60 | 0x00, 0x00, // DEFVAL 61 | 0x00, 0x00, // INTCON 62 | 0x00, 0x00, // IOCON 63 | 0x00, 0x00, // GPPU 64 | 0x00, 0x00, // INTF 65 | 0x00, 0x00, // INTCAP 66 | 0x00, 0x00, // GPIO 67 | 0x00, 0x00 // OLAT 68 | }; 69 | 70 | // Banks of IO expanders 1-7 71 | uint8_t iox_banks = 0; 72 | 73 | void iox_init(void) 74 | { 75 | spi_init(); 76 | // Enable individually addressable chips 77 | iox0_set(IOCON, HAEN); 78 | 79 | // Disable sequential operation 80 | iox0_set(IOCON, SEQOP); 81 | } 82 | 83 | void iox_begin(uint8_t chip, uint8_t mode, uint8_t reg) 84 | { 85 | IOX_SEL; 86 | if (iox_banks & (1 << chip)) 87 | reg = pgm_read_byte(&iox_bank1[reg]); 88 | spi_exchange(IOX_SIGNATURE | (chip << 1) | mode); 89 | spi_exchange(reg); 90 | } 91 | 92 | uint8_t iox_read(uint8_t chip, uint8_t reg) 93 | { 94 | chip &= 7; 95 | uint8_t data; 96 | iox_begin(chip, IOX_READ, reg); 97 | data = spi_exchange(0); 98 | IOX_END; 99 | return data; 100 | } 101 | 102 | void iox_write(uint8_t chip, uint8_t reg, uint8_t data) 103 | { 104 | chip &= 7; 105 | if (chip != 0) { 106 | iox_begin(chip, IOX_WRITE, reg); 107 | spi_exchange(data); 108 | IOX_END; 109 | if (reg == IOCON || reg == IOCONB) { 110 | if (data & BANK) 111 | iox_banks |= (1 << chip); 112 | else 113 | iox_banks &= ~(1 << chip); 114 | } 115 | } 116 | } 117 | 118 | void iox0_begin(uint8_t mode, uint8_t reg) 119 | { 120 | if (reg == IOCONB) 121 | reg = IOCON; 122 | if (iox0_registers[IOCON] & BANK) 123 | reg = pgm_read_byte(&iox_bank1[reg]); 124 | IOX_SEL; 125 | spi_exchange(IOX_SIGNATURE | mode); 126 | spi_exchange(reg); 127 | } 128 | 129 | uint8_t iox0_read(uint8_t reg) 130 | { 131 | iox0_begin(IOX_READ, reg); 132 | uint8_t data = spi_exchange(0); 133 | IOX_END; 134 | return data; 135 | } 136 | 137 | uint16_t iox0_read16(uint8_t reg) 138 | { 139 | iox0_begin(IOX_READ, reg); 140 | uint16_t data = spi_exchange(0); 141 | data |= spi_exchange(0) << 8; 142 | IOX_END; 143 | return data; 144 | } 145 | 146 | void iox0_write(uint8_t reg, uint8_t data) 147 | { 148 | iox0_registers[reg] = data; 149 | iox0_begin(IOX_WRITE, reg); 150 | spi_exchange(data); 151 | IOX_END; 152 | } 153 | 154 | void iox0_set(uint8_t reg, uint8_t mask) 155 | { 156 | iox0_write(reg, iox0_registers[reg] | mask); 157 | } 158 | 159 | void iox0_clear(uint8_t reg, uint8_t mask) 160 | { 161 | iox0_write(reg, iox0_registers[reg] & ~mask); 162 | } -------------------------------------------------------------------------------- /firmware/hardware/mcp23s17.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file mcp23s17.h MCP23S17 register definitions and convenience functions 25 | */ 26 | 27 | #ifndef HARDWARE_MCP23S17_H 28 | #define HARDWARE_MCP23S17_H 29 | 30 | #include 31 | 32 | // Register addresses in bank 0 33 | enum { 34 | IODIRA = 0x00, 35 | IODIRB = 0x01, 36 | IPOLA = 0x02, 37 | IPOLB = 0x03, 38 | GPINTENA = 0x04, 39 | GPINTENB = 0x05, 40 | DEFVALA = 0x06, 41 | DEFVALB = 0x07, 42 | INTCONA = 0x08, 43 | INTCONB = 0x09, 44 | IOCON = 0x0a, 45 | IOCONB = 0x0b, 46 | GPPUA = 0x0c, 47 | GPPUB = 0x0d, 48 | INTFA = 0x0e, 49 | INTFB = 0x0f, 50 | INTCAPA = 0x10, 51 | INTCAPB = 0x11, 52 | GPIOA = 0x12, 53 | GPIOB = 0x13, 54 | OLATA = 0x14, 55 | OLATB = 0x15 56 | }; 57 | 58 | // Bits in IOCON register 59 | enum { 60 | INTCC = (1 << 0), 61 | INTPOL = (1 << 1), 62 | ODR = (1 << 2), 63 | HAEN = (1 << 3), 64 | DISSLW = (1 << 4), 65 | SEQOP = (1 << 5), 66 | MIRROR = (1 << 6), 67 | BANK = (1 << 7) 68 | }; 69 | 70 | void iox_init(void); 71 | uint8_t iox_read(uint8_t chipaddr, uint8_t regaddr); 72 | uint16_t iox_read16(uint8_t chipaddr, uint8_t regaddr); 73 | void iox_write(uint8_t chipaddr, uint8_t regaddr, uint8_t data); 74 | 75 | void iox_extcs_init(uint8_t addr); 76 | void iox_extcs_lo(uint8_t c); 77 | void iox_extcs_hi(uint8_t c); 78 | 79 | uint8_t iox0_read(uint8_t reg); 80 | uint16_t iox0_read16(uint8_t reg); 81 | void iox0_write(uint8_t reg, uint8_t data); 82 | void iox0_set(uint8_t reg, uint8_t mask); 83 | void iox0_clear(uint8_t reg, uint8_t mask); 84 | #endif 85 | -------------------------------------------------------------------------------- /firmware/hardware/memory.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file memory.h memory-related functions 25 | */ 26 | 27 | #ifndef HARDWARE_MEMORY_H 28 | #define HARDWARE_MEMORY_H 29 | #include 30 | 31 | #if defined(BANK_PORT) || defined(BANK_BASE) 32 | void mem_bank(uint8_t bank, uint8_t page); 33 | void mem_bank_addr(uint32_t addr); 34 | #else 35 | #define mem_bank(bank, page) 36 | #define mem_bank_addr(addr) 37 | #endif 38 | 39 | void mem_read(uint32_t addr, void* buf, uint32_t len); 40 | void mem_write(uint32_t addr, const void* buf, uint32_t len); 41 | void mem_write_P(uint32_t addr, const void* buf, uint32_t len); 42 | 43 | void mem_read_banked(uint32_t addr, void* buf, uint32_t len); 44 | void mem_write_banked(uint32_t addr, const void* buf, uint32_t len); 45 | void mem_write_banked_P(uint32_t addr, const void* buf, uint32_t len); 46 | 47 | typedef void (*mem_readfunc_t)(uint32_t, void*, uint32_t); 48 | typedef void (*mem_writefunc_t)(uint32_t, const void*, uint32_t); 49 | uint32_t mem_loadbin(mem_writefunc_t mem_writefunc, char* filename, int32_t start, uint32_t offset, uint32_t len); 50 | void mem_savebin(mem_readfunc_t mem_readfunc, char* filename, uint32_t start, uint32_t len); 51 | 52 | #endif -------------------------------------------------------------------------------- /firmware/hardware/mmc.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /** @file mmc.h Low level disk interface modlue include file */ 3 | /* (C)ChaN, 2016 4 | /-----------------------------------------------------------------------*/ 5 | 6 | #ifndef HARDWARE_MMC_H 7 | #define HARDWARE_MMC_H 8 | 9 | #include "fatfs/diskio.h" 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | /*---------------------------------------*/ 16 | /* Prototypes for disk control functions */ 17 | 18 | DSTATUS mmc_disk_initialize(void); 19 | DSTATUS mmc_disk_status(void); 20 | DRESULT mmc_disk_read(BYTE* buff, DWORD sector, UINT count); 21 | DRESULT mmc_disk_write(const BYTE* buff, DWORD sector, UINT count); 22 | DRESULT mmc_disk_ioctl(BYTE cmd, void* buff); 23 | void mmc_disk_timerproc(void); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /firmware/hardware/rtc.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file rtc.h RTC functions 25 | */ 26 | #ifndef HARDWARE_RTC_H 27 | #define HARDWARE_RTC_H 28 | #include 29 | 30 | void rtc_read_burst(uint8_t start, uint8_t end, uint8_t values[]); 31 | void rtc_write_burst(uint8_t start, uint8_t end, uint8_t values[]); 32 | 33 | uint8_t rtc_read(uint8_t reg); 34 | void rtc_write(uint8_t reg, uint8_t value); 35 | 36 | void rtc_get_date(struct tm* date); 37 | void rtc_set_date(struct tm* date); 38 | #endif -------------------------------------------------------------------------------- /firmware/hardware/rtc_ds1302.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file rtc_ds1302.c DS1302+ RTC functions 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "rtc.h" 32 | #include "rtc_ds1302.h" 33 | #include "spi.h" 34 | 35 | void rtc_begin() 36 | { 37 | SPI_DISABLE; 38 | SCK_LO; 39 | _delay_us(4); 40 | RTC_SEL; 41 | _delay_us(4); 42 | } 43 | 44 | void rtc_end() 45 | { 46 | RTC_DESEL; 47 | SPI_ENABLE; 48 | } 49 | 50 | void rtc_byte_out(uint8_t value) 51 | { 52 | MISO_OUTPUT; 53 | for (uint8_t i = 0; i < 8; i++) { 54 | if (value & 1) 55 | MISO_HI; 56 | else 57 | MISO_LO; 58 | SCK_LO; 59 | _delay_us(2); 60 | SCK_HI; 61 | _delay_us(2); 62 | value >>= 1; 63 | } 64 | MISO_INPUT; 65 | } 66 | 67 | uint8_t rtc_byte_in() 68 | { 69 | uint8_t value = 0; 70 | MISO_INPUT; 71 | for (uint8_t i = 0; i < 8; i++) { 72 | value >>= 1; 73 | SCK_HI; 74 | _delay_us(2); 75 | SCK_LO; 76 | _delay_us(2); 77 | if (GET_MISO) 78 | value |= 0x80; 79 | } 80 | return value; 81 | } 82 | 83 | void rtc_read_burst(uint8_t addr, uint8_t len, uint8_t* values) 84 | { 85 | rtc_begin(); 86 | rtc_byte_out(addr | RTC_READ); 87 | for (uint8_t i = 0; i < len; i++) 88 | *values++ = rtc_byte_in(); 89 | rtc_end(); 90 | } 91 | 92 | void rtc_write_burst(uint8_t addr, uint8_t len, uint8_t* values) 93 | { 94 | rtc_begin(); 95 | rtc_byte_out(addr & ~RTC_READ); 96 | for (uint8_t i = 0; i <= len; i++) 97 | rtc_byte_out(*values++); 98 | rtc_end(); 99 | } 100 | 101 | uint8_t rtc_read(uint8_t reg) 102 | { 103 | uint8_t value; 104 | rtc_begin(); 105 | rtc_byte_out(reg | RTC_READ); 106 | value = rtc_byte_in(); 107 | rtc_end(); 108 | return value; 109 | } 110 | 111 | void rtc_write(uint8_t reg, uint8_t value) 112 | { 113 | rtc_begin(); 114 | rtc_byte_out(reg & ~RTC_READ); 115 | rtc_byte_out(value); 116 | rtc_end(); 117 | } 118 | 119 | #define frombcd(value) (((value) >> 4) * 10 + ((value) & 0xF)) 120 | 121 | void rtc_get_date(struct tm* date) 122 | { 123 | uint8_t data[8]; 124 | 125 | rtc_read_burst(RTC_CLKBURST, RTC_CLKSIZE, data); 126 | date->tm_year = frombcd(data[6]); 127 | date->tm_mon = frombcd(data[4]); 128 | date->tm_mday = frombcd(data[3]); 129 | date->tm_wday = data[5]; 130 | if ((data[2] & (1 << RTC_1224))) { 131 | // 12-hour mode 132 | date->tm_hour = frombcd(data[2] & 0x1F); 133 | if ((data[2] & (1 << RTC_AMPM))) // PM 134 | date->tm_hour += 12; 135 | } else { 136 | // 24-hour mode 137 | date->tm_hour = frombcd(data[2]); 138 | } 139 | date->tm_min = frombcd(data[1]); 140 | date->tm_sec = frombcd(data[0] & 0x7f); 141 | } 142 | 143 | #define tobcd(value) (((value / 10) << 4) | (value % 10)) 144 | 145 | void rtc_set_date(struct tm* date) 146 | { 147 | uint8_t data[8]; 148 | 149 | data[6] = tobcd(date->tm_year); 150 | data[5] = date->tm_wday; 151 | data[4] = tobcd(date->tm_mon); 152 | data[3] = tobcd(date->tm_mday); 153 | data[2] = tobcd(date->tm_hour); 154 | data[1] = tobcd(date->tm_min); 155 | data[0] = tobcd(date->tm_sec); 156 | rtc_write(RTC_WPREG, 0); 157 | rtc_write_burst(RTC_CLKBURST, RTC_CLKSIZE, data); 158 | } -------------------------------------------------------------------------------- /firmware/hardware/rtc_ds1302.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file rtc_ds1302.h DS1302+ RTC functions 25 | */ 26 | 27 | #ifndef HARDWARE_RTC_DS1302_H 28 | #define HARDWARE_RTC_DS1302_H 29 | 30 | #include 31 | #include 32 | 33 | #define RTC_READ 1 34 | 35 | #define RTC_SEC 0x80 36 | #define RTC_MIN 0x82 37 | #define RTC_HOUR 0x84 38 | #define RTC_DAY 0x86 39 | #define RTC_MONTH 0x88 40 | #define RTC_WEEKDAY 0x8A 41 | #define RTC_YEAR 0x8C 42 | #define RTC_WPREG 0x8E 43 | #define RTC_CHARGE 0x90 44 | #define RTC_CLKBURST 0xBE 45 | #define RTC_CLKSIZE 8 46 | 47 | #define RTC_RAMBASE 0xC0 48 | #define RTC_RAMSIZE 31 49 | #define RTC_RAMBURST 0xFE 50 | 51 | #define RTC_CHBIT 7 52 | #define RTC_WPBIT 7 53 | #define RTC_1224 7 54 | #define RTC_AMPM 5 55 | 56 | #define RTC_SEL AUX1_SEL 57 | #define RTC_DESEL AUX2_SEL 58 | 59 | #endif -------------------------------------------------------------------------------- /firmware/hardware/rtc_ds1306.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file rtc_ds1306.c DS1306+ RTC functions 25 | */ 26 | 27 | #include 28 | 29 | #include "rtc.h" 30 | #include "rtc_ds1306.h" 31 | #include "spi.h" 32 | 33 | void rtc_begin() 34 | { 35 | SPI_SLOW; 36 | SPI_PHASE1; 37 | RTC_SEL; 38 | } 39 | 40 | void rtc_end() 41 | { 42 | RTC_DESEL; 43 | SPI_PHASE0; 44 | SPI_FAST; 45 | } 46 | 47 | void rtc_read_burst(uint8_t start, uint8_t end, uint8_t values[]) 48 | { 49 | rtc_begin(); 50 | spi_exchange(start); 51 | for (uint8_t reg = start; reg <= end; reg++) 52 | *values++ = spi_exchange(0); 53 | rtc_end(); 54 | } 55 | 56 | void rtc_write_burst(uint8_t start, uint8_t end, uint8_t values[]) 57 | { 58 | rtc_begin(); 59 | spi_exchange(start | RTC_WRITE); 60 | for (uint8_t reg = start; reg <= end; reg++) 61 | spi_exchange(*values++); 62 | rtc_end(); 63 | } 64 | 65 | uint8_t rtc_read(uint8_t reg) 66 | { 67 | uint8_t value; 68 | rtc_read_burst(reg, reg, &value); 69 | return value; 70 | } 71 | 72 | void rtc_write(uint8_t reg, uint8_t value) 73 | { 74 | rtc_write_burst(reg, reg, &value); 75 | } 76 | 77 | #define frombcd(value) (((value) >> 4) * 10 + ((value) & 0xF)) 78 | 79 | void rtc_get_date(struct tm* date) 80 | { 81 | uint8_t data[7]; 82 | 83 | rtc_read_burst(RTC_SEC, RTC_YEAR, data); 84 | date->tm_year = frombcd(data[RTC_YEAR]); 85 | date->tm_mon = frombcd(data[RTC_MONTH]); 86 | date->tm_mday = frombcd(data[RTC_DAY]); 87 | date->tm_wday = data[RTC_WEEKDAY]; 88 | if ((data[RTC_HOUR] & (1 << RTC_1224))) { 89 | // 12-hour mode 90 | date->tm_hour = frombcd(data[RTC_HOUR] & 0x1F); 91 | if ((data[RTC_HOUR] & (1 << RTC_AMPM))) // PM 92 | date->tm_hour += 12; 93 | } else { 94 | // 24-hour mode 95 | date->tm_hour = frombcd(data[RTC_HOUR]); 96 | } 97 | date->tm_min = frombcd(data[RTC_MIN]); 98 | date->tm_sec = frombcd(data[RTC_SEC]); 99 | } 100 | 101 | #define tobcd(value) (((value / 10) << 4) | (value % 10)) 102 | 103 | void rtc_set_date(struct tm* date) 104 | { 105 | uint8_t data[7]; 106 | 107 | data[RTC_YEAR] = tobcd(date->tm_year); 108 | data[RTC_MONTH] = tobcd(date->tm_mon); 109 | data[RTC_DAY] = tobcd(date->tm_mday); 110 | data[RTC_WEEKDAY] = date->tm_wday; 111 | data[RTC_HOUR] = tobcd(date->tm_hour); 112 | data[RTC_MIN] = tobcd(date->tm_min); 113 | data[RTC_SEC] = tobcd(date->tm_sec); 114 | rtc_write_burst(RTC_SEC, RTC_YEAR, data); 115 | } -------------------------------------------------------------------------------- /firmware/hardware/rtc_ds1306.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file rtc_ds1306.h DS1306+ RTC functions 25 | */ 26 | 27 | #ifndef HARDWARE_RTC_DS1306_H 28 | #define HARDWARE_RTC_DS1306_H 29 | 30 | #include 31 | #include 32 | 33 | #define RTC_WRITE 0x80 34 | 35 | #define RTC_SEC 0x0 36 | #define RTC_MIN 0x1 37 | #define RTC_HOUR 0x2 38 | #define RTC_WEEKDAY 0x3 39 | #define RTC_DAY 0x4 40 | #define RTC_MONTH 0x5 41 | #define RTC_YEAR 0x6 42 | #define RTC_ALARM0 0x7 43 | #define RTC_ALARM1 0xB 44 | #define RTC_CONTROL 0xF 45 | #define RTC_STATUS 0x10 46 | #define RTC_CHARGE 0x11 47 | 48 | #define RTC_RAM_BASE 0x20 49 | #define RTC_RAM_SIZE 96 50 | 51 | #define RTC_AIE0 0 52 | #define RTC_AIE1 1 53 | #define RTC_HZ 2 54 | #define RTC_WP 6 55 | 56 | #define RTC_IRQF0 0 57 | #define RTC_IRQF1 1 58 | 59 | #define RTC_1224 6 60 | #define RTC_AMPM 5 61 | 62 | #define RTC_SEL AUX1_SEL 63 | #define RTC_DESEL AUX2_SEL 64 | 65 | #endif -------------------------------------------------------------------------------- /firmware/hardware/sn76489.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file sn76489.h SN76489 sound chip functions 25 | */ 26 | 27 | #include 28 | 29 | #include "bus.h" 30 | 31 | /** 32 | * Mute the SN76489 33 | */ 34 | void sn76489_mute() 35 | { 36 | #ifdef SN76489_PORT 37 | if (GET_BUSACK) 38 | return; 39 | uint8_t oldclkdiv = get_clkdiv(); 40 | set_clkdiv(4); 41 | clk_run(); 42 | DATA_OUTPUT; 43 | SET_ADDRLO(SN76489_PORT); 44 | IORQ_LO; 45 | SET_DATA(0x9F); 46 | WR_LO; 47 | _delay_us(10); 48 | WR_HI; 49 | SET_DATA(0xBF); 50 | WR_LO; 51 | _delay_us(10); 52 | WR_HI; 53 | SET_DATA(0xDF); 54 | WR_LO; 55 | _delay_us(10); 56 | WR_HI; 57 | SET_DATA(0xFF); 58 | WR_LO; 59 | _delay_us(10); 60 | WR_HI; 61 | IORQ_HI; 62 | clk_stop(); 63 | set_clkdiv(oldclkdiv); 64 | #endif 65 | } -------------------------------------------------------------------------------- /firmware/hardware/sn76489.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file sn76489.h SN76489 sound chip functions 25 | */ 26 | #ifndef HARDWARE_SN76489_H 27 | #define HARDWARE_SN76489_H 28 | void sn76489_mute(void); 29 | #endif -------------------------------------------------------------------------------- /firmware/hardware/spi.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file spi.c Low-level SPI convenience functions 25 | */ 26 | 27 | #include 28 | 29 | #include "spi.h" 30 | 31 | void spi_init(void) 32 | { 33 | SPI_DDR |= (1 << MOSI) | (1 << SCK) | CSADDRMASK; 34 | SPI_DDR &= ~(1 << MISO); 35 | #ifdef MISO_INPUT_PULLUP 36 | MISO_HI; 37 | #endif 38 | SPSR = (1 << SPI2X); 39 | SPCR = (1 << SPE) | (1 << MSTR); 40 | SPI_FAST; 41 | SPI_PHASE0; 42 | AUX2_SEL; 43 | } 44 | 45 | uint8_t spi_exchange(uint8_t data) 46 | { 47 | SPDR = data; 48 | while (!(SPSR & (1 << SPIF))) 49 | ; 50 | return SPDR; 51 | } -------------------------------------------------------------------------------- /firmware/hardware/spi.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file spi.h SPI chip select pin definitions 25 | */ 26 | 27 | #ifndef HARDWARE_SPI_H 28 | #define HARDWARE_SPI_H 29 | 30 | #include 31 | #include 32 | 33 | // SPI pins 34 | #define SPI_DDR DDRB 35 | #define SPI_PORT PORTB 36 | #define SPI_PIN PINB 37 | 38 | #define SCK DDB7 39 | #define MISO DDB6 40 | #define MOSI DDB5 41 | 42 | #define IOX_ADDR 0 43 | #define SD_ADDR 1 44 | #define AUX1_ADDR 2 45 | #define AUX2_ADDR 3 46 | 47 | #define CSADDR 3 48 | #define CSADDRMASK ((1 << CSADDR) | (1 << CSADDR + 1)) 49 | 50 | #define IOX_SEL SPI_PORT = SPI_PORT & ~CSADDRMASK | (IOX_ADDR << CSADDR) 51 | #define SD_SEL SPI_PORT = SPI_PORT & ~CSADDRMASK | (SD_ADDR << CSADDR) 52 | #define AUX1_SEL SPI_PORT = SPI_PORT & ~CSADDRMASK | (AUX1_ADDR << CSADDR) 53 | #define AUX2_SEL SPI_PORT = SPI_PORT & ~CSADDRMASK | (AUX2_ADDR << CSADDR) 54 | 55 | #define SPI_SLOW SPCR |= ((1 << SPR1) | (1 << SPR0)); 56 | #define SPI_FAST SPCR &= ~((1 << SPR1) | (1 << SPR0)) 57 | 58 | #define SPI_PHASE0 SPCR &= ~(1 << CPHA) 59 | #define SPI_PHASE1 SPCR |= (1 << CPHA) 60 | 61 | #define SPI_ENABLE SPCR |= (1 << SPE) 62 | #define SPI_DISABLE SPCR &= ~(1 << SPE) 63 | 64 | #define MISO_LO SPI_PORT &= ~(1 << MISO) 65 | #define MISO_HI SPI_PORT |= (1 << MISO) 66 | #define GET_MISO (SPI_PIN & (1 << MISO)) 67 | #ifdef MISO_INPUT_PULLUP 68 | #define MISO_INPUT \ 69 | SPI_DDR &= ~(1 << MISO); \ 70 | MISO_HI; 71 | #define MISO_OUTPUT \ 72 | SPI_DDR |= (1 << MISO); \ 73 | MISO_LO; 74 | #else 75 | #define MISO_INPUT SPI_DDR &= ~(1 << MISO) 76 | #define MISO_OUTPUT SPI_DDR |= (1 << MISO) 77 | #endif 78 | 79 | #define SCK_LO SPI_PORT &= ~(1 << SCK) 80 | #define SCK_HI SPI_PORT |= (1 << SCK) 81 | 82 | void spi_init(); 83 | uint8_t spi_exchange(uint8_t val); 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /firmware/hardware/sst39sf0x0.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file sst39sf0x0.c Support for SST39SF0x0 flash 25 | */ 26 | 27 | #include 28 | 29 | #include "bus.h" 30 | #include "sst39sf0x0.h" 31 | 32 | // Reference: http://ww1.microchip.com/downloads/en/DeviceDoc/20005022C.pdf 33 | 34 | static void sst_cmd_prefix(void) 35 | { 36 | SET_ADDR(0x5555); 37 | SET_DATA(0xAA); 38 | WR_LO; 39 | WR_HI; 40 | SET_ADDR(0x2AAA); 41 | SET_DATA(0x55); 42 | WR_LO; 43 | WR_HI; 44 | } 45 | 46 | void sst_write(uint32_t addr, const void* buf, uint32_t len) 47 | { 48 | const uint8_t* bytebuf; 49 | if (GET_BUSACK) 50 | return 0; 51 | // first two banks must be physical pages 0 and 1 52 | mem_bank(0, 0); 53 | mem_bank(1, 1); 54 | mem_bank(2, addr >> 14); 55 | DATA_OUTPUT; 56 | MREQ_LO; 57 | for (uint32_t i = 0; i < len; i++) { 58 | // Send byte program command sequence 59 | sst_cmd_prefix(); 60 | SET_ADDR(0x5555); 61 | SET_DATA(0xA0); 62 | WR_LO; 63 | WR_HI; 64 | 65 | // Write byte 66 | if ((addr & 0x3fff) == 0) { 67 | // Load page to write into bank 3 68 | MREQ_HI; 69 | mem_bank(2, addr >> 14); 70 | DATA_OUTPUT; 71 | MREQ_LO; 72 | } 73 | SET_ADDR((addr & 0x3fff) + 0x8000); 74 | SET_DATA(bytebuf[i]); 75 | DATA_OUTPUT; 76 | WR_LO; 77 | WR_HI; 78 | 79 | // Wait for write to finish 80 | _delay_us(20); 81 | addr++; 82 | } 83 | MREQ_HI; 84 | DATA_INPUT; 85 | } 86 | 87 | /** 88 | * Erase the 4KB sector that the address falls within 89 | */ 90 | void sst_erase(uint32_t addr) 91 | { 92 | if (GET_BUSACK) 93 | return 0; 94 | // first two banks must be physical pages 0 and 1 95 | mem_bank(0, 0); 96 | mem_bank(1, 1); 97 | DATA_OUTPUT; 98 | MREQ_LO; 99 | // Send erase command sequence 100 | sst_cmd_prefix(); 101 | SET_ADDR(0x5555); 102 | SET_DATA(0x80); 103 | WR_LO; 104 | WR_HI; 105 | sst_cmd_prefix(); 106 | if (addr > 0x7FFFF) { 107 | // Erase entire chip 108 | SET_ADDR(0x5555); 109 | SET_DATA(0x10); 110 | WR_LO; 111 | WR_HI; 112 | _delay_ms(100); 113 | } else { 114 | // Erase 4KB sector 115 | MREQ_HI; 116 | mem_bank(0, addr >> 14); 117 | DATA_OUTPUT; 118 | MREQ_LO; 119 | SET_ADDR(addr & 0x3000); 120 | SET_DATA(0x30); 121 | DATA_OUTPUT; 122 | WR_LO; 123 | WR_HI; 124 | _delay_ms(100); 125 | } 126 | MREQ_HI; 127 | DATA_INPUT; 128 | } 129 | -------------------------------------------------------------------------------- /firmware/hardware/sst39sf0x0.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file sst39sf0x0.h Support for SST39SF0x0 flash 25 | */ 26 | 27 | #ifndef HARDWARE_SST39SF0X0_H 28 | #define HARDWARE_SST39SF0X0_H 29 | 30 | #include 31 | 32 | void sst_erase(uint32_t addr); 33 | void sst_write(uint32_t addr, const void* buf, uint32_t len); 34 | 35 | #endif -------------------------------------------------------------------------------- /firmware/hardware/term.c: -------------------------------------------------------------------------------- 1 | /* 2 | * "Cooked" terminal mode functions are from libc-avr stdio demo 3 | * ---------------------------------------------------------------------------- 4 | * "THE BEER-WARE LICENSE" (Revision 42): 5 | * wrote this file. As long as you retain this notice you 6 | * can do whatever you want with this stuff. If we meet some day, and you think 7 | * this stuff is worth it, you can buy me a beer in return. Joerg Wunsch 8 | * ---------------------------------------------------------------------------- 9 | */ 10 | 11 | /** 12 | * @file term.c Cooked terminal mode functions 13 | */ 14 | 15 | #include 16 | 17 | #include "uart.h" 18 | 19 | #define LINE_BUFF 80 20 | 21 | /* 22 | * Send character c down the UART Tx, wait until tx holding register 23 | * is empty. 24 | */ 25 | int term_putchar(char c, FILE* stream) 26 | { 27 | 28 | if (c == '\n') 29 | term_putchar('\r', stream); 30 | uart_putc(0, c); 31 | 32 | return 0; 33 | } 34 | 35 | /* 36 | * Receive a character from the UART Rx. 37 | * 38 | * This features a simple line-editor that allows to delete and 39 | * re-edit the characters entered, until either CR or NL is entered. 40 | * Printable characters entered will be echoed using term_putchar(). 41 | * 42 | * Editing characters: 43 | * 44 | * . \b (BS) or \177 (DEL) delete the previous character 45 | * . ^u kills the entire input buffer 46 | * . ^w deletes the previous word 47 | * . ^r sends a CR, and then reprints the buffer 48 | * . \t will be replaced by a single space 49 | * 50 | * All other control characters will be ignored. 51 | * 52 | * The internal line buffer is RX_BUFSIZE (80) characters long, which 53 | * includes the terminating \n (but no terminating \0). If the buffer 54 | * is full (i. e., at RX_BUFSIZE-1 characters in order to keep space for 55 | * the trailing \n), any further input attempts will send a \a to 56 | * term_putchar() (BEL character), although line editing is still 57 | * allowed. 58 | * 59 | * Input errors while talking to the UART will cause an immediate 60 | * return of -1 (error indication). Notably, this will be caused by a 61 | * framing error (e. g. serial line "break" condition), by an input 62 | * overrun, and by a parity error (if parity was enabled and automatic 63 | * parity recognition is supported by hardware). 64 | * 65 | * Successive calls to term_getchar() will be satisfied from the 66 | * internal buffer until that buffer is emptied again. 67 | */ 68 | int term_getchar(FILE* stream) 69 | { 70 | uint8_t c; 71 | char *cp, *cp2; 72 | static char b[LINE_BUFF]; 73 | static char* rxp; 74 | 75 | if (rxp == 0) 76 | for (cp = b;;) { 77 | // block for character 78 | while (uart_testrx(0) == 0) 79 | ; 80 | c = uart_getc(0); 81 | /* behaviour similar to Unix stty ICRNL */ 82 | if (c == '\r') 83 | c = '\n'; 84 | if (c == '\n') { 85 | *cp = c; 86 | term_putchar(c, stream); 87 | rxp = b; 88 | break; 89 | } else if (c == '\t') 90 | c = ' '; 91 | 92 | if ((c >= (uint8_t)' ' && c <= (uint8_t)'\x7e') || c >= (uint8_t)'\xa0') { 93 | if (cp == b + LINE_BUFF - 1) 94 | term_putchar('\a', stream); 95 | else { 96 | *cp++ = c; 97 | term_putchar(c, stream); 98 | } 99 | continue; 100 | } 101 | 102 | switch (c) { 103 | case 'c' & 0x1f: 104 | return -1; 105 | 106 | case '\b': 107 | case '\x7f': 108 | if (cp > b) { 109 | term_putchar('\b', stream); 110 | term_putchar(' ', stream); 111 | term_putchar('\b', stream); 112 | cp--; 113 | } 114 | break; 115 | 116 | case 'r' & 0x1f: 117 | term_putchar('\r', stream); 118 | for (cp2 = b; cp2 < cp; cp2++) 119 | term_putchar(*cp2, stream); 120 | break; 121 | 122 | case 'u' & 0x1f: 123 | while (cp > b) { 124 | term_putchar('\b', stream); 125 | term_putchar(' ', stream); 126 | term_putchar('\b', stream); 127 | cp--; 128 | } 129 | break; 130 | 131 | case 'w' & 0x1f: 132 | while (cp > b && cp[-1] != ' ') { 133 | term_putchar('\b', stream); 134 | term_putchar(' ', stream); 135 | term_putchar('\b', stream); 136 | cp--; 137 | } 138 | break; 139 | } 140 | } 141 | 142 | c = *rxp++; 143 | if (c == '\n') 144 | rxp = 0; 145 | 146 | return c; 147 | } 148 | 149 | FILE term_stream = FDEV_SETUP_STREAM(term_putchar, term_getchar, _FDEV_SETUP_RW); 150 | 151 | void term_init() 152 | { 153 | uart_init(0, UBRR115200); 154 | uart_init(1, UBRR115200); 155 | stderr = stdout = stdin = &term_stream; 156 | } -------------------------------------------------------------------------------- /firmware/hardware/term.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file term.h Cooked terminal mode functions 25 | */ 26 | 27 | #ifndef HARDWARE_TERM_H 28 | #define HARDWARE_TERM_H 29 | #include 30 | int term_getchar(char c, FILE* stream); /* output with cr/lf conversion */ 31 | int term_putchar(FILE* stream); /* line buffered input */ 32 | void term_init(); 33 | #endif -------------------------------------------------------------------------------- /firmware/hardware/timer.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation argvs (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file timer.c AVR timer functions 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "timer.h" 34 | 35 | void config_timer(uint8_t timer, uint8_t prescaler) 36 | { 37 | switch (timer) { 38 | case 0: 39 | TIMSK0 = 0; 40 | TCCR0A = 0; 41 | TCCR0B = prescaler & 7; 42 | break; 43 | case 1: 44 | TIMSK1 = 0; 45 | TCCR1A = 0; 46 | TCCR1B = prescaler & 7; 47 | break; 48 | case 2: 49 | TIMSK2 = 0; 50 | TCCR2A = 0; 51 | TCCR2B = prescaler & 7; 52 | break; 53 | case 3: 54 | TIMSK3 = 0; 55 | TCCR3A = 0; 56 | TCCR3B = prescaler & 7; 57 | break; 58 | } 59 | } 60 | 61 | uint16_t get_tcnt(uint8_t timer) 62 | { 63 | if (timer == 0) { 64 | return TCNT0; 65 | } else if (timer == 2) { 66 | return TCNT2; 67 | } 68 | 69 | uint8_t sreg = SREG; 70 | uint16_t value = 0; 71 | cli(); 72 | if (timer == 1) 73 | value = TCNT1; 74 | else if (timer == 3) 75 | value = TCNT3; 76 | SREG = sreg; 77 | return value; 78 | } 79 | 80 | void set_tcnt(uint8_t timer, uint16_t value) 81 | { 82 | if (timer == 0) { 83 | TCNT0 = value; 84 | return; 85 | } else if (timer == 2) { 86 | TCNT2 = value; 87 | return; 88 | } 89 | 90 | uint8_t sreg = SREG; 91 | cli(); 92 | if (timer == 1) 93 | TCNT1 = value; 94 | else if (timer == 3) 95 | TCNT3 = value; 96 | SREG = sreg; 97 | } -------------------------------------------------------------------------------- /firmware/hardware/timer.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file timer.h AVR timer functions 25 | */ 26 | 27 | #ifndef HARDWARE_TIMER_H 28 | #define HARDWARE_TIMER_H 29 | 30 | /** 31 | * @file util.h Miscellaneous utility functions 32 | */ 33 | 34 | #include 35 | 36 | #define CLKOFF 0 37 | #define CLKDIV1 1 38 | #define CLKDIV8 2 39 | #define CLKDIV64 3 40 | #define CLKDIV256 4 41 | #define CLKDIV1024 5 42 | #define CLKEXTFALL 6 43 | #define CLKEXTRISE 7 44 | 45 | #define TCNT_TO_US(tcnt, freq) (tcnt / (freq / 1000000UL)) 46 | #define TCNT_TO_MS(tcnt, freq) (tcnt / (freq / 1000UL)) 47 | 48 | void config_timer(uint8_t timer, uint8_t prescaler); 49 | uint16_t get_tcnt(uint8_t timer); 50 | void set_tcnt(uint8_t timer, uint16_t value); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /firmware/hardware/tms9918.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file tms9918.h TMS9918-related functions 25 | */ 26 | 27 | #ifndef HARDWARE_TMS9918_H 28 | #define HARDWARE_TMS9918_H 29 | 30 | #include 31 | 32 | #define TMS_TILE 0xc000 33 | #define TMS_BITMAP 0xc002 34 | #define TMS_MULTICOLOR 0xc800 35 | #define TMS_TEXT 0xd000 36 | #define TMS_BLANK 0x8000 37 | 38 | void tms_config(); 39 | void tms_report(); 40 | void tms_read(uint32_t addr, void* buf, uint32_t len); 41 | void tms_write(uint32_t addr, const void* buf, uint32_t len); 42 | void tms_write_P(uint32_t addr, const void* buf, uint32_t len); 43 | void tms_init(uint16_t mode); 44 | void tms_save_status(uint8_t data); 45 | void tms_save_reg(uint8_t data); 46 | uint8_t tms_detect(); 47 | 48 | #endif -------------------------------------------------------------------------------- /firmware/hardware/uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | / UART FIFO implementation is from the FatFS AVR sample code 3 | / Copyright (C) 2016, ChaN, all right reserved. 4 | / 5 | / * This software is a free software and there is NO WARRANTY. 6 | / * No restriction on use. You can use, modify and redistribute it for 7 | / any purpose as you like UNDER YOUR RESPONSIBILITY. 8 | / * Redistributions of source code must retain the above copyright notice. 9 | */ 10 | 11 | /** 12 | * @file uart.c Interrupt-driven buffered UART driver 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "uart.h" 21 | 22 | uint8_t watch_flag; 23 | uint8_t watch_key; 24 | 25 | #define UART_BUFF 64 26 | 27 | typedef struct { 28 | uint16_t wi, ri, ct; 29 | uint8_t buff[UART_BUFF]; 30 | } FIFO; 31 | 32 | static volatile FIFO TxFifo[2], RxFifo[2]; 33 | 34 | volatile uint8_t* const UCSRA[] = { &UCSR0A, &UCSR1A }; 35 | volatile uint8_t* const UCSRB[] = { &UCSR0B, &UCSR1B }; 36 | volatile uint8_t* const UBRRL[] = { &UBRR0L, &UBRR1L }; 37 | volatile uint8_t* const UBRRH[] = { &UBRR0H, &UBRR1H }; 38 | volatile uint8_t* const UDR[] = { &UDR0, &UDR1 }; 39 | 40 | /* Initialize UART */ 41 | 42 | void uart_init(uint8_t uart, uint16_t ubrr) 43 | { 44 | uart &= 1; 45 | 46 | *UCSRB[uart] = 0; 47 | 48 | RxFifo[uart].ct = 0; 49 | RxFifo[uart].ri = 0; 50 | RxFifo[uart].wi = 0; 51 | TxFifo[uart].ct = 0; 52 | TxFifo[uart].ri = 0; 53 | TxFifo[uart].wi = 0; 54 | 55 | *UBRRH[uart] = ubrr >> 8; 56 | *UBRRL[uart] = ubrr & 0xff; 57 | 58 | *UCSRB[uart] = _BV(RXEN0) | _BV(RXCIE0) | _BV(TXEN0); 59 | } 60 | 61 | /* Get a received character */ 62 | 63 | uint16_t uart_testrx(uint8_t uart) 64 | { 65 | uart &= 1; 66 | return RxFifo[uart].ct; 67 | } 68 | 69 | uint8_t uart_getc(uint8_t uart) 70 | { 71 | uint8_t d, i; 72 | uart &= 1; 73 | 74 | // Non-blocking 75 | if (RxFifo[uart].ct == 0) 76 | return 0; 77 | 78 | i = RxFifo[uart].ri; 79 | d = RxFifo[uart].buff[i]; 80 | cli(); 81 | RxFifo[uart].ct--; 82 | sei(); 83 | RxFifo[uart].ri = (i + 1) % sizeof RxFifo[uart].buff; 84 | 85 | return d; 86 | } 87 | 88 | uint8_t uart_peek(uint8_t uart) 89 | { 90 | uint8_t d, i; 91 | uart &= 1; 92 | 93 | // Non-blocking 94 | if (RxFifo[uart].ct == 0) 95 | return 0; 96 | 97 | i = RxFifo[uart].ri; 98 | d = RxFifo[uart].buff[i]; 99 | 100 | return d; 101 | } 102 | 103 | /* Put a character to transmit */ 104 | 105 | uint16_t uart_testtx(uint8_t uart) 106 | { 107 | uart &= 1; 108 | return TxFifo[uart].ct; 109 | } 110 | 111 | /* Flush the transmit buffers */ 112 | void uart_flush(void) 113 | { 114 | while (uart_testtx(0) || uart_testtx(1)) 115 | ; 116 | loop_until_bit_is_set(UCSR0A, UDRE0); 117 | loop_until_bit_is_set(UCSR1A, UDRE1); 118 | } 119 | 120 | void uart_putc(uint8_t uart, uint8_t d) 121 | { 122 | uint8_t i; 123 | uart &= 1; 124 | 125 | while (TxFifo[uart].ct >= sizeof TxFifo[uart].buff) 126 | ; 127 | 128 | i = TxFifo[uart].wi; 129 | TxFifo[uart].buff[i] = d; 130 | cli(); 131 | TxFifo[uart].ct++; 132 | *UCSRB[uart] = _BV(RXEN0) | _BV(RXCIE0) | _BV(TXEN0) | _BV(UDRIE0); 133 | sei(); 134 | TxFifo[uart].wi = (i + 1) % sizeof TxFifo[uart].buff; 135 | #ifdef VDU_ANSI_EMU 136 | tms_putchar(d); 137 | #endif 138 | } 139 | 140 | /* UART RXC interrupt */ 141 | 142 | void uart_rx_vect(uint8_t uart) 143 | { 144 | uint8_t d, n, i; 145 | uart &= 1; 146 | 147 | d = *UDR[uart]; 148 | n = RxFifo[uart].ct; 149 | if (watch_key && d == watch_key) 150 | watch_flag = 1; 151 | if (n < sizeof RxFifo[uart].buff) { 152 | RxFifo[uart].ct = ++n; 153 | i = RxFifo[uart].wi; 154 | RxFifo[uart].buff[i] = d; 155 | RxFifo[uart].wi = (i + 1) % sizeof RxFifo[uart].buff; 156 | } 157 | } 158 | 159 | ISR(USART0_RX_vect) 160 | { 161 | uart_rx_vect(0); 162 | } 163 | 164 | ISR(USART1_RX_vect) 165 | { 166 | uart_rx_vect(1); 167 | } 168 | 169 | /* UART UDRE interrupt */ 170 | 171 | void uart_udre_vect(uint8_t uart) 172 | { 173 | uint8_t n, i; 174 | uart &= 1; 175 | 176 | n = TxFifo[uart].ct; 177 | if (n) { 178 | TxFifo[uart].ct = --n; 179 | i = TxFifo[uart].ri; 180 | *UDR[uart] = TxFifo[uart].buff[i]; 181 | TxFifo[uart].ri = (i + 1) % sizeof TxFifo[uart].buff; 182 | } 183 | if (n == 0) 184 | *UCSRB[uart] = _BV(RXEN0) | _BV(RXCIE0) | _BV(TXEN0); 185 | } 186 | 187 | ISR(USART0_UDRE_vect) 188 | { 189 | uart_udre_vect(0); 190 | } 191 | 192 | ISR(USART1_UDRE_vect) 193 | { 194 | uart_udre_vect(1); 195 | } -------------------------------------------------------------------------------- /firmware/hardware/uart.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file uart.h Interrupt-driven buffered UART driver 25 | */ 26 | #ifndef HARDWARE_UART_H 27 | #define HARDWARE_UART_H 28 | 29 | #include 30 | #include 31 | 32 | #define UBRR115200 10 33 | 34 | extern uint8_t watch_flag; 35 | extern uint8_t watch_key; 36 | 37 | void uart_init(uint8_t uart, uint16_t ubrr); /* Perform UART startup initialization. */ 38 | uint16_t uart_testrx(uint8_t uart); /* Check number of bytes in UART Rx FIFO */ 39 | uint16_t uart_testtx(uint8_t uart); /* Check number of bytes in UART Rx FIFO */ 40 | uint8_t uart_peek(uint8_t uart); 41 | uint8_t uart_getc(uint8_t uart); /* Get a byte from UART Rx FIFO */ 42 | void uart_putc(uint8_t uart, uint8_t d); /* Put a byte into UART Tx FIFO */ 43 | void uart_flush(void); /* flush uart transmit buffers */ 44 | 45 | #endif -------------------------------------------------------------------------------- /firmware/hardware/z80.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file z80.h Z80 run loop and debugger 25 | */ 26 | 27 | #ifndef HARDWARE_Z80_H 28 | #define HARDWARE_Z80_H 29 | 30 | #include 31 | 32 | enum { MEMRD, 33 | MEMWR, 34 | IORD, 35 | IOWR, 36 | OPFETCH, 37 | BUS, 38 | DEBUGCNT }; 39 | 40 | typedef struct { 41 | uint16_t start; 42 | uint16_t end; 43 | } range; 44 | 45 | extern range breaks[]; 46 | extern range watches[]; 47 | extern const char debug_names[]; 48 | 49 | #define INRANGE(ranges, type, addr) ((ranges)[(type)].start <= (addr) && (addr) <= (ranges)[type].end) 50 | #define ENABLED(ranges, type) ((ranges)[(type)].start <= (ranges)[(type)].end) 51 | 52 | void set_haltmask(uint8_t mask); 53 | uint8_t get_haltmask(void); 54 | void z80_page(uint32_t p); 55 | void z80_reset(uint32_t addr); 56 | void z80_run(void); 57 | void z80_debug(uint32_t cycles); 58 | 59 | #endif -------------------------------------------------------------------------------- /firmware/util/disasm.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file disasm.h Z80 disassembler 25 | */ 26 | 27 | #ifndef DISASM_H 28 | #define DISASM_H 29 | 30 | #include 31 | 32 | uint8_t disasm(uint8_t (*input)(), char* output); 33 | void disasm_mem(uint32_t start, uint32_t end); 34 | 35 | #endif -------------------------------------------------------------------------------- /firmware/util/ffwrap.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file ffwrap.h Wrapper functions for FatFS 25 | */ 26 | 27 | #ifndef UTIL_FFWRAP_H 28 | #define UTIL_FFWRAP_H 29 | 30 | #include 31 | #include 32 | 33 | #include "fatfs/ff.h" 34 | 35 | typedef FRESULT (*operation_t)(const TCHAR* path_old, const TCHAR* path_new); 36 | 37 | #define MEM 0 38 | #define TMS 1 39 | #define FLASH 2 40 | 41 | char* ffw_splitpath(const char* path); 42 | FRESULT ffw_open(FIL* fil, FILE* file, const TCHAR* filename, BYTE mode); 43 | FRESULT ffw_close(FIL* fil); 44 | FRESULT ffw_read(FIL* fil, void* buff, UINT btr, UINT* br); 45 | FRESULT ffw_write(FIL* fil, void* buff, UINT btw, UINT* bw); 46 | FRESULT ffw_seek(FIL* fil, FSIZE_t ofs); 47 | FRESULT ffw_delete(const TCHAR* path, const TCHAR* dummy); 48 | FRESULT ffw_rename(const TCHAR* path_old, const TCHAR* path_new); 49 | FRESULT ffw_copy(const TCHAR* path_old, const TCHAR* path_new); 50 | void ffw_iterate(operation_t operation, int count, char* file[], char* dest); 51 | const char* ffw_error(FRESULT fr); 52 | void ffw_init(); 53 | 54 | #endif -------------------------------------------------------------------------------- /firmware/util/ihex.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file ihex.h Functions for loading and saving Intel HEX files 25 | */ 26 | 27 | #ifndef UTIL_IHEX_H 28 | #define UTIL_IHEX_H 29 | 30 | #include 31 | #include 32 | 33 | typedef struct { 34 | uint16_t min; 35 | uint16_t max; 36 | uint16_t total; 37 | uint8_t errors; 38 | } ihex_res; 39 | 40 | int save_ihex(uint32_t start, uint16_t end, FILE* file); /**< Save an intel hex file */ 41 | ihex_res load_ihex(FILE* file); /**< Load an intel hex file */ 42 | 43 | #endif -------------------------------------------------------------------------------- /firmware/util/pgmspace.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file pgmspace.h Compatibility shims for AVR pgmspace.h macros and functions 25 | */ 26 | 27 | #ifndef UTIL_PGMSPACE_H 28 | #define UTIL_PGMSPACE_H 29 | 30 | #ifdef __AVR__ 31 | #include 32 | #else 33 | #define PROGMEM 34 | #define PGM_P const char* 35 | #define PGM_VOID_P const void* 36 | 37 | #define PSTR(s) (s) 38 | #define pgm_read_byte_near(p) (*(p)) 39 | #define pgm_read_word_near(p) (*(p)) 40 | #define pgm_read_dword_near(p) (*(p)) 41 | #define pgm_read_float_near(p) (*(p)) 42 | #define pgm_read_ptr_near(p) (*(p)) 43 | #define pgm_read_byte_far(p) (*(p)) 44 | #define pgm_read_word_far(p) (*(p)) 45 | #define pgm_read_dword_far(p) (*(p)) 46 | #define pgm_read_float_far(p) (*(p)) 47 | #define pgm_read_ptr_far(p) (*(p)) 48 | #define pgm_read_byte(p) (*(p)) 49 | #define pgm_read_word(p) (*(p)) 50 | #define pgm_read_dword(p) (*(p)) 51 | #define pgm_read_float(p) (*(p)) 52 | #define pgm_read_ptr(p) (*(p)) 53 | 54 | #define pgm_get_far_address(var) (var) 55 | 56 | #define memccpy_P memccpy 57 | #define memchr_P memchr 58 | #define memcmp_P memcmp 59 | #define memcmp_PF memcmp 60 | #define memcpy_P memcpy 61 | #define memcpy_PF memcpy 62 | #define memmem_P memmem 63 | #define memrchr_P memrchr 64 | #define strcasecmp_P strcasecmp 65 | #define strcasecmp_PF strcasecmp 66 | #define strcasestr_P strcasestr 67 | #define strcat_P strcat 68 | #define strcat_PF strcat 69 | #define strchr_P strchr 70 | #define strchrnul_P strchrnul 71 | #define strcmp_P strcmp 72 | #define strcmp_PF strcmp 73 | #define strcpy_P strcpy 74 | #define strcpy_PF strcpy 75 | #define strcspn_P strcspn 76 | #define strlcat_P strlcat 77 | #define strlcat_PF strlcat 78 | #define strlcpy_P strlcpy 79 | #define strlcpy_PF strlcpy 80 | #define strlen_P strlen 81 | #define strlen_PF strlen 82 | #define strncasecmp_P strncasecmp 83 | #define strncasecmp_PF strncasecmp 84 | #define strncat_P strncat 85 | #define strncat_PF strncat 86 | #define strncmp_P strncmp 87 | #define strncmp_PF strncmp 88 | #define strncpy_P strncpy 89 | #define strncpy_PF strncpy 90 | #define strnlen_P strnlen 91 | #define strnlen_PF strnlen 92 | #define strpbrk_P strpbrk 93 | #define strrchr_P strrchr 94 | #define strsep_P strsep 95 | #define strspn_P strspn 96 | #define strstr_P strstr 97 | #define strstr_PF strstr 98 | #define strtok_P strtok 99 | #define strtok_rP strtok_r 100 | #endif 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /firmware/util/string.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file string.h string utility functions 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | 31 | #include "string.h" 32 | #include "pgmspace.h" 33 | 34 | /** 35 | * Look up a text string by index from a NULL-separated PROGMEM array 36 | */ 37 | const char* skip_strings(const char* str, uint32_t count) 38 | { 39 | const char* p; 40 | uint32_t i; 41 | for (p = str, i = 0; i < count; i++) 42 | while (pgm_read_byte(p++)) 43 | ; 44 | return p; 45 | } -------------------------------------------------------------------------------- /firmware/util/string.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file string.h string utility functions 25 | */ 26 | 27 | #ifndef UTIL_STRING_H 28 | #define UTIL_STRING_H 29 | 30 | #include 31 | #include 32 | 33 | #include "util/pgmspace.h" 34 | 35 | #define endswith(str, suf) (strcmp_P((str) + strlen(str) - strlen_P(suf), (suf)) == 0) 36 | const char* skip_strings(const char* str, uint32_t count); 37 | 38 | #endif -------------------------------------------------------------------------------- /firmware/util/xmodem.h: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | /** 24 | * @file xmodem.h X and Y modem transmit and receive functions 25 | */ 26 | 27 | #ifndef UTIL_XMODEM_H 28 | #define UTIL_XMODEM_H 29 | 30 | #include "fatfs/ff.h" 31 | 32 | int xm_receive(int argc, char* argv[]); 33 | int xm_transmit(FIL* file); 34 | 35 | #endif -------------------------------------------------------------------------------- /firmware/z80ctrl.c: -------------------------------------------------------------------------------- 1 | /* z80ctrl (https://github.com/jblang/z80ctrl) 2 | * Copyright 2018-2023 J.B. Langston 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #include "util/pgmspace.h" 24 | 25 | #include "cli/cli.h" 26 | 27 | #include "hardware/hardware.h" 28 | #include "hardware/term.h" 29 | 30 | #include "util/ffwrap.h" 31 | 32 | const char z80ctrl_banner[] PROGMEM = 33 | "\n ___ ___ _ _ " 34 | "\n ___( _ ) / _ \\ ___| |_ _ __| |" 35 | "\n|_ / _ \\| | | |/ __| __| '__| |" 36 | "\n / / (_) | |_| | (__| |_| | | |" 37 | "\n/___\\___/ \\___/ \\___|\\__|_| |_|" 38 | "\nby J.B. Langston " 39 | #ifdef GITVERSION 40 | "(" GITVERSION ")" 41 | #endif 42 | "\n"; 43 | 44 | const char z80ctrl_copyright[] PROGMEM = 45 | "\nz80ctrl (https://github.com/jblang/z80ctrl)" 46 | "\nCopyright (c) 2018-2023 J.B. Langston" 47 | "\nMIT License" 48 | "\n" 49 | "\nFatFS (http://elm-chan.org/fsw/ff/)" 50 | "\nCopyright (C) 2022, ChaN, all right reserved" 51 | "\nFatFS License" 52 | "\n" 53 | "\nAltair Disk Emulation (https://github.com/open-simh/simh)" 54 | "\nCopyright (c) 2018-2023, J.B. Langston" 55 | "\nCopyright (c) 2002-2023, Peter Schorn" 56 | "\nCopyright (c) 1997-2010, Charles E. Owen" 57 | "\nMIT License" 58 | "\n" 59 | "\nX/Ymodem Protocol (https://www.menie.org/georges/embedded/#xmodem)" 60 | "\nCopyright 2001-2010 Georges Menie" 61 | "\nCopyright 2018-2023 J.B. Langston" 62 | "\n3-clause BSD License" 63 | "\n" 64 | "\nFull licenses at https://github.com/jblang/z80ctrl/blob/master/LICENSE.md"; 65 | 66 | /** 67 | * z80ctrl entry point 68 | */ 69 | int main(void) 70 | { 71 | term_init(); 72 | printf_P(z80ctrl_banner); 73 | hardware_init(); 74 | ffw_init(); 75 | cli_start(); 76 | } -------------------------------------------------------------------------------- /hardware/classic/z80ctrl_schematic_REV4.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/classic/z80ctrl_schematic_REV4.pdf -------------------------------------------------------------------------------- /hardware/classic/z80ctrl_schematic_REV6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/classic/z80ctrl_schematic_REV6.pdf -------------------------------------------------------------------------------- /hardware/iox/README.md: -------------------------------------------------------------------------------- 1 | [See Wiki](https://github.com/jblang/z80ctrl/wiki/IO-Expander-Board) 2 | -------------------------------------------------------------------------------- /hardware/iox/board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/iox/board.jpg -------------------------------------------------------------------------------- /hardware/iox/z80ctrl-iox.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/iox/z80ctrl-iox.pdf -------------------------------------------------------------------------------- /hardware/nextgen/LUTS.md: -------------------------------------------------------------------------------- 1 | # Lookup Table Definitions 2 | 3 | These are the lookup table definitions for the CCL in the AVR to generate the wait signal. 4 | 5 | ## LUT 0 6 | 7 | | A7 | A6 | IORQ | IOWAIT | 8 | |----|----|------|---------------| 9 | | 0 | 0 | 0 | 0 = 0x00-0x3F | 10 | | 0 | 0 | 1 | 1 | 11 | | 0 | 1 | 0 | 0 = 0x40-0x7F | 12 | | 0 | 1 | 1 | 1 | 13 | | 1 | 0 | 0 | 0 = 0x80-0xBF | 14 | | 1 | 0 | 1 | 1 | 15 | | 1 | 1 | 0 | 0 = 0xC0-0xFF | 16 | | 1 | 1 | 1 | 1 | 17 | 18 | ## LUT 5 19 | 20 | | M1 | WR | IOWAIT | CYCLE | 21 | |----|----|--------|-------------| 22 | | 0 | 0 | 0 | 1 | 23 | | 0 | 0 | 1 | 1 | 24 | | 0 | 1 | 0 | 0 = INTACK | 25 | | 0 | 1 | 1 | 0 = OPFETCH | 26 | | 1 | 0 | 0 | 0 = IOWR | 27 | | 1 | 0 | 1 | 0 = MEMWR | 28 | | 1 | 1 | 0 | 0 = IORD | 29 | | 1 | 1 | 1 | 0 = MEMDR | 30 | 31 | ## LUT 4 32 | 33 | | MREQ | BUSRQ | CYCLE | WAIT | 34 | |------|-------|-------|------------| 35 | | 0 | 0 | 0 | 1 | 36 | | 0 | 0 | 1 | 1 | 37 | | 0 | 1 | 0 | 0 = MWAIT | 38 | | 0 | 1 | 1 | 1 | 39 | | 1 | 0 | 0 | 1 | 40 | | 1 | 0 | 1 | 1 | 41 | | 1 | 1 | 0 | 0 = IOWAIT | 42 | | 1 | 1 | 1 | 1 | 43 | -------------------------------------------------------------------------------- /hardware/nextgen/README.md: -------------------------------------------------------------------------------- 1 | ## z80ctrl NG 2 | 3 | **Important: This design has not yet been tested. Manufacture at your own risk.** 4 | 5 | This is a new design for z80ctrl using the [Microchip AVR128DB64](https://www.microchip.com/en-us/product/avr128db64) microcontroller. 6 | 7 | This next-gen AVR has several advantages over the ATmega1284P used in the original design: 8 | 9 | - It's a 64-pin part with more than enough I/O to interface with the RC2014 bus without an I/O expander. This will allow much faster data transfers since all signals are accessed in parallel rather than serially. 10 | - It has built-in configurable logic used to assert the wait signal on I/O requests without external glue logic. 11 | - It has multi-voltage I/O where one port can run at 3.3V to interface the SD card and other peripherals directly without level shifters. 12 | - It has UPDI single-wire programming and debug interface, so it's possible to actually use the debugger in MPLAB X with a PicKit, without sacrificing too many pins to JTAG. UPDI also allows the part to be programmed directly from the USB to serial converter without a bootloader. 13 | - The TQFP package leaves enough space to incorporate 512KB of RAM with optional bank switching and an RTC on the same board. 14 | - The one disadvantage is that it's a fine-pitched surface mount part, but now that PCB manufacturers offer board assembly service, it is possible to order a board with the surface mount components pre-populated. 15 | 16 | ![Front Render](z80ctrlng-front.png) 17 | 18 | ### RAM 19 | 20 | This board combines features of the original z80ctrl board plus the RAM and RTC from the companion CPU/RAM/RTC board. The CPU remains on a separate board so that z80ctrl can be used with different CPUs. 21 | 22 | The RAM uses the same bank switching scheme as the original board, with two 32K windows into 512K of RAM: 23 | - The active banks for the upper and lower windows are stored in the upper and lower nybbles of a 74HCT574 8-bit register. 24 | - A 74HCT257 multiplexer selects between the two windows based on state of A15. 25 | - Bank switching on this board can be disabled via the slide switch, in which case A15 is connected directly to the SRAM and the output of the 74HCT257 is disabled. 26 | - A16-A18 are connected directly to the bus, so with bank switching disabled, a CPU with more address lines can be used. 27 | - The AVR is connected to A16-A18 directly as well so it can work with all 512KB of RAM in either mode. 28 | - Instead of using a 74HCT138 decoder to bank register, it is controlled directly by the AVR. The AVR will listen on a configurable I/O port for bank changes from the CPU and update the flip-flop as needed. 29 | 30 | The RAM and bank logic chips are still DIPs to keep the retro vibe, and for practical reasons as well: 31 | - It should still be possible to use z80ctrl for SBCs like the SC126, which already has RAM and ROM, by leaving the RAM on the z80ctrl unpopulated. 32 | - Choosing not to populate the RAM and logic chips allows using the z80ctrl as a stand-alone AVR dev board. 33 | - Without these chips populated, all the pins used for A0-A18 and D0-D7, and the Z80 control singals can used as GPIO. 34 | - The passive RCBus backplane can be used to connect non-retro components over the bus. 35 | 36 | ### MicroSD Card 37 | 38 | The board incorporates a MicroSD card holder that the AVR controls over SPI on its 3.3V port. 39 | 40 | ### RTC 41 | 42 | The board includes an RTC for accurate timestamps on the files stored on the SD card: 43 | 44 | - The chip used is an [NXP PCF8563T](https://www.nxp.com/part/PCF8563T) I2C RTC. It is backed up by a CR1216 coin cell. 45 | - The bus can be shared with additional I2C peripherals as long as they do not use the same address as the RTC. 46 | 47 | ### USB Adapter 48 | 49 | An on-board [CH340C](https://cdn.sparkfun.com/assets/9/3/0/2/e/ch3402CDS.pdf) USB-to-Serial adapter allows connecting the z80ctrl directly to a host computer over a MicroUSB cable, without any external USB-to-Serial converter required. 50 | 51 | Using the PROG EN slide switch, it's also possible to enable programming of the chip via UPDI without a bootloader installed using the same USB connection used for serial communication. 52 | 53 | ### UEXT Bus 54 | 55 | - The 3-volt SPI, I2C, and UART signals are exposed on the [UEXT header](https://www.olimex.com/Products/Modules/UEXT/). This allows it to interface with many different 3V peripherals using I2C, UART, or SPI. 56 | - Olimex sells many modules using the UEXT connector. For example, a $4 [ESP8266 module](https://www.olimex.com/Products/IoT/ESP8266/MOD-WIFI-ESP8266/open-source-hardware) will allow the z80ctrl to access the internet over its UART using the [ESP AT](https://github.com/espressif/esp-at) firmware. 57 | - The AVR can expose an parallel interface to peripherals over I/O requests on the RCbus. 58 | 59 | ### Optional RCBus Connections 60 | 61 | - The second 5V UART can be connected or disconnected from RX1 or RX2 and TX1 or TX2 signals on the RCbus using jumpers on the serial header. 62 | - 3.3V SPI, I2C, and UART signals can be optionally exported onto the D8-D15 pins by creating a solder bridge on the corresponding surface mount jumpers. -------------------------------------------------------------------------------- /hardware/nextgen/battery-half.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware/nextgen/brain.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 10 | 85 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /hardware/nextgen/qwiic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 17 | 20 | 23 | 24 | 25 | 34 | 39 | 41 | 44 | 47 | 51 | 52 | 55 | 59 | 60 | 63 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /hardware/nextgen/usb-symbol.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /hardware/nextgen/watch.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware/nextgen/z80ctrlng-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/nextgen/z80ctrlng-back.png -------------------------------------------------------------------------------- /hardware/nextgen/z80ctrlng-front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/nextgen/z80ctrlng-front.png -------------------------------------------------------------------------------- /hardware/nextgen/z80ctrlng.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/nextgen/z80ctrlng.pdf -------------------------------------------------------------------------------- /hardware/z80blinken/activity.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /hardware/z80blinken/lightbulb-fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /hardware/z80blinken/lightbulb-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /hardware/z80blinken/stoplights.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /hardware/z80blinken/z80blinken-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/z80blinken/z80blinken-back.png -------------------------------------------------------------------------------- /hardware/z80blinken/z80blinken-front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/z80blinken/z80blinken-front.png -------------------------------------------------------------------------------- /hardware/z80blinken/z80blinken.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/z80blinken/z80blinken.pdf -------------------------------------------------------------------------------- /hardware/z80ram/board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/z80ram/board.jpg -------------------------------------------------------------------------------- /hardware/z80ram/z80ram_schematic_REV2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jblang/z80ctrl/d1d8e71f24e81b93069692574dc5920f924b91c3/hardware/z80ram/z80ram_schematic_REV2.pdf --------------------------------------------------------------------------------