direction commands updated to Up down RPM value
Dependencies: MAX7219pot MCP23S17 mbed
Fork of POT_V_1_0 by
main.cpp
- Committer:
- viewdeep51
- Date:
- 2018-04-28
- Revision:
- 4:710464cb44fc
- Parent:
- 3:ae45e29f5d4f
- Child:
- 5:f7b7ee0702cc
File content as of revision 4:710464cb44fc:
/*Board configuration >>>>>place JP5 to E5V side to use external 5V supply >>>>>Remove jumper link SB13,SB14 usb uart debug disabled >>>>>Place jumper link SB62,SB63...uart PA2,PA3 enabled by these jumper links */ #include "mbed.h" #include "pot.h" #include "max7219.h" #include "MCP23S17.h" using namespace std; //------------------------------------ // Hyperterminal configuration // 9600 bauds, 8-bit data, no parity //------------------------------------ Serial UART(SERIAL_TX, SERIAL_RX); //timer instances creation// Ticker pot_HB; Ticker HB_Ticker; Ticker flash_Ticker; Ticker R_A_Ticker; Ticker CMD_Ticker; Ticker DIR_Ticker; Ticker HB_fail; Ticker RTC_ticker; Ticker led_refresh; Timeout timeout; //SPI instances creation// SPI _SPI2(SPI2_MOSI, SPI2_MISO, SPI2_SCK); //for displays max7219 SPI _SPI3(SPI3_MOSI, SPI3_MISO, SPI3_SCK); //for keyscan mcp23s17 //class object instances for key I/O expander and segment driver// MCP23S17 mcp23s17_1(1,_SPI3, SPI3_CS1,SPI3_RST); //class MCP23S17 object instance for mcp23s17 IC-1 key detection MCP23S17 mcp23s17_2(2,_SPI3, SPI3_CS2,SPI3_RST); //class MCP23S17 object instance for mcp23s17 IC-2 key detection Max7219 max7219(SPI2_MOSI, SPI2_MISO, SPI2_SCK,SPI2_CS1); //object instance for seven segment drivers max7219_configuration_t DEVICE1, DEVICE2; //interrupts definations InterruptIn int_A(INT_A); //8commands InterruptIn int_B(INT_B); //4 3commands+1ack InterruptIn int_C(INT_C); //4(3 controls(INC+,DEC-,TEST)+1 req) enbaled for all //chip select definations for max7219 & mcp23s17 as digitalout pins// DigitalOut cs_disp1(SPI2_CS1); DigitalOut cs_disp2(SPI2_CS2); //max7219 DigitalOut cs_key1(SPI3_CS1); DigitalOut cs_key2(SPI3_CS2); //mcp23s17 DigitalOut Drive_En(TX_EN); //uart driver enable //discrete outputs definations buzzer and hooter DigitalOut buzzer(BUZ); DigitalOut hooter(HTR); int err_ALL,sync_count,Hrs_1,Hrs_2, Mins_1, Mins_2, current_cmd, current_status,current_status_dir; int addr, req,ack, send_ADDR, rcvd_ADDR, ach_S,ach_M,test_cnt,req_ADDR,ack_ADDR, err_ID, err_Status; int rpm_data[4] = {0,0,0,0}; //digits 0-3 int last_entry[4] = {0,0,0,0}; //digits 0-3 uint8_t spi_error,no_pot_connected,num_bytes,ticker_count,ticker_count_fast,norm_count,set_bit; int dir, last_dir; int checksum_send_byte,checksum_rcvd_byte; char pot_Addr,addr_ID; float HB_timer,duty_cycle,sync_time; bool device_ERR,pot_Error, norm_op; bool toggle,test,toggle_fast,display_flash; bool key_CMD,key_CTRL,key_SET; bool HB_rcvd, HB_ack_rcvd, REQ_rcvd, BROADCAST_rcvd, ACK_rcvd,time_RCVD; bool DIR_cmd,DIR_cmd_ack,DIR_cmd_ack_send; bool RPM_cmd,RPM_cmd_ack,RPM_cmd_ack_send; bool HB_send, CMD_send, BROADCAST_send, REQ_send, ACK_send; bool ENTER_ACK_key,DIR_key,REQ_key,ACK_key,disp_clear; bool switch_CH, pot_MCR_err, pot_ER_err, ACH_SW_over; bool data_fail,disp_test; int device_addr = -1; char valid; char valid_sentence[8] = {'A', 'A','A','A','A','A','A','A'}; char rx_buf[RX_BUFFER_SIZE+1]; char tx_buf[TX_BUFFER_SIZE+1]; char RTC_buffer[5] = {1,2,3,4,0}; DigitalOut LED_CMD_ACK(_CMD_ACK); //ack command in slave devices only DigitalOut LED_CTRL[2] = {_REQ,_ACK}; //control transfer DigitalOut LED_DIR[2] = {_AHEAD,_ASTERN}; //dir command DigitalOut LED_ACH[8] = {_WH,_BRDG,_MCR,_ER,_WP,_WS,_OPS,_ASP}; //active channels //DigitalOut myled(PB_13); //for internal test LED1 PwmOut mypwm(_PWM); struct _POT { int slave_ID; int err_cnt; bool err_status; }; struct _POT* POT=NULL; enum AddrID { pot_Master = 1, pot_Submaster, pot_Slave_MCR, pot_Slave_ER, pot_Listner_WP, pot_Listner_WS, pot_Listner_OPS, pot_Listner_ASP = 8 }; enum LED_STATUS { OFF = 0, ON, _FLASH = 2 }; LED_STATUS led_cmd_ack; //only in slave devices LED_STATUS led_ctrl[2]; LED_STATUS led_dir[2]; LED_STATUS led_ach[8]; enum KEY { ZERO = 0, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, FALSE0 = 10 }; enum KEY num_KEY; enum CTRL { REQ_ = 1, ACK_ = 2, FALSE1= 3 }; enum CTRL ctrl_KEY; enum direction_KEY { AHEAD = 1, ASTERN, FALSE2 = 3 }; enum direction_KEY dir_KEY; enum display_KEY { clr_ENTRY = 0, //CE clr_ALL, //C, all data turns to zero ENTER_ACK, //enter in case of master and ACK in case of slaves/repeaters FALSE3 = 3 }; enum display_KEY disp_KEY; enum SET { INC=0, DEC, TEST, FALSE4 = 4 }; enum SET set_KEY; enum CHANNEL { ch_A=1, ch_B, ch_C, ch_D=4 }; //keyscan channelA,B,C,Dof MCP23s17 1& 2 respectively enum CHANNEL ch; /************************************************************************************** EOT RTC display update FUNCTIONS **************************************************************************************/ void RTC_display(char* digits) { for(uint8_t i = 0; i <= 3; i++) //to write all the four digits { if(i == 1) RTC_buffer[i] = RTC_buffer[i]|0b10000000; // to inc else __nop(); max7219.write_digit(1, i+1, *(digits+i)); //device 2, digit 1-4 ,data 0x01 } } /************************************************************************************** EOT RTC read FUNCTION **************************************************************************************/ void read_RTC() { time_t seconds = time(NULL); strftime(RTC_buffer, 5, "%H%M\n", localtime(&seconds)); wait_ms(5); RTC_display(RTC_buffer); wait_ms(1); } /************************************************************************************** EOT CHECK LED STATUS FUNCTION **************************************************************************************/ void update_led() { if(++ticker_count == 25) //25x20 = 500ms { ticker_count = 0; toggle = !toggle; //normal cmd flash } else __nop(); if(++ticker_count_fast == 10) //20x10 =200 { ticker_count_fast = 0; toggle_fast = !toggle_fast; //error flashing } else __nop(); if(test) { LED_CMD_ACK = ON; //in slave only for(uint8_t i=0;i<=1;i++) //control { LED_CTRL[i] = ON; } for(uint8_t i=0;i<=1;i++) //control { LED_DIR[i] = ON; /////////////////working here } for(uint8_t i=0;i<=7;i++) //active channel { LED_ACH[i] = ON; //duty cycle 10% } max7219.set_display_test(); //all on wait_us(1); disp_test = true; } else { if(disp_test) { disp_test = false; max7219.clear_display_test(); //normal operation } else __nop(); if(led_cmd_ack == ON) //status update LED_CMD_ACK LED_CMD_ACK = ON; else __nop(); if(led_cmd_ack == OFF) LED_CMD_ACK = OFF; else __nop(); if(led_cmd_ack == _FLASH) { if(toggle) LED_CMD_ACK= ON; else LED_CMD_ACK = OFF; } else __nop(); for(uint8_t i=0;i<=1;i++) //status update LED_CTRL { if(led_ctrl[i] == ON) LED_CTRL[i] = ON; else __nop(); if(led_ctrl[i] == OFF) LED_CTRL[i] = OFF; //duty cycle 10% else __nop(); if(led_ctrl[i] == _FLASH) { if(toggle) LED_CTRL[i]= ON; else LED_CTRL[i] = OFF; } else __nop(); } for(uint8_t i=0;i<=1;i++) //status update LED_CTRL { if(led_dir[i] == ON) LED_DIR[i] = ON; else __nop(); if(led_dir[i] == OFF) LED_DIR[i] = OFF; //duty cycle 10% else __nop(); if(led_dir[i] == _FLASH) { if(toggle) LED_DIR[i]= ON; else LED_DIR[i] = OFF; } else __nop(); } for(uint8_t i=0;i<=7;i++) //status update LED_ACH { if(led_ach[i] == ON) LED_ACH[i] = ON; //duty cycle 10% else __nop(); if(led_ach[i] == OFF) LED_ACH[i] = OFF; //duty cycle 10 else __nop(); if(led_ach[i] == _FLASH) { if(toggle_fast) LED_ACH[i]= ON; else LED_ACH[i] = OFF; } else __nop(); } } if(display_flash) //if command executed or command received { if(toggle) max7219.enable_device(2); //enable device 1 or normal mode else max7219.disable_device(2); //shutdown mode } else if(!device_ERR) //specific device is not in error device max7219.enable_device(2); //enable device 1 or normal mode; else __nop(); } /************************************************************************************** POT State Machines FUNCTIONS **************************************************************************************/ void HB_State_Machine() //run at an interval of 10ms,event driven start stop { static int hb_state_cnt = 0; if(HB_send) { HB_send = false; hb_state_cnt = 0; } else __nop(); if(HB_ack_rcvd) { HB_ack_rcvd = false; HB_Ticker.detach(); POT[device_addr].err_cnt = 0; if(POT[device_addr].err_status) //if that specific device is in error before but revert back to healthy state { POT[device_addr].err_status = false; err_Status = 0; err_ID = POT[device_addr].slave_ID; set_bit = (uint8_t)1<<(err_ID-1); err_ALL = err_ALL^set_bit; //bitwise XOR BROADCAST_send = true; // to tell all device that error diminished switch_CH = true; // to tell specific device abot active channels and rpm data if(POT[device_addr].slave_ID == pot_Slave_MCR) { pot_MCR_err = false; if(pot_ER_err) { ach_S = pot_Slave_MCR; switch_CH = true; //automatic takeover if ER is already faulty } else __nop(); } else __nop(); if(POT[device_addr].slave_ID == pot_Slave_ER) { pot_ER_err = false; if(pot_MCR_err) { ach_S = pot_Slave_ER; switch_CH = true; //automatic takeover if ER is already faulty } else __nop(); } else __nop(); } else { POT[device_addr].err_status = false; hb_state_cnt = 0; err_Status = 0; if((POT[device_addr].slave_ID == ach_S)&&(led_ach[send_ADDR - 1] != ON)) led_ach[send_ADDR - 1] = ON; else if((POT[device_addr].slave_ID != ach_S)&&(led_ach[send_ADDR - 1] != OFF)) led_ach[send_ADDR - 1] = OFF; else __nop(); if((addr_ID == ach_M)&&(led_ach[ach_M-1] != ON)) led_ach[ach_M-1] = ON; else if((addr_ID != ach_M)&&(led_ach[ach_M-1] != OFF)) led_ach[ach_M-1] = OFF; else __nop(); } } else { if(++hb_state_cnt >= 5) //if HB_response not arrived till 50ms { hb_state_cnt=0; HB_Ticker.detach(); if((++POT[device_addr].err_cnt >= 5)&&(!POT[device_addr].err_status)) //specific device in error state after 05 hb response missing { POT[device_addr].err_cnt = 0; led_ach[send_ADDR - 1] = _FLASH; err_ID = POT[device_addr].slave_ID; set_bit = (uint8_t)1<<(err_ID-1); err_ALL = err_ALL|set_bit; //bitwise OR POT[device_addr].err_status = true; err_Status = 1; BROADCAST_send = true; //broadcast needed to be sent if(POT[device_addr].slave_ID == pot_Slave_MCR) //means MCR fail { pot_MCR_err = true; if(ach_S == pot_Slave_MCR) { if(!pot_ER_err) //automatic changeover if ER healthy { ach_S = pot_Slave_ER; switch_CH = true; //transfer all slaves the new active slave } else { pot_Error = true; ach_S = 9; switch_CH = true; //both start flashing for ER nd MCR in all slaves } } else __nop(); } else __nop(); if(POT[device_addr].slave_ID == pot_Slave_ER) { pot_ER_err = true; if(ach_S == pot_Slave_ER) { if(!pot_MCR_err) //automatic changeover if MCR healthy { ach_S = pot_Slave_MCR; switch_CH = true; } else { pot_Error = true; ach_S = 9; switch_CH = true; //both start flashing for all MCR nd ER } } else __nop(); } else __nop(); } else __nop(); } else __nop(); } } void CMD_State_Machine() //function run periodcally in all connected devices on bus { static int cmd_state_cnt=0; if(RPM_cmd_ack) //PEOTX,CMD received in Master/SUB_Master, non Active Slave & Listner { for(uint8_t i = 0; i <=3; i++) { last_entry[i] = rpm_data[i]; //data saved to last entery } for(uint8_t i = 5; i <=8; i++) { max7219.write_digit(1,i,last_entry[i-5]); //last entery displayed } if(addr_ID == ach_M) { mcp23s17_1.gpintena(0xff); //ACK key interrupts disabled wait_us(1); mcp23s17_1.gpintenb(0xff); //ACK key interrupts disabled wait_us(1); disp_clear = true; } else if(addr_ID == ach_S) { int_B.rise(NULL); //all key functions/interrupt disabled for PORTA,B wait_us(1); mcp23s17_1.gpintenb(0x00); //interrupts disabled wait_us(1); } else __nop(); led_cmd_ack = ON; current_status = 1; //display steady cmd_state_cnt = 0; RPM_cmd = false; RPM_cmd_ack = false; display_flash = false; buzzer = OFF; hooter = OFF; CMD_Ticker.detach(); //cmd state machine ticker stopped in all devices } else if(++cmd_state_cnt >= 12) //Hotter ON after 3sec { if((hooter == OFF)&&(addr_ID == ach_S)) //if hooter still off { cmd_state_cnt = 0; hooter = ON; /* if(++cmd_state_cnt >= 96) //still command ack not recived for 24 sec { LED_CMD[cmd].OFF(); //command suspended buzzer = OFF; hooter = OFF; int_A.rise(NULL); int_A.rise(NULL); CMD_ticker.detach(); //timer stoped in all connected devices if ack not received in 3sec } */ } else __nop(); } else __nop(); } void R_A_Statemachine() { static int state_cnt = 0; if(++state_cnt >= 60) //REQ not acknowledged for 30 sec, leds turn off, timer stopped { state_cnt = 0; REQ_rcvd = false; //clear any pending request R_A_Ticker.detach(); /* if(addr_ID != ach_M) // TODO { int_B.rise(NULL); mcp23s17_1.gpintenb(0x00); //portb of mcp1 keys disabled related to ACK wait_us(10); } else __nop(); */ led_ctrl[REQ_-1] = OFF; led_ctrl[ACK_-1] = OFF; } else __nop(); if(ACK_rcvd) //active channel switchover true only after acknowledge receive { ACK_rcvd = false; led_ctrl[REQ_-1] = OFF; if(addr_ID == pot_Master) { if(ack_ADDR == 3 || ack_ADDR == 4) { if(ach_S == pot_Slave_MCR) ach_S = pot_Slave_ER; else if(ach_S == pot_Slave_ER) ach_S = pot_Slave_MCR; } else __nop(); if(ack_ADDR == 2 || ack_ADDR == 1) { if(ach_M == pot_Master) ach_M = pot_Submaster; else if(ach_M == pot_Submaster) ach_M = pot_Master; } else __nop(); switch_CH = true; state_cnt = 0; R_A_Ticker.detach(); } else { state_cnt = 0; R_A_Ticker.detach(); } } else __nop(); } void DIR_state_machine(void) { static int dir_state_cnt = 0; if(DIR_cmd_ack) { DIR_cmd = false; DIR_cmd_ack = false; current_status_dir = 1; //steady led_dir[dir-1] = ON; //led direction acknowledged turn steady buzzer = OFF; //buzzer Off hooter = OFF; DIR_Ticker.detach(); } else { if((++dir_state_cnt >= 12) && (hooter == OFF)) //direction command not ack for 03 sec { hooter = ON; dir_state_cnt = 0; } else __nop(); } } void HB_fail_state_machine() { static uint8_t fail_count = 0; if(HB_rcvd) { HB_rcvd = false; device_ERR = false; } else if(++fail_count >=3) // if max 07 number of connected eots 7x3=21, it takes 150x21=3.150 sec to alarm { fail_count = 0; led_dir[dir-1] = OFF; //current command if any turned OFF led_cmd_ack = OFF; display_flash = false; device_ERR = true; max7219.disable_device(2); //shutdown mode wait_ms(2); if(addr_ID != ach_M) { for(uint8_t i = 0; i <=7; i++) { led_ach[i] = OFF; //all other active chnnels leds or device errors } led_ach[addr_ID - 1] = _FLASH; //specific device is in error flshes only } HB_fail.detach(); } } void NUMERIC_handler(uint8_t key_ID) //function sacnning all the 0-9 number keys { uint8_t num; num = key_ID; if(key_ID != FALSE0) { if(((ach_M == pot_Master) && (addr_ID == pot_Master)) || ((ach_M == pot_Submaster) && (addr_ID == pot_Submaster))) //for Master { if(disp_clear) //if last command has been acknowledged { for (uint8_t j = 0; j < 4; j++) { rpm_data[j] = 0; //clear rpm_data to enter new values } disp_clear = false; } else __nop(); for (uint8_t j = 0; j < 4; j++) { rpm_data[j] = rpm_data[j + 1]; //at every key press array shift to left } rpm_data[3] = num; //new value be updated at place of digit 4 for (uint8_t j = 1; j <= 4; j++) { max7219.write_digit(2,j,rpm_data[j-1]); } } else __nop(); } else __nop(); } void CTRL_handler(uint8_t CTRL_ID) //handle control transfer { if(CTRL_ID != FALSE1) { if((addr_ID == pot_Slave_MCR) || (addr_ID == pot_Slave_ER)) { if((CTRL_ID == REQ_)&&(!REQ_rcvd)) //if no request has been received { req = REQ_; //req data updated 0 here, same int values as in enum REQ_key = true; led_ctrl[REQ_-1] = _FLASH; //req led flash starts R_A_Ticker.attach(&R_A_Statemachine,0.5); } else __nop(); if((CTRL_ID == ACK_)&& (REQ_rcvd)) { REQ_rcvd = false; ack = ACK_; //ack data updated 2 here ACK_key = true; int_B.rise(NULL); //interrupt disabled wait_us(10); mcp23s17_1.gpintenb(0x00); //ACK key interrupts disabled wait_us(10); led_ctrl[ACK_-1] = OFF; //ack led turns off R_A_Ticker.detach(); } else __nop(); } } else __nop(); //then do nothing } void DIR_handler(uint8_t DIR_ID) //handle control transfer { if(DIR_ID != FALSE2) { if(addr_ID == ach_M) { current_status_dir = 2; //flash led_dir[dir-1] = OFF; dir = DIR_ID; led_dir[dir-1] = _FLASH; //led direction AHEAD start flashing buzzer = ON; //buzzer ON DIR_cmd = true; // dir cmd needs to be sent } else __nop(); if (addr_ID == ach_S) { if((dir == DIR_ID)&&(DIR_cmd)) //direction command is received { current_status_dir = 1; led_dir[dir-1] = OFF; dir = DIR_ID; led_dir[dir-1] = ON; //led direction AHEAD start flashing buzzer = OFF; //buzzer OFF DIR_key = true; //dir ack will be sent in response to HB } else __nop(); } else __nop(); } else __nop(); //then do nothing } void DISP_handler(uint8_t DISP_ID) //handle control transfer { uint8_t disp_key; disp_key = DISP_ID; if(DISP_ID != FALSE3) { switch(disp_key) { case clr_ENTRY: //CE,elete only last/4th digit and shift others digits towards right/4th digit if(addr_ID == ach_M) { for (uint8_t j = 3; j > 0; j--) { rpm_data[j] = rpm_data[j - 1]; //at every key press array shift to left } rpm_data[0] = 0; for (uint8_t j = 1; j <= 4; j++) { max7219.write_digit(2,j,rpm_data[j-1]); } } else { __nop(); } break; case clr_ALL: if(addr_ID == ach_M) { //C delete all digits in DS1 and show last entered value for (uint8_t j = 0; j <=3; j++) { rpm_data[j] = 0; //at every key press array shift to left } for (uint8_t j = 1; j <= 4; j++) // all digits turns to zero { max7219.write_digit(2,j,rpm_data[j-1]); } } else { __nop(); } break; case ENTER_ACK: //work as Enter in master and CMD ACK in slave if((addr_ID == ach_S)&&(RPM_cmd)) //RPM command ack needs to be sent { RPM_cmd = false; display_flash = false; buzzer = OFF; int_B.rise(NULL); wait_us(10); mcp23s17_1.gpintenb(0x00); //ACK key interrupts disabled wait_us(10); ENTER_ACK_key = true; //flashing display1 turned steady //RPM command acknowledged by active slave } else if (addr_ID == ach_M) //in case of active masters { //disp1 start flashing, and data sent over UART for all digits 1-4 display_flash = true; //display starts flashing mcp23s17_1.gpintena(0x00); //ACK key interrupts disabled wait_us(10); mcp23s17_1.gpintenb(0x00); //ACK key interrupts disabled wait_us(10); current_status = 2; //flash buzzer = ON; RPM_cmd = true; //command need to be send } else { __nop(); } break; default: __nop(); break; } } else __nop(); //then do nothing } /****************************************************************** function to set brightness of leds and seven segment ******************************************************************/ void SET_handler(uint8_t Set_ID) { if(Set_ID != FALSE2) { switch(Set_ID) { case INC: duty_cycle = mypwm.read(); //as duty cycle decreases creases brightnes increases if( duty_cycle > 0.02f) { duty_cycle = duty_cycle-0.01f; mypwm.write(duty_cycle); } else { duty_cycle = 0.01f; } if(DEVICE1.intensity < 14) { DEVICE1.intensity ++; //intensity modified DEVICE2.intensity ++; max7219.set_intensity(DEVICE1); //updating brightness value of DEVICE1 max7219.set_intensity(DEVICE2); //updating brightness value of DEVICE2 } else { DEVICE1.intensity =15; DEVICE2.intensity =15; max7219.set_intensity(DEVICE1); //updating brightness value of DEVICE1 max7219.set_intensity(DEVICE2); //updating brightness value of DEVICE2 } break; case DEC: duty_cycle = mypwm.read(); if( duty_cycle < 0.98f) //as duty cycle increases brightnes decreases { duty_cycle = duty_cycle+0.01f; mypwm.write(duty_cycle); } else { duty_cycle = 0.99f; } if(DEVICE1.intensity > 2) { DEVICE1.intensity --; //intensity modified DEVICE2.intensity --; max7219.set_intensity(DEVICE1); //updating brightness value of DEVICE1 max7219.set_intensity(DEVICE2); //updating brightness value of DEVICE2 } else { DEVICE1.intensity =1; DEVICE2.intensity =1; //minimum brightnes max7219.set_intensity(DEVICE1); //updating brightness value of DEVICE1 max7219.set_intensity(DEVICE2); //updating brightness value of DEVICE2 } break; case TEST: test_cnt++; if(test_cnt <= 1) test = true; else if(test_cnt >= 2) { test = false; test_cnt = 0; } else __nop(); break; default: __nop(); break; } } else __nop(); } /************************************************************************************** POT SPI Data Read KEY FUNCTIONS **************************************************************************************/ unsigned char read_KEY_SPI(int CH) { char _key; switch(CH) { case 1: wait_ms(1); _key = mcp23s17_1.intcapa(); // read(INTCAPA_ADDR); wait_ms(1); break; case 2: wait_ms(1); _key=mcp23s17_1.intcapb(); wait_ms(1); break; case 3: wait_ms(1); _key=mcp23s17_2.intcapa(); wait_ms(1); break; case 4: wait_ms(1); _key = mcp23s17_2.gpiob(); //address read PORTB of chip2 wait_ms(1); break; default: _key = 0; break; } return(_key); } void read_KEY_A() //function check status of PORTA of MCP23S17 (1) chip { char key_status = 0; uint8_t num_KEY = 0; key_status = read_KEY_SPI(ch_A); //to read portA of mcp23s17(1) if(key_status != 0xff) //means some key must have been pressed { switch(key_status) { case 0xfe: //0xfe GPA0 num_KEY = ZERO; break; case 0xfd: //0xfd GPA1 num_KEY = ONE; break; case 0xfb: //0xfb GPA2 num_KEY = TWO; break; case 0xf7: //0xf7 GPA3 num_KEY = THREE; break; case 0xef: //0xef GPA4 num_KEY = FOUR; break; case 0xdf: //0xdf GPA5 num_KEY = FIVE; break; case 0xbf: //0xbf GPA6 num_KEY = SIX; break; case 0x7f: //0x7f GPA7 num_KEY = SEVEN; break; default: num_KEY = FALSE0; break; } NUMERIC_handler(num_KEY); } } void read_KEY_B() { char key_status = 0; uint8_t num_KEY = 0; uint8_t dir_KEY = 0; uint8_t disp_KEY = 0; uint8_t ctrl_KEY = 0; key_status = read_KEY_SPI(ch_B); //to read portBof mcp23s17(1) if(key_status != 0xff) { switch(key_status) { case 0xfe: //0xfe GPA0 num_KEY = EIGHT; NUMERIC_handler(num_KEY); break; case 0xfd: //0xfd GPA1 num_KEY = NINE; NUMERIC_handler(num_KEY); break; case 0xfb: //0xfb GPA2 dir_KEY = AHEAD; DIR_handler(dir_KEY); break; case 0xf7: //0xf7 GPA3 dir_KEY = ASTERN; DIR_handler(dir_KEY); break; case 0xef: //0xef GPA4 ctrl_KEY = ACK_; CTRL_handler(ctrl_KEY); break; case 0xdf: //0xdf GPA5 disp_KEY = clr_ENTRY; //CE DISP_handler(disp_KEY); break; case 0xbf: //0xbf GPA6 disp_KEY = clr_ALL; //C DISP_handler(disp_KEY); break; case 0x7f: //0x7f GPA7 disp_KEY = ENTER_ACK; DISP_handler(disp_KEY); break; default: num_KEY = FALSE0; ctrl_KEY = FALSE1; dir_KEY = FALSE2; disp_KEY = FALSE3; break; } } } void read_KEY_C() { char key_status = 0; uint8_t ctrl_KEY = 0; uint8_t set_KEY = 0; key_status = read_KEY_SPI(ch_C); //to read portA of mcp23s17(2) if(key_status != 0xff) { if(key_status==0xfe) { ctrl_KEY = REQ_; //control transfer REQ button pressed CTRL_handler(ctrl_KEY); } else { if(key_status==0xfd) set_KEY = INC; //setting key INC else if(key_status==0xfb) set_KEY = DEC; //setting key DEC else if(key_status==0xf7) set_KEY = TEST; //setting key TEST else { set_KEY = FALSE4; //setting key TEST ctrl_KEY = FALSE1; } SET_handler(set_KEY); } } } /************************************************************************************** POT Serial Data Out FUNCTIONS **************************************************************************************/ uint8_t get_checksum(const char *sentence) { const char *n = sentence + 1; // Plus one, skip '$' uint8_t chk = 0; /* While current char isn't '*' or sentence ending (newline) */ while (('*' != *n) &&(NMEA_END_CHAR_1 != *n)) { if ('\0' == *n || n - sentence > NMEA_MAX_LENGTH) { /* Sentence too long or short */ chk = 0; } chk ^= (uint8_t) *n; n++; } return chk; } void resp_HB(uint8_t seq) //presentees(submaster,slaves,listeners will respond back to the HB along with REQ and CMD ack status { switch(seq) { case 0: sprintf(tx_buf,"$PPOTA,%u,%c*", addr_ID,valid); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTA,%u,%c*%u",addr_ID,valid,checksum_send_byte); break; case 1: sprintf(tx_buf,"$PPOTR,%u,%u,%c*", addr_ID, REQ_,'A'); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTR,%u,%u,%c*%u",addr_ID,REQ_,'A',checksum_send_byte); break; case 2: sprintf(tx_buf,"$PPOTK,%u,%u,%c*", addr_ID, ACK_,'A'); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTK,%u,%u,%c*%u",addr_ID, ACK_,'A',checksum_send_byte); break; default: __nop(); //sprintf(tx_buf,"$PPOTA,%u,%c", addr_ID, valid); break; } Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; } void send_ack_CMD(uint8_t cmd_t) { sprintf(tx_buf,"$PPOTX,%u,%u,%c*", addr_ID, cmd_t,'A'); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTX,%u,%u,%c*%u",addr_ID,cmd_t,'A',checksum_send_byte); Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; } void send_RPM(uint8_t _adr) { sprintf(tx_buf,"$PPOTC,%u,%u,%u,%u,%u,%c*", _adr, rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3],'A'); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTC,%u,%u,%u,%u,%u,%c*%u",_adr, rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3],'A',checksum_send_byte); Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; } void send_DIR(uint8_t _adr) //addr 1-8 of leds,error=1 or 0(no error) { sprintf(tx_buf,"$PPOTD,%u,%u,%c*",_adr,dir,'A'); // dir is 1 for ahead, 2 for astern checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTD,%u,%u,%c*%u",_adr,dir,'A',checksum_send_byte); Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; } void send_HB(uint8_t _adr) //master will send the heartbeat to all presentees at periodic intervals { sprintf(tx_buf,"$PPOTH,%u,%c*", _adr,'A'); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTH,%u,%c*%u",_adr,'A',checksum_send_byte); Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; } void send_BROADCAST() //addr 1-8 of leds,error=1 or 0(no error) { sprintf(tx_buf,"$PPOTB,%u,%u,%c*",err_ALL,err_Status,'A'); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTB,%u,%u,%c*%u",err_ALL,err_Status,'A',checksum_send_byte); Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; BROADCAST_send=false; } /** Function will send ac-M, ac-S, rpm-data(04digits), cmd_state)**/ void send_ACH() { sprintf(tx_buf,"$PPOTS,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%c*", ach_M, ach_S, rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3],last_entry[0],last_entry[1],last_entry[2],last_entry[3],dir,current_status,current_status_dir,'A'); checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTS,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%c,*%u", ach_M, ach_S, rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3],last_entry[0],last_entry[1],last_entry[2],last_entry[3],dir,current_status,current_status_dir,'A',checksum_send_byte); Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; } void ask_TIME() { Hrs_1 = Hrs_2 = Mins_1 = Mins_2 = 0; sprintf(tx_buf,"$PPOTQ,%u,%u,%u,%u,%c*", Hrs_1,Hrs_2, Mins_1, Mins_2,'A'); //querry to CPU for time checksum_send_byte = get_checksum(tx_buf); sprintf(tx_buf,"$PPOTQ,%u,%u,%u,%u,%c*%u", Hrs_1,Hrs_2, Mins_1, Mins_2,'A',checksum_send_byte); Drive_En = 1; UART.printf("%s\r\n",tx_buf); wait_ms(2); Drive_En = 0; } /************************************************************************************** EOT Serial Data In FUNCTIONS **************************************************************************************/ void rcvd_HB() //all devices check for HB along with req response for all presentees { if(rcvd_ADDR == addr_ID) //addr_ID self address received { HB_rcvd = true; if(addr_ID > pot_Slave_ER) { //all listners replied with resp_HB(0); //normal HB response } else //in case of active slave { if(ENTER_ACK_key) //RPM ACK key is detected at active slave only { send_ack_CMD(1); RPM_cmd_ack = true; ENTER_ACK_key = false; } else if(DIR_key) //dir ack key detected at active slave { DIR_key = false; DIR_cmd_ack_send = true; send_ack_CMD(2); } else if(REQ_key) { REQ_key = false; resp_HB(1); //req and ack status data in req=1 and ack=2 if true } else if(ACK_key) { ACK_key = false; resp_HB(2); //req and ack status data in req=1 and ack=2 if true } else resp_HB(0); //req and ack status data in req=1 and ack=2 if true } HB_fail.attach(&HB_fail_state_machine,1); } else __nop(); } void resp_rcvd_HB() //master and active/passive slaves check HB response along with req/ack commands { static uint8_t checksum_flt[8] = {0,0,0,0,0,0,0,0}; static bool checksum_err[8] = {false,false,false,false,false,false,false,false}; if(addr_ID == pot_Master) //only master will be able to monitor status of all eots connected { if(send_ADDR == rcvd_ADDR) //valid broadcast not received { if(valid_sentence[rcvd_ADDR] == 'A') { HB_ack_rcvd = true; checksum_err[rcvd_ADDR] = false; checksum_flt[rcvd_ADDR] = 0; } else if((valid_sentence[rcvd_ADDR] == 'V')&&(++checksum_flt[rcvd_ADDR]<=3)) { HB_ack_rcvd = true; BROADCAST_send = true; //again broadcast switch_CH = true; //send active channels again } else if((valid_sentence[rcvd_ADDR] == 'V')&&(checksum_flt[rcvd_ADDR]>3)&&(!checksum_err[rcvd_ADDR])) { HB_ack_rcvd = false; checksum_err[rcvd_ADDR] = true; } else __nop(); } else HB_ack_rcvd = false; } else __nop(); } void rcvd_ACH() { led_ach[ach_M-1] = ON; if(current_status == 2) { led_cmd_ack = _FLASH; max7219.enable_device(2); display_flash = true; } else if(current_status == 1) { led_cmd_ack = ON; max7219.enable_device(2); display_flash = false; } else { led_cmd_ack = OFF; max7219.enable_device(2); } if(current_status_dir == 2) { led_dir[dir-1] = _FLASH; } else if(current_status_dir == 1) { led_dir[dir-1] = ON; } else { led_dir[dir-1] = OFF; } for(uint8_t i = 1; i <= 4 ; i++) //current cmd information { max7219.write_digit(2,i,rpm_data[i-1]); //device 2 digits 1-4 //data 0 means left most digit will be blank bcoz no decode mode is used } for(uint8_t i = 5; i <=8; i++) //last command executed { max7219.write_digit(1,i,last_entry[i-5]); //last cmd 0000 } if(ach_S != 9) { if(ach_S == pot_Slave_MCR) { led_ach[pot_Slave_MCR -1] = ON; if(led_ach[pot_Slave_ER -1] == ON) led_ach[pot_Slave_ER -1] = OFF; //ER off else __nop(); } else if(ach_S == pot_Slave_ER) { led_ach[pot_Slave_ER -1] = ON; //ER ON if(led_ach[pot_Slave_MCR -1] == ON) led_ach[pot_Slave_MCR -1] = OFF; //ER off else __nop(); } else __nop(); if((RPM_cmd || DIR_cmd)&& (addr_ID == ach_S)) // cmd ack not received before its failure control shifted to another slave { //all key functions enabled for PORTB in active slave only int_B.rise(&read_KEY_B); wait_us(10); mcp23s17_1.gpintenb(0xff); //ff wait_us(10); } else __nop(); } else { led_ach[pot_Slave_MCR-1] = _FLASH; led_ach[pot_Slave_ER-1] = _FLASH; } } void rcvd_rpm_CMD() //all devices check for received command { led_cmd_ack = _FLASH; //ack cmd led start flashing for(uint8_t i = 0; i <= 3 ; i++) { max7219.write_digit(2,i+1,rpm_data[i]); //device 2 digits 1-4 //data 0 means left most digit will be blank bcoz no decode mode is used } wait_us(10); buzzer = ON; display_flash = true; //display start flashing //buzzer on if(ach_S == addr_ID) { int_B.rise(&read_KEY_B); wait_us(10); mcp23s17_1.gpintenb(0xff); //ff wait_us(10); //portc is always enbaled in all cases and PORTA is enabled only for active master } else { __nop(); } CMD_Ticker.attach(&CMD_State_Machine,0.25); //state machine timer started in all connected devices except master } void rcvd_dir_CMD() //all devices check for received command { DIR_cmd = true; led_dir[last_dir-1] = OFF; led_dir[dir-1] = _FLASH; //led flash started buzzer = ON; //buzzer on last_dir = dir; //HB-cmd ack pending with "A" if(ach_S == addr_ID) { int_B.rise(&read_KEY_B); //enable portb interupts mcp23s17_1.gpintenb(0xff); //ff wait_us(10); } DIR_Ticker.attach(&DIR_state_machine,0.25); } void rcvd_BROADCAST() { for(uint8_t i = 0 ; i <= 7 ; i++) { if(((uint8_t)1<<i) & (uint8_t)err_ALL) { led_ach[i] = _FLASH; } else if(led_ach[i] != ON) { led_ach[i]= OFF; } else __nop(); } } void rcvd_TIME() { uint8_t Hrs,Mins; struct tm t; Hrs = 10*Hrs_1+Hrs_2; Mins = 10*Mins_1+Mins_2; t.tm_year = 2018-1900; t.tm_mon = 5; t.tm_mday = 16; t.tm_hour = Hrs; t.tm_min = Mins; t.tm_sec = 51; set_time((time_t)mktime(&t)); wait_ms(1); read_RTC(); wait_ms(1); time_RCVD = true; } void at_timeout() { timeout.detach(); data_fail = true; } void read_SERIAL() { char rcvd_char; char rcvd_valid; int cmd_t; uint8_t checksum_calculated; timeout.attach(&at_timeout,0.100); //100ms timeout data_fail = false; while(UART.readable() && (num_bytes < RX_BUFFER_SIZE)&&(!data_fail)) { rcvd_char = UART.getc(); if(rcvd_char == '$') //first character num_bytes = 0; else __nop(); rx_buf[num_bytes] = rcvd_char; num_bytes++; if(rcvd_char == '\n') //last character received { timeout.detach(); strtok(rx_buf,","); if(strcmp(rx_buf,"$PPOTH") == 0) //* present submaster,Slaves or lsitners receive HB *// { sscanf(strtok (NULL,","),"%u", &rcvd_ADDR); //address of connected device sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTH,%u,%c*",rcvd_ADDR,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { rcvd_HB(); //valid sentence received } else __nop(); //valid sentence receivedrcvd_HB(); //set flag when Heartbeat received } else if(strcmp(rx_buf,"$PPOTA") == 0) //* Master,submaster and Slaves receive heartbeat resp *// { sscanf(strtok (NULL,","),"%u", &rcvd_ADDR); sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTA,%u,%c*",rcvd_ADDR,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid_sentence[rcvd_ADDR] = rcvd_valid; resp_rcvd_HB(); //valid sentence received } else __nop(); } else if(strcmp(rx_buf,"$PPOTB") == 0) //* submaster,Slaves or listener receive broadcast *// { sscanf(strtok (NULL,","), "%u", &err_ALL); //device in error with addr_ID = err_ID sscanf(strtok (NULL,","), "%u",&err_Status); sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTB,%u,%u,%c*",err_ALL,err_Status,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { //valid sentence received valid = 'A'; rcvd_BROADCAST(); } else valid = 'V'; //not valid } else if(strcmp(rx_buf,"$PPOTC") == 0) //* submaster,Slaves or listener receive CMD *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); //cmd extracted sscanf(strtok (NULL,","), "%u", &rpm_data[0]); //rpm data digit 1 and soon sscanf(strtok (NULL,","), "%u", &rpm_data[1]); sscanf(strtok (NULL,","), "%u", &rpm_data[2]); sscanf(strtok (NULL,","), "%u",&rpm_data[3]); sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTC,%u,%u,%u,%u,%u,%c*",rcvd_ADDR,rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3],rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid = 'A'; RPM_cmd = true; // in all devices who receive RPM command rcvd_rpm_CMD(); } else valid = 'V'; } else if(strcmp(rx_buf,"$PPOTD") == 0) //* present submaster,Slaves or lsitners receive HB *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); //address of connected device sscanf(strtok (NULL,","), "%u",&dir); // 1 for ahead and 2 for astern sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTD,%u,%u,%c*",rcvd_ADDR,dir,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid = 'A'; DIR_cmd = true; rcvd_dir_CMD(); } else valid = 'V'; //set flag when Heartbeat received } else if(strcmp(rx_buf,"$PPOTX") == 0) //* Master,submaster,Slave or listners receive CMD acknowledge *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); //address extracted sscanf(strtok (NULL,","), "%u",&cmd_t); sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTX,%u,%u,%c*",rcvd_ADDR,cmd_t,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid = 'A'; switch(cmd_t) { case 1: RPM_cmd_ack = true; break; case 2: DIR_cmd_ack = true; led_dir[last_dir-1] = OFF; last_dir = dir; led_dir[dir-1] = ON; break; default: __nop(); break; } } else valid = 'V'; // not valid sentence received; } else if(strcmp(rx_buf,"$PPOTS") == 0) //*active channel status recieved *// { sscanf(strtok (NULL,","), "%u", &ach_M); //cmd extracted sscanf(strtok (NULL,","), "%u", &ach_S); sscanf(strtok (NULL,","), "%u", &rpm_data[0]); sscanf(strtok (NULL,","), "%u", &rpm_data[1]); sscanf(strtok (NULL,","), "%u", &rpm_data[2]); sscanf(strtok (NULL,","), "%u", &rpm_data[3]); sscanf(strtok (NULL,","), "%u", &last_entry[0]); sscanf(strtok (NULL,","), "%u", &last_entry[1]); sscanf(strtok (NULL,","), "%u", &last_entry[2]); sscanf(strtok (NULL,","), "%u", &last_entry[3]); sscanf(strtok (NULL,","), "%u", &dir); sscanf(strtok (NULL,","), "%u", ¤t_status); sscanf(strtok (NULL,","),"%u", ¤t_status_dir); sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTS,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%u,%c*",ach_M,ach_S,rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3],last_entry[0],last_entry[1],last_entry[2],last_entry[3],dir,current_status,current_status_dir,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid = 'A'; //valid sentence received rcvd_ACH(); } else valid = 'V'; } else if(strcmp(rx_buf,"$PPOTR") == 0) //* control transfer request arrived*// { sscanf(strtok (NULL,","),"%u", &rcvd_ADDR); sscanf(strtok (NULL,","),"%u", &req); //e.g $R req or $K ack sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); if(addr_ID <= pot_Slave_ER) { sprintf(rx_buf,"$PPOTR,%u,%u,%c*",rcvd_ADDR,req,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid = 'A'; REQ_rcvd = true; req_ADDR = rcvd_ADDR; if(((rcvd_ADDR == pot_Master) && (addr_ID == pot_Submaster)) || ((rcvd_ADDR == pot_Submaster) && (addr_ID == pot_Master))) { int_B.rise(&read_KEY_B); //to enable ACK key interrupt wait_us(10); mcp23s17_1.gpintenb(0xff); // portb of mcp1 ACK key enabled wait_us(10); led_ctrl[ACK_-1] = _FLASH; //ack led blink } else __nop(); if(((rcvd_ADDR == pot_Slave_MCR) && (addr_ID == pot_Slave_ER)) || ((rcvd_ADDR == pot_Slave_ER) && (addr_ID == pot_Slave_MCR))) { int_B.rise(&read_KEY_B); //to enable ACK key interrupt wait_us(10); mcp23s17_1.gpintenb(0xff); //portb of mcp1 ACK key enabled wait_us(10); led_ctrl[ACK_-1] = _FLASH; //ack led blink } else __nop(); R_A_Ticker.attach(&R_A_Statemachine,0.5); } else valid = 'V'; } else __nop(); } else if(strcmp(rx_buf,"$PPOTK") == 0) //* Master,submaster,Slave or listners REQ acknowledge *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); sscanf(strtok (NULL,","),"%u", &ack); //e.g $R req or $K ack sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); if(addr_ID <= pot_Slave_ER) { sprintf(rx_buf,"$PPOTK,%u,%u,%c*",rcvd_ADDR,ack,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid = 'A'; ack_ADDR = rcvd_ADDR; ACK_rcvd = true; //ACH_SW_over = true; if(((rcvd_ADDR == pot_Master) && (addr_ID == pot_Submaster)) || ((rcvd_ADDR == pot_Submaster) && (addr_ID == pot_Master))) { led_ctrl[ACK_-1] = OFF; //R_A_Ticker.detach(); } else if(((rcvd_ADDR == pot_Slave_ER) && (addr_ID == pot_Slave_MCR)) || ((rcvd_ADDR == pot_Slave_MCR) && (addr_ID == pot_Slave_ER))) { led_ctrl[ACK_-1] = OFF; //R_A_Ticker.detach(); } else __nop(); } else valid = 'V'; } else __nop(); } else if(strcmp(rx_buf,"$PPOTT") == 0) //* submaster,Slaves or listener receive CMD *// { sscanf(strtok (NULL,","), "%u", &Hrs_1); //cmd extracted sscanf(strtok (NULL,","), "%u", &Hrs_2); sscanf(strtok (NULL,","), "%u", &Mins_1); sscanf(strtok (NULL,","),"%u", &Mins_2); sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); //sentence validity char sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte); sprintf(rx_buf,"$PPOTT,%u,%u,%u,%u,%c*",Hrs_1,Hrs_2,Mins_1,Mins_2,rcvd_valid); checksum_calculated = get_checksum(rx_buf); if(checksum_calculated == checksum_rcvd_byte) { valid = 'A'; rcvd_TIME(); } else valid = 'V'; } else __nop(); } else __nop(); } } /********END of FUNCTION****************/ /************************************************************************************** EOT Handler FUNCTIONS **************************************************************************************/ void HB_handler() //function run periodically within active master only { if(++sync_count >= sync_time) { time_RCVD = false; norm_op = false; sync_count = 0; ask_TIME(); //master will send querry for GPS time } else if(time_RCVD || norm_op) //as all receive time update normal operation starts { if(ach_M == pot_Master) { device_addr++; if(device_addr == no_pot_connected) //max no-pot-conneted = 7 device_addr = 0; } else __nop(); /*else if(ach_M == eot_Submaster) { if(device_addr==2) { device_addr=3; } else { device_addr++; if(device_addr>NO_MAX_EOT) device_addr=1; } } */ send_ADDR = POT[device_addr].slave_ID; if(RPM_cmd) { send_RPM(send_ADDR); RPM_cmd = false; //cmd to be send with current running address and cmd value wait_ms(2); //HB_Ticker.attach(&HB_State_Machine,0.010); CMD_Ticker.attach(&CMD_State_Machine,0.25); //CMD_state_machine ticker started } else if(DIR_cmd) { send_DIR(send_ADDR); DIR_cmd = false; //cmd to be send with current running address and cmd value wait_ms(2); //HB_Ticker.attach(&HB_State_Machine,0.010); DIR_Ticker.attach(&DIR_state_machine,0.25); //CMD_state_machine ticker started } else if(BROADCAST_send) { send_BROADCAST(); //broadcast needed err_ID nd err_Status BROADCAST_send = false; wait_ms(2); } else if(switch_CH) //active channel switch over happened { send_ACH(); //active channel changeover switch_CH = false; wait_ms(2); } else { send_HB(send_ADDR); //hb is to be going on HB_Ticker.attach(&HB_State_Machine,0.015); //HB_state_machine timer started } } else if(++norm_count >= 5) { norm_count = 0; if(!time_RCVD) norm_op = true; else __nop(); } else __nop(); } /************************************************************************************** POT config and address Read FUNCTIONS **************************************************************************************/ void read_POT_ADDR() //function give present eots and no. of connected eots { pot_Addr = read_KEY_SPI(ch_D); if(pot_Addr==0xff) //if 0xff it means no addressing done pot_Error=true; else if(pot_Addr!=0xff) { for( uint8_t i=0;i<=7;i++) { if(((1 << i) & pot_Addr)== 0) // to check which bit of eot_Addr register is '0' { if(i==0) // bit 0 means master present and soon { addr_ID = pot_Master; ach_M = pot_Master; for(i = 1 ; i <= 7 ; i++) { if((((uint8_t)1<<i) & pot_Addr) == 0) { switch(i) { case 1: POT[no_pot_connected].slave_ID = pot_Submaster; POT[no_pot_connected].err_cnt=0; POT[no_pot_connected].err_status=false; no_pot_connected++; break; case 2: ach_S = pot_Slave_MCR; POT[no_pot_connected].slave_ID = pot_Slave_MCR; POT[no_pot_connected].err_cnt=0; POT[no_pot_connected].err_status=false; no_pot_connected++; break; case 3: if(ach_S == pot_Slave_MCR) //if MCR ispresent __nop(); else { //if MCR is not present ach_S = pot_Slave_ER; } POT[no_pot_connected].slave_ID = pot_Slave_ER; POT[no_pot_connected].err_cnt = 0; POT[no_pot_connected].err_status=false; no_pot_connected++; break; case 4: POT[no_pot_connected].slave_ID = pot_Listner_WP; POT[no_pot_connected].err_cnt = 0; POT[no_pot_connected].err_status=false; no_pot_connected++; break; case 5: POT[no_pot_connected].slave_ID = pot_Listner_WS; POT[no_pot_connected].err_cnt=0; POT[no_pot_connected].err_status=false; no_pot_connected++; break; case 6: POT[no_pot_connected].slave_ID = pot_Listner_OPS; POT[no_pot_connected].err_cnt=0; POT[no_pot_connected].err_status=false; no_pot_connected++; break; case 7: POT[no_pot_connected].slave_ID = pot_Listner_ASP; POT[no_pot_connected].err_cnt=0; POT[no_pot_connected].err_status=false; no_pot_connected++; break; } } } if(no_pot_connected <=0) pot_Error = true; else pot_Error = false; } else { switch(i) { case 1: { addr_ID = pot_Submaster; ach_S = pot_Slave_MCR; led_ach[ach_S-1] = ON; break; } case 2: { addr_ID = pot_Slave_MCR; ach_S = pot_Slave_MCR; led_ach[ach_S-1] = ON; break; } case 3: { addr_ID = pot_Slave_ER; ach_S = pot_Slave_MCR; led_ach[ach_S-1] = ON; break; } case 4: { addr_ID = pot_Listner_WP; ach_S = pot_Slave_MCR; led_ach[ach_S-1] = ON; break; } case 5: { addr_ID = pot_Listner_WS; ach_S = pot_Slave_MCR; led_ach[ach_S-1] = ON; break; } case 6: { addr_ID = pot_Listner_OPS; ach_S = pot_Slave_MCR; led_ach[ach_S-1] = ON; break; } case 7: { addr_ID = pot_Listner_ASP; ach_S = pot_Slave_MCR; led_ach[ach_S-1] = ON; break; } default: pot_Error = true; } } } } } } void interrupt_init() { int_A.mode(PullUp); wait_ms(1); int_B.mode(PullUp); wait_ms(1); int_C.mode(PullUp); wait_ms(1); } void Uart_init() { UART.baud(9600); UART.format(8,SerialBase::None,1); wait_ms(1); } void Led_init() { LED_CMD_ACK = ON; wait_ms(1); for(uint8_t i=0;i<=1;i++) //ctrl led intialisation { LED_CTRL[i] = ON; wait_ms(1); } for(uint8_t i=0;i<=1;i++) //ctrl led intialisation { LED_DIR[i] = ON; wait_ms(1); } for(uint8_t i=0; i<=7;i++) //ach led initialisation { LED_ACH[i] = ON ; wait_ms(1); } wait(1); LED_CMD_ACK = OFF; led_cmd_ack = OFF; wait_ms(1); for(uint8_t i=0;i<=1;i++) //ctrl led turned off { LED_CTRL[i] = OFF; led_ctrl[i] = OFF; wait_ms(1); } for(uint8_t i=0;i<=1;i++) //ctrl led intialisation { LED_DIR[i] = OFF; led_dir[i] = OFF; wait_ms(1); } for(uint8_t i=0; i<=7;i++) //ach led turned off { LED_ACH[i] = OFF; led_ach[i] = OFF; wait_ms(1); } } void pwm_init() { mypwm.period_ms(10); //initialy 20ms wait_us(1); mypwm.write(.10); //10%duty cycle more bright with less duty cycle wait_us(1); } void mcp23s17_init() { //device1 configuration mcp23s17_1.reset(); //reset on power-up wait_ms(1); mcp23s17_2.reset(); //reset on power-up wait_ms(1); mcp23s17_1.iocon(0x2a); wait_ms(1); mcp23s17_2.iocon(0x2a); wait_ms(1); mcp23s17_1.iodira(0xff); //set 8-bits PORTA as inputs wait_ms(1); mcp23s17_1.iodirb(0xff); //set 8-bits PORTB as inputs wait_ms(1); mcp23s17_1.ipola(0x00); wait_ms(1); mcp23s17_1.ipolb(0x00); wait_ms(1); mcp23s17_1.gpintena(0x00); //initially disabled wait_ms(1); mcp23s17_1.gpintenb(0x00); wait_ms(1); mcp23s17_1.defvala(0xff); wait_ms(1); mcp23s17_1.defvalb(0xff); wait_ms(1); mcp23s17_1.intcona(0x00); //bank0,mirror disabled, SEQOP disabled, slew rate disabled,HAEN enabled,open drain enabled,interrupt active high,not allowed wait_ms(1); mcp23s17_1.intconb(0x00); wait_ms(1); mcp23s17_1.gppua(0xff); wait_ms(1); mcp23s17_1.gppub(0xff); wait_ms(1); //device2 configuration mcp23s17_2.iodira(0xff); //set 8-bits PORTA as inputs wait_ms(1); mcp23s17_2.iodirb(0xff); //set 8-bits PORTb as inputs wait_ms(1); mcp23s17_2.ipola(0x00); wait_ms(1); mcp23s17_2.ipolb(0x00); wait_ms(1); mcp23s17_2.gpintena(0xff); //initially 0xff will be always enabled req/inc/dec/test wait_ms(1); mcp23s17_2.gpintenb(0x00); //interrupts disabled for address PORT wait_ms(1); mcp23s17_2.defvala(0xff); wait_ms(1); mcp23s17_2.defvalb(0xff); wait_ms(1); mcp23s17_2.intcona(0x00); //bank0,mirror disabled, SEQOP disabled, slew rate disabled,HAEN enabled,open drain enabled,interrupt active high,not allowed wait_ms(1); mcp23s17_2.intconb(0x00); wait_ms(1); mcp23s17_2.gppua(0xff); wait_ms(1); mcp23s17_2.gppub(0xff); wait_ms(1); mcp23s17_1.intcapa(); //dummy read performed to clear any interrupt on power up wait_ms(1); mcp23s17_1.intcapb(); wait_ms(1); mcp23s17_2.intcapa(); wait_ms(1); } void Spi3_init() //for mcp23s17 { _SPI3.format(8,0); //8bit,mode 0 _SPI3.frequency(1000000); //1mhz wait_ms(1); } void RTC_init() { read_RTC(); wait_ms(1); RTC_display(RTC_buffer); wait_ms(1); } void SetDateTime ( int year = 0 ,int mon = 0 ,int day = 0 ,int hour = 0 ,int min = 0 ,int sec = 0 ) { struct tm Clock; Clock.tm_year = year - 1900; Clock.tm_mon = mon; Clock.tm_mday = day; Clock.tm_hour = hour; Clock.tm_min = min; Clock.tm_sec = sec; time_t epoch = mktime(&Clock); set_time(epoch); //time set } void max7219_init() { max7219.set_num_devices(2); //total 02 no. of devices DEVICE1.device_number = 0x01; DEVICE1.decode_mode = 0xff; //bcd decode mode DEVICE1.intensity = 0x01; //Max7219::MAX7219_INTENSITY_8, DEVICE1.scan_limit = 0x07; // 1-4 digits RTC,5-8 digits last cmd RPM wait_ms(1); DEVICE2.device_number = 0x02; // DEVICE2.decode_mode = 0xff; //bcd decode mode DEVICE2.intensity = 0x01; //Max7219::MAX7219_INTENSITY_8, //intensity moderate DEVICE2.scan_limit = 0x03; //1-4 digits current wait_ms(1); max7219.init_device(DEVICE1); //DEVICE 1 configured as per above settings wait_ms(1); max7219.enable_device(1); //normal operation wait_ms(1); max7219.init_device(DEVICE2); //DEVICE 2 configured as per above settings wait_ms(1); max7219.enable_device(2); //normal operation wait_ms(1); max7219.set_display_test(); //all on wait(1); max7219.clear_display_test(); //normal operation wait_ms(1); for(uint8_t i=1; i<=4; i++) { max7219.write_digit(1, i, 0x00); //device 1 RTC, digit 1-4 ,data 0x01 wait_us(100); } wait_ms(100); for(uint8_t i=4; i<=8; i++) { max7219.write_digit(1, i, 0x00); //device 1 last cmd, digit 4-8 ,data 0x01 wait_us(100); } wait_ms(100); for(uint8_t i=1; i<=4;i++) { max7219.write_digit(2, i, 0x00); //device 2 current CMD, digits 1-4 ,data 0x01 } wait_ms(100); } void Spi2_init() // for max7219 { _SPI2.format(16,0); //16bit,mode 0 _SPI2.frequency(1000000); //1mhz wait_ms(1); } void Discrete_init() { buzzer = ON; hooter = ON; //on wait(1); // one second delay buzzer = OFF; hooter = OFF; //off } void Parameters_init() { /*intialization of all bool data types indicating different error flags */ pot_Error = false; device_ERR = false; pot_MCR_err = false; pot_ER_err = false; test = false; toggle = false; toggle_fast = false; display_flash = false; norm_op = false; /*intialization of all bool data types indicating flag on key press interruption */ key_CMD = false; key_CTRL = false; key_SET = false; REQ_key = false; ACK_key = false; RPM_cmd = false; //if true RPM command is raised DIR_cmd = false; //if true DIR command is raised ENTER_ACK_key = false; disp_clear = false; /*intialization of all bool data types indicating flags while serial receive */ RPM_cmd_ack = false; HB_ack_rcvd = false; BROADCAST_rcvd = false; HB_rcvd = false; REQ_rcvd = false; ACK_rcvd = false; time_RCVD = false; data_fail = false; /*intialization of all bool data types indicating flags while serial transmit */ BROADCAST_send = false; RPM_cmd_ack_send = false; DIR_cmd_ack_send = false; REQ_send = false; ACK_send = false; HB_send = false; /*intialization of all bool data types indicating active channel changeover*/ test=false; disp_test = false; ACH_SW_over = switch_CH = false; display_flash = false; /*intialization of all int data types*/ addr = req = ack = ach_S = ach_M = duty_cycle = sync_count = 0; pot_Addr = addr_ID = send_ADDR = rcvd_ADDR = req_ADDR = ack_ADDR = 0; test_cnt = err_ID = err_Status = ticker_count = ticker_count_fast = current_status = current_status_dir= 0; spi_error = set_bit = err_ALL = no_pot_connected = norm_count = Hrs_1 = Hrs_2 = Mins_1 = Mins_2 = 0; checksum_send_byte = checksum_rcvd_byte = 0; dir = last_dir = 0; HB_timer =0; sync_time = 0; num_bytes = 0; device_addr = -1; valid = 'A'; POT = new _POT[NO_MAX_POT]; } void POT_INIT() { Parameters_init(); wait_ms(1); Discrete_init(); wait_ms(1); Spi2_init(); wait_ms(1); max7219_init(); wait_ms(1); SetDateTime(2017,11,16,16,45,40); // set default date and time wait_ms(1); RTC_init(); wait_ms(1); Spi3_init(); wait_ms(1); mcp23s17_init(); wait_ms(1); pwm_init(); wait_ms(1); Led_init(); wait_ms(1); Uart_init(); wait_ms(1); read_POT_ADDR(); wait_ms(1); interrupt_init(); wait_ms(1); if((addr_ID == pot_Master)&&(!pot_Error)) //if addres of master eot found, by default master { wait(10); //wait for 10sec,as MCU take time to read time from GPS led_ach[ach_M-1] = ON; int_A.rise(&read_KEY_A); //all key functions enabled for PORTA,B,C int_B.rise(&read_KEY_B); int_C.rise(&read_KEY_C); wait_ms(2); mcp23s17_1.gpintena(0xff); //interrupts enabled wait_us(100); mcp23s17_1.gpintenb(0xff); //ff wait_us(100); HB_timer = 1.0/no_pot_connected; sync_time = 3600/HB_timer; // 3600.0/HB_timer; required pot_HB.attach(&HB_handler,HB_timer); // wait_ms(1); UART.attach( &read_SERIAL); //receive interrupt enabled wait_ms(1); ask_TIME(); //send enquiry to Central power unit for time setting wait_ms(2); send_ACH(); wait_ms(2); } else if(pot_Submaster <= addr_ID <= pot_Listner_ASP) { wait(1); led_ach[0] = ON; //by default master led turns on int_A.rise(NULL); //all key functions/interrupt disabled for PORTA,B int_B.rise(NULL); int_C.rise(&read_KEY_C); //only PORTC needs to be intialized in other all cases,inc,dec,tst,req wait_ms(1); UART.attach( &read_SERIAL); //receive interrupt enabled wait_ms(1); } else if(pot_Error) { int_A.rise(NULL); int_B.rise(NULL); int_C.rise(NULL); pot_Error = true; //return(-1); } else { __nop(); } } int main() { POT_INIT(); led_refresh.attach(&update_led , 0.020); //refresh rate 20ms wait_ms(2); RTC_ticker.attach(&read_RTC , 59); //after 60 sec wait_ms(2); while(1) { } }