From: Manfred Steiner Date: Sat, 28 Sep 2024 11:20:57 +0000 (+0200) Subject: Kostenabrechnung V2a (merge mit w-v2a-2024-08-30/a6c7093) X-Git-Tag: test-software/nano-1284/release/v2024-10-28_141638~2 X-Git-Url: https://git.htl-mechatronik.at/public/?a=commitdiff_plain;h=e7ae81432b6d7e203e7390bf66630504f7d31778;p=nano-x-base.git Kostenabrechnung V2a (merge mit w-v2a-2024-08-30/a6c7093) --- diff --git a/kicad/bom.kicad_sch b/kicad/bom.kicad_sch index acde2cd..fde4b1a 100644 --- a/kicad/bom.kicad_sch +++ b/kicad/bom.kicad_sch @@ -5,7 +5,7 @@ (uuid "b004f1c2-0e7b-40c6-8dd8-0e87ab26e003") (paper "A4") (title_block - (title "Nano-644 Extension Base") + (title "Nano-X-Base") (date "2024-08-30") (rev "V2a") (company "MIT License Copyright (c) 2024 Manfred Steiner") diff --git a/kicad/dist/v2a/README.md b/kicad/dist/v2a/README.md index a62568f..5bc74e5 100644 --- a/kicad/dist/v2a/README.md +++ b/kicad/dist/v2a/README.md @@ -39,16 +39,30 @@ Vorne | Hinten Datum | Kosten | Firma | Beschreibung --------- | --------- | -------- | ------------------------------------------- +10.7.2024 | € 55,35 | Reichelt | 30 Stück Leiterplattenbuchse 4mm (PB4 SW) +15.7.2024 | € 9,90 | ebay | 10 Stück USB-C Kabel +18.7.2024 | € 14,44 | Amazon | Standfüße +25.7.2024 | € 15,12 | ebay | M3-Schrauben +29.7.2024 | € 9,96 | ebay | 40 Stück Gummischeiben 22mm +29.7.2024 | € 60,98 | Reichelt | Diverse Bauteile 28.8.2024 | € 113,23 | JLCP | Bauteile -29.8.2024 | € 2,96 | JLCP | Bauteile Rückzahlung -29.8.2024 | € 3,96 | JLCP | Bauteile Rückzahlung +29.8.2024 | € -2,96 | JLCP | Bauteile Rückzahlung +29.8.2024 | € -3,96 | JLCP | Bauteile Rückzahlung 20.8.2024 | € 761,16 | JLCP | Bestellung 30 Baugruppen + 20 Leerprints V2a - - ---- | € ?,?? | Gesamtkosten - - -Ausständig: Zoll, Steuer + 5.9.2025 | € 21,27 | Reichelt | Distanzhülsen, Jumper +19.9.2924 | € 23,70 | Timetex | 5 Stück Aufbewahrungbehälter +20.9.2924 | € 68,69 | Digikey | Diverse Bauteile +28.9.2024 | € 200,51 | FedEx | Zoll +? | € 25 | | USB-C Kabel +? | € 71,70 | Timetex | 15 Stück Aufbewahrungbehälter +? | € 160,00 | | Teile für volle Bestückung 30 Stück +--------- | **€ 1604,69** | Gesamtkosten + +Gesamtpreis (V1a + V2a): +* V1a: € 1055,45 +* V2a: € 1604,69 +* Gesamt: € 2660,14 +* Stückkosten (33 Stück): € 80,61 ## Sonstiges diff --git a/kicad/dist/v2a/order_W202408301912956_2024-08-30/2015805767680-Produce_DanZhi.SMT_Snapshot.Top.2360571A_Y15.SMT02408301919496.png b/kicad/dist/v2a/order_W202408301912956_2024-08-30/2015805767680-Produce_DanZhi.SMT_Snapshot.Top.2360571A_Y15.SMT02408301919496.png new file mode 100644 index 0000000..dd25c34 Binary files /dev/null and b/kicad/dist/v2a/order_W202408301912956_2024-08-30/2015805767680-Produce_DanZhi.SMT_Snapshot.Top.2360571A_Y15.SMT02408301919496.png differ diff --git a/kicad/dist/v2a/order_W202408301912956_2024-08-30/8544242688-Produce_DanZhi.SMT_Snapshot.Bottom.2360571A_Y15.SMT02408301919496.png b/kicad/dist/v2a/order_W202408301912956_2024-08-30/8544242688-Produce_DanZhi.SMT_Snapshot.Bottom.2360571A_Y15.SMT02408301919496.png new file mode 100644 index 0000000..4b627e1 Binary files /dev/null and b/kicad/dist/v2a/order_W202408301912956_2024-08-30/8544242688-Produce_DanZhi.SMT_Snapshot.Bottom.2360571A_Y15.SMT02408301919496.png differ diff --git a/kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_GERBER-nano-x-base_Y15.zip b/kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_GERBER-nano-x-base_Y15.zip new file mode 100644 index 0000000..3e88c47 Binary files /dev/null and b/kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_GERBER-nano-x-base_Y15.zip differ diff --git a/kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_bom.ods b/kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_bom.ods new file mode 100644 index 0000000..416d9e9 Binary files /dev/null and b/kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_bom.ods differ diff --git a/kicad/i2c.kicad_sch b/kicad/i2c.kicad_sch index db7d028..6fefddf 100644 --- a/kicad/i2c.kicad_sch +++ b/kicad/i2c.kicad_sch @@ -5,7 +5,7 @@ (uuid "48646fd0-0162-46ac-ba69-0bd2efd639ae") (paper "A4") (title_block - (title "Nano-644 Extension Base") + (title "Nano-X-Base") (date "2024-08-30") (rev "V2a") (company "MIT License Copyright (c) 2024 Manfred Steiner") diff --git a/kicad/input-output.kicad_sch b/kicad/input-output.kicad_sch index b7e1a09..e5d7c6e 100644 --- a/kicad/input-output.kicad_sch +++ b/kicad/input-output.kicad_sch @@ -5,7 +5,7 @@ (uuid "54bfc8da-1e4c-47d3-9048-2eca4484dc55") (paper "A4") (title_block - (title "Nano-644 Extension Base") + (title "Nano-X-Base") (date "2024-08-30") (rev "V2a") (company "MIT License Copyright (c) 2024 Manfred Steiner") diff --git a/kicad/lcd-7-seg.kicad_sch b/kicad/lcd-7-seg.kicad_sch index 68f868d..39c6fbc 100644 --- a/kicad/lcd-7-seg.kicad_sch +++ b/kicad/lcd-7-seg.kicad_sch @@ -5,7 +5,7 @@ (uuid "2389d4ee-6559-4a50-b5e1-44cf897b8c6a") (paper "A4") (title_block - (title "Nano-644 Extension Base") + (title "Nano-X-Base") (date "2024-08-30") (rev "V2a") (company "MIT License Copyright (c) 2024 Manfred Steiner") diff --git a/kicad/nano-x-base.kicad_sch b/kicad/nano-x-base.kicad_sch index d42326f..000efad 100644 --- a/kicad/nano-x-base.kicad_sch +++ b/kicad/nano-x-base.kicad_sch @@ -5,7 +5,7 @@ (uuid "931ae915-4e9c-43f8-917c-b67506ca5d91") (paper "A4") (title_block - (title "Nano-644 Extension Base") + (title "Nano-X-Base") (date "2024-08-30") (rev "V2a") (company "MIT License Copyright (c) 2024 Manfred Steiner") diff --git a/software/nano-644/test_2024-07-23/src/main.cpp b/software/nano-644/test_2024-07-23/src/main.cpp index 2971b6e..18ee2d3 100644 --- a/software/nano-644/test_2024-07-23/src/main.cpp +++ b/software/nano-644/test_2024-07-23/src/main.cpp @@ -42,6 +42,8 @@ const char PSTR_LINEFEED[] PROGMEM = "\n"; const char PSTR_ERROR[] PROGMEM = "ERROR"; const char PSTR_Done[] PROGMEM = "Done"; +uint8_t hardwareVersion = 0; + extern "C" { void __cxa_pure_virtual () {} int __cxa_guard_acquire(uint8_t *g) { return 0; } @@ -145,6 +147,43 @@ extern "C" { Cc1101 cc1101Receive(Cc1101::Receive); } +uint8_t detectHardwareVersion () { + ADMUX = (1 << ADLAR) | (1 << REFS0) | 7; // ADC7, VREF=AVCC=3.3V + ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 + ADCSRA |= (1 << ADSC); // start ADC + while (ADCSRA & (1 << ADSC)) {} // wait for result + hardwareVersion = 0; // unknown board version + // printf("Hardware-Version: ADC7H = %d\n", ADCH); + #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) + if (ADCH >= 0xf0) { + hardwareVersion = 1; + } else if (ADCH >= 0xe0) { + hardwareVersion = 2; + } + #endif + #if defined(__AVR_ATmega328P__) + if (ADCH < 0xd8 && ADCH >= 0xc0) { + hardwareVersion = 1; + } else if (ADCH < 0xd8 && ADCH >= 0xb0) { + hardwareVersion = 2; + } + #endif + + if (hardwareVersion == 0) { + #ifdef __AVR_ATmega644P__ + printf("\nInvalid Hardware-Version: ADC7H = %d (ATmega644P, 3.3V)\n", ADCH); + #elif __AVR_ATmega1284P__ + printf("\nInvalid Hardware-Version: ADC7H = %d (ATmega1284P, 3.3V)\n", ADCH); + #elif __AVR_ATmega328P__ + printf("\nInvalid Hardware-Version: ADC7H = %d (ATmega328P, 5V)\n", ADCH); + #endif + } + + ADMUX = 0; + ADCSRA = 0; + return hardwareVersion; +} + void setTimer (uint32_t ms) { ATOMIC_BLOCK(ATOMIC_FORCEON) { timer1ms = ms; @@ -211,11 +250,13 @@ int main () { #ifdef __AVR_ATmega328P__ TestUnit *unit[] = { - &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &lcd, + &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &portExp, &lcd, &i2cMaster, &i2cSlave, &i2cSparkfun }; #endif + detectHardwareVersion(); + while (1) { uint16_t i; char s[4]; @@ -226,6 +267,13 @@ int main () { printf_P(MAIN_CPP_DATE); printf_P(PSTR(" / ")); printf_P(MAIN_CPP_TIME); printf_P(PSTR_DIVIDER); + if (hardwareVersion >= 1 && hardwareVersion <= 2) { + printf_P(PSTR("Hardware: %d"), hardwareVersion); + } else { + printf_P(PSTR("ERROR: Invalid Hardware (%d)"), hardwareVersion); + for(;;); + } + printf_P(PSTR_DIVIDER); printf_P(PSTR_LINEFEED); printf_P(PSTR("Available units:\n\n")); for (i = 0; i < sizeof(unit) / sizeof(unit[0]); i++) { diff --git a/software/nano-644/test_2024-07-23/src/main.hpp b/software/nano-644/test_2024-07-23/src/main.hpp index a7f2ae8..7eeff16 100644 --- a/software/nano-644/test_2024-07-23/src/main.hpp +++ b/software/nano-644/test_2024-07-23/src/main.hpp @@ -12,6 +12,8 @@ extern int wait (uint32_t ms); extern int waitAndReadKey (uint32_t ms); extern uint64_t millis (); +extern uint8_t hardwareVersion; + extern const char PSTR_DIVIDER[]; extern const char PSTR_LINEFEED[]; extern const char PSTR_ERROR[]; diff --git a/software/nano-644/test_2024-07-23/src/units/lcd.cpp b/software/nano-644/test_2024-07-23/src/units/lcd.cpp index 8640690..e779c16 100644 --- a/software/nano-644/test_2024-07-23/src/units/lcd.cpp +++ b/software/nano-644/test_2024-07-23/src/units/lcd.cpp @@ -7,34 +7,38 @@ #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) - // Nano-644 + // Nano-644 / Nano-1284 // --------------------------------------------------------------- - // PA3 ..... E --> LCD Enable (Verbindung via J25 erforderlich) - // PD6 ..... R/W --> Read/Write: Read=1, Write=0 - // PD7 ..... RS --> Register Select: Command=0, Data=1 - // PB7:0 ... Data --> Achtung von 5V LCD nicht lesen! - - - // #define LCD_3V3 - #ifdef LCD_3V3 - #define DATA_PIN PINB - #endif + + // Nano-X-Base V1a V2a Beschreibung + // --------------------------------- ------- + // BL ........... PC0 PC0 Backlight ON(=1) / OFF(=0) + // E ........... PA3 PA3 LCD Enable (Verbindung via J25 erforderlich) + // R/W .......... PD6 PD6 Read/Write: Read=1, Write=0 + // RS ........... PD7 PD7 Register Select: Command=0, Data=1 + // Data ......... PB7:0 PB7:0 Achtung von 5V LCD nicht lesen! void Lcd::init () { - DDRA |= (1 << PA3); + DDRA |= (1 << PA3) | (1 << PA0); DDRB = 0xff; DDRD |= (1 << PD7) | (1 << PD6); initLcd(); - #ifdef LCD_3V3 - printf_P(PSTR("init 3.3V LCD")); - #else - printf_P(PSTR("init 5V LCD")); - #endif + printf_P(PSTR("init LCD (")); + if (status == 1) { + printf_P(PSTR("OK)")); + } else { + printf_P(PSTR("ERROR %d)"), status); + } + setBacklightOn(); } void Lcd::cleanup () { - DDRA &= ~(1 << PA3); + clear(); + PORTA &= ~((1 << PA3) | (1 << PA0)); + DDRA &= ~((1 << PA3) | (1 << PA0)); + PORTB = 0; DDRB = 0; + PORTD &= ~((1 << PD7) | (1 << PD6)); DDRD &= ~((1 << PD7) | (1 << PD6)); } @@ -44,27 +48,65 @@ void Lcd::clrRW () { PORTD &= ~(1 << PD6); } void Lcd::setE () { PORTA |= (1 << PA3); } void Lcd::clrE () { PORTA &= ~(1 << PA3); } + void Lcd::dataDirectionOut () { DDRB = 0xff; } + + void Lcd::dataDirectionIn () { + if (hardwareVersion == 1) { + // read back not allowed (missing level shifter 5V -> 3.3V) + DDRB = 0xff; + } else { + DDRB = 0x00; + } + } + + uint8_t Lcd::getData () { + if (hardwareVersion == 1) { + // read back not allowed (missing level shifter 5V -> 3.3V) + _delay_ms(1); + return 0x00; // bit 8 (busy) = 0 + } else { + return PINB; + } + } void Lcd::setData (uint8_t data) { PORTB = data; } + + void Lcd::setBacklightOn () { + PORTA |= (1 << PA0); + } + + void Lcd::setBacklightOff () { + PORTA &= ~(1 << PA0); + } + #endif #ifdef __AVR_ATmega328P__ // Arduino Nano (5V) // --------------------------------------------------------------- + + // Nano-X-Base V1a V2a Beschreibung + // --------------------------------- ------- + // BL ........... PC0 PC0 Backlight ON(=1) / OFF(=0) + // E ........... PC3 PC3 LCD Enable (Verbindung via J25 erforderlich) + // R/W .......... PD3 PD3 Read/Write: Read=1, Write=0 + // RS ........... PD2 PD2 Register Select: Command=0, Data=1 + // Data0 ........ PD4 PD4 + // Data1 .........PB0 PB0 + // Data2 .........PD7 PD7 + // Data3 .........PD6 PD6 + // Data4 .........PB2 PB2 + // Data5 .........PB3 PB3 + // Data6 .........PB4 PB4 + // Data7 .........PB5 PB5 + // PC3 ..... E --> LCD Enable (Verbindung via J25 erforderlich) // PD3 ..... R/W --> Read/Write: Read=1, Write=0 // PD2 ..... RS --> Register Select: Command=0, Data=1 - // PD4 ..... Data0 - // PB0 ..... Data1 - // PD7 ..... Data2 - // PD6 ..... Data3 - // PB2 ..... Data4 - // PB3 ..... Data5 - // PB4 ..... Data6 - // PB5 ..... Data7 + void Lcd::init () { clrRW(); @@ -72,23 +114,25 @@ clrE(); setData(0); DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0); - DDRC |= (1 << PC3); + DDRC |= (1 << PC3) | (1 << PC0); DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2); initLcd(); - #ifdef LCD_3V3 - printf_P(PSTR("init 3.3V LCD")); - #else - printf_P(PSTR("init 5V LCD")); - #endif + printf_P(PSTR("init LCD (")); + if (status == 1) { + printf_P(PSTR("OK)")); + } else { + printf_P(PSTR("ERROR %d)"), status); + } + setBacklightOn(); } void Lcd::cleanup () { - clrRW(); - clrRS(); - clrE(); - setData(0); + clear(); + PORTB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0)); + PORTC &= ~((1 << PC3) | (1 << PC0)); + PORTD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2)); DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0)); - DDRC &= ~(1 << PC3); + DDRC &= ~((1 << PC3) | (1 << PC0)); DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2)); } @@ -109,6 +153,55 @@ if (data & 0x40) PORTB |= (1 << PB4); else PORTB &= ~((1 << PB4)); if (data & 0x80) PORTB |= (1 << PB5); else PORTB &= ~((1 << PB5)); } + + void Lcd::dataDirectionOut () { + if (!mode4Bit) { + DDRB |= (1 << PB0); + DDRD |= ((1 << PD7) | (1 << PD6) | (1 << PD4)); + } + DDRB |= ((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2)); + } + + void Lcd::dataDirectionIn () { + if (hardwareVersion == 1) { + // read back not allowed (missing level shifter 5V -> 3.3V) + dataDirectionOut(); + } else { + if (!mode4Bit) { + DDRB &= ~(1 << PB0); + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4)); + } + DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2)); + } + } + + uint8_t Lcd::getData () { + if (hardwareVersion == 1) { + // read back not allowed (missing level shifter 5V -> 3.3V) + _delay_ms(1); + return 0x00; // bit 8 (busy) = 0 + } else { + uint8_t b = 0; + b |= ((PIND & (1 << PD4)) != 0) << 0; + b |= ((PINB & (1 << PB0)) != 0) << 1; + b |= ((PIND & (1 << PD7)) != 0) << 2; + b |= ((PIND & (1 << PD6)) != 0) << 3; + b |= ((PINB & (1 << PB2)) != 0) << 4; + b |= ((PINB & (1 << PB3)) != 0) << 5; + b |= ((PINB & (1 << PB4)) != 0) << 6; + b |= ((PINB & (1 << PB5)) != 0) << 7; + return b; + } + } + + void Lcd::setBacklightOn () { + PORTC |= (1 << PC0); + } + + void Lcd::setBacklightOff () { + PORTC &= ~(1 << PC0); + } + #endif // Befehle für das Display @@ -121,25 +214,35 @@ #define BLINK_ON 0b00001111 // Cursor Blink #define BLINK_OFF 0b00001110 // Cursor No Blink +#define LCD_PULSE_LENGTH 15 +#define LCD_CMD_DISPLAY_CLEAR 0x01 // Display clear +#define LCD_CMD_CURSOR_HOME 0x02 // Move cursor digit 1 +#define LCD_CMD_SET_ENTRY_MODE 0x04 // Entry Mode Set +#define LCD_CMD_DISPLAY_ON_OFF 0x08 // Display on/off +#define LCD_CMD_SHIFT 0x10 // Display shift +#define LCD_CMD_SET_MODE4BIT 0x20 // 4/8 Bits... +#define LCD_CMD_SET_CGRAM_ADDR 0x40 // Character Generator ROM +#define LCD_CMD_SET_DDRAM_ADDR 0x80 // Display Data RAM +#define LCD_BUSY_FLAG 0x80 + + + int8_t Lcd::run (uint8_t subtest) { if (subtest == 0) { for (uint8_t i = 0; i < 20 * 4; i++) { char c = (char)(i + 32); if (i % 20 == 0) { - setCursor(i / 20 + 1, 1); + setCursor(i / 20, 0); } - writeData(c); - while (isBusy()) {}; + putChar(c); + waitOnReady(); + } + printf_P(PSTR("LCD ")); + if (status == 1) { + printf_P(PSTR("OK")); + } else { + printf_P(PSTR("ERROR(%d)"), status); } - // setCursor(1, 1); - // writeString(" 1234567890<>,;.:-_#+"); - // setCursor(2, 1); - // writeString("abcdefghijklmnopqrst"); - // setCursor(3, 1); - // writeString("uvwxyzABCDEFGHIJKLMN"); - // setCursor(4, 1); - // writeString("OPQRSTUVWXYZ "); - printf_P(PSTR("LCD beschrieben")); while (wait(1) == EOF) { } @@ -151,114 +254,190 @@ int8_t Lcd::run (uint8_t subtest) { return 0; } + void Lcd::initLcd () { + + setData(0x00); + dataDirectionOut(); + _delay_ms(16); // min 15ms warten für Reset des Displays + status = 0; + for (uint8_t i = 0; i < 4; i++) { + if (mode4Bit) { + setRegister(LCD_CMD_SET_MODE4BIT | 0x08); // 4 Bit, 2/4 Zeilen, 5x7 + } else { + setRegister(0x08); // 8 Bit, 2 Zeilen, 5x7 + } + if (i == 0) { + _delay_ms(5); + } else { + _delay_us(100); + } + } + + setRegister(LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off + if (!isReady(50)) { + status = -1; + return; + } + + setRegister(LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on, cursor off + if (!isReady(50)) { + status = -3; + return; + } + + setRegister(LCD_CMD_DISPLAY_CLEAR); + if (!isReady(1200)) { + status = -4; + return; + } - setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display - clrRW(); // write - clrRS(); // command - setE(); // E = 1 (transfer start) - _delay_us(10); // min. 10us - clrE(); // E = 0 (transfer end) - _delay_ms(5); // min. 4.1ms - - setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display - clrRW(); // write - clrRS(); // command - setE(); // E = 1 (transfer start) - _delay_us(10); // min. 10us - clrE(); // E = 0 (transfer end) - _delay_us(100); // min. 100us - - setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display - clrRW(); // write - clrRS(); // command - setE(); // E = 1 (transfer start) - _delay_us(10); // min. 10us - clrE(); // E = 0 (transfer end) - _delay_us(100); // min. 100us - - writeCommand(DISP_OFF); // Display aus - while(isBusy()) {}; - writeCommand(DISP_ON); // Display ein - while(isBusy()) {}; - writeCommand( BLINK_OFF & CURSOR_OFF); // Blink aus und Cursor aus - while(isBusy()) {}; - writeCommand(DISP_CLEAR);// Clear display - while(isBusy()) {}; + status = 1; } -uint8_t Lcd::isBusy () { - #ifdef LCD_3V3 - // DIR_DATA_PORT = 0; - // SET_RW_PIN; // read - // CLR_RS_PIN; // command - // SET_E_PIN; // E = 1 (transfer start) - // _delay_us(10); - // uint8_t busy = DATA_PIN & 0x80; // read bit 7 (busy bit) - // CLR_E_PIN; // E = 0 (transfer end) - // CLR_RW_PIN; - // DIR_DATA_PORT = 0xff; - // return busy != 0; - _delay_us(200); - #else - _delay_us(200); - #endif - return 0; +void Lcd::setRegister (uint8_t cmd) { + clrRW(); + clrRS(); + writeData(cmd); } -void Lcd::writeCommand (uint8_t cmd) { - setData(cmd); - clrRW(); // write - clrRS(); // command - setE(); // E = 1 (transfer start) - _delay_us(10); // min. 10us - clrE(); // E = 0 (transfer end) - setData(0); +void Lcd::writeData (uint8_t data) { + clrE(); + dataDirectionOut(); + if (mode4Bit) { + setData(data & 0xf0); // send High-Nibble + setE(); + _delay_us(LCD_PULSE_LENGTH); + clrE(); + _delay_us(1); + setData(data << 4); // send Low-Nibble + } else { + setData(data); // send data byte + } + setE(); + _delay_us(LCD_PULSE_LENGTH); + clrE(); + _delay_us(1); } -void Lcd::setDDRamAddr (uint8_t address) { - setData(address | 0x80); - clrRW(); // write - clrRS(); // command - setE(); // E = 1 (transfer start) - _delay_us(10); // min. 10us - clrE(); // E = 0 (transfer end) - _delay_us(10); // min. 10us - setData(0); +void Lcd::setDRAddr (uint8_t address) { + waitOnReady(); + setRegister(LCD_CMD_SET_DDRAM_ADDR | address); + waitOnReady(); } -void Lcd::writeString (const char *s) { - while (*s) { - writeData(*s++); - while (isBusy()) {}; +void Lcd::waitOnReady () { + if (isReady(50) == 0) { + status = -6; } } -void Lcd::writeData (uint8_t data) { - setData(data); - setRS(); // data - clrRW(); // write - setE(); // E = 1 (transfer start) - _delay_us(10); // min. 10us - clrE(); // E = 0 (transfer end) - _delay_us(10); // min. 10us - clrRS(); - setData(0); +bool Lcd::isReady (uint16_t us) { + if (status < 0) { + return false; + } + if (hardwareVersion == 1) { + // read back not allowed (missing level shifter) + _delay_ms(1); + return true; + } + + uint8_t busy; + dataDirectionIn(); + setData(0xff); // enable internal pull up + + do { + uint8_t data = 0; + setRW(); + clrRS(); + + _delay_us(1); + setE(); + _delay_us(LCD_PULSE_LENGTH); + data = getData() & 0xf0; // High Nibble + clrE(); + + _delay_us(1); + setE(); + _delay_us(LCD_PULSE_LENGTH); + data |= getData() >> 4; // Low Nibble + + clrE(); + _delay_us(1); + clrRW(); + + busy = data & LCD_BUSY_FLAG; + us = (us >= 11) ? us - 11 : 0; + } while (us > 0 && busy); + + if (status == 1 && busy) { + status = -5; + } + + setData(0x00); + dataDirectionOut(); + + return busy == 0; +} + + +void Lcd::setDisplayOn () { + if (status != 1) { + return; + } + waitOnReady(); + setRegister(LCD_CMD_DISPLAY_ON_OFF | 0x04); // display on + waitOnReady(); +} + +void Lcd::setDisplayOff () { + if (status != 1) { + return; + } + waitOnReady(); + setRegister(LCD_CMD_DISPLAY_ON_OFF); // display off + waitOnReady(); } -void Lcd::setCursor (uint8_t row, uint8_t column) { +void Lcd::clear () { + if (status != 1) { + return; + } + waitOnReady(); + setRegister(LCD_CMD_DISPLAY_CLEAR); + waitOnReady(); +} + +void Lcd::setCursor (uint8_t rowIndex, uint8_t columnIndex) { + if (status != 1 || columnIndex >= 20) { + return; + } uint8_t b; - if (column > 20) { - return; - } - switch (row) { - case 1: b = 0x00 + column - 1; break; - case 2: b = 0x40 + column - 1; break; - case 3: b = 0x14 + column - 1; break; - case 4: b = 0x54 + column - 1; break; - default: return; - } - setDDRamAddr(b); - while (isBusy()) {}; + switch (rowIndex) { + case 0: b = 0x00 + columnIndex; break; + case 1: b = 0x40 + columnIndex; break; + case 2: b = 0x14 + columnIndex; break; + case 3: b = 0x54 + columnIndex; break; + default: return; + } + setDRAddr(b); + waitOnReady(); } + +void Lcd::putChar (char c) { + if (status != 1) { + return; + } + clrRW(); + setRS(); + writeData(c); + clrRS(); + waitOnReady(); +} + +void Lcd::puts (const char * str) { + while (*str && status == 1) { + putChar(*str++); + } +} \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/lcd.hpp b/software/nano-644/test_2024-07-23/src/units/lcd.hpp index 3eb4456..47a30cc 100644 --- a/software/nano-644/test_2024-07-23/src/units/lcd.hpp +++ b/software/nano-644/test_2024-07-23/src/units/lcd.hpp @@ -7,27 +7,41 @@ class Lcd : public TestUnit { public: - Lcd () {}; + Lcd () { mode4Bit = hardwareVersion == 1 ? false : true; status = 0; }; virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Lcd"); } private: + bool mode4Bit; + int8_t status; + void initLcd (); - uint8_t isBusy (); - void writeCommand (uint8_t); - void setDDRamAddr (uint8_t); - void writeString (const char *s); - void writeData (uint8_t); - void setCursor (uint8_t row, uint8_t column); + void setRegister (uint8_t cmd); + void setDRAddr (uint8_t address); + void writeData (uint8_t data); + void waitOnReady (); + bool isReady (uint16_t us); + void setDisplayOn (); + void setDisplayOff (); + void clear (); + void setCursor (uint8_t rowIndex, uint8_t columnIndex); + void putChar (char c); + void puts (const char * str); + void setRS (); void clrRS (); void setRW (); void clrRW (); void setE (); void clrE (); + uint8_t getData (); void setData (uint8_t data); + void dataDirectionIn (); + void dataDirectionOut (); + void setBacklightOn (); + void setBacklightOff (); }; diff --git a/software/nano-644/test_2024-07-23/src/units/led.cpp b/software/nano-644/test_2024-07-23/src/units/led.cpp index 5a56665..e908c21 100644 --- a/software/nano-644/test_2024-07-23/src/units/led.cpp +++ b/software/nano-644/test_2024-07-23/src/units/led.cpp @@ -7,12 +7,15 @@ #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) - // Nano-644 + // Nano-644 / Nano 1284 // --------------------------------------------------------------- - // PD4 ..... Red - // PD5 ..... Orange/Yellow - // PD6 ..... Green - // PD7 ..... Blue + + // Nano-X-Base V1a V2a + // ----------------------- + // Red PD4 PD7 + // Orange/Yellow PD5 PD6 + // Green PD6 PD5 + // Blue PD7 PD4 void Led::init () { PORTD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4)); @@ -57,10 +60,13 @@ // Arduino-Nano-5V // --------------------------------------------------------------- - // PD5 ..... Red - // PB1 ..... Orange/Yellow - // PD3 ..... Green - // PD2 ..... Blue + + // Nano-X-Base V1a V2a + // ----------------------- + // Red PD5 PD2 + // Orange/Yellow PB1 PD3 + // Green PD3 PB1 + // Blue PD2 PD5 void Led::init () { PORTD &= ~((1 << PD5) | (1 << PD3) | (1 << PD2)); diff --git a/software/nano-644/test_2024-07-23/src/units/motor.cpp b/software/nano-644/test_2024-07-23/src/units/motor.cpp index 4457c1a..83f0c3b 100644 --- a/software/nano-644/test_2024-07-23/src/units/motor.cpp +++ b/software/nano-644/test_2024-07-23/src/units/motor.cpp @@ -18,6 +18,7 @@ #define ADC0K 64 void Motor::init () { + DDRD |= (1 << PD7); // sensor signal toggle on PD7 (LED D4 red) ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00); // Fast PWM on OC0A @@ -30,6 +31,7 @@ } void Motor::cleanup () { + DDRD &= ~(1 << PD7); ADMUX = 0; ADCSRA = 0; TCCR0A = 0; @@ -58,6 +60,11 @@ bool Motor::isSensorHigh () { return (PINB & (1 << PB0)) != 0; } + + void Motor::toggleD4 () { + PORTD ^= (1 << PD7); + } + #endif #ifdef __AVR_ATmega328P__ @@ -73,6 +80,7 @@ #define ADC0K 91 void Motor::init () { + DDRD |= (1 << PD2); // sensor signal toggle on PD2 (LED D4 red) ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=5V ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00); // Fast PWM on OC0A @@ -89,6 +97,7 @@ } void Motor::cleanup () { + DDRD &= ~(1 << PD2); enabled = 0; ADMUX = 0; ADCSRA = 0; @@ -122,6 +131,10 @@ return (PIND & (1 << PD4)) != 0; } + void Motor::toggleD4 () { + PORTD ^= (1 << PD2); + } + #endif int8_t Motor::run (uint8_t subtest) { @@ -169,9 +182,9 @@ int8_t Motor::run (uint8_t subtest) { } float rpm = 60.0 / (float)timer / 0.0001; if (timer > 0) { - printf_P(PSTR(" n= %4d U/min"), (int)rpm); + printf_P(PSTR(" n= %4d U/min (T=%04x)"), (int)rpm, timer); } else { - printf_P(PSTR(" no rotation ")); + printf_P(PSTR(" no rotation (T=%04x) "), timer); } } @@ -188,10 +201,11 @@ void Motor::tick100us () { static bool lastSensorHigh = false; bool sensorHigh = isSensorHigh(); - if (!sensorHigh && sensorHigh != lastSensorHigh && timerL > 10) { + if (!sensorHigh && sensorHigh != lastSensorHigh && timerL > 2) { rpmTimer = timerL + timerH; timerL = 0; timerH = 0; + toggleD4(); } if (sensorHigh) { timerH = timerH < 0x4000 ? timerH + 1 : 0x4000; diff --git a/software/nano-644/test_2024-07-23/src/units/motor.hpp b/software/nano-644/test_2024-07-23/src/units/motor.hpp index 6dc68f0..2cbd15a 100644 --- a/software/nano-644/test_2024-07-23/src/units/motor.hpp +++ b/software/nano-644/test_2024-07-23/src/units/motor.hpp @@ -24,6 +24,7 @@ class Motor : public TestUnit { void setEnable (); bool isFaultLow (); bool isSensorHigh (); + void toggleD4 (); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/portexp.cpp b/software/nano-644/test_2024-07-23/src/units/portexp.cpp index 7eac74d..a153589 100644 --- a/software/nano-644/test_2024-07-23/src/units/portexp.cpp +++ b/software/nano-644/test_2024-07-23/src/units/portexp.cpp @@ -21,7 +21,7 @@ #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) - // Nano-644 + // Nano-644 / Nano1284 // -------------------------------------------------------- // PA7 ... nCS // PB5 ... MOSI @@ -35,9 +35,10 @@ // PORTB/DDRB must be configured before SPCR !! PORTB |= (1 << PB4); // nSS must be HIGH, otherwise SPI master will not become active!! DDRB |= (1 << PB7) | (1 << PB5) | (1 << PB4); // SPI SCK (=PB7) and SPI MOSI (=PB5) + DDRB &= ~(1 << PB6); - // SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=12MHz/128=93,75kHz - SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz + SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=12MHz/128=93,75kHz + // SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz } void PortExp::cleanup () { @@ -76,8 +77,13 @@ PORTB |= (1 << PB2); // nSS must be HIGH, otherwise SPI master will not become active!! DDRB |= (1 << PB5) | (1 << PB3) | (1 << PB2); // SPI SCK (=PB5), SPI MOSI (=PB3), SPI nSS (=PB2) - // SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=16MHz/128=125kHz - SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz + SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=16MHz/128=125kHz + // SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz + + if (hardwareVersion == 2) { + PORTD |= (1 << PD7); // nCS when V2a/JP39.2-3 jumpered + DDRD |= (1 << PD7); + } } void PortExp::cleanup () { @@ -89,11 +95,15 @@ } void PortExp::setChipEnable () { - PORTC &= ~(1 << PC1); + if (hardwareVersion == 2) { + PORTD &= ~(1 << PD7); + } } void PortExp::clearChipEnable () { - PORTC |= (1 << PC1); + if (hardwareVersion == 2) { + PORTD |= (1 << PD7); + } } #endif @@ -101,62 +111,78 @@ int8_t PortExp::writeByte (uint8_t addr, uint8_t b) { - + // no response via SPI MISO because SO stays tristate on write cycle setChipEnable(); - SPDR = 0x40; // WRITE BYTE while ((SPSR & (1 << SPIF)) == 0) {} - if (SPDR != 0) { - printf_P(PSTR("E1")); - clearChipEnable(); - return -1; - } - SPDR = addr; // register address while ((SPSR & (1 << SPIF)) == 0) {} - if (SPDR != 0) { - printf_P(PSTR("E2")); - clearChipEnable(); - return -1; - } - SPDR = b; // value while ((SPSR & (1 << SPIF)) == 0) {} - if (SPDR != 0) { - printf_P(PSTR("E3")); - clearChipEnable(); - return -1; - } - clearChipEnable(); _delay_us(5); return 0; } +uint8_t PortExp::readByte (uint8_t addr) { + // response via SPI MISO only on third byte + setChipEnable(); + SPDR = 0x41; // write "READ BYTE" + while ((SPSR & (1 << SPIF)) == 0) {} + SPDR = addr; // write "register address" + while ((SPSR & (1 << SPIF)) == 0) {} + SPDR = 0; // additional 8 clocks to get response from port expander + while ((SPSR & (1 << SPIF)) == 0) {} + clearChipEnable(); + return SPDR; +} + +void PortExp::checkResponse (uint8_t address, uint8_t response, uint8_t desired) { + printf_P(PSTR(" (read 0x%02x -> 0x%02x"), address, response); + if (response != desired) { + printf_P(PSTR(" ERROR")); + if (response == 0xff) { + printf_P(PSTR(" JP39.2/3 jumpered (left)?")); + } + } else { + printf_P(PSTR(" OK")); + } + printf_P(PSTR(")")); +} + + int8_t PortExp::run (uint8_t subtest) { + #ifdef __AVR_ATmega328P__ + if (hardwareVersion == 1) { + printf_P(PSTR("ERROR - nCS not controlable\n")); + return -1; + } + #endif if (subtest == 0) { while (wait(500) == EOF) { printf_P(PSTR("\n => start ...")); for (uint8_t i = 0; i < 8; i++) { writeByte(0, ~(1 << i)); // IODIRA (Bank = 0) - // writeByte(0, 0x00); // IODIRA (Bank = 0) - all output writeByte(0x12, (1 << i)); // GPIOA (Bank = 0) printf_P(PSTR("\n Bank0 - GPA%d = 1"), i); + checkResponse (0x12, readByte(0x12), (1 << i)); wait(200); writeByte(0x12, 0); // GPIOA (Bank = 0) printf_P(PSTR("\n Bank0 - GPA%d = 0"), i); + checkResponse (0x12, readByte(0x12), 0); writeByte(0, 0xff); // IODIRA (Bank = 0) wait(200); } for (uint8_t i = 0; i < 8; i++) { writeByte(1, ~(1 << i)); // IODIRB (Bank = 0) - // writeByte(1, 0x00); // IODIRB (Bank = 0) - all output writeByte(0x13, (1 << i)); // GPIOB (Bank = 0) printf_P(PSTR("\n Bank0 - GPB%d = 1"), i); + checkResponse (0x13, readByte(0x13), (1 << i)); wait(200); writeByte(0x13, 0); // GPIOB (Bank = 0) printf_P(PSTR("\n Bank0 - GPB%d = 0"), i); + checkResponse (0x13, readByte(0x13), 0); writeByte(1, 0xff); // IODIRB (Bank = 0) wait(200); } diff --git a/software/nano-644/test_2024-07-23/src/units/portexp.hpp b/software/nano-644/test_2024-07-23/src/units/portexp.hpp index 2fb665c..8705662 100644 --- a/software/nano-644/test_2024-07-23/src/units/portexp.hpp +++ b/software/nano-644/test_2024-07-23/src/units/portexp.hpp @@ -17,6 +17,8 @@ class PortExp : public TestUnit { void setChipEnable (); void clearChipEnable (); int8_t writeByte (uint8_t addr, uint8_t b); + uint8_t readByte (uint8_t addr); + void checkResponse (uint8_t address, uint8_t response, uint8_t desired); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/r2r.cpp b/software/nano-644/test_2024-07-23/src/units/r2r.cpp index 87fb822..54664b1 100644 --- a/software/nano-644/test_2024-07-23/src/units/r2r.cpp +++ b/software/nano-644/test_2024-07-23/src/units/r2r.cpp @@ -11,11 +11,11 @@ #ifdef __AVR_ATmega328P__ // AVCC=4.7V, POTI Vmax=3.3V - #define K (1023.0 / 738.0) + #define K 1.32 #endif void R2r::init () { - ADMUX = (1 << REFS0) | 2; // ADC2, VREF=AVCC=3.3V + ADMUX = (1 << REFS0) | 2; // ADC2, VREF=AVCC (=3.3V for Nano-644/1284, =5V for Arduino Nano) ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 } @@ -33,8 +33,10 @@ int8_t R2r::run (uint8_t subtest) { ADCSRA |= (1 << ADSC); // start ADC while (ADCSRA & (1 << ADSC)) {} // wait for result printf_P(PSTR("%4d (0x%03x)"), ADC, ADC); - uint8_t sw = (uint8_t)( ((float)(ADC) + 32.0) / 64.0 * K ); - printf_P(PSTR(" SW9:6 = %d %d% d %d "), sw >> 3, (sw >> 2) & 0x01, (sw >> 1) & 0x01, sw & 0x01 ); + // uint8_t sw = (uint8_t)( ((float)(ADC) + 4.0) / 64.0 * K ); + float swf = ((float)(ADC) * K) / 64.8 + 0.55; + uint8_t sw = (uint8_t)swf ; + printf_P(PSTR(" %3.1f => SW9:6 = %d %d% d %d "), swf, sw >> 3, (sw >> 2) & 0x01, (sw >> 1) & 0x01, sw & 0x01 ); } return 0; } diff --git a/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp b/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp index 4bd75ca..6ae6497 100644 --- a/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp +++ b/software/nano-644/test_2024-07-23/src/units/rtc8563.cpp @@ -26,7 +26,7 @@ void Rtc8563::handleTwiIrq () { void Rtc8563::init () {} void Rtc8563::cleanup () {} int8_t Rtc8563::run (uint8_t subtest) { return -1; } -PGM_P Rtc8563::getName () {} +PGM_P Rtc8563::getName () { return PSTR("?"); } #endif #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) diff --git a/software/nano-644/test_2024-07-23/src/units/seg7.cpp b/software/nano-644/test_2024-07-23/src/units/seg7.cpp index 208107b..f522456 100644 --- a/software/nano-644/test_2024-07-23/src/units/seg7.cpp +++ b/software/nano-644/test_2024-07-23/src/units/seg7.cpp @@ -6,41 +6,63 @@ #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) - // Nano-644 + // Nano-644 / Nano 1284 // --------------------------------------------------------------- - // PA0 ... Cathode Char 1 - // PA1 ... Cathode Char 2 - // PA2 ... Cathode Char 3 - // PA3 ... Cathode Char 4 - - // PB0 ... Anode Segment A - // PB1 ... Anode Segment B - // PB2 ... Anode Segment C - // PB3 ... Anode Segment D - // PB4 ... Anode Segment E - // PB5 ... Anode Segment F - // PB6 ... Anode Segment G - // PB7 ... Anode DP - - // PD5 ... nOE (Output Enable) for all LEDs - // PD6 ... Anode L1:2 - // PD7 ... Anode L3 + // Nano-X-Base V1a V2a + // --------------------------------- + // Anode Segment A ....... PB0 PB0 + // Anode Segment B ....... PB1 PB1 + // Anode Segment C ....... PB2 PB2 + // Anode Segment D ....... PB3 PB3 + // Anode Segment E ....... PB4 PB4 + // Anode Segment F ....... PB5 PB5 + // Anode Segment G ....... PB6 PB6 + // Anode DP .............. PB7 PB7 + // --------------------------------- + // Cathode Char 1 ........ PA0 PD4 + // Cathode Char 2 ........ PA1 PD5 + // Cathode Char 3 ........ PA2 PD6 + // Cathode Char 4 ........ PA3 PD7 + // --------------------------------- + // nOE (Output Enable) ... PD5 PA1 + // Anode L1:2 ............ PD6 PA2 + // Anode L3 .............. PD7 PA3 void Seg7::init () { setAnodes(0); setCathodes(0); - DDRA |= (1 << PA3) | (1 << PA2) | (1 << PA1) | (1 << PA0); DDRB = 0xff; - DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD5); + switch (hardwareVersion) { + case 1: { + DDRA |= (1 << PA3) | (1 << PA2) | (1 << PA1) | (1 << PA0); + DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD5); + break; + } + case 2: { + DDRA |= (1 << PA3) | (1 << PA2) | (1 << PA1); + DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4); + } + break; + } } void Seg7::cleanup () { setAnodes(0); setCathodes(0); - DDRA &= ~((1 << PA3) | (1 << PA2) | (1 << PA1) | (1 << PA0)); DDRB = 0x00; - DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5)); + switch (hardwareVersion) { + case 1: { + DDRA &= ~((1 << PA3) | (1 << PA2) | (1 << PA1) | (1 << PA0)); + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5)); + break; + } + case 2: { + DDRA &= ~((1 << PA3) | (1 << PA2) | (1 << PA1)); + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4)); + } + break; + } } void Seg7::setAnodes (uint16_t a) { @@ -52,22 +74,43 @@ void Seg7::init () { if (a & 0x0020) PORTB |= (1 << PB5); else PORTB &= ~(1 << PB5); // Anode Char F if (a & 0x0040) PORTB |= (1 << PB6); else PORTB &= ~(1 << PB6); // Anode Char G if (a & 0x0080) PORTB |= (1 << PB7); else PORTB &= ~(1 << PB7); // Anode Char DP - if (a & 0x0100) PORTD |= (1 << PD6); else PORTD &= ~(1 << PD6); // Anode L1/L2 - if (a & 0x0200) PORTD |= (1 << PD7); else PORTD &= ~(1 << PD7); // Anode L3 + switch (hardwareVersion) { + case 1: { + if (a & 0x0100) PORTD |= (1 << PD6); else PORTD &= ~(1 << PD6); // Anode L1/L2 + if (a & 0x0200) PORTD |= (1 << PD7); else PORTD &= ~(1 << PD7); // Anode L3 + break; + } + case 2: { + if (a & 0x0100) PORTA |= (1 << PA2); else PORTA &= ~(1 << PA2); // Anode L1/L2 + if (a & 0x0200) PORTA |= (1 << PA3); else PORTA &= ~(1 << PA3); // Anode L3 + break; + } + } } void Seg7::setCathodes (uint8_t c) { - if (c & 0x01) PORTA |= (1 << PA0); else PORTA &= ~(1 << PA0); // Chathode Char 1 (most left) - if (c & 0x02) PORTA |= (1 << PA1); else PORTA &= ~(1 << PA1); // Chathode Char 2 - if (c & 0x04) PORTA |= (1 << PA2); else PORTA &= ~(1 << PA2); // Chathode Char 3 - if (c & 0x08) PORTA |= (1 << PA3); else PORTA &= ~(1 << PA3); // Chathode Char 4 (most right) + switch (hardwareVersion) { + case 1: { + if (c & 0x01) PORTA |= (1 << PA0); else PORTA &= ~(1 << PA0); // Chathode Char 1 (most left) + if (c & 0x02) PORTA |= (1 << PA1); else PORTA &= ~(1 << PA1); // Chathode Char 2 + if (c & 0x04) PORTA |= (1 << PA2); else PORTA &= ~(1 << PA2); // Chathode Char 3 + if (c & 0x08) PORTA |= (1 << PA3); else PORTA &= ~(1 << PA3); // Chathode Char 4 (most right) + break; + } + case 2: { + if (c & 0x01) PORTD |= (1 << PD4); else PORTD &= ~(1 << PD4); // Chathode Char 1 (most left) + if (c & 0x02) PORTD |= (1 << PD5); else PORTD &= ~(1 << PD5); // Chathode Char 2 + if (c & 0x04) PORTD |= (1 << PD6); else PORTD &= ~(1 << PD6); // Chathode Char 3 + if (c & 0x08) PORTD |= (1 << PD7); else PORTD &= ~(1 << PD7); // Chathode Char 4 (most right) + break; + } + } } void Seg7::setOE (bool enabled) { - if (enabled) { - PORTD &= ~(1 << PD5); - } else { - PORTD |= (1 << PD5); + switch (hardwareVersion) { + case 1: if (enabled) PORTD &= ~(1 << PD5); else PORTD |= (1 << PD5); break; + case 2: if (enabled) PORTA &= ~(1 << PA1); else PORTA |= (1 << PA1); break; } } @@ -78,31 +121,45 @@ void Seg7::init () { // Arduino-Nano-5V // --------------------------------------------------------------- - // PC0 ... Cathode Char 1 - // PC1 ... Cathode Char 2 - // PC2 ... Cathode Char 3 - // PC3 ... Cathode Char 4 + // Nano-X-Base V1a V2a + // --------------------------------- + // Anode Segment A ....... PD4 PD4 + // Anode Segment B ....... PB0 PB0 + // Anode Segment C ....... PD7 PD7 + // Anode Segment D ....... PD6 PD6 + // Anode Segment E ....... PB2 PB2 + // Anode Segment F ....... PB3 PB3 + // Anode Segment G ....... PB4 PB4 + // Anode DP .............. PB5 PB5 + // --------------------------------- + // Cathode Char 1 ........ PC0 PD5 + // Cathode Char 2 ........ PC1 PB1 + // Cathode Char 3 ........ PC2 PD3 + // Cathode Char 4 ........ PC3 PD2 + // --------------------------------- + // nOE (Output Enable) ... PB1 PC1 + // Anode L1:2 ............ PD3 PC2 + // Anode L3 .............. PD2 PC3 - // PD4 ... Anode Segment A - // PB0 ... Anode Segment B - // PD7 ... Anode Segment C - // PD6 ... Anode Segment D - // PB2 ... Anode Segment E - // PB3 ... Anode Segment F - // PB4 ... Anode Segment G - // PB5 ... Anode DP - - // PB1 ... nOE (Output Enable) for all LEDs - // PD3 ... Anode L1:2 - // PD2 ,,, Anode L3 void Seg7::init () { enabled = 1; setAnodes(0); setCathodes(0); - DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0) ; - DDRC |= (1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0); - DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2); + switch (hardwareVersion) { + case 1: { + DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0); + DDRC |= (1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0); + DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2); + break; + } + case 2: { + DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0); + DDRC |= (1 << PC3) | (1 << PC2) | (1 << PC1); + DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4) | (1 << PD3) | (1 << PD2); + break; + } + } } @@ -110,9 +167,21 @@ void Seg7::init () { enabled = 0; setAnodes(0); setCathodes(0); - DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0)); - DDRC &= ~((1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0)); - DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2)); + switch (hardwareVersion) { + case 1: { + DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0)); + DDRC &= ~((1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0)); + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2)); + break; + } + case 2: { + DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0) ); + DDRC &= ~((1 << PC3) | (1 << PC2) | (1 << PC1)); + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4) | (1 << PD3) | (1 << PD2)); + break; + } + } + } void Seg7::setAnodes (uint16_t a) { @@ -124,22 +193,43 @@ void Seg7::init () { if (a & 0x0020) PORTB |= (1 << PB3); else PORTB &= ~(1 << PB3); // Anode Char F if (a & 0x0040) PORTB |= (1 << PB4); else PORTB &= ~(1 << PB4); // Anode Char G if (a & 0x0080) PORTB |= (1 << PB5); else PORTB &= ~(1 << PB5); // Anode Char DP - if (a & 0x0100) PORTD |= (1 << PD3); else PORTD &= ~(1 << PD3); // Anode L1/L2 - if (a & 0x0200) PORTD |= (1 << PD2); else PORTD &= ~(1 << PD2); // Anode L3 + switch (hardwareVersion) { + case 1: { + if (a & 0x0100) PORTD |= (1 << PD3); else PORTD &= ~(1 << PD3); // Anode L1/L2 + if (a & 0x0200) PORTD |= (1 << PD2); else PORTD &= ~(1 << PD2); // Anode L3 + break; + } + case 2: { + if (a & 0x0100) PORTC |= (1 << PC2); else PORTC &= ~(1 << PC2); // Anode L1/L2 + if (a & 0x0200) PORTC |= (1 << PC3); else PORTC &= ~(1 << PC3); // Anode L3 + break; + } + } } void Seg7::setCathodes (uint8_t c) { - if (c & 0x01) PORTC |= (1 << PC0); else PORTC &= ~(1 << PC0); // Chathode Char 1 (most left) - if (c & 0x02) PORTC |= (1 << PC1); else PORTC &= ~(1 << PC1); // Chathode Char 2 - if (c & 0x04) PORTC |= (1 << PC2); else PORTC &= ~(1 << PC2); // Chathode Char 3 - if (c & 0x08) PORTC |= (1 << PC3); else PORTC &= ~(1 << PC3); // Chathode Char 4 (most right) + switch (hardwareVersion) { + case 1: { + if (c & 0x01) PORTC |= (1 << PC0); else PORTC &= ~(1 << PC0); // Chathode Char 1 (most left) + if (c & 0x02) PORTC |= (1 << PC1); else PORTC &= ~(1 << PC1); // Chathode Char 2 + if (c & 0x04) PORTC |= (1 << PC2); else PORTC &= ~(1 << PC2); // Chathode Char 3 + if (c & 0x08) PORTC |= (1 << PC3); else PORTC &= ~(1 << PC3); // Chathode Char 4 (most right) + break; + } + case 2: { + if (c & 0x01) PORTD |= (1 << PD5); else PORTD &= ~(1 << PD5); // Chathode Char 1 (most left) + if (c & 0x02) PORTB |= (1 << PB1); else PORTB &= ~(1 << PB1); // Chathode Char 2 + if (c & 0x04) PORTD |= (1 << PD3); else PORTD &= ~(1 << PD3); // Chathode Char 3 + if (c & 0x08) PORTD |= (1 << PD2); else PORTD &= ~(1 << PD2); // Chathode Char 4 (most right) + break; + } + } } void Seg7::setOE (bool enabled) { - if (enabled) { - PORTB &= ~(1 << PB1); - } else { - PORTB |= (1 << PB1); + switch (hardwareVersion) { + case 1: if (enabled) PORTB &= ~(1 << PB1); else PORTB |= (1 << PB1); break; + case 2: if (enabled) PORTC &= ~(1 << PC1); else PORTC |= (1 << PC1); break; } }