From: Jan Michel <j.michel@gsi.de>
Date: Mon, 26 May 2014 13:27:23 +0000 (+0200)
Subject: added first version of Power module firmware
X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=d056350f68eacece250a557321b27ce3f25e38aa;p=electronics.git

added first version of Power module firmware
---

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2a71a89
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+.kate*
+.~*
+*swp
diff --git a/Power/firmware/PowerSwitch.c b/Power/firmware/PowerSwitch.c
new file mode 100755
index 0000000..74158b6
--- /dev/null
+++ b/Power/firmware/PowerSwitch.c
@@ -0,0 +1,249 @@
+#define F_CPU 6000000UL
+
+#include <avr/interrupt.h>
+// #include <util/delay.h>
+// #include <avr/sleep.h>
+// #include <stdint.h>
+#include <avr/io.h>
+#include <string.h>
+
+
+//A0 Aref    In
+//A1 Adc2    In  (ADC1)
+//A2 Relay2  Out
+//A3 Relay1  Out
+//A4 RX      In
+//A5 TX      Out
+//A6 Switch1 In
+//A7 Adc1    In  (ADC7)
+
+//B0 X       --
+//B1 X       --
+//B2 Switch2 In 
+//B3 Reset   --
+
+// cc          -- channel address in hex 
+//Scc(0|1|/)   -- switch channel off/on/toggle
+//Scc?         -- read channel status
+//Ccc?         -- read current
+//Lccxxx       -- set current limit (hex)
+//Lcc?         -- read current limit
+//Axxx         -- answer - three hex digits or chars
+
+#define STARTTX(i) txcnt = (i);UCSR1B |= (1<< UDRIE1)
+#define ISMYADDR() (rxbuf[1] == '0' && (rxbuf[2] == '0' || rxbuf[2] == '1'))
+
+
+uint8_t  output_enable = 0;
+uint8_t  output_error = 0;
+uint16_t adc[2];
+
+uint8_t rxcnt = 0, txcnt = 0, txpoint = 0;
+uint8_t rxbuf[6];
+uint8_t txbuf[6];
+uint16_t limit[2] = {0x0800,0x0800};
+
+uint8_t nib_to_hex(uint16_t in, uint8_t nib) {
+  uint8_t t = (in >> (nib*4)) & 0xF;
+  if (t <= 9) {return t + 0x30;}
+  return t - 10 + 0x61;
+  }
+ 
+uint8_t hex_to_int(uint8_t h) { //assumes valid number
+  if (h < 0x40) return h-0x30;
+  if (h < 0x50) return h-0x41+10;
+                return h-0x61+10;
+  }
+ 
+void sub2(uint8_t* c1, uint8_t* c2) {
+  uint8_t b = hex_to_int(*c1)*16 + hex_to_int(*c2);
+  b -= 2;
+  *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);
+  STARTTX(i);
+  }  
+  
+void send_answer_hex(uint16_t v) {
+  txbuf[0]='A';
+  txbuf[1]=nib_to_hex(v,2);
+  txbuf[2]=nib_to_hex(v,1);
+  txbuf[3]=nib_to_hex(v,0);
+  STARTTX(4);
+  }
+  
+void send_answer_chars(uint8_t a, uint8_t b, uint8_t c) {
+  txbuf[0]='A';
+  txbuf[1]=a;
+  txbuf[2]=b;
+  txbuf[3]=c;
+  STARTTX(4);
+  }
+
+  
+void switchoutput(uint8_t chan, int8_t to) {
+  if(to == -1)
+    output_enable ^= (1<<chan);
+  else if (to == 0) {
+    output_enable &= ~(1<<chan);
+    output_error  &= ~(1<<chan);
+    }
+  else if (to == 1)
+    output_enable |= (1<<chan);
+    
+  uint8_t en1 = ((output_enable & 1) && !(output_error & 1))?1:0;
+  uint8_t en2 = ((output_enable & 2) && !(output_error & 2))?1:0;
+  PORTA = (PORTA & ~(1<<3)) | ((en1&1)<<3);
+  PORTA = (PORTA & ~(1<<2)) | ((en2&1)<<2);
+  }
+
+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;}
+	  
+  if(dwncnt[0] == 100) {switchoutput(0,-1);}	  
+  if(dwncnt[1] == 100) {switchoutput(1,-1);}
+	  
+  ADCSRA |= (1<<ADSC);  
+  }
+
+ISR(ADC_vect) {
+  static uint8_t channel = 0;
+  if(channel == 0) { 
+    adc[0] = ADC; 
+    ADMUXA = 1;  
+    ADCSRA |= (1<<ADSC); 
+    channel = 1;
+    if(limit[0]<adc[0]) {
+      output_error |= 2;
+      switchoutput(0,-2);
+      }  
+    }
+  if(channel == 1) { 
+    adc[1] = ADC; 
+    ADMUXA = 7;  
+    channel = 0;
+    if(limit[1]<adc[1]) {
+      output_error |= 2;
+      switchoutput(1,-2);
+      }    
+    }	  
+  }
+
+ISR(USART1_UDRE_vect) {
+  UDR1 = txbuf[txpoint++];
+  if(--txcnt == 0) {  
+    txpoint = 0;
+    UCSR1B &= ~(1<< UDRIE1);
+    }
+  }
+  
+ISR(USART1_RX_vect) {
+  uint8_t buf = UDR1;
+  if (rxcnt != 0 || (buf == 'S' || buf == 'A' || buf == 'L' || buf == 'C')) {
+    rxbuf[rxcnt++] = buf;
+    }
+  //Forward any incoming 4 letter answer  
+  if (rxcnt == 4) {
+    if (rxbuf[0] == 'A') {
+      rxcnt = 0;
+      memcpy ((uint8_t*)txbuf,(uint8_t*)rxbuf,4);
+      STARTTX(4);
+      }
+  //Four letter 'switch' command  
+    if (rxbuf[0] == 'S') {  
+      rxcnt = 0;
+      if (ISMYADDR()) {
+        rxbuf[2] -= '0';
+        if (rxbuf[3] != '?') {
+          switchoutput(rxbuf[2],rxbuf[3]-'0');
+          }
+        send_answer_chars('0', (output_error  & (1<<rxbuf[2]))?'e':'0', 
+                               (output_enable & (1<<rxbuf[2]))?'1':'0');      
+        }
+      else {
+        forward_msg(4);
+        }
+      }
+  //Read current command
+    if (rxbuf[0] == 'C') { 
+      rxcnt = 0;
+      if (ISMYADDR()) {
+        if (rxbuf[3] == '?')
+          send_answer_hex(adc[rxbuf[2]-'0']);
+        }
+      else {
+        forward_msg(4);
+        }
+      }
+  //Read current limit    
+    if (rxbuf[0] == 'L' && rxbuf[3] == '?') {
+      rxcnt = 0;
+      if (ISMYADDR()) {
+        send_answer_hex(limit[rxbuf[2]-'0']);      
+        }
+      else {
+        forward_msg(4);
+        }
+      } 
+    }
+  //Set current limit
+  if (rxcnt == 6 && rxbuf[0] == 'L') {
+    rxcnt = 0;
+    if (ISMYADDR()) {
+      rxbuf[2] -= '0';
+      if(rxbuf[3] != '?') {
+        uint16_t lim = hex_to_int(rxbuf[3])*256 + hex_to_int(rxbuf[4])*16 + hex_to_int(rxbuf[5]);
+        limit[rxbuf[2]] = lim;
+        }
+      send_answer_hex(limit[rxbuf[2]]);   
+      }
+    else {
+      forward_msg(6);
+      }
+    }   
+    
+  if (rxcnt >= 6) { rxcnt = 0; }  
+    
+} 
+
+
+__attribute__((naked)) int main(void) {
+	// Configure ports
+  DDRA  = 0b00101100; 
+  DDRB  = 0b00000000;
+  
+  PORTA = 0b00000000;
+  PORTB = 0b00000000;
+
+  PUEA  = 0b01011100;
+  PUEB  = 0b00001100;  
+  	
+  CLKPR = (0 << CLKPS0); // no prescaler  
+  PRR   =  (1 << PRTWI)  | (0 << PRUSART1) | (1 << PRUSART0) | (1 << PRSPI) 
+          |(1 << PRTIM2) | (1 << PRTIM1)   | (0 << PRTIM0)   | (0 << PRADC);  
+   
+  TCCR0B = (4 << CS00);  //prescaler 256 -> 6M/256*256 = 91.5 Hz
+  TIMSK0 = (1 << TOIE0); //Overflow interrupt`
+  
+  ADMUXA = 1;  //(1 (Out2),7 (Out1))
+  ADMUXB = (6 << REFS0);   //2.2V reference, with capacitor
+  ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADIE) | (7 << ADPS0); //enable, start, irq, /128
+  ADCSRB = 0;
+  DIDR0  = (1<<ADC1D) | (1<< ADC7D); //disable digital inputs
+  
+  UCSR1A = (1 << U2X1);
+  UCSR1B = (1 << RXCIE1) | (0 << TXCIE1) | (1 << RXEN1) | (1 << TXEN1);
+  UCSR1C = (3 << UCSZ10); //8 Bit
+  UBRR1  = 0x26; //19200
+  
+  sei();  
+  while(1) {
+    
+    }
+  }
\ No newline at end of file
diff --git a/Power/firmware/main.c b/Power/firmware/main.c
deleted file mode 100644
index e69de29..0000000