I/O
Mecrisp Ice supports both an I/O io@ and an I/O write io! command (Forth words).
The words look much like the memory read :duref:@ and memory write !
words but they work a bit differently. For memory reads and writes, the
address really is a 13/16/32/64 bit address. For I/O reads and writes, the 16 bit I/O address
really represents one of 16 ports, each represented by a bit. This I/O model comes from the MSP430 chips.
If you read the verilog, the io_addr wire really should be called the io_port wire.
Here are some example of I/O ports.
Addr Bit READ WRITE
0001 0 PMOD in
0002 1 PMOD out PMOD out
0004 2 PMOD dir PMOD dir
0008 3 misc.out misc.out
0010 4 header 1 in
0020 5 header 1 out header 1 out
0040 6 header 1 dir header 1 dir
0080 7
0100 8 header 2 in
0200 9 header 2 out header 2 out
0400 10 header 2 dir header 2 dir
0800 11
1000 12 UART RX UART TX
2000 13 misc.in
4000 14 ticks set ticks
8000 15
Contents of misc.out and misc.in
Bitmask Bit misc.out misc.in
0001 0 SPI CS UART Ready to Transmit
0002 1 SPI MOSI UART Character received
0004 2 SPI SCK SPI MISO
0008 3 IrDA-TXD IrDA-RXD
0010 4 IrDA-Sleep RTS
0020 5 CTS Random
0040 6 Green LED
0080 7 Red LED
0100 8 Red LED
0200 9 Red LED
0400 10 Red LED
Of course the particular port mappings will depend on your specific board. Please read the README file in the directory for the board that you are using.
It makes sense for the software to be able to set individual bits. But when there is a transmission protocol, such as SPI, this appraoch is based on the Forth software bit banging the outputs. For example, for SPI, even the output clock gets bit banged!
The IN register gives the current electrical state
The contents of the OUT registers determine what level the outputs should be
The DIR register let you switch a pin to be an output by writing an one into
- You can set two registers at once if you OR together their addresses.
255 $440 io! should set all header pins as outputs.
Inputs can be ORed together the same way and give an ORed result.
You can detect short-circuited pins
for example if a pin is set to output and low, but shortened to Vcc,
then the OUT register will read back low, as set by you, but the
IN register will read high for that pin.
Misc.out and misc.in are a mixed back of wires and flags available.
No fear to destroy the IrDA transceiver with too long pulses as it turns off the IR LED itself when IrDA-TXD is high for more than 50 us.
The UART data register is for both incoming and outgoing data, a read from it will clear the “Character received” flag and you should only write to it when “Ready to Transmit” is set.
Ticks contains a 16 bit cycle counter that counts up with 48 MHz and you can set it to any value you wish by writing to it.
Memory location $0002 is an interrupt vector for the ticks counter overflow. You can place an opcode there, perhaps ALU Exit ($608C) or a JMP to a handler. Interrupts can be enabled with eint and disabled with dint.