//
// 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;
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;
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