New Products Flash Sale
Thread Tools
Old Jul 26, 2015, 09:08 PM
extremewing is online now
Find More Posts by extremewing
A different attitude to RC
extremewing's Avatar
Draper, Utah
Joined Sep 2008
3,328 Posts
Download
*Updated* Launch Master for Taranis

Updated to work on 2.0.15, 2.0.17 and 2.1.0

After playing with LUA for a bit, I am proud to introduce Launch Master for Taranis!

This is a complete re-write of Nigel Sheffield's original launch height script:
http://www.rcgroups.com/forums/showthread.php?t=2237421

Launch Master provides an advanced launch detector borrowed from the BTOA.
It also implements the BTOA's zero offset mechanism to deal with any altimeter drift.


------------------------------------------------------------------------------
-- IMPORTANT: PLEASE READ THE FOLLOWING WARNING
------------------------------------------------------------------------------
-- If you use any GVAR's from flight modes six through nine, you must modify some options in the file (read the top part)
-- ALL GVAR's in flight modes six through nine will be OVERWRITTEN with data if you do not modify any options.
------------------------------------------------------------------------------

Features
- Uses GVAR's as a mini data store ** SEE WARNING ABOVE **
- Automatically adjusts base altitude with any altimeter drift
- Records and displays fourteen launches in two lists
- Records the best altitude over all launches
- Session data can be reset leaving the best launches list
- Launch target is automatically set - or choose your own
- SIM mode to play with on the couch
- Comments are made on your launches (requires Amber sound pack)

Functions
- Switch [SA] turns the readout on or off and can be used to repeat the last voice readout.
- [ENTER] toggles between last and top launch height lists.
- [MENU] button opens an options "popup" with the following options:
- Clear data: Use +/- buttons to select one of the following:
* Clear [SESSION] data: Clears last launches, average and session flight counter.
* Clear [ALL] data: Clears all launch history and counters and resets all settings to default.
- Set launch target:
* Use flap stick (throttle) to set the launch target.
* Pull flaps all the way down for automatic mode that uses your average + specified%.
* Use [S1] to adjust the percent above average in automatic target mode.
- Enable simulator (SIM) mode to play.
* While in the [MENU] popup, changing switch [SA] toggles SIM mode on or off
* In SIM mode:
- flaps set altitude
- elevator sets climb rate
- Rudder and ailerons both set g forces

NEW: Use units from the radio's settings in OpenTX 2.1 and above.
See comments in the file for enabling this feature.


SIM mode NOTES:
A launch is determined by a climb rate above the threshold for a defined period so to simulate a launch you need to have continued positive climb.


This script should work with all S.Port altimeters.

If you are using a BTOA with the special s.Port firmware, you get the following:
- G force readings
- Low peak voltage monitoring (output as VFAS)
- Temperature
- Extra high climb rate capability

Get more information on the BTOA here: http://www.bluetoothopenaltimeter.com.


The FrSky high precision altimeter may have a maximum climb rate of around 10m/s.

Rename the attachment to a telem.lua file of choice and enjoy!

Please let me know if you have any feedback or comments.

UPDATE: This script has now been tested on OpenTX Version 2.0.15, 2.0.17 and 2.1.0. Please let me know if you have any problems now!


If you have other scripts in the folder, they can take up some memory and prevent this one from running (even without viewing them), so if you get a script error, please remove all other scripts and try again.
extremewing is online now Find More Posts by extremewing
RCG Plus Member
Last edited by extremewing; Jul 31, 2015 at 02:15 AM.
Reply With Quote
Sign up now
to remove ads between posts
Old Jul 26, 2015, 09:09 PM
extremewing is online now
Find More Posts by extremewing
A different attitude to RC
extremewing's Avatar
Draper, Utah
Joined Sep 2008
3,328 Posts
Some screenshots!
extremewing is online now Find More Posts by extremewing
RCG Plus Member
Last edited by extremewing; Jul 28, 2015 at 08:56 PM.
Reply With Quote
Old Jul 27, 2015, 12:08 AM
cgmoth is offline
Find More Posts by cgmoth
Clif Motheral
cgmoth's Avatar
United States, CA, Susanville
Joined Nov 2013
85 Posts
Launch Master

Thanks for doing this Adrian! I've been using Nigel's script since you directed me to it and it's great, but this version looks much more robust. Can't wait to give it a go. I've already got it loaded up and hope to give it a try tomorrow after work. I'll let you know how it goes.

Clif
cgmoth is offline Find More Posts by cgmoth
Reply With Quote
Old Jul 27, 2015, 12:11 AM
extremewing is online now
Find More Posts by extremewing
A different attitude to RC
extremewing's Avatar
Draper, Utah
Joined Sep 2008
3,328 Posts
Clif, try out the simulator mode!

Press menu then change switch SA then press enter. Throttle is altitude and elevator climb (pull back and hold elevator to launch, setting altitude) and see what she says
extremewing is online now Find More Posts by extremewing
RCG Plus Member
Old Jul 27, 2015, 12:39 AM
cgmoth is offline
Find More Posts by cgmoth
Clif Motheral
cgmoth's Avatar
United States, CA, Susanville
Joined Nov 2013
85 Posts
So to get into simulator mode do you need to be hooked up to companion or can you do it with just the radio?
cgmoth is offline Find More Posts by cgmoth
Reply With Quote
Old Jul 27, 2015, 12:46 AM
extremewing is online now
Find More Posts by extremewing
A different attitude to RC
extremewing's Avatar
Draper, Utah
Joined Sep 2008
3,328 Posts
Just the radio, while running the script, press menu button and change SA position. Press enter to save. Last ltitude (big number) becomes inverse to indicate sim mode.
extremewing is online now Find More Posts by extremewing
RCG Plus Member
Old Jul 27, 2015, 12:53 AM
cgmoth is offline
Find More Posts by cgmoth
Clif Motheral
cgmoth's Avatar
United States, CA, Susanville
Joined Nov 2013
85 Posts
The script doesn't seem to be running. I loaded it on the SD card in the scripts file for the model. Do I need to do something else to get it to run?
cgmoth is offline Find More Posts by cgmoth
Reply With Quote
Old Jul 27, 2015, 03:28 AM
AlexxH is offline
Find More Posts by AlexxH
Registered User
United Kingdom, Hertfordshire
Joined Sep 2014
102 Posts
Quote:
Originally Posted by cgmoth View Post
The script doesn't seem to be running. I loaded it on the SD card in the scripts file for the model. Do I need to do something else to get it to run?
Did you rename it to the exact model name?
AlexxH is offline Find More Posts by AlexxH
Reply With Quote
Old Jul 27, 2015, 08:03 AM
frater is online now
Find More Posts by frater
Registered User
Joined Aug 2014
693 Posts
WAIT: IT's NECESSARY TO MODIFY SOMETHING BELOW THIS OR YOU CAN'T RUN IT ON 2.1.x!

Just looked at the code and it looks impressive and structured.
I've seen LUA-scripts fail because they took too much memory.
How is this script doing in practice?

Are you making a conversion to 2.1.x or do I need to do this myself?

EDIT:

I added some stuff to make it possible to run it on 2.1.x
As you can see it's not that much.
I did the same with Nigel's script and that worked....

I see you have a "bad launch" which makes Amber giggle...
Is that a really bad launch? If so, maybe you could add a "Next time a bit higher" ("/SOUNDS/en/nxttmhr.wav") for a reasonable launch that is just not good enough...

The sound "Mmmmm, you turn me on" could be used for a very very good launch ("/SOUNDS/en/turnon.wav")

It would makes it all a bit more dynamic.

Fully UNTESTED (hope to do that this evening)
Code:
--[[/*
    Launch Master for Taranis is Copyright (C) 2015 Adrian Dybwad

    This program is free software: you can redistribute it and/or modify
    it under the terms odf the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/--]]


--[[

    Thank you for downloading Launch Master for Taranis!

    This is a complete re-write of Nigel Sheffield's original launch height script: 
    http://www.rcgroups.com/forums/showthread.php?t=2237421

    Launch Master provides an advanced launch detector borrowed from the BTOA.
    It also implements the BTOA's zero offset mechanism to deal with any altimeter drift.


------------------------------------------------------------------------------
-- IMPORTANT: PLEASE READ THE FOLLOWING WARNING
------------------------------------------------------------------------------
-- If you use any GVAR's from flight modes six through nine, you must modify the options below
-- ALL GVAR's in flight modes six through nine will be OVERWRITTEN with data if you do not modify any options.
------------------------------------------------------------------------------

Features
- Uses GVAR's as a mini data store ** SEE WARNING ABOVE **
- Automatically adjusts base altitude with any altimeter drift
- Records and displays fourteen launches in two lists
- Records the best altitude over all launches
- Session data can be reset leaving the best launches list
- Launch target is automatically set - or choose your own
- SIM mode to play with on the couch
- Comments are made on your launches (requires Amber sound pack)

Functions
- Switch [SA] turns the readout on or off and can be used to repeat the last voice readout.
- [ENTER] toggles between last and top launch height lists.
- [MENU] button opens an options "popup" with the following options:
  - Clear data: Use +/- buttons to select one of the following:
   * Clear [SESSION] data: Clears last launches, average and session flight counter.
   * Clear [ALL] data: Clears all launch history and counters and resets all settings to default.
  - Set launch target:
   * Use flap stick (throttle) to set the launch target. 
   * Pull flaps all the way down for automatic mode that uses your average + specified%.
   * Use [S1] to adjust the percent above average in automatic target mode.
  - Enable simulator (SIM) mode to play.
   * While in the [MENU] popup, changing switch [SA] toggles SIM mode on or off
   * In SIM mode:
     - flaps set altitude
     - elevator sets climb rate
     - Rudder and ailerons both set g forces

    
    SIM mode NOTES:
    A launch is determined by a climb rate above the threshold   for a defined period so to simulate a launch you need to have continued positive climb.


    This script should work with all S.Port altimeters. 

    If you are using a BTOA with the special s.Port firmware, you get the following:
     - G force readings
     - Low peak voltage monitoring (output as VFAS)
     - Temperature
     - Extra high climb rate capability

    Get more information on the BTOA here: http://www.bluetoothopenaltimeter.com.
 

    The FrSky high precision altimeter may have a maximum climb rate of around 10m/s. 


--]]



------------------------------------------------------------------------------
--Customize the following settings by following the instructions for each one.
------------------------------------------------------------------------------


------------------------------------------------------------------------------
--DATA STORAGE IN GVARS
--This script uses two flight mode GVAR's to store data for each set of data (last and best lists)
--You can disable one of both of these storage locations (the script may not remember data or settings)
--
--By default:
--Flight modes 8 and 9 (INDEX 7 and 8) store BEST data and script settings
--Flight modes 6 and 7 (INDEX 5 and 6) store LAST data
------------------------------------------------------------------------------
local FM_BEST_DATA = 7 --Set this value to -1 to disable storing data in this (and 8) flight mode INDEX
local FM_LAST_DATA = 5 --Set this value to -1 to disable storing data in this (and 6) flight mode INDEX
------------------------------------------------------------------------------


------------------------------------------------------------------------------
--SOUNDS
--The following sounds from the AMBER sound pack are played for various events. 
--The sound file path will need to be correct and the sound file present
--Change them to suit your needs. 
------------------------------------------------------------------------------
LIMIT_EXCEEDED = "/SOUNDS/en/good.wav"
AMAZING_LAUNCH = "/SOUNDS/en/turnon.wav"
BEST_LAUNCH = "/SOUNDS/en/liketht.wav"
AVERAGE_LAUNCH = "/SOUNDS/en/nxttmhr.wav"
BAD_LAUNCH = "/SOUNDS/en/gglno.wav"
CLEAR_DATA = "/SOUNDS/en/reset.wav"
OFF = "/SOUNDS/en/off.wav"
------------------------------------------------------------------------------


------------------------------------------------------------------------------
--UNITS
--This setting should match what you have set in the radio's settings.
--It would be nice to get this from the radio within the script?
--Remove the "--" in front of the line you want 
--Don't forget to add "--" to the beginning of the other option not in use!
------------------------------------------------------------------------------
local METERS = "m"
local FEET = "ft"
local GRAVITY = "g"

local UNIT_ALT = FEET --use this for feet
local UNIT_ALT = METERS --use this for meters

local ALT_SPOKEN = 10
local SPEED_SPOKEN = 4
local G_SPOKEN = 18
if UNIT_ALT == METERS then 
  ALT_SPOKEN = 9
  SPEED_SPOKEN = 5
end

------------------------------------------------------------------------------


-- UNIT ----------------- 2.1.x -- 2.0.x
-- UNIT_RAW					0
-- UNIT_VOLTS				1		1
-- UNIT_AMPS				2		2
-- UNIT_MILLIAMPS			3		
-- UNIT_KTS					4		(14)
-- UNIT_METERS_PER_SECOND	5		3
-- UNIT_FEET_PER_SECOND		6
-- UNIT_KMH					7		14
-- UNIT_MPH					8		10
-- UNIT_METERS				9		6
-- UNIT_FEET				10		(6)
-- UNIT_CELSIUS				11		7
-- UNIT_FAHRENHEIT			12		(7)
-- UNIT_PERCENT				13		8
-- UNIT_MAH					14
-- UNIT_WATTS				15		11
-- UNIT_DBM					16		12
-- UNIT_RPMS				17		18
-- UNIT_G					18		19
-- UNIT_DEGREE				19		7
-- UNIT_MILLILITERS			20
-- UNIT_FLOZ				21
-- UNIT_HOURS				22		15
-- UNIT_MINUTES				23		16
-- UNIT_SECONDS				24		17

-- UNIT_FIRST_VIRTUAL		25
-- UNIT_CELLS				26
-- UNIT_FIRST_VIRTUAL		27
-- UNIT_DATETIME			28
-- UNIT_GPS					29
-- UNIT_GPS_LONGITUDE		30
-- UNIT_GPS_LATITUDE		31
-- UNIT_GPS_LONGITUDE_EW	32
-- UNIT_GPS_LATITUDE_NS		33
-- UNIT_DATETIME_YEAR		34
-- UNIT_DATETIME_DAY_MONTH	35
-- UNIT_DATETIME_HOUR_MIN	36
-- UNIT_DATETIME_SEC		37








----------------------------------------------------------------------------------------------------------
-- WAIT: IT's NOT NECESSARY TO MODIFY ANYTHING BELOW THIS OR YOU RISK BREAKING THE SCRIPT!
-- If you know what you are doing or want to experiment, feel free to try!
-- You may post comments or questions on the RCGroups thread
----------------------------------------------------------------------------------------------------------








local version = "1.03"
local ver = "Launch Master V"

local audioOn = 0
local simOn = 0



local alt_id = getTelemetryId("Alt")
local vario_id = getTelemetryId("VSpd")
local mode_id =  getFieldInfo("sa").id
local g_x_id =  getFieldInfo("accx").id
local g_y_id =  getFieldInfo("accy").id
local g_z_id =  getFieldInfo("accz").id




-- Data format:
-- First three fields describe the data
-- Field one is bit lengths
-- To increase resolution, the second field is a scale value (storedValue = value * scale) OR (readValue = stored / scale)
-- Field three is the length of the storage part
-- Field 4 is the length of the array that the data consists of
-- Fifth and on is the data itself

local BIT_PACKING_LIMIT = 21 -- The largest number we can store in the dual GVAR system
local META_LENGTH = 4 -- The length of positions taken up in the data by meta info

local INDEX_SETTINGS = 8 -- zero based GVAR position to use for settings

local BIT_LENGTH_INDEX = 1 -- position in data structure that contains bit length data
local SCALE_INDEX = 2 -- position in data structure that contains scale data
local STORAGE_LENGTH_INDEX = 3 -- position in data structure that contains the length of the data part of the array
local DATA_LENGTH_INDEX = 4 -- The number of elements in each data item


local bestData = { {9,6,6}, {3,1,1}, 8, 3, {1,0,0}, {2,0,0}, {3,0,0}, {4,0,0}, {5,0,0}, {6,0,0}, {7,0,0}, {8,0,0} }
local lastData = { {9,6,6}, {3,1,1}, 8, 3, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0} }

local mainSettings = { {15,5,1}, {1,1,1}, 1, 3, {0,0,0} }
local auxSettings = { {9, 6, 6}, {1,1,1}, 1, 3, {0,0,0} }

local altHistory = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }
local altHistoryIndex = 0

local ABOVE_AVERAGE_DEFAULT = 10


local maxClimb = 0
local maxG = 0
local maxClimbValue = 0
local maxHeight = 0
local launchHeight = 0
local launchWindowEndHeight = 0
local launchWindowCount = 0
local launchCount = 0
local launched = 0

local INTERVAL = 100 -- Milli seconds: The rate at which we update the launch detector
local LAUNCH_CLIMB_THRESHOLD = 3 -- meters/second
local LAUNCH_CLIMB_TIME = 1500 -- Milli seconds
local LAUNCH_WINDOW_TIME = 3500 -- Milli seconds
local LAUNCH_SEEKBACK_SAMPLES = 20
--local LAND_DETECTOR_TRIGGER_HEIGHT = 8 -- meters
local LAUNCH_DETECTOR_REARM_HEIGHT = 8 -- meters



local g_x = 0
local g_y = 0
local g_z = 0
local g_xMax = 0
local g_yMax = 0
local g_zMax = 0
local currentHeight = 0
local currentVario = 0
local currentG = 0
local average = 0
local baseAlt = 0

local startup = 0
local comment = ""

-- Main settings
local TOTAL_LAUNCHES = 1 --Setting index for launches total since last clear all data
local LIMIT_SETTING = 2 -- Your target launch height setting
local SHOW_LAST = 3 -- Sow last to best launches

-- Aux settings
local ABOVE_AVERAGE = 4 -- Percent to add to the average to make up the target launch height
local NUM_OVER_LIMIT = 5 -- Number of launches that are over the target height
local LAUNCH_NUM = 6 -- Launches since last clearing of session data

local ALT_INDEX = 1
local VARIO_INDEX = 2
local G_INDEX = 3

local UNIT_VARIO = "m/s" --not converted
local UNIT_VARIO_1 = METERS --not converted
local UNIT_VARIO_2 = "/s" --not converted
local UNIT_ACCEL = GRAVITY

local UNIT_CONVERSION = 3.28125   -- That's the value used in OpenTX  (105 / 32)
if UNIT_ALT == METERS then 
  UNIT_CONVERSION = 1
end

local function getTelemetryId(name)
  field=getFieldInfo(name)
  if field then
    return field.id
  else
    return -1
  end
end

-----------------------------------------------------------------------------
--Checks for a valid number for a GVAR
--Returns the number or zero if invalid
--Not used at the moment, reset data instead?
-----------------------------------------------------------------------------
local function checkValue(val)
-- Not sure we need this with the clear data function
  --Checks if a value is in a good range
  --Sometimes a GVAR returns a high value when not yet set?
  --if val > -1025 and val < 1025 then
  --values between -1024 and 1024 are OK.
    return val
  --else
  --All others are 0.
  --  return 0
  --end
end

-----------------------------------------------------------------------------
-- Helper function to retrieve data from GVAR's
-----------------------------------------------------------------------------
local function getGlobalValue(index, slot)
  return model.getGlobalVariable(index, slot) --checkValue()
end

-----------------------------------------------------------------------------
-- Helper function to save data in GVAR's
-----------------------------------------------------------------------------
local function setGlobalValue(index, slot, value)
  model.setGlobalVariable(index, slot, value)
end



-----------------------------------------------------------------------------
-- helper to get the data at a zero based index
-----------------------------------------------------------------------------
local function getData(data, index)
  return data[META_LENGTH+index+1]
end


-----------------------------------------------------------------------------
-- helper to set the values at a zero based index
-----------------------------------------------------------------------------
local function setData(data, value, index)
  data[META_LENGTH+index+1] = value
end
-----------------------------------------------------------------------------
-- helper to set the values at a zero based index
-----------------------------------------------------------------------------
local function setDataAtPosition(data, value, index, position)
  data[META_LENGTH+index+1][position] = value
end


-----------------------------------------------------------------------------
-- Reads dual GVAR values and fills an array with the original data
-----------------------------------------------------------------------------
local size = 0
local packedValue = 0
local unpackedValue = 0
local currentBitPosition = 0

local function readData(data, indexFrom, indexTo, type)
--[[
--]]
  packedValue = ((getGlobalValue(indexFrom, type)+1024) * 2047) + (getGlobalValue(indexFrom, type+1)+1024)
  --Extract values
  currentBitPosition = 0

  for i = data[DATA_LENGTH_INDEX], 1, -1 do
    size = data[BIT_LENGTH_INDEX][i]
    unpackedValue = 0
    unpackedValue = bit32.rshift (packedValue, currentBitPosition)
    unpackedValue = bit32.lshift (unpackedValue, 32-size)
    unpackedValue = bit32.rshift (unpackedValue, 32-size)
    data[indexTo + META_LENGTH + 1][i] = unpackedValue / data[SCALE_INDEX][i]
    currentBitPosition = currentBitPosition + size
  end
end

local gVar1 = 0
local gVar2 = 0
local copy = 0
-----------------------------------------------------------------------------
-- An implementation if a data store using GVAR's to store the data
-----------------------------------------------------------------------------
local function storeData(data, fromIndex, toIndex, type)
--[[
--]]
  --Ensure the storage location is enabled
  if (type > -1) then

    -- Packs a number array into a single large number
    packedValue = 0
    currentBitPosition = 0
    for i = data[DATA_LENGTH_INDEX], 1, -1 do
      --Ensure the max values are not exceeded
      --If so, set it to the max value
      size = data[BIT_LENGTH_INDEX][i]
      copy = data[META_LENGTH+fromIndex+1][i] * data[SCALE_INDEX][i]
      if (copy > (2^ size)-1) then
        copy = (2^ size)-1
      end
      copy = bit32.lshift(copy, 32 - size)
      copy = bit32.rshift(copy, 32 - size - currentBitPosition)
      packedValue = packedValue + copy
      currentBitPosition = currentBitPosition + size
    end

    --Enforce BIT_PACKING_LIMIT since this is the largest value we can save
    packedValue = bit32.lshift(packedValue, 32 - BIT_PACKING_LIMIT)
    packedValue = bit32.rshift(packedValue, 32 - BIT_PACKING_LIMIT)

    --extract two numbers to store in GVARs
    gVar1 = (math.floor(packedValue / 2047))
    gVar2 = (packedValue - (gVar1 * 2047))

    setGlobalValue(toIndex, type, gVar1 - 1024)
    setGlobalValue(toIndex, type+1, gVar2 - 1024)
  end
end


-----------------------------------------------------------------------------
-- Helper function to get altitude from a particular index in lastData
-----------------------------------------------------------------------------
local function getAlt(index)
  return getData(lastData, index)[ALT_INDEX]
end

-----------------------------------------------------------------------------
-- Helper function to get vario from a particular index in lastData
-----------------------------------------------------------------------------
local function getVario(index)
  return getData(lastData, index)[VARIO_INDEX]
end

-----------------------------------------------------------------------------
-- Helper function to get G forces from a particular index in lastData
-----------------------------------------------------------------------------
local function getG(index)
  return getData(lastData, index)[G_INDEX]
end

-----------------------------------------------------------------------------
-- Helper function to get a particular setting
-----------------------------------------------------------------------------
local function getSetting(setting)

  if (setting < 4) then
    return getData(mainSettings, 0)[setting]
  end
    
  return getData(auxSettings, 0)[setting - 3]

end

-----------------------------------------------------------------------------
-- Resets state tracking variables
-----------------------------------------------------------------------------
local function resetLocalState()

  maxVario = 0
  maxG = 0
  launched = 0
  g_xMax = 0;
  g_yMax = 0;
  g_zMax = 0;
end


local launches = 0
-----------------------------------------------------------------------------
-- Sets the average from all launches in the lastData list
-----------------------------------------------------------------------------
local function setAverage()
--[[
--]]
  average = 0
  launches = 0

  for i = 0, lastData[STORAGE_LENGTH_INDEX] - 1 do
    if (getAlt(i) > 0) then
      launches = launches + 1
      average = average + getAlt(i)
    end
  end
  
  if (launches > 0) then
    average = average / launches
  end
end


-----------------------------------------------------------------------------
-- Announces the launch results
-----------------------------------------------------------------------------
local function announce()
-- TODO: add the launchWindowEndHeight
-- TODO: add the maxHeight to the readout - periodically if the height is increased
  if (startup == -1) then
    playFile(comment)
    if getAlt(0) > 0 then
      playNumber( getAlt(0)*10, ALT_SPOKEN, PREC1 ) 
      playNumber( getVario(0)*10, SPEED_SPOKEN, PREC1 ) 
      if (getG(0) > 0) then
        playNumber( getG(0) * 10, G_SPOKEN, PREC1 ) 
      end
    end
  end
end


-----------------------------------------------------------------------------
-- Gets the launch limit by user preference
-----------------------------------------------------------------------------
local function getLimit(units)

  if (getSetting(LIMIT_SETTING) > 0) then
    return math.floor(getSetting(LIMIT_SETTING) * 1.5 * units * 10) / 10
  else
    return math.floor(((average * units * 10) * (100 + getSetting(ABOVE_AVERAGE))) / 100) / 10
  end
end

-----------------------------------------------------------------------------
-- Saves user preferences to GVAR's
-----------------------------------------------------------------------------
local function saveSettings() 

--[[
--]]
  setAverage()

  -- store the settings
  storeData(mainSettings, 0, INDEX_SETTINGS, FM_BEST_DATA)
  storeData(auxSettings, 0, INDEX_SETTINGS, FM_LAST_DATA)

  for i = 0, bestData[STORAGE_LENGTH_INDEX] - 1 do
    -- store best launches
    storeData(bestData, i, i, FM_BEST_DATA)
  end
  for i = 0, lastData[STORAGE_LENGTH_INDEX] - 1 do
    -- store last launches
    storeData(lastData, i, i, FM_LAST_DATA)
  end
end

-----------------------------------------------------------------------------
-- Helper function to set a particular setting
-----------------------------------------------------------------------------
local function setSetting(setting, value)
--[[
--]]
  if (setting == LIMIT_SETTING) then
    if (value <= 5) then
     value = 0
      setSetting(ABOVE_AVERAGE, ABOVE_AVERAGE_DEFAULT)
    end
      setSetting(NUM_OVER_LIMIT, 0)
  end

  if (setting == ABOVE_AVERAGE) then
      setSetting(NUM_OVER_LIMIT, 0)
  end

  if (setting < 4) then
    setDataAtPosition(mainSettings, value, 0, setting)
  else
    setDataAtPosition(auxSettings, value, 0, setting - 3)
  end

end


-----------------------------------------------------------------------------
-- Loads all launch data
-----------------------------------------------------------------------------
local function loadData()

--[[
--]]

  readData(mainSettings, INDEX_SETTINGS, 0, FM_BEST_DATA)
  readData(auxSettings, INDEX_SETTINGS, 0, FM_LAST_DATA)
    
  if (getSetting(ABOVE_AVERAGE) == 0) then
    setSetting(ABOVE_AVERAGE, ABOVE_AVERAGE_DEFAULT)
  end

  for i = 0, bestData[STORAGE_LENGTH_INDEX] - 1 do
    -- load best launches
    readData(bestData, i, i, FM_BEST_DATA)
  end
  for i = 0, lastData[STORAGE_LENGTH_INDEX] - 1 do
    -- load last launches
    readData(lastData, i, i, FM_LAST_DATA)
  end

  setAverage()

end


-----------------------------------------------------------------------------
-- Clears launch data stored in GVAR's
-----------------------------------------------------------------------------
local function clearData(switch)

--[[
--]]

  if (switch == 2) then

    for i=0, bestData[STORAGE_LENGTH_INDEX] - 1 do
      setData(bestData, {0,0,0}, i)
    end
    setSetting(TOTAL_LAUNCHES, 0)
    setSetting(LIMIT_SETTING, 0)
    setSetting(ABOVE_AVERAGE, ABOVE_AVERAGE_DEFAULT)

  end
    for i=0, lastData[STORAGE_LENGTH_INDEX] - 1 do
      setData(lastData, {0,0,0}, i)
    end
    setSetting(NUM_OVER_LIMIT, 0)
    setSetting(LAUNCH_NUM, 0)

    resetLocalState()
  --playTone(2000, 500, 100, 0, 100)

  playFile(CLEAR_DATA)

end


local bestIndex = 0
local i = 0

-----------------------------------------------------------------------------
-- Adds and sorts launch data to lists
-----------------------------------------------------------------------------
local function addLaunchData(values) 
--[[
--]]

  bestIndex = 0

  -- save LAST launches
  for i = (lastData[STORAGE_LENGTH_INDEX]-1), 1, -1 do
    setData(lastData, getData(lastData, i - 1), i)
  end
  setData(lastData, values, 0)

  -- save BEST launches
  i = bestData[STORAGE_LENGTH_INDEX]

  while i > 0 and values[ALT_INDEX] > getData(bestData, i - 1)[ALT_INDEX] do
    setData(bestData, getData(bestData, i - 1), i)
    setData(bestData, values, i - 1)
    bestIndex = i
    i = i - 1
  end
  
end

-----------------------------------------------------------------------------
-- Updates parameters after a launch detect
-----------------------------------------------------------------------------
local function commentOnLaunch()

  comment = ""

  if getAlt(0) < (getLimit(1) * 3) / 4 then
    comment = (BAD_LAUNCH)
  elseif getAlt(0) < (getLimit(1) * 7) / 8 then
      comment = (BEST_LAUNCH)
  elseif getAlt(0) >= (getLimit(1) * 4) / 3 then
      comment = (AMAZING_LAUNCH)
  elseif getAlt(0) >= getLimit(1) then
      comment = (BEST_LAUNCH)
  elseif bestIndex >= 0 and getAlt(0) >= (getLimit(1)*9)/10 then 
      comment = (LIMIT_EXCEEDED)
  end

  -- vocal announcement
  if audioOn == 1 then
    announce()
  end
end

-----------------------------------------------------------------------------
-- Sets things in motion after a launch detect
-----------------------------------------------------------------------------
local function setLaunched()

  setSetting(TOTAL_LAUNCHES, getSetting(TOTAL_LAUNCHES) + 1)
  setSetting(LAUNCH_NUM, getSetting(LAUNCH_NUM) + 1)


  addLaunchData({launchHeight, maxClimbValue, maxG})
  commentOnLaunch()


  if getAlt(0) >= getLimit(1) then
    setSetting(NUM_OVER_LIMIT, getSetting(NUM_OVER_LIMIT) + 1)
  end

  saveSettings()

end

local newBaseAlt = 0
local drift = 0
-----------------------------------------------------------------------------
--  This function tracks various height-related quantities, 
--  implementing the launch detectors, max height detector etc.
--  It is the main code from the BTOA's launch detector converted for use here
-----------------------------------------------------------------------------
local function updateHeightMonitor()

    altHistoryIndex = altHistoryIndex + 1
    altHistory[altHistoryIndex] = currentHeight
    if  (altHistoryIndex > LAUNCH_SEEKBACK_SAMPLES - 1) then
      altHistoryIndex = 0
    end

    if (currentVario > maxClimb) then 
      maxClimb = currentVario
    end

    if (launched == 0)
    then
      --if (launch_millis > 0 && currentHeight < LAND_DETECTOR_TRIGGER_HEIGHT) then
      --  duration = (millis() - launch_millis)/100
      --  launch_millis = 0
        --//Tell F3KM we have landed
      --  printMessage(AMP)
      --  Serial.print(duration)
      --  printMessage(STAR)
      --end
    --// We monitor the height data looking for a "launch". This is a number of samples that climb consistently at greater than a given rate.

      if (currentVario > LAUNCH_CLIMB_THRESHOLD) then
        launchCount = launchCount + 1
      else 
        launchCount = 0
      end

      if (launchCount >= math.floor(LAUNCH_CLIMB_TIME / INTERVAL))
      then
        --// we've just detected a launch - disable the launch detector
        launched = 1
        launchCount = 0
        maxClimbValue = maxClimb
        maxClimb = 0

        --// When we detect a launch we do a few things: we reset the base pressure to the highest pressure in the few seconds before the launch;
        --// we start a countdown which defines the "launch window"; we reset the maximum heights.
        --// -- reset base pressure
        newBaseAlt = currentHeight
        for i = LAUNCH_SEEKBACK_SAMPLES, 1, -1 do
            if (altHistory[i] < newBaseAlt) then
              newBaseAlt = altHistory[i]
            end
        end
--[[
--]]
        baseAlt = newBaseAlt
        --// -- time the launch window
        launchWindowCount = math.floor(LAUNCH_WINDOW_TIME / INTERVAL) + 1
        --// -- reset max heights
        maxHeight = currentHeight
        launchHeight = maxHeight
        launchWindowEndHeight = 0
      end
    else
      --// The launch detector is disabled after a launch, so that it can't retrigger in flight. It is reset by either the logger's altitude coming
      --// below a certain threshold, or a height output function being commanded by the user (on the basis that this should always happen on the
      --// ground - the latter is implemented to stop the logger getting stuck should the ground-level pressure change dramatically during a flight.)
      --// Here we check for the former.
  
      if (currentHeight < LAUNCH_DETECTOR_REARM_HEIGHT) then
        if (launched == 1) then 
    launched = 0
      g_xMax = 0;
      g_yMax = 0;
      g_zMax = 0;
    maxG = 0
  end
      end
      --// if we're in the launch window we need to track the maximum altitude.
      if (launchWindowCount > 0)
      then
        if (currentHeight > launchHeight) then 
    launchHeight = currentHeight
  end
        --// if this is the end of the launch window then we record the height
        if (launchWindowCount == 1) then
          launchWindowEndHeight = currentHeight
          setLaunched()
        end
        launchWindowCount = launchWindowCount - 1
--        if (launchWindowCount == 0) then
--        end
      end
      if (currentHeight > maxHeight) then 
        maxHeight = currentHeight
      end
    end
end


-----------------------------------------------------------------------------
-- Called as often as possible, 
-- Toggles the audio setting and plays last data if turned on
-----------------------------------------------------------------------------
local function checkAudio()
  if getValue(mode_id) < -100 and audioOn == 1 then 
    audioOn = 0
    playFile(OFF)
  elseif getValue(mode_id) > -100 and audioOn == 0 then
    audioOn = 1
    announce()
  end
end

-----------------------------------------------------------------------------
-- Called as often as possible, 
-- this function calls the height monitor at regular intervals
-----------------------------------------------------------------------------
local time = 0
local now = 0
local function checkState()

  if (simOn == 1) then
    currentHeight = (getValue("thr") + 1022) / 10
    currentVario = 0 - ((getValue("ele")) / 20)
    currentG = (getValue("ail") + getValue("rud") ) / 50
  else
    --get corrected altitude
    currentHeight = ( getValue(alt_id) - baseAlt )
    --get the vario (climb rate)
    currentVario = ( getValue(vario_id) )
    g_x = getValue(g_x_id)
    g_y = getValue(g_y_id)
    g_z = getValue(g_z_id)
    currentG = (math.sqrt((g_x * g_x) + (g_y * g_y) + (g_z * g_z)))
  end

  if g_x > g_xMax then
    g_xMax = g_x
  end
  if g_y > g_yMax then
    g_yMax = g_y
  end
  if g_z > g_zMax then
    g_zMax = g_z
  end

  if (currentG > maxG) then 
    maxG = currentG
  end

  if time == 0 then
    time = getTime()
  end
  now = getTime()
  if ((now - time)*10 > INTERVAL) then
    updateHeightMonitor()
    time = now
  end
end

-----------------------------------------------------------------------------
-- Called to initialize the script
-----------------------------------------------------------------------------
local function init()

  loadData()

end

-----------------------------------------------------------------------------
-- Called periodically from the radio
-----------------------------------------------------------------------------
local function background()

  checkState()
  checkAudio()

end


local leftcol = 36
local secondcol = 166
local lineheight = 7
local listtop = 16
local toprow = 10
local firstcol = 130
local firstcolwidth = 10
local secondcolwidth = 10
local bottomrow = 49-- +20

-----------------------------------------------------------------------------
-- When sending altitude in feet to the speech engine, 
-- the value in feet is rounded up so the number read does not match the screen
-- This function fixes that and is used wherever an altitude is displayed
-----------------------------------------------------------------------------
local function getAltToDisplay(alt, prec)
  if (UNIT_ALT == METERS) then
    return UNIT_CONVERSION * alt * prec
  end
  return math.floor((UNIT_CONVERSION * alt) + 0.5)
end


-----------------------------------------------------------------------------
-- Helper function to show a number in units and decimal places for the display
-----------------------------------------------------------------------------
local function showNumberInUnits(x, y, number, units, prec, attr)
  lcd.drawNumber(x, y, units * number * prec, attr)  
end

-----------------------------------------------------------------------------
-- Draws the "offset" vario units
-----------------------------------------------------------------------------
local function drawVarioUnits(x, y, param)
  lcd.drawText( x+1, y+6, UNIT_VARIO_2, param )
  lcd.drawText( x, y, UNIT_VARIO_1, param )
end

-----------------------------------------------------------------------------
-- Draws the layout lines and filled rectangles
-----------------------------------------------------------------------------
local function drawLayout()
--[[
--]]



--  lcd.drawLine( 0, 100, 0, 0, SOLID, 2 )
--  lcd.drawLine( 211, 100, 211, 0, SOLID, 2 )
  lcd.drawLine( leftcol-1, 100, leftcol-1, 0, SOLID, 2 )
  lcd.drawLine( secondcol-1, lineheight, secondcol-1, 63, SOLID, 2 )
--  lcd.drawLine(firstcol-1, 8, firstcol-1, 62, SOLID, 0)

  lcd.drawFilledRectangle( 0, 0, 212, 8, 0 )
  lcd.drawFilledRectangle( leftcol + 1, bottomrow, firstcol - 2, 14, 0 )
--[[

  --lcd.drawLine( 0, 63, 210, 63, SOLID, 2 )



  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )

--Hack to test memory by adding more lines

  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )

--
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )

--
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )

--
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )

--
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )

--
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
  lcd.drawLine(firstcol , 43, secondcol-1, 43, SOLID, 2 )
--]]
end

local above_avg = "% above avg"

-----------------------------------------------------------------------------
-- Draws the goals section
-----------------------------------------------------------------------------
local function drawGoals()
    
  if (getSetting(NUM_OVER_LIMIT) == 0) then
    if (getSetting(LIMIT_SETTING) == 0) then
      if (getLimit(1) == 0) then
        lcd.drawText(1, 1, "Launch goal is " .. getSetting(ABOVE_AVERAGE) .. above_avg, INVERS)
      return
      end
      lcd.drawText(1, 1, "" .. getSetting(ABOVE_AVERAGE) .. above_avg .. " is " .. getLimit(UNIT_CONVERSION) .. UNIT_ALT, INVERS)
      return
    end

    lcd.drawText(1, 1, "Launch goal is " .. getLimit(UNIT_CONVERSION) .. UNIT_ALT, INVERS)
    return
  end
    if (getSetting(LIMIT_SETTING) == 0) then
      lcd.drawText(1, 1, "" .. getSetting(NUM_OVER_LIMIT) .. "/" .. getSetting(LAUNCH_NUM) .. " " .. getSetting(ABOVE_AVERAGE) .. above_avg .. " now "..getLimit(UNIT_CONVERSION)..UNIT_ALT, INVERS)
      return
    end
    lcd.drawText(1, 1, "" .. getSetting(NUM_OVER_LIMIT) .. "/" .. getSetting(LAUNCH_NUM) .. " launches over " .. getLimit(UNIT_CONVERSION) .. UNIT_ALT, INVERS)
end

-----------------------------------------------------------------------------
-- Draws the goal settings
-----------------------------------------------------------------------------
local function drawGoalSettings()
--[[
--]]
   lcd.drawText(20,30,"Your launch goal is ", 0)

  if (getSetting(LIMIT_SETTING) == 0) then
    lcd.drawText(lcd.getLastPos(), 30, "avg+" .. getSetting(ABOVE_AVERAGE) .. "% (S1)", INVERS)
    return
  end
  showNumberInUnits(lcd.getLastPos(), 30, getLimit(1), UNIT_CONVERSION, 1, LEFT + INVERS )
  lcd.drawText(lcd.getLastPos(),30,UNIT_ALT .. " (flaps)", INVERS)

end


local p = 0
local r = 0
-----------------------------------------------------------------------------
-- Draws the current values section
-----------------------------------------------------------------------------
local function drawCurrent()
--[[
--]]
    p = 1
    r = DBLSIZE + INVERS
    if (UNIT_ALT == METERS) then
      p = 10
      r = r + PREC1
    end

    showNumberInUnits(secondcol-11, bottomrow, getAltToDisplay(currentHeight, p), 1, 1, r )
    lcd.drawText( lcd.getLastPos(), bottomrow + 1, UNIT_ALT, SMLSIZE + INVERS )

    showNumberInUnits(leftcol + 1, bottomrow, currentG, 1, 10, PREC1 + LEFT + DBLSIZE + INVERS )
    lcd.drawText(lcd.getLastPos(), bottomrow + 1, UNIT_ACCEL, SMLSIZE + INVERS)

    showNumberInUnits(leftcol + 60, bottomrow, currentVario, 1, 10, PREC1 + DBLSIZE + INVERS )
    drawVarioUnits(lcd.getLastPos(), bottomrow + 1, SMLSIZE + INVERS)


end

local l = ""
-----------------------------------------------------------------------------
-- Draws the last launch section
-----------------------------------------------------------------------------
local function drawLast()
  l = "last"
  if (simOn == 1) then
    l = "simulator"
  end
    lcd.drawText(firstcol + 2, lineheight+1, l, SMLSIZE+INVERS)

    p = 1
    r = XXLSIZE
    if (simOn == 1) then
      r = r + INVERS
    end
  if (UNIT_ALT == METERS) then
    p = 10
    r = r + PREC1
    if (simOn == 1) then
      r = r + INVERS
    end
  end

  lcd.drawNumber(firstcol + 2, toprow, getAltToDisplay(getAlt(0), p), r)

  lcd.drawNumber(firstcol + 1, toprow + lineheight - 1, getVario(0), DBLSIZE+LEFT)
  drawVarioUnits(lcd.getLastPos(), toprow + lineheight - 1, SMLSIZE)

  showNumberInUnits(firstcol + 5, toprow + lineheight + 16, getG(0), 10, 1, MIDSIZE+PREC1+LEFT )
  lcd.drawText( lcd.getLastPos(), toprow + lineheight + 20, UNIT_ACCEL, SMLSIZE)

end

local offset = 0
local values = {0,0,0}
-----------------------------------------------------------------------------
-- Draws the launch list section
-----------------------------------------------------------------------------
local function drawList(data, title, num)
--[[
--]]
  lcd.drawText(secondcol+0, 1, title .. (num), SMLSIZE+INVERS)
  lcd.drawText(secondcol+1, lineheight+1, UNIT_ALT .. "  " .. UNIT_VARIO .. "  " .. UNIT_ACCEL .. " ", SMLSIZE+INVERS)
      p = 1
      r = SMLSIZE + LEFT
    if (UNIT_ALT == METERS) then
      p = 10
      r = r + PREC1
    end
  for i = 0, (data[STORAGE_LENGTH_INDEX] - 1) do
    offset = lineheight*(i)
    values = getData(data, i)
    if (values[ALT_INDEX] > 0) then
      showNumberInUnits(secondcol+2, listtop + offset, getAltToDisplay(values[ALT_INDEX], p), 1, 1, r )
      lcd.drawNumber(197, listtop + offset, values[VARIO_INDEX], SMLSIZE)
      lcd.drawNumber(210, listtop + offset, values[G_INDEX], SMLSIZE)
    end
  end
end

-----------------------------------------------------------------------------
-- Helper function to draw the desired launch list
-----------------------------------------------------------------------------
local function drawLists()
  if getSetting(SHOW_LAST) == 0 then
    drawList(bestData, "TOP/", getSetting(TOTAL_LAUNCHES))
    return
  end
  drawList(lastData, "LAST/", getSetting(LAUNCH_NUM))
end

-----------------------------------------------------------------------------
-- Draws the best launch section
-----------------------------------------------------------------------------
local function drawBest()
--[[
--]]
  lcd.drawText( 2, 9, "* best *", SMLSIZE+INVERS)

    p = 1
    r = MIDSIZE+LEFT
  if (UNIT_ALT == METERS) then
    p = 10
    r = r + PREC1
  end
  
  showNumberInUnits(3, 18, getAltToDisplay(getData(bestData, 0)[ALT_INDEX], p), 1, 1, r )
  lcd.drawText( lcd.getLastPos(), 19, UNIT_ALT, SMLSIZE )

  lcd.drawNumber(1, 31, getData(bestData, 0)[VARIO_INDEX], LEFT)
  drawVarioUnits(lcd.getLastPos(), 30, SMLSIZE)

  lcd.drawNumber(leftcol-7, 30, getData(bestData, 0)[G_INDEX], SMLSIZE)
  lcd.drawText( lcd.getLastPos(), 30, GRAVITY, SMLSIZE )
end

-----------------------------------------------------------------------------
-- Draws the average section
-----------------------------------------------------------------------------
local function drawAverage()
  lcd.drawText(1, 45, "average", SMLSIZE + INVERS)  
  showNumberInUnits(2, 55, average, UNIT_CONVERSION, 10, PREC1+LEFT )
  lcd.drawText( lcd.getLastPos(), 54, UNIT_ALT, SMLSIZE )
end

local msg = ""
-----------------------------------------------------------------------------
-- Draws the clear data options
-----------------------------------------------------------------------------
local function drawClearData(swtch)

    if swtch == 0 then
      lcd.drawText(20,20,"Use +/- to choose data to clear", SMLSIZE)
      return
    elseif swtch == 1 then
msg = "[SESSION]"
    else
msg = "[ALL]"
    end
      lcd.drawText(20,20,"WARNING: [ENTER] CLEARS " .. msg .. " DATA", SMLSIZE + INVERS)

end

-----------------------------------------------------------------------------
-- Draws the SIM mode settings
-----------------------------------------------------------------------------
local function drawSimModeSetting()
--[[
--]]
  if simOn == 1 then
    lcd.drawText(57,43,"SIM ON (SA)", SMLSIZE + INVERS)
  else
    lcd.drawText(57,43,"SIM OFF (SA)", SMLSIZE + INVERS)
  end
end

  local debugheight = 50
-----------------------------------------------------------------------------
-- Draws debug info when needed
-----------------------------------------------------------------------------
local function drawDebug()

--  lcd.drawNumber(0, debugheight, INTERVAL, SMLSIZE + LEFT)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, getAltToDisplay(currentHeight, 10), PREC1 + SMLSIZE + LEFT+INVERS)  
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, launchNum, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+5, debugheight, launchCount, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, (LAUNCH_CLIMB_TIME / INTERVAL), SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+5, debugheight, currentVario, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, LAUNCH_CLIMB_THRESHOLD, SMLSIZE + LEFT+INVERS)

--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, launched, SMLSIZE + LEFT)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, maxClimb, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, getAltToDisplay(launchHeight, 10), PREC1 + SMLSIZE + LEFT)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, getAltToDisplay(launchWindowEndHeight, 10), PREC1 + SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, getAltToDisplay(maxHeight, 10), PREC1 + SMLSIZE + LEFT)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, period, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, INTERVAL, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, LIMIT, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, getLimit(), SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, lastAlt, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, getn(lastData), SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, average, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, dataLength, SMLSIZE + LEFT+INVERS)

--  packAndStoreNumbersA({40000,2,3,4,5},{10,2,2,3,3},5,0, FM_LAST_DATA)
--  local nums = unpackAndGetNumbersA({10,2,2,3,3},5,0, FM_LAST_DATA)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, pn, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, nums[1], SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, nums[2], SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, nums[3], SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, bit32max, SMLSIZE + LEFT+INVERS)

--    auxSettings[1] = 1--altTotal
--    auxSettings[2] = 2--launchNum
--    auxSettings[3] = 3--ABOVE_AVERAGE
--    mainSettings[1] = 4--totLaunch
--    mainSettings[2] = 3--LIMIT_SETTING
--    mainSettings[3] = 2--launchK
--    mainSettings[4] = 1--showlast

--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, altTotal, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, ABOVE_AVERAGE, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, launchNum, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, numOverLimit, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, totLaunch, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, LIMIT_SETTING, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, launchK, SMLSIZE + LEFT+INVERS)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, showlast, SMLSIZE + LEFT+INVERS)

--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, storedNum, SMLSIZE + LEFT)
--  lcd.drawNumber(lcd.getLastPos()+2, debugheight, packedNumber, SMLSIZE + LEFT+INVERS)

end

-----------------------------------------------------------------------------
-- Variables used only by the run function
-----------------------------------------------------------------------------
local result = 0
local swtch = 0
local ispopup = 0
local thrPosition = 0
local modePosition = 0
local s1Position = 0

-----------------------------------------------------------------------------
-- Called periodically when the script is visible. 
-- This function draws everything on the screen
-----------------------------------------------------------------------------
local function run(event)

--startup = -1
  if event == EVT_ENTER_BREAK and ispopup == 0 and startup == -1 then
    if getSetting(SHOW_LAST) == 0 then
      setSetting(SHOW_LAST, 1)
    else
      setSetting(SHOW_LAST, 0)
    end
    saveSettings()
  end

  if ispopup == 0 and startup == -1 then 
    background()
	lcd.clear()

    drawLayout()
    drawLast()
    drawGoals()
    drawCurrent()
    drawBest()
    drawLists()
    drawAverage()
    --drawDebug()

  end

  if (event == EVT_PLUS_BREAK or event == EVT_MINUS_BREAK or event == EVT_PAGE_BREAK) then
    startup = -1
--return 1
  end

  if (event == EVT_MENU_BREAK) then
    startup = -1
    if (ispopup == 1) then
      ispopup = 0
    else
      ispopup = 1
      swtch = 0
      thrPosition = math.floor( (getValue("thr") + 1224) / 36)
      modePosition = getValue(mode_id)
      s1Position = math.floor( (getValue("s1") + 1224) / 36 )
    end
  end

  if (startup > -1) then 
--[[
--]]
    result = popupInput("", event, swtch, -1, 1)
    lcd.drawScreenTitle(ver .. " " .. version,1,1)
    lcd.lock()
     lcd.drawText(20,20,"TIP: The [MENU] button shows options", SMLSIZE)
     lcd.drawText(25,30,"[ENTER] switches LAST or TOP lists", SMLSIZE)
    if (startup == 0) then
      startup = getTime()
    elseif (getTime() - startup > 700) then
      startup = -1
    end 
      if result == "OK" then
      startup = -1
          return 0 -- ignore
      elseif result == "CANCEL" then
      startup = -1
          return 1 -- exit program
      else
          return 0
      end
  elseif ispopup == 1 then 


    result = popupInput("", event, swtch, 0, 2)
    lcd.drawScreenTitle(ver .. " " .. version,1,1)
    lcd.lock()

    if (getValue(mode_id) == modePosition) then
    else
      modePosition = getValue(mode_id)
        if (simOn == 1) then
          simOn = 0
        else 
          simOn = 1
        end 
    end

    -- set ABOVE_AVERAGE with S1 if S1 is moved
    if (math.floor( (getValue("s1") + 1224) / 36 ) == s1Position) then
    else
      s1Position = -1
      setSetting(ABOVE_AVERAGE, math.floor( (getValue("s1") + 1224) / 36 ))
    end

    -- set LIMIT with throttle if throttle is moved
    if (math.floor( (getValue("thr") + 1224) / 36) == thrPosition) then
    else
      thrPosition = -1
      setSetting(LIMIT_SETTING, math.floor( (getValue("thr") + 1224) / 36 ))
    end

    drawGoalSettings()
    drawClearData(swtch)
    drawSimModeSetting()

      if result == "OK" then
        if (swtch > 0) then
          clearData(swtch)
        end
 
        saveSettings()
        ispopup = 0
        return 0 -- ignore
      elseif result == "CANCEL" then
        loadData()
        ispopup = 0
        return 1 -- exit program
      else
        swtch = result   -- it is number
        return 0
      end
  end

end

return { init=init, background=background, run=run }
frater is online now Find More Posts by frater
Last edited by frater; Jul 27, 2015 at 11:16 AM.
Reply With Quote
Old Jul 27, 2015, 10:26 AM
extremewing is online now
Find More Posts by extremewing
A different attitude to RC
extremewing's Avatar
Draper, Utah
Joined Sep 2008
3,328 Posts
I had to do a lot of work to keep the memory use in check while fitting everything in.

If you test your changes, I will add them to the main version...
extremewing is online now Find More Posts by extremewing
RCG Plus Member
Old Jul 27, 2015, 12:39 PM
frater is online now
Find More Posts by frater
Registered User
Joined Aug 2014
693 Posts
Quote:
Originally Posted by extremewing View Post
I had to do a lot of work to keep the memory use in check while fitting everything in.

If you test your changes, I will add them to the main version...
I did a bench test with that script and. alas, I'm getting a blank screen.
I wouldn't know if it is doing anything, but my guess is it doesn't/
You could still do a comparison between your script and mine to see what I think should change...

I can't do anything more as I can't tell if there's something wrong with the code or with the environment. You could make sensible comments on github and help the devs with getting 2.1.x mature.

I really hope you upgrade to 2.1.x
There is no future in 2.0.x
frater is online now Find More Posts by frater
Reply With Quote
Old Jul 27, 2015, 01:42 PM
extremewing is online now
Find More Posts by extremewing
A different attitude to RC
extremewing's Avatar
Draper, Utah
Joined Sep 2008
3,328 Posts
I did just upgrade and will post as soon as I get mine working
extremewing is online now Find More Posts by extremewing
RCG Plus Member
Old Jul 27, 2015, 02:54 PM
frater is online now
Find More Posts by frater
Registered User
Joined Aug 2014
693 Posts
Quote:
Originally Posted by extremewing View Post
i did just upgrade and will post as soon as i get mine working

Looking forward to it...
frater is online now Find More Posts by frater
Reply With Quote
Old Jul 27, 2015, 04:53 PM
nigelsheffield is online now
Find More Posts by nigelsheffield
Registered User
United Kingdom, Horbury
Joined Oct 2007
6,315 Posts
Not had much time to test anything ,
But 2.0 and 2.1 use different field names so script needs to be written for one or the other.
Hth.
nigelsheffield is online now Find More Posts by nigelsheffield
Reply With Quote
Old Jul 27, 2015, 05:16 PM
kelchm is online now
Find More Posts by kelchm
Registered User
kelchm's Avatar
United States, PA, Shippensburg
Joined Jan 2015
163 Posts
Nice work! Really looking forward to trying this out.

I haven't looked into it at all yet, but it would be great to use the file system access in OpenTX 2.1 rather than using GVARs. You can see some discussion on the subject here.

May dig into that some this week if I have time. PS, throw it up on github so others can easily contribute!
kelchm is online now Find More Posts by kelchm
RCG Plus Member
Reply With Quote


Thread Tools

Similar Threads
Category Thread Thread Starter Forum Replies Last Post
Data F3K Master - a talking Discus Launch Glider competition timer and contest director. extremewing Hand Launch 1078 Today 12:23 AM
Help! Taranis Master 9Xr slave riblit Radios 3 Apr 03, 2014 09:18 PM
Sold Radio Carbon Arts - Hand Launch Master Class #1 John Walter Aircraft - Sailplanes (FS/W) 5 Jun 06, 2012 06:12 PM
Sold Radio Carbon Art DVDs - Hand Launch Master Class 1,2,3 & Thermal Secrets apex Aircraft - Sailplanes (FS/W) 3 Jun 30, 2011 10:08 PM