PDA

View Full Version : Timer based Lua script



johnp
February 14th, 2008, 03:00 PM
Hi, It's been a while since I was around, but still love this stuff.

I am trying to send data to a keypad via serial plugin using LUA.

So far I can get data from media player to Girder and store data to global variables and also I can send data to the keypad and get it displayed without issue.

now things get interesting, the display on the keypad only supports 12 characters and that is much to short for what I want to display so I have to try and scroll the data.

I would like to display the data in this manner given the example of the following data
1. Artist is Deep Purple
2. Album is The Very Best of Deep Purple
3. Track Name is Smoke On The Water

on request:
Display "Artist:"
Wait 2 seconds
Display "Deep Purple"
wait 2 seconds
Display "Album:"
wait 2 seconds
Display "The Very Best of Deep Purple" (first 12 characters)
wait 1 second
Scroll remaining characters across the display with 200 ms between character shifts.
wait 2 seconds after last shift
Display "Title"
wait 2 seconds
Display "Smoke On the Water" (first 12 characters)
wait 1 second
Scroll remaining characters across the display with 200 ms between character shifts.
wait 2 seconds after last shift
Display "Smoke On th" (first 12 characters of Title)

What I can't do is hold up the rest of Girder processing while all the pauses are going on so it has to be timer based. Also there could be up to eight of these running simultaneously so that should be a consideration too.

Any ideas how this might be implemented in LUA??? Is it even possible?

Thanks in advance.

Mark F
March 13th, 2008, 01:59 PM
I've been away for a while as well. :)

The WinLUAEx plugin exports stuff that could be used to do this. The TIMER_CreateObject function would give you a timer object that could be used to generate events (or directly send data to the serial plugin) in the future. At the end of each future event, set the timer to trigger when the next future event needs to execute.

You could create a LUA object and put a unique timer object and all the current track information in it. When you get a display request, display the first stuff, save an indicator of what happens next and arm the timer. When the timer expires, it can generate an event or call a LUA routine to do the next thing (display, scroll, etc), set the indicator for the next, next thing and arm the timer. This continues until all the next next next next ... things have been done.

If you create one of these for each display instance (up to 8?), they will not conflict with each other except to steal CPU cycles from each other.

Does this help?

johnp
March 13th, 2008, 03:37 PM
Hi, it does help in part. Forgive me, I am sort of dense, so I will need to see a sample or two before it sinks in. Do you have an example of doing what you said?

Thanks

Mark F
March 21st, 2008, 06:17 AM
I don't know if this will work or not. I don't have a Girder 3.x system anymore.

Your part will be to add the TODO:

I know it is not commented very well. Sorry. :(



--
-- Timer based state machine sample
--
-- timer object and routines are part of a larger object
--
StateMachine = { timer = TIMER_CreateObject(),

AmountToShow = 12, -- show 12 characters at a time
WaitBeforeRestart = 30, -- seconds to wait before restart (0 = don't restart)

-- state functions
-- these are the routines we run on each trigger

DisplayArtistText = function()
StateMachine.SetupScroll ( "Artist:" )
end,

DisplayArtist = function()
StateMachine.SetupScroll ( StateMachine.Artist )
end,

DisplayAlbumText = function()
StateMachine.SetupScroll ( "Album:" )
end,

DisplayAlbum = function()
StateMachine.SetupScroll ( StateMachine.Album )
end,

DisplayTitleText = function()
StateMachine.SetupScroll ( "Title:" )
end,

DisplayTitle = function()
StateMachine.SetupScroll ( StateMachine.Title )
end,

DisplayTitleFinal = function()
StateMachine.ScrollingText = StateMachine.Title
StateMachine.ScrollingLocation = 1
-- display next characters of StateMachine.ScrollingText
StateMachine.DisplayText()
-- if we should not restart
if (StateMachine.WaitBeforeRestart == 0)
-- kill the timer
StateMachine.timer.Cancel()
else
-- set next state
StateMachine.CurrentState = 1
-- arm timer for an StateMachine.WaitBeforeRestart second wait
StateMachine.timer.Arm ( StateMachine.WaitBeforeRestart * 1000 )
end
end,

Scroll = function()
local stringlength

-- use the string length of StateMachine.ScrollingText, StateMachine.ScrollingLocation and
-- StateMachine.AmountToShow to determine if we are done scrolling
stringlength = strlen(StateMachine.ScrollingText) + 1 -- ScrollingLocation starts at 1
if (stringlength > (StateMachine.ScrollingLocation + StateMachine.AmountToShow) )
-- set up for next display
StateMachine.ScrollingLocation = StateMachine.ScrollingLocation + 1
-- display next characters of text from StateMachine.ScrollingText
StateMachine.DisplayText()
-- do NOT change state as we are still scrolling
-- arm timer for a 200 ms wait
StateMachine.timer.Arm ( 200 )
else
-- set next state
StateMachine.CurrentState = StateMachine.CurrentState + 1
-- arm timer for a 0 ms wait
StateMachine.timer.Arm ( 0 )
end
end,

WaitTwoSeconds = function()
-- set next state
StateMachine.CurrentState = StateMachine.CurrentState + 1
-- arm timer for an 2000 ms wait
StateMachine.timer.Arm ( 2000 )
end,

WaitOneSecond = function()
-- set next state
StateMachine.CurrentState = StateMachine.CurrentState + 1
-- arm timer for an 1000 ms wait
StateMachine.timer.Arm ( 1000 )
end,

-- this routine is used to show the scrolling text
DisplayText = function()
local substring
-- display next StateMachine.AmountToShow characters of text from StateMachine.ScrollingText
-- use StateMachine.ScrollingLocation as the starting location of the sub-string
substring = StrSub(StateMachine.ScrollingText, StateMachine.ScrollingLocation, StateMachine.ScrollingLocation + StateMachine.AmountToShow)

-- TODO: add your code to display substring on the device

end,
-- this is used to set up the scrolling text variables
SetupScroll = function( val )
StateMachine.ScrollingText = val
StateMachine.ScrollingLocation = 1
-- display next characters of text from StateMachine.ScrollingText
StateMachine.DisplayText()
-- set next state
StateMachine.CurrentState = StateMachine.CurrentState + 1
-- arm timer for a 0 ms wait
StateMachine.timer.Arm ( 0 )
end,

-- internal state machine variables
StateFunctions = {}, -- state function array
OneTime = 1,
CurrentState = 1,
Enable = "FALSE",

Trigger = function ()
if (StateMachine.Enable == "FALSE") then
StateMachine.timer.Cancel ( )
else
StateMachine.StateFunctions[ StateMachine.CurrentState ]()
end
end,

Cancel = function()
StateMachine.EnableStateMachine( "FALSE", "", "", "" )
end,

EnableStateMachine = function( val, artist, album, title )

if (StateMachine.OneTime == 1) then
StateMachine.OneTime = 0
-- this sets up the state machine routines
StateMachine.StateFunctions[1] = StateMachine.DisplayArtistText
StateMachine.StateFunctions[2] = StateMachine.WaitTwoSeconds
StateMachine.StateFunctions[3] = StateMachine.DisplayArtist
StateMachine.StateFunctions[4] = StateMachine.WaitOneSecond
StateMachine.StateFunctions[5] = StateMachine.Scroll
StateMachine.StateFunctions[6] = StateMachine.WaitOneSecond

StateMachine.StateFunctions[7] = StateMachine.DisplayAlbumText
StateMachine.StateFunctions[8] = StateMachine.WaitTwoSeconds
StateMachine.StateFunctions[9] = StateMachine.DisplayAlbum
StateMachine.StateFunctions[10] = StateMachine.WaitOneSecond
StateMachine.StateFunctions[11] = StateMachine.Scroll
StateMachine.StateFunctions[12] = StateMachine.WaitOneSecond

StateMachine.StateFunctions[13] = StateMachine.DisplayTitleText
StateMachine.StateFunctions[14] = StateMachine.WaitTwoSeconds
StateMachine.StateFunctions[15] = StateMachine.DisplayTitle
StateMachine.StateFunctions[16] = StateMachine.WaitOneSecond
StateMachine.StateFunctions[17] = StateMachine.Scroll
StateMachine.StateFunctions[18] = StateMachine.WaitOneSecond

StateMachine.StateFunctions[19] = StateMachine.DisplayTitleFinal
end
-- turn on the state machine
if (val == "TRUE") then
StateMachine.Enable = val
StateMachine.CurrentState = 1
StateMachine.Album = album
StateMachine.Title = title
StateMachine.Artist = artist
StateMachine.timer.Create ( "", "StateMachine.Trigger()", "StateMachine.Cancel()", 0 )
StateMachine.timer.Arm ( 0 )
else
StateMachine.timer.Destroy ( )
StateMachine.Enable = "FALSE"
StateMachine.CurrentState = 1
end
end

}

-- to turn this on, use this
StateMachine.EnableStateMachine( "TRUE", "Deep Purple", "Machine Head", "Smoke On The Water" )



I hope this helps.

johnp
March 21st, 2008, 09:11 AM
Thanks Mark as always. You have always been very helpful to me over the years and it is very much appreciated. I am humbled by your generosity. I will take it from here and comment back with the finished product.

Best to you.