(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")
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
(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")
(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")
(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")
(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")
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; }
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;
#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];
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++) {
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[];
#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) {
}
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
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 ();
};
#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));
#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
}
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__
#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
}
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) {
}
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);
}
}
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;
void setEnable ();
bool isFaultLow ();
bool isSensorHigh ();
+ void toggleD4 ();
};
#endif
\ No newline at end of file
#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);
}
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
#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
}
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;
}
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__)
#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) {
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;
}
}
// 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;
+ }
+ }
}
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) {
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;
}
}