avr: initial commit
[z80.git] / avr / mem.c
diff --git a/avr/mem.c b/avr/mem.c
new file mode 100644 (file)
index 0000000..f662ffe
--- /dev/null
+++ b/avr/mem.c
@@ -0,0 +1,91 @@
+/* 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);
+}
+