#platform "uVGA-II_GFX2" #inherit "4DGL_16bitColours.fnc" #constant TRUE 1 #constant FALSE 0 #CONST //Define the RX state machine states S_IDLE := 0x00, //Waiting for new message to start. Don't exit this state until we get a 0x02 S_GETID, //Get the message ID (can be any value) S_GETMSG //Get the encapsulated message, 6 bytes or less #END #CONST //Define misc Items (buffer sizes, etc) RX_BUF_SIZE := 128, //Size of the receive buffer for serial port TX_BUF_SIZE := 20, //Size of the transmit buffer for serial port RX_MSG_MAX_SIZE := 5 // 1/2 the Max length if an incoming message, not including "wrapper" of $ or CR #END //************************************************************************************************************************* // ---------------------------------------------- // Define any Global Variables here // ---------------------------------------------- var tx_buf[TX_BUF_SIZE]; //This is the TX buffer. It will hold 2x TX_BUF_SIZE bytes var rx_buf[RX_BUF_SIZE]; //This is the RX buffer. It will hold 2x RX_BUF_SIZE bytes //************************************************************************************************************************* func InitComPort() while(serin1() >= 0); //Empty out any pending bytes at port repeat com_SetBaud(COM1,960); //Set baud rate to 9600 com1_Init(rx_buf,RX_BUF_SIZE,0); //Set the comms RX buffer nbPause(5); //Non-blocking pause for 5 ms to see if any com errors occur until (!com1_Error()); //Keep retrying until no more errors com1_TXbuffer(tx_buf,sizeof(tx_buf)*2); HandleRxBytes.rx_state := S_IDLE; //Since we reset the com buffer, we should discard any messages we were building endfunc //************************************************************************************************************************* func main() var bytesatport; // var mainloopcounter; InitComPort(); //Init the com port. gfx_BGcolour(BLUE); gfx_Cls(); //print("Com test, Message Parser\n"); repeat //Do other stuff as desired..............Then...... bytesatport:=com1_Count(); //Get the number of bytes sitting in the RX buffer if(bytesatport>0) //Do we have any rec'd bytes to handle? //Handle the bytes we HAD in the buffer. We may actually have more now, or get more while in the //HandleRxBytes routine, but we want to make sure we get back here to the main loop HandleRxBytes(bytesatport); //Process the number of bytes else if(com1_Error()) //No bytes are in the buffer, make sure no com errors have occured InitComPort; //If so, then redo the com init and reset the RX message state endif endif forever endfunc //************************************************************************************************************************* func nbPause(var msec) sys_SetTimer(TIMER0, msec); // pause for 50 ms, non blocking while(peekW(TMR0)); endfunc //************************************************************************************************************************* func HandleRxBytes(var bytesatport) // This function will process the incoming serial data into valid messages var private rx_state := S_IDLE; //Holds the current message state. Retained between calls (because of private) var private msgID; //Holds the message ID. Retained between calls var private msg_buf[RX_MSG_MAX_SIZE]; //Holds the Message ASCII data. Retained between calls var private msgIndex; //Holds message body index. Retained between calls var private msgPtr; //String pointer Retained between calls // var private checksum; //Holds the current message Checksum. Inited to 0 only ONCE var comByte; //Next byte to be processed from RX buffer var validMsg := FALSE; //Flag that indicates we have rec'd a valid message while (bytesatport-- > 0) //We have more bytes to process comByte := serin1(); //Get the next buffered byte. Bufferd comms never return com errors, only -1 if buffer empty if (comByte < 0) break; //This should not happen, but just in case.... if (comByte == '$') rx_state:=S_IDLE; //At any time, $ forces reception of a new message. Aborts old if in process.... gosub(rx_state),(stateIDLE,stateGETID, stateGETMSG); //Go to current state and handle byte if(validMsg == TRUE) //We have just processed a complete message validMsg := FALSE; Process_Msg(msgID,&msg_buf[0]); //Process the message break; //Since we just processed a message, go back to MAIN loop and endif //defer processing the remaining rx bytes until next time wend //This help to smooth out the message processing goto ExitHandleRxBytes; stateIDLE: if(comByte=='$') //Did we get a Start of Message? //gfx_Cls(); rx_state := S_GETID; //Yes, so next state we will look for is the message ID msgIndex := 0; //Reset the message body index msgPtr := str_Ptr(msg_buf); //Create string pointer to the message buffer mem_Set(msg_buf,0,sizeof(msg_buf)*2); //Zero out the buffer //print("<$> "); // checksum := 0; //Clear the checksum else //print("(Ignored: ",[CHR]comByte,")"); endif //Otherwise, just ignore it endsub; stateGETID: msgID := comByte; //Save the byte as the message ID rx_state:= S_GETMSG; //Next, get the AscII message //print(" "); endsub; stateGETMSG: //Start building up the message if (comByte==13) //We just rec'd a CR //print(" "); if (msgIndex>0) //If the message body has some data in it (before the CR) validMsg := TRUE; //then call it a valid message //print(" (Msg Valid)"); endif rx_state := S_IDLE; //In any case, a CR will force us to the IDLE state else if(msgIndex < 6) //Is the current message length 6 or less? msgIndex is BASE 0.... if(lookup8(comByte, "-0123456789")) //Is byte one of these chars? str_PutByte(msgPtr++,comByte); //Yes, so store the byte in the buffer msgIndex++; //and increment the byte counter //print("<",[CHR]comByte,"> "); else //print(" "); rx_state := S_IDLE; //Not a valid char, dump message endif else //print(" (Buffer 2 Long)"); rx_state :=S_IDLE; //Ascii buffer too long, dump message endif endif endsub; ExitHandleRxBytes: endfunc //************************************************************************************************************************* func Process_Msg(var ID, var *msgBuf) var msgPtr; var msgvalue; var index; var private A; var private B; var private C; var private D; var private E; var private F; var private G; var private H; var private I; var private J; var private K; var private L; var private M; var private N; var private O; var private P; var private family; txt_MoveCursor(10,1); msgPtr := str_Ptr(msgBuf); //String pointer to the message buffer str_GetW(&msgPtr,&msgvalue); //Convert Ascii string to a value, and store it in msgvalue index:= lookup8(ID,"ABCDEFGHIJKLMNOP"); //Message ids gosub(index),(MSGINVALID,MSGA,MSGB,MSGC,MSGD,MSGE,MSGF,MSGG,MSGH,MSGI,MSGJ,MSGK,MSGL,MSGM,MSGN,MSGO,MSGP); // print("A = ",A," \n"); // print("B = ",B," \n"); // print("c = ",C," \n"); txt_Set(TEXT_COLOUR, WHITE); txt_BGcolour(BLUE); txt_MoveCursor(3,32); if (A == 1) print("Webster Pump Sort", " "); if (A == 2) print("J/H Pump Sort", " "); if (A == 3) print("Mini Pump Sort", " "); //if (A == 4) print("Webster Pump Match", " "); //if (A == 5) print("J/H Pump Match", " "); //if (A == 6) print("Mini Pump Match", " "); //txt_MoveCursor(29,5); // print("1. Push and hold the red button on the micrometer to change menu choices."); //txt_MoveCursor(31,5); // print("2. Push the floor pedal or micrometer base red button to set a sample."); txt_MoveCursor(5,32); if(A==1) if (B == 1) print("Below W2M", " "); if (B == 2) print("Webster 2M", " "); if (B == 3) print("W2M <-> WM34", " "); if (B == 4) print("Webster M34", " "); if (B == 5) print("WM34 <-> WM17", " "); if (B == 6) print("Webster M17", " "); if (B == 7) print("Over WM17", " "); endif if (A==2) if (B == 1) print("Below JH180", " "); if (B == 2) print("JH180", " "); if (B == 3) print("JH180 <-> JH280", " "); if (B == 4) print("JH280", " "); if (B == 5) print("JH280 <-> JH335", " "); if (B == 6) print("JH335/340", " "); if (B == 7) print("JH335 <-> JH437", " "); if (B == 8) print("JH437", " "); if (B == 9) print("JH437 <-> JH484", " "); if (B == 10) print("JH484", " "); if (B == 11) print("JH484 <-> JH562", " "); if (B == 12) print("JH562", " "); if (B == 13) print("JH562 <-> JH750", " "); if (B == 14) print("JH750", " "); if (B == 15) print("Over JH750", " "); endif if (A==3) if (B == 1) print("Below MP200", " "); if (B == 2) print("MP200", " "); if (B == 3) print("MP200 <-> MP230", " "); if (B == 4) print("MP230", " "); if (B == 5) print("MP230 <-> MP280", " "); if (B == 6) print("MP280", " "); if (B == 7) print("MP280 <-> MP340", " "); if (B == 8) print("MP340", " "); if (B == 9) print("MP340 <-> MP390", " "); if (B == 10) print("MP390", " "); if (B == 11) print("Over MP390", " "); endif // Static screen elements txt_MoveCursor(7,25); print("Static"); txt_MoveCursor(7,45); print("Moveable"); txt_MoveCursor(20,25); print("Static"); txt_MoveCursor(20,45); print("Moveable"); // Dynamic screen elements txt_MoveCursor(9,27); print(E, " "); txt_MoveCursor(9,47); print(F, " "); txt_MoveCursor(15,27); if (G == 1) print("S1"); if (G == 0) print(" "); txt_MoveCursor(15,37); if (H == 1) print("S2"); if (H == 0) print(" "); txt_MoveCursor(15,47); if (I == 1) print("S3"); if (I == 0) print(" "); //txt_Set(TEXT_COLOUR, GREEN); txt_MoveCursor(22,27); if (I == 0) print(" "); txt_MoveCursor(22,27); if (I != 0) print(L, " "); txt_MoveCursor(22,47); if (I == 0) print(" "); txt_MoveCursor(22,47); if (I != 0) print(M, " "); txt_Set(TEXT_COLOUR, RED); txt_MoveCursor(24,23); if (N == 1) print("Reject Bin"); if (N == 0) print(" "); txt_MoveCursor(24,45); if (N == 1) if (A==1) if (B == 2) print("Webster 2M", " "); if (B == 4) print("Webster M34", " "); if (B == 6) print("Webster M17", " "); endif if (A==2) if (B == 2) print("JH180", " "); if (B == 4) print("JH280", " "); if (B == 6) print("JH335/340", " "); if (B == 8) print("JH437", " "); if (B == 10) print("JH484", " "); if (B == 12) print("JH562", " "); if (B == 14) print("JH750", " "); endif if (A==3) if (B == 2) print("MP200", " "); if (B == 4) print("MP230", " "); if (B == 6) print("MP280", " "); if (B == 8) print("MP340", " "); if (B == 10) print("MP390", " "); endif endif if (O == 0) print(" "); goto ExitProcess_Msg; MSGINVALID: //Here because did not match A,B,or C //print("INVALID Message! \n"); endsub; MSGA: //Do something usefull A := msgvalue; endsub; MSGB: B := msgvalue; endsub; MSGC: C := msgvalue; endsub; MSGD: D := msgvalue; endsub; MSGE: E := msgvalue; endsub; MSGF: F := msgvalue; endsub; MSGG: G := msgvalue; endsub; MSGH: H := msgvalue; endsub; MSGI: I := msgvalue; endsub; MSGJ: J := msgvalue; endsub; MSGK: K := msgvalue; endsub; MSGL: L := msgvalue; endsub; MSGM: M := msgvalue; endsub; MSGN: N := msgvalue; endsub; MSGO: O := msgvalue; endsub; MSGP: P := msgvalue; endsub; ExitProcess_Msg: endfunc