Rev 131 | 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)#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;//volatile uint8_t doInt = 0;//uint8_t disVal[] = {8,8,8,8,8,8,8,8,8,8};volatile uint8_t disVal[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1};volatile uint8_t disPt[] = {0, 0};int main(void) {/*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;systime = 0;sysclockInit();PCMSK1 |= (( 1 << ROT_1A_PIN ) | ( 1 << ROT_1B_PIN ));GIMSK |= (1 << PCIE1);pcInt.last = ROT_1_PIN;pcInt.current = pcInt.last;pcInt.mask = 0;twires_begin(I2C_SLAVE_ADDR);twires_onReceive(receiveEvent);wdt_enable(WDTO_1S); // Watchdog for 1 secsei(); // Enable interrupts// Init and clear the displayshc595_init();hc595_write(0x00);uint32_t refresh = systime;uint8_t disIdx = 0;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) {cei(); // 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 (0x08): {// Recieve 2 bytes, for the decimal points// 5 bits used in eac bytedisPt[0] = twires_receive();disPt[1] = twires_receive();}break;case (0x09): {// Reset the rotaryinput.outer = 0;input.inner = 0;}break;case (0x0a): {// Send the value of the rotary counttwires_send(input.outer);}break;/* Not used in this versioncase (0x0b): {twires_send(input.inner);}break;*/case (0x0c): {// Send that status of the buttonsuint8_t out = (!rbi(SB_INPUT, SB_PIN)) << 1;out |= (!rbi(FB_INPUT, FB_PIN));twires_send(out);}/* Comined into 0x0ccase (0x0d): {twires_send(rbi(FB_INPUT, FB_PIN));}break;*/default: {// Don't know what it is, empty bufferwhile (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(BL_PORT, BL_PIN); // Blank the 4511cbi(DP_PORT, DP_PIN); // Drop the DP before changing digithc595_write((value << 4) | (digit & 0x0f)); //Write the value and digitif (dp) 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;}}// Clear the mask so we know we've dealt with it// Shouldn't be required now that 'doInt' has been removed//pcInt.mask = 0;}ISR(PCINT1_vect) {pcInt.current = ROT_1_PIN;}ISR(TIM0_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, 160rif (tmr0_ovf>=15) {systime++;tmr0_ovf = 0;}}