Module Gsm // ////////////////////////////////////////////////////////////////////////// // // 2003-11-04 // // Original code taken from CocaCola remote ervice pilot. // Original code was for Siemens xx35, adopted for Sony/Ericsson GM47/48 // // ////////////////////////////////////////////////////////////////////////// Public // ////////////////////////////////////////////////////////////////////////// // Define and export GsmState values Enum gsOff // 0 GSM is off gsTurningOn // 1 turning on - transient state gsOn // 2 GSM is on gsTurningOff // 3 turning off - transient state gsTurningOff2 // 4 turning off - transient state gsWaitForOK // 5 Wait for GSM to send OK, a called state gsPinQrySent // 6 PIN query was sent gsPinCodeSent // 7 PIN code was sent gsRegSent // 8 Network registration sent gsPreRegistered // 9 Waiting for OK on registration gsReqQrySent // 10 Query for registration status sent gsRegistered // 11 GSM is registered into the network gsCsqSent // 12 Quality of service request sent gsCsqSeen // 13 Waiting for Ok after Csq reception gsDialing // 14 Dialing a phone number gsATASent // 15 ATA sent to pick up the phone gsVoiceCall // 16 OK received after ATA, voice call gsBreakLink1 // 17 Breaking data link phase 1 - before +++ gsBreakLink2 // 18 Breaking data link phase 2 - after +++ gsBreakLink3 // 19 Waioting for OK after +++ process gsATHSent // 20 Hanging up gsReInit // 21 Delay before reset after error // The following states must be the last states defined (highest ordinal value) // And they must be defined in this order gsConnected // 22 A connection to a remote modem exists EndEnum // Vectors to be resolved by application using this module Defer GsmConnectedHandler ( bData -- ) // Called in connected mode to let app handle bData Defer GsmCsqHandler ( wRamAdr bLen -- ) // Called when quality of service report is available Defer GsmRegStatusHandler ( wRamAdr bLen -- bStat ) // Called when registration status report is available Defer GsmClearError ( -- ) // Called when app error should be cleared Defer GsmStateChangeHandler ( bData -- ) // Called when this modules main state changes Defer GsmGetUserInitString ( -- wRom ) // Called to send user initialization data to modem Defer GsmGetPinString ( -- wRom ) // Called to send SIM PIN code to GSM Defer GsmTerminated ( -- ) // Called to signal GSM shutdown completion Defer GsmShutDown ( -- ) // Request for total device shutdown Defer GsmErrorOccurred ( -- ) // Called when a fatal GSM error occurred // ////////////////////////////////////////////////////////////////////////// Private Uses Hardware Fatal Interrupt EndUses // /////////////////////////////////////////////////////////////////////////// // Coupling to hardware Alias iuRxHasData GsmHasData ( -- bCount ) // UART Rx buffer fill count Alias iuRxRead GsmRead ( -- bData ) // UART get Rx byte Alias iuTxHasRoom GsmHasRoom ( -- bCount ) // UART Tx buffer free count Alias iuTxWrite GsmTransmit ( bData -- ) // Called when this module wants to transmit // ////////////////////////////////////////////////////////////////////////// // Constants // ////////////////////////////////////////////////////////////////////////// 20 Constant GsmReplyBufSize $0a Constant chrLF $0d Constant chrCR '" Constant chrQuote // Transparency break state values Enum gstbNone // not break detecting gstb1 // first break detect time out seen, '*' is valid break starter now gstb2 // 1st '*' seen gstb3 // 2nd '*' seen gstbWait // 3rd '*' seen and awaiting final timeout EndEnum // ////////////////////////////////////////////////////////////////////////// // Variables // ////////////////////////////////////////////////////////////////////////// Variable GsmState // Main process state Variable GsmReturnState // State to return to after a state call (one level stack) GsmReplyBufSize 1 + Array GsmReplyBuffer // This is a Pascal string - 1st byte is length Variable GsmReplyBufFree // Nr of free bytes in reply buffer Variable GsmRxState // Receive state Variable GsmTries // Try counter for certain states Variable GsmCsqTries // Try counter for CSQ requests // ////////////////////////////////////////////////////////////////////////// // Device reply state // ////////////////////////////////////////////////////////////////////////// Enum grxNone // Nothing seen grxCR // CR seen grxData // CRLF seen, colecting string data, no closing CR seen yet grxDataCR // CR after data seen grxCompleted // CRLF after data seen - reception complete EndEnum // ////////////////////////////////////////////////////////////////////////// : @GsmReplyBuffer ( -- wAddress ) GsmReplyBuffer ; // ////////////////////////////////////////////////////////////////////////// : @GsmState ( -- wAddress ) GsmState ; // ////////////////////////////////////////////////////////////////////////// : @GsmTries ( -- wAddress ) GsmTries ; // ////////////////////////////////////////////////////////////////////////// : @GsmCsqTries ( -- wAddress ) GsmCsqTries ; // ////////////////////////////////////////////////////////////////////////// // Variable operators // ////////////////////////////////////////////////////////////////////////// : GsmState@ ( -- bState ) @GsmState @ ; // ////////////////////////////////////////////////////////////////////////// : GsmState! ( -- bState ) Dup @GsmState ! // Set the new state GsmStateChangeHandler // Call into App to let it know about the new state ; // ////////////////////////////////////////////////////////////////////////// : GsmReturnState@ ( -- bState ) GsmReturnState @ ; // ////////////////////////////////////////////////////////////////////////// : GsmReturnState! ( -- bState ) GsmReturnState ! ; // ////////////////////////////////////////////////////////////////////////// : GsmReplySize! ( bData -- ) @GsmReplyBuffer ! ; // ////////////////////////////////////////////////////////////////////////// : GsmReplySize@ ( bData -- ) @GsmReplyBuffer @ ; // ////////////////////////////////////////////////////////////////////////// : GsmReplyBufFree! ( bData -- ) GsmReplyBufFree ! ; // ////////////////////////////////////////////////////////////////////////// : GsmReplyBufFree@ ( bData -- ) GsmReplyBufFree @ ; // ////////////////////////////////////////////////////////////////////////// : GsmReplyBufferClr ( -- ) @GsmReplyBuffer 0! // Set length to 0 GsmReplyBufSize GsmReplyBufFree! // Set free to maximum ; // ////////////////////////////////////////////////////////////////////////// : GsmReplyBuffer! ( bData -- ) GsmReplyBufFree@ 0> // Check for room in reply buffer If // Room in buffer : @GsmReplyBuffer 1+! // One more filled @GsmReplyBuffer // Get base address GsmReplySize@ // Get offset a+! // Add base and offset, then store bData GsmReplyBufFree 1-! // One less free Else // No room in buffer : Drop // discard bData EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmRxState@ ( -- bData ) GsmRxState @ ; // ////////////////////////////////////////////////////////////////////////// : GsmRxState! ( bData -- ) GsmRxState ! ; // ////////////////////////////////////////////////////////////////////////// : GsmRxCompleted? ( -- f ) GsmRxState@ grxCompleted = Dup If grxNone GsmRxState! // Clear Rx machine for next reception EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmTries@ ( -- bData ) @GsmTries @ ; // ////////////////////////////////////////////////////////////////////////// : GsmTries0! ( -- ) @GsmTries 0! ; // ////////////////////////////////////////////////////////////////////////// : GsmTries++ ( -- ) @GsmTries 1+! ; // ////////////////////////////////////////////////////////////////////////// : GsmCheckReply ( wRomAddress -- f ) @GsmReplyBuffer StringBeginsWith ; // ////////////////////////////////////////////////////////////////////////// Variable GsmScanLen // ////////////////////////////////////////////////////////////////////////// : @GsmScanLen ( -- wRamAddress ) GsmScanLen ; // ////////////////////////////////////////////////////////////////////////// : GsmHandleCsqReply ( -- ) @GsmReplyBuffer RamPtr! // Initialize RAM pointer Ram@++ // Get length Dup @GsmScanLen ! // Keep a copy in GsmScanLen 0 Do @GsmScanLen 1-! // Remaining length one less Ram@++ Space = // Scan till space character If Leave // Space found, quit loop EndIf Loop @GsmScanLen @ // Be sure to have a sensible length 0> If RamPtr@ // Address of Csq string in RAM @GsmScanLen @ // Get remaining length GsmCsqHandler // Call into app EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmHandleRegStatusReply ( -- bStatus ) @GsmReplyBuffer RamPtr! // Initialize RAM pointer Ram@++ // Get length Dup @GsmScanLen ! // Keep a copy in GsmScanLen 0 Do @GsmScanLen 1-! // Remaining length one less Ram@++ ', = // Scan till comma character If Leave // Space found, quit loop EndIf Loop @GsmScanLen @ // Be sure to have a sensible length 0> If RamPtr@ // Address of Csq string in RAM @GsmScanLen @ // Get remaining length GsmRegStatusHandler // Call into app, returns status as byte Else 0 EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmSendRomString ( wRomAddress -- ) RomPtr! Rom@++ 0 Do Rom@++ GsmTransmit Loop ; // ////////////////////////////////////////////////////////////////////////// : GsmSendRamString ( wRamAddress -- ) RamPtr! Ram@++ 0 Do Ram@++ GsmTransmit Loop ; // ////////////////////////////////////////////////////////////////////////// : GsmSendCRLF ( -- ) chrCR GsmTransmit chrLF GsmTransmit ; // ////////////////////////////////////////////////////////////////////////// : GsmSendQuote ( -- ) chrQuote GsmTransmit ; // ////////////////////////////////////////////////////////////////////////// : GsmSendRomStringCRLF ( wRomAddress -- ) GsmSendRomString GsmSendCRLF ; // ////////////////////////////////////////////////////////////////////////// : GsmSendRamStringCRLF ( wRamAddress -- ) GsmSendRamString GsmSendCRLF ; // ////////////////////////////////////////////////////////////////////////// // The commands that can be sent // ////////////////////////////////////////////////////////////////////////// : GsmSend+++ ( -- ) // To break a data connection // " +++" GsmSendRomString GsmDtrOn ; // ////////////////////////////////////////////////////////////////////////// : GsmSendATD ( -- ) // To dial a number .// .// Maybe ATDI can be used ?? .// " ATD" GsmSendRomString GsmDtrOff ; // ////////////////////////////////////////////////////////////////////////// : GsmSendATA ( -- ) // To answer an incoming call " ATA" GsmSendRomStringCRLF GsmDtrOff ; // ////////////////////////////////////////////////////////////////////////// : GsmSendATH ( -- ) // To hang up " ATH" GsmSendRomStringCRLF ; // ////////////////////////////////////////////////////////////////////////// : GsmSendInitialization ( -- ) // Send device initialization string " AT&FE0&D1V1X1" // Factory defaults, no echo, use DTR to hang // up, verbose result codes, responses // level 1 GsmSendRomString GsmGetUserInitString // Ask application for additional init stuff ?PtrDup // If NULL don't send it If GsmSendRamString // Not NULL - send it EndIf GSMSendCRLF // GSM needs CRLF ; // ////////////////////////////////////////////////////////////////////////// : GsmSendAT+CPIN? ( -- ) // Send PIN query " AT+CPIN?" GsmSendRomStringCRLF ; // ////////////////////////////////////////////////////////////////////////// : GsmSendAT+CPIN= ( -- ) // Send PIN coe introduction " AT+CPIN=" GsmSendRomString ; // ////////////////////////////////////////////////////////////////////////// : GsmSendAT+CREG ( -- ) " AT+CREG=0" GsmSendRomStringCRLF ; // ////////////////////////////////////////////////////////////////////////// : GsmSendAT+CREG? ( -- ) " AT+CREG?" GsmSendRomStringCRLF ; // ////////////////////////////////////////////////////////////////////////// : GsmSendAT+CSQ ( -- ) " AT+CSQ" GsmSendRomStringCRLF ; // ////////////////////////////////////////////////////////////////////////// // String comparisons // ////////////////////////////////////////////////////////////////////////// : GsmSaidOK? ( -- f ) " OK" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidError? ( -- f ) " ERROR" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidRing? ( -- f ) " RING" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidConnect? ( -- f ) " CONNECT" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidNoCarrier? ( -- f ) " NO CARRIER" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidNoDialTone? ( -- f ) " NO DIALTONE" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidBusy? ( -- f ) " BUSY" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaid+CPIN_Ready? ( -- f ) " +CPIN: READY" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaid+CPIN_SIM_PIN? ( -- f ) " +CPIN: SIM PIN" GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidCREG? ( -- f ) " +CREG: 0," GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// : GsmSaidCsq? ( -- f ) " +CSQ: " GsmCheckReply ; // ////////////////////////////////////////////////////////////////////////// // Called control words // ////////////////////////////////////////////////////////////////////////// : GsmOn ( -- ) GSM_SetOnOff // OnOff signal On gsTurningOn GsmState! // Change state ms500 GsmTimer_Start // Set timeout GsmClearError 90 GsmGuardTimer_Start // Start guard timer for 1:30 minute ; // ////////////////////////////////////////////////////////////////////////// : GsmOff ( -- ) GSM_SetOnOff // OnOff signal on gsTurningOff GsmState! // Change state ms1200 GsmTimer_Start // Set timeout ; // ////////////////////////////////////////////////////////////////////////// : GsmDial ( wRamPtr -- ) // Ram pointer to phone nr to dial GsmState@ gsRegistered = If // Gsm is on : GsmSendATD // send ATD to device GsmSendRamStringCRLF // pass on wRamPtr (the phone number) + CRLF gsDialing GsmState! // change state s40 GsmTimer_Start // start timeout Else // Gsm is off : aDrop // discard wRamPtr EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmError ( -- ) GsmOff // Turn GSM Off gsReInit @GsmState ! // Goto re-initialization state, !! don't show feedback on LCD !! s3 GsmTimer_Start // Wait 3s. before re-initialization, allow for reading error msg. GsmErrorOccurred // Call the deferred error handler ; // ////////////////////////////////////////////////////////////////////////// Alias GsmOff GsmDone ( -- ) // ////////////////////////////////////////////////////////////////////////// : GsmSetConnected ( -- ) gsConnected GsmState! s50 GsmTimer_Start ; // ////////////////////////////////////////////////////////////////////////// : GsmHangup ( -- ) gsBreakLink1 GsmState! ms10 GsmTimer_Start // ms1200 GsmTimer_Start ; // ////////////////////////////////////////////////////////////////////////// // Gsm data processing // ////////////////////////////////////////////////////////////////////////// : GsmAcceptRx ( bData -- ) 90 GsmGuardTimer_Start // Start guard timer for 1:30 minute GsmState@ gsConnected = If // One of the app layer states is active ( bData ) // must still be on stack s30 GsmTimer_Start // Give us 30 extra seconds for each char GsmConnectedHandler Else ( bData ) GsmRxState@ // Local state - no app involvement Case grxNone // Nothing seen Of ( bData ) chrCR = // Initial CR If grxCR GsmRxState! // Change state GsmReplyBufferClr // Clear tracking buffer EndIf EndOf grxCR // CR seen Of ( bData ) Case chrLF Of grxData GsmRxState! // LF -> change state EndOf chrCR Of // CR -> Do nothing EndOf Default Drop grxNone GsmRxState! // No, restart EndCase EndOf grxData // CRLF seen, colecting string data, no closing CR seen yet Of ( bData ) Case // Dispatch on character chrCR Of // Closing CR grxDataCR GsmRxState! EndOf Default GsmReplyBuffer! // Otherwise, store in buffer EndCase EndOf grxDataCR // CR after data seen Of ( bData ) chrLF = // LF after CR ? If grxCompleted GsmRxState! // Yes, set state to completed Else grxNone GsmRxState! // No LF, reset ... EndIf EndOf grxCompleted // CRLF after data seen - reception complete Of .// grxCompleted : .// .// to be checked by process handler .// as processing is state dependant .// ( bData ) Drop // Drop bData EndOf Default Drop // Drop case value ftGsmRxState // Invalid GsmRxState, reboot. FatalError EndCase EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmHandleErrorTimeout ( -- ) GsmTimer_Fired If GsmError EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmStartWaitForOk ( bStateAfter -- ) GsmReturnState! // Set new state as return state gsWaitForOk // Set gsWaitForOk as the current state GsmState! s3 GsmTimer_Start // OK must be said within 3 seconds ; // ////////////////////////////////////////////////////////////////////////// // Gsm process handlers // ////////////////////////////////////////////////////////////////////////// : GsmProcessOff ( -- ) GsmOn // Gsm is off, turn it on ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessTurningOn ( -- ) GsmTimer_Fired If GSM_ClrOnOff // End pulse GsmSendInitialization gsOn GsmState! s3 GsmTimer_Start GsmTries0! EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessOn ( -- ) GsmRxCompleted? If GsmSaidOK? If GsmSendAT+CPIN? s50 GsmTimer_Start gsPinQrySent GsmState! EndIf Else GsmTimer_Fired If GsmTries@ 3 > If GsmError Else GsmTries++ GsmSendInitialization s2 GsmTimer_Start EndIf EndIf EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessTurningOff ( -- ) GsmTimer_Fired If GSM_ClrOnOff // End pulse gsTurningOff2 GsmState! s12 GsmTimer_Start EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessTurningOff2 ( -- ) GsmTimer_Fired GsmRings? // Assuming RING will go active when VIO drops to zero Or If gsOff GsmState! GsmTimer_Stop StopPowerGuardGsm // Turn off GSM power GSM_PowerOff // Also physically turn it off (so the process can be stopped) GsmTerminated // Shutdown completed, inform others (defered) EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessWaitForOK ( -- ) GsmRxCompleted? If GsmSaidOK? If GsmReturnState@ GsmState! EndIf Else GsmHandleErrorTimeout EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmSendPinCode ( -- ) GsmSendAT+CPIN= // AT+CPIN= GsmSendQuote // AT+CPIN=" GsmGetPinString ?PtrDup // Dup if not Nil If GsmSendRamString // AT+CPIN="xxxx Else " 0000" GsmSendRomString // AT+CPIN="0000 EndIf GsmSendQuote // AT+CPIN="xxxx" GsmSendCRLF // AT+CPIN="xxxx" ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessPinQrySent ( -- ) GsmRxCompleted? If GsmSaid+CPIN_Ready? If GsmSendAT+CREG gsRegSent GsmState! s50 GsmTimer_Start Else GsmSaid+CPIN_SIM_PIN? If GsmTries0! // Set tries to zero GsmSendPinCode // Send PIN gsPinCodeSent GsmState! // Change state s20 GsmTimer_Start Else GsmSaidError? If GsmError EndIf EndIf EndIf Else GsmHandleErrorTimeout EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessPinCodeSent ( -- ) GsmRxCompleted? If GsmSaidOK? If GsmSendAT+CREG gsRegSent GsmState! s50 GsmTimer_Start EndIf Else GsmTimer_Fired If GsmTries@ 3 > If GsmError Else BreakPoint pinerror GsmTries++ GsmSendPinCode s20 GsmTimer_Start EndIf EndIf EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessRegSent ( -- ) GsmRxCompleted? If GsmSaidOK? If gsPreRegistered GsmState! s3 GsmTimer_Start Else GsmSaidError? If gsPreRegistered GsmState! s3 GsmTimer_Start EndIf EndIf Else GsmHandleErrorTimeout EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessPreRegistrered ( -- ) GsmTimer_Fired If GsmSendAT+CREG? gsReqQrySent GsmState! GsmTries0! s2 GsmTimer_Start EndIf ; // ////////////////////////////////////////////////////////////////////////// // Some helpers : GsmGoRegistered ( -- ) gsRegistered GsmState! s3 GsmTimer_Start ; // ////////////////////////////////////////////////////////////////////////// : GsmGoCsqSent ( -- ) GsmSendAT+CSQ gsCsqSent GsmState! @GsmCsqTries 0! s2 GsmTimer_Start ; // ////////////////////////////////////////////////////////////////////////// : GsmRegQryCheckTimeout ( -- ) GsmTimer_Fired If GsmTries@ 120 > If GsmError Else GsmTries++ GsmSendAT+CREG? s2 GsmTimer_Start EndIf EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessRegQrySent ( -- ) GsmRxCompleted? If GsmSaidCREG? If GsmHandleRegStatusReply Case 0 Of GsmError EndOf 1 Of GsmTries0! GsmGoCsqSent EndOf 2 Of GsmRegQryCheckTimeout EndOf 3 Of GsmError EndOf 4 Of GsmRegQryCheckTimeout EndOf 5 Of GsmTries0! GsmGoCsqSent EndOf Default Drop // Unhandled reply GsmError EndCase EndIf Else GsmRegQryCheckTimeout EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmCheckRING ( -- ) // Handle possible incoming call GsmSaidRing? // String compare on GSM text GsmRings? // Looks at 'ring' input Or If GsmSendATA gsATASent GsmState! s30 GsmTimer_Start EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmCheck_NO_CONNECT ( -- f ) // Return TRUE if _NO_ CONNECT seen GsmSaidConnect? Dup If GsmSetConnected EndIf Not ; // ////////////////////////////////////////////////////////////////////////// // // GsmProcessRegistered - notes : // // Async transition to gsDialing is possible through GsmDial call : GsmProcessRegistered ( -- ) GsmTimer_Fired If GsmGoCsqSent Else GsmRxCompleted? If GsmCheckRING // Handle possible incoming call EndIf EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessCsqSent ( -- ) GsmRxCompleted? If GsmSaidCsq? If .// .// string after +CSQ: must be parsed and communicated .// to application (through 'GsmCsqHandler') .// GsmHandleCsqReply // Get CSQ etc, send it to app. GsmTries++ gsCsqSeen // State to go to after OK GsmStartWaitForOk // Await following OK Else GsmCheck_NO_CONNECT // Returns true if NO CONNECT seen, and issues a state change !! If GsmCheckRING // Handle possible incoming call EndIf EndIf Else GsmTimer_Fired If @GsmCsqTries 1+! @GsmCsqTries @ 5 > If GsmError Else GsmSendAT+CSQ gsCsqSent GsmState! s3 GsmTimer_Start EndIf Else GsmTries@ 250 > If GsmDone // Not an error, just a restart EndIf EndIf EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessCsqSeen ( -- ) GsmGoRegistered ; // ////////////////////////////////////////////////////////////////////////// : GsmDialFailed ( -- ) GsmError ; // ////////////////////////////////////////////////////////////////////////// // // See 'GsmProcessRegistered' and 'GsmDial' words : GsmProcessDialing ( -- ) GsmRxCompleted? If GsmCheck_NO_CONNECT // Returns true if NO CONNECT seen Not If // Nothing, connected Else GsmSaidNoCarrier? // No carriwer during dialing ? If GsmDialFailed EndIf EndIf Else GsmTimer_Fired If GsmDialFailed EndIf EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessATASent ( -- ) GsmRxCompleted? If GsmSaidConnect? If GsmSetConnected Else GsmSaidOk? // Voice call detection, just for error reporting If gsVoiceCall GsmState! s5 GsmTimer_Start EndIf EndIf Else GsmHandleErrorTimeout EndIf ; : GsmProcessVoiceCall ( -- ) GsmHandleErrorTimeOut ; // ////////////////////////////////////////////////////////////////////////// // // Hangup interface, reached through a call of GsmHangup (async) : GsmProcessBreakLink1 ( -- ) GsmTimer_Fired If GsmSend+++ gsBreakLink2 GsmState! ms10 GsmTimer_Start // ms1200 GsmTimer_Start EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessBreakLink2 ( -- ) GsmTimer_Fired If gsBreakLink3 GsmState! ms10 GsmTimer_Start // ms1000 GsmTimer_Start EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmDoSendATH ( -- ) GsmSendATH s5 GsmTimer_Start gsATHSent GsmState! ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessBreakLink3 ( -- ) GsmRxCompleted? If GsmSaidOk? If GsmDoSendATH EndIf Else GsmTimer_Fired If GsmDoSendATH EndIf EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessATHSent ( -- ) GsmRxCompleted? If GsmDone Else GsmHandleErrorTimeout EndIf ; // ////////////////////////////////////////////////////////////////////////// : GsmProcessReInit ( -- ) // Called after a non-recoverable GSM error was encountered. // Wait a while to allow for error messaga visability (? really) // then turn off system GsmTimer_Fired If GsmShutDown // reset controller on GSM errors (defered, request) // System not always correctly recovers otherwise. EndIf ; // ////////////////////////////////////////////////////////////////////////// Defer GsmSampleAdValue ( -- ) // ////////////////////////////////////////////////////////////////////////// : GsmProcess ( -- ) GsmHasData 0> If GsmRead GsmAcceptRx EndIf GsmGuardTimer_Fired If GsmError EndIf GsmState@ Case gsOff // GSM is off Of GsmProcessOff EndOf gsTurningOn // turning on - transient state Of GsmProcessTurningOn EndOf gsOn // GSM is on Of GsmProcessOn EndOf gsTurningOff // turning off - transient state Of GsmProcessTurningOff EndOf gsTurningOff2 // turning off - transient state Of GsmProcessTurningOff2 EndOf gsWaitForOK // Wait for GSM to send OK, a called state Of GsmProcessWaitForOK EndOf gsPinQrySent // PIN query was sent Of GsmProcessPinQrySent EndOf gsPinCodeSent // PIN code was sent Of GsmProcessPinCodeSent EndOf gsRegSent // Network registration sent Of GsmProcessRegSent EndOf gsPreRegistered // Waiting for OK on registration Of GsmProcessPreRegistrered EndOf gsReqQrySent // Query for registration status sent Of GsmProcessRegQrySent EndOf gsRegistered // GSM is registered into the network Of GsmProcessRegistered EndOf gsCsqSent // Quality of service request sent Of GsmProcessCsqSent EndOf gsCsqSeen // Waiting for OK after CSQ reception Of GsmProcessCsqSeen EndOf gsDialing // Dialing a phone number Of GsmProcessDialing EndOf gsATASent // ATA sent to pick up the phone Of GsmProcessATASent EndOf gsVoiceCall // OK received after ATA, voice call Of GsmProcessVoiceCall EndOf gsConnected // A connection to a remote modem exists Of // GsmProcessConnected // No need to do any processing EndOf gsBreakLink1 // Breaking data link phase 1 - before +++ Of GsmProcessBreakLink1 EndOf gsBreakLink2 // Breaking data link phase 2 - after +++ Of GsmProcessBreakLink2 EndOf gsBreakLink3 // Breaking data link phase 3 - wait for OK after +++ process Of GsmProcessBreakLink3 EndOf gsATHSent // Hanging up Of GsmProcessATHSent EndOf gsReInit // Delay before reset after error Of GsmProcessReInit EndOf Default // Invalid state - programming error, reset system Drop ftGsmState FatalError EndCase ; // ////////////////////////////////////////////////////////////////////////// : InitGsm ( -- ) StartPowerGuardGsm // Apply GSM power BaudSetGsm MPX_Gsm // Make GSM accessible 250. Delay // Wait a while for power to settle GsmOn // Start GSM ; // ////////////////////////////////////////////////////////////////////////// : ExitGsm ( -- ) // ExitGsm should normally only be called when GsmState = gsOff StopPowerGuardGsm // Remove GSM power GSM_PowerOff // Also physically turn it off (so the process can be stopped) ; // ////////////////////////////////////////////////////////////////////////// Public // ////////////////////////////////////////////////////////////////////////// Export InitGsm ( -- ) // Module initialization, turns GSM on Export ExitGsm ( -- ) // Module finalization Export GsmProcess ( -- ) // Gsm process driver Export GsmOn ( -- ) // Turn the Gsm on Export GsmOff ( -- ) // Turn the Gsm off Export GsmDial ( wRamPtr -- ) // Dial the counted string at wRamPtr Export GsmHangup ( -- ) // Hang up the phone Export GsmHasRoom ( -- bCount ) // Nr of bytes free in tx queue Export GsmTransmit ( bData -- ) // Transmit a byte of data to the Gsm Export GsmState@ ( -- bState ) // Get current GSM state Export GsmSampleAdValue ( -- ) // Deferred, Takes ad samples during power on Export GsmTerminated ( -- ) // Called to signal GSM shutdown completion Export GsmShutDown ( -- ) // Defered request for total device shutdown Export GsmErrorOccurred ( -- ) // Called when a fatal GSM error occurred // ////////////////////////////////////////////////////////////////////////// EndModule