Arduino-FVM comes with only a few Arduino-function words, basically just a few for working with the digital pins. So the test for Forth was going to be: how difficult is it to access other microchip functionality using memory reads and writes? An encouraging first step was to implement SPI TX, using the information in the 328 datasheet.
First I needed some constants for the register addresses and bit numbers:
0x24 constant DDR_SPI 0x3 constant DD_MOSI 0x5 constant DD_SCK 0x2 constant DD_SS 0x4c constant SPCR 0x6 constant SPE 0x4 constant MSTR 0x0 constant SPR0 0x4e constant SPDR 0x4d constant SPSR 0x7 constant SPIF
Next I needed to set up the data direction bits for the MOSI, SCK, and SS pins, as well as set some bits in the SPCR register to control mode and communication frequency:
: setup-master-spi ( -- ) 1 DD_MOSI lshift 1 DD_SCK lshift 1 DD_SS lshift or or DDR_SPI c! 1 SPE lshift 1 MSTR lshift 1 SPR0 lshift or or SPCR c! ;
And here is a function for transmitting a single byte, after dropping the byte on the stack:
: tx-master ( ch -- ) SPDR c! begin SPSR c@ 1 SPIF lshift and until ;
And here is a demo procedure for sending byte 0xA6 repeatedly:
: spi-demo setup-master-spi begin 0xa6 tx-master again ;
Now we can see that byte on the oscilloscope, from MOSI pin 11:
Byte 0xA6 equals 10100110, which you can understand from the signal image if you know that (1) signal low represents “1” and high represents “0”; (2) the X-scale is 2 microseconds, with one bit per microsecond; and (3) the first bit is the one microsecond of low signal just to the left of the Y axis.