diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f35e3c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*build* diff --git a/teng/address.hpp b/teng/address.hpp new file mode 100644 index 0000000..311d9f3 --- /dev/null +++ b/teng/address.hpp @@ -0,0 +1,104 @@ +#pragma once + +#include + +class Counter { + public: + const unsigned MAX_NUMBER = 4096; // 12-bit + const int RES = 18; + const int CB = 19; + void reset() { + digitalWrite(CB, HIGH); + digitalWrite(RES, HIGH); + delay(1); + digitalWrite(RES, LOW); + currentValue = 0; + } + /** + * @brief Increment the counter value + * @returns true if overflown to zero + */ + bool increment() { + digitalWrite(CB, LOW); + delay(1); + digitalWrite(CB, HIGH); + currentValue++; + if (currentValue >= MAX_NUMBER) { + currentValue = 0; + return true; + } + return false; + } + unsigned get() { return currentValue; } + private: + unsigned currentValue = 0; +}; + +class AddressState { + public: + AddressState(Counter counter_, int addressPinCount_, const int* addressPins_) + : counter(counter_), addressPinCount(addressPinCount_), addressPins(addressPins_) { + counter.reset(); + } + void set(unsigned targetAddress) { + unsigned targetCounterValue = targetAddress % counter.MAX_NUMBER; + if (counter.get() > targetCounterValue) { + counter.reset(); + + } + for (unsigned i = 0; i < (targetCounterValue - counter.get()); i++) { + counter.increment(); + } + + unsigned pinValues = targetAddress / counter.MAX_NUMBER; + addressPinStateMask = 0; + for (unsigned i = 0; i < addressPinCount; i++) { + unsigned bitSet = pinValues & (1 << i); + if (bitSet > 0) { + digitalWrite(addressPins[i], HIGH); + addressPinStateMask |= (1 << (addressPins[i] - 1)); + } + else { + digitalWrite(addressPins[i], LOW); + + } + } + address = targetAddress; + } + + + void increment() { + if (counter.increment()) { // if overflow + // add 1 to the other pins + for (unsigned i = 0; i < addressPinCount; i++) { + if ((addressPinStateMask & (addressPins[i] - 1)) == 0) { + addressPinStateMask |= (1 << (addressPins[i] - 1)); + digitalWrite(addressPins[i], HIGH); + break; + } + else { + addressPinStateMask ^= (1 << (addressPins[i] - 1)); + digitalWrite(addressPins[i], LOW); + } + } + } + address++; + } + + + unsigned getAddress() { return address; } + unsigned reset() { + counter.reset(); + for (unsigned i = 0; i < addressPinCount; i++) { + digitalWrite(addressPins[i], LOW); + } + } + private: + // if counter is 12 bit and address is 16 bit, this is the value of the top 4 bits + // i-th bit represents i-th pin + unsigned addressPinStateMask = 0; + unsigned address = 0; + Counter counter; + const int* addressPins; + int addressPinCount; +}; diff --git a/teng/control_bytes.hpp b/teng/control_bytes.hpp new file mode 100644 index 0000000..3f24b85 --- /dev/null +++ b/teng/control_bytes.hpp @@ -0,0 +1,7 @@ +#pragma once + + +const char CTRL_WRITE = 1; +const char CTRL_READ = 2; +const char CTRL_256KB = 11; +const char CTRL_2M = 14; diff --git a/teng/eeprom.hpp b/teng/eeprom.hpp new file mode 100644 index 0000000..8be1355 --- /dev/null +++ b/teng/eeprom.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include "address.hpp" + +class EEPROM { + public: + void setup() { + for (unsigned i = 0; i < addressPinCount; i++) { + pinMode(addressPins[i], OUTPUT); + } + for (unsigned i = 0; i < 8; i++) { + pinMode(dataPins[i], INPUT); + } + pinMode(OEb, OUTPUT); + pinMode(WEb, OUTPUT); + } + + /** + * @brief Read the data pins. + */ + uint8_t readDataPins() { + uint8_t b = 0; + for (unsigned i = 0; i < 8; i++) { + b |= (digitalRead(dataPins[i]) << i); + } + return b; + } + + // set start address in via AddressState + void read(uint8_t* data, unsigned dataSize, AddressState& address) { + unsigned i = 0; + for (unsigned i = 0; i < dataSize; i++) { + digitalWrite(OEb, LOW); + delay(t_OUTPUT_DELAY); + data[i] = readDataPins(); + digitalWrite(OEb, HIGH); + delay(t_OUTPUT_FLOAT); + address.increment(); + } + } + + /* private: */ + int OEb; + int WEb; + int addressPins[6]; + unsigned addressPinCount; + int dataPins[8] = { 2, 3, 4, 5, 6, 7, 8, 9 }; + + // in ms + unsigned t_OUTPUT_DELAY = 1; + unsigned t_MIN_WRITE_PULSE_WIDTH = 1; + unsigned t_OUTPUT_FLOAT = 1; + unsigned t_DATA_HOLD_TIME = 0; +}; + +constexpr EEPROM AT28C256 { + .OEb = 17, + .WEb = 16, + .addressPins = {10, 15, 11}, + .addressPinCount = 3 +}; + +constexpr EEPROM SST39SF02A { + .OEb = 17, + .WEb = 16, + .addressPins = {10, 15, 16, 11, 12, 14}, + .addressPinCount = 6 +}; diff --git a/teng/packet.hpp b/teng/packet.hpp new file mode 100644 index 0000000..517c4ae --- /dev/null +++ b/teng/packet.hpp @@ -0,0 +1,23 @@ +#pragma once +#include +#include + +enum PacketType : uint8_t { + MESSAGE, STATUS, COMMAND +}; + +struct Packet { + public: + using size_type = uint16_t; + Packet(PacketType type, size_type size) + : type(type), size(size) { + payload = new uint8_t[size]; + } + ~Packet() { + delete[] payload; + } + uint8_t type; + size_type size; + uint8_t* payload; + +}; diff --git a/teng/sketch.yaml b/teng/sketch.yaml new file mode 100644 index 0000000..081062c --- /dev/null +++ b/teng/sketch.yaml @@ -0,0 +1,6 @@ +profiles: + nanorp: + fqbn: arduino:mbed_nano:nanorp2040connect + platforms: + - platform: arduino:mbed_nano (4.0.2) + libraries: diff --git a/teng/teng.ino b/teng/teng.ino new file mode 100644 index 0000000..6dcccc7 --- /dev/null +++ b/teng/teng.ino @@ -0,0 +1,231 @@ +/* + * EEPROM PROGRAMMER + * 15-18 Address Pins + * 8 Data Pins + * 2 Control Pins (OEb, WEb) + * + * CEb must tied to ground + */ + +#include +#include +/* #include "eeprom.hpp" */ +/* #include "address.hpp" */ + +/* #include "control_bytes.hpp" */ + +constexpr int LED_RED = 2; +constexpr int LED_YELLOW = 3; +constexpr int LED_GREEN = 4; +constexpr int PIN_TENG = 0; + +/* void maskedWrite(uint32_t mask, uint32_t bits) { */ +/* for (uint32_t i = 0; i < 32; i++) { */ +/* if (mask & (1 << i)) { */ +/* digitalWrite(i, bits & (1 << i)); */ +/* } */ +/* } */ +/* } */ +void blinkLED(unsigned n=5, unsigned delay_=200) { + for (unsigned i = 0; i < n; i++) { + digitalWrite(LED_BUILTIN, HIGH); + delay(delay_); + digitalWrite(LED_BUILTIN, LOW); + delay(delay_); + } +} + + +unsigned MAX_DEVIATION = 0; +unsigned BASELINE = 0; +void measureBaseline(unsigned nMeas, unsigned interval=50) { + uint64_t value = 0; + unsigned minVal = 1023; + unsigned maxVal = 0; + for (unsigned i = 0; i < nMeas; i++) { + unsigned reading = analogRead(PIN_TENG); + value += reading; + delay(interval); + if (reading > maxVal) { maxVal = reading; } + if (reading < minVal) { minVal = reading; } + } + BASELINE = value / nMeas; + if (BASELINE - minVal > maxVal - BASELINE) { + MAX_DEVIATION = BASELINE - minVal; + } + else { + MAX_DEVIATION = maxVal - BASELINE; + } +} + +void setup() { + /* pinMode(LED_BUILTIN, OUTPUT); */ + /* digitalWrite(LED_BUILTIN, HIGH); */ + /* delay(200); */ + + Serial.begin(9600); + /* // wait until available */ + while (!Serial); + digitalWrite(LED_BUILTIN, LOW); + delay(200); // empty buffer + while (Serial.read() != -1); + + /* digitalWrite(LED_BUILTIN, HIGH); */ + /* delay(5000); */ + + /* // reset counter */ + /* blinkLED(); */ + + /* uint8_t payload[] = { 1, 2, 3, 4, 5, 69 }; */ + /* uint8_t type = '#'; */ + /* static_assert(sizeof(payload) == 6); */ + /* uint16_t size = sizeof(payload); */ + /* Serial.write(type); */ + /* Serial.write(lowByte(size)); */ + /* Serial.write(highByte(size));u */ + /* Serial.write(payload, size); */ + + /* delay(5000); */ + blinkLED(4); + if (!BLE.begin()) { + Serial.println("starting Bluetooth® Low Energy module failed!"); + } + BLE.setDeviceName("ArduinoTeng"); + BLE.advertise(); + + measureBaseline(100); + digitalWrite(LED_RED, HIGH); + digitalWrite(LED_YELLOW, HIGH); + digitalWrite(LED_GREEN, HIGH); + delay(500); + digitalWrite(LED_RED, LOW); + digitalWrite(LED_YELLOW, LOW); + digitalWrite(LED_GREEN, LOW); +} + + + +/* constexpr int max_val = 1023 / 5 * 3.5; // 1023 max val for 5V */ + +// the loop function runs over and over again forever +void loop() { + int led_red = LOW; + int led_yellow = LOW; + int led_green = LOW; + + int val = analogRead(PIN_TENG); + Serial.print(val, DEC); + val -= BASELINE; + if (val < 0) { val = -val; } + Serial.print("/"); + Serial.println(val, DEC); + + if (val >= MAX_DEVIATION * 1) { + led_green = HIGH; + } + if (val >= MAX_DEVIATION * 2) { + led_yellow = HIGH; + } + if (val >= MAX_DEVIATION * 3) { + led_red = HIGH; + } + digitalWrite(LED_RED, led_red); + digitalWrite(LED_YELLOW, led_yellow); + digitalWrite(LED_GREEN, led_green); + + delay(100); + + + + /* // init address */ + /* const int* addressPins = nullptr; */ + /* unsigned addressPinCount = 0; */ + /* // TODO pass eeprom via serial */ + /* EEPROM eeprom = AT28C256; */ + /* if (mem_size = CTRL_2M) { */ + /* eeprom = SST39SF02A; */ + /* } */ + /* AddressState address(Counter(), eeprom.addressPinCount, eeprom.addressPins); */ + /* const int dataSize = 0x8000; */ + /* uint8_t data[dataSize]; */ + + /* while (true) { */ + + /* } */ + /* if (!Serial.available()) { continue; } */ + + /* // read packet */ + /* uint8_t type = Serial.read(); */ + /* uint16_t size = Serial.read(); // low byte */ + /* size |= (Serial.read() << 8); // high byte */ + /* Packet packet(type, size); */ + /* Serial.readBytes(packet.payload, size); */ + + /* switch(type) { */ + /* case PacketType::WRITE: { */ + /* break; */ + /* } */ + /* case PacketType::READ: { */ + /* break; */ + /* } */ + /* case PacketType::SET_ADDRESS { */ + + /* } */ + /* default: { */ + /* break; */ + /* } */ + /* } */ + + + + + /* byte mem_size = 0; */ + /* byte action = 0; */ + /* byte x = 0; */ + /* while (action == 0 || mem_size == 0) { */ + /* digitalWrite(LED_BUILTIN, HIGH); */ + /* if (Serial.available() <= 0) { */ + /* blinkLED(3); */ + /* } */ + /* else { */ + /* /1* while (Serial.available() > 0) { *1/ */ + /* /1* Serial.write(Serial.read()); *1/ */ + /* /1* } *1/ */ + /* /1* Serial.write('\n'); *1/ */ + + /* Serial.write(static_cast(Serial.available())); */ + /* int cmd = Serial.read(); */ + /* switch (cmd) { */ + /* case CTRL_WRITE: */ + /* case CTRL_READ: */ + /* action = cmd; */ + /* Serial.write('\0'); */ + /* Serial.write('\0'); */ + /* break; */ + /* default: */ + /* mem_size = cmd; */ + /* Serial.write('\1'); */ + /* Serial.write('\1'); */ + /* } */ + /* Serial.write(static_cast(cmd)); */ + /* Serial.write('\2'); */ + /* Serial.write('\2'); */ + /* } */ + /* Serial.write(x); */ + /* Serial.print('\n'); */ + /* x++; */ + /* delay(1000); */ + /* digitalWrite(LED_BUILTIN, LOW); */ + /* delay(1000); */ + /* } */ + + /* if (action == CTRL_WRITE) { */ + /* Serial.println("Write"); */ + /* } */ + /* else if (action == CTRL_READ) { */ + /* Serial.println("Read"); */ + /* eeprom.read(data, dataSize, address); */ + /* Serial.write(data, dataSize); */ + /* blinkLED(10); */ + /* } */ +}