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 "config.h"
#include "avrutil.h"
#include "hc595.h"
#include "twires.h"


#ifndef NULL
#define NULL    ((void *)0)
#endif


void writeSegment(uint8_t digit, uint8_t value);
void pcInterrupt(void);
void receiveEvent(uint8_t howMany);

/* ------------------------------------------------------------------------- */

#define I2C_SLAVE_ADDR  0x26
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif

volatile uint8_t tmr0_ovf = 0;
volatile struct {
        uint8_t current;
        uint8_t last;
        uint8_t mask;
} pcInt;

struct {
        int8_t outer;
        int8_t inner;
} input;

//volatile uint8_t doInt = 0;



uint8_t disVal[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
uint8_t disPt[] = {0, 0};

int main(void) {


  /*
  DDR : 1 = Output, 0 = Input
  PORT: 1 = Pullup for Input, otherwise set output
  PIN : Read input pin
  */


  /*
                PA0     - Output                                        - System LED
                PA1     - Input, Pullup                         - System button
                PA2 - N/A                                               - Reset
  */
  DDRA          = 0B00000001;
  PORTA         = 0B00000010;
  /*
        PB0     - Input, PCInt, Pullup  - Rot1a
        PB1     - Input, PCInt, Pullup  - Rot1b
        PB2     - Input, PCInt, Pullup  - Rot2a
        PB3     - Input, PCInt, Pullup  - Rot2b
        PB4     - Input, Pullup                 - Swap button
        PB5     -
        PB6     -
        PB7     -
  */
  DDRB          = 0B00000000;
  PORTB         = 0B00011111;

  /*
        PD0     -
        PD1     -
        PD2     -       Output                  - Decimal Point
        PD3     -       Output                  - 4511 blanking
        PD4     -       Output                  - HC595 DS
        PD5     -       Output                  - HC595 ST
        PD6     -       Output                  - HC595 SH
  */
  DDRD          = 0B01111100;
  PORTD         = 0B00000000;

    systime = 0;
    sysclockInit();

    PCMSK |= (( 1 << PCINT0 ) | ( 1 << PCINT1 )| ( 1 << PCINT2 )| ( 1 << PCINT3 ));
    GIMSK |= (1 << PCIE);
    //PCICR |= ( 1 << PCIE1 );

    pcInt.last = PINB;
    pcInt.current = pcInt.last;
    pcInt.mask = 0;

    twires_begin(I2C_SLAVE_ADDR);
    twires_onReceive(receiveEvent);

    wdt_enable(WDTO_1S);        // Watchdog for 1 sec
    sei();                                      // Enable interrupts

    hc595_init();
    hc595_write(0x00);

    uint32_t refresh = systime;

    sbi(PORTA, PA0);
    _delay_ms(100);
    cbi(PORTA, PA0);


    uint8_t disIdx = 0;


    for(;;){
         wdt_reset();

        /*
                if ( rbi(PINA, PA1) )
                        cbi(PORTA, PA0);
                else
                        sbi (PORTA, PA0);
                */

                if (pcInt.current != pcInt.last) {
                        pcInterrupt();
                        //doInt = 0;
                }

                if (systime > refresh) {
                        writeSegment(disIdx, disVal[disIdx]);
                        refresh = systime+2;
                        disIdx++;
                        if (disIdx > 10) disIdx = 0;
                }

                twires_stop_check();
    }
    return 0;
}

void receiveEvent(uint8_t bytes) {
        uint8_t cmd = twires_receive();
        bytes--;
        switch (cmd) {
                case (0x05): {
                                while (bytes--) {
                                        uint8_t data = twires_receive();
                                        disVal[(data >> 4)] = (data & 0x0f);
                                }
                }
                        break;
                case (0x08): {
                                disPt[0] = twires_receive();
                                disPt[1] = twires_receive();
                }
                        break;
                case (0x0a): {
                                        twires_send(input.outer);
                }
                        break;
                case (0x0b): {
                                        twires_send(input.inner);
                }
                        break;
                case (0x0c): {
                                        twires_send(!rbi(PINB, PB4));
                }
                        break;
                default: {
                        while (twires_available())
                                twires_receive();
                }
                        break;
        }
}

void writeSegment(uint8_t digit, uint8_t value) {
        uint8_t dp = 0;
        if (digit <= 4 && rbi(disPt[0], digit)) dp = 1;
        if (digit > 4 && rbi(disPt[1], digit-5)) dp = 1;

        cbi(PORTD, PD3);                        // Blank the 4511
        cbi(PORTD, PD2);                        // Drop the DP before changing digit
        hc595_write((value << 4) | (digit & 0x0f)); //Write the value and digit
        if (dp) sbi(PORTD, PD2);        // Add DP if required
        sbi(PORTD, PD3);                        // Enable the 4511
}

void pcInterrupt() {
                wdt_reset();

                pcInt.mask = pcInt.current ^ pcInt.last;
                pcInt.last = pcInt.current;

        if (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.current, PCINT0) == 1 &&
             rbi(pcInt.current, PCINT1) == 1) ||
             (rbi(pcInt.current, PCINT0) == 0 &&
              rbi(pcInt.current, PCINT1) == 0))) {
              if (rbi(pcInt.mask, PCINT0) ) {
                        input.outer += 1;
              } else if (rbi(pcInt.mask, PCINT1) ) {
                input.outer -= 1;
              }

        }

        if (((rbi(pcInt.current, PCINT2) == 1 &&
                rbi(pcInt.current, PCINT3) == 1) ||
                (rbi(pcInt.current, PCINT2) == 0 &&
                 rbi(pcInt.current, PCINT3) == 0))) {
                if (rbi(pcInt.mask, PCINT2) ) {
                        input.inner += 1;
                } else if (rbi(pcInt.mask, PCINT3) ) {
                        input.inner -= 1;
                }
        }
        // Clear the mask so we know we've dealt with it
        pcInt.mask = 0;

}

#ifdef _AVR_ATtiny4313_H_
ISR(PCINT_B_vect) {
#else
ISR(PCINT_vect) {
#endif
        pcInt.current = PINB;
        //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
        // 8.0Mhz, 1ms = 31ovf
    // 8.0Mhz, .5ms = 15ovf, 160r

        if (tmr0_ovf>=15) {
                        systime++;
                        tmr0_ovf = 0;
        }

}