gdb: sim/$(NAME).elf
avr-gdb $<
+isp:
+ avrdude -c usbasp -p m644p
+
isp-flash: dist/$(NAME).elf all
avrdude -c usbasp -p m644p -e -U flash:w:$<
# picocom sends CR for ENTER -> convert cr (\r) to lf (\n)
picocom -b 115200 --omap crlf /dev/ttyUSB0
-fuse:
- avrdude -c usbasp -p m644p -U lfuse:w:0xEE:m -U hfuse:w:0xD9:m -U efuse:w:0xFF:m
+isp-fuse:
+ 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:
@rm -r dist
#include "units/switch.hpp"
#include "units/rgb.hpp"
#include "units/seg7.hpp"
+#include "units/poti.hpp"
+#include "units/encoder.hpp"
extern "C" {
void __cxa_pure_virtual () {
static volatile uint32_t timer1ms = 0;
static volatile int keyUart0 = EOF;
+
+ Led led;
+ Switch sw;
+ Rgb rgb;
+ Seg7 seg7;
+ Poti poti;
+ Encoder encoder;
+
}
void setTimer (uint32_t ms) {
int main () {
-
+
// Nano-644 LEDs (Green, Orange, Red)
DDRC |= (1 << DDC4) | (1 << DDC3) | (1 << DDC2);
PORTC &= ~((1 << PORT4) | (1 << PORT3) | (1 << PORT2));
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);
+ TCCR2A = (1 << WGM21);
+ TCCR2B = (1 << CS21); // CTC, F_CPU/8=1.5MHz
+ OCR2A = 150; // 150/1.5E6 = 0.1ms
+ TIMSK2 = (1 << OCIE2A);
stdout = &mystdout;
stderr = &mystderr;
printf("\n\nTEST Nano-X-Base\n");
printf("======================================");
-
- Led led;
- Switch sw;
- Rgb rgb;
- Seg7 seg7;
- TestUnit *unit[] = { &led, &sw, &rgb, &seg7 };
+
+ TestUnit *unit[] = { &led, &sw, &rgb, &seg7, &poti, &encoder };
for (uint8_t i = 0; i < sizeof(unit) / sizeof(unit[0]); i++) {
TestUnit *pu = unit[i];
keyUart0 = b;
}
-ISR (TIMER1_COMPA_vect) {
- if (timer1ms > 0) {
- timer1ms--;
+ISR (TIMER2_COMPA_vect) { // every 100us
+ static uint16_t timer500ms = 0;
+ static uint8_t timer100us = 0;
+
+ timer100us++;
+ encoder.tick100us();
+ if (timer100us >= 10) {
+ timer100us = 0;
+ if (timer1ms > 0) {
+ timer1ms--;
+ }
+ }
+
+ timer500ms++;
+ if (timer500ms >= 5000) {
+ PORTC ^= (1 << PORTC3); // orange LED blinking
+ timer500ms = 0;
}
}
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+
+#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 -------___-----
+// one step when: A = 0, B= 1->0
+
+// Encoder signals on rotation counterclockwise 1 step:
+// A -----____------ one char app. 1ms..2ms (rotation speed)
+// B --______-----
+// one step when: A = 0, B= 0->1
+
+
+void Encoder::cleanup () {
+ DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0));
+ PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0));
+}
+
+int8_t Encoder::run (uint8_t subtest) {
+ switch (subtest) {
+ case 0: {
+ printf("init");
+ DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0));
+ PORTB |= (1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0); // enable pullup
+ return 0;
+ }
+
+ case 1: {
+ while (wait(10) == EOF) {
+ printf("\r => Encoder (push to clear): ");
+ printf("%5d (0x%02x) ", count, (uint8_t)count);
+ if ((PINB & (1 << PINB2)) == 0) {
+ reset();
+ }
+ }
+ return 0;
+ }
+
+ case 2: {
+ printf("\r => Encoder end%30s", " ");
+ break;
+ }
+ }
+
+ return -1;
+}
+
+struct EncoderState {
+ uint8_t a:1; // signal A
+ uint8_t b:1; // signal B
+};
+
+void Encoder::tick100us () {
+ static EncoderState lastState = { 1, 1 };;
+ static EncoderState lastStableState = { 1, 1 };
+
+ if ((DDRB & 0x03) || (PORTB & 0x07) != 0x07) {
+ count = 0;
+ return; // Enocder pins not configured
+ }
+ EncoderState nextState = { (PINB & 0x01) == 0x01, (PINB & 0x02) == 0x02 };
+ if (nextState.a == lastState.a && nextState.b == lastState.b) {
+ if (lastStableState.a == 0 && nextState.b != lastStableState.b) {
+ if (nextState.b == 0) {
+ count = count < 127 ? count + 1 : 127;
+ } else {
+ count = count > -128 ? count - 1 : -128;
+ }
+ }
+ lastStableState.a = nextState.a;
+ lastStableState.b = nextState.b;
+ }
+ lastState.a = nextState.a;
+ lastState.b = nextState.b;
+}
+
--- /dev/null
+#ifndef ENCODER_HPP
+#define ENCODER_PP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+
+class Encoder : public TestUnit {
+ public:
+ int8_t count;
+
+ public:
+ Encoder () { reset(); };
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "Encoder"; }
+ void reset () { count = 0; }
+ void tick100us ();
+};
+
+#endif
\ No newline at end of file
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+
+#include "poti.hpp"
+#include "../main.hpp"
+
+void Poti::cleanup () {
+ ADMUX = 0;
+ ADCSRA = 0;
+}
+
+int8_t Poti::run (uint8_t subtest) {
+ switch (subtest) {
+ case 0: {
+ printf("init");
+ ADMUX = (1 << REFS0); // ADC0, VREF=AVCC=3.3V
+ ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
+ return 0;
+ }
+
+ case 1: {
+ printf("\n");
+ while (wait(10) == EOF) {
+ printf("\r => Measure ADC0: ");
+ ADCSRA |= (1 << ADSC); // start ADC
+ while (ADCSRA & (1 << ADSC)) {} // wait for result
+ printf("%4d (0x%03x)", ADC, ADC);
+ }
+ return 0;
+ }
+
+ case 2: {
+ printf("\r => ADC end%20s", " ");
+ break;
+ }
+ }
+
+ return -1;
+}
+
+
--- /dev/null
+#ifndef POTI_HPP
+#define POTI_PP
+
+#include <stdint.h>
+#include "../main.hpp"
+
+class Poti : public TestUnit {
+ public:
+ Poti () {};
+ virtual void cleanup ();
+ virtual int8_t run (uint8_t subtest);
+ virtual const char *getName () { return "Poti"; }
+};
+
+#endif
\ No newline at end of file
wait(400);
return 0;
+ } else {
+ printf("end");
}
return -1;