### Bestückung
-Keine
-
| Reference | Beschreibung |
| -------------- | ---------------------------------------------------------- |
-| D5 | JLCPCB plugin, Rotation um 90° |
-| U12 | JLCPCB plugin, Rotation um 180° |
+| D5 | JLCPCB plugin, Rotation um 90° |
+| U12 | JLCPCB plugin, Rotation um 180° |
+| R16 | 10R -> 560R (Vorwiderstand blaueLED D4) |
+| R72 | 1K -> 3K3 (Vorwiderstand Phototransistor) |
### Funktion / Software
$(shell mkdir -p sim >/dev/null)
NAME="test_2024-07-23_nano-644"
-SRC= $(wildcard src/*.c src/*.cpp)
+SRC= $(wildcard src/*.c src/*.cpp src/*/*.cpp)
OBJ = $(SRC:src/%.c=build/%.o)
OBJ_SIM = $(SRC:src/%.c=sim/%.o)
DEVICE=atmega644p
-CC= avr-gcc
+CC= avr-g++
CFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=12000000 -c
LFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=12000000
+++ /dev/null
-#include <avr/io.h>
-#include <util/delay.h>
-#include <stdio.h>
-#include <avr/interrupt.h>
-
-int uart_putchar(char c, FILE *stream) {
- if (c == '\n') {
- uart_putchar('\r', stream);
- }
- if (stream == stdout) {
- loop_until_bit_is_set(UCSR0A, UDRE0);
- UDR0 = c;
- } else if (stream == stderr) {
- loop_until_bit_is_set(UCSR1A, UDRE1);
- UDR1 = c;
- }
- return 0;
-}
-
-static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
-static FILE mystderr = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
-
-int main () {
-
- DDRC = 0x1C;
- PORTC = 0x3C;
-
- UCSR0A = (1 << U2X0);
- UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 <<TXEN0);
- UCSR0C = (1 << UCSZ01) | ( 1<< UCSZ00);
- UBRR0H = 0;
- UBRR0L = F_CPU / 8 / 115200 - 1;
-
- UCSR1A = (1 << U2X0);
- UCSR1B = (1 << RXCIE0) | (1 << RXEN0) | (1 <<TXEN0);
- UCSR1C = (1 << UCSZ01) | ( 1<< UCSZ00);
- UBRR1H = 0;
- UBRR1L = F_CPU / 8 / 115200 - 1;
-
- stdout = &mystdout;
- stderr = &mystderr;
-
- DDRD = 0xf0; // LED D4..D1
- PORTD = 0;
-
- DDRA = 0x00; // SW PA3..PA0
- PORTA = 0x0f;
-
- // DDRB = 0xff; // 7-Segment
- // PORTB = 0xff;
-
- DDRB = 0x07; // RGB-LED
- PORTB = 0;
-
- uint16_t cnt = 0;
- while (1) {
- _delay_ms(500);
- PORTC ^= 0x1C;
- printf("%04x: PINA=0x%02x PORTD=0x%02x \n", cnt++, PINA, PORTD);
-
- PORTD ^= 0xf0;
- for (uint8_t i = 0; i < 4; i++) {
- uint8_t swPressed = (PINA & (1 << i)) == 0;
- if (swPressed) {
- fprintf(stderr, "SW%d pressed\n", i);
- PORTD |= (1 << (i + 4));
- }
- }
-
- for (uint8_t i = 0; i < 3; i++) {
- uint8_t swPressed = (PINA & (1 << i)) == 0;
- if (swPressed) {
- PORTB |= (1 << i);
- } else {
- PORTB &= ~(1 << i);
- }
- }
-
- }
-
- // TCCR1B = (1 << WGM12) | (1 << CS11);
- // OCR1A = 1500;
- // TIMSK1 = (1 << OCIE1A);
-
- // UCSR0A = (1 << U2X0);
- // UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 <<TXEN0);
- // UCSR0C = (1 << UCSZ01) | ( 1<< UCSZ00);
- // UBRR0H = 0;
- // UBRR0L = F_CPU / 8 / 115200 - 1;
-
- // UCSR1A = (1 << U2X1);
- // UCSR1B = (1 << RXCIE1) | (1 << RXEN1) | (1 <<TXEN1);
- // UCSR1C = (1 << UCSZ11) | ( 1<< UCSZ10);
- // UBRR1H = 0;
- // UBRR1L = F_CPU / 8 / 115200 - 1;
-
- // stdout = &mystdout;
- // stderr = &mystderr;
- // fromUart0[0] = 0;
- // sei();
-
- // uint16_t cnt = 0;
- // while (1) {
- // printf("%04x: Hello world%s %12s\r",
- // cnt++,
- // fromUart0,
- // (PINC & (1 << PC5)) == 0 ? "SW2 pressed" : ""
- // );
- // if ((PINC & (1 << PC5)) == 0) {
- // PORTC &= ~(1 << PC2);
- // }
- // _delay_ms(10);
- // }
-}
-
-// ISR (USART0_RX_vect) {
-// PORTC ^= (1 << PC3);
-// uint8_t b = UDR0;
-// UDR1 = b;
-// fromUart0[0] = ' ';
-// fromUart0[4] = b;
-// }
-
-// ISR (USART1_RX_vect) {
-// uint8_t b = UDR1;
-// if (b == ' ') {
-// PORTC |= (1 << PC2);
-// }
-// }
-
-
-// ISR (TIMER1_COMPA_vect) {
-// static uint16_t timer = 0;
-// timer++;
-// if (timer >= 1000) {
-// PORTC ^= (1 << PC4);
-// timer = 0;
-// }
-// }
-
--- /dev/null
+#include <avr/io.h>
+#include <util/delay.h>
+#include <stdio.h>
+#include <avr/interrupt.h>
+#include <util/atomic.h>
+
+#include "main.hpp"
+#include "units/led.hpp"
+#include "units/switch.hpp"
+#include "units/rgb.hpp"
+#include "units/seg7.hpp"
+
+extern "C" {
+ void __cxa_pure_virtual () {
+ }
+
+ int uart_putchar(char c, FILE *stream) {
+ if (c == '\n') {
+ uart_putchar('\r', stream);
+ }
+ if (stream == stdout) {
+ loop_until_bit_is_set(UCSR0A, UDRE0);
+ UDR0 = c;
+ } else if (stream == stderr) {
+ loop_until_bit_is_set(UCSR1A, UDRE1);
+ UDR1 = c;
+ }
+ return 0;
+ }
+
+ static FILE mystdout = { 0, 0, _FDEV_SETUP_WRITE , 0, 0, uart_putchar, NULL, 0 } ;
+ static FILE mystderr = { 0, 0, _FDEV_SETUP_WRITE , 0, 0, uart_putchar, NULL, 0 } ;
+
+ static volatile uint32_t timer1ms = 0;
+ static volatile int keyUart0 = EOF;
+}
+
+void setTimer (uint32_t ms) {
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ timer1ms = ms;
+ }
+}
+
+int wait (uint32_t ms) {
+ setTimer(ms);
+ do {
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ ms = timer1ms;
+ }
+ } while (ms > 0 && keyUart0 == EOF);
+ return keyUart0;
+}
+
+
+int main () {
+
+ // Nano-644 LEDs (Green, Orange, Red)
+ DDRC |= (1 << DDC4) | (1 << DDC3) | (1 << DDC2);
+ PORTC &= ~((1 << PORT4) | (1 << PORT3) | (1 << PORT2));
+
+ // Nano-644 push button SW2
+ DDRC &= ~(1 << DDC5);
+ PORTC |= (1 << PORT5); // enable internal pullup resistor
+
+ // UART0 interface on Nano-644
+ UCSR0A = (1 << U2X0);
+ UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 <<TXEN0);
+ UCSR0C = (1 << UCSZ01) | ( 1<< UCSZ00);
+ UBRR0H = 0;
+ UBRR0L = F_CPU / 8 / 115200 - 1;
+
+ TCCR1B = (1 << WGM12) | (1 << CS11); // CTC, F_CPU/8=1.5MHz
+ OCR1A = 1500; // 1500/1.5E6 = 1ms
+ TIMSK1 = (1 << OCIE1A);
+
+ stdout = &mystdout;
+ stderr = &mystderr;
+
+ sei();
+
+ printf("\n\nTEST Nano-X-Base\n");
+ printf("======================================");
+
+ Led led;
+ Switch sw;
+ Rgb rgb;
+ Seg7 seg7;
+
+ TestUnit *unit[] = { &led, &sw, &rgb, &seg7 };
+
+ for (uint8_t i = 0; i < sizeof(unit) / sizeof(unit[0]); i++) {
+ TestUnit *pu = unit[i];
+ printf("\n\n[%s]: ", pu->getName());
+ printf("Press >ESC< to skip unit, any other key to start\n");
+ wait(0xffffffff);
+ if (keyUart0 == 27) {
+ keyUart0 = EOF;
+ continue;
+ }
+ keyUart0 = EOF;
+
+ for (uint8_t subtest = 0; subtest < 0xff; subtest++) {
+ printf("\n%4d: ", subtest);
+ if (pu->run(subtest) < 0) {
+ break;
+ }
+ if (keyUart0 == 27) {
+ keyUart0 = EOF;
+ break;
+ }
+ keyUart0 = EOF;
+ }
+ pu->cleanup();
+ }
+
+ printf("\n\nTest finished. \n");
+ return 0;
+}
+
+ISR (USART0_RX_vect) {
+ uint8_t b = UDR0;
+ keyUart0 = b;
+}
+
+ISR (TIMER1_COMPA_vect) {
+ if (timer1ms > 0) {
+ timer1ms--;
+ }
+}
+
--- /dev/null
+#ifndef MAIN_HPP
+#define MAIN_HPP
+
+#include <stdint.h>
+
+#define ENTER '\r'
+#define CTRLC '\003'
+
+extern int wait (uint32_t ms);
+extern int waitOnKey (char key);
+
+class TestUnit {
+ public:
+ virtual int8_t run (uint8_t subtest) = 0;
+ virtual void cleanup () = 0;
+ virtual const char *getName () = 0;
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include "led.hpp"
+#include <stdio.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "../main.hpp"
+
+void Led::cleanup () {
+ DDRD &= ~((1 << DDD7) | (1 << DDD6) | (1 << DDD5) | (1 << DDD4));
+ PORTD &= ~((1 << PORTD7) | (1 << PORTD6) | (1 << PORTD5) | (1 << PORTD4));
+}
+
+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("init");
+
+ } else if (subtest <= 16) {
+ subtest = (subtest - 1) % 4;
+ PORTD &= ~((1 << PORTD7) | (1 << PORTD6) | (1 << PORTD5) | (1 << PORTD4));
+ PORTD |= (1 << (subtest + 4));
+ printf("Test LED PD%d", subtest + 4);
+
+ } else {
+ printf("end");
+ return -1;
+ }
+ wait(500);
+ return 0;
+}
+
--- /dev/null
+#ifndef LED_HPP
+#define LED_HPP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class Led : public TestUnit {
+ public:
+ Led () {};
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "Led"; }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+
+#include "rgb.hpp"
+#include "../main.hpp"
+
+void Rgb::cleanup () {
+ PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0));
+ DDRB &= ~((1 << DDB2) | (1 << DDB1) | (1 << DDB0));
+}
+
+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("init");
+ return 0;
+ }
+
+ case 1: {
+ PORTB &= ~(1 << PORTB0); // ON
+ printf("Red");
+ wait(2000);
+ return 0;
+ }
+
+ case 2: {
+ PORTB |= (1 << PORTB0);
+ PORTB &= ~(1 << PORTB1); // ON
+ printf("Green");
+ wait(2000);
+ return 0;
+ }
+
+ case 3: {
+ PORTB |= (1 << PORTB1);
+ PORTB &= ~(1 << PORTB2); // ON
+ printf("Blue");
+ wait(2000);
+ return 0;
+ }
+
+ case 4: {
+ PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0));
+ printf("All");
+ wait(2000);
+ return 0;
+ }
+
+ case 5: {
+ printf("end");
+ break;
+ }
+ }
+
+ return -1;
+}
+
+
--- /dev/null
+#ifndef RGB_HPP
+#define RGB_PP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class Rgb : public TestUnit {
+ public:
+ Rgb () {};
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "Rgb"; }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+
+#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
+
+const char *segName[] = { "A", "B", "C", "D", "E", "F", "G", "DP" };
+
+void Seg7::cleanup () {
+ PORTA &= ~((1 <<PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0));
+ DDRA &= ~((1 <<DDA3) | (1 << DDA2) | (1 << DDA1) | (1 << DDA0));
+ PORTD &= ~((1 <<PORTD7) | (1 << PORTD6) | (1 << PORTD5));
+ DDRD &= ~((1 <<DDD7) | (1 << DDD6) | (1 << DDD5));
+ PORTB = 0;
+ DDRB = 0;
+}
+
+int8_t Seg7::run (uint8_t subtest) {
+ if (subtest == 0) {
+ PORTA &= ~((1 <<PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0));
+ DDRA |= (1 <<DDA3) | (1 << DDA2) | (1 << DDA1) | (1 << DDA0);
+ PORTB = 0;
+ DDRB = 0xff;
+ PORTD &= ~((1 <<PORTD7) | (1 << PORTD6));
+ PORTD |= (1 << PORTD5);
+ DDRD |= (1 <<DDD7) | (1 << DDD6) | (1 << DDD5);
+ printf("init");
+ return 0;
+
+ } else if (subtest == 1) {
+ PORTA |= 0x0f; // all segment cathodes conected to GND
+ PORTB = 0xff; // all segments ON
+ PORTD |= (1 << PORTD7) | (1 << PORTD6); // L1, L2, L3 ON
+ PORTD &= ~(1 << PORTD5); // Output enable
+ printf("ON");
+ wait(2000);
+ PORTB = 0x0; // all segments OFF
+ PORTD &= ~((1 << PORTD7) | (1 << PORTD6)); // L1, L2, L3 OFF
+ return 0;
+
+ } else if (subtest == 2) {
+ printf("OFF");
+ wait(1000);
+ return 0;
+
+ } else if (subtest == 3) {
+ PORTD |= (1 << PORTD6); // L1/L2 ON
+ printf("L1/L2 ON");
+ wait(1000);
+ PORTD &= ~(1 << PORTD6); // L1/L2 OFF
+ return 0;
+
+ } else if (subtest == 4) {
+ PORTD |= (1 << PORTD7); // L3 ON
+ printf("L1/L2 ON");
+ wait(1000);
+ PORTD &= ~(1 << PORTD7); // L3 OFF
+ return 0;
+
+ } else if (subtest < (5 + 4 * 8)) {
+ uint8_t chIndex = (subtest - 5) / 8;
+ uint8_t segIndex = (subtest - 5) % 8;
+ PORTA &= ~0x0f; // all segment cathodes disconnected from GND
+ PORTA |= (1 << chIndex);
+ PORTB = (1 << segIndex);
+ printf("Char %d - %s", chIndex, segName[segIndex]);
+ wait(400);
+ return 0;
+
+ }
+
+ return -1;
+}
+
+
--- /dev/null
+#ifndef SEG7_HPP
+#define SEG7_HPP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class Seg7 : public TestUnit {
+ public:
+ Seg7 () {};
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "Seg7"; }
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+#include <util/delay.h>
+
+#include "switch.hpp"
+#include "../main.hpp"
+
+void Switch::cleanup () {
+ PORTA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0));
+}
+
+
+int8_t Switch::run (uint8_t subtest) {
+ if (subtest == 0) {
+ DDRA &= ~((1 << DDA3) | (1 << DDA2) | (1 << DDA1) | (1 << DDA0));
+ // enable internal pullup resistor
+ 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("Release SW%d (PA%d) ", bit + 1, bit);
+ while ((PINA & (1 << bit)) == 0 && wait(0) == EOF) {}
+ wait(10);
+ }
+ return 0;
+ }
+
+ case 1: {
+ if ((PINA & (1 << bit)) != 0) {
+ printf("Press SW%d (PA%d) ", bit + 1, bit);
+ while ((PINA & (1 << bit)) != 0 && wait(0) == EOF) {}
+ wait(10);
+ }
+ return 0;
+ }
+
+ case 3: {
+ printf("end");
+ return 0;
+ }
+ }
+
+ }
+
+ return -1;
+}
--- /dev/null
+#ifndef SWITCH_HPP
+#define SWITCH_HPP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class Switch : public TestUnit {
+ public:
+ Switch () {};
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "Switch"; }
+};
+
+#endif
\ No newline at end of file