-#define F_CPU 8000000UL
+// #define F_CPU 8000000UL
#include <avr/interrupt.h>
#include <util/delay.h>
//Rcc? -- read ADC measurement of internal 1.1V reference (one register)
//Icc? -- Firmware Info
-#define STARTTX(i) txcnt = (i);UCSR1B |= (1<< UDRIE1)
#define ISMYADDR() (rxbuf[1] == '0' && (rxbuf[2] == '0' || rxbuf[2] == '1' || rxbuf[2] == '2' || rxbuf[2] == '3') )
volatile uint8_t settings_changed = 0;
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 rxbuf[7];
uint8_t txbuf[7];
uint16_t limit[4] = {0x0800,0x0800,0x0800,0x0800};
+
+void uart_puts(const uint8_t *s ){
+ while (*s)
+ usb_serial_putchar(*s++);
+ }
uint8_t nib_to_hex(uint16_t in, uint8_t nib) {
uint8_t t = (in >> (nib*4)) & 0xF;
void forward_msg(uint8_t i) {
sub2(&rxbuf[1],&rxbuf[2]);
memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,i);
- STARTTX(i);
+ txbuf[i] = 0;
+ uart_puts(txbuf);
}
uint8_t is_my_address(uint8_t s) {
txbuf[2]=nib_to_hex(v,1);
txbuf[3]=nib_to_hex(v,0);
txbuf[4]='\n';
- STARTTX(5);
+ txbuf[5] = 0;
+ uart_puts(txbuf);
}
void send_answer_chars(uint8_t a, uint8_t b, uint8_t c) {
txbuf[2]=b;
txbuf[3]=c;
txbuf[4]='\n';
- STARTTX(5);
+ txbuf[5] = 0;
+ uart_puts(txbuf);
}
-//----------------------------------------------------------------------------------------------------
+
+//Channels 0 1 2 3: PD4, PB6, PF6, PF1
void switchoutput(uint8_t chan, int8_t to) {
- if(to == -1) {
+ if(to == -1) {//toggle
output_enable ^= (1<<chan);
output_error &= ~(1<<chan);
}
- else if (to == 0 || to == -2) {
+ else if (to == 0 || to == -2) {//off
output_enable &= ~(1<<chan);
}
- else if (to == 1) {
+ else if (to == 1) {//on
output_enable |= (1<<chan);
output_error &= ~(1<<chan);
}
if(to >= -1) {settings_changed |= 16;}
- uint8_t en1 = ((output_enable & 1) && !(output_error & 1))?1:0; //switched for open drain version
- uint8_t en2 = ((output_enable & 2) && !(output_error & 2))?1:0;
-
- PORTA &= ~((1<<2) | (1<<3));
- DDRA = (DDRA & ~(3<<2)) | ((en1&1)<<3) | ((en2&1)<<2);
- //PORTA = (PORTA & ~(3<<2)) | ((en1&1)<<3) | ((en2&1)<<2);
-
+ if((output_enable & chan) && !(output_error & chan)) {
+ switch (chan) {
+ case 0 : PORTD |= (1<<4); break;
+ case 1 : PORTB |= (1<<6); break;
+ case 2 : PORTF |= (1<<6); break;
+ case 3 : PORTF |= (1<<1); break;
+ }
+ }
+ else {
+ switch (chan) {
+ case 0 : PORTD &= ~(1<<4); break;
+ case 1 : PORTB &= ~(1<<6); break;
+ case 2 : PORTF &= ~(1<<6); break;
+ case 3 : PORTF &= ~(1<<1); break;
+ }
+ }
}
void correct_adc(uint8_t channel) {
adc[channel] = adc[channel]*2 - (adc[channel]>>3);
}
}
-
+//Buttons 0 1 2 3: PD1, PD0, PB7, PB3
ISR(TIMER0_OVF_vect) {
- static uint8_t dwncnt[2] = {0,0};
- if(!(PINA & 0x40)) {dwncnt[0]++;} else {dwncnt[0] = 0;}
- if(!(PINB & 0x04)) {dwncnt[1]++;} else {dwncnt[1] = 0;}
+ 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;}
-
- for(uint8_t i=0; i<=1;i++) {
+ time++;
+ for(uint8_t i=0; i<=3;i++) {
if(dwncnt[i] == 50) {switchoutput(i,-1);}
if(countdown[i] != 0) {
if(countdown[i] == 1) {
}
countdown[i]--;
}
- }
+ }
if(adc_enable) {ADCSRA |= (1<<ADSC);}
asm volatile("wdr");
}
-
+
+//ADC ref: PF0(0)
+//Sense 0 1 2 3: PD6(9), PD7(10), PF7(7), PF4(4)
+//ADC ref: PF0(0,0)
+//Sense 0 1 2 3: PD6(9,3+MUX5), PD7(10,4+MUX5), PF7(7,7), PF4(4,4) (channel, ADMUX value)
+
ISR(ADC_vect) {
static uint8_t channel = 0;
- if(channel == 0) {
- adc_reference = ADC;
- ADMUXA = 7;
- ADCSRA |= (1<<ADSC);
- channel = 1;
- }
- else if(channel == 1) {
- adc[0] = ADC;
- correct_adc(0);
- ADMUXA = 1;
- ADCSRA |= (1<<ADSC);
- channel = 2;
- avgadc[0] -= avgadc[0]/8;
- avgadc[0] += adc[0];
- if(limit[0]*8<avgadc[0]) {
- output_error |= 1;
- switchoutput(0,-2);
- }
+ switch(channel) {
+ case 0: adc_reference = ADC; break;
+ default:
+ adc[channel] = ADC;
+ correct_adc(channel);
+ avgadc[channel] -= avgadc[channel]/8;
+ avgadc[channel] += adc[channel];
+ if(limit[channel]*8<avgadc[channel]) {
+ output_error |= 1;
+ switchoutput(channel,-2);
+ }
}
- else if(channel == 2) {
- adc[1] = ADC;
- correct_adc(1);
- ADMUXA = 0xD;
- channel = 0;
- avgadc[1] -= avgadc[1]/8;
- avgadc[1] += adc[1];
- if(limit[1]*8<avgadc[1]) {
- output_error |= 2;
- switchoutput(1,-2);
- }
+ channel++;
+ switch(channel) {
+ case 0: ADMUX &= 0xe0; ADMUX |= 9; ADCSRB |= (1<<MUX5); break;
+ case 1: ADMUX &= 0xe0; ADMUX |= 10; 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)
+ ADCSRA |= (1<<ADSC);
}
-ISR(USART1_UDRE_vect) {
- UDR1 = txbuf[txpoint++];
- if(--txcnt == 0 || txpoint > 7) {
- txpoint = 0;
- txcnt = 0;
- UCSR1B &= ~(1<< UDRIE1);
- }
- }
-ISR(USART1_RX_vect) {
- uint8_t buf = UDR1;
+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')) {
rxbuf[rxcnt++] = buf;
//Forward any incoming 4 letter answer
if (rxbuf[0] == 'A') {
memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,5);
- STARTTX(5);
+ txbuf[5] = 0;
+ uart_puts(txbuf);
}
//Switch command
//Read firmware info
if (rxbuf[0] == 'I' && rxbuf[3] == '?' && is_my_address(5)) {
- send_answer_hex(FIRMWARE_VERSION);
+ send_answer_hex(FIRMWARE_VERSION);
}
//Switch ADC
if (rxbuf[0] == 'O' && is_my_address(5)) {
- if(rxbuf[3] != '?')
- adc_enable = rxbuf[3] - '0';
+ if(rxbuf[3] != '?')
+ adc_enable = rxbuf[3] - '0';
send_answer_hex(adc_enable);
settings_changed |= 32;
-//TODO correct ADC settings
- if (adc_enable == 1) ADMUXB = (6 << REFS0); //2.2V reference, with capacitor
- if (adc_enable == 2) ADMUXB = (7 << REFS0); //4.096V as reference
- if (adc_enable == 3) ADMUXB = (0 << REFS0); //Vcc as reference
+ if (adc_enable == 1) ADMUX = (3 << REFS0); //2.56V reference, with capacitor
}
//Read current limit
}
-
+void update_eeprom(void) {
+ if (settings_changed & 1) {
+ settings_changed &= ~1;
+ eeprom_update_byte((uint8_t*)0x20,limit[0]&0xFF);
+ eeprom_update_byte((uint8_t*)0x21,(limit[0]>>8)&0xFF);
+ }
+ if (settings_changed & 2) {
+ settings_changed &= ~2;
+ eeprom_update_byte((uint8_t*)0x22,limit[1]&0xFF);
+ eeprom_update_byte((uint8_t*)0x23,(limit[1]>>8)&0xFF);
+ }
+ if (settings_changed & 4) {
+ settings_changed &= ~4;
+ eeprom_update_byte((uint8_t*)0x24,limit[2]&0xFF);
+ eeprom_update_byte((uint8_t*)0x25,(limit[2]>>8)&0xFF);
+ }
+ if (settings_changed & 8) {
+ settings_changed &= ~8;
+ eeprom_update_byte((uint8_t*)0x26,limit[3]&0xFF);
+ eeprom_update_byte((uint8_t*)0x27,(limit[3]>>8)&0xFF);
+ }
+ if (settings_changed & 16) {
+ settings_changed &= ~16;
+ eeprom_update_byte((uint8_t*)0x29,output_enable);
+ }
+ if (settings_changed & 32) {
+ settings_changed &= ~32;
+ eeprom_update_byte((uint8_t*)0x28,adc_enable);
+ }
+ }
__attribute__((naked)) int main(void) {
TIMSK0 = (1 << TOIE0); //Overflow interrupt`
- ADMUX = (3 << REFS0); --reference 2.56V internal
+ ADMUX = (3 << REFS0); //reference 2.56V internal
ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADIE) | (7 << ADPS0); //enable, start, irq, /128
DIDR0 = (1 << ADC4D) | (1 << ADC7D);
DIDR2 = (1 << ADC10D) | (1 << ADC9D);
WDTCSR = (1<<WDE) | (5<<WDP0);
sei();
-
+ uint16_t lasttime = 0;
while(1) {
- _delay_ms(3000);
- if(settings_changed != 0) {
- if (settings_changed & 1) {
- settings_changed &= ~1;
- eeprom_update_byte((uint8_t*)0x20,limit[0]&0xFF);
- eeprom_update_byte((uint8_t*)0x21,(limit[0]>>8)&0xFF);
- }
- if (settings_changed & 2) {
- settings_changed &= ~2;
- eeprom_update_byte((uint8_t*)0x22,limit[1]&0xFF);
- eeprom_update_byte((uint8_t*)0x23,(limit[1]>>8)&0xFF);
- }
- if (settings_changed & 4) {
- settings_changed &= ~4;
- eeprom_update_byte((uint8_t*)0x24,limit[2]&0xFF);
- eeprom_update_byte((uint8_t*)0x25,(limit[2]>>8)&0xFF);
- }
- if (settings_changed & 8) {
- settings_changed &= ~8;
- eeprom_update_byte((uint8_t*)0x26,limit[3]&0xFF);
- eeprom_update_byte((uint8_t*)0x27,(limit[3]>>8)&0xFF);
- }
- if (settings_changed & 16) {
- settings_changed &= ~16;
- eeprom_update_byte((uint8_t*)0x29,output_enable);
- }
- if (settings_changed & 32) {
- settings_changed &= ~32;
- eeprom_update_byte((uint8_t*)0x28,adc_enable);
- }
+ int n = usb_serial_getchar();
+ if (n >= 0) {
+ getdata(n);
+ }
+
+ if(settings_changed != 0 && (lasttime & 0xff) == 255 && (time & 0xff) == 0) {
+ update_eeprom();
}
+ lasttime = time;
}
}