#define ISMYADDR() (rxbuf[1] == '0' && (rxbuf[2] == '0' || rxbuf[2] == '1' || rxbuf[2] == '2' || rxbuf[2] == '3') )
+#define LED2_ON() PORTB |= (1<<PB1)
+#define LED2_OFF() PORTB &= ~(1<<PB1)
+
+#define SELECT_MASTER() PORTD |= (1<<PD5)
+#define SELECT_SLAVE() PORTD &= ~(1<<PD5)
+
volatile uint8_t settings_changed = 0;
uint8_t output_enable = 0x3;
uint8_t output_error = 0;
uint8_t adc_enable = 1;
+uint8_t calibphase = 1;
+uint16_t adc_offset[4] = {0,0,0,0};
uint16_t adc[4];
uint16_t avgadc[4] = {0,0,0,0};
uint8_t countdown[4] = {0,0,0,0};
uint16_t adc_reference = 0;
volatile uint16_t time = 0;
-uint8_t rxcnt = 0, txcnt = 0, txpoint = 0;
+uint8_t rxcnt = 0, txpoint = 0;
uint8_t rxbuf[7];
uint8_t txbuf[7];
uint16_t limit[4] = {0x0800,0x0800,0x0800,0x0800};
-
+uint8_t isMaster = 0;
void uart_puts(const uint8_t *s ){
while (*s)
void sub2(uint8_t* c1, uint8_t* c2) {
uint8_t b = hex_to_int(*c1)*16 + hex_to_int(*c2);
- b -= 2;
+ b -= 4;
*c1 = nib_to_hex(b,1);
*c2 = nib_to_hex(b,0);
}
-void forward_msg(uint8_t i) {
- sub2(&rxbuf[1],&rxbuf[2]);
- memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,i);
- txbuf[i] = 0;
- uart_puts(txbuf);
- }
-
-uint8_t is_my_address(uint8_t s) {
- if (ISMYADDR()) {
- rxbuf[2] -= '0';
- return 1;
- }
- else {
- forward_msg(s);
- return 0;
- }
+void send_answer_buf(uint8_t* b) {
+ UCSR1B |= (1<< UDRIE1);
}
void send_answer_hex(uint16_t v) {
txbuf[3]=nib_to_hex(v,0);
txbuf[4]='\n';
txbuf[5] = 0;
- uart_puts(txbuf);
+ send_answer_buf(txbuf);
}
void send_answer_chars(uint8_t a, uint8_t b, uint8_t c) {
txbuf[3]=c;
txbuf[4]='\n';
txbuf[5] = 0;
- uart_puts(txbuf);
+ send_answer_buf(txbuf);
}
+void forward_msg(uint8_t i) {
+ sub2(&rxbuf[1],&rxbuf[2]);
+ memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,i);
+ txbuf[i] = 0;
+ send_answer_buf(txbuf);
+ }
+
+uint8_t is_my_address(uint8_t s) {
+ if (ISMYADDR()) {
+ rxbuf[2] -= '0';
+ return 1;
+ }
+ else {
+ forward_msg(s);
+ return 0;
+ }
+ }
+
//Channels 0 1 2 3: PD4, PB6, PF6, PF1
void switchoutput(uint8_t chan, int8_t to) {
+ LED2_ON();
if(to == -1) {//toggle
output_enable ^= (1<<chan);
output_error &= ~(1<<chan);
if(to >= -1) {settings_changed |= 16;}
- if((output_enable & chan) && !(output_error & chan)) {
+ if((output_enable & (1<< chan))) { // && !(output_error & (1<< chan))
switch (chan) {
case 0 : PORTD |= (1<<4); break;
case 1 : PORTB |= (1<<6); break;
}
void correct_adc(uint8_t channel) {
- if(adc_enable == 1) return;
- if(adc_enable == 2) {
- adc[channel] = adc[channel]*2 - (adc[channel]>>3);
+ if (calibphase) {
+ //LED2_ON();
+ adc_offset[channel] = adc[channel];
+ if (channel == 3) {
+ calibphase = 0;
+ switchoutput(0,-3);
+ switchoutput(1,-3);
+ switchoutput(2,-3);
+ switchoutput(3,-3);
+ }
+ }
+ if (adc[channel] > 0x300)
+ adc[channel] = 0;
+ if(adc_offset[channel] > adc[channel] ) {
+ adc[channel] = adc_offset[channel] - adc[channel];
+ adc[channel] *= 25;
+ }
+ else {
+ adc[channel] = 0;
}
}
+
+
+
//Buttons 0 1 2 3: PD1, PD0, PB7, PB3
ISR(TIMER0_OVF_vect) {
static uint8_t dwncnt[4] = {0,0,0,0};
- if(!(PIND & 0x02)) {dwncnt[0]++;} else {dwncnt[0] = 0;}
- if(!(PIND & 0x01)) {dwncnt[1]++;} else {dwncnt[1] = 0;}
- if(!(PINB & 0x80)) {dwncnt[2]++;} else {dwncnt[2] = 0;}
- if(!(PINB & 0x08)) {dwncnt[3]++;} else {dwncnt[3] = 0;}
+ if(!(PIND & 0x02)) {if(dwncnt[0]<51) dwncnt[0]++;} else {dwncnt[0] = 0;}
+ if(!(PIND & 0x01)) {if(dwncnt[1]<51) dwncnt[1]++;} else {dwncnt[1] = 0;}
+ if(!(PINB & 0x80)) {if(dwncnt[2]<51) dwncnt[2]++;} else {dwncnt[2] = 0;}
+ if(!(PINB & 0x08)) {if(dwncnt[3]<51) dwncnt[3]++;} else {dwncnt[3] = 0;}
time++;
for(uint8_t i=0; i<=3;i++) {
- if(dwncnt[i] == 50) {switchoutput(i,-1);}
+ if(dwncnt[i] == 50) {
+ switchoutput(i,-1);
+ }
if(countdown[i] != 0) {
if(countdown[i] == 1) {
switchoutput(i,-1);
if(adc_enable) {ADCSRA |= (1<<ADSC);}
asm volatile("wdr");
+ LED2_OFF();
}
//ADC ref: PF0(0)
ISR(ADC_vect) {
static uint8_t channel = 0;
switch(channel) {
- case 0: adc_reference = ADC; break;
- default:
+ case 4: adc_reference = ADC; break;
+ case 0:
+ case 1:
+ case 2:
+ case 3:
adc[channel] = ADC;
correct_adc(channel);
avgadc[channel] -= avgadc[channel]/8;
avgadc[channel] += adc[channel];
if(limit[channel]*8<avgadc[channel]) {
- output_error |= 1;
+ output_error |= (1<<channel);
switchoutput(channel,-2);
}
}
- channel++;
+ if(channel<4) channel++; else channel = 0;
+
switch(channel) {
- case 0: ADMUX &= 0xe0; ADMUX |= 9; ADCSRB |= (1<<MUX5); break;
- case 1: ADMUX &= 0xe0; ADMUX |= 10; ADCSRB |= (1<<MUX5); break;
+ case 0: ADMUX &= 0xe0; ADMUX |= 1; ADCSRB |= (1<<MUX5); break;
+ case 1: ADMUX &= 0xe0; ADMUX |= 2; ADCSRB |= (1<<MUX5); break;
case 2: ADMUX &= 0xe0; ADMUX |= 7; ADCSRB &= ~(1<<MUX5); break;
case 3: ADMUX &= 0xe0; ADMUX |= 4; ADCSRB &= ~(1<<MUX5); break;
case 4: ADMUX &= 0xe0; ADMUX |= 0; ADCSRB &= ~(1<<MUX5); break;
}
- if (channel != 5)
+ if (channel != 0)
ADCSRA |= (1<<ADSC);
}
-
void getdata(uint8_t buf) {
if (rxcnt != 0 || (buf == 'S' || buf == 'A' || buf == 'L' || buf == 'C' || buf == 'I'
|| buf == 'D' || buf == 'O' || buf == 'P' || buf == 'R')) {
if (rxbuf[0] == 'A') {
memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,5);
txbuf[5] = 0;
- uart_puts(txbuf);
+ send_answer_buf(txbuf);
}
//Switch command
//Read average current command
if (rxbuf[0] == 'D' && rxbuf[3] == '?' && is_my_address(5)) {
if(adc_enable == 3) { send_answer_hex(avgadc[rxbuf[2]]/8+0x800); }
- else { send_answer_hex(avgadc[rxbuf[2]]/8); }
+ else { send_answer_hex(adc_offset[rxbuf[2]]); } //avgadc[rxbuf[2]]/8
}
//Read firmware info
adc_enable = rxbuf[3] - '0';
send_answer_hex(adc_enable);
settings_changed |= 32;
- if (adc_enable == 1) ADMUX = (3 << REFS0); //2.56V reference, with capacitor
+// if (adc_enable == 1) ADMUX = (3 << REFS0); //2.56V reference, with capacitor
}
//Read current limit
eeprom_update_byte((uint8_t*)0x28,adc_enable);
}
}
+
+
+
+ISR(USART1_RX_vect) {
+ uint8_t buf = UDR1;
+ //LED2_ON();
+ if(isMaster == 0)
+ getdata(buf);
+ else
+ usb_serial_putchar(buf);
+ }
+
+ISR(USART1_UDRE_vect) {
+ if(txbuf[txpoint] != 0)
+ UDR1 = txbuf[txpoint++];
+ if(txpoint > 7 || txbuf[txpoint] == 0) {
+ txpoint = 0;
+ UCSR1B &= ~(1<< UDRIE1);
+ }
+ }
+
__attribute__((naked)) int main(void) {
//Select: PD5
// Configure ports
+
+ MCUCR |= (1<<JTD);
+ MCUCR |= (1<<JTD); //yes, twice
+
PORTB = 0b10001110;
DDRB = 0b01000110;
- PORTD = 0b00000011;
+ PORTD = 0b00001111;
DDRD = 0b00110000;
PORTF = 0b00000000;
DDRF = 0b01000010;
-
- output_enable = eeprom_read_byte((uint8_t*)0x29);
- switchoutput(0,-3);
limit[0] = eeprom_read_byte((uint8_t*)0x21)<<8;
limit[0] |= eeprom_read_byte((uint8_t*)0x20);
limit[1] = eeprom_read_byte((uint8_t*)0x23)<<8;
limit[3] = eeprom_read_byte((uint8_t*)0x27)<<8;
limit[3] |= eeprom_read_byte((uint8_t*)0x26);
adc_enable = eeprom_read_byte((uint8_t*)0x28);
+ output_enable = eeprom_read_byte((uint8_t*)0x29);
+
//Timer0 at ~122 Hz overflow for ADC control and buttons
TCCR0B = (4 << CS00);
TIMSK0 = (1 << TOIE0); //Overflow interrupt`
-
+
+
+ UCSR1A = (1 << U2X1);
+ UCSR1B = (1 << RXCIE1) | (0 << TXCIE1) | (0 << RXEN1) | (1 << TXEN1);
+ UCSR1C = (3 << UCSZ10); //8 Bit
+ UBRR1 = 0x10; //57600
+ _delay_ms(10);
+ UCSR1B |= (1 << RXEN1);
+
ADMUX = (3 << REFS0); //reference 2.56V internal
- ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADIE) | (7 << ADPS0); //enable, start, irq, /128
+ ADCSRA = (1 << ADEN) | (0 << ADSC) | (1 << ADIE) | (7 << ADPS0); //enable, start, irq, /128
DIDR0 = (1 << ADC4D) | (1 << ADC7D);
DIDR2 = (1 << ADC10D) | (1 << ADC9D);
+ ADMUX &= 0xe0; ADMUX |= 1; ADCSRB |= (1<<MUX5);
//Watchdog at .5 seconds
WDTCSR = (1<<WDCE);
while(1) {
int n = usb_serial_getchar();
if (n >= 0) {
+// LED2_ON();
+ isMaster = 1;
+ SELECT_MASTER();
getdata(n);
}
- if(settings_changed != 0 && (lasttime & 0xff) == 255 && (time & 0xff) == 0) {
+ if(settings_changed != 0 && (lasttime & 0x3ff) == 0x3ff && (time & 0x3ff) == 0) {
update_eeprom();
}
lasttime = time;