direction commands updated to Up down RPM value
Dependencies: MAX7219pot MCP23S17 mbed
Fork of POT_V_1_0 by
main.cpp
- Committer:
- viewdeep51
- Date:
- 2017-09-28
- Revision:
- 0:ba33a62aea4e
- Child:
- 1:e116808d8b00
File content as of revision 0:ba33a62aea4e:
#include "mbed.h" #include "mbed.h" #include "pot.h" #include "max7219.h" #include "MCP23S17.h" using namespace std; //------------------------------------ // Hyperterminal configuration // 9600 bauds, 8-bit data, no parity //------------------------------------ Serial UART(SERIAL_TX, SERIAL_RX); //timer instances creation// Ticker pot_HB; Ticker HB_Ticker; Ticker flash_Ticker; Ticker R_A_Ticker; Ticker CMD_Ticker; Ticker disp_FLASH; //display blink Ticker DIR_Ticker; //SPI instances creation// SPI _SPI2(SPI2_MOSI, SPI2_MISO, SPI2_SCK); //for displays max7219 SPI _SPI3(SPI3_MOSI, SPI3_MISO, SPI3_SCK); //for keyscan mcp23s17 //class object instances for key I/O expander and segment driver// MCP23S17 mcp23s17_1(1,_SPI3, SPI3_CS1,SPI3_RST); //class MCP23S17 object instance for mcp23s17 IC-1 key detection MCP23S17 mcp23s17_2(2,_SPI3, SPI3_CS2,SPI3_RST); //class MCP23S17 object instance for mcp23s17 IC-2 key detection Max7219 max7219(SPI2_MOSI, SPI2_MISO, SPI2_SCK,SPI2_CS1); //object instance for seven segment drivers //interrupts definations InterruptIn int_A(INT_A); //8commands InterruptIn int_B(INT_B); //4 3commands+1ack InterruptIn int_C(INT_C); //4(3 controls(INC+,DEC-,TEST)+1 req) enbaled for all //chip select definations for max7219 & mcp23s17 as digitalout pins// DigitalOut cs_disp1(SPI2_CS1); DigitalOut cs_disp2(SPI2_CS2); //max7219 DigitalOut cs_key1(SPI3_CS1); DigitalOut cs_key2(SPI3_CS2); //mcp23s17 DigitalOut Drive_En(Tx_EN); //uart driver enable //discrete outputs definations buzzer and hooter DigitalOut buzzer(BUZ); DigitalOut hooter(HTR); int addr,req,ack,cmd,dir,last_cmd, send_ADDR, rcvd_ADDR, ach_S,ach_M,test_cnt,req_ADDR,ack_ADDR, err_ID, err_Status; uint8_t digit_disp_1, digit_disp_2, digit_disp_3; //disp1 for new rpm, disp2 for current rpm, disp3 for rtc float brightness; uint8_t spi_error,no_pot_connected; char pot_Addr,addr_ID,checksum; float HB_timer; bool spi_ERR,pot_Error,_disp_FLASH; bool RPM_cmd,DIR_cmd, RPM_cmd_ack, DIR_cmd_ack; bool HB_rcvd, HB_ack_rcvd, CMD_rcvd, CMD_ack_rcvd, REQ_rcvd, BROADCAST_rcvd, ACK_rcvd, rcvd_DIR; bool HB_send, CMD_send, BROADCAST_send, REQ_send, ACK_send, CMD_ack_send; bool test; bool CMD_key; bool switch_CH, pot_MCR_err, pot_ER_err, ACH_SW_over; char *key;// = new char[RX_BUFFER_SIZE]; //memory allocation for Receive buffer char* valid; int device_addr = -1; /************************************************************************************** EOT LED CLASS **************************************************************************************/ class LED{ public: LED(PinName led); //constructor declaration void set_Brightness(float bright); void ON(); void OFF(); void FLASHH(); private: Ticker _flash; bool on_off; bool Fllash; float brightness; PwmOut _LED; void __flash(); }; LED::LED(PinName led): _LED(led) //constructor defination { brightness = 0.000; on_off = false; Fllash = false; _LED = brightness; } void LED::set_Brightness(float bright) { brightness = bright; if(!Fllash) _LED = bright; else __nop(); } void LED::ON() { _LED = brightness; Fllash = false; _flash.detach(); } void LED::OFF() { _LED = 0; Fllash = false; _flash.detach(); } void LED::FLASHH() { Fllash = true; _flash.attach(callback(this, &LED::__flash),0.5); } void LED::__flash() { if(on_off) _LED = brightness; else _LED = 0; on_off = !on_off; } /************************************************************************************** EOT LED CLASS END **************************************************************************************/ //array of objects/instances of class LED & PwmOut// LED LED_DIR[2] = {_AHEAD,_ASTERN}; // direction control LED LED_CTRL[2] = {_REQ,_ACK}; //transfer control LED LED_ACH[8] = {_WH,_BRDG,_MCR,_ER,_WP,_WS,_OPS,_ASP}; //active channels uint8_t rpm_data[4] = {0,0,0,0}; //digits 0-3 uint8_t last_entry[4] = {0,0,0,0}; //digits 0-3 struct _POT { int slave_ID; uint8_t err_cnt; bool c_err; //communication error }; _POT* POT=NULL; enum AddrID { pot_Master = 1, pot_Submaster, pot_Slave_MCR, pot_Slave_ER, pot_Listner_WP, pot_Listner_WS, pot_Listner_OPS, pot_Listner_ASP = 8 }; enum pin_STATUS { _OFF =0, _ON =1 }; enum KEY { ZERO = 0, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, FALSE0 = 10 }; enum KEY num_KEY; enum CTRL { REQ_ = 1, ACK_ = 2, FALSE1= 3 }; enum CTRL ctrl_KEY; enum direction_KEY { AHEAD = 1, ASTERN, FALSE2 = 3 }; enum direction_KEY dir_KEY; enum display_KEY { clr_ENTRY = 0, //CE last_ENTRY, //C ENTER_ACK, //enter in case of master and ACK in case of slaves/repeaters FALSE3 = 3 }; enum display_KEY disp_KEY; enum SET { INC=0, DEC, TEST, FALSE4 = 4 }; enum SET set_KEY; enum CHANNEL { ch_A=1, ch_B, ch_C, ch_D=4 }; //keyscan channelA,B,C,Dof MCP23s17 1& 2 respectively enum CHANNEL ch; enum ack_dir_rpm { _RPM = 1, _DIR = 2 }; /************************************************************************************** EOT display update FUNCTIONS **************************************************************************************/ void display_update(bool RTC_disp, char* digits) { if(RTC_disp) { for(uint8_t i = 0; i <= 3; i++) //to write all the four digits { max7219.write_digit(2, i+1, *(digits+i)); //device 2, digit 1-4 ,data 0x01 } } else { for(uint8_t i = 0; i <= 3; i++) //to write all the four digits { max7219.write_digit(1, i+1, *(digits+i)); //device 1, digit 1-4 ,data pointer } } } /************************************************************************************** EOT State Machines FUNCTIONS **************************************************************************************/ void HB_State_Machine() //run for 50ms at an interval of 10ms,event driven start stop { static int hb_state_cnt = 0; /* if(HB_send) { HB_send = false; hb_state_cnt = 0; } else __nop(); */ if(HB_ack_rcvd) { HB_ack_rcvd = false; HB_Ticker.detach(); POT[device_addr].err_cnt = 0; POT[device_addr].c_err = false; hb_state_cnt = 0; if(POT[device_addr].slave_ID == ach_S) LED_ACH[send_ADDR - 1].ON(); else LED_ACH[send_ADDR - 1].OFF(); } else { if(++hb_state_cnt >= 5) //50ms { if((++POT[device_addr].err_cnt >= 3) && (!POT[device_addr].c_err)) //hb ack not received in third attempt { POT[device_addr].c_err = true; POT[device_addr].err_cnt = 0; LED_ACH[send_ADDR - 1].FLASHH(); err_ID = POT[device_addr].slave_ID; err_Status = 1; BROADCAST_send = true; //broadcast needed to be sent if((POT[device_addr].slave_ID == pot_Slave_MCR) && (ach_S == pot_Slave_MCR)) { ach_S = pot_Slave_ER; pot_MCR_err = true; switch_CH = true; } else if((POT[device_addr].slave_ID == pot_Slave_ER) && (!POT[device_addr-1].c_err)) { //if((ach_S == pot_Slave_ER) && (pot_MCR_err)) // pot_Error = true; // if((ach_S == pot_Slave_ER) && (!pot_MCR_err)) // { ach_S = pot_Slave_MCR; pot_ER_err = true; switch_CH = true; } else pot_Error = false; } } hb_state_cnt=0; // pot_MCR_err = false; // pot_ER_err = false; err_Status = 0; // no communication error HB_Ticker.detach(); } } } void CMD_State_Machine() //function run periodcally in all connected devices on bus { int cmd_state_cnt=0; if(RPM_cmd_ack) //PEOTX,CMD received in Master/SUB_Master, non Active Slave & Listner { RPM_cmd = false; //no more PEOTC will be sent onwards disp_FLASH.detach(); //timer stoped max7219.enable_device(1); //disp 1 back in normal mode buzzer = _OFF; hooter = _OFF; cmd_state_cnt = 0; RPM_cmd_ack = false; CMD_Ticker.detach(); //cmd state machine ticker stopped in all devices } //else // { //if(addr_ID != ach_S) //PEOTC, CMD received in other than Active Slave // return; else if((CMD_ack_send) && (addr_ID == ach_S)) //if Hotter is ON then send ACK, in case of active Slave { disp_FLASH.detach(); //flash timer stoped max7219.enable_device(1); //disp 1 back in normal mode steady ON buzzer = _OFF; hooter = _OFF; cmd_state_cnt = 0; CMD_ack_send = false; int_B.rise(NULL); //cmd ack send so disable the key of active slave CMD_Ticker.detach(); //would be stopped in active slave only } else if(hooter == _OFF) //if hooter still off { if(++cmd_state_cnt >= 12) //Hotter ON after 3sec { hooter = _ON; /* if(++cmd_state_cnt >= 96) //still command ack not recived for 24 sec { LED_CMD[cmd].OFF(); //command suspended buzzer = OFF; hooter = OFF; int_A.rise(NULL); int_A.rise(NULL); CMD_ticker.detach(); //timer stoped in all connected devices if ack not received in 3sec } */ } else __nop(); } } } void R_A_Statemachine() { static int state_cnt = 0; if(ACK_rcvd) { //ack_ADDR = rcvd_ADDR; ACK_rcvd = false; } else if(REQ_rcvd) { //req_ADDR = rcvd_ADDR; REQ_rcvd = false; } if(++state_cnt >= 10) //REQ not acknowledged for 5 sec, leds turn off, timer stopped { R_A_Ticker.detach(); LED_CTRL[REQ_-1].OFF(); LED_CTRL[ACK_-1].OFF(); } else { if(ACH_SW_over) //active channel switchover true only after acknowledge receive { ACH_SW_over = false; if(addr_ID == pot_Master) { if(ack_ADDR == 3 || ack_ADDR == 4) { if(ach_S == pot_Slave_MCR) ach_S = pot_Slave_ER; else if(ach_S == pot_Slave_ER) ach_S = pot_Slave_MCR; } else if(ack_ADDR == 2 || ack_ADDR == 1) { if(ach_M == pot_Master) ach_M = pot_Submaster; else if(ach_M == pot_Submaster) ach_M = pot_Master; } switch_CH = true; state_cnt = 0; R_A_Ticker.detach(); } else { state_cnt = 0; R_A_Ticker.detach(); } } } } void DIR_Statemachine(void) { static int dir_state_cnt = 0; if(DIR_cmd_ack) { DIR_cmd_ack = false; LED_DIR[dir-1].ON(); //led direction acknowledged turn steady buzzer = _OFF; //buzzer Off hooter = _OFF DIR_Ticker.detach(); } else { if((++dir_state_cnt >= 12) && (hooter == _OFF)) //direction command not ack for 03 sec { hooter = _ON; dir_state_cnt = 0; } else __nop(); } } void DISP_FLASH(void) //function attached to event driven ticker disp_FLASH { _disp_FLASH = !_disp_FLASH; if(_disp_FLASH) max7219.disable_device(1); else max7219.enable_device(1); } void NUMERIC_handler(uint8_t key_ID) //function sacnning all the 0-9 number keys { uint8_t num; num = key_ID; if(key_ID != FALSE0) { if(((ach_M == pot_Master) && (addr_ID == pot_Master)) || ((ach_M == pot_Submaster) && (addr_ID == pot_Submaster))) //for Master { if(digit_disp1 <= 1) digit_disp1 = 4; else digit_disp1-- ; rpm_data[digit_disp1-1] = num; max7219.write_digit(1,digit_disp1,rpm_data[digit_disp1-1]); //4th digit updated on first press, then 3rd on next press....soon } else __nop(); } else __nop(); } } void CTRL_handler(uint8_t CTRL_ID) //handle control transfer { if(CTRL_ID != FALSE1) { if((addr_ID == pot_Slave_MCR) || (addr_ID == pot_Slave_ER)) { if(CTRL_ID == REQ_) { req = REQ_; //req data updated 0 here, same int values as in enum LED_CTRL[REQ_-1].FLASHH(); //req led flash starts R_A_Ticker.attach(&R_A_Statemachine,0.5); } if(CTRL_ID == ACK_ && REQ_rcvd) { ack = ACK_; //ack data updated 2 here LED_CTRL[ACK_-1].OFF(); //ack led turns off R_A_Ticker.detach(); } } } else __nop(); //then do nothing } void DIR_handler(uint8_t DIR_ID) //handle control transfer { if(DIR_ID != FALSE2) { if(addr_ID == ach_M) { if(DIR_ID == AHEAD) { dir = AHEAD; LED_DIR[dir-1].FLASHH(); //led direction AHEAD start flashing buzzer = _ON; //buzzer ON DIR_cmd = true; DIR_Ticker.attach(&DIR_Statemachine,0.5); } else __nop(); if(DIR_ID == ASTERN) { dir = ASTERN; LED_DIR[dir-1].FLASHH(); //led direction AHEAD start flashing buzzer = _ON; //buzzer ON DIR_cmd = true; DIR_Ticker.attach(&DIR_Statemachine,0.5); } else __nop(); } else if (addr_ID == ach_S) { if(DIR_ID == AHEAD) { if(rcvd_DIR && (dir == AHEAD)); //direction command is received LED_DIR[dir-1].ON(); //led direction AHEAD start flashing buzzer = _OFF; //buzzer ON DIR_cmd = true; DIR_Ticker.attach(&DIR_Statemachine,0.5); } if(DIR_ID == ASTERN) { dir = ASTERN; LED_DIR[dir-1].FLASHH(); //led direction AHEAD start flashing buzzer = _ON; //buzzer ON DIR_cmd = true; DIR_Ticker.attach(&DIR_Statemachine,0.5); } } } else __nop(); //then do nothing } void DISP_handler(uint8_t DISP_ID) //handle control transfer { uint8_t disp_key; disp_key = DISP_ID; if(DISP_ID != FALSE3) { if((addr_ID == ach_M)||(addr_ID == ach_S)) { switch(disp_key) { case clr_ENTRY: //CE delete only last/4th digit and shift others digits towards right/4th digit if(addr_ID == ach_M) { for(uint8_t i = 3; i >= 0 ; i--) { rpm_data[i] = rpm_data[i-1]; if(i==0) rpm_data[i] = 0; //data 0 means left most digit will be blank bcoz no decode mode is used } for(uint8_t i = 0; i >=3; i++) { max7219.write_digit(1,i+1,rpm_data[i]); //4th digit will be deleted whilers are shifted towards right 1st will be blank } } else { __nop(); } break; case last_ENTRY: //C delete all digits in DS1 and show last entered value if(addr_ID == ach_M) { for(uint8_t i = 0; i >=3; i++) { max7219.write_digit(1,i+1,last_entry[i]); //last entery displayed } } else { __nop(); } break; case ENTER_ACK: if((addr_ID == ach_S)&&(CMD_rcvd)) //RPM command ack needs to be sent { //flashing display1 turned steady RPM_cmd_ack = true; //RPM command acknowledged by active slave } else if (addr_ID == ach_M) //in case of active masters { //disp1 start flashing, and data sent over UART for all digits 1-4 for(uint8_t i = 0; i >=3; i++) { last_entry[i] = rpm_data[i]; //data saved to last entery } disp_FLASH.attach(&DISP_FLASH,0.500); //timer started int_A.rise(NULL); //all key functions DISabled for PORTA,B in active MASTER only int_B.rise(NULL); RPM_cmd = true; //command need to be send } else { __nop(); } break; default: break; } } } else __nop(); //then do nothing } void BRT_handler(float brt) { for(uint8_t i=0;i<=1;i++) //cmd led initialisation { LED_DIR[i].set_Brightness(brt); //setting period 100 ms } for(uint8_t i=0;i<=1;i++) //ctrl led intialisation { LED_CTRL[i].set_Brightness(brt); } for(uint8_t i=0; i<=7;i++) //ach led initialisation { LED_ACH[i].set_Brightness(brt); } } void SET_handler(uint8_t Set_ID) { if(Set_ID != FALSE4) { if(Set_ID == INC) { if(brightness <= 0.99f) { brightness = +0.01; BRT_handler(brightness); } else { brightness = 0.99; BRT_handler(brightness); } } else if(Set_ID == DEC) { if(brightness >= 0.01f) { brightness = -0.01; BRT_handler(brightness); } else { brightness = 0.01; //minimum brightnes BRT_handler(brightness); } } else if(Set_ID == TEST) { test_cnt++; if(test_cnt <= 1) test = true; else if(test_cnt >= 2) { test = false; test_cnt = 0; } } } else __nop(); } /************************************************************************************** EOT SPI Data Read KEY FUNCTIONS **************************************************************************************/ unsigned char read_KEY_SPI(int CH) { char _key; uint8_t spi_err=0; switch(CH) { case 1: if(spi_err<3) { _key=mcp23s17_1.intcapa(); // read(INTCAPA_ADDR); if(mcp23s17_1.intcapa()) //read(INTCAPA_ADDR)) again if some non zero value obtained //if Interrupt pending { spi_err++; } else { spi_err=0; } } else { _key=0; spi_ERR=true; } break; case 2: if(spi_err<3) { _key=mcp23s17_1.intcapb(); if(mcp23s17_1.intcapb()) //if Interrupt pending { spi_err++; } else { spi_err=0; } } else { _key=0; spi_ERR=true; } break; case 3: if(spi_err<3) { _key=mcp23s17_2.intcapa(); if(mcp23s17_2.intcapa()) //if Interrupt pending { spi_err++; } else { spi_err=0; } } else { _key=0; spi_ERR=true; } break; case 4: _key = mcp23s17_2.gpiob(); //address read PORTB of chip2 for getting pot addresses break; default: _key = 0; break; } return(_key); } void read_KEY_A() //function check status of PORTA of MCP23S17 (1) chip { char key_status = 0; key_status = read_KEY_SPI(ch_A); //to read portA of mcp23s17(1) if(key_status != 0xff) //means some key must have been pressed { switch(key_status) { case 0xfe: //0xfe GPA0 num_KEY = ZER0; break; case 0xfd: //0xfd GPA1 num_KEY = ONE; break; case 0xfb: //0xfb GPA2 num_KEY = TWO; break; case 0xf7: //0xf7 GPA3 num_KEY = THREE; break; case 0xef: //0xef GPA4 num_KEY = FOUR; break; case 0xdf: //0xdf GPA5 num_KEY = FIVE; break; case 0xbf: //0xbf GPA6 num_KEY = SIX; break; case 0x7f: //0x7f GPA7 num_KEY = SEVEN; break; default: num_KEY = FALSE0; break; } NUMERIC_handler(num_KEY); } } void read_KEY_B() { char key_status = 0; key_status = read_KEY_SPI(ch_B); //to read portBof mcp23s17(1) if(key_status != 0xff) { switch(key_status) { case 0xfe: //0xfe GPA0 num_KEY = EIGHT; NUMERIC_handler(num_KEY); break; case 0xfd: //0xfd GPA1 num_KEY = NINE; NUMERIC_handler(num_KEY); break; case 0xfb: //0xfb GPA2 dir_KEY = AHEAD; DIR_handler(dir_KEY); break; case 0xf7: //0xf7 GPA3 dir_KEY = ASTERN; DIR_handler(dir_KEY); break; case 0xef: //0xef GPA4 ctrl_KEY = ACK; CTRL_handler(ctrl_KEY); break; case 0xdf: //0xdf GPA5 disp_KEY = clr_ENTRY; //CE DISP_handler(disp_KEY); break; case 0xbf: //0xbf GPA6 disp_KEY = last_ENTRY; //C DISP_handler(disp_KEY); break; case 0x7f: //0x7f GPA7 disp_KEY = ENTER_ACK; DISP_handler(disp_KEY); break; default: num_KEY = FALSE0; ctrl_KEY = FALSE1; dir_KEY = FALSE2; disp_KEY = FALSE3; break; } } } void read_KEY_C() { char key_status = 0; key_status = read_KEY_SPI(ch_C); //to read portA of mcp23s17(2) if(key_status != 0xff) { if(key_status==0xfe) { ctrl_KEY = REQ_; //control transfer REQ button pressed CTRL_handler(ctrl_KEY); } else { if(key_status==0xfd) set_KEY = INC; //setting key INC else if(key_status==0xfb) set_KEY = DEC; //setting key DEC else if(key_status==0xf7) set_KEY = TEST; //setting key TEST else { set_KEY = FALSE4; //setting key TEST ctrl_KEY = FALSE1; } SET_handler(set_KEY); } } } /************************************************************************************** EOT Serial Data Out FUNCTIONS **************************************************************************************/ uint8_t get_checksum(const char *sentence) { const char *n = sentence + 1; // Plus one, skip '$' uint8_t chk = 0; /* While current char isn't '*' or sentence ending (newline) */ while ('*' != *n && NMEA_END_CHAR_1 != *n) { if ('\0' == *n || n - sentence > NMEA_MAX_LENGTH) { /* Sentence too long or short */ return 0; } chk ^= (uint8_t) *n; n++; } return chk; } void resp_HB(uint8_t seq) //presentees(submaster,slaves,listeners will respond back to the HB along with REQ and CMD ack status { switch(seq) { case 0: sprintf(key,"$PEOTA,%u,%c*", addr_ID, *valid); break; case 1: sprintf(key,"$PEOTR,%u,%u,%c*", addr_ID, req, *valid); break; case 2: sprintf(key,"$PEOTK,%u,%u,%c*", addr_ID, ack, *valid); break; default: sprintf(key,"$PEOTA,%u,%c*", addr_ID, *valid); break; } checksum=get_checksum(key); sprintf(key,"%u\r\n",checksum); UART.printf("%s",key); } void send_ack_CMD(uint8_t _adr, uint8_t x) { sprintf(key,"$PEOTX,%u,%u,%c*", _adr, x, *valid); checksum=get_checksum(key); sprintf(key,"%u\r\n",checksum); UART.printf("%s",key); } void send_CMD(uint8_t _adr) { //digiit1 digit2 digit3 digit4 sprintf(key,"$PEOTC,%u,%u,%u,%u,%u,%c*", _adr, rpm_data[0],rpm_data[1],rpm_data[2],rpm_data[3], *valid); checksum = get_checksum(key); sprintf(key,"%u\r\n",checksum); UART.printf("%s",key); } void send_DIR(uint8_t _adr) //addr 1-8 of leds,error=1 or 0(no error) { sprintf(key,"$PEOTD,%u,%u,%c*",_adr,dir,*valid); // dir is 1 for ahead, 2 for astern checksum=get_checksum(key); sprintf(key,"%u\r\n",checksum); UART.printf("%s",key); } void send_HB(uint8_t _adr) //master will send the haertbeat to all presentees at periodic intervals { sprintf(key,"$PEOTH,%u,%c*", _adr, *valid); checksum=get_checksum(key); sprintf(key,"%u\r\n",checksum); UART.printf("%s",key); } void send_BROADCAST() //addr 1-8 of leds,error=1 or 0(no error) { sprintf(key,"$PEOTB,%u,%u,%c*",err_ID,err_Status,*valid); checksum=get_checksum(key); sprintf(key,"%u\r\n",checksum); UART.printf("%s",key); BROADCAST_send=false; } void send_ACH() { sprintf(key,"$PEOTS,%u,%u,%c*", ach_M, ach_S, *valid); checksum=get_checksum(key); sprintf(key,"%u\r\n",checksum); UART.printf("%s",key); } /************************************************************************************** EOT Serial Data In FUNCTIONS **************************************************************************************/ void rcvd_HB() //master check HB along with req response for all presentees { if(rcvd_ADDR == addr_ID) //self address received { if(addr_ID > pot_Slave_ER) { //if no req resp_HB(0); //normal HB response } else { if(req) { resp_HB(1); //req and ack status data in req=1 and ack=2 if true req = 0; } else if(ack) { resp_HB(2); //req and ack status data in req=1 and ack=2 if true ack = 0; } else resp_HB(0); //req and ack status data in req=1 and ack=2 if true } } else __nop(); } void resp_rcvd_HB() //master and active/passive slaves check HB response along with req/ack commands { if(addr_ID == eot_Master) //only master will be able to monitor status of all eots connected { if(send_ADDR == rcvd_ADDR) HB_ack_rcvd = true; else HB_ack_rcvd = false; } else __nop(); } void rcvd_rpm_CMD() //all devices check for received command { for(uint8_t i = 0; i >= 3 ; i--) { max7219.write_digit(1,i+1,rpm_data[i]); //disp1 //data 0 means left most digit will be blank bcoz no decode mode is used } buzzer = _ON; //buzzer on if(ach_S == addr_ID) { int_B.rise(&read_KEY_B); //portc is always enbaled in all cases and PORTA is enabled only for active master } else { __nop(); } if(addr_ID == rcvd_ADDR) //particular device responds cmd_ack { resp_HB(0); //CMD_ack or response with PEOTA syntax send by devices as per their addresss } else { __nop(); } disp_FLASH.attach(&DISP_FLASH,0.50); //disp1 flash timer started in all connected devices except master CMD_Ticker.attach(&CMD_State_Machine,0.25); //state machine timer started in all connected devices except master } void rcvd_dir_CMD() //all devices check for received command { rcvd_DIR = true; LED_DIR[last_dir-1].OFF(); LED_DIR[dir-1].FLASHH(); //led flash started buzzer = _ON; //buzzer on last_dir = dir; //ACK_pending = true; //HB-cmd ack pending with "A" DIR_Ticker.attach(&DIR_State_Machine,0.25); //state machine timer started in all connected devices if(ach_S == addr_ID) { int_B.rise(&read_KEY_B); //enable keys bcoz ahead/astern keys co-grouped to PORTB of mcp23s17(1) } } void rcvd_BROADCAST() { if(err_Status==1) //err non zero { LED_ACH[err_ID].FLASHH(); } else { LED_ACH[err_ID].OFF(); } } void read_SERIAL() { UART.scanf("%s",key); strtok(key,","); if(strcmp(key,"$PEOTH") == 0) //* present submaster,Slaves or lsitners receive HB *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); //address of connected device rcvd_HB(); //set flag when Heartbeat received } else if(strcmp(key,"$PEOTA") == 0) //* Master,submaster and Slaves receive heartbeat resp *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); if(RPM_cmd_ack && addr_ID == ach_S) //ENTER_ACK key here is detected from active slave { send_ack_CMD(addr_ID,RPM); //PEOTX,addr_ID,R(for RPM) CMD_ack_send = true; RPM_cmd_ack = false; //in active slave } else if(DIR_cmd_ack && addr_ID == ach_S) { send_ack_CMD(addr_ID,DIR); //PEOTX,addr_ID,D(for direction) DIR_cmd_ack = false; DIR_Ticker.detach(); //DIR_state_machine suspended in active slave } else resp_rcvd_HB(); } else if(strcmp(key,"$PEOTB") == 0) //* submaster,Slaves or listener receive broadcast *// { sscanf(strtok (NULL,","), "%u", &err_ID); //cmd extracted sscanf(strtok (NULL,","), "%u", &err_Status); rcvd_BROADCAST(); } else if(strcmp(key,"$PEOTC") == 0) //* submaster,Slaves or listener receive CMD *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); //address extracted sscanf(strtok (NULL,","), "%u", &rpm_data[0]); //rpm data digit 1 and soon sscanf(strtok (NULL,","), "%u", &rpm_data[1]); sscanf(strtok (NULL,","), "%u", &rpm_data[2]); sscanf(strtok (NULL,","), "%u", &rpm_data[3]); CMD_rcvd = true; rcvd_rpm_CMD(); } else if(strcmp(key,"$PEOTD") == 0) //* present submaster,Slaves or lsitners receive HB *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); //address of connected device sscanf(strtok (NULL,","), "%u", &dir); // 1 for ahead and 2 for astern rcvd_dir_CMD(); //set flag when Heartbeat received } else if(strcmp(key,"$PEOTX") == 0) //* Master,submaster,Slave or listners receive CMD acknowledge *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); //addr extracted sscanf(strtok (NULL,","), "%u", &ack_rpm_dir); //ack extracted if(ack_rpm_dir == RPM) RPM_cmd_ack = true; else if (ack_rpm_dir == DIR) DIR_cmd_ack = true; else __nop(); } else if(strcmp(key,"$PEOTS") == 0) //*active channel status recieved *// { int _M = ach_M; int _S = ach_S; sscanf(strtok (NULL,","), "%u", &ach_M); //cmd extracted sscanf(strtok (NULL,","), "%u", &ach_S); if(_M != ach_M) { LED_ACH[ach_M-1].ON(); //TODO in case of master submaster PORTA,B needs to be enabled/disabled LED_ACH[_M-1].OFF(); // along with HB_ticker attach/detach } else if(_S != ach_S) { LED_ACH[ach_S-1].ON(); LED_ACH[_S-1].OFF(); } else __nop(); } else if(strcmp(key,"$PEOTR") == 0) //* control transfer request arrived*// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); sscanf(strtok (NULL,","), "%u", &req); //e.g $R req or $K ack if(addr_ID < eot_Slave_ER) { REQ_rcvd = true; req_ADDR = rcvd_ADDR; R_A_Ticker.attach(&R_A_Statemachine,0.5); if((rcvd_ADDR == eot_Master || rcvd_ADDR == eot_Submaster) && (addr_ID == eot_Master || addr_ID == eot_Submaster)) { LED_CTRL[ACK_-1].FLASHH(); //ack led blink } else if((rcvd_ADDR == eot_Slave_ER || rcvd_ADDR == eot_Slave_MCR) && (addr_ID == eot_Slave_ER || addr_ID == eot_Slave_MCR)) { LED_CTRL[ACK_-1].FLASHH(); //ack led blink } else __nop(); } else __nop(); } else if(strcmp(key,"$PEOTK") == 0) //* Master,submaster,Slave or listners receive CMD acknowledge *// { sscanf(strtok (NULL,","), "%u", &rcvd_ADDR); sscanf(strtok (NULL,","), "%u", &ack); //e.g $R req or $K ack ACK_rcvd = true; if(addr_ID < eot_Slave_ER) { ack_ADDR = rcvd_ADDR; ACK_rcvd = true; ACH_SW_over = true; if((rcvd_ADDR == eot_Master || rcvd_ADDR == eot_Submaster) && (addr_ID == eot_Master || addr_ID == eot_Submaster)) LED_CTRL[ACK_-1].OFF(); else if((rcvd_ADDR == eot_Slave_ER || rcvd_ADDR == eot_Slave_MCR) && (addr_ID == eot_Slave_ER || addr_ID == eot_Slave_MCR)) LED_CTRL[ACK_-1].OFF(); else __nop(); } else __nop(); } } /************************************************************************************** EOT Handler FUNCTIONS **************************************************************************************/ void HB_handler() //function run periodically within active master only { if(addr_ID == ach_M) //function run only in active master { if(ach_M == eot_Master) { device_addr++; if(device_addr >= no_eot_connected) device_addr = 0; } else __nop(); /*else if(ach_M == eot_Submaster) { if(device_addr==2) { device_addr=3; } else { device_addr++; if(device_addr>NO_MAX_EOT) device_addr=1; } } */ send_ADDR = EOT[device_addr].slave_ID; if(RPM_cmd) { send_CMD(send_ADDR); //cmd to be send with current running address and rpm data value HB_Ticker.attach(&HB_State_Machine,0.010); //HB_state_machine runing for CMD_ack with PEOTA sentence in master only CMD_Ticker.attach(&CMD_State_Machine,0.25); //CMD_state_machine ticker started in master only } else if(DIR_cmd) { send_CMD(send_ADDR); HB_Ticker.attach(&HB_State_Machine,0.010); DIR_Ticker.attach(&DIR_State_Machine,0.25); } else if(BROADCAST_send) { send_BROADCAST(); //broadcast needed err_ID nd err_Status BROADCAST_send = false; } else if(switch_CH) //active channel switch over happened { send_ACH(); //active channel changeover switch_CH = false; } else { cmd=0x0; send_HB(send_ADDR); //hb is to be going on HB_ticker.attach(&HB_State_Machine,0.010); //HB_state_machine timer started } } else __nop(); } /************************************************************************************** EOT config FUNCTIONS **************************************************************************************/ void read_POT_ADDR() //function give present eots and no. of connected eots { pot_Addr = read_KEY_SPI(ch_D); if(pot_Addr==0xff) //if 0xff it means no addressing done pot_Error=true; else if(pot_Addr!=0xff) { for( uint8_t i=0;i<=7;i++) { if(((1 << i) & pot_Addr)== 0) // to check which bit of eot_Addr register is '0' { if(i==0) // bit 0 means master present and soon { addr_ID = pot_Master; ach_M = pot_Master; for(i = 1 ; i <= 7 ; i++) { if((((uint8_t)1<<i) & pot_Addr) == 0) { switch(i) { case 1: POT[no_pot_connected].slave_ID = pot_Submaster; POT[no_pot_connected].err_cnt=0; no_eot_connected++; break; case 2: ach_S = pot_Slave_MCR; POT[no_pot_connected].slave_ID = pot_Slave_MCR; POT[no_pot_connected].err_cnt=0; no_pot_connected++; break; case 3: if(ach_S == pot_Slave_MCR) //if MCR ispresent __nop(); else { //if MCR is not present ach_S = pot_Slave_ER; } POT[no_pot_connected].slave_ID = pot_Slave_ER; POT[no_pot_connected].err_cnt = 0; no_pot_connected++; break; case 4: POT[no_pot_connected].slave_ID = pot_Listner_WP; POT[no_pot_connected].err_cnt = 0; no_pot_connected++; break; case 5: POT[no_pot_connected].slave_ID = pot_Listner_WS; POT[no_pot_connected].err_cnt=0; no_pot_connected++; break; case 6: POT[no_pot_connected].slave_ID = pot_Listner_OPS; POT[no_pot_connected].err_cnt=0; no_pot_connected++; break; case 7: POT[no_pot_connected].slave_ID = pot_Listner_ASP; POT[no_pot_connected].err_cnt=0; no_pot_connected++; break; } } } } else { switch(i) { case 1: { addr_ID = pot_Submaster; break; } case 2: { addr_ID = pot_Slave_MCR; break; } case 3: { addr_ID = pot_Slave_ER; break; } case 4: { addr_ID = pot_Listner_WP; break; } case 5: { addr_ID = pot_Listner_WS; break; } case 6: { addr_ID = pot_Listner_OPS; break; } case 7: { addr_ID = pot_Listner_ASP; break; } default: pot_Error = true; } } } } } } void Uart_Init() { //buffer initialisation Serial UART(SERIAL_TX, SERIAL_RX); UART.baud(9600); UART.format(8,SerialBase::None,1); //UART.attach( &read_SERIAL, UART.RxIrq); //receive interrupt enabled } void Spi3_Init() //for mcp23s17 { _SPI3.format(8,0); //8bit,mode 0 _SPI3.frequency(1000000); //1mhz } void mcp23s17_init() { //device1 configuration mcp23s17_1.reset(); //reset on power-up mcp23s17_1.iodira(0xff); //set 8-bits PORTA as inputs mcp23s17_1.iodirb(0xff); //set 8-bits PORTb as inputs mcp23s17_1.ipola(0x00); mcp23s17_1.ipolb(0x00); mcp23s17_1.gpintena(0xff); //interrupt enabled on PORTA mcp23s17_1.gpintenb(0xff); //interrupt enabled on PORTB mcp23s17_1.defvala(0xff); mcp23s17_1.defvalb(0xff); mcp23s17_1.intcona(0x2a); //bank0,mirror disabled, SEQOP disabled, slew rate disabled,HAEN enabled,open drain enabled,interrupt active high,not allowed mcp23s17_1.intconb(0x2a); mcp23s17_1.gppua(0xff); mcp23s17_1.gppub(0xff); //device2 configuration mcp23s17_2.reset(); //reset on power-up mcp23s17_2.iodira(0xff); //set 8-bits PORTA as inputs mcp23s17_2.iodirb(0xff); //set 8-bits PORTb as inputs mcp23s17_2.ipola(0x00); mcp23s17_2.ipolb(0x00); mcp23s17_2.gpintena(0xff); //interrupt enabled on PORTA mcp23s17_2.gpintenb(0x00); //interrupts disabled for address PORTB mcp23s17_2.defvala(0xff); mcp23s17_2.defvalb(0xff); mcp23s17_2.intcona(0x2a); //bank0,mirror disabled, SEQOP disabled, slew rate disabled,HAEN enabled,open drain enabled,interrupt active high,not allowed mcp23s17_2.intconb(0x2a); mcp23s17_2.gppua(0xff); mcp23s17_2.gppub(0xff); } void Spi2_Init() // for max7219 { _SPI2.format(16,0); //16bit,mode 0 _SPI2.frequency(1000000); //1mhz } void max7219_init() { max7219.set_num_devices(2); //total 02 no. of devices which will drive 03 displays max7219_configuration_t DEVICE1, DEVICE2; DEVICE1.device_number = 1; DEVICE1.decode_mode = 0xff; //bcd decode mode DEVICE1.intensity = 8; //Max7219::MAX7219_INTENSITY_8, //intensity moderate DEVICE1.scan_limit = 8; // Max7219::MAX7219_SCAN_8, 8-digit scan driving two displays ds1 nd ds2 DEVICE2.device_number = 2; DEVICE2.decode_mode = 0xff; //bcd decode mode DEVICE2.intensity = 8; //Max7219::MAX7219_INTENSITY_8, //intensity moderate DEVICE2.scan_limit = 4; //Max7219::MAX7219_SCAN_4, 4-digit scan driving one display max7219.init_device(DEVICE1); //DEVICE 1 configured as per above settings max7219.enable_device(1); max7219.init_device(DEVICE2); //DEVICE 2 configured as per above settings max7219.enable_device(2); max7219.set_display_test(); wait(1); max7219.clear_display_test(); for(uint8_t i=0; i<=07;i++) { max7219.write_digit(1, i+1, 0x01); //device 1 cmd display, digit 0-7 ,data 0x01, ----, ---- on both displays } for(uint8_t i=0; i<=03;i++) { max7219.write_digit(1, i+1, 0x01); //device 2 RTC display, digit 0-3 ,data 0x01, ---- on display } } void Discrete_Init() { buzzer = _ON; hooter = _ON; //on wait(1); // one second delay buzzer = _OFF; hooter = _OFF; //off } void Led_Init() { /* setting brightness as 50% duty cycle*/ for(uint8_t i=0;i<=1;i++) //direction led initialisation 02 no.s { LED_DIR[i].set_Brightness(0.50); //setting duty cycle 50% } for(uint8_t i=0;i<=1;i++) //ctrl led intialisation 02 no.s { LED_CTRL[i].set_Brightness(0.50); } for(uint8_t i=0; i<=7;i++) //ach led initialisation 08 no.s { LED_ACH[i].set_Brightness(0.50); } /* turning all leds ON*/ for(uint8_t i=0;i<=1;i++) { LED_DIR[i].ON(); } for(uint8_t i=0;i<=1;i++) { LED_CTRL[i].ON(); } for(uint8_t i=0; i<=7;i++) { LED_ACH[i].ON(); } wait(1); //wait for a 1 sec /* turning all leds OFF*/ for(uint8_t i=0;i<=1;i++) { LED_DIR[i].OFF(); } for(uint8_t i=0;i<=1;i++) { LED_CTRL[i].OFF(); } for(uint8_t i=0; i<=7;i++) { LED_ACH[i].OFF(); } } void parameters_init() { /*intialization of all bool data types indicating different error flags */ pot_Error = false; spi_ERR = false; pot_MCR_err = false; pot_ER_err = false; test = false; /*intialization of all bool data types indicating flag on key press interruption */ key_NUM = false; key_CTRL = false; key_DISP = false; key_SET = false; RPM_cmd = false; //if true RPM command is raised DIR_cmd = false; //if true DIR command is raised /*intialization of all bool data types indicating flags while serial receive */ CMD_ack_rcvd = false; HB_ack_rcvd = false; CMD_rcvd = false; BROADCAST_rcvd = false; HB_rcvd = false; REQ_rcvd = false; ACK_rcvd = false; rcvd_DIR = false; /*intialization of all bool data types indicating flags while serial transmit */ BROADCAST_send = false; CMD_send = false; REQ_send = false; ACK_send = false; HB_send = false; CMD_ack_send = false; /*intialization of all bool data types indicating active channel changeover*/ test=false; ACH_SW_over = switch_CH = false; _disp_FLASH = false; /*intialization of all int data types*/ addr = req = ack = cmd = dir = last_cmd = ach_S = ach_M = brightness = 0; pot_Addr = addr_ID = send_ADDR = rcvd_ADDR = req_ADDR = ack_ADDR = 0; test_cnt = err_ID = err_Status = 0; spi_error = no_pot_connected = checksum =0; HB_timer =0; device_addr = -1; digit_disp1 = 5; //bcoz 5-1 = 4th digit is entered first digit_disp2 = 0; digit_disp3 = 0; POT = new _POT[NO_MAX_POT]; } void POT_INIT() { parameters_init(); Led_Init(); Discrete_Init(); //INT_Init(); Spi2_Init(); max7219_init(); Spi3_Init(); mcp23s17_init(); Uart_Init(); read_EOT_ADDR(); //config_EOT(); if(addr_ID == pot_Master) //if addres of master eot found, by default master { int_A.rise(&read_KEY_A); //all key functions enabled for PORTA,B,C int_B.rise(&read_KEY_B); int_C.rise(&read_KEY_C); HB_timer=(float)(1/no_pot_connected); // NVIC_SetPriority(UART2_IRQn,0); pot_HB.attach(&HB_handler,HB_timer); //HB timer started UART.attach( &read_SERIAL, UART.RxIrq); //receive interrupt enabled } else { if(pot_Submaster <= addr_ID <= pot_Listner_ASP) { int_A.rise(NULL); //all key functions/interrupt disabled for PORTA & B int_B.rise(NULL); int_C.rise(&read_KEY_C); //only PORTC needs to be intialized in other all cases req,inc,dec,tst UART.attach( &read_SERIAL, UART.RxIrq); //receive interrupt enabled } else { int_A.rise(NULL); int_B.rise(NULL); int_C.rise(NULL); pot_Error = true; //return(-1); } } } int main() { POT_INIT(); while(1) { } }