![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
direction commands updated to Up down RPM value
Dependencies: MAX7219pot MCP23S17 mbed
Fork of POT_V_1_0 by
Diff: main.cpp
- Revision:
- 0:ba33a62aea4e
- Child:
- 1:e116808d8b00
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Thu Sep 28 05:10:42 2017 +0000 @@ -0,0 +1,1664 @@ +#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) + { + } +}