#define FIRMWARE_VERSION 0x001
+/*
//ADC
// 0 Sense1 Vmon0 DCDC
// 1 Sense2 Vmon0 LDO
// 6 Sense5 Vmon1 LDO
// 7 Sense6 Vmon1 DCDC
// 13 Sense7 Imon1 LDO
-//
+
// PB7 not output enable
// PB3 copy to outputs
// PB2/1 MOSI/SCLK
// LED PC7 PC6
// WS2812 PD7
-
// CTRL30 DCDC Res Ch 0 (MSB)
// CTRL31
// CTRL32
// CTRL11
// CTRL12 (LSB)
-// | Registers | description |
-// |-----------|--------------------------------------------
-// | 0 | SPI word |
-// | 1 | ADC reading from channel c |
+// | Registers | description |
+// |-----------|--------------------------------------------------------------|
+// | 0 | LDO ON/OFF |
+// | 1 | DCDC set voltage adjustment resistors |
+// | 2 | Voltage V_in (RO) |
+// | 3 | Current C_in (RO) |
+// | 4 | Temperature (RO) |
+// | 5 | [15:4] Firmware; [3:2] reserved; [1] Switch ; [0] LED (RO) |
+// | 6 | Current Offset |
// **Data format:** *XuuGcRvvvv*
// **Data format:** *X000cRvvvv*
-
+*/
#define ISMYADDR() (rxbuf[1] == '0' && rxbuf[2] == '0')
#define LED1_ON() PORTC |= (1<<PC7)
#define LED1_OFF() PORTC &= ~(1<<PC7)
-#define LED2_ON() PORTC |= (1<<PC6)
+#define LED2_ON() PORTC |= (1<<PC6) //Switch deactivated
#define LED2_OFF() PORTC &= ~(1<<PC6)
-
#define SHCP_HIGH() PORTB |= (1<<PB1) //SCLK
#define SHCP_LOW() PORTB &= ~(1<<PB1)
#define SHIFT_EN_OUTPUT() PORTB &= ~(1<<PB7)
#define SHIFT_DIS_OUTPUT() PORTB |= (1<<PB7)
-
uint16_t time;
uint8_t rxcnt = 0, txpoint = 0;
uint8_t rxbuf[11];
uint8_t txbuf[12];
uint16_t adc[16]; //raw values from ADC
+uint16_t volt = 0;
+uint16_t curr = 0;
+uint16_t temp = 0;
+uint16_t information = 1;
+int8_t curr_offset = 0;
uint16_t shift_register;
+uint16_t read_LDO_status;
+uint16_t read_setting;
+uint8_t isMaster = 0;
uint8_t nib_to_hex(uint16_t in, uint8_t nib) {
uint8_t t = (in >> (nib*4)) & 0xF;
return h-0x61+10;
}
-
void sub1(uint8_t* c1, uint8_t* c2) {
uint8_t b = hex_to_int(*c1)*16 + hex_to_int(*c2);
b -= 1;
*c2 = nib_to_hex(b,0);
}
-
+void send_answer_buf(uint8_t*b) {
+ UCSR1B |= (1<<UDRIE1);
+ }
+
void send_answer_hex(uint8_t* rxbuf, uint16_t v) {
txbuf[0]='A';
txbuf[1]=rxbuf[1];
txbuf[2]=rxbuf[2];
- txbuf[3]=rxbuf[3];
+ txbuf[3]=rxbuf[3];//Switch deactivated
txbuf[4]=rxbuf[4];
txbuf[5]=rxbuf[5];
txbuf[6]=nib_to_hex(v,3);
txbuf[9]=nib_to_hex(v,0);
txbuf[10]='\n';
txbuf[11] = 0;
- usb_serial_write(txbuf,12);
+ send_answer_buf(txbuf);
}
-
-uint8_t is_my_address(void) {
+void forward_msg(uint8_t i) {
+ sub1(&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'; // write number to buffer, instead of ascii.
return 1;
} else {
+ forward_msg(s);
return 0;
}
}
sei();
}
+void switchLDO(uint8_t chan, uint8_t val) {
+ if (chan == 2) {
+ shift_register &= ~(1<<4);
+ if (val ==0) {} //LDO CH1 off
+ else {shift_register |= (1<<4);} //LDO CH1 on
+ }
+ if (chan == 1) {
+ shift_register &= ~(1<<3);
+ if (val ==0) {} //LDO CH0 off
+ else {shift_register |= (1<<3);} //LDO CH0 on
+ }
+ setVoltages();
+}
+void setDCDC(uint8_t chan, uint8_t val) {
+//DCDC CH0
+ if (chan == 3) {
+ shift_register &= ~((1<<15)|(1<<14)|(1<<13)); //clear decbitpos15-13
+ if (val == 0) {}
+ if (val == 1) {shift_register |= (1<<15);}
+ if (val == 2) {shift_register |= (1<<14);}
+ if (val == 3) {shift_register |= (1<<15)|(1<<14);}
+ if (val == 4) {shift_register |= (1<<13);}
+ if (val == 5) {shift_register |= (1<<15)|(1<<13);}
+ if (val == 6) {shift_register |= (1<<14)|(1<<13);}
+ if (val == 7) {shift_register |= (1<<15)|(1<<14)|(1<<13);}
+ }
+//DCDC CH1
+ if (chan == 4) {
+ shift_register &= ~((1<<11)|(1<<10)|(1<<9));
+ if (val == 0) {}
+ if (val == 1) {shift_register |= (1<<11);}
+ if (val == 2) {shift_register |= (1<<10);}
+ if (val == 3) {shift_register |= (1<<11)|(1<<10);}
+ if (val == 4) {shift_register |= (1<<19);}
+ if (val == 5) {shift_register |= (1<<11)|(1<<9);}
+ if (val == 6) {shift_register |= (1<<10)|(1<<9);}
+ if (val == 7) {shift_register |= (1<<11)|(1<<10)|(1<<9);}
+ }
+//LDO CH1
+ if (chan == 2) {
+ shift_register &= ~((1<<7)|(1<<6)|(1<<5));
+ if (val == 0) {}
+ if (val == 1) {shift_register |= (1<<7);}
+ if (val == 2) {shift_register |= (1<<6);}
+ if (val == 3) {shift_register |= (1<<7)|(1<<6);}
+ if (val == 4) {shift_register |= (1<<5);}
+ if (val == 5) {shift_register |= (1<<7)|(1<<5);}
+ if (val == 6) {shift_register |= (1<<6)|(1<<5);}
+ if (val == 7) {shift_register |= (1<<7)|(1<<6)|(1<<5);}
+ }
+//LDO CH0
+ if (chan == 1) {
+ shift_register &= ~((1<<2)|(1<<1)|(1<<0));
+ if (val == 0) {}
+ if (val == 1) {shift_register |= (1<<2);}
+ if (val == 2) {shift_register |= (1<<1);}
+ if (val == 3) {shift_register |= (1<<2)|(1<<1);}
+ if (val == 4) {shift_register |= (1<<0);}
+ if (val == 5) {shift_register |= (1<<2)|(1<<1);}
+ if (val == 6) {shift_register |= (1<<1)|(1<<0);}
+ if (val == 7) {shift_register |= (1<<2)|(1<<1)|(1<<0);}
+ }
+ setVoltages();
+}
+void setInfo(uint8_t chan, uint8_t val){
+ if ((val & 0x1) == 1) { LED1_ON(); information |= (1<<0);}// LED1 on
+ if ((val & 0x1) == 0) { LED1_OFF(); information &= ~(1<<0);}// LED1 off
+
+ if (((val>>1) & 0x1) == 1) { LED2_ON(); information |= (1<<1);}// LED2 on
+ if (((val>>1) & 0x1) == 0) { LED2_OFF(); information &= ~(1<<1);}// LED2 off
+ information |= (FIRMWARE_VERSION<<4);
+}
-/***
- * Data: XuuGcRvvvv
- *
- * X - command (write: W, read: R, answer: A etc.)
- * uu - Controllernumber (Hex value)
- * G - Groupnumber (to talk to all channels, that belong together, in one command.)
- * c - channelnumber in the group (Hex value)
- * R - register (Hex value)
- * vvvv - 16 Bit value
- *
- * All in all 10 characters
- *
- *
- * close with a "\n"
- * e.g. "RF2012FE51\n"
- *
- ***/
+/*
+// Data: XuuGcRvvvv
+//Switch deactivated
+// X - command (write: W, read: R, answer: A etc.)
+// uu - Controllernumber (Hex value)
+// G - Groupnumber (to talk to all channels, that belong together, in one command.)
+// c - channelnumber in the group (Hex value)
+// R - register (Hex value)
+// vvvv - 16 Bit value
+//
+// All in all 10 characters
+// RF2012FE51
+//
+// close with a "\n"
+// e.g. "RF2012FE51\n"
+//
+//
+//
+// | Registers | description |
+// |-----------|--------------------------------------------------------------|
+// | 0 | LDO ON/OFF |
+// | 1 | DCDC set voltage adjustment resistors |
+// | 2 | Voltage V_in (RO) |
+// | 3 | Current C_in (RO) |
+// | 4 | Temperature (RO) |
+// | 5 | [15:4] Firmware; [3:2] reserved; [1] Switch ; [0] LED (RO) |
+// | 6 | Current Offset |
+*/
void getdata(uint8_t buf) {
- if (rxcnt != 0 || (buf == 'W' || buf == 'R')) {
+ if (rxcnt != 0 || (buf == 'A' || buf == 'W' || buf == 'R')) {
rxbuf[rxcnt++] = buf;
}
if (buf == '\n' || buf == '\r') { //End of Command
-
- if (is_my_address()){ // message is for this uC
-
- if (rxbuf[0] == 'W'){ //write
-
+ if (rxbuf[0] == 'A') {
+//answer
+ memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,10);
+ txbuf[11] = 0;
+ send_answer_buf(txbuf);
+ } else if (rxbuf[0] == 'S') { // Scann of chain, returns number of boards
+ txbuf[0] = 'S';
+ uint8_t length = rxcnt - 2 ; // Length of Counter
+ //read current counter value
+ uint32_t cnt = 0;
+ if (length == 0){
+ length = 1;
+ } else {
+ uint32_t base = 1;
+ for (uint8_t i = length; i > 0; i--){
+ cnt += hex_to_int(rxbuf[i])*base;
+ base *= 16;
+ }
+ }
+ // inc counter value
+ cnt++;
+ //send to next uC
+ if ((cnt % 16) == 0) length++;
+ for (uint8_t i = length; i > 0; i--){
+ txbuf[i] = nib_to_hex(cnt,length-i);
+ }
+ if (length > 8) length = 8; // skip to keep a clean ending of message
+ txbuf[length+1] = 10;
+ txbuf[length+2] = 0;
+ send_answer_buf(txbuf);
+ rxcnt = 0;
+ } else if (is_my_address(10)){ // message is for this uC
+ if (rxbuf[0] == 'W'){
+//write
switch (hex_to_int(rxbuf[5])) {
- // shift reg settings
- case 0:
- shift_register = (hex_to_int(rxbuf[6])<<12) | (hex_to_int(rxbuf[7])<<8) | (hex_to_int(rxbuf[8])<<4) | (hex_to_int(rxbuf[9]));
- setVoltages();
- break;
+
+ // set LDO ON/OFF
+ case 0: if (hex_to_int(rxbuf[4]) < 3) {
+ switchLDO(hex_to_int(rxbuf[4]),hex_to_int(rxbuf[9]));
+ eeprom_update_byte((uint8_t*)0x21,shift_register);
+ eeprom_update_byte((uint8_t*)0x22,shift_register>>8);
+ }
+ send_answer_hex(&rxbuf[0],shift_register);
+ break;
+
+ // set voltage of DCDC-Converter
+ case 1: if (hex_to_int(rxbuf[4]) < 5) {
+ setDCDC(hex_to_int(rxbuf[4]),hex_to_int(rxbuf[9]));
+ eeprom_update_byte((uint8_t*)0x21,shift_register);
+ eeprom_update_byte((uint8_t*)0x22,shift_register>>8);
+ }
+ send_answer_hex(&rxbuf[0],shift_register);
+ break;
+
+ // set information
+ case 5: setInfo(hex_to_int(rxbuf[4]),hex_to_int(rxbuf[9]));
+ send_answer_hex(&rxbuf[0],information);
+ break;
+
+ // set current offset
+ case 6: curr_offset = (hex_to_int(rxbuf[7])*16+hex_to_int(rxbuf[8]))&0xFF;
+ eeprom_update_byte((uint8_t*)0x26,curr_offset);
+ send_answer_hex(&rxbuf[0],curr_offset*16);
+ break;
+
+ default:send_answer_hex(&rxbuf[0], 0xFFFF);
+ break;
+
}
}
- if (rxbuf[0] == 'R'){ //read
- // get DCDC selection
+ if (rxbuf[0] == 'R'){
+//read
+ // get LDO status
if (hex_to_int(rxbuf[5]) == 0) {
- send_answer_hex(&rxbuf[0],shift_register);
+ uint16_t read_LDO_status = 0xFFFF;
+ //LDO Status CH1
+ if (hex_to_int(rxbuf[4]) == 2) {read_LDO_status = ((shift_register >> 4) & 1);
+ }
+ //LDO Status CH0
+ if (hex_to_int(rxbuf[4]) == 1) {read_LDO_status = ((shift_register >> 3) & 1);
+ }
+ send_answer_hex(&rxbuf[0],read_LDO_status);
}
+
+ // get DCDC selection
if (hex_to_int(rxbuf[5]) == 1) {
- send_answer_hex(&rxbuf[0],adc[hex_to_int(rxbuf[4])]);
+ uint16_t read_setting = 0xFFFF;
+ //DCDC CH0
+ if (hex_to_int(rxbuf[4]) == 3) {read_setting = ((shift_register >> 15) & 1) | ((shift_register >> 13) & 2) | ((shift_register >> 11) & 4);
+ }
+ //DCDC CH1
+ if (hex_to_int(rxbuf[4]) == 4) {read_setting = ((shift_register >> 11) & 1) | ((shift_register >> 9) & 2) | ((shift_register >> 7) & 4);
+ }
+ //LDO CH1
+ if (hex_to_int(rxbuf[4]) == 2) {read_setting = ((shift_register >> 7) & 1) | ((shift_register >> 5) & 2) | ((shift_register >> 3) & 4);
+ }
+ //LDO CH0
+ if (hex_to_int(rxbuf[4]) == 1) {read_setting = ((shift_register >> 2) & 1) | (shift_register & 2) | ((shift_register << 2) & 4);
+ }
+ send_answer_hex(&rxbuf[0],read_setting);
+ }
+
+ // get voltage
+ if (hex_to_int(rxbuf[5]) == 2) {
+ send_answer_hex(&rxbuf[0],volt);
+ }
+
+ // get current
+ if (hex_to_int(rxbuf[5]) == 3) {
+ send_answer_hex(&rxbuf[0],curr);
+ }
+
+ // get temperature
+ if (hex_to_int(rxbuf[5]) == 4) {
+ send_answer_hex(&rxbuf[0],temp);
+ }
+
+ // get information
+ if (hex_to_int(rxbuf[5]) == 5) {
+ information |= (FIRMWARE_VERSION<<4);
+ send_answer_hex(&rxbuf[0],information);
}
+
+ // get current offset
+ if (hex_to_int(rxbuf[5]) == 6) {
+ send_answer_hex(&rxbuf[0],curr_offset*16);
+ }
}
}
- }
if (rxcnt >= 10 || buf == '\n' || buf == '\r') { rxcnt = 0; }
}
-
+}
+
ISR(ADC_vect) {
static uint8_t channel = 0;
adc[channel] = ADC;
ADCSRA |= (1<<ADSC);
}
+ISR(USART1_RX_vect) {
+ uint8_t buf = UDR1;
+ if(isMaster == 0) {
+ getdata(buf);
+ } else {
+ //usb_serial_putchar(buf);
+ }
+}
+
+ISR(USART1_UDRE_vect) {
+ if(txbuf[txpoint] != 0)
+ UDR1 = txbuf[txpoint++];
+ if(txpoint > 11 || txbuf[txpoint] == 0) {
+ txpoint = 0;
+ UCSR1B &= ~(1<< UDRIE1); //deactivate Transmit
+ }
+ }
ISR(TIMER0_OVF_vect) {
time++;
asm volatile("wdr");
}
-__attribute__((naked)) int main(void) {
+__attribute__((naked)) void main(void) {
CLKPR = (1 << CLKPCE); // prescaler 2 = 8 MHz
CLKPR = (1 << CLKPS0); // prescaler 2
- usb_init();
// Configure ports
TCCR0B = (5 << CS00);
TIMSK0 = (1 << TOIE0); //Overflow interrupt`
+ //Init USART
+ UCSR1A = (1 << U2X1); // Double Speed Mode
+ //UCSR1A = (0 << U2X1); // Single Speed Mode
+ UCSR1B = (1 << RXCIE1) | (0 << TXCIE1) | (0 << RXEN1) | (1 << TXEN1);
+ UCSR1C = (3 << UCSZ10); //8 Bit
+ UBRR1 = 0x10; // 38k4 (SSM) //0x33; // 38k4 //0x10; //57600
+ _delay_ms(10);
+ UCSR1B |= (1 << RXEN1);
+
ADMUX = (3 << REFS0); //reference 2.56V internal
ADCSRA = (1 << ADEN) | (0 << ADSC) | (1 << ADIE) | (7 << ADPS0); //enable, start, irq, /128
DIDR0 = 0b11111111;
// ADMUX &= 0xe0; ADMUX |= 1; ADCSRB |= (1<<MUX5);
ADCSRA |= (1<<ADSC);
- uint16_t lasttime = 0;
-
- shift_register = 0xee00;
+//eeprom
+ shift_register = eeprom_read_byte((uint8_t*)0x21) | eeprom_read_byte((uint8_t*)0x22)<<8;
+ curr_offset = eeprom_read_byte((uint8_t*)0x26);
+
setVoltages();
+ SHIFT_EN_OUTPUT();// Enable output of shift register to mosfet
sei();
+
+ uint16_t lasttime = 0;
+
while(1) {
- int n = usb_serial_getchar();
- if (n >= 0) {
- getdata(n);
- }
+// int n = usb_serial_getchar();
+// if (n >= 0) {
+// isMaster = 1;
+// //SELECT_MASTER();
+// getdata(n);
+// }
if((time != lasttime)) {
}