|
Step 4: Completing the Project |
Top Previous Next |
This sample project is published on our website under the name "test_stg_lib".
OK, settings defined, comms protocol is their to read and write them, now let's put all this to good use. Rules of engagement:
| • | Writing new value into the "CPTN" setting should play a corresponding pattern stored in the "PTN" setting. |
| • | Briefly pressing the MD button should play the next pattern. |
Our sample project nicely illustrates what was said in Using Pre-gets and Post-sets. When the "CPTN" setting is being written to, callback_stg_post_set() is called and this gives us a chance to "load" another pattern. Notice how this is done! We can't use stg_get() or stg_sg() inside callback_stg_post_set() -- this limitation is explained in Using Pre-gets and Post-sets. We, however, need to read the "PTN" setting in order to play the new pattern!
Luckily, there is almost always a work around. In our case, we load a very short blank pattern "-" instead. When this pattern is done playing, the on_pat() event is generated and then we read one of the "PTN" members according to the pattern_num variable.
Callback_stg_pre_get() is also useful in our project. When we send a command to read the current value of the "CPTN" setting, the setting is first updated with the current value of the pattern_num variable!
Notice also how stg_get_num_members() is used in play_next_pattern(). Each time the button is pressed, pattern_num is incremented by one, until it reaches the number of members in the "PTN" setting, after which pattern_num is reset back to 0. Note: should actually check the code returned by stg_get_num_members(). We don't do this because we are pretty sure there won't be any errors -- this function only deals with the descriptor file. If the file is correct, and arguments to the function are correct, then no error should occur.
Here is the I/O Ninja (ninja.tibbo.com) session where we switched between different patterns:
Established TCP connection with 192.168.1.93:1000 from 1723 SCPTN,0,1<CR> A<CR> ASCPTN,0,2<CR> A<CR>
|
The project in its entirety:
global.tbh: |
'DEFINES------------------------------------------------------------- #define STG_DEBUG_PRINT 1 'highly recommended -- will print a lot of useful debug info #define STG_MAX_SETTING_NAME_LEN 4 #define STG_MAX_NUM_SETTINGS 5 #define STG_RAM_ARRAY_SIZE 2
'INCLUDES------------------------------------------------------------ include "settings\trunk\settings.tbh" include "sock\trunk\sock.tbh"
'DECLARATIONS-------------------------------------------------------- declare sub play_next_pattern() declare sub comms_init() declare sub comms_proc_cmd()
declare pattern_num as byte
|
main.tbs: |
include "global.tbh"
'==================================================================== sub on_sys_init() dim x as en_stg_status_codes dim stg_name as string(STG_MAX_SETTING_NAME_LEN)
if stg_start()<>EN_STG_STATUS_OK then sys.halt
x=stg_check_all(stg_name) select case x case EN_STG_STATUS_OK: '--- all good ---
case EN_STG_STATUS_INVALID, EN_STG_STATUS_FAILURE: if stg_restore_multiple(EN_STG_INIT_MODE_NORMAL)<>EN_STG_STATUS_OK then sys.halt
case else: 'some other trouble sys.halt end select
comms_init() end sub
'-------------------------------------------------------------------- sub on_button_released() if button.time>4 then if stg_restore_multiple(EN_STG_INIT_MODE_NORMAL)<>EN_STG_STATUS_OK then sys.halt sys.reboot else play_next_pattern() end if end sub
'-------------------------------------------------------------------- sub on_sock_data_arrival() comms_proc_cmd() end sub
'-------------------------------------------------------------------- sub on_pat() pat.play(stg_get("PTN",pattern_num),PL_PAT_CANINT) end sub
|
device.tbs: |
include "global.tbh"
'-------------------------------------------------------------------- dim pattern_num as byte dim comms_sock as byte
'==================================================================== sub callback_stg_error(byref stg_name_or_num as string,index as byte,status as en_stg_status_codes) sys.halt end sub
'-------------------------------------------------------------------- sub callback_stg_pre_get(byref stg_name_or_num as string,index as byte,byref stg_value as string) if stg_name_or_num="CPTN" then stg_value=str(pattern_num) end if end sub
'-------------------------------------------------------------------- sub callback_stg_post_set(byref stg_name_or_num as string, index as byte,byref stg_value as string) if stg_name_or_num="CPTN" then pattern_num=val(stg_value) pat.play("-",PL_PAT_CANINT) end if end sub
'-------------------------------------------------------------------- sub play_next_pattern() dim x as byte
stg_get_num_members("PTN",x) pattern_num=pattern_num+1 if pattern_num>=x then pattern_num=0 pat.play(stg_get("PTN",pattern_num),PL_PAT_CANINT) end sub
'-------------------------------------------------------------------- sub comms_init() net.ip=stg_get("IP",0)
comms_sock=sock_get("COMM") if comms_sock=255 then sys.halt
sock.num=comms_sock sock.rxbuffrq(1) sock.txbuffrq(1) sys.buffalloc
sock.protocol=PL_SOCK_PROTOCOL_TCP sock.localportlist=stg_get("PN",0) sock.inconmode=PL_SOCK_INCONMODE_ANY_IP_ANY_PORT sock.reconmode=PL_SOCK_RECONMODE_3 end sub
'-------------------------------------------------------------------- sub comms_proc_cmd() dim pos as byte dim s as string dim stg_name as string(STG_MAX_SETTING_NAME_LEN) dim stg_value as string(STG_MAX_SETTING_VALUE_LEN) dim index as byte dim result as en_stg_status_codes
if sock.num=comms_sock then pos=instr(1,sock.peekdata(255),chr(13),1) 'is there CR in the buffer if pos=0 then 'this is to prevent buffer overflow with garbage if sock.rxlen=sock.txbuffsize then s=sock.getdata(255) end if else 'yes, there is CR -- we have a complete command s=sock.getdata(pos) s=left(s,len(s)-1)
'eliminate LF if present if asc(left(s,1))=10 then s=right(s,len(s)-1) end if
'process this command select case asc(left(s,1)) case `S`: 'set setting, is index specified? s=right(s,len(s)-1) pos=instr(1,s,",",1) if pos=0 then stg_name=s index=0 else stg_name=left(s,pos-1) index=val(mid(s,pos+1,255)) end if
'is value specified? s=mid(s,pos+1,255) pos=instr(1,s,",",1) if pos=0 then stg_value=0 else stg_value=mid(s,pos+1,255) end if
result=stg_sg(stg_name,index,stg_value,EN_STG_SET) s=""
case `G`: 'get setting, is index specified? s=right(s,len(s)-1) pos=instr(1,s,",",1) if pos=0 then stg_name=s index=0 else stg_name=left(s,pos-1) index=val(mid(s,pos+1,255)) end if
result=stg_sg(stg_name,index,s,EN_STG_GET)
case else: result=EN_STG_STATUS_UNKNOWN end select
'common portion -- generate reply select case result case EN_STG_STATUS_OK: s="A"+s
case EN_STG_STATUS_UNKNOWN, EN_STG_STATUS_INVALID_INDEX: s="C" 'invalid setting name or index
case EN_STG_STATUS_FAILURE: s="F" 'failure (hardware, etc.)
case EN_STG_STATUS_INVALID: s="I" 'invalid value
case else: s="U" 'some internal error end select
sock.setdata(s) sock.send end if end if end sub
|
settings.txt: |
>>DN E S 1 0 10 I ^ Device Name >>IP E D 1 4 4 A 192.168.1.93 IP address <-- set the one you want as the default value >>PN E W 1 0 65535 A 1000 Port number >>PTN E S 3 0 16 A G-~/R-~/B-~ LED patterns >>CPTN R B 1 0 2 A 0 Current pattern to play
#define STG_DEBUG_PRINT 1 #define STG_MAX_SETTING_NAME_LEN 4 #define STG_MAX_NUM_SETTINGS 5 #define STG_RAM_ARRAY_SIZE 2
|