Marine Electricals / Mbed 2 deprecated POT_V_1_1

Dependencies:   MAX7219pot MCP23S17 mbed

Fork of POT_V_1_0 by Marine Electricals

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*Board configuration
00002 >>>>>place JP5 to E5V side to use external  5V supply
00003 >>>>>Remove jumper link SB13,SB14 usb uart debug disabled
00004 >>>>>Place jumper link SB62,SB63...uart PA2,PA3 enabled by these jumper links
00005 */
00006 
00007 #include "mbed.h"
00008 #include "pot.h"
00009 #include "max7219.h"
00010 #include "MCP23S17.h"
00011 
00012 using namespace std;
00013 
00014 //------------------------------------
00015 // Hyperterminal configuration
00016 // 9600 bauds, 8-bit data, no parity
00017 //------------------------------------
00018 Serial UART(SERIAL_TX, SERIAL_RX); 
00019 
00020 //timer instances creation//
00021 Ticker pot_HB;              
00022 Ticker HB_Ticker;
00023 Ticker flash_Ticker;
00024 Ticker R_A_Ticker;
00025 Ticker CMD_Ticker;
00026 //Ticker DIR_Ticker;      //function changed to Up-Down Rpm counts
00027 Ticker HB_fail;
00028 Ticker RTC_ticker;
00029 Ticker led_refresh;
00030 Timeout timeout;
00031 
00032 //SPI instances creation//
00033 SPI _SPI2(SPI2_MOSI, SPI2_MISO, SPI2_SCK);  //for displays max7219
00034 SPI _SPI3(SPI3_MOSI, SPI3_MISO, SPI3_SCK);  //for keyscan  mcp23s17
00035 
00036 //class object instances for key I/O expander and segment driver//
00037 MCP23S17 mcp23s17_1(1,_SPI3, SPI3_CS1,SPI3_RST);  //class MCP23S17 object instance for mcp23s17 IC-1 key detection
00038 MCP23S17 mcp23s17_2(2,_SPI3, SPI3_CS2,SPI3_RST);  //class MCP23S17 object instance for mcp23s17 IC-2 key detection
00039 Max7219 max7219(SPI2_MOSI, SPI2_MISO, SPI2_SCK,SPI2_CS1);  //object instance for seven segment drivers
00040 max7219_configuration_t DEVICE1, DEVICE2;
00041 //interrupts definations
00042 InterruptIn int_A(INT_A);       //8commands
00043 InterruptIn int_B(INT_B);       //4  3commands+1ack
00044 InterruptIn int_C(INT_C);       //4(3 controls(INC+,DEC-,TEST)+1 req) enbaled for all
00045 
00046 //chip select definations for max7219 & mcp23s17 as digitalout pins//
00047 DigitalOut cs_disp1(SPI2_CS1);   
00048 DigitalOut cs_disp2(SPI2_CS2);   //max7219
00049 DigitalOut cs_key1(SPI3_CS1);    
00050 DigitalOut cs_key2(SPI3_CS2);    //mcp23s17
00051 
00052 DigitalOut Drive_En(TX_EN);      //uart driver enable
00053 
00054 //discrete outputs definations buzzer and hooter
00055 DigitalOut buzzer(BUZ);
00056 DigitalOut hooter(HTR); 
00057 
00058 
00059 int err_ALL,sync_count,Hrs_1,Hrs_2, Mins_1, Mins_2, current_cmd, current_status,current_status_dir;
00060 int addr, req,ack, send_ADDR, rcvd_ADDR, ach_S,ach_M,test_cnt,req_ADDR,ack_ADDR, err_ID, err_Status;
00061 int rpm_data[4] = {0,0,0,0};               //digits 0-3
00062 int last_entry[4] = {0,0,0,0};          //digits 0-3
00063 
00064 
00065 uint8_t spi_error,no_pot_connected,num_bytes,ticker_count,ticker_count_fast,norm_count,set_bit;
00066 
00067 
00068 //int dir, last_dir;
00069 int checksum_send_byte,checksum_rcvd_byte;
00070 
00071 char pot_Addr,addr_ID;
00072 
00073 float HB_timer,duty_cycle,sync_time;
00074 
00075 bool device_ERR,pot_Error, norm_op;
00076 bool toggle,test,toggle_fast,display_flash;
00077 bool key_CMD,key_CTRL,key_SET;
00078 bool HB_rcvd, HB_ack_rcvd, REQ_rcvd, BROADCAST_rcvd, ACK_rcvd,time_RCVD;
00079 
00080 bool DIR_cmd,DIR_cmd_ack,DIR_cmd_ack_send;
00081 bool RPM_cmd,RPM_cmd_ack,RPM_cmd_ack_send;
00082 
00083 bool HB_send, CMD_send, BROADCAST_send, REQ_send, ACK_send;
00084 
00085 bool ENTER_ACK_key,DIR_key,REQ_key,ACK_key,disp_clear;
00086 
00087 bool switch_CH, pot_MCR_err, pot_ER_err, ACH_SW_over;
00088 bool data_fail,disp_test;
00089 
00090 int device_addr = -1;
00091 
00092 char valid;
00093 char valid_sentence[8] = {'A', 'A','A','A','A','A','A','A'};
00094 char rx_buf[RX_BUFFER_SIZE+1];
00095 char tx_buf[TX_BUFFER_SIZE+1];
00096 char RTC_buffer[5] = {1,2,3,4,0};
00097 
00098 DigitalOut LED_CMD_ACK(_CMD_ACK);                              //ack command in slave devices only
00099 DigitalOut LED_CTRL[2] = {_REQ,_ACK};                             //control transfer
00100 //DigitalOut LED_DIR[2] = {_AHEAD,_ASTERN};                         //dir command
00101 DigitalOut LED_ACH[8] =  {_WH,_BRDG,_MCR,_ER,_WP,_WS,_OPS,_ASP};  //active channels
00102 
00103 //DigitalOut myled(PB_13);  //for internal test LED1
00104 
00105 PwmOut mypwm(_PWM);
00106 
00107 struct _POT
00108 {
00109     int slave_ID;
00110     int err_cnt;
00111     bool err_status;
00112 }; 
00113 struct _POT* POT=NULL;  
00114 
00115 enum AddrID
00116 {
00117     pot_Master = 1,
00118     pot_Submaster,
00119     pot_Slave_MCR,
00120     pot_Slave_ER,
00121     pot_Listner_WP,
00122     pot_Listner_WS,
00123     pot_Listner_OPS,
00124     pot_Listner_ASP = 8
00125 };
00126 
00127 enum LED_STATUS
00128 { 
00129     OFF = 0,
00130     ON,
00131     _FLASH = 2
00132 };          
00133 LED_STATUS led_cmd_ack;   //only in slave devices
00134 LED_STATUS led_ctrl[2];
00135 //LED_STATUS led_dir[2];
00136 LED_STATUS led_ach[8];
00137 
00138 enum KEY
00139 {
00140         ZERO = 0,
00141         ONE,
00142         TWO,
00143         THREE,
00144         FOUR,
00145         FIVE,
00146         SIX,
00147         SEVEN,
00148         EIGHT,
00149         NINE,
00150         FALSE0 = 10
00151 };
00152 enum KEY num_KEY; 
00153 
00154 enum CTRL
00155 {
00156     REQ_ = 1,
00157     ACK_ = 2,
00158     FALSE1= 3
00159     
00160 };
00161 enum CTRL ctrl_KEY; 
00162 
00163 enum UP_DOWN
00164 {
00165     UP_key=1,
00166     DOWN_key,
00167     FALSE2 = 3
00168 };
00169 enum UP_DOWN up_down_KEY;
00170 
00171 /*
00172 enum direction_KEY
00173 {
00174     AHEAD = 1,
00175     ASTERN,
00176     FALSE2 = 3
00177 };
00178 enum direction_KEY dir_KEY;
00179 */
00180 
00181 enum display_KEY
00182 {
00183     clr_ENTRY = 0,           //CE
00184     clr_ALL,                 //C, all data turns to zero
00185     ENTER_ACK,               //enter in case of master and ACK in case of slaves/repeaters
00186     FALSE3 = 3
00187 };
00188 enum display_KEY disp_KEY;
00189 
00190 enum SET
00191 {
00192     INC=0,
00193     DEC,
00194     TEST,
00195     FALSE4 = 4
00196 };
00197 enum SET set_KEY; 
00198 
00199 enum CHANNEL
00200 { 
00201     ch_A=1,
00202     ch_B,
00203     ch_C,
00204     ch_D=4
00205 };          //keyscan channelA,B,C,Dof MCP23s17 1& 2 respectively
00206 enum CHANNEL ch;
00207 
00208 
00209 /**************************************************************************************
00210  EOT RTC display update FUNCTIONS
00211  **************************************************************************************/
00212 void RTC_display(char* digits)
00213 {
00214     for(uint8_t i = 0; i <= 3; i++)              //to write all the four digits
00215         {
00216             if(i == 1)
00217               RTC_buffer[i] = RTC_buffer[i]|0b10000000;   // to inc
00218             else
00219                 __nop();
00220             max7219.write_digit(1, i+1, *(digits+i));   //device 2, digit 1-4 ,data 0x01
00221         }  
00222 }
00223 
00224 /**************************************************************************************
00225 EOT RTC read FUNCTION
00226  **************************************************************************************/
00227 void read_RTC()
00228 {
00229     time_t seconds = time(NULL);
00230     strftime(RTC_buffer, 5, "%H%M\n", localtime(&seconds));
00231     wait_ms(5);
00232     RTC_display(RTC_buffer);
00233     wait_ms(1);
00234 }
00235 
00236 /**************************************************************************************
00237 EOT CHECK LED STATUS FUNCTION
00238  **************************************************************************************/
00239 void update_led()
00240 {
00241     if(++ticker_count == 25)                //25x20 = 500ms
00242     {
00243         ticker_count = 0;
00244         toggle = !toggle;                   //normal cmd flash
00245     }
00246     else
00247         __nop();
00248         
00249     if(++ticker_count_fast == 10)          //20x10 =200
00250     {
00251         ticker_count_fast = 0;
00252         toggle_fast = !toggle_fast;        //error flashing
00253     }
00254     else
00255         __nop();
00256     
00257     if(test)
00258     {
00259         LED_CMD_ACK = ON;                  //in slave only
00260        
00261         for(uint8_t i=0;i<=1;i++)          //control
00262         {
00263                 LED_CTRL[i] = ON;
00264         }
00265         
00266         /*
00267         for(uint8_t i=0;i<=1;i++)          // dir control
00268         {
00269                 LED_DIR[i] = ON;                                  /////////////////working here
00270         }
00271         */
00272         
00273         for(uint8_t i=0;i<=7;i++)          //active channel
00274         {
00275                 LED_ACH[i] = ON;                  //duty cycle 10%
00276         }
00277         max7219.set_display_test();                  //all on
00278         wait_us(1);
00279         disp_test = true;
00280     }
00281     else
00282     {
00283             if(disp_test)
00284                 {
00285                     disp_test = false;
00286                     max7219.clear_display_test();                //normal operation
00287                 }
00288             else
00289                 __nop();
00290             
00291             if(led_cmd_ack == ON)          //status update LED_CMD_ACK
00292                 LED_CMD_ACK = ON;
00293             else
00294                 __nop();
00295                 
00296             if(led_cmd_ack == OFF)
00297                 LED_CMD_ACK = OFF;
00298             else
00299                 __nop();
00300                 
00301             if(led_cmd_ack == _FLASH)
00302             {
00303                 if(toggle)
00304                     LED_CMD_ACK= ON;
00305                 else
00306                     LED_CMD_ACK = OFF;
00307             }
00308             else
00309                 __nop();
00310             
00311         for(uint8_t i=0;i<=1;i++)          //status update LED_CTRL 
00312         {
00313             if(led_ctrl[i] == ON)
00314                 LED_CTRL[i] = ON;
00315             else
00316                 __nop();
00317                 
00318             if(led_ctrl[i] == OFF)
00319                 LED_CTRL[i] = OFF;                  //duty cycle 10%
00320             else
00321                 __nop();
00322                 
00323             if(led_ctrl[i] == _FLASH)
00324             {
00325                  if(toggle)
00326                     LED_CTRL[i]= ON;
00327                 else
00328                     LED_CTRL[i] = OFF;
00329             }
00330             else
00331                 __nop();
00332         }
00333         /*
00334         for(uint8_t i=0;i<=1;i++)          //status update LED_CTRL 
00335         {
00336             if(led_dir[i] == ON)
00337                 LED_DIR[i] = ON;
00338             else
00339                 __nop();
00340                 
00341             if(led_dir[i] == OFF)
00342                 LED_DIR[i] = OFF;                  //duty cycle 10%
00343             else
00344                 __nop();
00345                 
00346             if(led_dir[i] == _FLASH)
00347             {
00348                  if(toggle)
00349                     LED_DIR[i]= ON;
00350                 else
00351                     LED_DIR[i] = OFF;
00352             }
00353             else
00354                 __nop();
00355         }
00356         */
00357         
00358         for(uint8_t i=0;i<=7;i++)          //status update LED_ACH
00359         {
00360             if(led_ach[i] == ON)
00361                 LED_ACH[i] = ON;                  //duty cycle 10%
00362             else
00363                 __nop();
00364                 
00365             if(led_ach[i] == OFF)
00366                 LED_ACH[i] = OFF;                  //duty cycle 10
00367             else
00368                 __nop();
00369                 
00370             if(led_ach[i] == _FLASH)
00371             {
00372                 if(toggle_fast)
00373                     LED_ACH[i]= ON;
00374                 else
00375                     LED_ACH[i] = OFF;
00376             }
00377             else
00378                 __nop();
00379         }
00380     }
00381     if(display_flash)                               //if command executed or command received
00382     {
00383         if(toggle)
00384             max7219.enable_device(2);                //enable device 1 or normal mode
00385         else
00386             max7219.disable_device(2);              //shutdown mode
00387     }
00388     else if(!device_ERR)                           //specific device is not in error device 
00389        max7219.enable_device(2);               //enable device 1 or normal mode;
00390     else
00391         __nop();
00392 }
00393 
00394 /**************************************************************************************
00395   POT State Machines FUNCTIONS
00396  **************************************************************************************/
00397 void HB_State_Machine()                       //run at an interval of 10ms,event driven start stop
00398 {
00399     static int hb_state_cnt = 0;
00400     if(HB_send)
00401     {
00402         HB_send = false;
00403         hb_state_cnt = 0;
00404     }
00405     else
00406         __nop();
00407         
00408     if(HB_ack_rcvd)
00409     {
00410         HB_ack_rcvd = false;
00411         HB_Ticker.detach();
00412         POT[device_addr].err_cnt = 0;
00413         if(POT[device_addr].err_status)                //if that specific device is in error before but revert back to healthy state
00414         {
00415             POT[device_addr].err_status = false;
00416             err_Status = 0;
00417             err_ID = POT[device_addr].slave_ID;
00418             
00419             set_bit =  (uint8_t)1<<(err_ID-1);
00420             err_ALL = err_ALL^set_bit;                  //bitwise XOR
00421             
00422             BROADCAST_send = true;                      // to tell all device that error diminished
00423             switch_CH = true;                           // to tell specific device abot active channels and rpm data                                
00424             if(POT[device_addr].slave_ID == pot_Slave_MCR)
00425             {
00426                 pot_MCR_err = false;
00427                 if(pot_ER_err)
00428                 {
00429                     ach_S = pot_Slave_MCR;
00430                     switch_CH = true;                         //automatic takeover if ER is already faulty
00431                 }
00432                 else
00433                     __nop();
00434             }
00435             else
00436                 __nop();
00437                 
00438             if(POT[device_addr].slave_ID == pot_Slave_ER)
00439             {
00440                 pot_ER_err = false;
00441                 if(pot_MCR_err)
00442                 {
00443                     ach_S = pot_Slave_ER;
00444                     switch_CH = true;                         //automatic takeover if ER is already faulty
00445                 }
00446                 else
00447                     __nop();
00448             }
00449             else
00450                 __nop();
00451         }
00452         else
00453         {
00454             POT[device_addr].err_status = false;
00455             hb_state_cnt = 0;
00456             err_Status = 0;
00457             
00458             if((POT[device_addr].slave_ID == ach_S)&&(led_ach[send_ADDR - 1] != ON))
00459                 led_ach[send_ADDR - 1] = ON;
00460             else if((POT[device_addr].slave_ID != ach_S)&&(led_ach[send_ADDR - 1] != OFF))
00461                 led_ach[send_ADDR - 1] = OFF; 
00462             else
00463                 __nop();  
00464                 
00465             if((addr_ID == ach_M)&&(led_ach[ach_M-1] != ON))
00466                 led_ach[ach_M-1] = ON;
00467             else if((addr_ID != ach_M)&&(led_ach[ach_M-1] != OFF))
00468                 led_ach[ach_M-1] = OFF;
00469             else
00470                 __nop();
00471         }
00472     }
00473     else
00474     {
00475         if(++hb_state_cnt >= 5)             //if HB_response not arrived till 50ms
00476         {
00477             hb_state_cnt=0;
00478             HB_Ticker.detach();
00479             
00480             if((++POT[device_addr].err_cnt >= 5)&&(!POT[device_addr].err_status))  //specific device  in error state after 05 hb response missing
00481             {
00482                 POT[device_addr].err_cnt = 0;
00483                 led_ach[send_ADDR - 1] = _FLASH;
00484                 err_ID = POT[device_addr].slave_ID; 
00485                 
00486                 set_bit =  (uint8_t)1<<(err_ID-1); 
00487                 err_ALL = err_ALL|set_bit;                //bitwise OR
00488                 
00489                 POT[device_addr].err_status = true;
00490                 err_Status = 1;
00491                 BROADCAST_send = true;                //broadcast needed to be sent
00492                 if(POT[device_addr].slave_ID == pot_Slave_MCR)  //means MCR fail
00493                 {   
00494                     pot_MCR_err = true;
00495                     if(ach_S == pot_Slave_MCR)
00496                     {
00497                         if(!pot_ER_err)                   //automatic changeover if ER healthy
00498                         {
00499                             ach_S = pot_Slave_ER;
00500                             switch_CH = true;                  //transfer all slaves the new active slave
00501                         }
00502                         else
00503                         {
00504                             pot_Error = true;
00505                             ach_S = 9;
00506                             switch_CH = true;        //both start flashing for ER nd MCR in all slaves
00507                         }
00508                     }
00509                     else 
00510                         __nop();
00511                 }
00512                 else 
00513                     __nop();
00514                    
00515                 if(POT[device_addr].slave_ID == pot_Slave_ER)
00516                 {
00517                     pot_ER_err = true;
00518                     if(ach_S == pot_Slave_ER)
00519                     {
00520                         if(!pot_MCR_err)                   //automatic changeover if MCR healthy
00521                         {
00522                             ach_S = pot_Slave_MCR;
00523                             switch_CH = true;
00524                         }
00525                         else
00526                         {
00527                             pot_Error = true;
00528                             ach_S = 9;
00529                             switch_CH = true;    //both start flashing for all MCR nd ER
00530                         } 
00531                     }
00532                     else
00533                         __nop();
00534                 }
00535                 else
00536                     __nop();
00537             }
00538             else
00539                 __nop();
00540         }
00541         else                        
00542             __nop();
00543     }    
00544 }
00545 
00546 void CMD_State_Machine()                //function run periodcally in all connected devices on bus
00547 {
00548     static int cmd_state_cnt=0;
00549         
00550     if(RPM_cmd_ack)                        //PEOTX,CMD received in Master/SUB_Master, non Active Slave & Listner
00551     {
00552         for(uint8_t i = 0; i <=3; i++)
00553         {
00554             last_entry[i] = rpm_data[i];           //data saved to last entery
00555         }
00556         for(uint8_t i = 5; i <=8; i++)
00557         {
00558             max7219.write_digit(1,i,last_entry[i-5]);     //last entery displayed
00559         }
00560         if(addr_ID == ach_M)
00561         {
00562             mcp23s17_1.gpintena(0xff);      //ACK key interrupts disabled
00563             wait_us(1);
00564             mcp23s17_1.gpintenb(0xff);      //ACK key interrupts disabled
00565             wait_us(1);
00566             disp_clear = true;
00567         }
00568         else if(addr_ID == ach_S)
00569         {
00570             int_B.rise(NULL);             //all key functions/interrupt disabled for PORTA,B
00571             wait_us(1);
00572             mcp23s17_1.gpintenb(0x00);    //interrupts disabled
00573             wait_us(1); 
00574         }
00575         else
00576             __nop();
00577             
00578         led_cmd_ack = ON;
00579         current_status =  1;              //display steady
00580         cmd_state_cnt = 0;
00581         RPM_cmd = false; 
00582         RPM_cmd_ack = false;
00583         display_flash = false;
00584         buzzer = OFF;
00585         hooter = OFF;
00586         CMD_Ticker.detach();                        //cmd state machine ticker stopped in all devices
00587     }
00588     else if(++cmd_state_cnt >= 12)                       //Hotter ON after 3sec
00589     {
00590         if((hooter == OFF)&&(addr_ID == ach_S))              //if hooter still off
00591         {
00592             cmd_state_cnt = 0;
00593             hooter = ON;
00594        /* if(++cmd_state_cnt >= 96)                     //still command ack not recived for 24 sec
00595         {
00596             LED_CMD[cmd].OFF();                //command suspended
00597             buzzer = OFF;
00598             hooter = OFF;
00599             int_A.rise(NULL);
00600             int_A.rise(NULL);
00601             CMD_ticker.detach();           //timer stoped in all connected devices if ack not received in 3sec
00602         } */
00603         }
00604         else
00605             __nop();
00606     }
00607     else
00608         __nop();
00609 }
00610 
00611 void R_A_Statemachine()
00612 {
00613     static int state_cnt = 0;
00614     if(++state_cnt >= 60)             //REQ not acknowledged for 30 sec, leds turn off, timer stopped
00615     {
00616         state_cnt = 0;
00617         REQ_rcvd = false;            //clear any pending request
00618         R_A_Ticker.detach();
00619     /*  
00620         if(addr_ID != ach_M)      // TODO         
00621         {
00622             int_B.rise(NULL);
00623             mcp23s17_1.gpintenb(0x00);      //portb of mcp1 keys disabled related to ACK
00624             wait_us(10);
00625         }
00626         else
00627             __nop();
00628      */
00629             
00630         led_ctrl[REQ_-1] = OFF;
00631         led_ctrl[ACK_-1] = OFF;
00632     }
00633     else
00634         __nop();
00635         
00636     if(ACK_rcvd)               //active channel switchover true only after acknowledge receive
00637         {
00638             ACK_rcvd = false;
00639             led_ctrl[REQ_-1] = OFF;
00640             if(addr_ID == pot_Master)
00641             {
00642                 if(ack_ADDR == 3 || ack_ADDR == 4)
00643                 {
00644                     if(ach_S == pot_Slave_MCR)
00645                         ach_S = pot_Slave_ER;
00646                     else if(ach_S == pot_Slave_ER)
00647                         ach_S = pot_Slave_MCR;
00648                 }
00649                 else
00650                     __nop();
00651                     
00652                 if(ack_ADDR == 2 || ack_ADDR == 1)       
00653                 {
00654                     if(ach_M == pot_Master)
00655                         ach_M = pot_Submaster;
00656                     else if(ach_M == pot_Submaster)
00657                         ach_M = pot_Master;
00658                 }
00659                 else
00660                     __nop();
00661                     
00662                 switch_CH = true;
00663                 state_cnt = 0;
00664                 R_A_Ticker.detach();
00665             }
00666             else
00667             {
00668                 state_cnt = 0;
00669                 R_A_Ticker.detach();
00670             }
00671         }
00672         else
00673             __nop();
00674 }
00675 
00676 //Direction function changed to RPM Up-Down Counter so Dir_state_machine function not required
00677 /*                
00678 void DIR_state_machine(void)
00679 {
00680     static int dir_state_cnt = 0;
00681     if(DIR_cmd_ack)
00682     {
00683         DIR_cmd =  false;
00684         DIR_cmd_ack = false;
00685         current_status_dir = 1;             //steady
00686         led_dir[dir-1] = ON;                //led direction acknowledged turn steady
00687         buzzer = OFF;                             //buzzer Off
00688         hooter = OFF;
00689         DIR_Ticker.detach();
00690     }
00691     else
00692     {
00693         if((++dir_state_cnt >= 12) && (hooter == OFF))          //direction command not ack for 03 sec
00694             {
00695                 hooter = ON;
00696                 dir_state_cnt = 0;
00697             }
00698         else
00699             __nop();
00700     } 
00701 }
00702 */
00703 
00704 void HB_fail_state_machine()
00705 {
00706     static uint8_t fail_count = 0;
00707     if(HB_rcvd)
00708     {
00709         HB_rcvd = false;
00710         device_ERR = false;
00711     }
00712     else if(++fail_count >=3)             // if max 07 number of connected eots 7x3=21, it takes 150x21=3.150 sec to alarm
00713     {
00714         fail_count = 0;
00715         //led_dir[dir-1] = OFF;               //current command if any turned OFF
00716         led_cmd_ack = OFF;
00717         display_flash = false;
00718         device_ERR = true;
00719         max7219.disable_device(2);              //shutdown mode
00720         wait_ms(2);
00721         if(addr_ID != ach_M)
00722         {
00723             for(uint8_t i = 0; i <=7; i++)
00724             {
00725                 led_ach[i] = OFF;             //all other active chnnels leds or device errors
00726             }
00727             led_ach[addr_ID - 1] = _FLASH;    //specific device is in error flshes only
00728         }
00729         HB_fail.detach();
00730     }
00731 }
00732 
00733 void NUMERIC_handler(uint8_t key_ID)                             //function sacnning all the 0-9 and up-down number keys
00734 {  
00735     uint8_t num;
00736     num = key_ID;
00737     if(key_ID != FALSE0)
00738         {                                                                                  
00739         if(((ach_M == pot_Master) && (addr_ID == pot_Master)) || ((ach_M == pot_Submaster) && (addr_ID == pot_Submaster)))                               //for Master
00740             {
00741                 if(disp_clear)                   //if last command has been acknowledged
00742                 {
00743                     for (uint8_t j = 0; j < 4; j++)
00744                     {
00745                         rpm_data[j] = 0;          //clear rpm_data to enter new values
00746                     } 
00747                     disp_clear = false;
00748                 } 
00749                 else
00750                     __nop();
00751                     
00752                 for (uint8_t j = 0; j < 4; j++)
00753                 {
00754                         rpm_data[j] = rpm_data[j + 1];   //at every key press array shift to left
00755                 }
00756                 
00757                 rpm_data[3] = num;   //new value be updated at place of digit 4
00758                 
00759                 for (uint8_t j = 1; j <= 4; j++)
00760                 {
00761                     max7219.write_digit(2,j,rpm_data[j-1]);
00762                 }                                     
00763             }
00764         else
00765             __nop();
00766         }
00767     else
00768         __nop();
00769 }
00770 
00771 
00772 void CTRL_handler(uint8_t CTRL_ID)                        //handle  control transfer 
00773 {
00774     if(CTRL_ID != FALSE1)
00775     {
00776         if((addr_ID == pot_Slave_MCR) || (addr_ID == pot_Slave_ER))
00777         {
00778             if((CTRL_ID == REQ_)&&(!REQ_rcvd))  //if no request has been received
00779             {   
00780                 req = REQ_;                     //req data updated 0 here, same int values as in enum
00781                 REQ_key = true;
00782                 led_ctrl[REQ_-1] = _FLASH;                //req led flash starts
00783                 R_A_Ticker.attach(&R_A_Statemachine,0.5);
00784             }
00785             else
00786                 __nop();
00787                 
00788             if((CTRL_ID == ACK_)&& (REQ_rcvd))
00789             {
00790                 REQ_rcvd = false;
00791                 ack = ACK_;                     //ack data updated 2 here
00792                 ACK_key = true;
00793                 int_B.rise(NULL);               //interrupt disabled
00794                 wait_us(10);
00795                 mcp23s17_1.gpintenb(0x00);      //ACK key interrupts disabled
00796                 wait_us(10);
00797                 led_ctrl[ACK_-1] = OFF;                  //ack led turns off
00798                 R_A_Ticker.detach();
00799             }
00800             else
00801                 __nop();
00802         }
00803     }
00804     else 
00805         __nop(); //then do nothing
00806 }
00807 
00808 void UP_DOWN_handler(uint8_t key_ID)
00809 {
00810     if(key_ID != FALSE2)
00811         {                                                                                  
00812         if(((ach_M == pot_Master) && (addr_ID == pot_Master)) || ((ach_M == pot_Submaster) && (addr_ID == pot_Submaster)))                               //for Master
00813             {    
00814                 if(key_ID == UP_key)
00815                 {
00816                     rpm_data[3]++;
00817                     if(rpm_data[3] == 10)
00818                         {
00819                             rpm_data[3] = 0;
00820                             rpm_data[2]++;
00821                             if(rpm_data[2] == 10)
00822                             {
00823                                 rpm_data[2] = 0;
00824                                 rpm_data[1]++;
00825                                 if(rpm_data[1] == 10)
00826                                 {
00827                                     rpm_data[1] = 0;
00828                                     rpm_data[0]++;
00829                                     if(rpm_data[0] == 10)
00830                                         rpm_data[0] = 9;
00831                                     else
00832                                         __nop();
00833                                 }
00834                                 else
00835                                     __nop();
00836                             }
00837                             else
00838                                 __nop();
00839                         }
00840                     else
00841                         __nop();
00842                 }
00843                 else if(key_ID == DOWN_key)
00844                     {
00845                         rpm_data[3]--;
00846                     if(rpm_data[3] == 0)
00847                         {
00848                             rpm_data[3] = 0;
00849                             rpm_data[2]--;
00850                             if(rpm_data[2] == 0)
00851                             {
00852                                 rpm_data[2] = 0;
00853                                 rpm_data[1]--;
00854                                 if(rpm_data[1] == 0)
00855                                 {
00856                                     rpm_data[1] = 0;
00857                                     rpm_data[0]--;
00858                                     if(rpm_data[0] == 0)
00859                                         rpm_data[0] = 0;
00860                                     else
00861                                         __nop();
00862                                 }
00863                                 else
00864                                     __nop();
00865                             }
00866                             else
00867                                 __nop();
00868                         }
00869                     else
00870                         __nop();
00871                         
00872                     }
00873                 else
00874                     __nop();
00875                                 
00876                 for (uint8_t j = 1; j <= 4; j++)
00877                 {
00878                     max7219.write_digit(2,j,rpm_data[j-1]);    //update data to display
00879                 }                                     
00880             }
00881         else
00882             __nop();
00883         }
00884     else
00885         __nop();
00886     
00887 }
00888 
00889 //functon not required as DiR keys change to UP-down RPM
00890 /*
00891 void DIR_handler(uint8_t DIR_ID)                        //handle  control transfer 
00892 {
00893     if(DIR_ID != FALSE2)
00894     {
00895         if(addr_ID == ach_M)
00896         { 
00897             current_status_dir = 2;                  //flash
00898             led_dir[dir-1] = OFF;
00899             dir = DIR_ID;                     
00900             led_dir[dir-1] = _FLASH;                //led direction AHEAD start flashing
00901             buzzer = ON;                             //buzzer ON
00902             DIR_cmd = true;                          // dir cmd needs to be sent
00903         }
00904         else
00905             __nop();
00906             
00907         if (addr_ID == ach_S)
00908         { 
00909             if((dir == DIR_ID)&&(DIR_cmd))         //direction command is received                  
00910             {
00911                 current_status_dir = 1;
00912                 led_dir[dir-1] = OFF;
00913                 dir = DIR_ID;                     
00914                 led_dir[dir-1] = ON;                    //led direction AHEAD start flashing
00915                 buzzer = OFF;                             //buzzer OFF
00916                 DIR_key = true;                   //dir ack will be sent in response to HB
00917             }
00918             else
00919                 __nop();
00920         } 
00921         else
00922                 __nop();
00923     }
00924     else 
00925         __nop();                                //then do nothing
00926 }
00927 */
00928 
00929 void DISP_handler(uint8_t DISP_ID)                        //handle  control transfer 
00930 {
00931     uint8_t disp_key;
00932     disp_key = DISP_ID;
00933     if(DISP_ID != FALSE3)
00934     {
00935         switch(disp_key)
00936         {
00937             case clr_ENTRY:                                      //CE,elete only last/4th digit and shift others digits towards right/4th digit
00938                 if(addr_ID == ach_M)
00939                 {
00940                     for (uint8_t j = 3; j > 0; j--)
00941                     {
00942                         rpm_data[j] = rpm_data[j - 1];   //at every key press array shift to left
00943                     }
00944                     rpm_data[0] = 0;
00945                 
00946                     for (uint8_t j = 1; j <= 4; j++)
00947                     {
00948                         max7219.write_digit(2,j,rpm_data[j-1]);
00949                     }
00950                 }
00951                 else
00952                 {
00953                     __nop();
00954                 }
00955             break;
00956             
00957             case clr_ALL: 
00958                 if(addr_ID == ach_M) 
00959                 {                                    //C      delete all digits in DS1 and show last entered value                                 
00960                     for (uint8_t j = 0; j <=3; j++)
00961                     {
00962                         rpm_data[j] = 0;   //at every key press array shift to left
00963                     }
00964                     for (uint8_t j = 1; j <= 4; j++)      // all digits turns to zero
00965                     {
00966                         max7219.write_digit(2,j,rpm_data[j-1]);
00967                     }
00968                 }
00969                 else
00970                 {
00971                     __nop();
00972                 }  
00973             break;
00974             
00975             case ENTER_ACK:                                    //work as Enter in master and CMD ACK in slave
00976                 if((addr_ID == ach_S)&&(RPM_cmd))                    //RPM command ack needs to be sent
00977                 {
00978                     RPM_cmd = false;    
00979                     display_flash = false; 
00980                     buzzer = OFF;
00981                     int_B.rise(NULL);
00982                     wait_us(10);
00983                     mcp23s17_1.gpintenb(0x00);      //ACK key interrupts disabled
00984                     wait_us(10);
00985                     ENTER_ACK_key = true;           //flashing display1 turned steady                              //RPM command acknowledged by active slave
00986                 } 
00987                 else  if (addr_ID == ach_M)                                 //in case of active masters
00988                 {
00989                     int RPM_set = 0;                                              //disp1 start flashing, and data sent over UART for all digits 1-4
00990                     RPM_set = (rpm_data[0]*1000) + (rpm_data[1]*100) + (rpm_data[2]*10) + rpm_data[3];
00991                     if(RPM_set>Max_RPM)
00992                     {
00993                         for (uint8_t j = 0; j <=3; j++)
00994                         {
00995                             rpm_data[j] = 0;   //at every key press array shift to left
00996                         }
00997                         for (uint8_t j = 1; j <= 4; j++)      // all digits turns to zero
00998                         {
00999                             max7219.write_digit(2,j,rpm_data[j-1]);
01000                         }  
01001                     }
01002                     else
01003                     {
01004                         display_flash = true;             //display starts flashing
01005                         mcp23s17_1.gpintena(0x00);      //ACK key interrupts disabled
01006                         wait_us(10);
01007                         mcp23s17_1.gpintenb(0x00);      //ACK key interrupts disabled
01008                         wait_us(10);
01009                         current_status =  2;              //flash
01010                         buzzer = ON;
01011                         RPM_cmd = true;                   //command need to be send
01012                     }
01013                 }
01014                 else
01015                 {
01016                     __nop();
01017                 }
01018             break;
01019             
01020             default:
01021                 __nop();
01022             break;
01023         }
01024     }
01025     else 
01026         __nop(); //then do nothing
01027 }
01028 
01029 /******************************************************************
01030 function to set brightness of leds and seven segment
01031 ******************************************************************/
01032 void SET_handler(uint8_t Set_ID)
01033 {
01034     if(Set_ID != FALSE2)
01035     {
01036         switch(Set_ID)
01037         {
01038             case INC:
01039                 duty_cycle = mypwm.read();     //as duty cycle decreases creases brightnes increases
01040                 if( duty_cycle > 0.02f)
01041                 {
01042                     duty_cycle = duty_cycle-0.01f;
01043                     mypwm.write(duty_cycle);
01044                 }
01045                 else
01046                 {
01047                     duty_cycle = 0.01f;
01048                 }
01049                 if(DEVICE1.intensity  < 14)
01050                 {
01051                     DEVICE1.intensity ++;                               //intensity modified
01052                     DEVICE2.intensity ++;
01053                     max7219.set_intensity(DEVICE1);       //updating brightness value of DEVICE1
01054                     max7219.set_intensity(DEVICE2);       //updating brightness value of DEVICE2
01055                 }
01056                 else
01057                 {
01058                     DEVICE1.intensity =15;
01059                     DEVICE2.intensity =15;
01060                     max7219.set_intensity(DEVICE1);       //updating brightness value of DEVICE1
01061                     max7219.set_intensity(DEVICE2);       //updating brightness value of DEVICE2
01062                 }
01063             break;
01064         
01065             case DEC:
01066                 duty_cycle = mypwm.read();
01067                 if( duty_cycle < 0.98f)          //as duty cycle increases brightnes decreases
01068                 {
01069                     duty_cycle = duty_cycle+0.01f;
01070                     mypwm.write(duty_cycle);
01071                 }
01072                 else
01073                 {
01074                     duty_cycle = 0.99f;
01075                 }
01076                 if(DEVICE1.intensity  > 2)
01077                 {
01078                     DEVICE1.intensity --;                              //intensity modified
01079                     DEVICE2.intensity --;
01080                     max7219.set_intensity(DEVICE1);       //updating brightness value of DEVICE1
01081                     max7219.set_intensity(DEVICE2);       //updating brightness value of DEVICE2
01082                 }
01083                 else
01084                 {
01085                     DEVICE1.intensity =1;
01086                     DEVICE2.intensity =1;                                //minimum brightnes
01087                     max7219.set_intensity(DEVICE1);       //updating brightness value of DEVICE1
01088                     max7219.set_intensity(DEVICE2);       //updating brightness value of DEVICE2
01089                 }
01090             break;
01091         
01092             case TEST:
01093                 test_cnt++;
01094                 if(test_cnt <= 1)
01095                 test = true;
01096                 else if(test_cnt >= 2)
01097                 {
01098                     test = false;
01099                     test_cnt = 0;
01100                 }
01101                 else
01102                     __nop();
01103             break;
01104             
01105             default:
01106                 __nop();
01107             break;
01108         }
01109     }
01110     else
01111         __nop();
01112 }
01113 /**************************************************************************************
01114  POT SPI Data Read KEY FUNCTIONS
01115  **************************************************************************************/
01116 unsigned char read_KEY_SPI(int CH)
01117 {
01118     char _key;
01119     switch(CH)
01120     {
01121         case 1:
01122             wait_ms(1);
01123             _key = mcp23s17_1.intcapa();                   // read(INTCAPA_ADDR);
01124             wait_ms(1);
01125         break;
01126         
01127         case 2:
01128             wait_ms(1);
01129             _key=mcp23s17_1.intcapb();
01130             wait_ms(1);
01131         break;
01132         
01133         case 3:
01134             wait_ms(1);
01135             _key=mcp23s17_2.intcapa();
01136             wait_ms(1);
01137         break;
01138         case 4:
01139         wait_ms(1);
01140         _key = mcp23s17_2.gpiob(); //address read PORTB of chip2
01141         wait_ms(1);
01142         break;
01143         default:
01144         _key = 0;
01145         break;
01146     }
01147     return(_key);
01148 }
01149 
01150 void read_KEY_A()                      //function check status of PORTA of MCP23S17 (1) chip
01151 {
01152     char key_status = 0;
01153     num_KEY = FALSE0;
01154     key_status = read_KEY_SPI(ch_A);    //to read portA of mcp23s17(1)
01155     if(key_status != 0xff)                    //means some key must have been pressed
01156     {
01157         switch(key_status)
01158         {
01159             case 0xfe:               //0xfe  GPA0
01160                 num_KEY = ZERO;
01161             break;
01162             case 0xfd:               //0xfd  GPA1
01163                 num_KEY = ONE;
01164             break;
01165             case 0xfb:               //0xfb  GPA2
01166                 num_KEY = TWO;
01167             break;
01168             case 0xf7:               //0xf7  GPA3
01169                 num_KEY = THREE;
01170             break;
01171             case 0xef:               //0xef  GPA4
01172                 num_KEY = FOUR;
01173             break;
01174             case 0xdf:               //0xdf  GPA5
01175                 num_KEY = FIVE;
01176             break;
01177             case 0xbf:               //0xbf  GPA6
01178                 num_KEY = SIX;
01179             break;
01180             case 0x7f:               //0x7f  GPA7
01181                 num_KEY = SEVEN;
01182             break;
01183             default:
01184                 num_KEY = FALSE0;
01185             break;
01186         }
01187         NUMERIC_handler(num_KEY);
01188     }
01189 }
01190 
01191 void read_KEY_B()
01192 {
01193     char key_status = 0;
01194     num_KEY = FALSE0;
01195     ctrl_KEY = FALSE1;
01196     //dir_KEY = FALSE2;  /not required
01197     up_down_KEY = FALSE2;
01198     disp_KEY = FALSE3;
01199     
01200     key_status = read_KEY_SPI(ch_B);   //to read portBof mcp23s17(1)
01201     if(key_status != 0xff)
01202     {   
01203         switch(key_status)
01204         {
01205             case 0xfe:               //0xfe  GPA0
01206                 num_KEY = EIGHT;
01207                 NUMERIC_handler(num_KEY);
01208             break;
01209             case 0xfd:               //0xfd  GPA1
01210                 num_KEY = NINE;
01211                 NUMERIC_handler(num_KEY);
01212             break;
01213             case 0xfb:                      //0xfb  GPA2
01214                 up_down_KEY = UP_key;             //dir_KEY = AHEAD; /not required now
01215                 UP_DOWN_handler(up_down_KEY);   //DIR_handler(dir_KEY); /not required now                                            
01216             break;
01217             case 0xf7:                          //0xf7  GPA3
01218                 up_down_KEY = DOWN_key;             //dir_KEY = ASTERN;  /not required now
01219                 UP_DOWN_handler(up_down_KEY);     //DIR_handler(dir_KEY); /not required now
01220             break;
01221             case 0xef:                     //0xef  GPA4
01222                 ctrl_KEY = ACK_;
01223                 CTRL_handler(ctrl_KEY);
01224             break;
01225             case 0xdf:                     //0xdf  GPA5
01226                 disp_KEY = clr_ENTRY;               //CE
01227                 DISP_handler(disp_KEY);
01228             break;
01229             case 0xbf:                     //0xbf  GPA6
01230                 disp_KEY = clr_ALL;             //C
01231                 DISP_handler(disp_KEY);
01232             break;
01233             case 0x7f:                    //0x7f  GPA7
01234                 disp_KEY = ENTER_ACK;
01235                 DISP_handler(disp_KEY);
01236             break;
01237             default:
01238                 num_KEY = FALSE0;
01239                 ctrl_KEY = FALSE1;
01240                 //dir_KEY = FALSE2;
01241                 up_down_KEY = FALSE2;
01242                 disp_KEY = FALSE3;
01243             break;
01244         }
01245     }
01246 }
01247 void read_KEY_C()
01248 {
01249     char key_status = 0;
01250     ctrl_KEY = FALSE1;
01251     set_KEY = FALSE4;
01252     key_status = read_KEY_SPI(ch_C);   //to read portA of mcp23s17(2)
01253     if(key_status != 0xff)
01254     {
01255         if(key_status==0xfe)
01256         {
01257             ctrl_KEY  = REQ_;                    //control transfer REQ button pressed
01258             CTRL_handler(ctrl_KEY);
01259         }
01260         else
01261         {
01262             if(key_status==0xfd)
01263                 set_KEY = INC;                     //setting key INC
01264             else if(key_status==0xfb)
01265                 set_KEY = DEC;                      //setting key DEC
01266             else if(key_status==0xf7)
01267                 set_KEY = TEST;                       //setting key TEST
01268             else 
01269             {
01270                 set_KEY = FALSE4;                       //setting key TEST
01271                 ctrl_KEY = FALSE1;
01272             }
01273             
01274             SET_handler(set_KEY);
01275         }
01276     }
01277 }
01278 
01279 
01280 /**************************************************************************************
01281 POT Serial Data Out FUNCTIONS
01282  **************************************************************************************/
01283 uint8_t  get_checksum(const char *sentence)
01284 {
01285     const char *n = sentence + 1; // Plus one, skip '$'
01286     uint8_t chk = 0;
01287 
01288     /* While current char isn't '*' or sentence ending (newline) */
01289     while (('*' != *n) &&(NMEA_END_CHAR_1 != *n))
01290     {
01291         if ('\0' == *n || n - sentence > NMEA_MAX_LENGTH) 
01292         {
01293             /* Sentence too long or short */
01294             chk = 0;
01295         }
01296         chk ^= (uint8_t) *n;
01297         n++;
01298     }
01299     return chk;
01300 }
01301 
01302 void resp_HB(uint8_t seq)      //presentees(submaster,slaves,listeners will respond back to the HB along with REQ and CMD ack status
01303 {
01304    switch(seq)
01305     {
01306         case 0:
01307             sprintf(tx_buf,"$PPOTA,%u,%c*", addr_ID,valid);
01308             checksum_send_byte = get_checksum(tx_buf);
01309             sprintf(tx_buf,"$PPOTA,%u,%c*%u",addr_ID,valid,checksum_send_byte);
01310         break;
01311         case 1:
01312             sprintf(tx_buf,"$PPOTR,%u,%u,%c*", addr_ID, REQ_,'A');
01313             checksum_send_byte = get_checksum(tx_buf);
01314             sprintf(tx_buf,"$PPOTR,%u,%u,%c*%u",addr_ID,REQ_,'A',checksum_send_byte);
01315         break;
01316         case 2:
01317             sprintf(tx_buf,"$PPOTK,%u,%u,%c*", addr_ID, ACK_,'A');
01318             checksum_send_byte = get_checksum(tx_buf);
01319             sprintf(tx_buf,"$PPOTK,%u,%u,%c*%u",addr_ID, ACK_,'A',checksum_send_byte);
01320         break;
01321         default:
01322             __nop(); //sprintf(tx_buf,"$PPOTA,%u,%c", addr_ID, valid);
01323         break;
01324     }                
01325     Drive_En = 1;              
01326     UART.printf("%s\r\n",tx_buf);
01327     wait_ms(2);
01328     Drive_En = 0;
01329 }
01330 
01331 void send_ack_CMD(uint8_t cmd_t)
01332 {
01333     sprintf(tx_buf,"$PPOTX,%u,%c*", addr_ID,'A');
01334     checksum_send_byte = get_checksum(tx_buf);                
01335     sprintf(tx_buf,"$PPOTX,%u,%c*%u",addr_ID,'A',checksum_send_byte);
01336     Drive_En = 1;              
01337     UART.printf("%s\r\n",tx_buf);
01338     wait_ms(2);
01339     Drive_En = 0;
01340 }
01341 
01342 void send_RPM(uint8_t _adr)
01343 {
01344     sprintf(tx_buf,"$PPOTC,%u,%u,%u,%u,%u,%c*", _adr, rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3],'A');
01345     checksum_send_byte = get_checksum(tx_buf);                
01346     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);
01347     Drive_En = 1;              
01348     UART.printf("%s\r\n",tx_buf);
01349     wait_ms(2);
01350     Drive_En = 0;
01351 }
01352 
01353 /*
01354 void send_DIR(uint8_t _adr)             //addr 1-8 of leds,error=1 or 0(no error)
01355 {
01356     sprintf(tx_buf,"$PPOTD,%u,%u,%c*",_adr,dir,'A');             // dir is 1 for ahead, 2 for astern
01357     checksum_send_byte = get_checksum(tx_buf);                
01358     sprintf(tx_buf,"$PPOTD,%u,%u,%c*%u",_adr,dir,'A',checksum_send_byte);
01359     Drive_En = 1;              
01360     UART.printf("%s\r\n",tx_buf);
01361     wait_ms(2);
01362     Drive_En = 0;
01363 }
01364 */
01365 
01366 void send_HB(uint8_t _adr)                   //master will send the heartbeat to all presentees at periodic intervals
01367 {      
01368     sprintf(tx_buf,"$PPOTH,%u,%c*", _adr,'A');
01369     checksum_send_byte = get_checksum(tx_buf);                
01370     sprintf(tx_buf,"$PPOTH,%u,%c*%u",_adr,'A',checksum_send_byte);
01371     Drive_En = 1;              
01372     UART.printf("%s\r\n",tx_buf);
01373     wait_ms(2);
01374     Drive_En = 0;
01375 }
01376 
01377 void send_BROADCAST()                        //addr 1-8 of leds,error=1 or 0(no error)
01378 {
01379     sprintf(tx_buf,"$PPOTB,%u,%u,%c*",err_ALL,err_Status,'A');
01380     checksum_send_byte = get_checksum(tx_buf);                
01381     sprintf(tx_buf,"$PPOTB,%u,%u,%c*%u",err_ALL,err_Status,'A',checksum_send_byte);
01382     Drive_En = 1;              
01383     UART.printf("%s\r\n",tx_buf);
01384     wait_ms(2);
01385     Drive_En = 0;
01386     BROADCAST_send=false;
01387 }
01388  /** Function will send ac-M, ac-S, rpm-data(04digits), cmd_state)**/
01389 void send_ACH()                 
01390 {
01391     sprintf(tx_buf,"$PPOTS,%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],current_status,'A');
01392     checksum_send_byte = get_checksum(tx_buf);                
01393     sprintf(tx_buf,"$PPOTS,%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],current_status,'A',checksum_send_byte);
01394     Drive_En = 1;              
01395     UART.printf("%s\r\n",tx_buf);
01396     wait_ms(2);
01397     Drive_En = 0;
01398 }
01399 
01400 void ask_TIME()
01401 {
01402     Hrs_1 = Hrs_2 = Mins_1 = Mins_2 = 0;
01403     sprintf(tx_buf,"$PPOTQ,%u,%u,%u,%u,%c*", Hrs_1,Hrs_2, Mins_1, Mins_2,'A');    //querry to CPU for time
01404     checksum_send_byte = get_checksum(tx_buf);                
01405     sprintf(tx_buf,"$PPOTQ,%u,%u,%u,%u,%c*%u", Hrs_1,Hrs_2, Mins_1, Mins_2,'A',checksum_send_byte);
01406     Drive_En = 1;              
01407     UART.printf("%s\r\n",tx_buf);
01408     wait_ms(2);
01409     Drive_En = 0;
01410 }
01411 
01412 /**************************************************************************************
01413  EOT Serial Data In FUNCTIONS
01414  **************************************************************************************/
01415 void rcvd_HB()      //all devices check for HB  along with req response for all presentees
01416 {
01417     if(rcvd_ADDR == addr_ID)             //addr_ID  self address received
01418     {   
01419         HB_rcvd = true;       
01420         if(addr_ID > pot_Slave_ER)
01421         {                                //all listners replied with
01422             resp_HB(0);                  //normal HB response
01423         }
01424         else                             //in case of active slave
01425         {
01426             if(ENTER_ACK_key)               //RPM ACK key is detected at active slave only
01427             {
01428                 send_ack_CMD(1);  
01429                 RPM_cmd_ack = true;  
01430                 ENTER_ACK_key = false;
01431             }
01432             /*
01433             else if(DIR_key)                //dir ack key detected at active slave
01434             {
01435                 DIR_key = false;
01436                 DIR_cmd_ack_send = true;
01437                 send_ack_CMD(2);
01438             }
01439             */
01440             else if(REQ_key)
01441             {
01442                 REQ_key = false;
01443                 resp_HB(1);                 //req and ack status data in req=1 and ack=2 if true
01444             }
01445             else if(ACK_key)
01446             {
01447                 ACK_key = false;
01448                 resp_HB(2);                 //req and ack status data in req=1 and ack=2 if true
01449             }
01450             else
01451                 resp_HB(0);                 //req and ack status data in req=1 and ack=2 if true
01452         }
01453         HB_fail.attach(&HB_fail_state_machine,1);
01454     }
01455     else
01456       __nop(); 
01457 }
01458 
01459 void resp_rcvd_HB()                  //master and active/passive slaves check HB response along with req/ack commands
01460 { 
01461     static uint8_t checksum_flt[8] = {0,0,0,0,0,0,0,0}; 
01462     static bool checksum_err[8] = {false,false,false,false,false,false,false,false};
01463     if(addr_ID == pot_Master)                                       //only master will be able to monitor status of all eots connected
01464     { 
01465         if(send_ADDR == rcvd_ADDR)              //valid broadcast not received  
01466         {
01467             if(valid_sentence[rcvd_ADDR] == 'A')
01468             {
01469                 HB_ack_rcvd = true;
01470                 checksum_err[rcvd_ADDR] = false;
01471                 checksum_flt[rcvd_ADDR] = 0;
01472             } 
01473             else if((valid_sentence[rcvd_ADDR] == 'V')&&(++checksum_flt[rcvd_ADDR]<=3))
01474             {
01475                 HB_ack_rcvd = true;
01476                 BROADCAST_send = true;    //again broadcast
01477                 switch_CH = true;         //send active channels again
01478             }
01479             else if((valid_sentence[rcvd_ADDR] == 'V')&&(checksum_flt[rcvd_ADDR]>3)&&(!checksum_err[rcvd_ADDR]))
01480             {
01481                HB_ack_rcvd = false;
01482                checksum_err[rcvd_ADDR] = true;
01483             } 
01484             else
01485                 __nop();
01486             
01487         }
01488         else
01489             HB_ack_rcvd = false;     
01490     }
01491     else
01492         __nop();
01493 }
01494 
01495 void rcvd_ACH()
01496 {
01497     led_ach[ach_M-1] = ON;
01498     if(current_status == 2)
01499     {
01500         led_cmd_ack = _FLASH;
01501         max7219.enable_device(2);
01502         display_flash = true; 
01503     }
01504     else if(current_status == 1)
01505     {
01506         led_cmd_ack = ON;
01507         max7219.enable_device(2);
01508         display_flash = false;
01509     }
01510     else
01511     {
01512         led_cmd_ack = OFF;
01513         max7219.enable_device(2);
01514     }
01515     /*
01516     if(current_status_dir == 2)
01517     {
01518         led_dir[dir-1] = _FLASH;
01519     }
01520     else if(current_status_dir == 1)
01521     {
01522         led_dir[dir-1] = ON;
01523     }
01524     else
01525     {
01526         led_dir[dir-1] = OFF;
01527     }
01528     */
01529     for(uint8_t i = 1; i <= 4 ; i++)    //current cmd information
01530     {
01531         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
01532     }
01533     
01534     for(uint8_t i = 5; i <=8; i++)     //last command executed
01535     {
01536         max7219.write_digit(1,i,last_entry[i-5]);     //last cmd 0000
01537     }
01538         
01539     if(ach_S != 9)
01540     {
01541         if(ach_S == pot_Slave_MCR)
01542         {
01543             led_ach[pot_Slave_MCR -1] = ON;
01544             if(led_ach[pot_Slave_ER -1] == ON)
01545                 led_ach[pot_Slave_ER -1] = OFF;    //ER off
01546             else
01547                 __nop();
01548         }
01549         else if(ach_S == pot_Slave_ER)
01550         {
01551             led_ach[pot_Slave_ER -1] = ON;    //ER ON 
01552             if(led_ach[pot_Slave_MCR -1] == ON)
01553                 led_ach[pot_Slave_MCR -1] = OFF;    //ER off
01554             else
01555                 __nop();   
01556         }
01557         else
01558             __nop();
01559             
01560         if((RPM_cmd || DIR_cmd)&& (addr_ID == ach_S))      // cmd ack not received before its failure control shifted to another slave
01561         {                                                //all key functions enabled for PORTB in active slave only        
01562             int_B.rise(&read_KEY_B);
01563             wait_us(10);
01564             mcp23s17_1.gpintenb(0xff);    //ff
01565             wait_us(10);
01566         }
01567         else
01568             __nop();
01569     }
01570     else
01571     {
01572         led_ach[pot_Slave_MCR-1] = _FLASH;
01573         led_ach[pot_Slave_ER-1]  = _FLASH;
01574     }  
01575 }
01576 
01577 void rcvd_rpm_CMD()                         //all devices check for received command
01578 {
01579     led_cmd_ack = _FLASH;                   //ack cmd led start flashing
01580     for(uint8_t i = 0; i <= 3 ; i++)
01581     {
01582         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
01583     }  
01584     wait_us(10);                                      
01585     buzzer = ON;
01586     display_flash = true;                     //display start flashing                                                         //buzzer on                                                     
01587     
01588     if(ach_S == addr_ID)
01589     {   
01590         int_B.rise(&read_KEY_B);
01591         wait_us(10);     
01592         mcp23s17_1.gpintenb(0xff);    //ff
01593         wait_us(10);                                              //portc is always enbaled in all cases and PORTA is enabled only for active master
01594     }
01595     else 
01596     {
01597         __nop();
01598     }
01599     CMD_Ticker.attach(&CMD_State_Machine,0.25);                                 //state machine timer started in all connected devices except  master
01600 }
01601 /*
01602 void rcvd_dir_CMD()         //all devices check for received command
01603 {
01604     DIR_cmd =  true;
01605     led_dir[last_dir-1] = OFF;
01606     led_dir[dir-1] = _FLASH;                                                    //led flash started
01607     buzzer = ON;                                                                 //buzzer on
01608     last_dir = dir;                                                        //HB-cmd ack pending with "A"  
01609     if(ach_S == addr_ID)
01610     {       
01611         int_B.rise(&read_KEY_B);                      //enable portb interupts
01612         mcp23s17_1.gpintenb(0xff);    //ff
01613         wait_us(10); 
01614     }
01615     DIR_Ticker.attach(&DIR_state_machine,0.25);
01616 }
01617 */
01618 
01619 void rcvd_BROADCAST()
01620 {
01621     for(uint8_t i = 0 ; i <= 7 ; i++)
01622     {
01623         if(((uint8_t)1<<i) & (uint8_t)err_ALL)
01624         {
01625             led_ach[i] = _FLASH;
01626         }
01627         else if(led_ach[i] != ON)
01628         {
01629             led_ach[i]= OFF;
01630         }
01631         else
01632             __nop();
01633     } 
01634 }
01635 
01636 void rcvd_TIME()
01637 {
01638     uint8_t Hrs,Mins;
01639     struct tm t;
01640     Hrs = 10*Hrs_1+Hrs_2;
01641     Mins = 10*Mins_1+Mins_2;
01642     t.tm_year = 2018-1900; 
01643     t.tm_mon = 5;
01644     t.tm_mday = 16;
01645     t.tm_hour = Hrs;
01646     t.tm_min = Mins;
01647     t.tm_sec = 51;
01648     set_time((time_t)mktime(&t));
01649     wait_ms(1);
01650     read_RTC();
01651     wait_ms(1);
01652     time_RCVD = true;
01653 }
01654 
01655 void at_timeout()
01656 {
01657     timeout.detach();
01658     data_fail = true;
01659 }
01660 
01661 void read_SERIAL()
01662 {  
01663     char rcvd_char;
01664     char rcvd_valid;
01665     //int cmd_t;
01666     uint8_t checksum_calculated;
01667     timeout.attach(&at_timeout,0.100);    //100ms timeout
01668     data_fail = false;
01669     while(UART.readable() && (num_bytes < RX_BUFFER_SIZE)&&(!data_fail))
01670     {
01671         rcvd_char = UART.getc();
01672         if(rcvd_char == '$')             //first character
01673             num_bytes = 0;
01674         else
01675             __nop();
01676             
01677         rx_buf[num_bytes] = rcvd_char;
01678         num_bytes++;
01679         if(rcvd_char == '\n')             //last character received
01680         {
01681             timeout.detach();
01682             strtok(rx_buf,",");
01683             if(strcmp(rx_buf,"$PPOTH") == 0)                      //* present submaster,Slaves or lsitners receive HB *// 
01684             {
01685                 sscanf(strtok (NULL,","),"%u", &rcvd_ADDR);        //address of connected device
01686                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01687                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01688                 sprintf(rx_buf,"$PPOTH,%u,%c*",rcvd_ADDR,rcvd_valid);
01689                 checksum_calculated = get_checksum(rx_buf);
01690                 if(checksum_calculated == checksum_rcvd_byte)
01691                 {
01692                     rcvd_HB();               //valid sentence received   
01693                 }                   
01694                 else
01695                     __nop();              //valid sentence receivedrcvd_HB();                                   //set flag when Heartbeat received
01696             }
01697             else if(strcmp(rx_buf,"$PPOTA") == 0)                  //* Master,submaster and Slaves receive  heartbeat resp *//
01698             {
01699                 sscanf(strtok (NULL,","),"%u", &rcvd_ADDR);
01700                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);
01701                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01702                 sprintf(rx_buf,"$PPOTA,%u,%c*",rcvd_ADDR,rcvd_valid);
01703                 checksum_calculated = get_checksum(rx_buf);
01704                 if(checksum_calculated == checksum_rcvd_byte)
01705                 {
01706                     valid_sentence[rcvd_ADDR] = rcvd_valid;
01707                     resp_rcvd_HB();               //valid sentence received  
01708                 }                    
01709                 else
01710                     __nop();
01711             }
01712             else if(strcmp(rx_buf,"$PPOTB") == 0)                 //* submaster,Slaves or listener receive broadcast *//
01713             {
01714                 sscanf(strtok (NULL,","), "%u", &err_ALL);       //device in error with addr_ID =  err_ID
01715                 sscanf(strtok (NULL,","), "%u",&err_Status);
01716                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01717                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01718                 sprintf(rx_buf,"$PPOTB,%u,%u,%c*",err_ALL,err_Status,rcvd_valid);
01719                 checksum_calculated = get_checksum(rx_buf);
01720                 if(checksum_calculated == checksum_rcvd_byte)
01721                 {               //valid sentence received  
01722                     valid = 'A';
01723                     rcvd_BROADCAST();   
01724                 }                 
01725                 else
01726                     valid = 'V';              //not valid 
01727             }
01728             else if(strcmp(rx_buf,"$PPOTC") == 0)                 //* submaster,Slaves or listener receive CMD *//
01729             {
01730                 sscanf(strtok (NULL,","), "%u", &rcvd_ADDR);       //cmd extracted
01731                 sscanf(strtok (NULL,","), "%u", &rpm_data[0]);     //rpm data digit 1 and soon
01732                 sscanf(strtok (NULL,","), "%u", &rpm_data[1]);       
01733                 sscanf(strtok (NULL,","), "%u", &rpm_data[2]);
01734                 sscanf(strtok (NULL,","), "%u",&rpm_data[3]);
01735                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01736                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01737                 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);
01738                 checksum_calculated = get_checksum(rx_buf);
01739                 if(checksum_calculated == checksum_rcvd_byte)
01740                    {
01741                     valid = 'A';             
01742                     RPM_cmd = true;                                    // in all devices who receive RPM command
01743                     rcvd_rpm_CMD();
01744                    }
01745                 else
01746                     valid = 'V';
01747             }
01748             /*
01749             else if(strcmp(rx_buf,"$PPOTD") == 0)                      //present submaster,Slaves or lsitners receive HB 
01750             {
01751                 sscanf(strtok (NULL,","), "%u", &rcvd_ADDR);        //address of connected device
01752                 sscanf(strtok (NULL,","), "%u",&dir);        // 1 for ahead and 2 for astern
01753                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01754                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01755                 sprintf(rx_buf,"$PPOTD,%u,%u,%c*",rcvd_ADDR,dir,rcvd_valid);
01756                 checksum_calculated = get_checksum(rx_buf);
01757                 if(checksum_calculated == checksum_rcvd_byte)
01758                 {
01759                     valid = 'A';
01760                     DIR_cmd = true;
01761                     rcvd_dir_CMD(); 
01762                 }
01763                 else
01764                     valid = 'V';                                   //set flag when Heartbeat received
01765             }
01766             */
01767             else if(strcmp(rx_buf,"$PPOTX") == 0)                //* Master,submaster,Slave or listners receive CMD acknowledge *//
01768             {
01769                 sscanf(strtok (NULL,","), "%u", &rcvd_ADDR);       //address extracted
01770                 //sscanf(strtok (NULL,","), "%u",&cmd_t);
01771                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01772                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01773                 sprintf(rx_buf,"$PPOTX,%u,%c*",rcvd_ADDR,rcvd_valid);
01774                 checksum_calculated = get_checksum(rx_buf);
01775                 if(checksum_calculated == checksum_rcvd_byte)
01776                     {
01777                         valid = 'A';
01778                         RPM_cmd_ack = true;       
01779                     }                      
01780                 else
01781                      valid = 'V';               // not valid sentence received;       
01782             }
01783             else if(strcmp(rx_buf,"$PPOTS") == 0)                 //*active channel status recieved *//
01784             {
01785                 sscanf(strtok (NULL,","), "%u", &ach_M);       //cmd extracted
01786                 sscanf(strtok (NULL,","), "%u", &ach_S);
01787                 sscanf(strtok (NULL,","), "%u", &rpm_data[0]);
01788                 sscanf(strtok (NULL,","), "%u", &rpm_data[1]);
01789                 sscanf(strtok (NULL,","), "%u", &rpm_data[2]);
01790                 sscanf(strtok (NULL,","), "%u", &rpm_data[3]);
01791                 sscanf(strtok (NULL,","), "%u", &last_entry[0]);
01792                 sscanf(strtok (NULL,","), "%u", &last_entry[1]);
01793                 sscanf(strtok (NULL,","), "%u", &last_entry[2]);
01794                 sscanf(strtok (NULL,","), "%u", &last_entry[3]);
01795                 //sscanf(strtok (NULL,","), "%u", &dir);
01796                 sscanf(strtok (NULL,","), "%u", &current_status);
01797                 //sscanf(strtok (NULL,","),"%u", &current_status_dir);
01798                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01799                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01800                 sprintf(rx_buf,"$PPOTS,%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],current_status,rcvd_valid);
01801                 checksum_calculated = get_checksum(rx_buf);
01802                 if(checksum_calculated == checksum_rcvd_byte)
01803                     {
01804                         valid = 'A';              //valid sentence received
01805                         rcvd_ACH(); 
01806                     }                      
01807                 else
01808                     valid = 'V';  
01809             }
01810             else if(strcmp(rx_buf,"$PPOTR") == 0)               //* control transfer request arrived*//
01811             {
01812                 sscanf(strtok (NULL,","),"%u", &rcvd_ADDR);
01813                 sscanf(strtok (NULL,","),"%u", &req);    //e.g $R req or $K ack 
01814                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01815                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01816                 if(addr_ID <= pot_Slave_ER)
01817                 {
01818                     sprintf(rx_buf,"$PPOTR,%u,%u,%c*",rcvd_ADDR,req,rcvd_valid);
01819                     checksum_calculated = get_checksum(rx_buf);
01820                     if(checksum_calculated == checksum_rcvd_byte)
01821                         { 
01822                             valid = 'A';                  
01823                             REQ_rcvd = true;
01824                             req_ADDR = rcvd_ADDR;
01825                             if(((rcvd_ADDR == pot_Master) && (addr_ID == pot_Submaster)) || ((rcvd_ADDR == pot_Submaster) && (addr_ID == pot_Master)))
01826                             {
01827                                 int_B.rise(&read_KEY_B);        //to enable ACK key interrupt
01828                                 wait_us(10);
01829                                 mcp23s17_1.gpintenb(0xff);      // portb of mcp1 ACK key enabled
01830                                 wait_us(10);
01831                                 led_ctrl[ACK_-1] = _FLASH;        //ack led blink
01832                             }
01833                             else 
01834                                 __nop();
01835                                 
01836                             if(((rcvd_ADDR == pot_Slave_MCR) && (addr_ID == pot_Slave_ER)) || ((rcvd_ADDR == pot_Slave_ER) && (addr_ID == pot_Slave_MCR)))
01837                             {
01838                                 int_B.rise(&read_KEY_B);        //to enable ACK key interrupt
01839                                 wait_us(10);
01840                                 mcp23s17_1.gpintenb(0xff);      //portb of mcp1 ACK key enabled
01841                                 wait_us(10);
01842                                 led_ctrl[ACK_-1] = _FLASH;       //ack led blink
01843                             }
01844                             else
01845                                 __nop();
01846                     
01847                             R_A_Ticker.attach(&R_A_Statemachine,0.5);
01848                         }
01849                     else
01850                         valid = 'V'; 
01851                 }
01852                 else
01853                     __nop();
01854             }
01855             else if(strcmp(rx_buf,"$PPOTK") == 0)               //* Master,submaster,Slave or listners REQ acknowledge *//
01856             {
01857                 sscanf(strtok (NULL,","), "%u", &rcvd_ADDR);
01858                 sscanf(strtok (NULL,","),"%u", &ack);    //e.g $R req or $K ack
01859                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid); 
01860                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01861                 
01862                 if(addr_ID <= pot_Slave_ER)
01863                 {
01864                     sprintf(rx_buf,"$PPOTK,%u,%u,%c*",rcvd_ADDR,ack,rcvd_valid);
01865                     checksum_calculated = get_checksum(rx_buf);
01866                     if(checksum_calculated == checksum_rcvd_byte)
01867                         { 
01868                             valid = 'A';
01869                             ack_ADDR = rcvd_ADDR;
01870                             ACK_rcvd = true;
01871                             //ACH_SW_over = true;
01872                         
01873                             if(((rcvd_ADDR == pot_Master) && (addr_ID == pot_Submaster)) || ((rcvd_ADDR == pot_Submaster) && (addr_ID == pot_Master)))
01874                             {
01875                                  led_ctrl[ACK_-1] = OFF;
01876                                  //R_A_Ticker.detach();
01877                             }
01878                             else if(((rcvd_ADDR == pot_Slave_ER) && (addr_ID == pot_Slave_MCR)) || ((rcvd_ADDR == pot_Slave_MCR) && (addr_ID == pot_Slave_ER)))
01879                             {
01880                                 led_ctrl[ACK_-1] = OFF;
01881                                 //R_A_Ticker.detach();
01882                             }
01883                             else
01884                                 __nop();
01885                         }
01886                     else
01887                         valid = 'V';
01888                 }                    
01889                 else
01890                     __nop();
01891             }
01892             else if(strcmp(rx_buf,"$PPOTT") == 0)                 //* submaster,Slaves or listener receive CMD *//
01893             {
01894                 sscanf(strtok (NULL,","), "%u", &Hrs_1);       //cmd extracted
01895                 sscanf(strtok (NULL,","), "%u", &Hrs_2); 
01896                 sscanf(strtok (NULL,","), "%u", &Mins_1);
01897                 sscanf(strtok (NULL,","),"%u", &Mins_2);
01898                 sscanf(strtok (NULL,"*"),"%c", &rcvd_valid);        //sentence validity char
01899                 sscanf(strtok (NULL,","),"%u", &checksum_rcvd_byte);
01900                 sprintf(rx_buf,"$PPOTT,%u,%u,%u,%u,%c*",Hrs_1,Hrs_2,Mins_1,Mins_2,rcvd_valid);
01901                 checksum_calculated = get_checksum(rx_buf);
01902                 if(checksum_calculated == checksum_rcvd_byte)
01903                 {
01904                     valid = 'A';
01905                     rcvd_TIME();
01906                 }                     
01907                 else
01908                     valid = 'V';
01909             }
01910             else
01911                 __nop();
01912         }
01913         else
01914             __nop();
01915     }
01916 }
01917 
01918 /********END of FUNCTION****************/
01919 
01920 /**************************************************************************************
01921 EOT Handler FUNCTIONS
01922  **************************************************************************************/
01923 void HB_handler()                     //function run periodically within active master only
01924 {   
01925     if(++sync_count >= sync_time)
01926     {
01927         time_RCVD = false;
01928         norm_op = false;
01929         sync_count = 0;
01930         ask_TIME();                         //master will send querry for GPS time
01931     }
01932     else if(time_RCVD || norm_op)                     //as all receive time update normal operation starts
01933     {
01934         if(ach_M == pot_Master)
01935         {   
01936             device_addr++;
01937             if(device_addr == no_pot_connected)    //max no-pot-conneted = 7
01938                 device_addr = 0;
01939         }
01940         else
01941             __nop();
01942         /*else if(ach_M == eot_Submaster)
01943         {   
01944             if(device_addr==2)
01945             {
01946                 device_addr=3;
01947             }
01948             else
01949             {
01950                 device_addr++;
01951                 if(device_addr>NO_MAX_EOT)
01952                 device_addr=1;
01953             }
01954         }
01955                         */
01956         
01957         send_ADDR = POT[device_addr].slave_ID;
01958         
01959         if(RPM_cmd)
01960         {
01961             send_RPM(send_ADDR);
01962             RPM_cmd =  false;                                                      //cmd to be send with current running address and cmd value
01963             wait_ms(2);
01964             //HB_Ticker.attach(&HB_State_Machine,0.010);
01965             CMD_Ticker.attach(&CMD_State_Machine,0.25);                   //CMD_state_machine ticker started              
01966         }
01967         /*
01968         else if(DIR_cmd)
01969         {
01970             send_DIR(send_ADDR);
01971             DIR_cmd =  false;                                                      //cmd to be send with current running address and cmd value
01972             wait_ms(2);
01973             //HB_Ticker.attach(&HB_State_Machine,0.010);
01974             //DIR_Ticker.attach(&DIR_state_machine,0.25);                   //CMD_state_machine ticker started              
01975         }
01976         */
01977         else  if(BROADCAST_send)
01978         {
01979             send_BROADCAST();         //broadcast needed err_ID nd err_Status
01980             BROADCAST_send = false;
01981             wait_ms(2);
01982         }
01983         else if(switch_CH)                            //active channel switch over happened
01984         {
01985             send_ACH();                              //active channel changeover
01986             switch_CH = false;
01987             wait_ms(2);
01988         }
01989         
01990         else
01991         {    
01992             send_HB(send_ADDR);   //hb is to be going on
01993             HB_Ticker.attach(&HB_State_Machine,0.015);                          //HB_state_machine timer started
01994         }
01995     }
01996     else if(++norm_count >= 5)
01997     {
01998         norm_count = 0;
01999         if(!time_RCVD)
02000             norm_op = true;
02001         else
02002             __nop();
02003     }
02004     else
02005         __nop();
02006 }
02007 
02008 /**************************************************************************************
02009 POT config and address Read FUNCTIONS
02010  **************************************************************************************/
02011 void read_POT_ADDR()                     //function give present eots and no. of connected eots
02012 {   
02013     pot_Addr = read_KEY_SPI(ch_D);
02014     if(pot_Addr==0xff)   //if 0xff it means no addressing done
02015         pot_Error=true;
02016     else if(pot_Addr!=0xff)
02017     {
02018         for( uint8_t i=0;i<=7;i++)
02019         {
02020             if(((1 << i) & pot_Addr)== 0)      // to check which bit of eot_Addr register is '0'
02021             {
02022                 if(i==0)                       // bit 0 means master present and soon
02023                 {   
02024                     addr_ID = pot_Master;
02025                     ach_M = pot_Master;
02026                     for(i = 1 ; i <= 7 ; i++)
02027                     {
02028                         if((((uint8_t)1<<i) & pot_Addr) == 0)
02029                         {
02030                             switch(i)
02031                             {
02032                                 case 1:
02033                                     POT[no_pot_connected].slave_ID = pot_Submaster;
02034                                     POT[no_pot_connected].err_cnt=0;
02035                                     POT[no_pot_connected].err_status=false;
02036                                     no_pot_connected++;
02037                                 break;
02038                                 case 2:
02039                                     ach_S = pot_Slave_MCR; 
02040                                     POT[no_pot_connected].slave_ID = pot_Slave_MCR;
02041                                     POT[no_pot_connected].err_cnt=0;
02042                                     POT[no_pot_connected].err_status=false;
02043                                     no_pot_connected++;
02044                                 break;
02045                                 case 3:
02046                                     if(ach_S == pot_Slave_MCR)                 //if MCR ispresent
02047                                         __nop();
02048                                     else
02049                                     {                                            //if MCR is not present
02050                                         ach_S = pot_Slave_ER;
02051                                     }                                     
02052                                     POT[no_pot_connected].slave_ID = pot_Slave_ER;
02053                                     POT[no_pot_connected].err_cnt = 0;
02054                                     POT[no_pot_connected].err_status=false;
02055                                     no_pot_connected++;
02056                                 break;
02057                                 case 4:
02058                                     POT[no_pot_connected].slave_ID = pot_Listner_WP;
02059                                     POT[no_pot_connected].err_cnt = 0;
02060                                     POT[no_pot_connected].err_status=false;
02061                                     no_pot_connected++;
02062                                 break;
02063                                 case 5:
02064                                     POT[no_pot_connected].slave_ID = pot_Listner_WS;
02065                                     POT[no_pot_connected].err_cnt=0;
02066                                     POT[no_pot_connected].err_status=false;
02067                                     no_pot_connected++;
02068                                 break;
02069                                 case 6:
02070                                     POT[no_pot_connected].slave_ID = pot_Listner_OPS;
02071                                     POT[no_pot_connected].err_cnt=0;
02072                                     POT[no_pot_connected].err_status=false;
02073                                     no_pot_connected++;
02074                                 break;
02075                                 case 7:
02076                                     POT[no_pot_connected].slave_ID = pot_Listner_ASP;
02077                                     POT[no_pot_connected].err_cnt=0;       
02078                                     POT[no_pot_connected].err_status=false;
02079                                     no_pot_connected++;
02080                                 break;
02081                             }
02082                         }
02083                     }
02084                     if(no_pot_connected <=0)
02085                         pot_Error = true;
02086                     else
02087                         pot_Error = false;  
02088                 }
02089                 else
02090                 {
02091                     switch(i)
02092                     {
02093                         case 1:
02094                         {
02095                             addr_ID = pot_Submaster;
02096                             ach_S = pot_Slave_MCR;
02097                             led_ach[ach_S-1] = ON;
02098                             break;
02099                         }
02100                         case 2:
02101                         {
02102                             addr_ID = pot_Slave_MCR;
02103                             ach_S = pot_Slave_MCR;
02104                             led_ach[ach_S-1] = ON;
02105                             break;
02106                         }
02107                         case 3:
02108                         {
02109                             addr_ID = pot_Slave_ER;
02110                             ach_S = pot_Slave_MCR;
02111                             led_ach[ach_S-1] = ON;
02112                             break;
02113                         }
02114                         case 4:
02115                         {
02116                             addr_ID = pot_Listner_WP;
02117                             ach_S = pot_Slave_MCR;
02118                             led_ach[ach_S-1] = ON;
02119                             break;
02120                         }
02121                         case 5:
02122                         {
02123                             addr_ID = pot_Listner_WS;
02124                             ach_S = pot_Slave_MCR;
02125                             led_ach[ach_S-1] = ON;
02126                             break;
02127                         }
02128                         case 6:
02129                         {
02130                             addr_ID = pot_Listner_OPS;
02131                             ach_S = pot_Slave_MCR;
02132                             led_ach[ach_S-1] = ON;
02133                             break;
02134                         }
02135                         case 7:
02136                         {
02137                             addr_ID = pot_Listner_ASP;
02138                             ach_S = pot_Slave_MCR;
02139                             led_ach[ach_S-1] = ON;
02140                             break;
02141                         }
02142                         default:
02143                             pot_Error = true;
02144                     }   
02145                 }
02146             }
02147         }
02148     }
02149 }
02150 
02151 void interrupt_init()
02152 {
02153     int_A.mode(PullUp);
02154     wait_ms(1);
02155     int_B.mode(PullUp);
02156     wait_ms(1);
02157     int_C.mode(PullUp);
02158     wait_ms(1); 
02159 }
02160 
02161 void Uart_init()
02162 {                                    
02163   UART.baud(9600);
02164   UART.format(8,SerialBase::None,1);
02165   wait_ms(1);
02166 }
02167 
02168 void Led_init()
02169 {   
02170     
02171     LED_CMD_ACK = ON;                  
02172     wait_ms(1);
02173        
02174     for(uint8_t i=0;i<=1;i++)             //ctrl led intialisation
02175     {
02176         LED_CTRL[i] = ON;
02177         wait_ms(1);
02178     }
02179     /*
02180     for(uint8_t i=0;i<=1;i++)             //ctrl led intialisation
02181     {
02182         LED_DIR[i] = ON;
02183         wait_ms(1);
02184     }
02185     */
02186     for(uint8_t i=0; i<=7;i++)            //ach led initialisation
02187     {
02188         LED_ACH[i] = ON ; 
02189         wait_ms(1);
02190     } 
02191     
02192     wait(1);
02193     
02194     LED_CMD_ACK = OFF;
02195     led_cmd_ack = OFF;
02196     wait_ms(1);
02197     
02198     for(uint8_t i=0;i<=1;i++)         //ctrl led turned off
02199     {
02200         LED_CTRL[i] = OFF;
02201         led_ctrl[i] = OFF;
02202         wait_ms(1);
02203     }
02204     /*
02205     for(uint8_t i=0;i<=1;i++)             //ctrl led intialisation
02206     {
02207         LED_DIR[i] = OFF;
02208         led_dir[i] = OFF;
02209         wait_ms(1);
02210     }
02211     */
02212     for(uint8_t i=0; i<=7;i++)         //ach led turned off
02213     {
02214         LED_ACH[i] = OFF; 
02215         led_ach[i] = OFF;
02216         wait_ms(1);
02217     } 
02218 }
02219 
02220 void pwm_init()
02221 {
02222     mypwm.period_ms(10);           //initialy 20ms
02223     wait_us(1);
02224     mypwm.write(.10);      //10%duty cycle more bright with less duty cycle
02225     wait_us(1);
02226 }
02227 
02228 void mcp23s17_init()
02229 {
02230     //device1 configuration
02231     mcp23s17_1.reset();           //reset on power-up
02232     wait_ms(1);
02233     mcp23s17_2.reset();           //reset on power-up
02234     wait_ms(1);
02235     mcp23s17_1.iocon(0x2a);
02236     wait_ms(1);
02237     mcp23s17_2.iocon(0x2a);
02238     wait_ms(1);
02239     mcp23s17_1.iodira(0xff);     //set 8-bits PORTA as inputs
02240     wait_ms(1);
02241     mcp23s17_1.iodirb(0xff);     //set 8-bits PORTB as inputs
02242     wait_ms(1);
02243     mcp23s17_1.ipola(0x00);
02244     wait_ms(1);
02245     mcp23s17_1.ipolb(0x00);
02246     wait_ms(1);
02247     mcp23s17_1.gpintena(0x00);   //initially disabled
02248     wait_ms(1);
02249     mcp23s17_1.gpintenb(0x00);    
02250     wait_ms(1);
02251     mcp23s17_1.defvala(0xff);
02252     wait_ms(1);
02253     mcp23s17_1.defvalb(0xff);
02254     wait_ms(1);
02255     mcp23s17_1.intcona(0x00);     //bank0,mirror disabled, SEQOP disabled, slew rate disabled,HAEN enabled,open drain enabled,interrupt active high,not allowed
02256     wait_ms(1);
02257     mcp23s17_1.intconb(0x00);
02258     wait_ms(1);
02259     mcp23s17_1.gppua(0xff);
02260     wait_ms(1);
02261     mcp23s17_1.gppub(0xff);
02262     wait_ms(1);
02263     
02264     //device2 configuration
02265    
02266     mcp23s17_2.iodira(0xff);       //set 8-bits PORTA as inputs
02267     wait_ms(1);
02268     mcp23s17_2.iodirb(0xff);       //set 8-bits PORTb as inputs
02269     wait_ms(1);
02270     mcp23s17_2.ipola(0x00);
02271     wait_ms(1);
02272     mcp23s17_2.ipolb(0x00);
02273     wait_ms(1);
02274     mcp23s17_2.gpintena(0xff);     //initially 0xff will be always enabled req/inc/dec/test
02275     wait_ms(1);
02276     mcp23s17_2.gpintenb(0x00);     //interrupts disabled for address PORT
02277     wait_ms(1);
02278     mcp23s17_2.defvala(0xff);
02279     wait_ms(1);
02280     mcp23s17_2.defvalb(0xff);
02281     wait_ms(1);
02282     mcp23s17_2.intcona(0x00);    //bank0,mirror disabled, SEQOP disabled, slew rate disabled,HAEN enabled,open drain enabled,interrupt active high,not allowed
02283     wait_ms(1);
02284     mcp23s17_2.intconb(0x00);
02285     wait_ms(1);
02286     mcp23s17_2.gppua(0xff);
02287     wait_ms(1);
02288     mcp23s17_2.gppub(0xff);
02289     wait_ms(1);
02290     mcp23s17_1.intcapa();    //dummy read performed to clear any interrupt on power up
02291     wait_ms(1);
02292     mcp23s17_1.intcapb();
02293     wait_ms(1);
02294     mcp23s17_2.intcapa();
02295     wait_ms(1);
02296     
02297 }
02298 
02299 void Spi3_init()              //for mcp23s17
02300 {
02301   _SPI3.format(8,0);         //8bit,mode 0
02302   _SPI3.frequency(1000000);  //1mhz   
02303   wait_ms(1);
02304 }
02305 
02306 void RTC_init()
02307 {
02308     read_RTC();
02309     wait_ms(1);
02310     RTC_display(RTC_buffer);
02311     wait_ms(1);
02312 }
02313 
02314 void SetDateTime
02315 (    int           year = 0
02316     ,int           mon = 0
02317     ,int           day = 0
02318     ,int           hour = 0
02319     ,int           min = 0
02320     ,int           sec = 0
02321 )
02322 {
02323     struct     tm Clock;
02324     Clock.tm_year = year - 1900;
02325     Clock.tm_mon  = mon;
02326     Clock.tm_mday = day;
02327     Clock.tm_hour = hour;
02328     Clock.tm_min  = min;
02329     Clock.tm_sec  = sec;
02330     time_t epoch = mktime(&Clock);
02331     set_time(epoch);                              //time set
02332 }
02333 
02334 void max7219_init()
02335 {
02336     max7219.set_num_devices(2);                 //total 02 no. of devices
02337     DEVICE1.device_number = 0x01;
02338     DEVICE1.decode_mode = 0xff;                 //bcd decode mode
02339     DEVICE1.intensity = 0x01;                   //Max7219::MAX7219_INTENSITY_8,
02340     DEVICE1.scan_limit = 0x07;                  // 1-4 digits RTC,5-8 digits last cmd RPM
02341     wait_ms(1);
02342     DEVICE2.device_number = 0x02;               //
02343     DEVICE2.decode_mode = 0xff;                 //bcd decode mode
02344     DEVICE2.intensity = 0x01;                   //Max7219::MAX7219_INTENSITY_8,     //intensity moderate
02345     DEVICE2.scan_limit = 0x03;                  //1-4 digits current
02346     wait_ms(1);
02347 
02348     max7219.init_device(DEVICE1);               //DEVICE 1 configured as per above settings
02349     wait_ms(1);
02350     max7219.enable_device(1);                   //normal operation
02351     wait_ms(1);
02352     max7219.init_device(DEVICE2);               //DEVICE 2 configured as per above settings
02353     wait_ms(1);
02354     max7219.enable_device(2);                   //normal operation
02355     wait_ms(1);
02356     max7219.set_display_test();                  //all on
02357     wait(1);
02358     max7219.clear_display_test();                //normal operation
02359     wait_ms(1);
02360     for(uint8_t i=1; i<=4; i++)  
02361     {
02362         max7219.write_digit(1, i, 0x00);   //device 1 RTC, digit 1-4 ,data 0x01
02363         wait_us(100);
02364     }
02365     wait_ms(100);
02366     
02367     for(uint8_t i=4; i<=8; i++)
02368     {
02369         max7219.write_digit(1, i, 0x00);   //device 1 last cmd, digit 4-8 ,data 0x01
02370         wait_us(100);
02371     }
02372     wait_ms(100);
02373     for(uint8_t i=1; i<=4;i++)
02374     {
02375         max7219.write_digit(2, i, 0x00);   //device 2 current CMD, digits 1-4 ,data 0x01
02376     }
02377     wait_ms(100);
02378 }
02379 
02380 void Spi2_init()             // for max7219
02381 {
02382        _SPI2.format(16,0);         //16bit,mode 0
02383        _SPI2.frequency(1000000);  //1mhz
02384        wait_ms(1);
02385 }
02386 
02387 void Discrete_init()
02388 {
02389      buzzer = ON;
02390      hooter = ON;             //on
02391      wait(1);   // one second delay
02392      buzzer = OFF;
02393      hooter = OFF;              //off
02394 }
02395 
02396 void Parameters_init()
02397 { 
02398     /*intialization of all bool data types indicating different error flags */     
02399     pot_Error = false;
02400     device_ERR = false;  
02401     pot_MCR_err = false;
02402     pot_ER_err = false;
02403     test = false; 
02404     toggle = false;
02405     toggle_fast = false;  
02406     display_flash = false;   
02407     norm_op = false;                    
02408     
02409     /*intialization of all bool data types indicating flag on key press interruption */
02410     key_CMD = false;
02411     key_CTRL = false;
02412     key_SET = false;
02413     REQ_key = false;
02414     ACK_key = false;
02415     RPM_cmd = false;              //if true RPM command is raised
02416     DIR_cmd = false;              //if true DIR command is raised
02417     ENTER_ACK_key = false;
02418     disp_clear = false;
02419     
02420     /*intialization of all bool data types indicating flags while serial receive */ 
02421     RPM_cmd_ack = false;
02422     HB_ack_rcvd = false;
02423     BROADCAST_rcvd = false;
02424     HB_rcvd = false;
02425     REQ_rcvd = false;
02426     ACK_rcvd = false;
02427     time_RCVD = false;
02428     data_fail = false;
02429     
02430     /*intialization of all bool data types indicating flags while serial transmit */ 
02431     BROADCAST_send = false;
02432     RPM_cmd_ack_send = false;
02433     DIR_cmd_ack_send = false;
02434     REQ_send = false;
02435     ACK_send = false;
02436     HB_send = false;
02437     
02438     /*intialization of all bool data types indicating active channel changeover*/
02439     test=false;
02440     disp_test = false;
02441     ACH_SW_over = switch_CH = false;
02442     
02443     display_flash = false;
02444     
02445     /*intialization of all int  data types*/
02446     addr = req = ack = ach_S = ach_M = duty_cycle = sync_count = 0;
02447     pot_Addr = addr_ID = send_ADDR = rcvd_ADDR = req_ADDR = ack_ADDR = 0;
02448     test_cnt = err_ID = err_Status = ticker_count = ticker_count_fast  = current_status = current_status_dir= 0;
02449     spi_error = set_bit = err_ALL = no_pot_connected = norm_count = Hrs_1 = Hrs_2 = Mins_1 = Mins_2 = 0;
02450     checksum_send_byte = checksum_rcvd_byte = 0;
02451     
02452     //dir = last_dir = 0;
02453     HB_timer =0;
02454     sync_time = 0;
02455     num_bytes = 0;
02456 
02457     device_addr = -1;
02458     valid = 'A';
02459     
02460     POT = new  _POT[NO_MAX_POT];
02461 }
02462 
02463 void POT_INIT()
02464 {   
02465     Parameters_init();
02466     wait_ms(1);
02467     
02468     Discrete_init();
02469     wait_ms(1);
02470     
02471     Spi2_init();
02472     wait_ms(1);
02473     
02474     max7219_init();
02475     wait_ms(1);
02476     
02477     SetDateTime(2017,11,16,16,45,40); // set default date and time
02478     wait_ms(1);
02479     
02480     RTC_init();
02481     wait_ms(1);
02482     
02483     Spi3_init();
02484     wait_ms(1);
02485     
02486     mcp23s17_init();
02487     wait_ms(1);
02488     
02489     pwm_init();
02490     wait_ms(1);
02491     
02492     Led_init();
02493     wait_ms(1);
02494     
02495     Uart_init(); 
02496     wait_ms(1);
02497     
02498     read_POT_ADDR();
02499     wait_ms(1);
02500     
02501     interrupt_init();
02502     wait_ms(1);
02503     
02504     if((addr_ID == pot_Master)&&(!pot_Error))                         //if addres of master eot found, by default master
02505     {
02506         wait(10);                             //wait for 10sec,as MCU take time to read time from GPS
02507         led_ach[ach_M-1] = ON;   
02508         int_A.rise(&read_KEY_A);              //all key functions enabled for PORTA,B,C        
02509         int_B.rise(&read_KEY_B);                
02510         int_C.rise(&read_KEY_C); 
02511         wait_ms(2);
02512         mcp23s17_1.gpintena(0xff);    //interrupts enabled
02513         wait_us(100);
02514         mcp23s17_1.gpintenb(0xff);    //ff
02515         wait_us(100);
02516         HB_timer = 1.0/no_pot_connected;
02517         sync_time = 3600/HB_timer;                //   3600.0/HB_timer; required
02518         pot_HB.attach(&HB_handler,HB_timer);    //
02519         wait_ms(1);
02520         UART.attach( &read_SERIAL);    //receive interrupt enabled
02521         wait_ms(1);
02522         ask_TIME();                    //send enquiry to Central power unit for time setting
02523         wait_ms(2);
02524         send_ACH();
02525         wait_ms(2);
02526     }
02527     else if(pot_Submaster <= addr_ID <= pot_Listner_ASP)
02528     {
02529         wait(1);
02530         led_ach[0] = ON;           //by default master led turns on
02531         int_A.rise(NULL);          //all key functions/interrupt disabled for PORTA,B       
02532         int_B.rise(NULL);
02533         int_C.rise(&read_KEY_C);   //only PORTC needs to be intialized in other all cases,inc,dec,tst,req
02534         wait_ms(1);
02535         UART.attach( &read_SERIAL);    //receive interrupt enabled
02536         wait_ms(1);
02537     }
02538     else if(pot_Error)
02539     {
02540         int_A.rise(NULL);
02541         int_B.rise(NULL);
02542         int_C.rise(NULL);
02543         pot_Error = true;
02544         //return(-1);
02545     }   
02546     else
02547     {
02548         __nop();
02549     }
02550 }
02551 
02552 int main()
02553 {
02554     POT_INIT();
02555     
02556     led_refresh.attach(&update_led , 0.020);   //refresh rate 20ms
02557     wait_ms(2);
02558     
02559     RTC_ticker.attach(&read_RTC , 59);   //after 60 sec
02560     wait_ms(2);
02561     
02562     while(1) 
02563     {
02564     }
02565 }