The code continues to grow. Since last update, I've added the ability for the main app to request data transfers through the bluetooth connection. In addition, I spent about 6 hours today adding code to support characteristics with the notification attribute set. This is so Android can be notified when I change local characteristic values.
For those interested, all the heavy lifting, once the bluetooth is set up, occurs in state 15. This state handles pretty much everything for most of the working life of the bluetooth.
BTWPROP is also a really cool routine, if one wants to try to make sense of it.
I still need to add data written to my device from the Android central. That's tomorrow.
For those interested, all the heavy lifting, once the bluetooth is set up, occurs in state 15. This state handles pretty much everything for most of the working life of the bluetooth.
BTWPROP is also a really cool routine, if one wants to try to make sense of it.
I still need to add data written to my device from the Android central. That's tomorrow.
Code:
;**************************************
;** BLTOG -- Toggle Bluetooth on/off **
;**************************************
bltog bbs fbton,bltoff ;turn bluetooth off?
;Turn bluetooth off
blton bsf fbton
return
;Turn bluetooth on
bltoff bcf fbton
return
;***************************************************************
;** POLLBT -- Bluetooth polling -- called each main loop pass **
;***************************************************************
pollbt retbc run ;don't process bluetooth until system initialized and running
BANKSEL btstate ;select bluetooth working bank
clrf btsresp,1 ;clear standard response flags
clrf btsresp+1,1
rcall btprcv ;check to see if a new bluetooth response has been received.
bz pbtnrsp ;no response
;if a non-standard response is received, and allowed, parse it
bbc fwrnsr,pbtnnwr ;nsr allowed?
btfsc fsrnsr ;nsr received?
rcall btpnsr ;go parse non-standard response
;a response has been received from bluetooth
pbtnnwr movlw b'01111111' ;ignore NWR flag
andwf btswait+1,w,1
iorwf btswait,w,1 ;are we waiting for a particular response?
bz pbstate ;no, just process machine
;decide whether or not to throw an error
bbs fwrerr,pbteok ;is ERR an acceptable response?
bbs fsrerr,pbterr ;No, flag ERR as error.
pbteok bbs FWRNWR,pbstate ;improper responses don't throw errors if NWR bit set
movf btswait,w,1 ;are we waiting for a response?
andwf btsresp,w,1 ;has a proper response been received?
bnz pbstate ;yes, process state machine
movf btswait+1,w,1 ;again, next byte
andwf btsresp+1,w,1
bnz pbstate
bra pbtimp ;flag an improper response
;no response received from bluetooth this pass -- process timed functions
pbtnrsp movf btstime,f,1 ;is timer running?
bz pbtntim ;no, not a timed function
;timed function -- either response time-out or timed state
btfsc tc16ms ;process 16ms timer
decfsz btstime,f,1 ;decrement state timer
bra btx____ ;no further processing if timer not expired
movlw b'01111111' ;ignore NWR flag
andwf btswait+1,w,1
iorwf btswait,w,1 ;are we waiting for a particular response?
bz pbstate ;no, just process timed state after delay
;otherwise, flag a timeout error
bra pbtrto ;show timeout error
;not a timed function
pbtntim bbs fwrnwr,pbstate ;don't wait for response if bit is set
movf btswait,w,1 ;are we waiting for a particular response?
iorwf btswait+1,w,1
bz pbstate ;no, just process the untimed state
bra btx____ ;otherwise, just wait until response
;Handle improper response
pbtimp bra btx____ ;ignore improper responses (for now)
;Handle ERR response
pbterr movlb 0
movlw bterr ;get ERR error code
call seterr ;and show error
BANKSEL btstate ;select bluetooth working bank
bra btx____ ;ignore erroneous responses
;Handle timeout during reception of response
pbtrto movlb 0
movlw btrto ;get time out error code
call seterr ;and set error limp along
BANKSEL btstate ;select bluetooth working bank
bra btx____ ;ignore erroneous responses
;process Bluetooth state machine
pbstate clrf btswait,1 ;clear waiting flags for next pass
clrf btswait+1,1
clrf btstime,1 ;and state timer
movfw btstate
call cjump
;idle with bluetooth off
bra btsid0 ;state 0: if fbton, wake BT and wait for CMD message
;setup blue tooth
bra btssu0 ;state 1: get/set feature string
bra btssu1 ;state 2: get/set friendly name
bra btssu2 ;state 3: get/set model name
bra btssu3 ;state 4: get/set manufacturers name
bra btssu4 ;state 5: get/set bitmap services
bra btssu5 ;state 6: send LS to confirm private services
bra btssu6 ;state 7: confirm private service UUID is defined
bra btssu7 ;state 8: confirm all private characteristic UUIDs
bra btssu8 ;state 9: scan for end of LS list
bra btssu9 ;state 10: start reset/reboot process -- clear private services
bra btssuA ;state 11: add private services
bra btssuB ;state 12: iteratively add private characteristics then reboot
bra btssuC ;state 13: wait for reboot to complete and redo LS to load handles
bra btsadv ;state 14: start advertising
;active with bluetooth on
bra btsac0 ;state 15: idle for connects/disconnects and monitor monitor for shutdown
;shudown bluetooth
bra btssd0 ;state 16: switch to dormant mode
bra btssd1 ;state 17: clear wakesw and shutdown EUSART
;***********************
;** Bluetooth states **
;***********************
;-- State 0: if fbton, wake BT and wait for CMD message
btsid0 bbc fbton,btx____ ;do nothing if bluetooth not activated
bbs shtdwn,btx____ ;and don't start up if in system shutdown
call uarton ;turn eusart on
bsf wakesw ;wake bluetooth
bsf wakehw
bcf fbtrbt ;clear reboot flag for setup
bsf fwrcmd ;wait for "CMD"
bsf fwrzcmd ; or \0CMD if restart
bra btx__LN ;long timeout in case of restart
;-- State 1: begin setup, get, compare, and set feature string if necessary
btssu0 bbs fsrnsr,btssu01 ;gf data received (as non-standard response?)
btssu00 txpstr sbtgfs ;get feature settings string
bsf fwrnsr ; wait for non-standard response
bra btx__T_ ; wait 200ms and don't advance
btssu01 rxpcstr sbtsfs ;expected value received?
skpnz
bra btx___N ;yes, advance to next state
bsf fbtrbt ;indicate a reboot is going to be required
txpstr sbtsfs ;send feature settings string
bra btx_ATN ;and advance
;-- State 2: get, compare, and set friendly name if necessary
btssu1 bbs fsrnsr,btssu10 ;friendly name received (as non-standard response?)
txpstr sbtgfn ;get friendly name string
bra btx__TR ; wait 200ms for NSR and don't advance
btssu10 rxpcstr sbtsfn ;expected value received?
skpnz
bra btx___N ;yes, advance to next state
bsf fbtrbt ;indicate a reboot is going to be required
txpstr sbtsfn ;send new friendly name
bra btx_ATN ;and advance
;-- State 3: get, compare, and set model if necessary
btssu2 bbs fsrnsr,btssu20 ;model received (as non-standard response?)
txpstr sbtgmod ;get model string
bra btx__TR ; wait 200ms for NSR and don't advance
btssu20 rxpcstr sbtsmod ;expected value received?
skpnz
bra btx___N ;yes, advance to next state
bsf fbtrbt ;indicate a reboot is going to be required
txpstr sbtsmod ;send new model
bra btx_ATN ;and advance
;-- State 4: get, compare, and set msnufacturer's name if necessary
btssu3 bbs fsrnsr,btssu30 ;manufacturer's name received (as non-standard response?)
txpstr sbtgmn ;get manufacturer's name string
bra btx__TR ; wait 200ms for NSR and don't advance
btssu30 rxpcstr sbtsmn ;expected value received?
skpnz
bra btx___N ;yes, advance to next state
bsf fbtrbt ;indicate a reboot is going to be required
txpstr sbtsmn ;send new manufacturer's name
bra btx_ATN ;and advance
;-- State 5: get, compare, and set bitmap services if necessary
btssu4 bbs fsrnsr,btssu40 ;bitmap services received (as non-standard response?)
txpstr sbtgbms ;get bitmap services string
bra btx__TR ; wait 200ms for NSR and don't advance
btssu40 rxpcstr sbtsbms ;expected value received?
skpnz
bra btx___N ;yes, advance to next state
bsf fbtrbt ;indicate a reboot is going to be required
txpstr sbtsbms ;send new bitmap services
bra btx_ATN ;and advance
;-- State 6: send LS command to confirm private characteristics set up properly
btssu5 clrf btsptr,1 ;preclear string pointer
clrf btsptr+1,1
clrf bthctr,1 ;clear handle counter for later
clrf btcctr,1 ;and characteristic counter
bcf fbtcapp ;preclear pcp capture for scan
txpstr sbtls ;send ls
bsf fwrnsr ;wait for non-standard response
bsf fwrend ;allow an END if nothing in the list
bra btx__TN ;and advance
;-- State 7: check if the private service is defined
btssu6 bbs fsrend,btrbt ;if END received, list is empty, reset and reboot
rxpcstr sbtsps ;expected value received?
bz btssu60 ;yes, set up for private characteristics
bsf fwrend ;allow an END if nothing in the list
bra btx__TR ;await response for END/NSR and return here
btssu60 bsf fwrnsr ;wait for non-standard response
bsf fwrend ;allow an END if nothing in the list
bra btx__TN ;and advance
;-- State 8: iterate to check UUID for each private characteristic -- capture handle if exists
; and process notification characteristics
btssu7 bbs fsrend,btssu70 ;if END received, ensure we got all characteristics
movfwb btcctr ;have we exhausted the number of characteristics?
xorlw cnumcar ;compare
bz btssu71 ;yes. Should have been END. Scan to END, reset and reboot.
movlf tblptrl,low sbtspc1 ;tblptr->first characteristic setup string
movlf tblptrh,high sbtspc1
movfwb btsptr ;add in string pointer to point to proper string
addwf tblptrl,f
movfwb btsptr+1
addwfc tblptrh,f
bsf fbtrpc ;indicate that we are scanning a private characteristic
call _rxpcstr ;compare string & capture handle
bnz btssu71 ;no, string not matched. Scan to end, reboot and reset
incf bthctr,f,1 ;bump counter for next private characteristic handle
bbs fbtcapp,btssu72 ;need to reload string for notification?
movlw 44 ;no, update string pointer
addwf btsptr,f,1
clrw
addwfc btsptr+1,f,1
incf btcctr,f,1 ;and increment characteristic pointer
btssu72 bsf fwrend ;allow an END if nothing in the list
bra btx__TR ;come back to this state with NSR/END response
; END received -- ensure we captured [cnumcar] characteristics
btssu70 movfwb btcctr ;have we exhausted the number of characteristics?
xorlw cnumcar ;compare
bnz btrbt ;no. Should have been END. Reset and reboot.
nextst cbtsrbt ;all good, but reboot if necessary
bra btx____
; No match. Scan to END, reboot and reset
btssu71 bsf fwrnsr ;wait for non-standard response
bsf fwrend ;wait for END if nothing in the list
bra btx__TN ;and advance
;-- State 9: scan for END, reboot and reset
btssu8 bbs fsrend,btrbt ;reset and reboot if END received
bsf fwrend ;wait for END if nothing in the list
bra btx__TR ;come back to this state with NSR/END response
;-- State 10: start reset/reboot process if necessary -- clear all private services
btssu9 bbs fbtrbt,btssu90 ;reboot necessary?
nextst cbtsadv ;no, start advertising
bra btx____
btrbt nextst cbtsrbt ;jump in here. Set to this state.
btssu90 bcf fbtrbt ;clear reboot flag for next pass
txpstr sbtcps ;clear any existing private services/characteristics
bra btx_ATN ;and advance
;-- State 11: add private services
btssuA clrf bthctr,1 ;preclear handle counter to index private characteristics
txpstr sbtsps ;add private servcie
bra btx_ATN ;and advance
;-- State 12: iteratively add private characteristics, then, reboot
btssuB movfwb bthctr ;have we exhausted the number of characteristics?
xorlw cnumcar ;compare
bz btssuB0 ;do actual reboot
movlf tblptrl,low sbtspc1 ;tblptr->first characteristic setup string
movlf tblptrh,high sbtspc1
movlw 44 ;43 bytes per private service string
;including stupid assembler padding 0
mulwf bthctr,1 ;prod = index into list of strings
movfw prodl ;set tblptr->correct characteristic string
addwf tblptrl,f
movfw prodh
addwfc tblptrh,f
incf bthctr,f,1 ;index to next characteristic
call _txpstr ;transmit string
bra btx_AT_ ;AOK and return here
;all characteristics set. Reboot
btssuB0 txpstr sbtres ;send reset
bsf fwrrbt ;wait for 'Reboot'
bra btx__TN
;-- State 13: wait up to 3,200 ms for reboot sequence -- then go do LS all over again to load handles
btssuC bsf fwrzcmd ;wait for '\0CMD'
nextst cbtsls ;set up LS as next state
bra btx__L_ ;long timeout for reset
;-- State 14: start advertisement
btsadv bsf fbtwcp ;ensure we wait for connection parameters
txpstr sbtadv ;send start advertisement
bra btxEATN ; AOK Expected (Error if already advertising)
;-- State 15: active as connected/disconnecedt -- monitor fbton in case bluetooth is to shut down
; and process all characteristic writes,reads,and requests from central device
btsac0 bbs FSRCON,btsac00 ;connect received?
bbs FSRCEND,btsac02 ;disconnect received?
bbs FSRAOK,btsac05
;don't process hardware signals or data writes until expected AOK or CONNP received
bbs fbtwcp,btsac01 ;expecting connection parameters?
bbs fbtww,btsac01 ;expecting AOK from value write?
;process shutdown signals if necessary
bbc fbton,btsac03 ;bluetooth needs to turn off?
bbs shtdwn,btsac03 ;system shutting down? Then turn off bluetooth.
;is data ready to write?
rcall btwprop ;write properties if necessary
;no other action, try again next main loop
bra btsac01 ;quit to next loop
;AOK received -- clear wait for AOK data write flag
btsac05 bcf fbtww ;clear flag
bra btsac01 ;and quit to next loop
;connect received
btsac00 bsf fbtconn ;indicate connection
rcall btcbonconn ;tell app that connection made
;quit and come back
btsac01 bsf FWRAOK ;allow AOK for properties written
bsf FWRCON ;allow connection response
bsf FWRCEND ;allow connection end response
bsf FWRNSR ;allow non-standard for notifications
bsf FWRNWR ;don't wait for a response
bra btx____ ;and come right back next pass
;disconnect received -- start advertising again for seamless reconnect
btsac02 bcf fbtconn ;indicate connection lost
rcall btcboffconn ;tell app that connection is broken
bsf fbtwcp ;wait for connection parameters
txpstr sbtadv ;send start advertisement
bra btx_AT_ ;wait for AOK
;shut down gracefully -- stop advertising or kill a connection
btsac03 bbs fbtconn,btsac04 ;connected?
;stop advertising
txpstr sbtkadv ;no, send stop advertise command
bra btxEATN ;and advance (allow error, but shouldn't happen)
btsac04 bcf fbtconn ;killing connection, so clear it
txpstr sbtkill ;send kill command
bsf FWRCEND ;wait for Connection End
bra btxE_TN ;wait for connection end, but allow for error JIC
;-- State 16: put bluetooth into dormant mode
btssd0 bcf wakehw ;pull line low
txpstr sbtdorm ;send dormant command
bra btx__TN ;result will be 0x00, which we cannot parse, so just time it
;-- State 17: shutdown bluetooth and EUSART
btssd1 call uartoff ;turn eusart off
bcf wakesw ;turn off bluetooth uart transmitter
nextst cbtsid ;set up idle0 as next state
bra btx____ ;and immediate idle
;***** END OF STATES *********
;**** Various Exits of SM to set up next state, timeouts, and responses ****
; E=ERR A=AOK T=short timeout L=long timeout N=advance to next state R=Allow non-standard response
btxE_TN movlfb btstime,cbtsto ;STO/ERR/NEXT
btxE__N bsf FWRERR ;ERR/NEXT
bra btx___N
btxEATN bsf FWRERR ;ERR/AOK/STO/NEXT
btx_ATN bsf FWRAOK ;AOK/STO/NEXT
btx__TN movlfb btstime,cbtsto ;STO/NEXT
btx___N incf btstate,f,1 ;NEXT
bra btx____
btx__TR bsf FWRNSR ;STO/NSR
bra btx__T_
btxEAT_ bsf FWRERR ;ERR/AOK/STO
btx_AT_ bsf FWRAOK ;AOK/STO
btx__T_ movlfb btstime,cbtsto
bra btx____
btx__LN incf btstate,f,1 ;LTO/NEXT
btx__L_ movlfb btstime,cbtslo ;LTO
btx____ movlb 0 ;nothing
return
;**** END OF SM EXITS ****
;*****************************************
;** BTPRCV -- Process Bluetooth receiver**
;** return z if no response **
;*****************************************
btprcv movlf fsr1h,high btrcvbuff ;point to receiver buffer
movff btrhead,fsr1l ; and index to next character
btplp rcall rxbyte ;receiver byte available?
retz ; z if none
movwf indf1 ;save character at current position
movlw '\r' ;ignore return characters
cpfseq indf1
movf postinc1,w ;get back in w, and update pointer
movff fsr1l,btrhead ;save new head position
xorlw '\n' ;new character a line feed?
bnz btplp ;no, get some more characters, if available
movlfb btrhead,low btrcvbuff ;reset btrhead for next message
;parse for common messages
;if common response not matched, indicate (likely) parameters returned from RN4020
bsf btsresp,0,1 ;set 1st bit in standard response flags
movdf tblptr,btsmes ;tblptr -> possible standard responses (\n separated, \r terminated)
btplp0 lfsr 0,btrcvbuff ;fsr0 -> point to head of response buffer
btplp1 tblrd *+ ;get next character from list of responses
movlw '\r' ;\r is response list terminating character
xorwf tablat,w ; end of response list?
bz btpnmf ;yes, no response matched
movf tablat,w ;get character
cpfseq postinc0 ;test against charcter in response buffer
bra btpnom ;!= means no match, skip to next response
movlw '\n' ;is it a new line character?
xorwf tablat,w
bz btpmat ;yes, we have found a match
bra btplp1 ;keep testing characters till match
;no match of current response, skip ahead till /n or /r
btpnom clrc ;roll to next response
rlcf btsresp,f,1
rlcf btsresp+1,f,1
btplp2 tblrd *+ ;get next character from list of responses
movlw '\r' ;get terminating character
xorwf tablat,w ; end of response list?
bz btpnmf ;yes, no response matched
movlw '\n' ;is it a new line character?
xorwf tablat,w
bnz btplp2 ;loop till \0 or \n
bra btplp0 ;and test against next response
;match found, response bit set
btpmat
;match not found, non-standard response bit set
btpnmf clrz ;nz indicates a new reponse has been received
return
;********************************************
;** BTPNSR -- Parse Non-Standard Responses **
;********************************************
btpnsr clrf bitcnt ;use bitcnt as index to received response
movdf tblptr,btnsmes ;tblptr -> possible non-standard responses (\n separated, \0 terminated)
btpnlp0 lfsr 0,btrcvbuff ;fsr0 -> point to head of response buffer
btpnlp1 tblrd *+ ;get next character from list of responses
movf tablat,w ;get character from list
bz btpnnf ;z=end of list, not found
movlw '\n' ;== \n means we have a match!
xorwf tablat,w
bz btpnm ;go process for arguments
movf tablat,w ;get character from list
cpfseq postinc0 ;compare with received
bra btpnnm ;no match, skip to next response
bra btpnlp1 ;continue till match/no match
;no match of current response, skip ahead till /0 or /n
btpnnm incf bitcnt,f ;update response counter
btpnlp2 tblrd *+ ;get next character from list of responses
movf tablat,w ;get character
bz btpnnf ;z=end of list -- no match
xorlw '\n' ;is it a new line character?
bnz btpnlp2 ;loop till \0 or \n
bra btpnlp0 ;and test against next non-standard response
;no match found - what do we do?
btpnnf return ;for now, just ignore the response
;match found -- bit count has response number
btpnm movfw bitcnt ;get response number
call cjump ;and process it
bra btnscp ;'ConnParam:'
bra btnsnfy ;'Notify,'
bra btnsind ;'Indicate,'
bra btnswv ;'WV,'
bra btnswc ;'WC,'
bra btnsrv ;'RV,'
;ConnParam <hex16>,<hex16>,<hex16> (connection interval, slave latency, supervison timeout)
btnscp lfsr 1,conint+1 ;point to holders
rcall hex2bin ;capture interval
rcall hex2bin ;capture slave latency
rcall hex2bin ;capture supervision timeout
bcf fbtwcp ;indicate connection parameters have been received
return
;other non-standard responses -- for later -- just indicate unhandled for now
;notification received
btnsnfy ;'Notify,'
;indication received
btnsind ;'Indicate,'
;write value to local server characteristic
btnswv ;'WV,'
;write configuration to local server characteristic
btnswc ;'WC,'
;real time read (bit must be set in supported features (SR)
btnsrv ;'RV,'
bra btpnnf ;indicate unhandled non-standard response
;**************************************************************
;** HEX2BIN -- Convert arbitrary length hex to binary **
;** store result at fsr1 -> RAM (high byte) **
;** ignore spaces, comma or \n terminated **
;** target RAM must be large enough to hold expected value **
;**************************************************************
hex2bin
;process high byte first
movf postinc0,w ;get next character
sublw '\n' ;is it a newline?
retz ;yes, we are done
addlw 22 ;is it a space?
bz hex2bin ;yes, ignore it
addlw 12 ;is it a comma?
retz ;yes, we are done
sublw -14 ;'A'-'F' = 7-12, '0'-'9' = -10 - -1
skpc ;correct for 0-9
addlw 7 ;'0'-'9' = -3 - 6
addlw 3 ;final result
swapf wreg,f ;swap for high byte
movwf indf1 ;and save
;then low byte (no need to check for terminators on odd characters)
h2b1 movlw 58
subwf postinc0,w ;'A'-'F' = 7 - 12, '0'-'9' = -10 - -1
skpc ;correct for 0-9
addlw 7 ;'0'-'9' = -3 - 6
addlw 3 ;final result
iorwf postdec1,f ;merge in
bra hex2bin ;do for all characters
;********************************************************************
;** RXPCSTR -- Compare received string with program memory **
;** program memory string terminated with \r **
;** tblptr -> string **
;** ignore leading characters in PM until first comma **
;** ignore leading spaces in RAM **
;** z if match, nz if no match **
;** if fbtrpc=1, pc handle is captured and pc properties checked **
;** if fbtcaph is set, handle for char #(bthctr) is captured **
;** on exit, if fbtcapp=1, line must be rescanned for property **
;********************************************************************
_rxpcstr
btfsc fbtrpc ;are we scanning a private characteristic?
bsf fbtcaph ;yes, we must capture the handle
lfsr 0,btrcvbuff ;point to bluetooth receive buffer
movlw ',' ;skip to character after first comma
rxpclp0 tblrd *+
cpfseq tablat
bra rxpclp0
rxpclp1 movlw ' ' ;ignore leading spaces in RAM
xorwf postinc0,w
bz rxpclp1
movf postdec0,w ;move pointer back to first non-space character
rxpclp2 tblrd *+ ;get character from program memory
movlw '\r' ;terminates with /r
xorwf tablat,w ;compare
bz rxpcbx ;return with z to indicate match
bbc fbtrpc,rxpcb0 ;scanning a private characteristic?
bbc fbtcaph,rxpcb0 ;capture handle flag set?
movlw ',' ;handle starts at first comma
xorwf indf0,w ;compare
bnz rxpcb0 ;scan till first comma
;first comma found, parse handle for this characteristic
rcall rxpch ;go capture handle
;adjust for notifiers - match comma
movf indf0,w ;current character should be comma
movfw tablat ;get pm character
xorwf postinc0,w ;compare with received character
bnz rxpcbx ;no match, reload
;check for match of high nibble of characteristic properties
tblrd *+ ;indext to next program character
movfw tablat ;get pm character
xorwf indf0,w ;compare with current ram character
bz rxpcb1 ;match. check second character
;if current RAM byte is non-zero, we are scanning properties
movlw '0'
xorwf indf0,w ;compare z=value, nz=char
skpnz ;if we are scanning characteristic property, proceed as normal
bsf fbtcapp ;otherwise, we must recheck line for property
;check for match of low nibble of characteristic properties
rxpcb1 movf postinc0,w ;skip to next character
tblrd *+ ;get next program character
movfw tablat ;get rom character
xorwf indf0,w ;compare with current ram character
bz rxpcb2 ;continue normally if match (first line, fbtcapp is set)
;second line of notified characteristic -- ensure ftbcapp and char '0'
bbc fbtcapp,rxpcbx ;fbtcapp should be set here, if not, we've got a mismatch
bcf fbtcapp ;clear fbtcapp for next characteristic
movlw '0' ;ram byte should be zero
xorwf indf0,w ;compare z=value, nz=char
bra rxpcbx ;z=string matched (ignore last parameter), nz=mismatched.
;first line of characteristic -- scan normally
rxpcb2 movf postinc0,w ;to next character
bra rxpclp2 ;continue scanning normally
;just normal scan here
rxpcb0 movf indf0,w
movfw tablat ;get pm character
xorwf postinc0,w ;compare with received character
bz rxpclp2 ;match, keep going
rxpcbx bcf fbtrpc ;clear private characteristic indication
return ;return with no match/no match
;capture handle at current ram position +1
rxpch bcf fbtcaph ;clear capture flag for any remaining commas
lfsr 1,hpchar1 ;fsr1->start of characteristic handle table
rlncf bthctr,w,1 ; *4 (size of handle)
rlncf wreg,w
addwf fsr1l,f ;fsr1->proper handle
movff preinc0,postinc1 ;copy 4 bytes
movff preinc0,postinc1
movff preinc0,postinc1
movff preinc0,postinc1
movf postinc0,f ;index to tailing comma
return ;and go finish scan
;******************************************************
;** BTWPROP -- Write property value if indicated **
;** btwrite has one or more properties **
;** bit 0 for battery service **
;** bit 1 through cnumcar for private service **
;** format out: "SHW,hhhh,v..." **
;** callback to get value **
;******************************************************
btwprop retbc fbtconn ;no writes if not connected
movfwb btwrite ;properties to write?
iorwf btwrite+1,w,1 ; two sets
retz ;no, get out
;yes, find next data item to send
movlf temp1,1 ;start at bit0
clrf temp2
clrf bthctr,1 ;will hold property number
;find the next property who's value requires writing
btwplp0 movfwb btwrite ;test a bit
andwf temp1,w ;got a hit?
bnz btwp0 ;yes, go send it
movfwb btwrite+1 ;test a bit
andwf temp2,w ;got a hit?
bnz btwp0 ;yes, go send it
clrc ;shift bit mask
rlcf temp1,f
rlcf temp2,f
incf bthctr,f,1 ;increment property number
bra btwplp0 ;and check next
;bthctr has property number to write
btwp0 comf temp1,w ;invertmask
andwf btwrite,f,1 ;and clear bit for next pass
comf temp2,w ;invertmask
andwf btwrite+1,f,1 ;and clear bit for next pass
bsf fbtww ;ensure AOK returned after following command
decf bthctr,f,1 ;get bthctr-1
bc btwpps ; c=private service
;bthctr was 0 -- send battery service
txpstr sbtbsh ;send battery service handle
call btcbwbl ;go write actual value in callback
bra ptwpx ;exit adding trailing return
;enumerated private services (up to 10)
btwpps txpstr sbtshw ;send "SHW," to begin property write
lfsr 1,hpchar1 ;point first characteristic handle
rlncf bthctr,w ;double count
rlncf wreg,w ; 4 bytes per entry
addwf fsr1l,f ; and index
movfw postinc1 ;send handle for indicated service
call txbyte
movfw postinc1 ;send handle for indicated service
call txbyte
movfw postinc1 ;send handle for indicated service
call txbyte
movfw postinc1 ;send handle for indicated service
call txbyte
movlw ','
call txbyte ;send a comma to separate from value
switch bthctr,1,ptwpx ;make proper callback and exit with trailing \r
goto btcbps1 ;each must send a value to TX
goto btcbps2
goto btcbps3
goto btcbps4
goto btcbps5
goto btcbps6
goto btcbps7
goto btcbps8
goto btcbps9
goto btcbpsA
;add trailing return character to complete command
ptwpx movlw '\r'
goto txbyte ;send and return
;************************************************
;** BTSI8 -- send INT8 in btsdata to bluetooth **
;************************************************
btsi8 lfsr 1,btsdata ;point to btsdata
;********************************************
;** BTSPI8 -- send fsr1->INT8 to bluetooth **
;********************************************
btspi8 movlw 1 ;one byte
bra btpssd ;write the data
;**************************************************
;** BTSI16 -- send INT16 in btsdata to bluetooth **
;**************************************************
btsi16 lfsr 1,btsdata ;point to btsdata
;**********************************************
;** BTSPI16 -- send fsr1->INT16 to bluetooth **
;**********************************************
btspi16 movlw 2 ;two bytes to send
bra btpssd ;and write data
;************************************************
;** BTSFLS -- send float on stack to bluetooth **
;************************************************
btsfls popfl btsdata ;get float into btsdata
;*******************************************************
;** BTS32 -- send 4 bytes of binary data to bluetooth **
;** btsdata has data to send **
;*******************************************************
bts32 movlw 4 ;four bytes
;***********************************************************
;** BTSSD -- send wreg bytes of binary data to bluetooth **
;** btsdata has data to send **
;***********************************************************
btssd lfsr 1,btsdata ;point to btsdata
;***********************************************************
;** BTPSSD -- send wreg bytes of binary data to bluetooth **
;** fsr1->data **
;***********************************************************
btpssd movwf bitcnt ;save number of bytes
addwf fsr1l,f ;and point to high byte +1
movf postdec1,f ;point to high byte
btssdl1 swapf indf1,w ;get high byte
rcall tbc2hex ;transmit ASCII
movf postdec1,w ;get low byet
rcall tbc2hex ;transmit ASCII
djnz bitcnt,btssdl1 ;do for all bytes
return ;and return
;********************************************************
;** BTTHEX -- Convert low nibble of WREG to ASCII HEX **
;** and transmit to bluetooth
;********************************************************
tbc2hex andlw b'1111' ;mask lower nibble
addlw -10 ;0-9=-10 to (-1) (nc), A-F=0 to 5 (c)
skpnc ;A-F?
addlw 7 ;A-F = 7 to 12
addlw 58 ;0-9=48-57,A-F=65-70 ('0'-'9','A'-'F')
goto txbyte ;and send it
;custom app files
include "btcb.asm" ;include custom callbacks to main program
include "btstrings.asm" ;include command/response strings