From bdf7bfd1126982fce76a6e063f699f5f4fa52c17 Mon Sep 17 00:00:00 2001 From: Manfred Steiner Date: Sat, 3 Aug 2024 20:16:23 +0200 Subject: [PATCH] ... --- software/nano-644/test_2024-07-23/Makefile | 8 +- .../nano-644/test_2024-07-23/src/main.cpp | 74 +++-- .../nano-644/test_2024-07-23/src/main.hpp | 1 + .../test_2024-07-23/src/units/encoder.cpp | 108 +++++-- .../test_2024-07-23/src/units/encoder.hpp | 6 + .../test_2024-07-23/src/units/i2c.cpp | 110 +------ .../test_2024-07-23/src/units/i2c.hpp | 1 + .../test_2024-07-23/src/units/ieee485.cpp | 66 +++-- .../test_2024-07-23/src/units/ieee485.hpp | 1 + .../test_2024-07-23/src/units/lcd.cpp | 278 ++++++++++-------- .../test_2024-07-23/src/units/lcd.hpp | 14 +- .../test_2024-07-23/src/units/led.cpp | 141 +++++++-- .../test_2024-07-23/src/units/led.hpp | 9 + .../test_2024-07-23/src/units/modbus.cpp | 15 + .../test_2024-07-23/src/units/modbus.hpp | 1 + .../test_2024-07-23/src/units/motor.cpp | 178 ++++++++--- .../test_2024-07-23/src/units/motor.hpp | 8 + .../test_2024-07-23/src/units/portexp.cpp | 120 ++++++-- .../test_2024-07-23/src/units/portexp.hpp | 6 + .../test_2024-07-23/src/units/poti.cpp | 17 +- .../test_2024-07-23/src/units/poti.hpp | 1 + .../test_2024-07-23/src/units/r2r.cpp | 29 +- .../test_2024-07-23/src/units/r2r.hpp | 1 + .../test_2024-07-23/src/units/rgb.cpp | 148 ++++++++-- .../test_2024-07-23/src/units/rgb.hpp | 9 + .../test_2024-07-23/src/units/seg7.cpp | 216 ++++++++++---- .../test_2024-07-23/src/units/seg7.hpp | 11 +- .../test_2024-07-23/src/units/switch.cpp | 91 ++++-- .../test_2024-07-23/src/units/switch.hpp | 6 +- .../test_2024-07-23/src/units/uart1.cpp | 43 +-- .../test_2024-07-23/src/units/uart1.hpp | 1 + 31 files changed, 1179 insertions(+), 539 deletions(-) diff --git a/software/nano-644/test_2024-07-23/Makefile b/software/nano-644/test_2024-07-23/Makefile index 12a996a..8c5128c 100644 --- a/software/nano-644/test_2024-07-23/Makefile +++ b/software/nano-644/test_2024-07-23/Makefile @@ -57,13 +57,13 @@ simuc: sim/$(NAME).elf gdb: sim/$(NAME).elf avr-gdb $< -isp: +isp-644p: avrdude -c usbasp -p m644p -isp-flash: dist/$(NAME).elf all +isp-flash-644p: dist/$(NAME).elf all avrdude -c usbasp -p m644p -e -U flash:w:$< -flash: dist/$(NAME).elf all +flash-644p: dist/$(NAME).elf all avrdude -c arduino -p m644p -P /dev/ttyUSB0 -b 115200 -e -U flash:w:$< @@ -71,7 +71,7 @@ picocom: # picocom sends CR for ENTER -> convert cr (\r) to lf (\n) picocom -b 115200 --omap crlf /dev/ttyUSB0 -isp-fuse: +isp-fuse-644p: avrdude -c usbasp -p m644p -U lfuse:w:0xFF:m -U hfuse:w:0xD9:m -U efuse:w:0xFF:m -U lock:w:0xFF:m clean: diff --git a/software/nano-644/test_2024-07-23/src/main.cpp b/software/nano-644/test_2024-07-23/src/main.cpp index 0223927..23bcc90 100644 --- a/software/nano-644/test_2024-07-23/src/main.cpp +++ b/software/nano-644/test_2024-07-23/src/main.cpp @@ -7,21 +7,21 @@ #include #include "main.hpp" +#include "units/encoder.hpp" +#include "units/i2c.hpp" #include "units/led.hpp" +#include "units/ieee485.hpp" +#include "units/led.hpp" +#include "units/lcd.hpp" #include "units/switch.hpp" #include "units/rgb.hpp" #include "units/seg7.hpp" #include "units/poti.hpp" -#include "units/encoder.hpp" #include "units/r2r.hpp" #include "units/motor.hpp" #include "units/portexp.hpp" -#include "units/lcd.hpp" #include "units/uart1.hpp" #include "units/modbus.hpp" -#include "units/ieee485.hpp" -#include "units/i2c.hpp" - extern "C" { void __cxa_pure_virtual () { @@ -118,6 +118,7 @@ int wait (uint32_t ms) { int main () { + #ifdef __AVR_ATmega644P__ // Nano-644 LEDs (Green, Orange, Red) DDRC |= (1 << DDC4) | (1 << DDC3) | (1 << DDC2); PORTC &= ~((1 << PORT4) | (1 << PORT3) | (1 << PORT2)); @@ -125,6 +126,12 @@ int main () { // Nano-644 push button SW2 DDRC &= ~(1 << DDC5); PORTC |= (1 << PORT5); // enable internal pullup resistor + #endif + + #ifdef __AVR_ATmega328P__ + DDRB |= (1 << PB5); + PORTB &= ~(1 << PB5); + #endif // UART0 interface on Nano-644 UCSR0A = (1 << U2X0); @@ -143,10 +150,19 @@ int main () { sei(); - TestUnit *unit[] = { - &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &portExp, &lcd, &uart1, &modbus, &ieee485, - &i2cMaster, &i2cSlave, &i2cSparkfun - }; + #ifdef __AVR_ATmega644P__ + TestUnit *unit[] = { + &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &portExp, &lcd, &uart1, &modbus, &ieee485, + &i2cMaster, &i2cSlave, &i2cSparkfun + }; + #endif + + #ifdef __AVR_ATmega328P__ + TestUnit *unit[] = { + &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &lcd, + &i2cMaster, &i2cSlave, &i2cSparkfun + }; + #endif while (1) { uint16_t i; @@ -158,6 +174,7 @@ int main () { TestUnit *pu = unit[i]; printf_P(PSTR("%3x ... "), i); printf_P(pu->getName()); + printf_P(PSTR("\n")); } printf_P(PSTR("\nSelect unit: ")); rIndex = 0; wIndex = 0; @@ -165,9 +182,10 @@ int main () { } while (sscanf(s, "%x", &i) != 1 || i < 0 || i >= sizeof(unit) / sizeof(unit[0]) ); TestUnit *pu = unit[i]; - printf_P(PSTR("\n\n[%s]: "), pu->getName()); + printf_P(PSTR("\n\n[")); printf_P(pu->getName()); printf_P(PSTR("]: ")); keyUart0 = EOF; + pu->init(); for (uint8_t subtest = 0; subtest < 0xff; subtest++) { printf_P(PSTR("\n%4d: "), subtest); if (pu->run(subtest) < 0) { @@ -191,6 +209,9 @@ uint64_t millis () { return millis; } +#ifndef USART0_RX_vect + #define USART0_RX_vect USART_RX_vect +#endif ISR (USART0_RX_vect) { uint8_t b = UDR0; keyUart0 = b; @@ -202,18 +223,20 @@ ISR (USART0_RX_vect) { } } -ISR (USART1_RX_vect) { - uint8_t b = UDR1; - if (modbus.enabled) { - modbus.handleRxByte(b); - } - if (uart1.enabled) { - uart1.handleRxByte(b); - } - if (ieee485.enabled) { - ieee485.handleRxByte(b); +#ifdef USART1_RX_vect + ISR (USART1_RX_vect) { + uint8_t b = UDR1; + if (modbus.enabled) { + modbus.handleRxByte(b); + } + if (uart1.enabled) { + uart1.handleRxByte(b); + } + if (ieee485.enabled) { + ieee485.handleRxByte(b); + } } -} +#endif ISR (TWI_vect) { if (i2cMaster.enabled) { @@ -252,7 +275,14 @@ ISR (TIMER2_COMPA_vect) { // every 100us timer500ms++; if (timer500ms >= 5000) { - PORTC ^= (1 << PORTC3); // orange LED blinking + #ifdef __AVR_ATmega644P__ + PORTC ^= (1 << PC3); // orange LED blinking + #endif + #ifdef __AVR_ATmega328P__ + if (!seg7.enabled) { + PORTB ^= (1 << PB5); // LED L + } + #endif timer500ms = 0; } } diff --git a/software/nano-644/test_2024-07-23/src/main.hpp b/software/nano-644/test_2024-07-23/src/main.hpp index f60ec89..bef51b6 100644 --- a/software/nano-644/test_2024-07-23/src/main.hpp +++ b/software/nano-644/test_2024-07-23/src/main.hpp @@ -13,6 +13,7 @@ extern uint64_t millis (); class TestUnit { public: virtual int8_t run (uint8_t subtest) = 0; + virtual void init () = 0; virtual void cleanup () = 0; virtual PGM_P getName () = 0; }; diff --git a/software/nano-644/test_2024-07-23/src/units/encoder.cpp b/software/nano-644/test_2024-07-23/src/units/encoder.cpp index bc84f48..975f358 100644 --- a/software/nano-644/test_2024-07-23/src/units/encoder.cpp +++ b/software/nano-644/test_2024-07-23/src/units/encoder.cpp @@ -4,10 +4,6 @@ #include "encoder.hpp" #include "../main.hpp" -// PB0/T0 ... Encoder A -// PB1/T1 ... Encoder B -// PB2/INT2 ... push switch of encoder (pushed = 0) - // Encoder signals on rotation clockwise 1 step: // A -----____------ one char app. 1ms..2ms (rotation speed) // B -------___----- @@ -18,57 +14,113 @@ // B --______----- // one step when: A = 0, B= 0->1 +#ifdef __AVR_ATmega644P__ + + // Nano-644 + // --------------------------------------------------------------- + // PB0/T0 ... Encoder A + // PB1/T1 ... Encoder B + // PB2/INT2 ... push switch of encoder (pushed = 0) + + void Encoder::init () { + DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0)); + PORTB |= (1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0); // enable pullup + enabled = 1; + } + + void Encoder::cleanup () { + enabled = 0; + DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0)); + PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0)); + } + + bool Encoder::isPressed () { + return (PINB & (1 << PB2)) == 0; + } + + bool Encoder::getA () { + return (PINB & (1 << PB0)) == 0; + } + + bool Encoder::getB () { + return (PINB & (1 << PB1)) == 0; + } + + +#endif + +#ifdef __AVR_ATmega328P__ + + // Arduino-Nano-5V + // --------------------------------------------------------------- + // PD4/T0 ... Encoder A + // PB0 ... Encoder B + // PD7 ... push switch of encoder (pushed = 0) + + void Encoder::init () { + DDRB &= ~(1 << PB0); + DDRD &= ~((1 << PD7) | (1 << PD4)); + PORTB |= (1 << PB0); // enable pullup + PORTD |= (1 << PD7) | (1 << PD4); // enable pullup + enabled = 1; + } + + void Encoder::cleanup () { + enabled = 0; + PORTB &= ~(1 << PB0); + PORTD &= ~((1 << PD7) | (1 << PD4)); + DDRB &= ~(1 << PB0); + DDRD &= ~((1 << PD7) | (1 << PD4)); + } + + bool Encoder::isPressed () { + return (PIND & (1 << PD7)) == 0; + } + + bool Encoder::getA () { + return (PIND & (1 << PD4)) == 0; + } + + bool Encoder::getB () { + return (PINB & (1 << PB0)) == 0; + } + +#endif -void Encoder::cleanup () { - DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0)); - PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0)); - enabled = 0; -} int8_t Encoder::run (uint8_t subtest) { switch (subtest) { case 0: { - printf_P(PSTR("init")); - DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0)); - PORTB |= (1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0); // enable pullup - enabled = 1; - return 0; - } - - case 1: { while (wait(10) == EOF) { printf_P(PSTR("\r => Encoder (push to clear): ")); printf_P(PSTR("%5d (0x%02x) "), count, (uint8_t)count); - if ((PINB & (1 << PINB2)) == 0) { + if (isPressed()) { reset(); } } return 0; } - - case 2: { - printf_P(PSTR("end")); - break; - } } return -1; } struct EncoderState { - uint8_t a:1; // signal A - uint8_t b:1; // signal B + int8_t a:1; // signal A + int8_t b:1; // signal B }; void Encoder::tick100us () { static EncoderState lastState = { 1, 1 }; static EncoderState lastStableState = { 1, 1 }; - if ((DDRB & 0x03) || (PORTB & 0x07) != 0x07) { + if (!enabled) { count = 0; - return; // Enocder pins not configured + return; } - EncoderState nextState = { (PINB & 0x01) == 0x01, (PINB & 0x02) == 0x02 }; + EncoderState nextState; + nextState.a = getA() ? 1 : 0; + nextState.b = getB() ? 1 : 0; if (nextState.a == lastState.a && nextState.b == lastState.b) { if (lastStableState.a == 0 && nextState.b != lastStableState.b) { if (nextState.b == 0) { diff --git a/software/nano-644/test_2024-07-23/src/units/encoder.hpp b/software/nano-644/test_2024-07-23/src/units/encoder.hpp index 10bcc0f..9b0861b 100644 --- a/software/nano-644/test_2024-07-23/src/units/encoder.hpp +++ b/software/nano-644/test_2024-07-23/src/units/encoder.hpp @@ -12,11 +12,17 @@ class Encoder : public TestUnit { public: Encoder () { reset(); enabled = 0; }; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Encoder"); } void reset () { count = 0; } void tick100us (); + bool isPressed (); + + private: + bool getA (); + bool getB (); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/i2c.cpp b/software/nano-644/test_2024-07-23/src/units/i2c.cpp index 4c5934f..0c92e13 100644 --- a/software/nano-644/test_2024-07-23/src/units/i2c.cpp +++ b/software/nano-644/test_2024-07-23/src/units/i2c.cpp @@ -23,6 +23,16 @@ PGM_P I2c::getName () { return "?"; } +void I2c::init () { + TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4); + TWBR = 28; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4); + TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4); + TWCR = (1 << TWEN); + ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V + ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 + enabled = true; +} + void I2c::cleanup () { enabled = false; TWCR = (1 << TWEN); @@ -32,17 +42,7 @@ void I2c::cleanup () { } int8_t I2c::run (uint8_t subtest) { - if (subtest == 0) { - TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4); - TWBR = 28; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4); - TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4); - TWCR = (1 << TWEN); - ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V - ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 - enabled = true; - printf_P(PSTR("init")); - - } else if (subtest == 1 && mode == I2c::SparkFunEnvCombo) { + if (subtest == 0 && mode == I2c::SparkFunEnvCombo) { printf_P(PSTR(" BM280 ... ")); if (!bm280.begin()) { printf_P(PSTR("E1")); @@ -156,7 +156,7 @@ int8_t I2c::run (uint8_t subtest) { } while (wait(1000) == EOF); - } else if (subtest == 1 && mode == I2c::Master) { + } else if (subtest == 0 && mode == I2c::Master) { if (!master.begin(0x01)) { printf_P(PSTR("E1")); return -1; @@ -180,7 +180,7 @@ int8_t I2c::run (uint8_t subtest) { } while (wait(1000) == EOF); master.end(); - } else if (subtest == 1 && mode == I2c::Slave) { + } else if (subtest == 0 && mode == I2c::Slave) { if (!slave.begin(0x01, false)) { printf_P(PSTR("E1")); return -1; @@ -214,87 +214,3 @@ void I2c::handleTwiIrq () { TWCR |= (1 << TWINT); // clear Interrupt Request } } - -// uint16_t I2c::startRead (uint8_t address) { -// TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send START condition -// while (!(TWCR & (1 << TWINT))) {}; // wait until last action done -// uint8_t sr = TWSR & 0xf8; -// if (sr != 0x08 && sr != 0x10) { -// return 0x0100 | sr; -// } - -// TWDR = (address << 1) | 0x01; // address + READ (R/W = 1) -// TWCR = (1 << TWINT) | (1 << TWEN); // send address/RW -// while (!(TWCR & (1 << TWINT))) {}; // wait until last action done -// sr = TWSR & 0xf8; -// if (sr != 0x40) { -// return 0x0200 | sr; -// } -// return 0; -// } - -// uint16_t I2c::startWrite (uint8_t address) { -// TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send START condition -// while (!(TWCR & (1 << TWINT))) {}; // wait until last action done -// uint8_t sr = TWSR & 0xf8; -// if (sr != 0x08 && sr != 0x10) { -// return 0x0300 | sr; -// } - -// TWDR = (address << 1) | 0x00; // address + WRITE (R/W = 0) -// TWCR = (1 << TWINT) | (1 << TWEN); // send address/RW -// while (!(TWCR & (1 << TWINT))) {}; // wait until last action done -// sr = TWSR & 0xf8; -// if (sr != 0x18) { -// return 0x0400 | sr; -// } -// return 0; -// } - -// void I2c::stop () { -// TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO); -// } - -// uint16_t I2c::writeData (uint8_t size, const uint8_t *data) { -// while (size-- > 0) { -// TWDR = *data++; -// TWCR = (1 << TWINT) | (1 << TWEN); // send data byte -// while (!(TWCR & (1 << TWINT))) {}; // wait until last action done -// uint8_t sr = TWSR & 0xf8; -// if (sr != 0x28) { -// return 0x0500 | sr; -// } -// } -// return 0; -// } - -// uint16_t I2c::writeByte (uint8_t data) { -// return writeData(1, &data); -// } - -// uint16_t I2c::readData (uint8_t size, uint8_t *data) { -// while (size-- > 0) { -// if (size > 0) { -// TWCR = (1 << TWEA) | (1 << TWINT) | (1 << TWEN); // read data byte with ACK enabled -// } else { -// TWCR = (1 << TWINT) | (1 << TWEN); // read data byte with ACK disabled -// } -// while (!(TWCR & (1 << TWINT))) {}; // wait until last action done -// uint8_t sr = TWSR & 0xf8; -// if ((size > 0 && sr != 0x50) || (size == 0 && sr != 0x58)) { -// return 0x0600 | sr; -// } -// *data++ = TWDR; -// } -// return 0; -// } - -// int32_t I2c::compensateBm280T (int32_t adcT) { -// // int32_t var1, var2, t; -// // var1 = ((((adcT >> 3) - ((int32_t)bm280.digT[0] << 1))) * ((int32_t)bm280.digT[1])) >> 11; -// // var2 = (((((adcT >> 4) - ((int32_t)bm280.digT[0])) * ((adcT >> 4) - ((int32_t)bm280.digT[0]))) >> 12) * ((int32_t)bm280.digT[2])) >> 14; -// // bm280.tFine = var1 + var2; -// // t = (bm280.tFine * 5 + 128) >> 8; -// // return t; -// return -1; -// } diff --git a/software/nano-644/test_2024-07-23/src/units/i2c.hpp b/software/nano-644/test_2024-07-23/src/units/i2c.hpp index e1f1802..f039366 100644 --- a/software/nano-644/test_2024-07-23/src/units/i2c.hpp +++ b/software/nano-644/test_2024-07-23/src/units/i2c.hpp @@ -26,6 +26,7 @@ class I2c : public TestUnit { public: I2c (I2cMode mode) { enabled = false; this->mode = mode; } void tick1ms () { master.tick1ms(); slave.tick1ms(); } + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName (); diff --git a/software/nano-644/test_2024-07-23/src/units/ieee485.cpp b/software/nano-644/test_2024-07-23/src/units/ieee485.cpp index 89e25ec..3d0bfca 100644 --- a/software/nano-644/test_2024-07-23/src/units/ieee485.cpp +++ b/software/nano-644/test_2024-07-23/src/units/ieee485.cpp @@ -6,6 +6,25 @@ #include "ieee485.hpp" #include "../main.hpp" +#ifdef __AVR_ATmega328P__ + +// Nano-328P +// ------------------------------------ +// IEE485 not supported (no UART1) + +void Ieee485::init () {} +void Ieee485::cleanup () {} +int8_t Ieee485::run (uint8_t subtest) { + return -1; +} + +#endif + + +#ifdef __AVR_ATmega644P__ + +// Nano-644 +// ------------------------------------ // PB0 ... nRE .. Read enable // PB1 ... DE .. Data enable @@ -14,6 +33,28 @@ #define SET_DE (PORTB |= (1 << PB1)) #define CLR_DE (PORTB &= ~(1 << PB1)) +void Ieee485::init () { + // Poti + ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V + ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 + + // Modbus + SET_nRE; + CLR_DE; + DDRB |= (1 << PB1) | (1 << PB0); + + // UART1 interface on Nano-644 + PORTD |= (1 << PD2); // enable RxD1 pullup + UCSR1A = (1 << U2X1); + UCSR1B = (1 << RXCIE1) | (1 << RXEN1) | (1 < 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 +#ifdef __AVR_ATmega644P__ + + // Nano-644 + // --------------------------------------------------------------- + // 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 + + void Lcd::init () { + DDRA |= (1 << PA3); + 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 + } + + void Lcd::cleanup () { + DDRA &= ~(1 << PA3); + DDRB = 0; + DDRD &= ~((1 << PD7) | (1 << PD6)); + } + + void Lcd::setRS () { PORTD |= (1 << PD7); } + void Lcd::clrRS () { PORTD &= ~(1 << PD7); } + void Lcd::setRW () { PORTD |= (1 << PD6); } + void Lcd::clrRW () { PORTD &= ~(1 << PD6); } + void Lcd::setE () { PORTA |= (1 << PA3); } + void Lcd::clrE () { PORTA &= ~(1 << PA3); } + + void Lcd::setData (uint8_t data) { + PORTB = data; + } #endif -#define DATA_PORT PORTB -#define DIR_DATA_PORT DDRB +#ifdef __AVR_ATmega328P__ -#define PORT_RS PD7 -#define SET_RS_PIN (PORTD |= (1 << PORT_RS)) -#define CLR_RS_PIN (PORTD &= ~(1 << PORT_RS)) -#define SET_DIR_RS (DDRD |= (1 << PORT_RS)) -#define CLR_DIR_RS (DDRD &= ~(1 << PORT_RS)) + // Arduino Nano (5V) + // --------------------------------------------------------------- + // 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 -#define PORT_RW PD6 -#define SET_RW_PIN (PORTD |= (1 << PORT_RW)) -#define CLR_RW_PIN (PORTD &= ~(1 << PORT_RW)) -#define SET_DIR_RW (DDRD |= (1 << PORT_RW)) -#define CLR_DIR_RW (DDRD &= ~(1 << PORT_RW)) + void Lcd::init () { + clrRW(); + clrRS(); + clrE(); + setData(0); + DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0); + DDRC |= (1 << PC3); + 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 + } + + void Lcd::cleanup () { + clrRW(); + clrRS(); + clrE(); + setData(0); + DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0)); + DDRC &= ~(1 << PC3); + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2)); + } + + void Lcd::setRS () { PORTD |= (1 << PD2); } + void Lcd::clrRS () { PORTD &= ~(1 << PD2); } + void Lcd::setRW () { PORTD |= (1 << PD3); } + void Lcd::clrRW () { PORTD &= ~(1 << PD3); } + void Lcd::setE () { PORTC |= (1 << PC3); } + void Lcd::clrE () { PORTC &= ~(1 << PC3); } -#define SET_E_PIN (PORTA |= (1 << PA3)) -#define CLR_E_PIN (PORTA &= ~(1 << PA3)) -#define SET_DIR_E (DDRA |= (1 << PA3)) -#define CLR_DIR_E (DDRA &= ~(1 << PA3)) + void Lcd::setData (uint8_t data) { + if (data & 0x01) PORTD |= (1 << PD4); else PORTD &= ~((1 << PD4)); + if (data & 0x02) PORTB |= (1 << PB0); else PORTB &= ~((1 << PB0)); + if (data & 0x04) PORTD |= (1 << PD7); else PORTD &= ~((1 << PD7)); + if (data & 0x08) PORTD |= (1 << PD6); else PORTD &= ~((1 << PD6)); + if (data & 0x10) PORTB |= (1 << PB2); else PORTB &= ~((1 << PB2)); + if (data & 0x20) PORTB |= (1 << PB3); else PORTB &= ~((1 << PB3)); + if (data & 0x40) PORTB |= (1 << PB4); else PORTB &= ~((1 << PB4)); + if (data & 0x80) PORTB |= (1 << PB5); else PORTB &= ~((1 << PB5)); + } +#endif // Befehle für das Display @@ -45,32 +121,8 @@ #define BLINK_ON 0b00001111 // Cursor Blink #define BLINK_OFF 0b00001110 // Cursor No Blink - -void Lcd::cleanup () { - DDRA &= ~(1 << PA3); - PORTA &= ~(1 << PA3); - DDRD &= ~((1 << DDD7) | (1 << DDD6)); - PORTD &= ~((1 << PORTD7) | (1 << PORTD6)); - PORTB = 0; - DDRB = 0; -} - int8_t Lcd::run (uint8_t subtest) { if (subtest == 0) { - // DDRA |= (1 << PA3); - // PORTA &= ~(1 << PA3); - // DDRD |= (1 << DDD7) | (1 << DDD6); - // PORTD &= ~((1 << PORTD7) | (1 << PORTD6)); - // PORTB = 0; - // DDRB = 0xff; - init(); - #ifdef LCD_3V3 - printf_P(PSTR("init 3.3V LCD")); - #else - printf_P(PSTR("init 5V LCD")); - #endif - - } else if (subtest == 1) { for (uint8_t i = 0; i < 20 * 4; i++) { char c = (char)(i + 32); if (i % 20 == 0) { @@ -99,42 +151,32 @@ int8_t Lcd::run (uint8_t subtest) { return 0; } -void Lcd::init () { - CLR_RW_PIN; // write - CLR_RS_PIN; // command - CLR_E_PIN; // E = 0 +void Lcd::initLcd () { + _delay_ms(16); // min 15ms warten für Reset des Displays - SET_DIR_RW; - SET_DIR_RS; - SET_DIR_E; + 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 - DATA_PORT = 0; - DIR_DATA_PORT = 0xff; - _delay_ms(16); // min 15ms warten für Reset des Displays + 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 - DATA_PORT = 0b00111011; // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display - CLR_RW_PIN; // write - CLR_RS_PIN; // command - SET_E_PIN; // E = 1 (transfer start) - _delay_us(10); // min. 10us - CLR_E_PIN; // E = 0 (transfer end) - _delay_ms(5); // min. 4.1ms - - DATA_PORT = 0b00111011; // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display - CLR_RW_PIN; // write - CLR_RS_PIN; // command - SET_E_PIN; // E = 1 (transfer start) - _delay_us(10); // min. 10us - CLR_E_PIN; // E = 0 (transfer end) - _delay_us(100); // min. 100us - - DATA_PORT = 0b00111011; // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display - CLR_RW_PIN; // write - CLR_RS_PIN; // command - SET_E_PIN; // E = 1 (transfer start) - _delay_us(10); // min. 10us - CLR_E_PIN; // 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()) {}; @@ -148,43 +190,42 @@ void Lcd::init () { 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; + // 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); - return 0; #endif - + return 0; } void Lcd::writeCommand (uint8_t cmd) { - DATA_PORT = cmd; - CLR_RW_PIN; // write - CLR_RS_PIN; // command - SET_E_PIN; // E = 1 (transfer start) - _delay_us(10); // min. 10us - CLR_E_PIN; // E = 0 (transfer end) - _delay_us(10); // min. 10us - DATA_PORT = 0; + 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::setDDRamAddr (uint8_t address) { - DATA_PORT = address | 0x80; - CLR_RW_PIN; // write - CLR_RS_PIN; // command - SET_E_PIN; // E = 1 (transfer start) - _delay_us(10); // min. 10us - CLR_E_PIN; // E = 0 (transfer end) - _delay_us(10); // min. 10us - DATA_PORT = 0; + 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::writeString (const char *s) { @@ -195,15 +236,15 @@ void Lcd::writeString (const char *s) { } void Lcd::writeData (uint8_t data) { - DATA_PORT = data; // Write data to port - SET_RS_PIN; // data - CLR_RW_PIN; // command - SET_E_PIN; // E = 1 (transfer start) - _delay_us(10); // min. 10us - CLR_E_PIN; // E = 0 (transfer end) - _delay_us(10); // min. 10us - CLR_RS_PIN; - DATA_PORT = 0; + 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); } void Lcd::setCursor (uint8_t row, uint8_t column) { @@ -221,4 +262,3 @@ void Lcd::setCursor (uint8_t row, uint8_t column) { setDDRamAddr(b); while (isBusy()) {}; } - diff --git a/software/nano-644/test_2024-07-23/src/units/lcd.hpp b/software/nano-644/test_2024-07-23/src/units/lcd.hpp index 14561b0..3eb4456 100644 --- a/software/nano-644/test_2024-07-23/src/units/lcd.hpp +++ b/software/nano-644/test_2024-07-23/src/units/lcd.hpp @@ -8,17 +8,27 @@ class Lcd : public TestUnit { public: Lcd () {}; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Lcd"); } - - void init (); + + private: + 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 setRS (); + void clrRS (); + void setRW (); + void clrRW (); + void setE (); + void clrE (); + void setData (uint8_t data); + }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/led.cpp b/software/nano-644/test_2024-07-23/src/units/led.cpp index a35ca81..c3175c1 100644 --- a/software/nano-644/test_2024-07-23/src/units/led.cpp +++ b/software/nano-644/test_2024-07-23/src/units/led.cpp @@ -5,28 +5,129 @@ #include "led.hpp" #include "../main.hpp" -void Led::cleanup () { - DDRD &= ~((1 << DDD7) | (1 << DDD6) | (1 << DDD5) | (1 << DDD4)); - PORTD &= ~((1 << PORTD7) | (1 << PORTD6) | (1 << PORTD5) | (1 << PORTD4)); +#ifdef __AVR_ATmega644P__ + + // Nano-644 + // --------------------------------------------------------------- + // PD4 ..... Red + // PD5 ..... Orange/Yellow + // PD6 ..... Green + // PD7 ..... Blue + + void Led::init () { + PORTD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4)); + DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4); + } + + void Led::cleanup () { + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4)); + PORTD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4)); + } + + void Led::setLed (LED led, bool on) { + if (on) { + switch(led) { + case RED: PORTD |= (1 << PD4); break; + case ORANGE: PORTD |= (1 << PD5); break; + case GREEN: PORTD |= (1 << PD6); break; + case BLUE: PORTD |= (1 << PD7); break; + } + } else { + switch(led) { + case RED: PORTD &= ~(1 << PD4); break; + case ORANGE: PORTD &= ~(1 << PD5); break; + case GREEN: PORTD &= ~(1 << PD6); break; + case BLUE: PORTD &= ~(1 << PD7); break; + } + } + } + + void Led::ledToggle (LED led) { + switch(led) { + case RED: PORTD ^= (1 << PD4); break; + case ORANGE: PORTD ^= (1 << PD5); break; + case GREEN: PORTD ^= (1 << PD6); break; + case BLUE: PORTD ^= (1 << PD7); break; + } + } + +#endif + +#ifdef __AVR_ATmega328P__ + + // Arduino-Nano-5V + // --------------------------------------------------------------- + // PD5 ..... Red + // PB1 ..... Orange/Yellow + // PD3 ..... Green + // PD2 ..... Blue + + void Led::init () { + PORTD &= ~((1 << PD5) | (1 << PD3) | (1 << PD2)); + PORTB &= ~(1 << PB1); + DDRD |= (1 << PD5) | (1 << PD3) | (1 << PD2); + DDRB |= (1 << PB1); + } + + void Led::cleanup () { + DDRD &= ~((1 << PD5) | (1 << PD3) | (1 << PD2)); + DDRB &= ~(1 << PB1); + PORTD &= ~((1 << PD5) | (1 << PD3) | (1 << PD2)); + PORTB &= ~(1 << PB1); + } + + void Led::setLed (LED led, bool on) { + if (on) { + switch(led) { + case RED: PORTD |= (1 << PD5); break; + case ORANGE: PORTB |= (1 << PB1); break; + case GREEN: PORTD |= (1 << PD3); break; + case BLUE: PORTD |= (1 << PD2); break; + } + } else { + switch(led) { + case RED: PORTD &= ~(1 << PD5); break; + case ORANGE: PORTB &= ~(1 << PB1); break; + case GREEN: PORTD &= ~(1 << PD3); break; + case BLUE: PORTD &= ~(1 << PD2); break; + } + } + } + + void Led::ledToggle (LED led) { + switch(led) { + case RED: PORTD ^= (1 << PD5); break; + case ORANGE: PORTB ^= (1 << PB1); break; + case GREEN: PORTD ^= (1 << PD3); break; + case BLUE: PORTD ^= (1 << PD2); break; + } + } + +#endif + +void Led::ledOn (LED led) { + setLed(led, true); +} + +void Led::ledOff (LED led) { + setLed(led, false); } + int8_t Led::run (uint8_t subtest) { - if (subtest == 0) { - DDRD |= (1 << DDD7) | (1 << DDD6) | (1 << DDD5) | (1 << DDD4); - PORTD &= ~((1 << PORTD7) | (1 << PORTD6) | (1 << PORTD5) | (1 << PORTD4)); - printf_P(PSTR("init")); - - } else if (subtest <= 16) { - subtest = (subtest - 1) % 4; - PORTD &= ~((1 << PORTD7) | (1 << PORTD6) | (1 << PORTD5) | (1 << PORTD4)); - PORTD |= (1 << (subtest + 4)); - printf_P(PSTR("Test LED PD%d"), subtest + 4); - - } else { - printf_P(PSTR("end")); - return -1; - } - wait(500); - return 0; + if (subtest <= 15) { + subtest = (subtest) % 4; + switch (subtest) { + case 0: ledOff(BLUE); ledOn(RED); break; + case 1: ledOff(RED); ledOn(ORANGE); break; + case 2: ledOff(ORANGE); ledOn(GREEN); break; + case 3: ledOff(GREEN); ledOn(BLUE); break; + } + printf_P(PSTR("Test LED D%d"), subtest + 1); + wait(500); + return 0; + } + + return -1; } diff --git a/software/nano-644/test_2024-07-23/src/units/led.hpp b/software/nano-644/test_2024-07-23/src/units/led.hpp index acff045..780827f 100644 --- a/software/nano-644/test_2024-07-23/src/units/led.hpp +++ b/software/nano-644/test_2024-07-23/src/units/led.hpp @@ -6,11 +6,20 @@ #include class Led : public TestUnit { + public: + enum LED { RED, ORANGE, GREEN, BLUE }; + public: Led () {}; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Led"); } + + void setLed (LED led, bool on); + void ledOn (LED led); + void ledOff (LED led); + void ledToggle (LED led); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/modbus.cpp b/software/nano-644/test_2024-07-23/src/units/modbus.cpp index ec74d50..9faf8db 100644 --- a/software/nano-644/test_2024-07-23/src/units/modbus.cpp +++ b/software/nano-644/test_2024-07-23/src/units/modbus.cpp @@ -5,6 +5,16 @@ #include "modbus.hpp" #include "../main.hpp" + +#ifdef __AVR_ATmega328P__ +void Modbus::init () {} +void Modbus::cleanup () {} +int8_t Modbus::run (uint8_t subtest) { return -1; } +void Modbus::handleRxByte (uint8_t b) {} +#endif + +#ifdef __AVR_ATmega644P__ + // PB0 ... nRE .. Read enable // PB1 ... DE .. Data enable @@ -14,6 +24,9 @@ #define CLR_DE (PORTB &= ~(1 << PB1)) +void Modbus::init () { +} + void Modbus::cleanup () { enabled = 0; UCSR1A = 0; @@ -143,3 +156,5 @@ void Modbus::handleRxByte (uint8_t b) { received[receivedBytes++] = b; } } + +#endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/modbus.hpp b/software/nano-644/test_2024-07-23/src/units/modbus.hpp index d0f6c48..44b6a9d 100644 --- a/software/nano-644/test_2024-07-23/src/units/modbus.hpp +++ b/software/nano-644/test_2024-07-23/src/units/modbus.hpp @@ -14,6 +14,7 @@ class Modbus : public TestUnit { public: Modbus () { enabled = 0; receivedBytes = 0; } + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Modbus"); } diff --git a/software/nano-644/test_2024-07-23/src/units/motor.cpp b/software/nano-644/test_2024-07-23/src/units/motor.cpp index 429d39a..eac61bb 100644 --- a/software/nano-644/test_2024-07-23/src/units/motor.cpp +++ b/software/nano-644/test_2024-07-23/src/units/motor.cpp @@ -5,42 +5,149 @@ #include "motor.hpp" #include "../main.hpp" -void Motor::cleanup () { - ADMUX = 0; - ADCSRA = 0; - TCCR0A = 0; - TCCR0B = 0; - DDRB &= ~((1 << PB4) | (1 << PB3)); - PORTA &= ~(1 << PORTA3); - enabled = 0; -} +#ifdef __AVR_ATmega644P__ + + // Nano-644 + // --------------------------------------------------------------- + // PB0 ..... rotation-sensor + // PB2 ..... nFault + // PB3 ..... PWM (OC0A) + // PB4 ..... EN + // PA3 ..... SW3 -> push button for Motor enable control + + #define ADC0K 64 + + void Motor::init () { + 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 + // TCCR0B = (1 << CS02) | ( 1 << CS00); // f = 12 MHz / 1024 = 11,71875 kHz -> fPWM=45Hz + TCCR0B = (1 << CS02); // f = 12 MHz / 256 = 46,875 kHz -> fPWM=183,1Hz + DDRB |= (1 << PB4) | (1 << PB3); // Motor enable + PORTA |= (1 << PORTA3); // push button for Motor enable control + setEnable(); + enabled = 1; + } + + void Motor::cleanup () { + ADMUX = 0; + ADCSRA = 0; + TCCR0A = 0; + TCCR0B = 0; + DDRB &= ~((1 << PB4) | (1 << PB3)); + PORTA &= ~(1 << PORTA3); + enabled = 0; + } + + bool Motor::isSW3Pressed () { + return (PINA & (1 << PC3)) == 0; + } + + void Motor::clearEnable () { + PORTB &= ~(1 << PB4); + } + + void Motor::setEnable () { + PORTB |= (1 << PB4); + } + + bool Motor::isFaultLow () { + return (PINB & (1 << PB2)) == 0; + } + + bool Motor::isSensorHigh () { + return (PINB & (1 << PB0)) != 0; + } +#endif + +#ifdef __AVR_ATmega328P__ + + // Arduino-Nano-5V + // --------------------------------------------------------------- + // PD4 ..... rotation-sensor + // PD7 ..... nFault + // PD6/OC0A ..... PWM + // PB2 ..... EN + // PC3 ..... SW3 -> push button for Motor enable control + + #define ADC0K 91 + + void Motor::init () { + 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 + // TCCR0B = (1 << CS02) | ( 1 << CS00); // f = 16 MHz / 1024 = 15,625 kHz -> fPWM=61.04Hz + TCCR0B = (1 << CS02); // f = 16 MHz / 256 = 62.5 kHz -> fPWM=244.14Hz + DDRB |= (1 << PB2); + DDRC &= ~(1 << PC3); + DDRD |= (1 << PD6); + DDRD &= ~((1 << PD4) | (1 << PD7)); + PORTC |= ( 1 << PC3); + PORTD |= (1 << PD7) | (1 << PD5); + setEnable(); + enabled = 1; + } + + void Motor::cleanup () { + enabled = 0; + ADMUX = 0; + ADCSRA = 0; + TCCR0A = 0; + TCCR0B = 0; + clearEnable(); + DDRB &= ~((1 << PB2)); + DDRC &= ~(1 << PC3); + DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4)); + PORTC &= ~( 1 << PC3); + PORTD &= ~((1 << PD7) | (1 << PD6)); + } + + bool Motor::isSW3Pressed () { + return (PINC & (1 << PC3)) == 0; + } + + void Motor::clearEnable () { + PORTB &= ~(1 << PB2); + } + + void Motor::setEnable () { + PORTB |= (1 << PB2); + } + + bool Motor::isFaultLow () { + return (PIND & (1 << PD7)) == 0; + } + + bool Motor::isSensorHigh () { + return (PIND & (1 << PD4)) != 0; + } + +#endif int8_t Motor::run (uint8_t subtest) { switch (subtest) { case 0: { - printf_P(PSTR("init")); - 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 - // TCCR0B = (1 << CS02) | ( 1 << CS00); // f = 12 MHz / 1024 = 11,71875 kHz -> fPWM=45Hz - TCCR0B = (1 << CS02); // f = 12 MHz / 256 = 46,875 kHz -> fPWM=183,1Hz - DDRB |= (1 << PB4) | (1 << PB3); // Motor enable - PORTA |= (1 << PORTA3); // push button for Motor enable control - enabled = 1; - return 0; - } - - case 1: { printf_P(PSTR("\n")); while (wait(10) == EOF) { + printf_P(PSTR("\r SW3=%d->"), isSW3Pressed() ? 0 : 1); + if (isSW3Pressed()) { + clearEnable(); + printf_P(PSTR("EN=0")); + } else { + setEnable(); + printf_P(PSTR("EN=1")); + } + ADCSRA |= (1 << ADSC); // start ADC while (ADCSRA & (1 << ADSC)) {} // wait for result printf_P(PSTR("\r => ADC0=%3d"), ADCH); ADMUX = (1 << ADLAR) | (1 << REFS1) | (1 << REFS0) | 2; // ADC2, VREF=2.5V - uint8_t dutyCycle = 0xff - ADCH; + int16_t x = ((int16_t)(ADCH) - 5) * ADC0K / 64; + if (x < 0) x = 0; else if (x > 255) x = 255; + uint8_t dutyCycle = 0xff - (uint8_t)x; if (dutyCycle <= 1) { dutyCycle = 0; } else if (dutyCycle > 254) { @@ -54,12 +161,8 @@ int8_t Motor::run (uint8_t subtest) { printf_P(PSTR(" ADC2=%3d"), ADCH); ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V - if ((PINA & (1<< PA3)) == 0) { - PORTB &= ~(1 << PORTB4); - } else { - PORTB |= (1 << PORTB4); - } - + printf_P(PSTR(" nFAULT=%d"), isFaultLow() ? 0 : 1); + printf_P(PSTR(" SENSOR=%d "), isSensorHigh()); uint16_t timer; ATOMIC_BLOCK(ATOMIC_FORCEON) { timer = rpmTimer; @@ -68,17 +171,12 @@ int8_t Motor::run (uint8_t subtest) { if (timer > 0) { printf_P(PSTR(" n= %4d U/min"), (int)rpm); } else { - printf_P(PSTR(" no rotation")); + printf_P(PSTR(" no rotation ")); } } return 0; } - - case 2: { - printf_P(PSTR("end")); - break; - } } return -1; @@ -87,13 +185,15 @@ int8_t Motor::run (uint8_t subtest) { void Motor::tick100us () { static uint16_t timerH = 0; static uint16_t timerL = 0; - static uint8_t pinb = 0; - if ((PINB & 0x01) && PINB != pinb && timerL > 10) { + static bool lastSensorHigh = false; + + bool sensorHigh = isSensorHigh(); + if (!sensorHigh && sensorHigh != lastSensorHigh && timerL > 10) { rpmTimer = timerL + timerH; timerL = 0; timerH = 0; } - if (PINB & 0x01) { + if (sensorHigh) { timerH = timerH < 0x4000 ? timerH + 1 : 0x4000; } else { timerL = timerL < 0x4000 ? timerL + 1 : 0x4000; @@ -101,7 +201,7 @@ void Motor::tick100us () { if (timerH >= 0x4000 || timerL >= 0x4000) { rpmTimer = 0; // no ratation detected } - pinb = PINB; + lastSensorHigh = sensorHigh; } diff --git a/software/nano-644/test_2024-07-23/src/units/motor.hpp b/software/nano-644/test_2024-07-23/src/units/motor.hpp index 74623ca..6dc68f0 100644 --- a/software/nano-644/test_2024-07-23/src/units/motor.hpp +++ b/software/nano-644/test_2024-07-23/src/units/motor.hpp @@ -12,10 +12,18 @@ class Motor : public TestUnit { public: Motor () { enabled = 0; rpmTimer = 0; }; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Motor"); } void tick100us (); + + private: + bool isSW3Pressed (); + void clearEnable (); + void setEnable (); + bool isFaultLow (); + bool isSensorHigh (); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/portexp.cpp b/software/nano-644/test_2024-07-23/src/units/portexp.cpp index bcc2052..409d1f8 100644 --- a/software/nano-644/test_2024-07-23/src/units/portexp.cpp +++ b/software/nano-644/test_2024-07-23/src/units/portexp.cpp @@ -19,25 +19,96 @@ // GPA6 | IO16O1 (PA1) | L-Gelb | | GPB6 | IO16U1 (PC1) | O-Gelb | // GPA7 | IO16O0 (PA0) | L-Rot | | GPB7 | IO16U0 (PC0) | O-Rot | +#ifdef __AVR_ATmega644P__ -void PortExp::cleanup () { - DDRB &= ~(1 << PB6); // // SPI MISO (=PB6) - DDRB &= ~((1 << PB7) | (1 << PB5)); // SPI SCK (=PB7) and SPI MOSI (=PB5) - DDRA &= ~(1 << PA7); - PORTA &= ~(1 << PA7); // SPI nCS - SPCR = 0; - -} + // Nano-644 + // -------------------------------------------------------- + // PA7 ... nCS + // PB5 ... MOSI + // PB6 ... MISO + // PB7 ... SCK + + void PortExp::init () { + PRR &= (1 << PRSPI); + PORTA |= (1 << PA7); + DDRA |= (1 << PA7); // SPI nCS + // 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) -int8_t writeByte (uint8_t addr, uint8_t b) { + // 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 + } - PORTA &= ~(1 << PA7); // SPI nCS 1 -> 0 + void PortExp::cleanup () { + DDRB &= ~(1 << PB6); // // SPI MISO (=PB6) + DDRB &= ~((1 << PB7) | (1 << PB5)); // SPI SCK (=PB7) and SPI MOSI (=PB5) + DDRA &= ~(1 << PA7); + PORTA &= ~(1 << PA7); // SPI nCS + SPCR = 0; + } + + void PortExp::setChipEnable () { + PORTA &= ~(1 << PA7); + } + + void PortExp::clearChipEnable () { + PORTA |= (1 << PA7); + } + + +#endif + +#ifdef __AVR_ATmega328P__ + + // Arduino-Nano-5V + // ------------------------------------ + // PC1 ... nCS (MANUAL (!) connection PA1 - PA7 required) + // PB3 ... MOSI + // PB4 ... MISO + // PB5 ... SCK + + void PortExp::init () { + PRR &= (1 << PRSPI); + PORTC |= (1 << PC1); + DDRC |= (1 << PC1); // SPI nCS + // PORTB/DDRB must be configured before SPCR !! + 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 + } + + void PortExp::cleanup () { + PORTC &= ~(1 << PC1); + DDRC &= ~(1 << PC1); + PORTB &= ~(1 << PB2); + DDRB &= ~((1 << PB5) | (1 << PB3) | (1 << PB2)); + SPCR = 0; + } + + void PortExp::setChipEnable () { + PORTC &= ~(1 << PC1); + } + + void PortExp::clearChipEnable () { + PORTC |= (1 << PC1); + } + +#endif + + + +int8_t PortExp::writeByte (uint8_t addr, uint8_t b) { + + setChipEnable(); SPDR = 0x40; // WRITE BYTE while ((SPSR & (1 << SPIF)) == 0) {} if (SPDR != 0) { printf_P(PSTR("E1")); - PORTA |= (1 << PA7); // SPI nCS 0 -> 1 + clearChipEnable(); return -1; } @@ -45,7 +116,7 @@ int8_t writeByte (uint8_t addr, uint8_t b) { while ((SPSR & (1 << SPIF)) == 0) {} if (SPDR != 0) { printf_P(PSTR("E2")); - PORTA |= (1 << PA7); // SPI nCS 0 -> 1 + clearChipEnable(); return -1; } @@ -53,11 +124,11 @@ int8_t writeByte (uint8_t addr, uint8_t b) { while ((SPSR & (1 << SPIF)) == 0) {} if (SPDR != 0) { printf_P(PSTR("E3")); - PORTA |= (1 << PA7); // SPI nCS 0 -> 1 + clearChipEnable(); return -1; } - PORTA |= (1 << PA7); // SPI nCS 0 -> 1 + clearChipEnable(); _delay_us(5); return 0; @@ -65,18 +136,6 @@ int8_t writeByte (uint8_t addr, uint8_t b) { int8_t PortExp::run (uint8_t subtest) { if (subtest == 0) { - PRR &= (1 << PRSPI); - PORTA |= (1 << PA7); - DDRA |= (1 << PA7); // SPI nCS - // 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) - - // 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 - printf_P(PSTR("init")); - - } else if (subtest == 1) { while (wait(500) == EOF) { printf_P(PSTR("\n => start ...")); for (uint8_t i = 0; i < 8; i++) { @@ -102,12 +161,9 @@ int8_t PortExp::run (uint8_t subtest) { wait(200); } } - - } else { - printf_P(PSTR("end")); - return -1; + return 0; } - wait(500); - return 0; + + return -1; } diff --git a/software/nano-644/test_2024-07-23/src/units/portexp.hpp b/software/nano-644/test_2024-07-23/src/units/portexp.hpp index cacea83..2fb665c 100644 --- a/software/nano-644/test_2024-07-23/src/units/portexp.hpp +++ b/software/nano-644/test_2024-07-23/src/units/portexp.hpp @@ -8,9 +8,15 @@ class PortExp : public TestUnit { public: PortExp () {}; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("PortExp"); } + + private: + void setChipEnable (); + void clearChipEnable (); + int8_t writeByte (uint8_t addr, uint8_t b); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/poti.cpp b/software/nano-644/test_2024-07-23/src/units/poti.cpp index d316a0b..94fc5a4 100644 --- a/software/nano-644/test_2024-07-23/src/units/poti.cpp +++ b/software/nano-644/test_2024-07-23/src/units/poti.cpp @@ -4,6 +4,11 @@ #include "poti.hpp" #include "../main.hpp" +void Poti::init () { + ADMUX = (1 << REFS0); // ADC0, VREF=AVCC=3.3V + ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 +} + void Poti::cleanup () { ADMUX = 0; ADCSRA = 0; @@ -12,13 +17,6 @@ void Poti::cleanup () { int8_t Poti::run (uint8_t subtest) { switch (subtest) { case 0: { - printf_P(PSTR("init")); - ADMUX = (1 << REFS0); // ADC0, VREF=AVCC=3.3V - ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 - return 0; - } - - case 1: { printf_P(PSTR("\n")); while (wait(10) == EOF) { printf_P(PSTR("\r => Measure ADC0: ")); @@ -28,11 +26,6 @@ int8_t Poti::run (uint8_t subtest) { } return 0; } - - case 2: { - printf_P(PSTR("end")); - break; - } } return -1; diff --git a/software/nano-644/test_2024-07-23/src/units/poti.hpp b/software/nano-644/test_2024-07-23/src/units/poti.hpp index 2ca46e3..b13dd29 100644 --- a/software/nano-644/test_2024-07-23/src/units/poti.hpp +++ b/software/nano-644/test_2024-07-23/src/units/poti.hpp @@ -8,6 +8,7 @@ class Poti : public TestUnit { public: Poti () {}; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Poti"); } diff --git a/software/nano-644/test_2024-07-23/src/units/r2r.cpp b/software/nano-644/test_2024-07-23/src/units/r2r.cpp index 60f9ab1..ef299ce 100644 --- a/software/nano-644/test_2024-07-23/src/units/r2r.cpp +++ b/software/nano-644/test_2024-07-23/src/units/r2r.cpp @@ -4,6 +4,21 @@ #include "r2r.hpp" #include "../main.hpp" +#ifdef __AVR_ATmega644P__ + // AVCC=3.3, POTI Vmax=3.3V + #define K 1.0 +#endif + +#ifdef __AVR_ATmega328P__ + // AVCC=4.7V, POTI Vmax=3.3V + #define K (1023.0 / 738.0) +#endif + +void R2r::init () { + ADMUX = (1 << REFS0) | 2; // ADC2, VREF=AVCC=3.3V + ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 +} + void R2r::cleanup () { ADMUX = 0; ADCSRA = 0; @@ -12,29 +27,17 @@ void R2r::cleanup () { int8_t R2r::run (uint8_t subtest) { switch (subtest) { case 0: { - printf_P(PSTR("init")); - ADMUX = (1 << REFS0) | 2; // ADC2, VREF=AVCC=3.3V - ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128 - return 0; - } - - case 1: { printf_P(PSTR("\n")); while (wait(10) == EOF) { printf_P(PSTR("\r => Measure ADC2: ")); ADCSRA |= (1 << ADSC); // start ADC while (ADCSRA & (1 << ADSC)) {} // wait for result printf_P(PSTR("%4d (0x%03x)"), ADC, ADC); - uint8_t sw = (ADC + 32) / 64; + 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 ); } return 0; } - - case 2: { - printf_P(PSTR("end")); - break; - } } return -1; diff --git a/software/nano-644/test_2024-07-23/src/units/r2r.hpp b/software/nano-644/test_2024-07-23/src/units/r2r.hpp index 6088ce5..84e97e6 100644 --- a/software/nano-644/test_2024-07-23/src/units/r2r.hpp +++ b/software/nano-644/test_2024-07-23/src/units/r2r.hpp @@ -8,6 +8,7 @@ class R2r : public TestUnit { public: R2r () {}; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("R2R"); } diff --git a/software/nano-644/test_2024-07-23/src/units/rgb.cpp b/software/nano-644/test_2024-07-23/src/units/rgb.cpp index 6f08cb5..c8d32c5 100644 --- a/software/nano-644/test_2024-07-23/src/units/rgb.cpp +++ b/software/nano-644/test_2024-07-23/src/units/rgb.cpp @@ -4,54 +4,146 @@ #include "rgb.hpp" #include "../main.hpp" -void Rgb::cleanup () { - PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0)); - DDRB &= ~((1 << DDB2) | (1 << DDB1) | (1 << DDB0)); +#ifdef __AVR_ATmega644P__ + + // Nano-644 + // --------------------------------------------------------------- + // PB0 ..... Red (inverse logic -> 0 = ON) + // PB1 ..... Green (inverse logic -> 0 = ON) + // PB2 ..... Blue (inverse logic -> 0 = ON) + + void Rgb::init () { + ledOff(RED); + ledOff(GREEN); + ledOff(BLUE); + DDRB |= (1 << PB2) | (1 << PB1) | (1 << PB0); + } + + void Rgb::cleanup () { + ledOff(RED); + ledOff(GREEN); + ledOff(BLUE); + DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0)); + } + + void Rgb::setLed (LED led, bool on) { + if (on) { + switch(led) { + case RED: PORTB &= ~(1 << PB0); break; + case GREEN: PORTB &= ~(1 << PB1); break; + case BLUE: PORTB &= ~(1 << PB2); break; + } + } else { + switch(led) { + case RED: PORTB |= (1 << PB0); break; + case GREEN: PORTB |= (1 << PB1); break; + case BLUE: PORTB |= (1 << PB2); break; + } + } + } + + void Rgb::ledToggle (LED led) { + switch(led) { + case RED: PORTB ^= (1 << PB0); break; + case GREEN: PORTB ^= (1 << PB1); break; + case BLUE: PORTB ^= (1 << PB2); break; + } + } + + +#endif + +#ifdef __AVR_ATmega328P__ + + // Arduino-Nano-5V + // --------------------------------------------------------------- + // PD4 ..... Red (inverse logic -> 0 = ON) + // PB0 ..... Green (inverse logic -> 0 = ON) + // PD7 ..... Blue (inverse logic -> 0 = ON) + + void Rgb::init () { + ledOff(RED); + ledOff(GREEN); + ledOff(BLUE); + DDRB |= (1 << PB0); + DDRD |= (1 << PD7) | (1 << PD4); + } + + void Rgb::cleanup () { + ledOff(RED); + ledOff(GREEN); + ledOff(BLUE); + DDRB &= ~(1 << PB0); + DDRD &= ~((1 << PD7) | (1 << PD4)); + } + + void Rgb::setLed (LED led, bool on) { + if (on) { + switch (led) { + case RED: PORTD &= ~(1 << PD4); break; + case GREEN: PORTB &= ~(1 << PB0); break; + case BLUE: PORTD &= ~(1 << PD7); break; + } + } else { + switch (led) { + case RED: PORTD |= (1 << PD4); break; + case GREEN: PORTB |= (1 << PB0); break; + case BLUE: PORTD |= (1 << PD7); break; + } + } + } + + void Rgb::ledToggle (LED led) { + switch (led) { + case RED: PORTD ^= (1 << PD4); break; + case GREEN: PORTB ^= ~(1 << PB0); break; + case BLUE: PORTD ^= (1 << PD7); break; + } + } + +#endif + +void Rgb::ledOn (LED led) { + setLed(led, true); +} + +void Rgb::ledOff (LED led) { + setLed(led, false); } int8_t Rgb::run (uint8_t subtest) { switch (subtest) { case 0: { - DDRB |= (1 << DDB2) | (1 << DDB1) | (1 << DDB0); - PORTB |= (1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0); // all OFF - printf_P(PSTR("init")); - return 0; - } - - case 1: { - PORTB &= ~(1 << PORTB0); // ON + ledOn(RED); printf_P(PSTR("Red")); - wait(2000); + wait(3000); + ledOff(RED); return 0; } - case 2: { - PORTB |= (1 << PORTB0); - PORTB &= ~(1 << PORTB1); // ON + case 1: { + ledOn(GREEN); printf_P(PSTR("Green")); - wait(2000); + wait(3000); + ledOff(GREEN); return 0; } - case 3: { - PORTB |= (1 << PORTB1); - PORTB &= ~(1 << PORTB2); // ON + case 2: { + ledOn(BLUE); printf_P(PSTR("Blue")); - wait(2000); + wait(3000); + ledOff(BLUE); return 0; } - case 4: { - PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0)); + case 3: { + ledOn(RED); ledOn(GREEN); ledOn(BLUE); printf_P(PSTR("All")); - wait(2000); + wait(3000); + ledOff(RED); ledOff(GREEN); ledOff(BLUE); return 0; } - - case 5: { - printf_P(PSTR("end")); - break; - } } return -1; diff --git a/software/nano-644/test_2024-07-23/src/units/rgb.hpp b/software/nano-644/test_2024-07-23/src/units/rgb.hpp index cb5641d..12e9da4 100644 --- a/software/nano-644/test_2024-07-23/src/units/rgb.hpp +++ b/software/nano-644/test_2024-07-23/src/units/rgb.hpp @@ -6,11 +6,20 @@ #include class Rgb : public TestUnit { + public: + enum LED { RED, GREEN, BLUE }; + public: Rgb () {}; + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Rgb"); } + + void setLed (LED led, bool on); + void ledOn (LED led); + void ledOff (LED led); + void ledToggle (LED led); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/seg7.cpp b/software/nano-644/test_2024-07-23/src/units/seg7.cpp index 6ca477e..d7d8c05 100644 --- a/software/nano-644/test_2024-07-23/src/units/seg7.cpp +++ b/software/nano-644/test_2024-07-23/src/units/seg7.cpp @@ -4,89 +4,187 @@ #include "seg7.hpp" #include "../main.hpp" -// 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 +#ifdef __AVR_ATmega644P__ + + // Nano-644 + // --------------------------------------------------------------- + + // 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 + +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); + } + + 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)); + } + + void Seg7::setAnodes (uint16_t a) { + if (a & 0x0001) PORTB |= (1 << PB0); else PORTB &= ~(1 << PB0); // Anode Char A + if (a & 0x0002) PORTB |= (1 << PB1); else PORTB &= ~(1 << PB1); // Anode Char B + if (a & 0x0004) PORTB |= (1 << PB2); else PORTB &= ~(1 << PB2); // Anode Char C + if (a & 0x0008) PORTB |= (1 << PB3); else PORTB &= ~(1 << PB3); // Anode Char D + if (a & 0x0010) PORTB |= (1 << PB4); else PORTB &= ~(1 << PB4); // Anode Char E + 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 + } + + 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) + } + + void Seg7::setOE (bool enabled) { + if (enabled) { + PORTD &= ~(1 << PD5); + } else { + PORTD |= (1 << PD5); + } + } + +#endif + +#ifdef __AVR_ATmega328P__ + + // Arduino-Nano-5V + // --------------------------------------------------------------- + + // PC0 ... Cathode Char 1 + // PC1 ... Cathode Char 2 + // PC2 ... Cathode Char 3 + // PC3 ... Cathode Char 4 + + // 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); + + } + + void Seg7::cleanup () { + 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)); + } + + void Seg7::setAnodes (uint16_t a) { + if (a & 0x0001) PORTD |= (1 << PD4); else PORTD &= ~(1 << PD4); // Anode Char A + if (a & 0x0002) PORTB |= (1 << PB0); else PORTB &= ~(1 << PB0); // Anode Char B + if (a & 0x0004) PORTD |= (1 << PD7); else PORTD &= ~(1 << PD7); // Anode Char C + if (a & 0x0008) PORTD |= (1 << PD6); else PORTD &= ~(1 << PD6); // Anode Char D + if (a & 0x0010) PORTB |= (1 << PB2); else PORTB &= ~(1 << PB2); // Anode Char E + 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 + } + + 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) + } + + void Seg7::setOE (bool enabled) { + if (enabled) { + PORTB &= ~(1 << PB1); + } else { + PORTB |= (1 << PB1); + } + } + +#endif const char *segName[] = { "A", "B", "C", "D", "E", "F", "G", "DP" }; -void Seg7::cleanup () { - PORTA &= ~((1 < %02x"), chIndex, segName[segIndex], (1 << segIndex)); wait(400); return 0; - - } else { - printf_P(PSTR("end")); } return -1; diff --git a/software/nano-644/test_2024-07-23/src/units/seg7.hpp b/software/nano-644/test_2024-07-23/src/units/seg7.hpp index 70c1084..0e71fde 100644 --- a/software/nano-644/test_2024-07-23/src/units/seg7.hpp +++ b/software/nano-644/test_2024-07-23/src/units/seg7.hpp @@ -7,10 +7,19 @@ class Seg7 : public TestUnit { public: - Seg7 () {}; + bool enabled; + + public: + Seg7 () { enabled = false; } + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Seg7"); } + + private: + void setAnodes (uint16_t); + void setCathodes (uint8_t mask); + void setOE (bool enabled); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/switch.cpp b/software/nano-644/test_2024-07-23/src/units/switch.cpp index 9f738e5..45866a4 100644 --- a/software/nano-644/test_2024-07-23/src/units/switch.cpp +++ b/software/nano-644/test_2024-07-23/src/units/switch.cpp @@ -5,42 +5,91 @@ #include "switch.hpp" #include "../main.hpp" -void Switch::cleanup () { - PORTA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0)); -} +#ifdef __AVR_ATmega644P__ + // Nano-644 + // --------------------------------------------------------------- + // PA0 ..... SW1 + // PA1 ..... SW2 + // PA2 ..... SW3 + // PA3 ..... SW4 -int8_t Switch::run (uint8_t subtest) { - if (subtest == 0) { - DDRA &= ~((1 << DDA3) | (1 << DDA2) | (1 << DDA1) | (1 << DDA0)); - // enable internal pullup resistor + void Switch::init () { + DDRA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0)); PORTA |= (1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0); - wait(10); - return 0; + } - } else if (subtest <= 17) { - uint8_t bit = (subtest - 1) / 4; - switch ((subtest - 1) % 4) { - case 0: case 2: { - if ((PINA & (1 << bit)) == 0) { - printf_P(PSTR("Release SW%d (PA%d) "), bit + 1, bit); - while ((PINA & (1 << bit)) == 0 && wait(0) == EOF) {} + void Switch::cleanup () { + PORTA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0)); + DDRA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0)); + } + + bool Switch::isPressed (SWITCH sw) { + switch (sw) { + case SW1: return (PINA & ( 1 << PA0)) == 0; + case SW2: return (PINA & ( 1 << PA1)) == 0; + case SW3: return (PINA & ( 1 << PA2)) == 0; + case SW4: return (PINA & ( 1 << PA3)) == 0; + default: return false; + } + } + +#endif + +#ifdef __AVR_ATmega328P__ + + // Arduino-Nano-5V + // --------------------------------------------------------------- + // PC0 ..... SW1 + // PC1 ..... SW2 + // PC2 ..... SW3 + // PC3 ..... SW4 + + void Switch::init () { + DDRC &= ~((1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0)); + PORTC |= (1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0); + } + + void Switch::cleanup () { + PORTC &= ~((1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0)); + DDRC &= ~((1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0)); + } + + bool Switch::isPressed (SWITCH sw) { + switch (sw) { + case SW1: return (PINC & ( 1 << PC0)) == 0; + case SW2: return (PINC & ( 1 << PC1)) == 0; + case SW3: return (PINC & ( 1 << PC2)) == 0; + case SW4: return (PINC & ( 1 << PC3)) == 0; + default: return false; + } + } + +#endif + +int8_t Switch::run (uint8_t subtest) { + if (subtest < 16) { + SWITCH sw = (SWITCH)(subtest / 4); + switch (subtest % 4) { + case 1: { + if (!isPressed(sw)) { + printf_P(PSTR("Press SW%d"), sw + 1); + while (!isPressed(sw) && wait(0) == EOF) {} wait(10); } return 0; } - case 1: { - if ((PINA & (1 << bit)) != 0) { - printf_P(PSTR("Press SW%d (PA%d) "), bit + 1, bit); - while ((PINA & (1 << bit)) != 0 && wait(0) == EOF) {} + case 0: case 2: { + if (isPressed(sw)) { + printf_P(PSTR("Release SW%d "), sw + 1); + while (isPressed(sw) && wait(0) == EOF) {} wait(10); } return 0; } case 3: { - printf_P(PSTR("end")); return 0; } } diff --git a/software/nano-644/test_2024-07-23/src/units/switch.hpp b/software/nano-644/test_2024-07-23/src/units/switch.hpp index a4caf2f..03bf0b2 100644 --- a/software/nano-644/test_2024-07-23/src/units/switch.hpp +++ b/software/nano-644/test_2024-07-23/src/units/switch.hpp @@ -6,11 +6,15 @@ #include class Switch : public TestUnit { + typedef enum { SW1 = 0, SW2 = 1, SW3 = 2, SW4 = 3 } SWITCH; + public: Switch () {}; - virtual void cleanup (); + virtual void init (); + virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Switch"); } + bool isPressed (SWITCH sw); }; #endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/uart1.cpp b/software/nano-644/test_2024-07-23/src/units/uart1.cpp index 02f411e..d813648 100644 --- a/software/nano-644/test_2024-07-23/src/units/uart1.cpp +++ b/software/nano-644/test_2024-07-23/src/units/uart1.cpp @@ -5,6 +5,15 @@ #include "uart1.hpp" #include "../main.hpp" +#ifdef __AVR_ATmega328P__ + void Uart1::init () {} + void Uart1::cleanup () {} + int8_t Uart1::run (uint8_t subtest) { return -1; } + void Uart1::handleRxByte (uint8_t b) {} +#endif + +#ifdef __AVR_ATmega644P__ + int uart1_putchar(char c, FILE *stream) { if (c == '\n') { uart1_putchar('\r', stream); @@ -16,6 +25,17 @@ int uart1_putchar(char c, FILE *stream) { static FILE mystderr = { 0, 0, _FDEV_SETUP_WRITE , 0, 0, uart1_putchar, NULL, 0 }; +void Uart1::init () { + PORTD |= (1 << PD2); // enable RxD1 pullup + UCSR1A = (1 << U2X1); + UCSR1B = (1 << RXCIE1) | (1 << RXEN1) | (1 < send text via UART1 now...")); fprintf_P(stderr, PSTR("Hello UART1, ECHO-Modus active\n")); } while (wait(5000) == EOF); - - } else { - printf_P(PSTR("end")); - return -1; + return 0; } - wait(500); - return 0; + + return -1; } void Uart1::handleRxByte (uint8_t b) { uart1_putchar(b, stderr); } + +#endif \ No newline at end of file diff --git a/software/nano-644/test_2024-07-23/src/units/uart1.hpp b/software/nano-644/test_2024-07-23/src/units/uart1.hpp index 16b6425..40437e1 100644 --- a/software/nano-644/test_2024-07-23/src/units/uart1.hpp +++ b/software/nano-644/test_2024-07-23/src/units/uart1.hpp @@ -11,6 +11,7 @@ class Uart1 : public TestUnit { public: Uart1 () { enabled = 0; } + virtual void init (); virtual void cleanup (); virtual int8_t run (uint8_t subtest); virtual PGM_P getName () { return PSTR("Uart1"); } -- 2.39.5