2013-08-26 20:39:15 +02:00
|
|
|
#include <pentabug/hal.h>
|
|
|
|
|
|
|
|
#include <avr/io.h>
|
|
|
|
#include <avr/interrupt.h>
|
|
|
|
|
|
|
|
#include <pentabug/lifecycle.h>
|
|
|
|
|
|
|
|
#include <pentabug/timer.h>
|
|
|
|
|
2013-08-29 19:14:30 +02:00
|
|
|
static volatile uint8_t ir_active = 0;
|
|
|
|
static volatile int16_t wait_time = 0;
|
2013-08-26 20:39:15 +02:00
|
|
|
|
2013-09-05 21:56:20 +02:00
|
|
|
static uint8_t timerdivider;
|
|
|
|
|
2013-09-05 01:27:52 +02:00
|
|
|
static uint8_t button_count[2];
|
2013-08-29 20:56:43 +02:00
|
|
|
static uint8_t button_pressed[2];
|
2013-08-26 20:39:15 +02:00
|
|
|
|
2013-09-05 01:27:52 +02:00
|
|
|
// interrupt for button handling, every 10ms
|
2013-09-05 21:56:20 +02:00
|
|
|
ISR(TIMER2_COMPA_vect,ISR_NOBLOCK) {
|
2013-08-26 20:39:15 +02:00
|
|
|
uint8_t i = 0;
|
|
|
|
|
|
|
|
for(i = 0; i < 2; ++i) {
|
2013-08-30 17:23:38 +02:00
|
|
|
// button pressed?
|
2013-08-26 20:39:15 +02:00
|
|
|
if(PINB & (1 << i)) {
|
2013-08-30 17:23:38 +02:00
|
|
|
// pressed for more than 50ms is a click
|
2013-09-05 01:27:52 +02:00
|
|
|
if(button_count[i] > 5 && button_count[i] < 100) {
|
2013-08-29 20:56:43 +02:00
|
|
|
button_pressed[i] = 1;
|
|
|
|
}
|
|
|
|
|
2013-08-30 17:23:38 +02:00
|
|
|
// not pressed, reset
|
2013-08-26 20:39:15 +02:00
|
|
|
button_count[i] = 0;
|
|
|
|
} else {
|
2013-08-30 17:23:38 +02:00
|
|
|
//.count time pressed
|
2013-08-26 20:39:15 +02:00
|
|
|
++button_count[i];
|
|
|
|
}
|
|
|
|
|
2013-08-30 17:23:38 +02:00
|
|
|
// 1s pressed, request next app
|
2013-09-05 01:27:52 +02:00
|
|
|
if(button_count[i] == 100) {
|
2013-08-26 20:39:15 +02:00
|
|
|
next_app(i ? 1 : -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ISR(TIMER0_COMPA_vect) {
|
2013-09-05 21:56:20 +02:00
|
|
|
// (2*38)kHz ISR
|
|
|
|
//generate 38kHz signal:
|
2013-08-26 20:39:15 +02:00
|
|
|
if(ir_active) {
|
|
|
|
PORTD ^= 1 << 2;
|
|
|
|
}
|
2013-09-05 21:56:20 +02:00
|
|
|
timerdivider ++;
|
|
|
|
|
|
|
|
//quaterdivider for wait_ms
|
|
|
|
if(!(timerdivider & 0x03)) {
|
2013-09-05 23:06:13 +02:00
|
|
|
--wait_time;
|
2013-09-05 21:56:20 +02:00
|
|
|
}
|
2013-08-26 20:39:15 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-09-05 23:06:13 +02:00
|
|
|
#if 0
|
|
|
|
pinchangeportisr(ireingangport)
|
|
|
|
{
|
|
|
|
if pinchanged is ir input:
|
|
|
|
if ir inactive
|
|
|
|
irrstate = IRR_IDLE
|
|
|
|
return
|
|
|
|
time_since_last = timedivider - oldtime //2d handle overflow
|
|
|
|
|
|
|
|
//State machine:
|
|
|
|
select (irrstate){
|
|
|
|
case ( IRR_IDLE):
|
|
|
|
irrstate = IRR_AWAIT_START_COMP;
|
|
|
|
…
|
|
|
|
break;
|
|
|
|
case (IRR_AWAIT_START_COMP):
|
|
|
|
//check for transition in time
|
|
|
|
if (time_since_last > IR_MAX_STARTBIT_TICKS)
|
|
|
|
{
|
|
|
|
irrstate = IRR_GET_BIT_FIRSTHALF;
|
|
|
|
bitnum = 0;
|
|
|
|
} else { irrstate = IRR_IDLE // errorreset}
|
|
|
|
break;
|
|
|
|
case (IRR_GET_BIT_FIRSTHALF)
|
|
|
|
//check beeing in time
|
|
|
|
// -> buffer bit[bitnum]
|
|
|
|
// else reset
|
|
|
|
irrstate = IRR_GET_BIT_SECHALF;
|
|
|
|
break;
|
|
|
|
case (IRR_GET_BIT_SECHALF)
|
|
|
|
//check beeing in time
|
|
|
|
// -> inc bitnum
|
|
|
|
// -> irrstate = (maxbits)?IRR_GET_STOP_COND:IRR_GET_BIT_FIRSTHALF;
|
|
|
|
// else reset
|
|
|
|
…
|
|
|
|
break;
|
|
|
|
case (IRR_GET_STOP_COND):
|
|
|
|
//check beeing in time <- need macro for this :-)
|
|
|
|
//-> mark received done and set ir inactive (mainloop has to poll done or idle loop callback registration?)
|
|
|
|
//-> else reset
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2013-08-26 20:39:15 +02:00
|
|
|
void init_hw(void) {
|
|
|
|
// we need to get real fast (8MHz) to handle 38kHz IR frequency ...
|
|
|
|
|
|
|
|
CLKPR = 0b10000000;
|
|
|
|
CLKPR = 0b00000000;
|
|
|
|
|
2013-09-05 01:18:57 +02:00
|
|
|
// IR timer
|
2013-08-26 20:39:15 +02:00
|
|
|
|
|
|
|
TIMSK0 |= (1 << OCIE0A);
|
|
|
|
|
|
|
|
// calculated and works, but frequency is a little bit off?
|
|
|
|
OCR0A = 105;
|
|
|
|
|
|
|
|
TCCR0A = (1 << WGM01);
|
|
|
|
TCCR0B = (1 << CS00);
|
|
|
|
|
2013-09-05 01:18:57 +02:00
|
|
|
// button timer
|
|
|
|
|
|
|
|
TIMSK2 |= (1 << OCIE2A);
|
|
|
|
|
2013-09-05 01:27:52 +02:00
|
|
|
OCR2A = 70;
|
2013-09-05 01:18:57 +02:00
|
|
|
|
|
|
|
TCCR2A = (1 << WGM01);
|
|
|
|
TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20);
|
|
|
|
|
2013-08-30 17:23:38 +02:00
|
|
|
// activate interrupts
|
|
|
|
|
2013-08-26 20:39:15 +02:00
|
|
|
sei();
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset_hw(void) {
|
|
|
|
stop_timer();
|
|
|
|
|
|
|
|
// 0: S1
|
|
|
|
// 1: S2
|
2013-08-29 21:16:35 +02:00
|
|
|
// 6: MOTOR
|
2013-08-26 20:39:15 +02:00
|
|
|
// 7: BUZZR
|
|
|
|
PORTB = (1 << 0) | (1 << 1) | (1 << 7);
|
2013-08-29 21:16:35 +02:00
|
|
|
DDRB = (1 << 6) | (1 << 7);
|
2013-08-26 20:39:15 +02:00
|
|
|
|
|
|
|
// 0: BUZGND
|
|
|
|
// 2: LED2
|
|
|
|
// 3: LED2 (+)
|
|
|
|
PORTC = (1 << 2) | (1 << 3);
|
|
|
|
DDRC = (1 << 0) | (1 << 2) | (1 << 3);
|
|
|
|
|
2013-08-30 21:43:50 +02:00
|
|
|
// 2: IRSEND
|
|
|
|
// 3: IRRECV
|
2013-08-26 20:39:15 +02:00
|
|
|
// 4: LED
|
|
|
|
PORTD = (1 << 4);
|
|
|
|
DDRD = (1 << 2) | (1 << 4);
|
2013-08-29 20:56:43 +02:00
|
|
|
|
|
|
|
// do not carry button state
|
|
|
|
|
|
|
|
button_pressed[0] = 0;
|
|
|
|
button_pressed[1] = 0;
|
2013-08-30 21:43:50 +02:00
|
|
|
|
|
|
|
// turn ir off
|
|
|
|
|
|
|
|
ir_off();
|
2013-08-31 22:26:26 +02:00
|
|
|
|
|
|
|
// disable adc
|
|
|
|
|
|
|
|
ADCSRA &= ~(1 << ADEN);
|
2013-08-29 20:56:43 +02:00
|
|
|
}
|
|
|
|
|
2013-08-29 23:07:17 +02:00
|
|
|
uint8_t button_state(uint8_t btn) {
|
|
|
|
return !(PINB & (1 << btn));
|
|
|
|
}
|
|
|
|
|
2013-08-29 20:56:43 +02:00
|
|
|
uint8_t button_clicked(uint8_t btn) {
|
|
|
|
uint8_t clicked = button_pressed[btn];
|
|
|
|
button_pressed[btn] = 0;
|
|
|
|
return clicked;
|
|
|
|
}
|
|
|
|
|
|
|
|
void button_reset(uint8_t btn) {
|
|
|
|
button_pressed[btn] = 0;
|
2013-08-26 20:39:15 +02:00
|
|
|
}
|
|
|
|
|
2013-08-29 23:07:17 +02:00
|
|
|
void led_set(uint8_t led, uint8_t state) {
|
|
|
|
if(state) {
|
|
|
|
led_on(led);
|
|
|
|
} else {
|
|
|
|
led_off(led);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-27 00:54:30 +02:00
|
|
|
void led_on(uint8_t led) {
|
|
|
|
if(led == RIGHT) {
|
|
|
|
PORTC &= ~(1 << 2);
|
|
|
|
} else {
|
|
|
|
PORTD &= ~(1 << 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void led_off(uint8_t led) {
|
|
|
|
if(led == RIGHT) {
|
|
|
|
PORTC |= 1 << 2;
|
|
|
|
} else {
|
|
|
|
PORTD |= 1 << 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void led_inv(uint8_t led) {
|
|
|
|
if(led == RIGHT) {
|
|
|
|
PORTC ^= 1 << 2;
|
|
|
|
} else {
|
|
|
|
PORTD ^= 1 << 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-09-03 21:25:07 +02:00
|
|
|
uint8_t led_state(uint8_t led) {
|
|
|
|
if(led == RIGHT) {
|
|
|
|
return !(PORTC & (1 << 2));
|
|
|
|
} else {
|
|
|
|
return !(PORTD & (1 << 4));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-29 23:07:17 +02:00
|
|
|
void motor_set(uint8_t state) {
|
|
|
|
if(state) {
|
|
|
|
motor_on();
|
|
|
|
} else {
|
|
|
|
motor_off();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-29 19:14:30 +02:00
|
|
|
void motor_on(void) {
|
|
|
|
PORTB |= 1 << 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
void motor_off(void) {
|
|
|
|
PORTB &= ~(1 << 6);
|
|
|
|
}
|
|
|
|
|
2013-08-29 20:56:43 +02:00
|
|
|
void motor_inv(void) {
|
|
|
|
PORTB ^= 1 << 6;
|
|
|
|
}
|
|
|
|
|
2013-08-30 17:23:38 +02:00
|
|
|
void buzzer_up(void) {
|
|
|
|
PORTB |= 1 << 7;
|
|
|
|
PORTC &= ~(1 << 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void buzzer_down(void) {
|
|
|
|
PORTB &= ~(1 << 7);
|
|
|
|
PORTC |= 1 << 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void buzzer_inv(void) {
|
|
|
|
PORTB ^= 1 << 7;
|
|
|
|
PORTC ^= 1 << 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void buzzer_off(void) {
|
|
|
|
PORTB &= ~(1 << 7);
|
|
|
|
PORTC &= ~(1 << 0);
|
|
|
|
}
|
|
|
|
|
2013-08-29 19:14:30 +02:00
|
|
|
|
2013-09-05 21:56:20 +02:00
|
|
|
// uses the 76k ISR dividet by 4 -> 4 * 19 == 76
|
|
|
|
void wait_ms(uint16_t ms) {
|
|
|
|
wait_time = ms * (int16_t) 19;
|
2013-08-29 19:14:30 +02:00
|
|
|
while(wait_time > 0) {
|
|
|
|
test_stop_app();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-31 14:17:24 +02:00
|
|
|
void wait_ticks(int16_t ticks) {
|
|
|
|
wait_time = ticks;
|
|
|
|
|
|
|
|
while(wait_time > 0) {
|
|
|
|
test_stop_app();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-30 21:43:50 +02:00
|
|
|
void ir_on(void) {
|
|
|
|
ir_active = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ir_off(void) {
|
|
|
|
ir_active = 0;
|
|
|
|
PORTD &= ~(1 << 2);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ir_inv(void) {
|
|
|
|
if(ir_active) {
|
|
|
|
ir_off();
|
|
|
|
} else {
|
|
|
|
ir_on();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ir_set(uint8_t state) {
|
|
|
|
if(state) {
|
|
|
|
ir_on();
|
|
|
|
} else {
|
|
|
|
ir_off();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ir_recv(void) {
|
|
|
|
return !(PIND & (1 << 3));
|
|
|
|
}
|
|
|
|
|