From 9a10a193c326e5207f661c64523370ff5a9cd534 Mon Sep 17 00:00:00 2001
From: Daniele Verducci su MatissePenguin <daniele.verducci@gmail.com>
Date: Tue, 27 Oct 2020 22:27:39 +0100
Subject: [PATCH] Experimenting with lcd cursor location instructions

---
 README.md                                     |  33 +++-
 .../eeprom_programmer/eeprom_programmer.ino   | 175 ++++++++++++++++++
 assembly/bios/driver_hd44780.asm              |   8 +-
 assembly/bios/main.asm                        |  27 ++-
 4 files changed, 235 insertions(+), 8 deletions(-)
 create mode 100644 arduino/eeprom_programmer/eeprom_programmer/eeprom_programmer.ino

diff --git a/README.md b/README.md
index 6ea9ad5..9c39114 100644
--- a/README.md
+++ b/README.md
@@ -4,15 +4,38 @@ Compilatore c: sdcc (da repo debian)
 Eeprom flash: minipro (da https://gitlab.com/DavidGriffith/minipro/)
 
 # Assembly
-## Compilare assembly:
+## Deploy
+### Compilare assembly:
 `z80asm -i hd44780_lcd_test_procedure.asm -o rom.bin`
-## Portare binario alla dimensione dell eeprom:
+### Portare binario alla dimensione dell eeprom:
 `dd if=/dev/zero of=rom.bin bs=1 count=0 seek=8192`
-## Scrivere su EEPROM:
+### Scrivere su EEPROM:
 `minipro -w rom.bin -p "AT28C64B"`
-## Leggere EEPROM:
+### Leggere EEPROM:
 `minipro -r rom_read.bin -p "AT28C64B"`
+## Istruzioni
+### Dichiarare una variabile:
+Usare EQU per assegnare una posizione di memoria nota (nella RAM) al nome variabile.
+```
+myVar: EQU 0x800F   ; init variable
+ld hl, "A"          ; load value into register
+ld (myVar), hl      ; copy value into variable
+```
+NB: Se il programma si blocca, verificare che la variabile non sia stata dichiarata in una parte non scrivibile della memoria (ROM)
+### Accedere ad una variabile
+Modificarne il valore (nell'esempio: incrementarla di 1)
+```
+ld a, (myVar)
+inc a
+ld (myVar), a
+```
+Passarne il puntatore ad una funzione:
+```
+ld bc, myVar
+call lcd_print
+```
 
 # C
-## Compilare c:
+## Deploy
+### Compilare c:
 `sdcc -mz80 test.c`
diff --git a/arduino/eeprom_programmer/eeprom_programmer/eeprom_programmer.ino b/arduino/eeprom_programmer/eeprom_programmer/eeprom_programmer.ino
new file mode 100644
index 0000000..b33cd6e
--- /dev/null
+++ b/arduino/eeprom_programmer/eeprom_programmer/eeprom_programmer.ino
@@ -0,0 +1,175 @@
+/* ************** EEPROM PROGRAMMER ******************
+
+HARDWARE:
+
+    CORRISPONDENZA PIN EEPROM Atmel AT28C64B  -> ARDUINO MEGA 2560
+    (Compatibile con eeprom fino a 16 bit di address bus. In caso di altre eeprom collegare secondo datasheet)
+    NB: Nel caso della eeprom da 8k, ci sono solo 12 address bus, quindi gli altri 4 pin provenienti dall'Arduino
+    vengono lasciati disconnessi
+
+      Arduino   VCC  11        38   40   44   10   42   12    9    8    7    6    5
+      Eeprom    28   27   26   25   24   23   22   21   20   19   18   17   16   15
+                ____________________________________________________________________
+               |                                                                    |
+               |                                                                    |
+               |_                                                                   |
+               |_)                         Atmel AT28C64B                           |
+               |                                                                    |
+               |                                                                    |
+               |____________________________________________________________________|
+               
+      Eeprom    1    2    3    4    5    6    7    8    9    10   11   12   13   14
+      Arduino       46    36  34   32   30   28   26   24    22    2    3    4   GND
+
+
+
+
+    CORRISPONDENZA FUNZIONALE:
+    
+      Address bus (A0...A15):     22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52
+      
+      Data bus (D0...D7):         2, 3, 4, 5, 6, 7, 8, 9
+  
+      Control bus:
+        /OE     10
+        /WE     11
+        /CE     12
+
+*/
+
+const byte ROM_DATA[] = {0x76, 0x00, 0x00, 0x00, 0x76, 0x00, 0x00};
+
+
+const byte ADDR_BUS[] = {52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22};
+const byte DATA_BUS[] = {9, 8, 7, 6, 5, 4, 3, 2};
+const byte CTRL_BUS_OE = 10;
+const byte CTRL_BUS_WE = 11;
+const byte CTRL_BUS_CE = 12;
+
+void setup() {
+  Serial.begin(57600);
+  for(int pin=0; pin < 16; pin++) {
+    pinMode(ADDR_BUS[pin], OUTPUT);
+  }
+  setDataBusAs(INPUT);
+  pinMode(CTRL_BUS_OE, OUTPUT);
+  pinMode(CTRL_BUS_WE, OUTPUT);
+  pinMode(CTRL_BUS_CE, OUTPUT);
+  digitalWrite(CTRL_BUS_OE, HIGH);  //Active low
+  digitalWrite(CTRL_BUS_WE, HIGH);  //Active low
+  digitalWrite(CTRL_BUS_CE, HIGH);  //Active low
+
+  delay(1000);
+  
+  //readRom(8192);
+  writeRom();
+  verifyRom();
+}
+
+void writeRom() {
+  digitalWrite(CTRL_BUS_OE, HIGH);
+  setDataBusAs(OUTPUT);
+  Serial.print("Starting to write ROM... ");
+  for (int i=0; i<sizeof(ROM_DATA); i++) {
+    writeIntToAddressBus(i);
+    delayMicroseconds(5); // Address hold time (tAH)
+    digitalWrite(CTRL_BUS_CE, LOW);
+    digitalWrite(CTRL_BUS_WE, LOW);
+    writeByteToDataBus(ROM_DATA[i]);
+    delayMicroseconds(5); // Data setup time (tDS)
+    digitalWrite(CTRL_BUS_WE, HIGH);
+    digitalWrite(CTRL_BUS_CE, HIGH);  //Active low
+    delayMicroseconds(5); // Data hold time (tDH)
+  }
+  setDataBusAs(INPUT);
+  Serial.println("Done.");
+}
+
+void verifyRom() {
+  Serial.print("Starting to verify ROM... ");
+  digitalWrite(CTRL_BUS_WE, HIGH);  //Active low
+  char output[50] = {};
+  for (int i=0; i<sizeof(ROM_DATA); i++) {
+    writeIntToAddressBus(i);
+    delayMicroseconds(5);
+    digitalWrite(CTRL_BUS_OE, LOW);  //Active low
+    digitalWrite(CTRL_BUS_CE, LOW);  //Active low
+    delayMicroseconds(5);
+    byte readData = getData();
+    if(readData != ROM_DATA[i]) {
+      sprintf(output, "Error at addr %04x: expected %02x, found %02x", i, ROM_DATA[i], readData);
+      Serial.println(output);
+    }
+    
+    while(true){}
+    digitalWrite(CTRL_BUS_OE, HIGH);  //Active low
+    digitalWrite(CTRL_BUS_CE, HIGH);  //Active low
+    delayMicroseconds(5);
+  }
+  Serial.println("Done.");
+}
+
+void readRom(int bytes) {
+  digitalWrite(CTRL_BUS_WE, HIGH);  //Active low
+  char output[50] = {};
+  for (int i=0; i<bytes; i++) {
+    writeIntToAddressBus(i);
+    delayMicroseconds(5);
+    digitalWrite(CTRL_BUS_OE, LOW);  //Active low
+    digitalWrite(CTRL_BUS_CE, LOW);  //Active low
+    delayMicroseconds(5);
+    byte readData = getData();
+    sprintf(output, "0x%02x ", readData);
+    Serial.print(output);
+    digitalWrite(CTRL_BUS_OE, HIGH);  //Active low
+    digitalWrite(CTRL_BUS_CE, HIGH);  //Active low
+    delayMicroseconds(5);
+  }
+  Serial.println("Done.");
+}
+
+unsigned int getData() {
+  setDataBusAs(INPUT);
+  unsigned int data = 0;
+    for(int pin=0; pin < 8; pin++) {
+      byte b = digitalRead(DATA_BUS[pin]) ? 1 : 0;
+      data = (data << 1) + b;   // Shifta di 1 e aggiunge il bit corrente. Serve per ricostruire il numero da binario
+    }
+    return data;
+}
+
+void setDataBusAs(byte mode){
+  for(int pin=0; pin < 8; pin++) {
+    pinMode(DATA_BUS[pin], mode);
+  }  
+}
+
+void writeByteToDataBus(byte j) {
+  setDataBusAs(OUTPUT);
+  for (int n=0; n<8; n++)
+  {
+    if((0x01&j) < 0x01)
+    {
+      digitalWrite(DATA_BUS[n],LOW);
+    } else {
+      digitalWrite(DATA_BUS[n],HIGH);
+    }
+    j>>=1;
+  }
+}
+
+
+void writeIntToAddressBus(int j) {
+  for (int n=0; n<16; n++)
+  {
+    if((0x01&j) < 0x01)
+    {
+      digitalWrite(ADDR_BUS[n],LOW);
+    } else {
+      digitalWrite(ADDR_BUS[n],HIGH);
+    }
+    j>>=1;
+  }
+}
+
+void loop() {}
diff --git a/assembly/bios/driver_hd44780.asm b/assembly/bios/driver_hd44780.asm
index e60d083..11ad50c 100644
--- a/assembly/bios/driver_hd44780.asm
+++ b/assembly/bios/driver_hd44780.asm
@@ -1,6 +1,9 @@
 ; HD44780 20x4 characters LCD display driver
 ; @author Daniele Verducci
 
+; variables
+;lcd_cur_x: EQU DRV_VAR_SPACE
+;lcd_cur_y: lcd_cur_x + 1
 
 ; functions
 
@@ -36,7 +39,10 @@ lcd_print:
 ; @param B X-axis position (0 to 19)
 ; @param C Y-axis position (0 to 3)
 lcd_locate:
-    ; TODO
+    ld a,0xFE
+    out (LCD_INSTR_REG),a   ; warns the lcd microcontroller that a command is coming
+    ld a,0xA8
+    out (LCD_INSTR_REG),a   ; place cursor to first char of second line
     ret
 
 ; Clears the screen
diff --git a/assembly/bios/main.asm b/assembly/bios/main.asm
index d51b6a6..dbf8a2f 100644
--- a/assembly/bios/main.asm
+++ b/assembly/bios/main.asm
@@ -1,8 +1,11 @@
 ; Pat80 BIOS v0.01
 ; @author: Daniele Verducci
 ; 
-; ROM is at 0x00
-; RAM is at 0x80
+; ROM is at 0x0000
+; RAM is at 0x8000
+;   SYSTEM VAR SPACE: 0x8000 - 0x8FFF (4kb)
+;   DRIVERS VAR SPACE: 0x9000 - 0x9FFF (4kb)
+;   APPLICATION VAR SPACE: 0xA000 - 0xFFFF (24kb)
 ; LCD is at I/O 0x00 and 0x01
 
 
@@ -13,6 +16,9 @@ jp sysinit     ; Startup vector: DO NOT MOVE! Must be the first instruction
 ; SYSTEM CONFIGURATION
 LCD_INSTR_REG: EQU %00000000
 LCD_DATA_REG: EQU %00000001
+SYS_VAR_SPACE: EQU 0x8000
+DRV_VAR_SPACE: EQU 0x9000
+APP_VAR_SPACE: EQU 0xA000
 
 
 ; CONSTANTS
@@ -35,12 +41,29 @@ sysinit:
     ld bc, SYSINIT_GREETING
     call lcd_print      ; write string to screen
 
+    call lcd_locate
+
     ld bc, LIPSUM
     call lcd_print
 
     ;call lcd_cls        ; clear screen
 
+    ;call count
+
     halt
 
 
+; count:
+;     myVar: EQU APP_VAR_SPACE   ; init variable
+;     ld hl, "A"          ; load value into register
+;     ld (myVar), hl      ; copy value into variable
+;     call count_loop
 
+; count_loop:
+;     ld bc, myVar
+;     call lcd_print
+;     ; increm var
+;     ld a, (myVar)
+;     inc a
+;     ld (myVar), a
+;     call count_loop