# HG changeset patch # User Paul Boddie # Date 1421606924 -3600 # Node ID b3a0a3951381572d96f7afaa0c2a3c24cf6b2289 # Parent 934a843e6b9b564f15552d4ef445cfdfece57d03 Simplified the interfacing, dropping the multiplexer and data latch. Added the initial program for communicating with the flash device. diff -r 934a843e6b9b -r b3a0a3951381 ArduinoAm29F010B.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ArduinoAm29F010B.cpp Sun Jan 18 19:48:44 2015 +0100 @@ -0,0 +1,191 @@ +const int CE = 1, OE = 2, WE = 3, + CS1 = 4, CS2 = 5, + DQ0 = 6, DQ1 = 7, DQ2 = 8, DQ3 = 9, + DQ4 = 10, DQ5 = 11, DQ6 = 12, DQ7 = 13; + +const int BUFSIZE = 8; +char buffer[BUFSIZE]; + +int fromHex(char c) +{ + if ((c >= 48) && (c <= 57)) + return c - 48; + if ((c >= 65) && (c <= 70)) + return c - 65 + 10; + if ((c >= 97) && (c <= 102)) + return c - 97 + 10; + return 0; +} + +void setDataOut() +{ + pinMode(DQ0, OUTPUT); + pinMode(DQ1, OUTPUT); + pinMode(DQ2, OUTPUT); + pinMode(DQ3, OUTPUT); + pinMode(DQ4, OUTPUT); + pinMode(DQ5, OUTPUT); + pinMode(DQ6, OUTPUT); + pinMode(DQ7, OUTPUT); +} + +void setDataIn() +{ + pinMode(DQ0, INPUT); + pinMode(DQ1, INPUT); + pinMode(DQ2, INPUT); + pinMode(DQ3, INPUT); + pinMode(DQ4, INPUT); + pinMode(DQ5, INPUT); + pinMode(DQ6, INPUT); + pinMode(DQ7, INPUT); +} + +int readData() +{ + int i = DQ7; + int data = 0; + + setDataIn(); + delayMicroseconds(1); + + while (1) + { + data += digitalRead(i); + if (i == DQ0) + break; + i--; + data <<= 1; + } + + setDataOut(); + return data; +} + +void writeData(int data) +{ + int i = DQ0; + + while (1) + { + digitalWrite(i, data % 2); + if (i == DQ7) + break; + i++; + data >>= 1; + } +} + +void setAddress(int high, int low) +{ + writeData(high); + delayMicroseconds(1); + digitalWrite(CS2, HIGH); + delayMicroseconds(1); + digitalWrite(CS2, LOW); + writeData(low); + delayMicroseconds(1); + digitalWrite(CS1, HIGH); + delayMicroseconds(1); + digitalWrite(CS1, LOW); +} + +int readOutput(int nread) +{ + int high, low, data; + + if (nread < 5) + return 0; + + high = (fromHex(buffer[1]) << 4) + (fromHex(buffer[2])); + low = (fromHex(buffer[3]) << 4) + (fromHex(buffer[4])); + + setAddress(high, low); + digitalWrite(OE, LOW); + data = readData(); + digitalWrite(OE, HIGH); + + return data; +} + +bool writeOutput(int nread) +{ + int high, low, data; + + if (nread < 7) + return false; + + high = (fromHex(buffer[1]) << 4) + (fromHex(buffer[2])); + low = (fromHex(buffer[3]) << 4) + (fromHex(buffer[4])); + data = (fromHex(buffer[5]) << 4) + (fromHex(buffer[6])); + + setAddress(high, low); + digitalWrite(WE, LOW); + writeData(data); + digitalWrite(WE, HIGH); + + return true; +} + +void setup() +{ + int nread = 0; + + Serial.begin(115200); + pinMode(CE, OUTPUT); + pinMode(OE, OUTPUT); + pinMode(WE, OUTPUT); + pinMode(CS1, OUTPUT); + pinMode(CS2, OUTPUT); + setDataOut(); + + // Initial state for the flash device. + + digitalWrite(CE, HIGH); + digitalWrite(OE, HIGH); + digitalWrite(WE, HIGH); + + // Initial state for the latches. + + digitalWrite(CS1, LOW); + digitalWrite(CS2, LOW); + + // Interface loop. + + Serial.print("? "); + Serial.setTimeout(3600000); // 1 hour + + while (nread = Serial.readBytesUntil('\n', buffer, BUFSIZE)) + { + switch (buffer[0]) + { + case 'R': + Serial.println(readOutput(nread), HEX); + break; + + case 'W': + if (writeOutput(nread)) + Serial.println("Written."); + else + Serial.println("Command?"); + break; + + default: + break; + } + + Serial.print("? "); + } + + Serial.println("Done."); +} + +void loop() +{ +} + +extern "C" void __cxa_pure_virtual(void) { + while(1); +} + +// tabstop=4 expandtab shiftwidth=4 diff -r 934a843e6b9b -r b3a0a3951381 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sun Jan 18 19:48:44 2015 +0100 @@ -0,0 +1,143 @@ +TARGET = $(notdir $(CURDIR)) +INSTALL_DIR = ../arduino-1.0.5 +PORT = /dev/ttyUSB0 +UPLOAD_RATE = 57600 # 19200 +AVRDUDE_PROGRAMMER = stk500v1 +MCU = atmega328p # atmega168 +F_CPU = 16000000 + +EXTRA_SRC = +EXTRA_CXXSRC = +EXTRA_CINCS = +EXTRA_CXXINCS = + + +### Internal definitions. + + +ARDUINO = $(INSTALL_DIR)/hardware/arduino/cores/arduino +VARIANT = $(INSTALL_DIR)/hardware/arduino/variants/standard +SRC = $(ARDUINO)/wiring.c \ + $(ARDUINO)/wiring_analog.c $(ARDUINO)/wiring_digital.c \ + $(ARDUINO)/wiring_pulse.c $(ARDUINO)/wiring_shift.c \ + $(ARDUINO)/WInterrupts.c $(EXTRA_SRC) +CXXSRC = $(ARDUINO)/HardwareSerial.cpp $(ARDUINO)/WMath.cpp \ + $(ARDUINO)/Print.cpp $(ARDUINO)/WString.cpp \ + $(ARDUINO)/Stream.cpp $(EXTRA_CXXSRC) +FORMAT = ihex + +# Name of this Makefile (used for "make depend"). +MAKEFILE = Makefile + +# Debugging format. +# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2. +# AVR (extended) COFF requires stabs, plus an avr-objcopy run. +DEBUG = stabs + +# Place -D or -U options here +CDEFS = -DF_CPU=$(F_CPU) +CXXDEFS = -DF_CPU=$(F_CPU) + +# Place -I options here +CINCS = -I$(ARDUINO) -I$(VARIANT) $(EXTRA_CINCS) +CXXINCS = -I$(ARDUINO) -I$(VARIANT) $(EXTRA_CXXINCS) + +# Compiler flag to set the C Standard level. +# c89 - "ANSI" C +# gnu89 - c89 plus GCC extensions +# c99 - ISO C99 standard (not yet fully implemented) +# gnu99 - c99 plus GCC extensions +CSTANDARD = -std=gnu99 +CDEBUG = -g$(DEBUG) +CWARN = -Wall -Wstrict-prototypes + +OPT = s + +CFLAGS = $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA) +CXXFLAGS = $(CXXDEFS) $(CXXINCS) -O$(OPT) +LDFLAGS = -lm + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) +ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS) + +# Programming support using avrdude. Settings and variables. +AVRDUDE_PORT = $(PORT) +AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex +AVRDUDE_FLAGS = -V -F -C /etc/avrdude.conf \ + -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \ + -b $(UPLOAD_RATE) + +# Program settings +CC = avr-gcc +CXX = avr-g++ +LD = avr-ld +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +AR = avr-ar +SIZE = avr-size +NM = avr-nm +AVRDUDE = avrdude +REMOVE = rm -f +MV = mv -f + +# Define all object files. +OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) + +# Default target. +all: applet_files build sizeafter + +build: elf hex + +applet_files: $(TARGET).cpp + test -d applet || mkdir applet + cat $(ARDUINO)/main.cpp > applet/$(TARGET).cpp + cat $(TARGET).cpp >> applet/$(TARGET).cpp + +elf: applet/$(TARGET).elf +hex: applet/$(TARGET).hex + +# Program the device. +upload: applet/$(TARGET).hex + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) + +# Display size of file. +HEXSIZE = $(SIZE) --target=$(FORMAT) applet/$(TARGET).hex +ELFSIZE = $(SIZE) applet/$(TARGET).elf + +sizebefore: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi + +sizeafter: + @if [ -f applet/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(HEXSIZE); echo; fi + + +### File-specific processing. + + +.SUFFIXES: .elf .hex .eep .lss .sym + +.elf.hex: + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +applet/$(TARGET).elf: applet/$(TARGET).cpp applet/core.a + $(CXX) $(ALL_CXXFLAGS) -o $@ applet/$(TARGET).cpp -L. applet/core.a $(LDFLAGS) + +applet/core.a: $(OBJ) + @for i in $(OBJ); do echo $(AR) rcs applet/core.a $$i; $(AR) rcs applet/core.a $$i; done + +# Compile: create object files from C++ source files. +.cpp.o: + $(CXX) -c $(ALL_CXXFLAGS) $< -o $@ + +# Compile: create object files from C source files. +.c.o: + $(CC) -c $(ALL_CFLAGS) $< -o $@ + +# Target: clean project. +clean: + $(REMOVE) applet/$(TARGET).hex applet/$(TARGET).elf applet/$(TARGET).cpp \ + applet/$(TARGET).map applet/core.a $(OBJ) + +.PHONY: all build elf hex eep lss sym program coff extcoff clean applet_files sizebefore sizeafter diff -r 934a843e6b9b -r b3a0a3951381 README.txt --- a/README.txt Sun Jan 18 02:13:56 2015 +0100 +++ b/README.txt Sun Jan 18 19:48:44 2015 +0100 @@ -74,98 +74,50 @@ channel address and data via 8 common pins to latches, and then employ the remaining pins to control the latches. -Two pins can be used to select the latches: - -Pin A Pin B Latch select ------ ----- ------------ -0 1 1 -1 0 2 -1 1 3 - -Thus, the following logic is required: - -CP (latch 1) = ~A & B -CP (latch 2) = A & ~B -CP (latch 3) = A & B - -Selector (in) 74HC04 (NOT) 74HC08 (AND) Selector (out) -------------- ------------ ------------ -------------- -A 1A (*) - 1Y 1A -B 1B (*) - 1Y LS1 -A 2A (*) -B 2A (*) - 2Y 2B - 2Y LS2 -A 3A (*) -B 3B (*) - 3Y LS3 - -(*) Apply pull-down resistor to 74HC04 1A, 2A, 3A, 3B when driving using switches. +Two pins can be used to select the latches, and when neither latch is +selected, the data pins will be used to read or write data from the flash +memory. As a result, only 13 pins are needed on the Arduino. -Arduino Selector 74HC273 #1 74HC273 #2 74HC273 #3 74HC4052N Am29F010B -------- -------- ---------- ---------- ---------- --------- --------- -1 CE# -2 OE# -3 WE# -4 A -5 B - LS1 CP - LS2 CP - LS3 CP S0 -6 D0 (*) D0 (*) D0 (*) 1Z0 (#1) -7 D1 (*) D1 (*) D1 (*) 2Z0 (#1) -8 D2 (*) D2 (*) D2 (*) 1Z0 (#2) -9 D3 (*) D3 (*) D3 (*) 2Z0 (#2) -10 D4 (*) D4 (*) D4 (*) 1Z0 (#3) -11 D5 (*) D5 (*) D5 (*) 2Z0 (#3) -12 D6 (*) D6 (*) D6 (*) 1Z0 (#4) -13 D7 (*) D7 (*) D7 (*) 2Z0 (#4) - Q0 A0 - Q1 A1 - Q2 A2 - Q3 A3 - Q4 A4 - Q5 A5 - Q6 A6 - Q7 A7 - Q0 A8 - Q1 A9 - Q2 A10 - Q3 A11 - Q4 A12 - Q5 A13 - Q6 A14 - Q7 A15 -GND A16 (not used) - Q0 1Z1 (#1) - Q1 2Z1 (#1) - Q2 1Z1 (#2) - Q3 2Z1 (#2) - Q4 1Z1 (#3) - Q5 2Z1 (#3) - Q6 1Z1 (#4) - Q7 2Z1 (#4) - 1Z (#1) DQ0 - 2Z (#1) DQ1 - 1Z (#2) DQ2 - 2Z (#2) DQ3 - 1Z (#3) DQ4 - 2Z (#3) DQ5 - 1Z (#4) DQ6 - 2Z (#4) DQ7 -5V MR# (**) MR# (**) MR# (**) -GND E# (***) -GND S0 (***) -5V VCC VCC VCC VCC VCC VCC -GND GND GND GND GND GND VSS +Arduino 74HC273 #1 74HC273 #2 Am29F010B +------- ---------- ---------- --------- +1 CE# +2 OE# +3 WE# +4 CP +5 CP +6 D0 (*) D0 (*) DQ0 +7 D1 (*) D1 (*) DQ1 +8 D2 (*) D2 (*) DQ2 +9 D3 (*) D3 (*) DQ3 +10 D4 (*) D4 (*) DQ4 +11 D5 (*) D5 (*) DQ5 +12 D6 (*) D6 (*) DQ6 +13 D7 (*) D7 (*) DQ7 + Q0 A0 + Q1 A1 + Q2 A2 + Q3 A3 + Q4 A4 + Q5 A5 + Q6 A6 + Q7 A7 + Q0 A8 + Q1 A9 + Q2 A10 + Q3 A11 + Q4 A12 + Q5 A13 + Q6 A14 + Q7 A15 +GND A16 (not used) +5V MR# (**) MR# (**) +5V VCC VCC VCC +GND GND GND VSS (*) Apply pull-down resistor to 74HC273 D inputs when driving using switches. (**) Apply pull-up resistor to 74HC273 MR# inputs to preserve state. -(***) Hold 74HC4052N lines low using pull-down resistors. 74HC273 Q outputs may initially be high and should be reset, either driving MR# low or by explicitly latching values onto each device. @@ -173,17 +125,25 @@ Set Address ----------- -Selector A = 0; Selector B = 1; 74HC273 #1 D[7...0] = A[7...0] -Selector A = 1; Selector B = 0; 74HC273 #2 D[7...0] = A[15...8] +74HC273 #1 CP = 1; 74HC273 #2 CP = 0 +74HC273 #1 D[7...0] = A[7...0] +74HC273 #1 CP = 0; 74HC273 #2 CP = 1 +74HC273 #2 D[7...0] = A[15...8] Write Data ---------- Configure pins as D[7...0] -Selector A = 1; Selector B = 1; 74HC273 #3 D[7...0] = D[7...0] +WE# = 0 +74HC273 #1 CP = 0; 74HC273 #2 CP = 0 +74HC273 #3 D[7...0] = D[7...0] +WE# = 1 Read Data --------- Configure pins as Q[7...0] -Selector A = 0; Selector B = 0; Q[7...0] = 74HC273 #0 Q[7...0] +OE# = 0 +74HC273 #1 CP = 1; 74HC273 #2 CP = 0 +Q[7...0] = 74HC273 #0 Q[7...0] +OE# = 1