Rev 128 | Blame | Compare with Previous | Last modification | View Log | RSS feed
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/interrupt.h>
#include <string.h>
#include <util/delay.h>
#include <stdlib.h>
#include "avrutil.h"
#include "wire.h"
#include "lcd.h"
#include "config.h"
#include "uart.h"
#include "lmd.h"
#ifndef NULL
#define NULL ((void *)0)
#endif
/* ------------------------------------------------------------------------- */
#define LCD_SEND_DELAY 80
#define OLED_SEND_DELAY 500
#define OLED_LCDWIDTH 128
#define OLED_LCDHEIGHT 64
#define UART_BAUD_RATE 9600
volatile uint8_t lcdTimer = LCD_SEND_DELAY;
volatile uint16_t oledTimer = OLED_SEND_DELAY;
volatile uint8_t tmr0_ovf = 0;
char display[10];
volatile struct {
uint8_t current;
uint8_t last;
uint8_t mask;
} pcInt[3];
volatile struct {
int8_t outer;
int8_t inner;
} input;
volatile uint8_t doInt = 0;
void pcInterrupt(uint8_t pcint);
int main(void) {
/*
DDR : 1 = Output, 0 = Input
PORT: 1 = Pullup for Input, otherwise set output
PIN : Read input pin
*/
/*
PB0 -
PB1 -
PB2 -
PB3 -
PB4 -
PB5 -
PB6 -
PB7 -
*/
DDRB = 0B00000111;
PORTB = 0B00000000;
/*
PC0 -
PC1 -
PC2 -
PC3 -
PC4 -
PC5 -
*/
DDRC = 0B00000000;
PORTC = 0B00001111;
/*
PD0 -
PD1 -
PD2 -
PD3 -
PD4 -
PD5 - Input PcInt - * I/O Interrupt PCINT21
PD6 - Output - * Status LED
PD7 - Input, Pullup - * Button
*/
DDRD = 0B01000000;
PORTD = 0B10000000;
PCMSK1 |= (( 1 << PCINT8 ) | ( 1 << PCINT9 )| ( 1 << PCINT10 )| ( 1 << PCINT11 ));
PCICR |= ( 1 << PCIE1 );
pcInt[1].last = PINC;
pcInt[1].current = pcInt[1].last;
pcInt[1].mask = 0;
systime = 0;
sysclockInit();
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );
wdt_enable(WDTO_1S); // Watchdog for 1 sec
sei(); // Enable interrupts
i2c_master();
lcd_init();
sbi(PORTD, PD6);
_delay_us(100);
cbi(PORTD, PD6);
lcd_setCursor(0, 1);
lcd_print("Time:\0");
lmd_init(0x03, PB0, PB1, PB2, 2); // PORTB = 0x03, 5 digits = 0x04
// Let the MAX's settle. There's also a 200us delay inside the init
_delay_ms(200);
uint16_t comm1[2];
comm1[0] = 12010;
comm1[1] = 12190;
input.outer = 0;
input.inner = 0;
uint8_t c;
for (c=0; c<=1; c++) {
lmd_scanlimit(c, 0x04);
lmd_decodemode(c, 0xff);
lmd_dp(c, 0x04);
lmd_print_u16(c, comm1[c]);
}
for(;;){
wdt_reset();
if (doInt) {
pcInterrupt(doInt);
doInt = 0;
}
#ifdef _DEBUG_
if (!lcdTimer) {
ultoa(systime, display, 10);
lcd_overprint_right(display, 10, 6, 1);
lcdTimer = LCD_SEND_DELAY;
}
#endif
if (!oledTimer && !rbi(PIND, PD7)) {
cli();
statusLed(ON);
//swap_u16(&comm1[0], &comm1[1]);
uint16_t t = comm1[1];
comm1[1] = comm1[0];
comm1[0] = t;
_delay_ms(100);
statusLed(OFF);
sei();
oledTimer = OLED_SEND_DELAY;
lmd_print_u16(0, comm1[0]);
lmd_print_u16(1, comm1[1]);
#ifdef _DEBUG_
uart_puts("Swap: ");
utoa(systime, display, 10);
uart_puts(display);
uart_puts("\r\n");
#endif
}
if (input.inner != 0 || input.outer != 0) {
int16_t delta = 0;
if (input.inner) {
delta = (input.inner * 5);
}
if (input.outer) {
delta = (input.outer * 100);
}
input.inner = 0;
input.outer = 0;
comm1[1] += delta;
lmd_print_u16(1, comm1[1]);
}
_delay_ms(1);
}
return 0;
}
void pcInterrupt(uint8_t pcint) {
wdt_reset();
pcInt[pcint].mask = pcInt[pcint].current ^ pcInt[pcint].last;
#ifdef _DEBUG_
utoa(pcInt[pcint].last, display, 2);
uart_puts(display);
uart_puts("\r\n");
utoa(pcInt[pcint].current, display, 2);
uart_puts(display);
uart_puts("\r\n");
utoa(pcInt[pcint].mask, display, 2);
uart_puts(display);
uart_puts("\r\n");
#endif
pcInt[pcint].last = pcInt[pcint].current;
if (pcInt[pcint].mask == 0)
return;
// Check which pin caused the interrupt. If they both
// equal 0 || 1, the pin that interrupted is the direction
if ((
(rbi(pcInt[pcint].current, PCINT8) == 1 &&
rbi(pcInt[pcint].current, PCINT9) == 1) ||
(rbi(pcInt[pcint].current, PCINT8) == 0 &&
rbi(pcInt[pcint].current, PCINT9) == 0))) {
if (rbi(pcInt[pcint].mask, PCINT8) ) {
input.outer += 1;
uart_puts("+Outer\r\n");
} else if (rbi(pcInt[pcint].mask, PCINT9) ) {
input.outer -= 1;
uart_puts("-Outer\r\n");
}
}
if ((
(rbi(pcInt[pcint].current, PCINT10) == 1 &&
rbi(pcInt[pcint].current, PCINT11) == 1) ||
(rbi(pcInt[pcint].current, PCINT10) == 0 &&
rbi(pcInt[pcint].current, PCINT11) == 0))) {
if (rbi(pcInt[pcint].mask, PCINT10) ) {
input.inner += 1;
uart_puts("+Inner\r\n");
} else if (rbi(pcInt[pcint].mask, PCINT11) ) {
input.inner -= 1;
uart_puts("-Inner\r\n");
}
}
// Clear the mask so we know we've dealt with it
pcInt[pcint].mask = 0;
}
ISR(PCINT1_vect) {
pcInt[1].current = PINC;
if (!doInt) {
doInt = 1;
}
}
ISR(TIMER0_OVF_vect) {
tmr0_ovf++;
// Clk/1 TCCR0B = (1<< CS00);
//20.0Mhz, 1ms = 78ovf
//16.5Mhz, 1ms = 64ovf
//16.0Mhz, 1ms = 62ovf
//12.0Mhz, 1ms = 46ovf
if (tmr0_ovf>=64) {
systime++;
tmr0_ovf = 0;
if (lcdTimer)
lcdTimer--;
if (oledTimer)
oledTimer--;
}
}