Commit 5c90424829087600178b16fed575240ee444e31c
receivedSat, 14. Sep 2024, 17:11:56 (by user sx)
Sat, 14 Sep 2024 15:11:56 +0000 (17:11 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Sat, 14 Sep 2024 15:11:48 +0000 (17:11 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Sat, 14 Sep 2024 15:11:48 +0000 (17:11 +0200)
3 files changed:
software/nano-644/test_2024-07-23/src/main.cpp
software/nano-644/test_2024-07-23/src/units/portexp.cpp
software/nano-644/test_2024-07-23/src/units/portexp.hpp

index 34abcb62bfb996c704719bdf3fb8fc007b501890..18ee2d34c21198574bafae5bc7a391239035442f 100644 (file)
@@ -162,20 +162,20 @@ uint8_t detectHardwareVersion () {
       }
    #endif
    #if defined(__AVR_ATmega328P__)
-      if (ADCH < 0xd0 && ADCH >= 0xc0) {
+      if (ADCH < 0xd8 && ADCH >= 0xc0) {
          hardwareVersion = 1;
-      } else if (ADCH < 0xd0 && ADCH >= 0xb0) {
+      } else if (ADCH < 0xd8 && ADCH >= 0xb0) {
          hardwareVersion = 2;
       }
    #endif
 
    if (hardwareVersion == 0) {
       #ifdef __AVR_ATmega644P__
-         printf("Invalid Hardware-Version: ADC7H = %d (ATmega644P, 3.3V)\n", ADCH);
+         printf("\nInvalid Hardware-Version: ADC7H = %d (ATmega644P, 3.3V)\n", ADCH);
       #elif __AVR_ATmega1284P__
-         printf("Invalid Hardware-Version: ADC7H = %d (ATmega1284P, 3.3V)\n", ADCH);
+         printf("\nInvalid Hardware-Version: ADC7H = %d (ATmega1284P, 3.3V)\n", ADCH);
       #elif __AVR_ATmega328P__
-         printf("Invalid Hardware-Version: ADC7H = %d (ATmega328P, 5V)\n", ADCH);
+         printf("\nInvalid Hardware-Version: ADC7H = %d (ATmega328P, 5V)\n", ADCH);
       #endif
    }
 
@@ -250,7 +250,7 @@ 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
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