Line: 1 to 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Serial EEPROMs as Mass Storage
Intro
Forth without mass storage (blocks, screens) is a not complete. A SD-Card interface could be a reasonable solution but it is an overkill for a small Forth system. Small serial EEPROMs are for my opinion more suitable.
SPI EEPROMs
SPI EEPROMsThe Serial Peripheral Interface SPI or four-wire serial bus is easy to use. The CDP1802 (MC) is the SPI master, the EEPROM is the slave. There are many different EEPROM types and sizes available e.g. AT25M02 (2Mbit, 256 KiB, $3), 25LC1024 (128 KiB, $2), or 25LC512 (64 KiB, $1.50). All available in DIL8 packages. 64/128/256 KiB seems very small for today's standards where storage is quantified in GiB, but I think it's more than enough for a small Forth system, the size is similar to early floppy disks. If you want more memory there are 16 MiB serial Flash chips e.g. from WINBOND W25Q128J or IS25LP128F, please note they are 3.3 V devices and in SMT!CLK MC ->- host MOSI MC ->- host MISO MC -<- host SS MC ->- host or other peripherals (optional)A high-to-low transition on the CS pin is required to start an operation and a low-to-high transition is required to end an operation. Invalid Opcode: If an invalid opcode is received, no data will be shifted into AT25M02 and the Serial Data Output (SO) pin will remain in a high impedance state until the falling edge of CS is detected again. This will reinitialize the serial communication. While in Hold mode, the SO pin will be in a high impedance state. In addition, both the SI pin and the SCK pin will be ignored. From 1024 Kibit up there are 24 address bits, 8 Kibit to 512 Kibit have 16 address bits. 1, 2, and 4 Kibit have 8 bit address bits. SPI Serial EEPROM Family Data Sheet 25AAXXXX/25LCXXXX. 25LCxxxx Instruction Set
EEPROM Connected to MC's Centronics DB25 Connector (Switches and LEDs)
EEPROM Connected to MC's Centronics DB25 Connector (Switches and LEDs)Sharing the LED and Switch port, you loose three LEDs and one switch or IN. Possible conflict with the bootstrap loader, if there is a read sequence (CS and read pattern 0000 0011). To prevent this, set the EEPROM into HOLD state e.g. with the WAIT signal.
Read ByteLDI 01H PLO R4 ; for the carry PLO R5 ; reset all bits LDI 8 ; counting down 8 times PLO R6 ; bit counter RDBITLOOP GLO R4 ; set CARRY SHR GLO R5 ; get bits BN4 SETBIT ; branch if bit set (EF4 == 0) SHL ; bit not set SKP ; BR SAVEBIT SETBIT SHLC ; set bit SAVEBIT OUT P4 ; CLK on for SPI BYTE 01000000B OUT P4 ; CLK off BYTE 00000000b PLO R5 ; save bits DEC R6 GLO R6 BNZ RDBITLOOPabout 230 cycles for one byte -> 1 ms -> 1 KiB takes about 1 s @ 1.79 MHz Write ByteWRITEBYTE PLO R5 ; save transmit byte LDI 8 ; counter 8 bits PLO R6 WRBITLOOP GLO R5 ; get the next bit SHL ; next bit is in the carry PLO R5 BDF BITSET OUT P4 ; bit cleared BYTE 00000000B OUT P4 ; clock on BYTE 01000000B OUT P4 ; clock off BYTE 00000000B BR WRTEST BITSET OUT P4 ; bit set BYTE 10000000B OUT P4 ; clock on BYTE 11000000B OUT P4 ; clock off BYTE 10000000B WRTEST DEC R6 GLO R6 EEPROM patched on MC PCB
EEPROM patched on MC PCBSPI Mode 0, data is always latched in on the rising edge of SCK and always output on the falling edge of SCK. For CS one output port bis is needed e.g. O7 or N0 (INP1) to start/end operation (A high-to-low transition on the CS pin is required to start an operation and a low-to-high transition is required to end an operation).
Read ByteLDI 01 PLO R4 ; for the carry GHI R0 ; D = 0 PLO R5 ; reset all bits LDI 0 - 8 ; counting up 8 times PLO R6 ; bit counter RDBITLOOP GLO R4 ; set CARRY SHR GLO R5 BN2 SETBIT ; branch if bit set (EF2 == 0) SHL ; bit not set SKP ; BR SAVEBIT SETBIT SHLC SAVEBIT OUT P2 ; CLK for SPI, INC Rx PLO R5 GLO R6 BNZ RDBITLOOPabout 200 cycles for one byte -> 1 ms -> 1 KiB takes about 1 s Write ByteWRITEBYTE PLO R5 ; save transmit byte LDI 8 ; counter 8 bits PLO R6 WRBITLOOP GLO R5 ; get the next bit SHL ; next bit is in the carry PLO R5 LSNF ; skip if bit is 0 OUT P2 BYTE 00000001B ; CLK for SPI with data bit cleared LSDF ; skip if bit is 1 OUT P2 BYTE 00000000B ; CLK for SPI with data bit set DEC R6 GLO R6 BNZ WRBITLOOP EEPROM Connected to Raspberry Pi
EEPROM Connected to Raspberry PiI use a Raspberry Pi Zero (about $20) as an EEPROM programmer.
eeprom2bin (download tool)
bin2eeprom (upload tool)
How to get and build the EEPROM toolsGet the source from the GIT repository (if you have not installed GIT yet, then install it withsudo apt-get install git ), type only the bold text after the $ sign:
pi@cosmac:~/elf $ git clone https://github.com/spyren/RaspiElf Cloning into 'RaspiElf'... pi@cosmac:~/elf $Build (compile) from the sources: pi@cosmac:~/elf $ cd RaspiElf pi@cosmac:~/elf/RaspiElf $ cd eeprom pi@cosmac:~/elf/RaspiElf/eeprom $ make cc -g -c eeprom2bin.c cc -g -o eeprom2bin -lwiringPi eeprom2bin.o cc -g -c bin2eeprom.c cc -g -o bin2eeprom -lwiringPi bin2eeprom.o pi@cosmac:~/elf/RaspiElf/eeprom $Install the binaries into /usr/local/bin
pi@cosmac:~/elf/RaspiElf/eeprom $ sudo make install install -m 557 eeprom2bin bin2eeprom /usr/local/binInstall wiringPi (GPIO Interface library for the Raspberry Pi), details see http://wiringpi.com/download-and-install/ Enable the SPI interface @cosmac:~/elf/RaspiElf/eeprom $ sudo raspi-config
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Changed: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
< < | For RAM only Membership Cards you need some kind of bootstrap loader. To type in a monitor or even BASIC or FORTH is nearly impossible. Serial EEPROMs in DIP8 packages are cheap and easy to get. But you still have to use the front panel to type in the boot loader itself (this is the first-stage boot loader). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
> > | For RAM only Membership Cards you need some kind of bootstrap loader. To toggle in a monitor or even BASIC or FORTH is nearly impossible. Serial EEPROMs in DIP8 packages are cheap and easy to get. But you still have to use the front panel to toggle in the boot loader itself (this is the first-stage boot loader). | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
The "patched on MC PCB" boot loader takes about 25 s for 32 KiB, the DB25 variant takes about 29 s. For the sources see https://github.com/spyren/RaspiElf/tree/master/eeprom .
; TITL "EEPROM Boot Loader for Elf Memebership Card" ; EJCT 60 CPU 1802 NUMBER EQU 0 ; ; Register Definitions: ; R0 EQU 0 R1 EQU 1 R2 EQU 2 R3 EQU 3 R4 EQU 4 R5 EQU 5 R6 EQU 6 R7 EQU 7 R8 EQU 8 R9 EQU 9 R10 EQU 10 R11 EQU 11 R12 EQU 12 R13 EQU 13 R14 EQU 14 R15 EQU 15 ; ; I/O Port Definitions: ; P1 EQU 1 P2 EQU 2 P3 EQU 3 P4 EQU 4 P5 EQU 5 P6 EQU 6 P7 EQU 7 ORG 0H ; R0 program counter ; R1 subroutine pc ; R2 stack pointer ; R5.0 byte (read/write) ; R6.0 bit counter ; R4.0 carry bits ; R7 destination address ; R8 length ; R9 start address START 0000 c0:11000000 LBR BOOTLOADER 0001 00:00000000 0002 03:00000011 BOOTLOADER 0003 f8:11111000 LDI 080H ; set destination address 0004 80:10000000 0005 b7:10110111 PHI R7 0006 b9:10111001 PHI R9 ; start address 0007 f8:11111000 LDI 080H ; set length 0008 80:10000000 0009 b8:10111000 PHI R8 000a 90:10010000 GHI R0 ; D = 00H 000b a7:10100111 PLO R7 ; destination address page boundry 000c a8:10101000 PLO R8 ; length in pages 000d a9:10101001 PLO R9 000e b1:10110001 PHI R1 ; high byte subroutine 000f a2:10100010 PLO R2 ; stack pointer = 0100H 0010 f8:11111000 LDI 01H 0011 01:00000001 0012 b2:10110010 PHI R2 0013 a4:10100100 PLO R4 ; for the carry 0014 f8:11111000 LDI LOW WRITEBYTE ; low byte subroutine 0015 4f:01001111 0016 a1:10100001 PLO R1 0017 61:01100001 OUT P1 ; deactivate CS to start operation 0018 00:00000000 BYTE 00H 0019 e1:11100001 SEX R1 ; for immediate OUT in subroutine 001a f8:11111000 LDI 03H ; EEPROM read command 001b 03:00000011 001c d1:11010001 SEP R1 ; CALL WRITEBYTE 001d 90:10010000 GHI R0 ; address bit 16 to 23 = 0 001e d1:11010001 SEP R1 ; CALL WRITEBYTE, replace by NOP for ; 1 to 512 Kibit EEPROMs 001f 90:10010000 GHI R0 ; address bit 8 to 15 = 0 0020 d1:11010001 SEP R1 ; CALL WRITEBYTE, replace by NOP for ; 1 to 4 Kibit EEPROMs 0021 90:10010000 GHI R0 ; address bit 0 to 7 = 0 0022 d1:11010001 SEP R1 ; CALL WRITEBYTE 0023 e6:11100110 SEX R6 ; Rx for OUT 0024 90:10010000 BLOCKLOOP GHI R0 ; D = 0 0025 a5:10100101 PLO R5 ; reset all bits 0026 f8:11111000 LDI 0 - 8 ; counting up 8 times 0027 f8:11111000 0028 a6:10100110 PLO R6 ; bit counter 0029 84:10000100 RDBITLOOP GLO R4 ; set CARRY 002a f6:11110110 SHR 002b 85:10000101 GLO R5 ; get bits 002c 3d:00111101 BN2 SETBIT ; branch if bit set (EF2 == 0) 002d 30:00110000 002e fe:11111110 SHL ; bit not set 002f 38:00111000 SKP ; BR SAVEBIT 0030 7e:01111110 SETBIT SHLC ; set bit 0031 62:01100010 SAVEBIT OUT P2 ; CLK for SPI, INC Rx 0032 a5:10100101 PLO R5 ; save bits 0033 86:10000110 GLO R6 0034 3a:00111010 BNZ RDBITLOOP 0035 29:00101001 0036 85:10000101 GLO R5 ; get byte 0037 57:01010111 STR R7 ; save byte 0038 17:00010111 INC R7 0039 28:00101000 DEC R8 003a 88:10001000 GLO R8 003b 3a:00111010 BNZ BLOCKLOOP 003c 24:00100100 003d e2:11100010 SEX R2 ; one page finished 003e 98:10011000 GHI R8 003f 52:01010010 STR R2 0040 64:01100100 OUT P4 ; show left pages on LEDs 0041 22:00100010 DEC R2 0042 3a:00111010 BNZ BLOCKLOOP-1 0043 23:00100011 0044 61:01100001 OUT P1 ; deactivate CS to stop operation 0045 e0:11100000 SEX R0 0046 18:00011000 INC R8 ; set R8 to 0001h 0047 99:10011001 GHI R9 ; store start address 0048 58:01011000 STR R8 0049 18:00011000 INC R8 004a 89:10001001 GLO R9 004b 58:01011000 STR R8 004c 30:00110000 BR START 004d 00:00000000 004e d0:11010000 SEP R0 004f a5:10100101 WRITEBYTE PLO R5 ; save transmit byte 0050 f8:11111000 LDI 8 ; counter 8 bits 0051 08:00001000 0052 a6:10100110 PLO R6 0053 85:10000101 WRBITLOOP GLO R5 ; get the next bit 0054 fe:11111110 SHL ; next bit is in the carry 0055 a5:10100101 PLO R5 0056 c7:11000111 LSNF ; skip if bit is 0 0057 62:01100010 OUT P2 0058 01:00000001 BYTE 00000001B ; CLK for SPI with data bit cleared 0059 cf:11001111 LSDF ; skip if bit is 1 005a 62:01100010 OUT P2 005b 00:00000000 BYTE 00000000B ; CLK for SPI with data bit set 005c 26:00100110 DEC R6 005d 86:10000110 GLO R6 005e 3a:00111010 BNZ WRBITLOOP 005f 53:01010011 0060 30:00110000 BR WRITEBYTE-1 0061 4e:01001110 END Kermit/ZModem
Kermit/ZModemWhat about using KERMIT or ZMODEM protocol for the file transfer and use the file system on the host? No need to add additional hardware (SD-card is anyway to modern You could use an old CP/M or even a PDP11 as host. The C-Kermit Local Server mode, e.g. MC can read/write the blocks as filesblock.0 , block.2 , block.255 .
The serial communication is really slow, not only because of the 9600 baud, but you have to wait after each character to give CDP1802 some computation time.
https://github.com/utoh/pygmy-forth/blob/master/extras/kermit/pfkerm.doc
Comments
|