]> jspc29.x-matter.uni-frankfurt.de Git - avr.git/commitdiff
Add tested code version of Power Switch 48
authorJan Michel <j.michel@gsi.de>
Fri, 27 Jan 2017 16:57:52 +0000 (17:57 +0100)
committerJan Michel <j.michel@gsi.de>
Fri, 27 Jan 2017 16:57:52 +0000 (17:57 +0100)
atmega32u4/power48/main.c

index c17970e67603c59fcc55a9b68522ac2fcff2944b..89ccd40340dc8db9ffd2b432627279af6aa780f8 100644 (file)
 
 #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) 
@@ -68,27 +76,13 @@ uint8_t hex_to_int(uint8_t h) { //assumes valid number
  
 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) {
@@ -98,7 +92,7 @@ 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) {
@@ -108,12 +102,31 @@ 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);
@@ -128,7 +141,7 @@ void switchoutput(uint8_t chan, int8_t to) {
 
   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;
@@ -147,22 +160,43 @@ void switchoutput(uint8_t chan, int8_t to) {
   }
 
 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);
@@ -173,6 +207,7 @@ ISR(TIMER0_OVF_vect) {
   
   if(adc_enable) {ADCSRA |= (1<<ADSC);}
   asm volatile("wdr");
+  LED2_OFF();
   }  
 
 //ADC ref:          PF0(0)
@@ -183,30 +218,33 @@ ISR(TIMER0_OVF_vect) {
 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')) {
@@ -220,7 +258,7 @@ void getdata(uint8_t buf) {
       if (rxbuf[0] == 'A') {
         memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,5);
         txbuf[5] = 0;
-        uart_puts(txbuf);
+        send_answer_buf(txbuf);
         }
         
 //Switch command  
@@ -251,7 +289,7 @@ void getdata(uint8_t buf) {
 //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
@@ -265,7 +303,7 @@ void getdata(uint8_t buf) {
           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    
@@ -325,6 +363,27 @@ void update_eeprom(void) {
     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) {
   
@@ -340,19 +399,20 @@ __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;
@@ -362,16 +422,27 @@ __attribute__((naked)) int main(void) {
   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);
@@ -382,10 +453,13 @@ __attribute__((naked)) int main(void) {
   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;