Rev 131 | Go to most recent revision | 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 bytes);
/* ------------------------------------------------------------------------- */
#ifndef TWI_RX_BUFFER_SIZE
#define TWI_RX_BUFFER_SIZE ( 16 )
#endif
volatile 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 = Input
PORT: 1 = Pullup for Input, otherwise set output
PIN : Read input pin
*/
/*
PA0 - Output - HC595 DS
PA1 - Output - HC595 ST
PA2 - Output - HC595 SH
PA3 - Output - 4511 blanking
PA4 - SCK
PA5 - Output - Decimal Point
PA6 - SDA
PA7 - Input, Pullup - Flip button
*/
DDRA = 0B00101111;
PORTA = 0B10001000;
/*
PB0 - Input, PCInt, Pullup - Rot1a
PB1 - Input, PCInt, Pullup - Rot1b
PB2 - Input, Pullup - Swap button
PB3 - 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 sec
sei(); // Enable interrupts
hc595_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) {
pcInterrupt();
}
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): {
twires_send(HW_VERSION);
twires_send(SW_VERSION);
}
break;
case (0x03): {
user_debug = twires_receive();
}
break;
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 (0x09): {
input.outer = 0;
input.inner = 0;
}
break;
case (0x0a): {
twires_send(input.outer);
}
break;
/* Not used in this version
case (0x0b): {
twires_send(input.inner);
}
break;
*/
case (0x0c): {
uint8_t out = (!rbi(SB_INPUT, SB_PIN)) << 1;
out |= (!rbi(FB_INPUT, FB_PIN));
twires_send(out);
}
/* Comined into 0x0c
case (0x0d): {
twires_send(rbi(FB_INPUT, FB_PIN));
}
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(BL_PORT, BL_PIN); // Blank the 4511
cbi(DP_PORT, DP_PIN); // Drop the DP before changing digit
hc595_write((value << 4) | (digit & 0x0f)); //Write the value and digit
if (dp) sbi(DP_PORT, DP_PIN); // Add DP if required
sbi(BL_PORT, BL_PIN); // Enable the 4511
}
void pcInterrupt() {
wdt_reset();
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 direction
if (((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, 160r
if (tmr0_ovf>=15) {
systime++;
tmr0_ovf = 0;
}
}