--- /dev/null
+/* MEMORY access */
+
+#include <stdio.h>
+
+#include <avr/io.h>
+
+#include "i2c.h"
+#include "bus.h"
+#include "mem.h"
+
+#define MEMTEST_MAX 512
+
+static uint8_t rand(uint16_t *x)
+{
+ *x ^= (*x << 1);
+ *x ^= (*x >> 1);
+ *x ^= (*x << 14);
+ return(*x & 0xFF);
+}
+
+void mem_init(void)
+{
+ int seed;
+ int s = 0;
+
+ mem_start();
+ seed = 0x4D7A;
+ for(uint16_t i = 0; i < MEMTEST_MAX; i++) {
+ if(!(i%512)) printf("|");
+ mem_write(i, rand(&seed));
+ }
+ mem_stop();
+
+ mem_start();
+ seed = 0x4D7A;
+ for(uint16_t i = 0; i < MEMTEST_MAX; i++) {
+ if(!(i%512)) printf("-");
+ uint8_t v1 = mem_read(i);
+ uint8_t v2 = rand(&seed);
+
+ if((v1 & 0xFF) != (v2 & 0xFF)) {
+ if(!s) printf("<0x%x-", i);
+ s = 1;
+ } else {
+ if(s) printf("0x%x>", i-1);
+ s = 0;
+ }
+ }
+ mem_stop();
+}
+
+void mem_start(void)
+{
+ bus_lock(); /* get bus access */
+ MEMPORT |= (1 << MREQ) | (1 << RD) | (1 << WR); /* turn on pullups */
+ MEMDDR |= (1 << MREQ) | (1 << RD) | (1 << WR); /* pins as outputs */
+}
+
+void mem_stop(void)
+{
+ MEMDDR &= ~((1 << MREQ) | (1 << RD) | (1 << WR)); /* pins as inputs */
+ i2c_write(I2C_ALOW, 0xFF); /* tristate PCF8574s */
+ i2c_write(I2C_AHIGH, 0xFF);
+ i2c_write(I2C_DATA, 0xFF);
+}
+
+uint8_t mem_read(uint16_t addr)
+{
+ uint8_t data;
+
+ /* do a read request */
+ i2c_write(I2C_ALOW, (addr & 0x00FF));
+ i2c_write(I2C_AHIGH, (addr & 0xFF00) >> 8);
+ i2c_write(I2C_DATA, 0xFF);
+ MEMPORT &= ~((1 << MREQ) | (1 << RD));
+ data = i2c_read(I2C_DATA);
+ MEMPORT |= (1 << MREQ) | (1 << RD);
+
+ return(data);
+}
+
+void mem_write(uint16_t addr, uint8_t data)
+{
+ /* do a write request */
+ i2c_write(I2C_ALOW, (addr & 0x00FF));
+ i2c_write(I2C_AHIGH, (addr & 0xFF00) >> 8);
+ i2c_write(I2C_DATA, data);
+ MEMPORT &= ~((1 << MREQ) | (1 << WR));
+ MEMPORT |= (1 << MREQ) | (1 << WR);
+}
+