Subversion Repositories group.electronics

Rev

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--;
        }
}