Rev 2 | 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#ifndef PROTOTYPE#define PROTOTYPE#endifvoid writeSegment(uint8_t digit, uint8_t value);void pcInterrupt(void);void receiveEvent(uint8_t bytes);/* ------------------------------------------------------------------------- */#ifndef TWI_RX_BUFFER_SIZE#define TWI_RX_BUFFER_SIZE ( 16 )#endifvolatile uint8_t user_debug = 0;volatile uint8_t tmr0_ovf = 0;volatile struct {uint8_t current;uint8_t last;uint8_t mask;} pcInt;volatile struct {int8_t outer;int8_t inner;} input;uint8_t i2c_address = I2C_SLAVE_ADDR;uint8_t disIdx = 0;volatile uint8_t disVal[] = {0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a};volatile uint16_t disPt = 0x00;int main(void) {#if HW_VERSION==0x01/*DDR : 1 = Output, 0 = InputPORT: 1 = Pullup for Input, otherwise set outputPIN : Read input pin*//*PA0 - Output - HC595 DSPA1 - Output - HC595 STPA2 - Output - HC595 SHPA3 - Output - 4511 blankingPA4 - SCKPA5 - Output - Decimal PointPA6 - SDAPA7 - Input, Pullup - Flip button*/DDRA = 0B00101111;PORTA = 0B10001000;/*PB0 - Input, PCInt, Pullup - Rot1aPB1 - Input, PCInt, Pullup - Rot1bPB2 - Input, Pullup - Swap buttonPB3 - N/A - Reset (Future - I2C address select)*/DDRB = 0B00000000;PORTB = 0B00000111;#else/*DDR : 1 = Output, 0 = InputPORT: 1 = Pullup for Input, otherwise set outputPIN : Read input pin*//*PA0 - Input, Pullup - i2c addr select 0 (Dip 1)PA1 - Input, Pullup - i2c addr select 1 (Dip 2)PA2 - Reset*/DDRA = 0B00000000;PORTA = 0B00000011;/*PB0 - Input, PCInt0, Pullup - Rot1aPB1 - Input, PCInt1, Pullup - Rot1bPB2 - Input, PCInt2, Pullup - Rot2aPB3 - Input, PCInt3, Pullup - Rot2bPB4 - Input, Pullup - Rot buttonPB5 - SDAPB6 - Input, Pullup - Swap buttonPB7 - SCL*/DDRB = 0B00000000;PORTB = 0B01011111;/*PD0 - Output - Decimal pointPD1 - Output - 4511 BlankingPD2 - Output - '95 DS SerPD3 - Output - '95 SHCP SckPD4 - Output - '95 STCP RskPD5 - Input, Pullup - Config (Dip 3)PD6 - Input, Pullup - Config (Dip 4)*/DDRD = 0B00011111;PORTD = 0B01100010;#endifsystime = 0;sysclockInit();#if HW_VERSION==0x01// hwver1 only has a single rotary shaftPCMSK1 |= (( 1 << ROT_1A_PIN ) | ( 1 << ROT_1B_PIN ));GIMSK |= (1 << PCIE1);#else// hwver2 only has a selectable single/dual rotary shaftPCMSK |= (( 1 << ROT_1A_PIN ) | ( 1 << ROT_1B_PIN ) | ( 1 << ROT_2A_PIN ) | ( 1 << ROT_2B_PIN ));GIMSK |= (1 << PCIE);#endifpcInt.last = ROT_PIN;pcInt.current = pcInt.last;pcInt.mask = 0;#if HW_VERSION==0x02// hw vers 2 has selectable i2c address. Add the value of// the selections to the default i2c addressuint8_t i2c_add = ((!rbi(I2CADDR_PIN, I2CADDR_0)) << 1);i2c_add |= (!rbi(I2CADDR_PIN, I2CADDR_1));i2c_address += i2c_add;#endiftwires_begin(i2c_address);twires_onReceive(receiveEvent);wdt_enable(WDTO_1S); // Watchdog for 1 secsei(); // Enable interruptsuint32_t refresh = systime;// Init and clear the displayshc595_init();hc595_write(0x00);for(;;){wdt_reset();if (user_debug) {disVal[9] = rbi(SB_INPUT, SB_PIN);disVal[8] = rbi(FB_INPUT, FB_PIN);disVal[0] = input.outer & 0x0f;disVal[1] = (input.outer >> 4);}if (pcInt.current != pcInt.last) {cli(); // Dont process interrupts for a bitpcInterrupt();sei();}if (systime > refresh) {writeSegment(disIdx, disVal[disIdx]);refresh = systime + DISPLAY_REFRESH;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 (0x01): {// Send 2 bytes with version detailstwires_send(HW_VERSION);twires_send(SW_VERSION);}break;case (0x03): {// Enable debugging modeuser_debug = twires_receive();}break;case (0x05): {// Receive n numbers of digits to DISPLAY_REFRESH// High nibble = segment number// Low nibble = digit to displaywhile (bytes--) {uint8_t data = twires_receive();disVal[data >> 4] = (data & 0x0f);}}break;case (0x06): {// Recive a digit to retrieve to value ofuint8_t digit = twires_receive();uint8_t out = (digit << 4) | (disVal[digit] & 0x0f);twires_send(out);}break;case (0x08): {// Recieve 2 bytes, for the decimal points// 5 bits used in eac bytedisPt = ((uint16_t)twires_receive() << 8);disPt |= (uint16_t)twires_receive();}break;case (0x09): {// Reset the rotaryinput.outer = 0;input.inner = 0;}break;case (0x0a): {twires_send(input.outer);}break;#if HW_VERSION==0x02case (0x0b): {twires_send(input.inner);}break;#endifcase (0x0c): {// Send that status of the buttonsuint8_t out = (!rbi(SB_INPUT, SB_PIN)) << 1;out |= (!rbi(FB_INPUT, FB_PIN));twires_send(out);}break;#if HW_VERSION==0x02case (0x0d): {// Send all the config switch datauint8_t out = ((!rbi(I2CADDR_PIN, I2CADDR_0)) << 3);out |= ((!rbi(I2CADDR_PIN, I2CADDR_1)) << 2);out |= ((!rbi(CONFSW_PIN, CONFSW_1)) << 1);out |= (!rbi(CONFSW_PIN, CONFSW_0));twires_send(out);}break;#endifdefault: {// Don't know what it is, empty bufferwhile (twires_available())twires_receive();}break;}}void writeSegment(uint8_t digit, uint8_t value) {cbi(BL_PORT, BL_PIN); // Blank the 4511cbi(DP_PORT, DP_PIN); // Drop the DP before changing digithc595_write((value << 4) | (9-(digit & 0x0f))); //Write the value and digitif (rbi(disPt, digit)) sbi(DP_PORT, DP_PIN); // Add DP if requiredsbi(BL_PORT, BL_PIN); // Enable the 4511}void pcInterrupt() {pcInt.mask = pcInt.current ^ pcInt.last;pcInt.last = pcInt.current;if (!pcInt.mask)return;// Check which pin caused the interrupt. If they both// equal 0 || 1, the pin that interrupted is the directionif (((rbi(pcInt.current, ROT_1A_PIN) == 1 &&rbi(pcInt.current, ROT_1B_PIN) == 1) ||(rbi(pcInt.current, ROT_1A_PIN) == 0 &&rbi(pcInt.current, ROT_1B_PIN) == 0))) {if (rbi(pcInt.mask, ROT_1A_PIN) ) {input.outer -= 1;} else if (rbi(pcInt.mask, ROT_1B_PIN) ) {input.outer += 1;}}#if HW_VERSION==0x02if (((rbi(pcInt.current, ROT_2A_PIN) == 1 &&rbi(pcInt.current, ROT_2B_PIN) == 1) ||(rbi(pcInt.current, ROT_2A_PIN) == 0 &&rbi(pcInt.current, ROT_2B_PIN) == 0))) {if (rbi(pcInt.mask, ROT_2A_PIN) ) {input.inner -= 1;} else if (rbi(pcInt.mask, ROT_2B_PIN) ) {input.inner += 1;}}#endif// Clear the mask so we know we've dealt with it// Shouldn't be required now that 'doInt' has been removed//pcInt.mask = 0;}#if HW_VERSION==0x01ISR(PCINT1_vect) {#elseISR(PCINT_B_vect) {#endifpcInt.current = ROT_PIN;}#if HW_VERSION==0x01ISR(TIM0_OVF_vect) {#elseISR(TIMER0_OVF_vect) {#endiftmr0_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, 160rif (tmr0_ovf>=15) {systime++;tmr0_ovf = 0;}}