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