Commit e7ae81432b6d7e203e7390bf66630504f7d31778
receivedSat, 28. Sep 2024, 13:22:36 (by user sx)
Sat, 28 Sep 2024 11:22:36 +0000 (13:22 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Sat, 28 Sep 2024 11:20:57 +0000 (13:20 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Sat, 28 Sep 2024 11:20:57 +0000 (13:20 +0200)
22 files changed:
kicad/bom.kicad_sch
kicad/dist/v2a/README.md
kicad/dist/v2a/order_W202408301912956_2024-08-30/2015805767680-Produce_DanZhi.SMT_Snapshot.Top.2360571A_Y15.SMT02408301919496.png [new file with mode: 0644]
kicad/dist/v2a/order_W202408301912956_2024-08-30/8544242688-Produce_DanZhi.SMT_Snapshot.Bottom.2360571A_Y15.SMT02408301919496.png [new file with mode: 0644]
kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_GERBER-nano-x-base_Y15.zip [new file with mode: 0644]
kicad/dist/v2a/order_W202408301912956_2024-08-30/jlcp-confirmation-2024-08-30_bom.ods [new file with mode: 0644]
kicad/i2c.kicad_sch
kicad/input-output.kicad_sch
kicad/lcd-7-seg.kicad_sch
kicad/nano-x-base.kicad_sch
software/nano-644/test_2024-07-23/src/main.cpp
software/nano-644/test_2024-07-23/src/main.hpp
software/nano-644/test_2024-07-23/src/units/lcd.cpp
software/nano-644/test_2024-07-23/src/units/lcd.hpp
software/nano-644/test_2024-07-23/src/units/led.cpp
software/nano-644/test_2024-07-23/src/units/motor.cpp
software/nano-644/test_2024-07-23/src/units/motor.hpp
software/nano-644/test_2024-07-23/src/units/portexp.cpp
software/nano-644/test_2024-07-23/src/units/portexp.hpp
software/nano-644/test_2024-07-23/src/units/r2r.cpp
software/nano-644/test_2024-07-23/src/units/rtc8563.cpp
software/nano-644/test_2024-07-23/src/units/seg7.cpp

index acde2cd4de1ea314da6d13d2c8a1c5840c297cba..fde4b1a1814efa0b3b477291b83ffc04f9d10ba8 100644 (file)
@@ -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")
index a62568fe1b10a1ce832f4d08d9d90d8b1868eb29..5bc74e552876130fd3bf8c3c7cf1fafe76b8305d 100644 (file)
@@ -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 (file)
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 (file)
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 (file)
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 (file)
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
index db7d0285414ec947782230c8d3191e2a544f3b85..6fefddf8d80cd0c589712d1962f373f4727bc77b 100644 (file)
@@ -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")
index b7e1a092ed46e16a2b815a7f16354adab69f8506..e5d7c6e0620865d5d5ff1e904831b3f57b133cb0 100644 (file)
@@ -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")
index 68f868dce1fd01be5714d2352bb9c1d9c973f3b7..39c6fbc4815d19931be744154ec0e0623b400b95 100644 (file)
@@ -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")
index d42326fb0cdc33a9ee87ac789ea8b492e98e9686..000efad2566534490e3ad540cc2f67ab3459141a 100644 (file)
@@ -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")
index 2971b6e5809b44f238d1c6c871c638a16fcffc9d..18ee2d34c21198574bafae5bc7a391239035442f 100644 (file)
@@ -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++) {
index a7f2ae8068c509d9b81625c189d3c1ed6860105e..7eeff16eca000816b1e16a59d5cf3bdd9253eec4 100644 (file)
@@ -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[];
index 86406900388c8de7c33a9b88c2869ca7d4ad566c..e779c16e53582a9c18f58d229442f6008fa80aeb 100644 (file)
@@ -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));
    }
 
    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();
       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));
    }
 
       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
 #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
index 3eb445694a5a55f21e0fb8b42ec3e2bd425927cd..47a30ccc8da2fe98d930829ec06890bbfeabd77a 100644 (file)
@@ -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 ();
 
 };
 
index 5a56665977d46f19a1ed2dd8037edf0cec5945b0..e908c21d90603938b2de9cfaa823afbbd4716cd9 100644 (file)
@@ -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));
 
    // 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));
index 4457c1a393142944197aba94d0d14bf0264b87ac..83f0c3bf47d6b018d95e4993239f31bef7038567 100644 (file)
@@ -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;
    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;
       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;
index 6dc68f01e0686ce7d5be5ec26d30e951dac5d6a3..2cbd15a3972a2155bc8deb02dadb5a0962e2661b 100644 (file)
@@ -24,6 +24,7 @@ class Motor : public TestUnit {
       void setEnable ();
       bool isFaultLow ();
       bool isSensorHigh ();
+      void toggleD4 ();
 };
 
 #endif
\ No newline at end of file
index 7eac74d0dadd793ae5be13a2c92193e2af7cddf7..a1535893bf19ef33dda3d44d33ff9995d7170cf5 100644 (file)
@@ -21,7 +21,7 @@
 
 #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
 
-   // Nano-644
+   // Nano-644 / Nano1284
    // --------------------------------------------------------
    // PA7 ... nCS
    // PB5 ... MOSI
       // 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 () {
       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 () {
    }
 
    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
 
 
 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);
          }
index 2fb665c649f543b45c0d4b1bd86f399412d62c1d..8705662d4c364fe1eb688d5b481cf4ce6672abcb 100644 (file)
@@ -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
index 87fb822b20264a3cf336ad78d446a85dde51d5b1..54664b18cf545c59d61e2a403fd8fae93ba86357 100644 (file)
 
 #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;
       }
index 4bd75ca0ca4c2908bf6fd7a8734147f40c4cb1f0..6ae6497007ff163620e797fa179b3c6feadff9d6 100644 (file)
@@ -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__)
index 208107bcc0b74d96104a5699ca393cc66522d559..f5224564e2128aafc1e02e95a7bdcf36402d469c 100644 (file)
@@ -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;
       }
    }