The lack of memory in an Arduino Uno is a bit of a problem if you want to write a uLisp application that logs data to memory; for example, you might want to measure the temperature in your greenhouse every minute over a 24-hour period. The solution is to use one of the low-cost serial EEPROM chips that are widely available. Here's an application showing to interface an I2C Serial EEPROM chip to uLisp.
There's also a 64 Kbyte version called the 24LC512.
Connect the pins to the Arduino as follows:
Pins 1 to 3 on the 24LC256 can be tied to +5V to configure the bottom three bits of the device's I2C address. The default address with all these pins unconnected is #x50.
The memory in the 24LC256 is paged into 64-byte blocks, and you can write up to 64 consecutive bytes within one page in a single operation. If you write over the page boundary the address will wrap around, and you will continue reading or writing from the start of the page.
Here's the function to write a list of up to 64 bytes to the EPROM:
(defun wr (adr lst) (with-i2c (str #x50) (write-byte (ash adr -8) str) (write-byte (logand adr #xFF) str) (dolist (b lst) (write-byte b str))))
First we write the two-byte address we want to write to, high byte first, and then write the bytes from the list. For example, to write ten bytes starting at the EEPROM address #x1240 execute:
> (wr #x1240 '(1 2 3 4 5 6 7 8 9 0)) nil
Here's the function to read n bytes of data:
(defun rd (adr n) (let (lst) (with-i2c (str #x50) (write-byte (ash adr -8) str) (write-byte (logand adr #xFF) str) (restart-i2c str n) (dotimes (i n) (push (read-byte str) lst))) (reverse lst)))
For example, to read back the data we wrote earlier:
> (rd #x1240 10) (1 2 3 4 5 6 7 8 9 0)