Mass storage
Forth without mass storage (blocks, screens) is a not complete. A SD-Card interface could be a reasonable solution but this is an overkill for a small Forth system.
EEPROM Serial Communication
Serial Peripheral Interface SPI, MC is the SPI master, the host is the slave.
e.g.
AT25M02
SPI EEPROM 2Mbit (256 KiB, $3),
25LC1024
(128 KiB, $2), or
25LC512
(64 KiB, $1.50). DIL8 Package. 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. If you want more memory there is 16 MiB serial EEPROM
W25Q128J
from WINBOND, please note that is a 3.3 V part!
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.
25LCxxxx Instruction Set
Name |
Format |
Description |
READ |
0000 0011 |
Read data from memory array beginning at selected address |
WRITE |
0000 0010 |
Write data to memory array beginning at selected address |
WREN |
0000 0110 |
Set the write enable latch (enable write operations) |
WRDI |
0000 0100 |
Reset the write enable latch (disable write operations) |
RDSR |
0000 0101 |
Read STATUS register |
WRSR |
0000 0001 |
Write STATUS register |
PE |
0100 0010 |
Page Erase – erase one page in memory array |
SE |
1101 1000 |
Sector Erase – erase one sector in memory array |
CE |
1100 0111 |
Chip Erase – erase all sectors in memory array |
RDID |
1010 1011 |
Release from Deep power-down and read electronic signature |
DPD |
1011 1001 |
Deep Power-Dow |
AT25M02 Instruction Set
Name |
Format |
Description |
READ |
0000 0011 |
Read from Memory Array |
WRITE |
0000 0010 |
Write to Memory Array |
WREN |
0000 0110 |
Set Write Enable Latch (WEL) |
WRDI |
0000 0100 |
Reset Write Enable Latch (WEL) |
RDSR |
0000 0101 |
Read Status Register (SR) |
WRSR |
0000 0001 |
Write Status Register (SR) |
LPWP |
0000 1000 |
Low Power Write Poll |
Serial EEPROM Connected to Centronics Connector (Switches and LEDs)
Sharing the LED and Switch port, you loose two LEDs and one switch. 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.
SPI |
MC (Master) |
25LCxxxx (Slave) |
Interface |
MISO |
J2.1 IN EF4 |
2 SO |
diode e.g. 1N4148 |
MOSI |
J2.11 O7 LED7 |
5 SI |
direct |
CLK |
J2.10 O6 LED6 |
6 SCK |
direct |
CS |
J2.12 O5 LED5 |
1 CS |
direct |
|
P4.3 VDD |
8 VCC |
+5V capacitor 100 nF to GND |
|
" |
3 WP |
+5V |
|
J2.14 WAIT |
7 HOLD |
direct |
|
21 GND |
4 GND |
GND |
Raspberry Pi can emulate SPI EEPROM. On
RaspiElf the switches/LEDs are already connected to Raspi's GPIOs. No need for additional hardware. But I have to write an SPI server for the Raspberry Pi.
Raspi's SPI interfaces can't be used because of conflicting port usage.
- BCM 19 (SPI1 MISO) O5
- BCM 20 (SPI1 MOSI) -
- BCM 21 (SPI1 SCLK) shutdown
- BCM 18 (SPI1 CS0) CLR
- BCM 17 (SPI1 CS1) WAIT
- BCM 9 (SPI0 MISO) IN4
- BCM 10 (SPI0 MOSI) IN3
- BCM 11 (SPI0 SCLK) IN6
- BCM 8 (SPI0 CS0) IN7
- BCM 7 (SPI0 CS1) O0
Read Byte
CS0 EQU 0b1101111
CS1 EQU 0b0010000
CLK0 EQU 0b1011111
CLK1 EQU 0b0100000
DATA0 EQU 0b0111111
DATA1 EQU 0b1000000
; MSB first
READBYTE:
LDI 0
PLO R5
LDI 0xFF
PHI R6
LDI 0xFF - 8
PLO R6
SEX R0
BITLOOP:
OUT4,0b01000000 ; CLK for SPI
OUT4,0b00000000
INC R6
GHI R6 ; set CARRY
SHRC
GLO R5
B4 SETBIT ; branch if bit set
SHL ; bit not set
BR SAVEBIT
SETBIT:
SHLC
SAVEBIT:
PLO R5
GLO R6
BNZ BITLOOP
about 230 cycles for one byte -> 1 ms -> 1
KiB takes about 1 s @ 1.79 MHz
Write Byte
WRITEBYTE:
LDI 0
PHI R6
LDI 8
PLO R6
SEX R0
BITLOOP:
GLO R5 ; get the next bit
SHLC , next bit is in the carry
PLO R5
BDF SETBIT
OUT4,0b01000000 ; CLK for SPI with data bit cleared
OUT4,0b00000000
BR NEXT
SETBIT:
OUT4,0b11000000 ; CLK for SPI with data bit set
OUT4,0b10000000
NEXT:
DEC R6
GLO R6
BNZ BITLOOP
Serial EEPROM patched on MC PCB
SPI 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 N2 (INP4) 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 Byte
; MSB first
LDI 0
PLO R5
LDI 0xFF
PHI R6
LDI 0xFF - 8
PLO R6
SEX R6
BITLOOP:
OUT2 ; CLK for SPI, INC Rx
GHI R6 ; set CARRY
SHRC
GLO R5
B2 SETBIT ; branch if bit set
SHR ; bit not set
BR SAVEBIT
SETBIT:
SHRC
SAVEBIT:
PLO R5
GLO R6
BNZ BITLOOP
about 200 cycles for one byte -> 1 ms -> 1
KiB takes about 1 s
Write Byte
WRITEBYTE:
LDI 0
PHI R6
LDI 8
PLO R6
SEX R0
BITLOOP:
GLO R5 ; get the next bit
SHLC , next bit is in the carry
PLO R5
LSNF
OUT2,0b00000000 ; CLK for SPI with data bit cleared
LSDF
OUT2,0b00000001 ; CLK for SPI with data bit set
DEC R6
GLO R6
BNZ BITLOOP
Kermit/ZModem
What 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 files
block.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