]> rtime.felk.cvut.cz Git - eurobot/public.git/blobdiff - src/eb_pwr/main.c
eb_pwr: New version of power management.
[eurobot/public.git] / src / eb_pwr / main.c
index 834caddf5ddc10119fd7c7bdecfb7a981cdfb85b..6a95901880a317f4014d31a63d97a402845a2fa6 100644 (file)
@@ -4,7 +4,7 @@
 //
 // Description
 // -----------
-// This software controls the eurobot powerboard 
+// This software controls the eurobot powerboard
 // Author : Jiri Kubias DCE CVUT
 //
 //
 #include <system_def.h>
 #include <periph/can.h>
 #include <can_ids.h>
-
+#include <can_msg_def.h>
 
 #include "pwrstep.h"
 #include "uart.h"
+#include "def.h"
 
-#define CAN_SPEED      1000000
-
-#define CAN_ISR                0
-#define ADC_ISR                1
-#define TIME_ISR       2
-
-
-#define TIME1MS        ((CPU_APB_HZ) / 1000)
-
-
-#define CAN_TRY                20
-
-enum {
-  ALERT_LOW = 1,
-  ALERT_MAIN,
-  ALERT_BYE,
-  ALERT_33V,
-  ALERT_50V,
-  ALERT_80V
-} alert_states;
-
-
-
-#define TIME_COUNT     4
-#define LEDG_TIME      500
-#define CAN_REPORT_TIME 500
-#define CAN_ALERT_TIME         200
-#define CAN_TIMEOUT_TIME 50
-enum {
-  TIM_CAN_REPORT = 0,
-  TIM_CAN_ALERT,
-  TIM_LEDG,
-  TIM_CAN_TIMEOUT
-}time;
-
-
-
-#define BAT_CNT                10
-#define        BAT_STAT_LOW    120000
-#define BAT_STAT_MAIN  110000
-#define BAT_STAT_BYE   105000
+can_msg_t msg;
 
-#define V33_MIN                30000
-#define V50_MIN                45000
-#define V80_MIN                75000
+struct power power_state;
 
-#define CAN_TIMEOUT    10
+volatile uint32_t timer_msec = 0, timer_usec = 0;
 
+void set_irq_handler(uint8_t source, uint8_t irq_vect, void (*handler)())
+{
+        /* set interrupt vector */
+        ((uint32_t*)&VICVectAddr0)[irq_vect] = (uint32_t)handler;
+        ((uint32_t*)&VICVectCntl0)[irq_vect] = 0x20 | source;
+        /* enable interrupt */
+        VICIntEnable = 1<<source;
+}
 
+void timer0_irq() __attribute__((interrupt));
+void timer0_irq()
+{
+        static unsigned cnt1khz = 0;
 
+        /* reset timer irq */
+        T0IR = -1;
 
-//#define TEST
+        /* increment timer_usec */
+        timer_usec += 10;
+        /* increment msec @1kHz */
+        if (++cnt1khz == 100) {
+                cnt1khz = 0;
+                ++timer_msec;
+        }
 
-can_msg_t msg;
+        /* int acknowledge */
+        VICVectAddr = 0;
+}
 
-volatile uint32_t dev_time[TIME_COUNT];
+void init_timer0(uint32_t prescale, uint32_t period)
+{
+        T0TCR = 0x2; /* reset */
+        T0PR = prescale - 1;
+        T0MR0 = period;
+        T0MCR = 0x3; /* match0: reset & irq */
+        T0EMR = 0; /* no ext. match */
+        T0CCR = 0x0; /* no capture */
+        T0TCR = 0x1; /* go! */
+}
 
-unsigned int cnt_12V;
-unsigned int cnt_10V;
+void can_rx(can_msg_t *msg) {
+        can_msg_t rx_msg;
+
+        memcpy(&rx_msg, msg, sizeof(can_msg_t));
+
+        if (rx_msg.id == CAN_PWR) {
+                /* set 3.3V power line */
+                if ((rx_msg.data[0] & (1<<0)) && !(rx_msg.data[0] & (1<<3))) {
+                        pwr_33(PWR_ON, &power_state);
+                        power_state.can_33v_req = PWR_ON;
+                } else if (rx_msg.data[0] & (1<<3)) {
+                        pwr_33(PWR_OFF, &power_state);
+                        power_state.can_33v_req = PWR_OFF;
+                }
+                /* set 5.0V power line */
+                if ((rx_msg.data[0] & (1<<1)) && !(rx_msg.data[0] & (1<<4))) {
+                        pwr_50(PWR_ON, &power_state);
+                        power_state.can_50v_req = PWR_ON;
+                } else if (rx_msg.data[0] & (1<<4)) {
+                        pwr_50(PWR_OFF, &power_state);
+                        power_state.can_50v_req = PWR_OFF;
+                }
+                /* set 8.0V power line */
+                if ((rx_msg.data[0] & (1<<2)) && !(rx_msg.data[0] & (1<<5))) {
+                        pwr_80(PWR_ON, &power_state);
+                        power_state.can_80v_req = PWR_ON;
+                } else if(rx_msg.data[0] & (1<<5)) {
+                        pwr_80(PWR_OFF, &power_state);
+                        power_state.can_80v_req = PWR_OFF;
+                }
+        }
+}
 
+void init_perip(struct power *pwr)      // inicializace periferii mikroprocesoru
+{
+        can_init_baudrate(CAN_SPEED, CAN_ISR, can_rx);
+        init_uart0((int)9600 ,UART_BITS_8, UART_STOP_BIT_1, UART_PARIT_OFF, 0 );
+        init_adc(ADC_ISR);
+        init_pwr(pwr);
+        init_timer0(1, CPU_APB_HZ/100000);
+        set_irq_handler(4 /*timer0*/, TIMER_IRQ_PRIORITY, timer0_irq);
+
+        pwr_80(PWR_ON, pwr);
+        pwr_50(PWR_ON, pwr);
+}
 
-void led_blik()
+void blink_led()
 {
-       
-       if (dev_time[TIM_LEDG] == 0)
-       {
-               deb_led_change(LEDG);
-               dev_time[TIM_LEDG] = LEDG_TIME;
-       }
+        static uint32_t led_time = 0;
 
+        if(timer_msec >= led_time + 500) {
+                led_time = timer_msec;
+                deb_led_change(LEDG);
+        }
 }
 
-void send_alert(unsigned char type )
+void send_alert(unsigned char alert)
 {
-       
-       
        msg.id = CAN_PWR_ALERT;
        msg.flags = 0;
        msg.dlc = 1;
-       msg.data[0] = type;
-       
-       dev_time[TIM_CAN_TIMEOUT] = CAN_TIMEOUT_TIME;
-       while(can_tx_msg(&msg) && (dev_time[TIM_CAN_TIMEOUT] != 0));
-                       
+       msg.data[0] = alert;
+
+       can_tx_msg(&msg);
 }
 
-void power_alert()
+void power_lines_check(struct power *pwr)
 {
-       if (dev_time[TIM_CAN_ALERT] == 0)
-       {
-               
-               if (adc_val[0] < BAT_STAT_BYE)          // bat < 9,5V
-               {
-                       deb_led_on(LEDR);
-                       send_alert(ALERT_BYE);
-                       pwr_50(PWR_OFF);
-                       //pwr_80(PWR_OFF);      
-                       pwr_33(PWR_OFF);
-                       
-
-               }
-               else if (adc_val[0] < BAT_STAT_MAIN)            // bat < 12V
-               {
-                       deb_led_on(LEDB);
-                       ++cnt_10V;
-                       if (cnt_10V > BAT_CNT)
-                       {
-                               send_alert(ALERT_MAIN);
-                               pwr_50(PWR_OFF);
-                               //pwr_80(PWR_OFF);      
-                       }
-                       
-
-               }       
-               else if (adc_val[0] < BAT_STAT_LOW)             // bat < 12V
-               {
-                       deb_led_on(LEDY);
-                       ++cnt_12V;
-                       if (cnt_12V > BAT_CNT)
-                               send_alert(ALERT_LOW);  
-               }
-               else 
-                       deb_led_off(LEDY);
-               
-               if (cnt_10V < BAT_CNT)
-               {
-                       if (adc_val[3] < V80_MIN)
-                       {
-                               send_alert(ALERT_80V);  
-                       }
-                       
-                       if (adc_val[2] < V50_MIN)
-                       {
-                               send_alert(ALERT_50V);  
-                       }
-                       
-                       if (adc_val[1] < V33_MIN)
-                       {
-                               send_alert(ALERT_33V);  
-                       }
-               }
-               dev_time[TIM_CAN_ALERT] = CAN_ALERT_TIME;
+        static uint32_t power_time = 0;
+        static unsigned char cnt_33V = 0, cnt_50V = 0, cnt_80V = 0;
+
+        //TODO dodelat kontrolu napajecich vetvi tak aby se merilo cca 10x po sobe a pak vyhodnotila situace
+       if (timer_msec >= power_time + CAN_ALERT_TIME) {
+                if ((V80_CH < V80_MIN || V80_CH > V80_MAX) && (pwr->pwr_80v_state == PWR_ON)) {
+                        if (++cnt_80V > 20) {
+                                pwr->alert |= CAN_PWR_ALERT_80;
+                                send_alert(pwr->alert);
+                                //pwr_80(PWR_OFF, pwr);
+                        }
+                }
+
+                if ((V50_CH < V50_MIN || V50_CH > V50_MAX) && (pwr->pwr_50v_state == PWR_ON)) {
+                        if (++cnt_50V > 20) {
+                                pwr->alert |= CAN_PWR_ALERT_50;
+                                send_alert(pwr->alert);
+                                pwr_50(PWR_OFF, pwr);
+                        }
+                }
+
+                if ((V33_CH < V33_MIN || V33_CH > V33_MAX) && (pwr->pwr_33v_state == PWR_ON)) {
+                        if (++cnt_33V > 10) {
+                                pwr->alert |= CAN_PWR_ALERT_33;
+                                send_alert(pwr->alert);
+                                pwr_33(PWR_OFF, pwr);
+                        }
+                }
+
+               power_time = timer_msec;
        }
 }
 
-void send_can()
+void battery_check(struct power *pwr)
+{
+        static uint32_t battery_time = 0;
+        static unsigned char cnt_10V = 0, cnt_11V = 0, cnt_12V = 0;
+
+        //TODO upravit mereni baterie, po zapnuti napajeni cekat cca 5s a merit stav, pokud OK, zapnout dasli vetve ap.
+        if (timer_msec >= battery_time + 200) {
+                        /* check battery empty state - Ubat < 10.5 V */
+                        /* red LED signalization */
+                        if (BATTERY_CH < BAT_STAT_CRITICAL) {
+                                if (++cnt_10V > 20) {
+                                        deb_led_on(LEDR);
+                                        pwr->alert |= CAN_PWR_BATT_CRITICAL;
+                                        send_alert(pwr->alert);
+                                        pwr_50(PWR_OFF, pwr);
+                                        pwr_33(PWR_OFF, pwr);
+                                        /// do not switch off 8V pwr line - this will cause power-down of this board!!
+                                }
+                        }
+                        /* check battery low state - Ubat < 11V */
+                        /* blue LED signalization*/
+                        else if (BATTERY_CH < BAT_STAT_LOW) {
+                                if (++cnt_11V > BAT_CNT) {
+                                        deb_led_on(LEDY);
+                                        pwr->alert |= CAN_PWR_BATT_LOW;
+                                        send_alert(pwr->alert);
+                                }
+                        }
+                        /* check battery alert state - Ubat < 12V */
+                        /* yellow LED signalization*/
+                        else if (BATTERY_CH < BAT_STAT_MEAN) {
+                                if (++cnt_12V > BAT_CNT) {
+                                        deb_led_on(LEDY);
+                                        pwr->alert |= CAN_PWR_BATT_MEAN;
+                                        send_alert(pwr->alert);
+                                }
+                        } else {
+                                /* batery OK */
+                        }
+                battery_time = timer_msec;
+        }
+}
+
+void send_voltage()
 {
-       if (dev_time[TIM_CAN_REPORT] == 0)
-       {
+        static uint32_t send_time = 0;
+        static uint32_t can_timeout = 0;
+
+       if (timer_msec >= send_time + CAN_REPORT_TIME) {
                deb_led_on(LEDB);
 
                msg.id = CAN_PWR_ADC1;
@@ -183,10 +231,10 @@ void send_can()
                msg.data[5] = (((adc_val[1]) >> 16) & 0xFF);
                msg.data[6] = (((adc_val[1]) >> 8) & 0xFF);
                msg.data[7] = (((adc_val[1]) >> 0) & 0xFF);
-                       
-               
-               dev_time[TIM_CAN_TIMEOUT] = CAN_TIMEOUT_TIME;
-               while(can_tx_msg(&msg) && (dev_time[TIM_CAN_TIMEOUT] != 0));
+
+
+               can_timeout = timer_msec;
+               while(can_tx_msg(&msg) && (timer_msec <= can_timeout + CAN_TIMEOUT_TIME));
 
                msg.id = CAN_PWR_ADC2;
                msg.flags = 0;
@@ -199,114 +247,25 @@ void send_can()
                msg.data[5] = (((adc_val[3]) >> 16) & 0xFF);
                msg.data[6] = (((adc_val[3]) >> 8) & 0xFF);
                msg.data[7] = (((adc_val[3]) >> 0) & 0xFF);
-               
-               dev_time[TIM_CAN_TIMEOUT] = CAN_TIMEOUT_TIME;
-               while(can_tx_msg(&msg) && (dev_time[TIM_CAN_TIMEOUT] != 0));
-               
-               deb_led_off(LEDB);
-               dev_time[TIM_CAN_REPORT] = CAN_REPORT_TIME;
-       }
-}
-
-void can_rx(can_msg_t *msg) {
-       can_msg_t rx_msg;
-       
-       memcpy(&rx_msg, msg, sizeof(can_msg_t));
-       
-
-       if (rx_msg.id == CAN_PWR)
-       {
-               if(rx_msg.data[0] & (1<<0)) pwr_33(PWR_ON);
-               if(rx_msg.data[0] & (1<<1)) pwr_50(PWR_ON);
-               if(rx_msg.data[0] & (1<<2)) pwr_80(PWR_ON);
-               
-               if(rx_msg.data[0] & (1<<3)) pwr_33(PWR_OFF);
-               if(rx_msg.data[0] & (1<<4)) pwr_50(PWR_OFF);
-               if(rx_msg.data[0] & (1<<5)) pwr_80(PWR_OFF);
-       }       
-}
-
 
+               can_timeout = timer_msec;
+                while(can_tx_msg(&msg) && (timer_msec <= can_timeout + CAN_TIMEOUT_TIME));
 
-
-
-void tc1 (void) __attribute__ ((interrupt));
-void tc1 (void)   {
-
-       uint32_t i;
-       
-       for (i = 0; i < TIME_COUNT; i++)
-       {
-               if(dev_time[i] != 0)
-                 --dev_time[i];
+               deb_led_off(LEDB);
+               send_time = timer_msec;
        }
-
-       T1IR        = 4;                            // Vynulovani priznaku preruseni
-       VICVectAddr = 0;                            // Potvrzeni o obsluze preruseni
 }
 
-
-/* Setup the Timer Counter 1 Interrupt */
-void init_time (unsigned rx_isr_vect)
+int main (void)
 {
+       init_perip(&power_state);       // sys init MCU
 
-       T1PR = 0;
-       T1MR2 = TIME1MS;
-       T1MCR = (3<<6);                 // interrupt on MR1
-       T1TCR = 1;                                  // Starts Timer 1 
-
-       ((uint32_t*)&VICVectAddr0)[rx_isr_vect] = (unsigned long)tc1;          // Nastaveni adresy vektotu preruseni
-       ((uint32_t*)&VICVectCntl0)[rx_isr_vect] = 0x20 | 0x5;                    // vyber casovece pro preruseni
-       VICIntEnable = (1<<5);                  // Povoli obsluhu preruseni
-}
-
-
-
-void init_perip(void)     // inicializace periferii mikroprocesoru
-{
-       int i;
-       for (i = 0; i < TIME_COUNT; i++)
-         dev_time[i] = 0;
-  
-       init_pwr();
-       can_init_baudrate(CAN_SPEED, CAN_ISR, can_rx);
-       init_adc(ADC_ISR);
-       init_time (TIME_ISR);
-       init_uart0((int)9600 ,UART_BITS_8, UART_STOP_BIT_1, UART_PARIT_OFF, 0 );
-
-
-#ifdef TEST
-       pwr_33(PWR_ON);
-       pwr_50(PWR_ON);
-       pwr_80(PWR_ON);
-#else
-       pwr_33(PWR_OFF);
-       pwr_50(PWR_OFF);
-       pwr_80(PWR_OFF);
-#endif
-
-       pwr_33(PWR_ON);
-       pwr_50(PWR_ON);
-       pwr_80(PWR_ON);
-}
-
-
-int main (void)  
-{
-       init_perip();                   // sys init MCU
-
-       dev_time[TIM_LEDG] = 1000;
-       while(dev_time[TIM_LEDG]);
-        
-
-       while(1)
-       {
-               led_blik();
-               send_can();
-               power_alert();
-
-       } 
-}
-
-
+        //TODO wait one secdond here
 
+       while (1) {
+               blink_led();
+               send_voltage();
+                battery_check(&power_state);
+               power_lines_check(&power_state);
+       }
+}
\ No newline at end of file