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