]> jspc29.x-matter.uni-frankfurt.de Git - electronics.git/commitdiff
added first version of Power module firmware
authorJan Michel <j.michel@gsi.de>
Mon, 26 May 2014 13:27:23 +0000 (15:27 +0200)
committerJan Michel <j.michel@gsi.de>
Mon, 26 May 2014 13:27:23 +0000 (15:27 +0200)
.gitignore [new file with mode: 0644]
Power/firmware/PowerSwitch.c [new file with mode: 0755]
Power/firmware/main.c [deleted file]

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