+commit 15ae97fbdb4e75a74ea2e716194661d19dec46ff
+Merge: ac7be4a 1216c0c
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 18:11:01 2016 -0600
+
+ Merge branch 'master' into branch-1.6
+
+commit 1216c0ccece4ca1492967a341c5d01e9e5068ed8
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 6 17:10:14 2016 -0700
+
+ Ignore some built files for 1.6.3
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ac7be4a40df88ee3a0992e041635e4ac4cf5ac48
+Merge: b53c78e ce4c8a8
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 17:59:39 2016 -0600
+
+ Merge branch 'master' into branch-1.6
+
+commit ce4c8a8ad57515e851207b0a82f3af791bb30d3e
+Merge: aa9630c 320e312
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 17:49:30 2016 -0600
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit aa9630c30ee09bf358e77bf47ed0815a19237fca
+Author: Bdale Garbee <bdale@gag.com>
+Date: Fri May 6 17:49:09 2016 -0600
+
+ add beep to TeleMega turnon script
+
+commit 320e312db36fb6519a0bb1530d79595af18cdc86
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri May 6 16:46:57 2016 -0700
+
+ windows: Change install to look for browser in a different place
+
+ The windows registry is a mystery.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0081f7ba6fc9f1e4484d3e291fd30065ad5b620
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu May 5 02:25:52 2016 -0700
+
+ altoslib: Fix map preloading callbacks, run in separate thread
+
+ The map storage and tile callbacks were muddled together. Create
+ clearly separate states for map data and have status updates be
+ delivered when registering for new status events so that registration
+ is sufficient to track the state without an explicit call to get the
+ current state.
+
+ Run the map tile creation in a separate thread so that even checking
+ status of files on disk runs out of the UI thread.
+
+ These fixes serve to make the pacifier update more smoothly, and also
+ not over/under count tile loading so that the loading actually
+ completes when all of the tiles are loaded.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 13179f614a99cad3016832ac1b365eaa4208c10f
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 4 23:56:44 2016 -0700
+
+ micropeak: Change order of windows install so that java detect works
+
+ I have no idea why this matters, but if you run the FTDI script before
+ trying to detect java, then the javaw.exe program isn't found and java
+ detection fails.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 85191fe911a5ea4af384bff9b2ed9986679cd9fd
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 4 21:13:31 2016 -0700
+
+ doc: 1.6.3 release notes note TeleBT rts/cts and TM 2.0 monitor idle fixes
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 541996f95f9e26299618dbb79e723b82a52afd31
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed May 4 21:12:46 2016 -0700
+
+ doc: Update AltosDroid chapter for 1.6.3
+
+ New menu structure, idle mode and frequency configuration
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b540f6f5b034f33b8e1d1c3b91e2403a56479caa
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 2 16:19:39 2016 -0700
+
+ altos: Make sure AO_MMA655X_INVERT is declared where needed
+
+ Add #define AO_MMA655X_INVERT 0 to existing products which didn't
+ declare it at all. This will make sure the value is set correctly for
+ each new board.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0b0b359cbce6b818257b44b2a6aee0edcbaee40d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon May 2 16:13:53 2016 -0700
+
+ altoslib: Deal with TeleMetrum v2.0 MMA6555 being inverted
+
+ Dumping the MMA655X data with the 'A' command provides the raw sensor
+ value. On TM v2.0 boards, the sensor is inverted, and all of the
+ firmware uses the inverted value except for the 'dump the raw data'
+ command. As a result, MonitorIdle was using the un-inverted value and
+ displaying mystic values.
+
+ I've fixed this in the ground station code by checking the product
+ name and conditionally inverting the value (4095 - value) for
+ TeleMetrum v2.0 products. Unknown products will generate a warning
+ dialog on AltosUI so we'll catch places where we've failed to add a
+ new product name.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1a797f5fd5d25ba635fd79ad7604763253caabf2
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:38:42 2016 -0700
+
+ publish AltosDroid in keithp-fat target
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 59466c1c2dbf95c427c2bb52304049eaac4d124f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:37:05 2016 -0700
+
+ altoslib: Flush during set_state. Don't store listener state.
+
+ The listener state wasn't used anyways, so don't bother storing
+ it. Also, flush the state during set_state, which actually causes the
+ state to be written out.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4219fd7720caeec196bf6cb1b4cf78c8fadaf3cd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:33:25 2016 -0700
+
+ altoslib: Correct stats for flights without a real landing
+
+ The landing time was miscomputed when the flight ended without
+ entering the landed state, as when the recording terminates at
+ apogee.
+
+ This led to an uncomputed average boost accel, so that is now checked
+ separately from max accel (which is done over the whole flight, not
+ just boost).
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9734f1198429dc8939eebf48b6e6acc1cef96485
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 18:30:16 2016 -0700
+
+ altosdroid: max height is a height, not a speed
+
+ Was using the wrong units in the flight tab
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7695da327ff8861a858b6695f4849fa1399548d8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 30 08:46:52 2016 -0700
+
+ Revert "altos/stm: Run scheduler code on interrupt stack"
+
+ This reverts commit 6a9546413d6a236c010e806b50506d870961d074.
+
+ This causes the device to stop reliably handling interrupts.
+
+commit 7db1cba64a2f6c80c5fe6e3073a0ff65be9c04c1
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 29 21:49:43 2016 -0700
+
+ doc: Add idle mode info to 1.6.3 release note
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ec20e2f72460010c4f59e6d59775671260e01026
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 28 12:29:16 2016 -0700
+
+ altoslib: Make AltosPreferencesBackend abstract. Add set/put Serializable
+
+ This lets us add functionality to this directly, such as the new
+ serializable APIs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3c7b68b8a513b611500dfd734182e1a2e7bdd40c
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 27 01:40:47 2016 -0400
+
+ altosdroid: Add configurable frequency set
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02f47fa98536eb0ecd58cd8f063600ced60e0a8a
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 27 01:39:01 2016 -0400
+
+ Fix key in AndroidManifest.xml.in
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d81f94fd5339d513de9bde5a2e19f8eca526344f
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 26 21:01:44 2016 -0400
+
+ altosdroid: Split setup functions to separate dialog
+
+ Remove them from the options menu, handle all preferences through
+ listeners.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 204ae5142702044eb8ad2697a55028e904067958
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 23:12:34 2016 -0400
+
+ altosdroid: Add idle mode monitoring, reboot. Start igniters
+
+ This adds three idle mode operations -- monitor idle, reboot flight
+ computer and test igniters. The igniter test isn't quite wired up.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 565404599fe9edf9ba16aec348eeb19ea31af743
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 18:50:58 2016 -0400
+
+ altos: Clear packet queue when starting packet master
+
+ This avoids overfilling the packet buffer when
+ disconnected. Applications using packet mode shouldn't expect that
+ output be saved across master sessions.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c816bea3536d025568dab313d7c8944a56ba0801
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 18:49:45 2016 -0400
+
+ altos/telebt-v3.0: Flip CTS/RTS pins for BT module
+
+ These are wired backwards, so ask that the right pins be used, which
+ requires switching to software control of the pins.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 27319e4edbc503f193475b437fa5fe2937d47cbe
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 18:48:47 2016 -0400
+
+ altos/stm32l: Add support for software-driven HW flow control
+
+ This allows applications to request that the flow control bits be
+ driven from software rather than hardware, permitting more flexible
+ pin configuration.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7c9a111ac1c88467ce28e03b4a9d3eabc9d7015b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 23:53:27 2016 -0800
+
+ altos: Use TXE instead of TC for serial on STM32l
+
+ Using TXE allows for full-speed communication, rather than waiting for
+ each byte to be transmitted before inserting the next into the queue.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eee2ca7fa7fd77be8ca5806cad7e250053465048
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Apr 25 11:47:45 2016 -0400
+
+ Debug bits for telebt
+
+commit a995d73838c8e7ec5126e563baa2e59d5e071b28
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 19:15:51 2016 -0400
+
+ altoslib: Don't try to drag lines around until map is loaded
+
+ When the transform is null, it's hard to draw lines.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a5373e2f9d2f1af211aa98029d448aeb518b45ce
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 19:15:05 2016 -0400
+
+ altoslib: Report exceptions caught while opening launch sites URL
+
+ This just dumps them to stdout, which helps debug on Linux at least.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6bca0ed8183b85e5825eb0f4093dcd749592faf3
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 19:00:46 2016 -0400
+
+ altoslib: Use feet per second for imperial speed
+
+ This is more useful during descent than miles per hour...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f49fd5d2be68de97ebe65fa4f6484746e91dd677
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 18:53:32 2016 -0400
+
+ altosdroid: Run even without Bluetooth
+
+ This lets us view old state information on USB-only devices, or when
+ the bluetooth device can't be enabled.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ea89feedd4185a5f583fa8ddf33a2ec0906e0dc0
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 18:52:42 2016 -0400
+
+ altosdroid: Redraw offline map when my location changes
+
+ Update the map view even if there isn't any current telemetry data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 39af826ce9032e339929eb7917b1d29c87d03f69
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 17:32:10 2016 -0400
+
+ altosdroid: Track device location in app, not telemetry service
+
+ This means we get location even if there isn't a telemetry device
+ connected, making it possible to walk to old device locations
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b3f0c4d5c4ab8288db5fcabb0e848627031c4fd1
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Apr 22 17:31:49 2016 -0400
+
+ Bump version to 1.6.3
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 57c1320962ad08d52e89d39bd5852f8d228dd872
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 22:37:35 2016 -0400
+
+ altosdroid: Can only use message once
+
+ And here I thought re-using the message was clever. That generates a
+ nice exception and crashes the program.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4d4a39b569d7982405748b961b93dcd33e59b833
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:32:50 2016 -0400
+
+ Add preliminary 1.6.3 release notes
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 565d8f22c23c7c6c6817d11ef1ca02e70ba5d2ae
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 20 20:27:47 2016 -0400
+
+ libaltos: Fix for Mac OS X El Capitan
+
+ USB enumeration for serial devices changed
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f10fbff6758dfcfbeeeb224f8ab02fa107aae5f6
+Author: Justin Vreeland <vreeland.justin@gmail.com>
+Date: Thu Apr 21 08:30:10 2016 -0400
+
+ Fix java class differing only by case
+
+ OSX and Windows cannot handle files with names differing only by
+ case. When these files are present in either there's a constant
+ unfixable change viewable in git status and git diff.
+
+ Since this code can be run and compiled on both platforms
+ names different only by case should be avoided.
+
+ Signed-off-by: Justin Vreeland <vreeland.justin@gmail.com>
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c989237366ada094cdc817f50b7f58bbcf5b377a
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:11:29 2016 -0400
+
+ Prepare for new Android release by updating version number
+
+ 10->11
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 18b10ddf0e713431cb3e1065e62b0e6f597ce9d7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:12:06 2016 -0400
+
+ AltosDroid play store keys have moved, update configure.ac
+
+ The actual build files were already updated, but the configure.ac bits
+ which detect that they are available were not.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 21d176f161b90f18f236ef887cef9676d712eee3
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Apr 21 21:12:40 2016 -0400
+
+ Update java library version numbers
+
+ Prepare for 1.6.3 release.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4db6074bb15c66bd23c513e1e41b408e5408cff8
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:19:59 2016 -0400
+
+ altos: avoid mixed declarations and code in ao_task.c
+
+ sdcc can't handle this.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 09acb6821ab490d69f679a195e70acb4a71ba342
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:18:46 2016 -0400
+
+ altoslib: switch from keySet() to keys() in altos map tiles
+
+ Android appears to not have the keySet() API in the same way that
+ regular java does, so use the alternate older keys() api instead.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 49c3e3dffe748d0d155d4876efcaf7d39e1cc8e3
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:17:50 2016 -0400
+
+ altoslib: Make AltosGPSSat implement Serializable
+
+ This is required to save state values in AltosDroid.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 45bcf595d0a6a6001459f7f2055cd15e4839550b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:17:01 2016 -0400
+
+ altoslib: Add debugging to AltosPreferences.state() etc
+
+ This let me find why AltosDroid was losing the last state information
+ for each target.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 90ba010aaa84a7d8b93c63543568a16ab0cb5984
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 19 23:15:26 2016 -0400
+
+ altosdroid: Don't set target location if lat/lon is MISSING
+
+ Otherwise, we get a nice pointer to some random location on the planet.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fd0ca040a5cccae18145bd29b3e4c09f14df3865
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 13 06:14:33 2016 -0700
+
+ altos/telefiretwo-v0.2: Change alarm names in comment
+
+ The PCB is labeled 'A' and 'B'.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3abc0fc5e4484d862709501133d35563aa0c25fa
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 13 06:11:44 2016 -0700
+
+ altos/stmf0: Fix external interrupts
+
+ Missing a reserved address in the registers broke everything nicely,
+ but the priority values were also wrong - stm32f0 exposes 8 bits per
+ priority, like the stm32l, but it uses only the top two bits.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 14fecd672807982ce6232fa3b4bdce0aebe132e8
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 6 22:32:36 2016 -0700
+
+ Add TeleFireTwo v0.2 project
+
+ This is much like TeleFireTwo v0.1, with only one pyro channel and
+ added siren and strobe
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 70e46100acf597014ce54cf3b642254ce1cba59b
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 5 23:45:52 2016 -0700
+
+ altos/telelcotwo: Add idle timeout
+
+ Puts TeleLCOTwo in a low power state (drawing about 80µA) after a
+ timeout (default two minutes) to keep from killing the battery if the
+ device is left turned on.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aef5049cf8311927fada922730f85f31c8ddf177
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Dec 25 20:46:40 2015 -0800
+
+ altos: Use simpler debounce logic for buttons
+
+ Instead of waiting for a while after the transition to decide if it
+ has stuck, signal the event right away and then ignore other
+ transitions for the debounce interval.
+
+ This seems to work just as reliably, but has the benefit of
+ eliminating button latency at press time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4c2a7503373c0584de77f9b0e5632a58ab8bbd1f
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Dec 25 11:26:34 2015 -0800
+
+ altos: Add ao_lco_two.c; alternate LCO interface code
+
+ The LCO interface is likely to end up very device specific as the
+ interactions depends on the input devices. Here's a version for
+ TeleLCOTwo, which has two arming switches and a firing button.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 26023cfbf7e117114a4d62b7dbfc0f907efdfb47
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:52:31 2015 -0800
+
+ altos: Fix telefiretwo .gitignore
+
+ Was ignoring the wrong built files
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 11f8ab90d2267715010e652d709beec363f74ed5
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:50:43 2015 -0800
+
+ altos: Add TeleLCOTwo firmware
+
+ The LCO side of a two-channel launch controller setup.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e6bad553009704af69b08b4a22fb5eb8ac6921f8
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:48:37 2015 -0800
+
+ altos: Support pad/lco boxes with fixed box numbers
+
+ This allows for a configuration without adjustable box numbers on
+ either end of the link, simplifying the UI.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 93100ae8d4c8bd8fd6bdeff2cdc87b613c5d8058
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 21 21:47:10 2015 -0800
+
+ altos: Allow for pad boxes with different sensor configurations
+
+ This allows for a pad box without a resistor from power to each
+ FET. That resistor is needed to detect welded relays, but in a
+ solid-state system, that's not a possibility.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2038dd2cfed5bbf049144172e3f7436b6cd3a55
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:54:23 2015 -0800
+
+ altos: telefiretwo-v0.1 bits
+
+ Get this board running.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 26ce7a9a213bdd35a13937054988e7b8fa749632
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:30:35 2015 -0800
+
+ altos: Add pad support for new telefire versions
+
+ Makes the voltage divider values configurable, and allows for pyro
+ channels that don't have the resistors necessary to check for a stuck
+ relay.
+
+ Also supports STM32L processors with wider GPIO registers, and uses
+ the new ao_gpio_set/clr_bits functions to fire igniters rather than
+ cc1111-specific code.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 553c89f8c64398cb1a815b1fa248980cd3f62ef8
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:29:36 2015 -0800
+
+ altos: Support telefire products in cc1200 driver
+
+ Need to disable the pad code while testing the radio.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b8a19e83b7b1b8e2a1fcbdd58e41f9f974ae28ff
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Apr 13 06:16:01 2016 -0700
+
+ altos/detherm: Add servo driver
+
+ This just provides commands to test the servo with.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cfb91ec7ef6ef485d813af96a0f206bb7a2204dd
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Apr 5 22:03:37 2016 -0700
+
+ altos/detherm: Add ms5607 to detherm
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8da29480a2fdf890d553b30eab58fc884210c1a5
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Dec 23 23:15:16 2015 -0800
+
+ altos: Add easy mini plotting helper in test code
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e3f0c5eb8e5d57cbd8882587477d1381e2a83226
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Dec 17 19:27:42 2015 -0800
+
+ altos: Add ao_gpi_set/clr_bits functions
+
+ These set or clear a group of bits in a single GPIO register all together.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 097c156b13ae975c742f294b46429e8ff14c365b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 22:41:06 2016 -0700
+
+ altos/stmf0: Add pwm and exti drivers
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0f227683e29062224a612c4a2ab5c8b2fc166059
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 22:40:23 2016 -0700
+
+ altos: Add detherm product
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eeceee3520fae66b35a9a9b39c866c1c2e3b0c9a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:44:06 2016 -0700
+
+ doc: Note that EasyMega and TeleMega report A-D continuity
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f95c781bc16d332ea5442590521074396d6981ae
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:43:32 2016 -0700
+
+ altos/stmf0: Support HPE clock source
+
+ Allows the use of crystals instead of requiring USB.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9f9d77b6d025d8285e362e53a8f728ec47adb234
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:42:44 2016 -0700
+
+ altos/stmf0: Add SPI driver.
+
+ This also changes the DMA interface a bit so we can select for
+ interrupts on only the interesting channels.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f5e6caab78f4ca0e5c8a2d96ef53b8752d64f4b3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:41:21 2016 -0700
+
+ altos: Use mini logging for detherm, just without ADC
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6ead4c570a264afdc4e45eed6e87bf541668be6f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:40:19 2016 -0700
+
+ altos: Add Detherm log format (easymini without ADC)
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0ee235e1126f34987522fe852ba6ab3ac92d6cfd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Apr 2 19:39:07 2016 -0700
+
+ altos: Allow for flight hardware without any ADC values
+
+ Detherm has no ADC connections, so we don't need to disable the ADC
+ when going to landed state.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7348cc4736c9a94f9ad299edd78199b544d0e95a
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Mar 24 19:25:33 2016 -0600
+
+ altos: Add one-byte SPI output routine for LPC and STM cores
+
+ This allows for SPI output at interrupt time, one byte at a time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b31c6fd153825ae5ad0fcea7189472af1a9cffff
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Mar 24 19:28:16 2016 -0600
+
+ altos/lpc: Add fast timer
+
+ This offers a faster timer callback for higher-precision operation
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a86d98b708d84c6e0b85cb950e3f1ee16cfc56f5
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:59:26 2016 -0700
+
+ altos/stm: Allow apps to define different stack size
+
+ While 512 bytes is a reasonable size, sometimes apps don't have that
+ much stack space.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4fa71ecf168e275b24534a5a20e3dd4e178c7bbd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:54:24 2016 -0700
+
+ altos/stm: Validate current task SP in interrupt by looking at PSP
+
+ We use a separate stack pointer for task code, which means we can
+ verify that it is in range in any interrupt handler. This adds checks
+ for the task stack (under #ifdef DEBUG) that run in ao_wakeup as well
+ as at every timer interrupt.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a9546413d6a236c010e806b50506d870961d074
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:49:59 2016 -0700
+
+ altos/stm: Run scheduler code on interrupt stack
+
+ This provides a bit more room for tasks on their stack
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 55db3b3e8addaa2dc0af50470d3bc8c25cb57df3
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Mar 21 22:28:39 2016 -0600
+
+ altosui,telegps: Do not allow radio calibration to be edited
+
+ This leads to sorrow for almost everyone. If you want to edit this,
+ use a terminal program.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c61014914c80ad0dba72224109d9b147bb343562
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:57:59 2016 -0700
+
+ altosuilib: Control map debugging output with Serial.debug
+
+ This uses the same debug control as the serial output to monitor map downloading
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4f8a325949ed3cece4b646c808ad68677b16d1b6
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 26 15:57:21 2016 -0700
+
+ altoslib: use env var LAUNCH_SITES to override default URL
+
+ This makes it easier to debug new launch site data before uploading.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2fc47e7052a08de464f08d890e222afd7dec75d8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 23:11:49 2016 -0700
+
+ libaltos: Fix warning in linux libaltos code
+
+ Just returned the wrong name of the value
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4dddf0a9134690d94217ad12bc7372683276f8ba
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 22:01:07 2016 -0700
+
+ altosuilib: Note that Windows now supports Bluetooth
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 054f2896b98a14051e0b818090f2de178bb77283
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 21:54:08 2016 -0700
+
+ altosui: Delay between polling for igniter status in Fire Igniters
+
+ This gives a remote like time to report the full status instead of
+ sending another request before the reply has been processed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1594691ea88ca84634eea237ac8137a5bdc19f5c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 20 21:52:53 2016 -0700
+
+ libaltos: Add Windows BT support. Split into separate source files.
+
+ Add Bluetooth support to Windows. Split libaltos into separate files.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit afba05c41f30c9273668d5ed71e0dc8c1ca53141
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 11:17:46 2016 -0700
+
+ ao-bringup: Use dfu-util to install flash loader on chaoskey
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4635203e9be530f53b697ac0349838916e146983
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 11:16:59 2016 -0700
+
+ altos/stmf0: Construct .bin files for flash loaders
+
+ This builds a .bin file which can be used with dfu-util instead of
+ using openocd to load the initial flash loader.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f393482ec47e857db654fa071d4df95e98dab381
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 11:15:57 2016 -0700
+
+ ao-tools: Add ao-makebin
+
+ This constructs a raw binary or DFU format file for use with dfu-util,
+ which can be used with a bare STM processor to load code before the
+ boot loader is available.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d7f88bf7521fa6d301da072f95f97fa42d9d247
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:52:03 2016 -0700
+
+ ao-tools/lib: Add ao_hex_image_cat function
+
+ This takes two images and constructs a third containing the union of
+ the contents along with 0xff bytes for any area between them.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4e738dff6dec4685b8712d3e96742971fa39c8f1
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:51:20 2016 -0700
+
+ ao-tools/lib: Remove trailing whitespace from ao-elf.c
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 45d61b79665197ff99f415cda7bd5907830233e9
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:50:32 2016 -0700
+
+ ao-tools/ao-dump-up: Remove spurious flight state strings
+
+ MicroPeak doesn't have flight states like this...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 25cdbf15e7284eb963070b28dd886aa299af6487
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:48:49 2016 -0700
+
+ Change how we detect and install java
+
+ Detect by finding 'javaw.exe' in the current path and extracting the
+ version from the program itself.
+
+ Install by simply opening the web browser to java.com and letting the
+ user install it themselves.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a7c7e10b3bbfbdf9667d071634cdd6fdf12a1f85
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Mar 18 10:17:24 2016 -0700
+
+ altos: Expose fast timer API from kernel/
+
+ This allows multiple SoCs to provide the same driver interface
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d1af180c2d2a2caf1e13f00d83f2b86ba26de27f
+Author: Bart Massey <bart@cs.pdx.edu>
+Date: Sat Mar 5 17:38:19 2016 -0800
+
+ altos: Fixed timing of panic display LED to be readable
+
+ When we don't have a beeper, there's no way to signal a 'warble' for
+ panic. So, elide that bit.
+
+ Second, panic can't use the scheduler and timer because those may not
+ be running (or may have failed), and so it uses a delay loop. Add a
+ configurable scale value to the panic loop so that the LED blinks can
+ be read. For stm32f0 devices, scale that by the sysclk value to
+ automatically make them of reasonable length.
+
+commit 20d9286402b7da74fef9b7c98e79d13671f6c82b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 6 15:05:51 2016 -0800
+
+ libaltos: Add unistd.h to get defines for various syscalls
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ad07578d04926cb4b96c40a446c47ad3f9bad7df
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Mar 6 15:04:23 2016 -0800
+
+ libaltos: jni_md.h moved to linux subdir in Java install
+
+ Add the linux subdir to CFLAGS to find it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7cb388a33104fd78c8cb1fa08a6f114e3e1e372d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Mar 5 14:37:40 2016 -0800
+
+ altos/stmf0: Fix build without second USB IN endpoint
+
+ The code for the second IN endpoint was using the wrong ifdef.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 99d3248a390379cfabf821ea4a195072799861eb
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 14:36:31 2016 -0800
+
+ ao-tools: Add ao-chaosread
+
+ This reads from the raw descriptor to help validate the hardware.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 88ee4ac0c91e12a02cc1954ffad0fd8603e24e55
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 14:01:00 2016 -0800
+
+ ao-bringup: Switch to v1.0 for chaoskey
+
+ Not going to build any more v0.1 boards. Also, chaoskey now uses the
+ unique ID for a serial, so we don't need to provide a serial number.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3a355d5c84e9d975897fa69a103952a1f1558947
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 14:00:06 2016 -0800
+
+ altos: Add ChaosKey v1.0 product
+
+ Much like ChaosKey v0.1, just different SoC package and a few wiring changes.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 05fcb717bfc44aba3c1cfd43281e323505a46402
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Mar 2 13:54:58 2016 -0800
+
+ altos/chaoskey: Add another USB endpoint to read raw data
+
+ This replaces having the single output switch based on a pin value and
+ allows us to box the device and still fetch raw data.
+
+ For now, this will use a special libusb2 program, ao-chaosread, to
+ pull bits as I haven't figure out how to make linux provide two
+ /dev entries for one USB device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 05354b8fee6a9af05d66bb7f4761f597da038fdd
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 15:26:00 2016 -0800
+
+ altos/chaoskey: Use SoC device ID as serial number
+
+ To make manufacturing these devices tractable, we don't want to
+ require a custom firmware load for each device, but we still want a
+ unique serial number. Fortunately, the SoC provides a 96-bit ID which
+ we can use.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5637c1b2fd7232842245af1437e33b5bb1583c7d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 15:24:35 2016 -0800
+
+ altos/stmf0: Use device ID as usb serial number if requested
+
+ This exposes the hardware device ID (which is unique per-chip) as the
+ USB serial number, avoiding the need to create a custom ROM image for
+ each device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e4006444d3d7b0c499139f58f13353988d38dbb4
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 15:23:15 2016 -0800
+
+ altos/chaoskey: Encode both hardware and software versions in product ID
+
+ We have no other way of reporting the software version, so just encode
+ it in the product ID.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit afef70bb8f31075de364ddf713f3ccf1d9c6361d
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 15 14:04:04 2016 -0800
+
+ altos/stmf0: Fix location of device_id register
+
+ Copied from stm32l and never fixed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0bae4b25882983cd0b7950b3e80b6d93a72f0847
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Feb 8 19:15:31 2016 -0800
+
+ altos: Another fix for non CDC-ACM devices
+
+ Need to set the bInterfaceNumber for the actual interface to zero when
+ there isn't an INT interface before it.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e36117ccbf7cbe3704c6b44d3ad429e720a1e16c
+Author: Bart Massey <bart.massey@gmail.com>
+Date: Mon Feb 8 18:55:28 2016 -0800
+
+ Clean up stmf0 adc init.
+
+ This better matches the documented cal sequence.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5ce26345784459f5864ef59c96c8aa633d2ddf64
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 22:30:27 2016 -0800
+
+ altos/stmf0: Add missing ao_gpio.c
+
+ This contains the code for power managing the GPIO pins
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bab082605e3fca6b6d11447c45cd948ddfe74bb9
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 22:28:34 2016 -0800
+
+ altos: Add simple stats test to TRNG code
+
+ This detects broken hardware by making sure the standard deviation in
+ the raw values used to compute each buffer is at least 128.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 147f0df6a29b37fbfb0824ecd276482f0eecb397
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 15:33:42 2016 -0800
+
+ altos: Delay TRNG ADC long enough for HV supply to stabilize
+
+ Looks like it takes about 70ms for the supply to start running right,
+ so delay after powering it up for that long.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1473f9234ffd34d8f37bc489dfc9fc4d7f1b3eed
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 00:15:47 2016 +1100
+
+ altos/chaoskey-v0.1: Add power management and change USB classes
+
+ Enable power management.
+ Expose only a single IN endpoint.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 235198b85f1583d2792c7028decace61d1b4229e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 00:14:22 2016 +1100
+
+ altos: Add power management to TRNG driver
+
+ Support suspend/resume of the TRNG power supply, delaying after resume
+ to wait for it to stabilize.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2ad756bd1b63a2c8450edd7001628b92279fd1b8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 7 00:10:57 2016 +1100
+
+ altos: Allow USB drivers to skip CDC-ACM -specific descriptors
+
+ For devices not providing the standard CDC-ACM interface, let them
+ skip the various descriptors and interfaces to provide a more limited
+ set of capabilities.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a5607aad694c01c01c48229172b289f005a1b6bb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 6 22:51:32 2016 +1100
+
+ altos/stmf0: Add suspend/resume support
+
+ Allow USB suspend to suspend USB, GPIOs and master clock.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 36c6d74048283d27c890054814eee2cb39b7cbb7
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 6 22:47:23 2016 +1100
+
+ altos: Add power management APIs
+
+ This provides sequenced suspend/resume functionality, allowing modules
+ to register for power management at configuration time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit fbb07cf50ba7fa278d1f8201ef376ec12480e9aa
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 23:55:52 2016 -0800
+
+ altos/stmf0: Allow projects to specify non-default stack size
+
+ 512 may not be suitable for everyone.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1d7463befc18f415d8982f04e52729d3bf5b95a9
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 23:55:32 2016 -0800
+
+ altos: remove blank line in stmf0/ao_timer.c
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 35407e664886bed21dcef7764843aac03be8490c
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jan 28 13:58:43 2016 -0800
+
+ altos/chaoskey: Delay ADC reading for 250ms at startup
+
+ This lets the HV supply stabilize before we start sampling values.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2d3202de9a5847923f72afe2969eb7ccd7342c7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jan 28 00:14:36 2016 -0800
+
+ altos/chaoskey: Add support for flipping between raw and cooked bits
+
+ Plug the 'force bootloader' thing onto the board while it's running
+ and it will generate raw bits instead of running them through the CRC
+ to whiten. Useful for validating the raw hardware.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02fd767ab60a9957faa2bff29c62ed954abc34e7
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 19 18:30:57 2016 -0800
+
+ src/chaoskey-v0.1: Add HV enable support
+
+ Turn on the HV supply when the OS starts.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e5be0be35f724507d7efff48339a297df73d2641
+Author: Robert Garbee <robert@gag.com>
+Date: Sat Jan 16 10:19:47 2016 -0700
+
+ fix argument to ao-cal-freq so devices other than /dev/ttyACM0 work
+
+commit 6a7644a0d179e1eb7d665123157ad76c956e524a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jan 10 21:39:38 2016 -0800
+
+ Releasing: Copy TeleMega v2.0 bits to Binaries
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b53c78e75879d647935a30acb88fdd69467617a7
+Merge: a2ea621 64adfbb
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jan 10 19:15:16 2016 -0700
+
+ Merge branch 'master' into branch-1.6
+
+commit 64adfbbb80c90dfe244179d81beaef8a84ed8bd6
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Jul 16 14:47:10 2015 -0600
+
+ process updates from 1.6.1 release
+
+commit a2ea621eac3263348aff50885c79296f8ece26ed
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sun Jan 10 19:08:12 2016 -0700
+
+ update Changelog from git log
+
commit 1681776abc0873bcbbbc5b2b17e15d54a1031f51
Merge: 8830926 aebdcaf
Author: Bdale Garbee <bdale@gag.com>
telegps/TeleGPS-Windows-$(VERSION_DASH).exe \
micropeak/MicroPeak-Windows-$(VERSION_DASH).exe
+fat_android = \
+ altosdroid/bin/AltosDroid-debug.apk \
+ altosdroid/bin/AltosDroid-release.apk
+
keithp-fat: fat
ssh keithp.com mkdir -p public_html/altos-$(VERSION)
- scp -p $(fat_linux) $(fat_mac) $(fat_windows) keithp.com:public_html/altos-$(VERSION)
+ scp -p $(fat_linux) $(fat_mac) $(fat_windows) $(fat_android) keithp.com:public_html/altos-$(VERSION)
set-java-versions:
$(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION)
src/teledongle-v3.0/*.elf \
src/telegps-v1.0/*.elf \
src/telemega-v1.0/*.elf \
+ src/telemega-v2.0/*.elf \
src/telemetrum-v2.0/*.elf \
~/altusmetrumllc/Binaries/
cp src/easymega-v1.0/flash-loader/*.elf \
src/teledongle-v3.0/flash-loader/*.elf \
src/telegps-v1.0/flash-loader/*.elf \
src/telemega-v1.0/flash-loader/*.elf \
+ src/telemega-v2.0/flash-loader/*.elf \
src/telemetrum-v2.0/flash-loader/*.elf \
~/altusmetrumllc/Binaries/loaders/
(cd ~/altusmetrumllc ; git add Binaries ; git commit -a)
google-play-services_lib
src/org/altusmetrum/AltosDroid/BuildInfo.java
res/drawable/*led.png
+AndroidManifest.xml
<uses-permission android:name="org.altusmetrum.AltosDroid.permission.MAPS_RECEIVE"/>
<!-- Permissions needed to access USB OTG -->
- <uses-feature android:name="android.hardware.usb.host" />
+ <uses-feature android:name="android.hardware.usb.host" android:required="false" />
<application android:label="@string/app_name"
android:icon="@drawable/app_icon"
android:theme="@android:style/Theme.Dialog"
android:configChanges="orientation|keyboardHidden" />
+ <activity android:name=".IdleModeActivity"
+ android:label="@string/idle_mode"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboardHidden" />
+
+ <activity android:name=".IgniterActivity"
+ android:label="@string/igniters"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboardHidden" />
+
+ <activity android:name=".SetupActivity"
+ android:label="@string/setup"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation" />
+
+ <activity android:name=".ManageFrequenciesActivity"
+ android:label="@string/manage_frequencies"
+ android:theme="@android:style/Theme.Dialog"
+ android:configChanges="orientation|keyboard" />
+
<service android:name=".TelemetryService" />
<meta-data android:name="com.google.android.maps.v2.API_KEY"
- android:value="AIzaSyDSr6u4i9TJmVGhgGk4g0wUUhTy9FGyn0s"/>
+ android:value="@GOOGLEKEY@"/>
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />
</application>
LAYOUTS=$(LAYOUT_DIR)/*.xml
MENUS=$(MENU_DIR)/*.xml
VALUES=$(VALUES_DIR)/*.xml
-XMLS=$(XML_DIR)/*.xml
+XMLS=$(XML_DIR)/*.xml AndroidManifest.xml
RES=$(LAYOUTS) $(MENUS) $(VALUES) $(XMLS)
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
+<!--
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
- http://www.apache.org/licenses/LICENSE-2.0
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="horizontal"
+ >
+ <TextView
+ android:id="@+id/frequency"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="1"
+ />
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <TextView android:id="@+id/set_callsign_label"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/set_callsign_label"
+ />
+ <EditText android:id="@+id/set_callsign"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/set_callsign_label"/>
+ <Button android:id="@+id/connect_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/connect_idle"
+ />
+ <Button android:id="@+id/disconnect_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/disconnect_idle"
+ />
+ <Button android:id="@+id/reboot_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/reboot_idle"
+ />
+ <Button android:id="@+id/igniters_idle"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/igniters_idle"
+ />
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent">
+ <TextView
+ android:id="@+id/igniter_status"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_alignParentRight="true"
+ />
+ <TextView
+ android:id="@+id/igniter_name"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_alignParentLeft="@+id/igniter_status"
+ />
+</RelativeLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <ListView android:id="@+id/igniters"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:fadeScrollbars="false"
+ android:scrollbars="vertical"
+ android:choiceMode="singleChoice"
+ />
+
+ <ToggleButton android:id="@+id/igniter_arm"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:textOn="@string/igniter_armed"
+ android:textOff="@string/igniter_arm"
+ />
+
+ <Button android:id="@+id/igniter_fire"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/igniter_fire"
+ />
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/set_layout"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ >
+ <EditText
+ android:id="@+id/set_frequency"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="1"
+ android:hint="@string/frequency"
+ android:inputType="number|numberDecimal"/>
+ />
+ <TextView
+ android:id="@+id/mhz"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="0"
+ android:text="@string/mhz"
+ />
+ <EditText
+ android:id="@+id/set_description"
+ android:layout_width="wrap_content"
+ android:layout_height="fill_parent"
+ android:padding="10dp"
+ android:layout_weight="2"
+ android:hint="@string/description"
+ />
+ </LinearLayout>
+ <LinearLayout
+ android:orientation="horizontal"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <Button android:id="@+id/set"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/set"
+ android:layout_weight="1"
+ />
+
+ <Button android:id="@+id/remove"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/remove"
+ android:layout_weight="1"
+ />
+
+ <Button android:id="@+id/done"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/done"
+ android:layout_weight="1"
+ />
+ </LinearLayout>
+
+ <ListView android:id="@+id/frequencies"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:fadeScrollbars="false"
+ android:scrollbars="vertical"
+ android:choiceMode="singleChoice"
+ />
+
+
+</LinearLayout>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ Copyright © 2016 Keith Packard <keithp@keithp.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ 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, write to the Free Software Foundation, Inc.,
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <TableLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:stretchColumns="2,3"
+ android:layout_weight="0"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/select_rate_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/telemetry_rate"
+ />
+ <Spinner android:id="@+id/select_rate"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/telemetry_rate"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/set_units_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/set_units"
+ />
+ <Spinner android:id="@+id/set_units"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/set_units"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/map_type_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/map_type"
+ />
+ <Spinner android:id="@+id/map_type"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/map_type"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ <TableRow
+ android:layout_gravity="center"
+ android:layout_weight="1"
+ android:padding="2dip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <TextView
+ android:id="@+id/map_source_label"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/map_source"
+ />
+ <Spinner android:id="@+id/map_source"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:prompt="@string/map_source"
+ android:spinnerMode="dropdown"
+ />
+ </TableRow>
+ </TableLayout>
+ <Button android:id="@+id/preload_maps"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/preload_maps"
+ />
+ <Button android:id="@+id/manage_frequencies"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/manage_frequencies"
+ />
+ <Button android:id="@+id/done"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/done"
+ />
+</LinearLayout>
<item android:id="@+id/select_freq"
android:icon="@android:drawable/ic_menu_preferences"
android:title="@string/select_freq" />
- <item android:id="@+id/select_rate"
- android:icon="@android:drawable/ic_menu_preferences"
- android:title="@string/select_rate" />
- <item android:id="@+id/change_units"
- android:icon="@android:drawable/ic_menu_view"
- android:title="@string/change_units" />
- <item android:id="@+id/preload_maps"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/preload_maps" />
- <item android:id="@+id/map_type"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/map_type" />
- <item android:id="@+id/map_source"
- android:icon="@android:drawable/ic_menu_mapmode"
- android:title="@string/map_source" />
+
<item android:id="@+id/select_tracker"
android:icon="@android:drawable/ic_menu_view"
android:title="@string/select_tracker"/>
<item android:id="@+id/delete_track"
android:icon="@android:drawable/ic_notification_clear_all"
android:title="@string/delete_track"/>
+
+ <item android:id="@+id/setup"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:title="@string/setup" />
+ <item android:id="@+id/idle_mode"
+ android:icon="@android:drawable/ic_menu_preferences"
+ android:title="@string/idle_mode" />
+
<item android:id="@+id/quit"
android:icon="@android:drawable/ic_menu_close_clear_cancel"
android:title="@string/quit" />
<string name="connect_device">Connect a device</string>
<string name="disconnect_device">Disconnect device</string>
<string name="quit">Quit</string>
+ <string name="setup">Setup</string>
<string name="select_freq">Select radio frequency</string>
<string name="select_rate">Select data rate</string>
<string name="change_units">Change units</string>
<string name="preload_radius">Radius</string>
<string name="preload_load">Load Map</string>
+
+ <!-- Idle mode -->
+ <string name="idle_mode">Idle Mode</string>
+ <string name="set_callsign_label">Callsign</string>
+ <string name="connect_idle">Monitor</string>
+ <string name="disconnect_idle">Disconnect</string>
+ <string name="reboot_idle">Reboot</string>
+ <string name="igniters_idle">Fire Igniters</string>
+
+ <!-- igniters -->
+ <string name="igniters">Igniters</string>
+ <string name="igniter_arm">Arm</string>
+ <string name="igniter_armed">Armed</string>
+ <string name="igniter_fire">Fire</string>
+
+ <!-- setup -->
+ <string name="telemetry_rate">Telemetry Rate</string>
+ <string name="set_units">Units</string>
+ <string name="map_type">Map Type</string>
+ <string name="map_source">Map Source</string>
+ <string name="preload_maps">Preload Maps</string>
+ <string name="manage_frequencies">Manage Frequencies</string>
+ <string name="done">OK</string>
+
+ <!-- manage frequencies -->
+ <string name="set">Set</string>
+ <string name="mhz">MHz</string>
+ <string name="remove">Remove</string>
+ <string name="done">OK</string>
+ <string name="frequency">Frequency</string>
+ <string name="description">Description</string>
</resources>
import android.os.Handler;
//import android.os.Message;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBluetooth extends AltosDroidLink {
import java.io.*;
import java.lang.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
import android.widget.*;
import android.app.AlertDialog;
import android.location.Location;
+import android.location.LocationManager;
+import android.location.LocationListener;
import android.hardware.usb.*;
import android.graphics.*;
import android.graphics.drawable.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
+public class AltosDroid extends FragmentActivity implements AltosUnitsListener, LocationListener {
// Actions sent to the telemetry server at startup time
public static final int MSG_STATE = 1;
public static final int MSG_UPDATE_AGE = 2;
+ public static final int MSG_IDLE_MODE = 3;
+ public static final int MSG_IGNITER_STATUS = 4;
// Intent request codes
public static final int REQUEST_CONNECT_DEVICE = 1;
public static final int REQUEST_ENABLE_BT = 2;
public static final int REQUEST_PRELOAD_MAPS = 3;
- public static final int REQUEST_MAP_TYPE = 4;
+ public static final int REQUEST_IDLE_MODE = 5;
+ public static final int REQUEST_IGNITERS = 6;
+ public static final int REQUEST_SETUP = 7;
- public int map_type = AltosMap.maptype_hybrid;
+ public static final String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+ public static final String EXTRA_TELEMETRY_SERVICE = "telemetry_service";
+
+ // Setup result bits
+ public static final int SETUP_BAUD = 1;
+ public static final int SETUP_UNITS = 2;
+ public static final int SETUP_MAP_SOURCE = 4;
+ public static final int SETUP_MAP_TYPE = 8;
public static FragmentManager fm;
// field to display the version at the bottom of the screen
private TextView mVersion;
- private double frequency;
- private int telemetry_rate;
+ private boolean idle_mode = false;
+
+ public Location location = null;
// Tabs
TabHost mTabHost;
case MSG_UPDATE_AGE:
ad.update_age();
break;
+ case MSG_IDLE_MODE:
+ ad.idle_mode = (Boolean) msg.obj;
+ ad.update_state(null);
+ break;
}
}
};
switch (telemetry_state.connect) {
case TelemetryState.CONNECT_CONNECTED:
if (telemetry_state.config != null) {
- String str = String.format("S/N %d %6.3f MHz", telemetry_state.config.serial,
- telemetry_state.frequency);
+ String str = String.format("S/N %d %6.3f MHz%s", telemetry_state.config.serial,
+ telemetry_state.frequency, idle_mode ? " (idle)" : "");
if (telemetry_state.telemetry_rate != AltosLib.ao_telemetry_rate_38400)
str = str.concat(String.format(" %d bps",
AltosLib.ao_telemetry_rate_values[telemetry_state.telemetry_rate]));
state = newest_state;
}
- update_ui(telemetry_state, state, telemetry_state.location);
+ update_ui(telemetry_state, state);
start_timer();
}
}
}
- void update_ui(TelemetryState telem_state, AltosState state, Location location) {
+ void update_ui(TelemetryState telem_state, AltosState state) {
int prev_state = AltosLib.ao_flight_invalid;
mCallsignView.setText(state.callsign);
}
if (saved_state == null || state.serial != saved_state.serial) {
- mSerialView.setText(String.format("%d", state.serial));
+ if (state.serial == AltosLib.MISSING)
+ mSerialView.setText("");
+ else
+ mSerialView.setText(String.format("%d", state.serial));
}
if (saved_state == null || state.flight != saved_state.flight) {
if (state.flight == AltosLib.MISSING)
}
}
if (saved_state == null || state.rssi != saved_state.rssi) {
- mRSSIView.setText(String.format("%d", state.rssi));
+ if (state.rssi == AltosLib.MISSING)
+ mRSSIView.setText("");
+ else
+ mRSSIView.setText(String.format("%d", state.rssi));
}
}
return tab_view;
}
- public void set_map_source(int source) {
- for (AltosDroidTab mTab : mTabs)
- mTab.set_map_source(source);
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mAgeOldColor = getResources().getColor(R.color.old_color);
}
- private boolean ensureBluetooth() {
+ private void ensureBluetooth() {
// Get local Bluetooth adapter
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- // If the adapter is null, then Bluetooth is not supported
- if (mBluetoothAdapter == null) {
- Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
- return false;
- }
-
- if (!mBluetoothAdapter.isEnabled()) {
+ /* if there is a BT adapter and it isn't turned on, then turn it on */
+ if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) {
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent, AltosDroid.REQUEST_ENABLE_BT);
}
-
- return true;
}
private boolean check_usb() {
return;
}
AltosDebug.debug("Starting by looking for bluetooth devices");
- if (ensureBluetooth())
- return;
- finish();
+ ensureBluetooth();
}
}
public void onResume() {
super.onResume();
AltosDebug.debug("+ ON RESUME +");
+
+ // Listen for GPS and Network position updates
+ LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
+
+ location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+
+ if (location != null)
+ AltosDebug.debug("Resume, location is %f,%f\n",
+ location.getLatitude(),
+ location.getLongitude());
+
+ update_ui(telemetry_state, saved_state);
}
@Override
public void onPause() {
super.onPause();
AltosDebug.debug("- ON PAUSE -");
+ // Stop listening for location updates
+ ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
}
@Override
if (resultCode == Activity.RESULT_OK) {
// Bluetooth is now enabled, so set up a chat session
//setupChat();
+ AltosDebug.debug("BT enabled");
+ bluetoothEnabled(data);
} else {
// User did not enable Bluetooth or an error occured
- AltosDebug.error("BT not enabled");
- stopService(new Intent(AltosDroid.this, TelemetryService.class));
- Toast.makeText(this, R.string.bt_not_enabled, Toast.LENGTH_SHORT).show();
- finish();
+ AltosDebug.debug("BT not enabled");
}
break;
- case REQUEST_MAP_TYPE:
+ case REQUEST_IDLE_MODE:
if (resultCode == Activity.RESULT_OK)
- set_map_type(data);
+ idle_mode(data);
+ break;
+ case REQUEST_IGNITERS:
break;
+ case REQUEST_SETUP:
+ if (resultCode == Activity.RESULT_OK)
+ note_setup_changes(data);
+ break;
+ }
+ }
+
+ private void note_setup_changes(Intent data) {
+ int changes = data.getIntExtra(SetupActivity.EXTRA_SETUP_CHANGES, 0);
+
+ if ((changes & SETUP_BAUD) != 0) {
+ try {
+ mService.send(Message.obtain(null, TelemetryService.MSG_SETBAUD,
+ AltosPreferences.telemetry_rate(1)));
+ } catch (RemoteException re) {
+ }
+ }
+ if ((changes & SETUP_UNITS) != 0) {
+ /* nothing to do here */
+ }
+ if ((changes & SETUP_MAP_SOURCE) != 0) {
+ /* nothing to do here */
}
+ if ((changes & SETUP_MAP_TYPE) != 0) {
+ /* nothing to do here */
+ }
+ set_switch_time();
}
private void connectUsb(UsbDevice device) {
}
}
+ private void bluetoothEnabled(Intent data) {
+ try {
+ mService.send(Message.obtain(null, TelemetryService.MSG_BLUETOOTH_ENABLED, null));
+ } catch (RemoteException e) {
+ AltosDebug.debug("send BT enabled message failed");
+ }
+ }
+
private void connectDevice(Intent data) {
// Attempt to connect to the device
try {
}
}
- private void set_map_type(Intent data) {
- int type = data.getIntExtra(MapTypeActivity.EXTRA_MAP_TYPE, -1);
+ private void idle_mode(Intent data) {
+ int type = data.getIntExtra(IdleModeActivity.EXTRA_IDLE_RESULT, -1);
+ Message msg;
- AltosDebug.debug("intent set_map_type %d\n", type);
- if (type != -1) {
- map_type = type;
- for (AltosDroidTab mTab : mTabs)
- mTab.set_map_type(map_type);
+ AltosDebug.debug("intent idle_mode %d", type);
+ switch (type) {
+ case IdleModeActivity.IDLE_MODE_CONNECT:
+ msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_START);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_DISCONNECT:
+ msg = Message.obtain(null, TelemetryService.MSG_MONITOR_IDLE_STOP);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_REBOOT:
+ msg = Message.obtain(null, TelemetryService.MSG_REBOOT);
+ try {
+ mService.send(msg);
+ } catch (RemoteException re) {
+ }
+ break;
+ case IdleModeActivity.IDLE_MODE_IGNITERS:
+ Intent serverIntent = new Intent(this, IgniterActivity.class);
+ startActivityForResult(serverIntent, REQUEST_IGNITERS);
+ break;
}
}
}
}
- void setFrequency(String freq) {
- try {
- setFrequency (AltosParse.parse_double_net(freq.substring(11, 17)));
- } catch (ParseException e) {
- }
+ void setFrequency(AltosFrequency frequency) {
+ setFrequency (frequency.frequency);
}
void setBaud(int baud) {
Intent serverIntent = null;
switch (item.getItemId()) {
case R.id.connect_scan:
- if (ensureBluetooth()) {
- // Launch the DeviceListActivity to see devices and do scan
- serverIntent = new Intent(this, DeviceListActivity.class);
- startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
- }
+ ensureBluetooth();
+ // Launch the DeviceListActivity to see devices and do scan
+ serverIntent = new Intent(this, DeviceListActivity.class);
+ startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
return true;
case R.id.disconnect:
/* Disconnect the device
disconnectDevice();
finish();
return true;
+ case R.id.setup:
+ serverIntent = new Intent(this, SetupActivity.class);
+ startActivityForResult(serverIntent, REQUEST_SETUP);
+ return true;
case R.id.select_freq:
// Set the TBT radio frequency
- final String[] frequencies = {
- "Channel 0 (434.550MHz)",
- "Channel 1 (434.650MHz)",
- "Channel 2 (434.750MHz)",
- "Channel 3 (434.850MHz)",
- "Channel 4 (434.950MHz)",
- "Channel 5 (435.050MHz)",
- "Channel 6 (435.150MHz)",
- "Channel 7 (435.250MHz)",
- "Channel 8 (435.350MHz)",
- "Channel 9 (435.450MHz)"
- };
+ final AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+ String[] frequency_strings = new String[frequencies.length];
+ for (int i = 0; i < frequencies.length; i++)
+ frequency_strings[i] = frequencies[i].toString();
AlertDialog.Builder builder_freq = new AlertDialog.Builder(this);
builder_freq.setTitle("Pick a frequency");
- builder_freq.setItems(frequencies,
+ builder_freq.setItems(frequency_strings,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
setFrequency(frequencies[item]);
AlertDialog alert_freq = builder_freq.create();
alert_freq.show();
return true;
- case R.id.select_rate:
- // Set the TBT baud rate
-
- final String[] rates = {
- "38400",
- "9600",
- "2400",
- };
-
- AlertDialog.Builder builder_rate = new AlertDialog.Builder(this);
- builder_rate.setTitle("Pick a baud rate");
- builder_rate.setItems(rates,
- new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int item) {
- setBaud(rates[item]);
- }
- });
- AlertDialog alert_rate = builder_rate.create();
- alert_rate.show();
- return true;
- case R.id.change_units:
- boolean imperial = AltosPreferences.imperial_units();
- AltosPreferences.set_imperial_units(!imperial);
- return true;
- case R.id.preload_maps:
- serverIntent = new Intent(this, PreloadMapActivity.class);
- startActivityForResult(serverIntent, REQUEST_PRELOAD_MAPS);
- return true;
- case R.id.map_type:
- serverIntent = new Intent(this, MapTypeActivity.class);
- startActivityForResult(serverIntent, REQUEST_MAP_TYPE);
- return true;
- case R.id.map_source:
- int source = AltosDroidPreferences.map_source();
- int new_source = source == AltosDroidPreferences.MAP_SOURCE_ONLINE ? AltosDroidPreferences.MAP_SOURCE_OFFLINE : AltosDroidPreferences.MAP_SOURCE_ONLINE;
- AltosDroidPreferences.set_map_source(new_source);
- set_map_source(new_source);
- return true;
case R.id.select_tracker:
if (serials != null) {
String[] trackers = new String[serials.length+1];
}
return true;
+ case R.id.idle_mode:
+ serverIntent = new Intent(this, IdleModeActivity.class);
+ serverIntent.putExtra(EXTRA_IDLE_MODE, idle_mode);
+ startActivityForResult(serverIntent, REQUEST_IDLE_MODE);
+ return true;
}
return false;
}
static String direction(AltosGreatCircle from_receiver,
- Location receiver) {
+ Location receiver) {
if (from_receiver == null)
return null;
else
return String.format("right %d°", iheading);
}
+
+ public void onLocationChanged(Location location) {
+ this.location = location;
+ AltosDebug.debug("Location changed to %f,%f",
+ location.getLatitude(),
+ location.getLongitude());
+ update_ui(telemetry_state, saved_state);
+ }
+
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+ AltosDebug.debug("Location status now %d\n", status);
+ }
+
+ public void onProviderEnabled(String provider) {
+ AltosDebug.debug("Location provider enabled %s\n", provider);
+ }
+
+ public void onProviderDisabled(String provider) {
+ AltosDebug.debug("Location provider disabled %s\n", provider);
+ }
}
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosDroidLink extends AltosLink {
}
buffer_off = 0;
}
- if (AltosDebug.D)
- debug_input(in_buffer[buffer_off]);
+// if (AltosDebug.D)
+// debug_input(in_buffer[buffer_off]);
return in_buffer[buffer_off++];
}
public void print(String data) {
byte[] bytes = data.getBytes();
- AltosDebug.debug("print(): begin");
+// AltosDebug.debug(data.replace('\n', '\\'));
for (byte b : bytes)
putchar(b);
- AltosDebug.debug("print(): Wrote bytes: '" + data.replace('\n', '\\') + "'");
}
public AltosDroidLink(Handler handler) {
import java.util.*;
import java.io.*;
import android.location.Location;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public interface AltosDroidMapInterface {
public void onCreateView(AltosDroid altos_droid);
+ public void onDestroyView();
+
public void set_visible(boolean visible);
public void center(double lat, double lon, double accuracy);
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+public interface AltosDroidMapSourceListener {
+ public void map_source_changed(int map_source);
+}
*/
package org.altusmetrum.AltosDroid;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
import android.content.Context;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDroidPreferences extends AltosPreferences {
}
}
+ static LinkedList<AltosDroidMapSourceListener> map_source_listeners;
+
public static void set_map_source(int map_source) {
synchronized(backend) {
AltosDroidPreferences.map_source = map_source;
backend.putInt(mapSourcePreference, map_source);
flush_preferences();
}
+ if (map_source_listeners != null) {
+ for (AltosDroidMapSourceListener l : map_source_listeners) {
+ l.map_source_changed(map_source);
+ }
+ }
}
public static int map_source() {
return map_source;
}
}
+
+ public static void register_map_source_listener(AltosDroidMapSourceListener l) {
+ synchronized(backend) {
+ if (map_source_listeners == null)
+ map_source_listeners = new LinkedList<AltosDroidMapSourceListener>();
+ map_source_listeners.add(l);
+ }
+ }
+
+ public static void unregister_map_source_listener(AltosDroidMapSourceListener l) {
+ synchronized(backend) {
+ map_source_listeners.remove(l);
+ }
+ }
}
import android.os.Environment;
import android.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
+public class AltosDroidPreferencesBackend extends AltosPreferencesBackend {
public final static String NAME = "org.altusmetrum.AltosDroid";
private Context context = null;
private SharedPreferences prefs = null;
}
public AltosPreferencesBackend node(String key) {
+ if (!nodeExists(key))
+ putBoolean(key, true);
return new AltosDroidPreferencesBackend(context, key);
}
public File homeDirectory() {
return Environment.getExternalStorageDirectory();
}
+
+ public void debug(String format, Object ... arguments) {
+ AltosDebug.debug(format, arguments);
+ }
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.location.Location;
import android.app.Activity;
import android.graphics.Color;
public abstract String tab_name();
- public void set_map_type(int map_type) {
- }
-
- public void set_map_source(int map_source) {
- }
-
public void units_changed(boolean imperial_units) {
if (!isHidden())
show(last_telem_state, last_state, last_from_receiver, last_receiver);
import java.util.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
}
}
-public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface {
+public class AltosMapOffline extends View implements ScaleGestureDetector.OnScaleGestureListener, AltosMapInterface, AltosDroidMapInterface, AltosMapTypeListener {
ScaleGestureDetector scale_detector;
boolean scaling;
AltosMap map;
if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA))
return;
- AltosImage altos_image = cache.get(this, store, px_size, px_size);
+ AltosImage altos_image = this.get_image();
MapImage map_image = (MapImage) altos_image;
if (t.has_location()) {
String message = null;
switch (status) {
- case AltosMapTile.loading:
- message = "Loading...";
+ case AltosMapTile.fetching:
+ message = "Fetching...";
break;
case AltosMapTile.bad_request:
message = "Internal error";
}
}
- public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size, 2);
+ public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size, 2);
}
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public AltosMapPath new_path() {
}
public void show(TelemetryState telem_state, AltosState state, AltosGreatCircle from_receiver, Location receiver) {
+ boolean changed = false;
+
if (state != null) {
map.show(state, null);
if (state.pad_lat != AltosLib.MISSING && pad == null)
}
}
if (receiver != null) {
- here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+ AltosLatLon new_here = new AltosLatLon(receiver.getLatitude(), receiver.getLongitude());
+ if (!new_here.equals(here)) {
+ here = new_here;
+ AltosDebug.debug("Location changed, redraw");
+ repaint();
+ }
}
}
public void onCreateView(AltosDroid altos_droid) {
this.altos_droid = altos_droid;
map = new AltosMap(this);
- map.set_maptype(altos_droid.map_type);
+ AltosPreferences.register_map_type_listener(this);
+ map.set_maptype(AltosPreferences.map_type());
pad_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pad);
/* arrow at the bottom of the launchpad image */
here_off_y = here_bitmap.getHeight() / 2;
}
- public void set_map_type(int map_type) {
+ public void onDestroyView() {
+ AltosPreferences.unregister_map_type_listener(this);
+ }
+
+ public void map_type_changed(int map_type) {
if (map != null)
map.set_maptype(map_type);
}
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import com.google.android.gms.maps.*;
import com.google.android.gms.maps.model.*;
}
}
-public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener {
+public class AltosMapOnline implements AltosDroidMapInterface, GoogleMap.OnMarkerClickListener, GoogleMap.OnMapClickListener, AltosMapTypeListener {
public SupportMapFragment mMapFragment;
private GoogleMap mMap;
private boolean mapLoaded = false;
public void onCreateView(AltosDroid altos_droid) {
this.altos_droid = altos_droid;
- final int map_type = altos_droid.map_type;
+ final int map_type = AltosPreferences.map_type();
+ AltosPreferences.register_map_type_listener(this);
mMapFragment = new SupportMapFragment() {
@Override
public void onActivityCreated(Bundle savedInstanceState) {
};
}
-// public void onActivityCreated() {
-// getChildFragmentManager().beginTransaction().add(R.id.map, mMapFragment).commit();
-// }
+ public void onDestroyView() {
+ AltosPreferences.unregister_map_type_listener(this);
+ }
private double pixel_distance(LatLng a, LatLng b) {
Projection projection = mMap.getProjection();
public void setupMap(int map_type) {
mMap = mMapFragment.getMap();
if (mMap != null) {
- set_map_type(map_type);
+ map_type_changed(map_type);
mMap.setMyLocationEnabled(true);
mMap.getUiSettings().setTiltGesturesEnabled(false);
mMap.getUiSettings().setZoomControlsEnabled(false);
mPadMarker.setVisible(true);
}
}
- if (state.gps != null) {
+ if (state.gps != null && state.gps.lat != AltosLib.MISSING) {
target_position = new AltosLatLon(state.gps.lat, state.gps.lon);
if (state.gps.locked && state.gps.nsat >= 4)
}
- public void set_map_type(int map_type) {
+ public void map_type_changed(int map_type) {
if (mMap != null) {
if (map_type == AltosMap.maptype_hybrid)
mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
import android.app.*;
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUsb extends AltosDroidLink {
import android.speech.tts.TextToSpeech.OnInitListener;
import android.location.Location;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosVoice {
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Bundle;
+import android.view.View;
+import android.view.Window;
+import android.view.View.OnClickListener;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class IdleModeActivity extends Activity {
+ private EditText callsign;
+ private Button connect;
+ private Button disconnect;
+ private Button reboot;
+ private Button igniters;
+
+ public static final String EXTRA_IDLE_MODE = "idle_mode";
+ public static final String EXTRA_IDLE_RESULT = "idle_result";
+
+ public static final int IDLE_MODE_CONNECT = 1;
+ public static final int IDLE_MODE_REBOOT = 2;
+ public static final int IDLE_MODE_IGNITERS = 3;
+ public static final int IDLE_MODE_DISCONNECT = 4;
+
+ private void done(int type) {
+ AltosPreferences.set_callsign(callsign());
+ Intent intent = new Intent();
+ intent.putExtra(EXTRA_IDLE_RESULT, type);
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private String callsign() {
+ return callsign.getEditableText().toString();
+ }
+
+ public void connect_idle() {
+ done(IDLE_MODE_CONNECT);
+ }
+
+ public void disconnect_idle() {
+ AltosDebug.debug("Disconnect idle button pressed");
+ done(IDLE_MODE_DISCONNECT);
+ }
+
+ public void reboot_idle() {
+ done(IDLE_MODE_REBOOT);
+ }
+
+ public void igniters_idle() {
+ done(IDLE_MODE_IGNITERS);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.idle_mode);
+
+ callsign = (EditText) findViewById(R.id.set_callsign);
+ callsign.setText(new StringBuffer(AltosPreferences.callsign()));
+
+ connect = (Button) findViewById(R.id.connect_idle);
+ connect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ connect_idle();
+ }
+ });
+ disconnect = (Button) findViewById(R.id.disconnect_idle);
+ disconnect.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ disconnect_idle();
+ }
+ });
+
+ boolean idle_mode = getIntent().getBooleanExtra(AltosDroid.EXTRA_IDLE_MODE, false);
+
+ if (idle_mode)
+ connect.setVisibility(View.GONE);
+ else
+ disconnect.setVisibility(View.GONE);
+
+ reboot = (Button) findViewById(R.id.reboot_idle);
+ reboot.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ reboot_idle();
+ }
+ });
+ igniters = (Button) findViewById(R.id.igniters_idle);
+ igniters.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ igniters_idle();
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class IgniterItem {
+ public String name;
+ public String pretty;
+ public String status;
+ public LinearLayout igniter_view = null;
+ public TextView pretty_view = null;
+ public TextView status_view = null;
+
+ private void update() {
+ if (pretty_view != null)
+ pretty_view.setText(pretty);
+ if (status_view != null)
+ status_view.setText(status);
+ }
+
+ public void set(String name, String pretty, String status) {
+ if (!name.equals(this.name) ||
+ !pretty.equals(this.pretty) ||
+ !status.equals(this.status))
+ {
+ this.name = name;
+ this.pretty = pretty;
+ this.status = status;
+ update();
+ }
+ }
+
+ public void realize(LinearLayout igniter_view,
+ TextView pretty_view,
+ TextView status_view) {
+ if (igniter_view != this.igniter_view ||
+ pretty_view != this.pretty_view ||
+ status_view != this.status_view)
+ {
+ this.igniter_view = igniter_view;
+ this.pretty_view = pretty_view;
+ this.status_view = status_view;
+ update();
+ }
+ }
+
+ public IgniterItem() {
+ }
+}
+
+class IgniterAdapter extends ArrayAdapter<IgniterItem> {
+ int resource;
+ int selected_item = -1;
+
+ public IgniterAdapter(Context context, int in_resource) {
+ super(context, in_resource);
+ resource = in_resource;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ IgniterItem item = getItem(position);
+ if (item.igniter_view == null) {
+ LinearLayout igniter_view = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+ li.inflate(resource, igniter_view, true);
+
+ item.realize(igniter_view,
+ (TextView) igniter_view.findViewById(R.id.igniter_name),
+ (TextView) igniter_view.findViewById(R.id.igniter_status));
+ }
+ if (position == selected_item)
+ item.igniter_view.setBackgroundColor(Color.RED);
+ else
+ item.igniter_view.setBackgroundColor(Color.BLACK);
+ return item.igniter_view;
+ }
+}
+
+public class IgniterActivity extends Activity {
+ private ListView igniters_view;
+ private ToggleButton arm;
+ private Button fire;
+
+ private HashMap<String,IgniterItem> igniters = new HashMap<String,IgniterItem>();;
+
+ private IgniterAdapter igniters_adapter;
+
+ private boolean is_bound;
+ private Messenger service = null;
+ private final Messenger messenger = new Messenger(new IncomingHandler(this));
+
+ private Timer query_timer;
+ private boolean query_timer_running;
+
+ private Timer arm_timer;
+ private int arm_remaining;
+
+ public static final int IGNITER_QUERY = 1;
+ public static final int IGNITER_FIRE = 2;
+
+ // The Handler that gets information back from the Telemetry Service
+ static class IncomingHandler extends Handler {
+ private final WeakReference<IgniterActivity> igniter_activity;
+ IncomingHandler(IgniterActivity ia) { igniter_activity = new WeakReference<IgniterActivity>(ia); }
+
+ @Override
+ public void handleMessage(Message msg) {
+ IgniterActivity ia = igniter_activity.get();
+
+ switch (msg.what) {
+ case AltosDroid.MSG_IGNITER_STATUS:
+ ia.igniter_status((HashMap <String,Integer>) msg.obj);
+ break;
+ }
+ }
+ };
+
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = new Messenger(binder);
+ query_timer_tick();
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+ service = null;
+ }
+ };
+
+ void doBindService() {
+ bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+ is_bound = true;
+ }
+
+ void doUnbindService() {
+ if (is_bound) {
+ // If we have received the service, and hence registered with it, then now is the time to unregister.
+ unbindService(connection);
+ is_bound = false;
+ }
+ }
+
+ private void done() {
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ class FireThread extends Thread {
+ private final String igniter;
+
+ @Override
+ public void run() {
+ Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_FIRE, igniter);
+ try {
+ service.send(msg);
+ } catch (RemoteException re) {
+ }
+ }
+
+ public FireThread(String igniter) {
+ this.igniter = igniter;
+ }
+ }
+
+ private void fire_igniter() {
+ if (igniters_adapter.selected_item >= 0) {
+ IgniterItem item = igniters_adapter.getItem(igniters_adapter.selected_item);
+ FireThread ft = new FireThread(item.name);
+ ft.run();
+ arm.setChecked(false);
+ }
+ }
+
+ private void arm_igniter(boolean is_checked) {
+ if (is_checked) {
+ arm_timer_stop();
+ arm_timer = new Timer();
+ arm_remaining = 10;
+ arm_set_text();
+ fire.setEnabled(true);
+ arm_timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ arm_timer_tick();
+ }},
+ 1000L, 1000L);
+ } else {
+ arm_timer_stop();
+ fire.setEnabled(false);
+ }
+ }
+
+ private synchronized void query_timer_tick() {
+ if (query_timer_running)
+ return;
+ if (service == null)
+ return;
+ query_timer_running = true;
+ Thread thread = new Thread(new Runnable() {
+ public void run() {
+ try {
+ Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY);
+ msg.replyTo = messenger;
+ if (service == null) {
+ synchronized(IgniterActivity.this) {
+ query_timer_running = false;
+ }
+ } else
+ service.send(msg);
+ } catch (RemoteException re) {
+ AltosDebug.debug("igniter query thread failed");
+ synchronized(IgniterActivity.this) {
+ query_timer_running = false;
+ }
+ }
+ }
+ });
+ thread.start();
+ }
+
+ private boolean set_igniter(HashMap <String,Integer> status, String name, String pretty) {
+ if (!status.containsKey(name))
+ return false;
+
+ IgniterItem item;
+ if (!igniters.containsKey(name)) {
+ item = new IgniterItem();
+ igniters.put(name, item);
+ igniters_adapter.add(item);
+ } else
+ item = igniters.get(name);
+
+ item.set(name, pretty, AltosIgnite.status_string(status.get(name)));
+ return true;
+ }
+
+ private synchronized void igniter_status(HashMap <String,Integer> status) {
+ query_timer_running = false;
+ if (status == null) {
+ AltosDebug.debug("no igniter status");
+ return;
+ }
+ set_igniter(status, "drogue", "Apogee");
+ set_igniter(status, "main", "Main");
+ for (int extra = 0;; extra++) {
+ String name = String.format("%d", extra);
+ String pretty = String.format("%c", 'A' + extra);
+ if (!set_igniter(status, name, pretty))
+ break;
+ }
+ }
+
+ private synchronized void arm_timer_stop() {
+ if (arm_timer != null) {
+ arm_timer.cancel();
+ arm_timer = null;
+ }
+ arm_remaining = 0;
+ }
+
+ private void arm_set_text() {
+ String text = String.format("Armed %d", arm_remaining);
+
+ if (arm.isChecked())
+ arm.setText(text);
+ arm.setTextOn(text);
+ }
+
+ private void arm_timer_tick() {
+ --arm_remaining;
+ if (arm_remaining <= 0) {
+ arm_timer_stop();
+ runOnUiThread(new Runnable() {
+ public void run() {
+ arm.setChecked(false);
+ fire.setEnabled(false);
+ }
+ });
+ } else {
+ runOnUiThread(new Runnable() {
+ public void run() {
+ arm_set_text();
+ }
+ });
+ }
+ }
+
+ private void select_item(int position) {
+ if (position != igniters_adapter.selected_item) {
+ if (igniters_adapter.selected_item >= 0)
+ igniters_view.setItemChecked(igniters_adapter.selected_item, false);
+ if (position >= 0) {
+ igniters_view.setItemChecked(position, true);
+ arm.setEnabled(true);
+ } else
+ arm.setEnabled(false);
+ igniters_adapter.selected_item = position;
+ }
+ }
+
+ private class IgniterItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+ AltosDebug.debug("select %d\n", position);
+ select_item(position);
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.igniters);
+
+ igniters_view = (ListView) findViewById(R.id.igniters);
+ igniters_view.setClickable(true);
+
+ igniters_adapter = new IgniterAdapter(this, R.layout.igniter_status);
+
+ igniters_view.setAdapter(igniters_adapter);
+ igniters_view.setOnItemClickListener(new IgniterItemClickListener());
+
+ fire = (Button) findViewById(R.id.igniter_fire);
+ fire.setEnabled(false);
+ fire.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ fire_igniter();
+ }
+ });
+
+ arm = (ToggleButton) findViewById(R.id.igniter_arm);
+ arm.setEnabled(false);
+ arm.setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
+ public void onCheckedChanged(CompoundButton v, boolean is_checked) {
+ arm_igniter(is_checked);
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ doBindService();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ query_timer = new Timer(true);
+ query_timer.scheduleAtFixedRate(new TimerTask() {
+ public void run() {
+ query_timer_tick();
+ }},
+ 0L, 5000L);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ if (query_timer != null) {
+ query_timer.cancel();
+ query_timer = null;
+ }
+ arm_timer_stop();
+ arm.setChecked(false);
+ fire.setEnabled(false);
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ doUnbindService();
+ }
+}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import java.text.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.content.*;
+import android.graphics.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.view.inputmethod.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+class FrequencyItem {
+ public AltosFrequency frequency;
+ public LinearLayout frequency_view = null;
+ public TextView pretty_view = null;
+
+ private void update() {
+ if (pretty_view != null && frequency != null)
+ pretty_view.setText(frequency.toString());
+ }
+
+ public void realize(LinearLayout frequency_view,
+ TextView pretty_view) {
+ if (frequency_view != this.frequency_view ||
+ pretty_view != this.pretty_view)
+ {
+ this.frequency_view = frequency_view;
+ this.pretty_view = pretty_view;
+ update();
+ }
+ }
+
+ public void set_frequency(AltosFrequency frequency) {
+ this.frequency = frequency;
+ update();
+ }
+
+ public FrequencyItem(AltosFrequency frequency) {
+ this.frequency = frequency;
+ }
+}
+
+class FrequencyAdapter extends ArrayAdapter<FrequencyItem> {
+ int resource;
+ int selected_item = -1;
+
+ public FrequencyAdapter(Context context, int in_resource) {
+ super(context, in_resource);
+ resource = in_resource;
+ }
+
+ public int count() {
+ int count;
+
+ for (count = 0;; count++) {
+ try {
+ getItem(count);
+ } catch (IndexOutOfBoundsException ie) {
+ return count;
+ }
+ }
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ FrequencyItem item = getItem(position);
+ if (item.frequency_view == null) {
+ LinearLayout frequency_view = new LinearLayout(getContext());
+ String inflater = Context.LAYOUT_INFLATER_SERVICE;
+ LayoutInflater li = (LayoutInflater) getContext().getSystemService(inflater);
+ li.inflate(resource, frequency_view, true);
+
+ item.realize(frequency_view,
+ (TextView) frequency_view.findViewById(R.id.frequency));
+ }
+ if (position == selected_item)
+ item.frequency_view.setBackgroundColor(Color.RED);
+ else
+ item.frequency_view.setBackgroundColor(Color.BLACK);
+ return item.frequency_view;
+ }
+}
+
+public class ManageFrequenciesActivity extends Activity {
+ private ListView frequencies_view;
+
+ private Button set;
+ private Button remove;
+ private Button done;
+
+ private EditText set_frequency;
+ private EditText set_description;
+
+ private HashMap<String,FrequencyItem> frequencies = new HashMap<String,FrequencyItem>();;
+
+ private FrequencyAdapter frequencies_adapter;
+
+ private boolean is_bound;
+ private boolean changed = false;
+
+ private void done() {
+
+ if (changed) {
+ AltosFrequency[] frequencies = new AltosFrequency[frequencies_adapter.count()];
+ for (int i = 0; i < frequencies.length; i++)
+ frequencies[i] = frequencies_adapter.getItem(i).frequency;
+ AltosPreferences.set_common_frequencies(frequencies);
+ }
+
+ Intent intent = new Intent();
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private void load_item() {
+ if (frequencies_adapter.selected_item >= 0) {
+ FrequencyItem item = frequencies_adapter.getItem(frequencies_adapter.selected_item);
+
+ set_frequency.setText(item.frequency.frequency_string());
+ set_description.setText(item.frequency.description);
+ } else {
+ set_frequency.setText("");
+ set_description.setText("");
+ }
+ }
+
+ private void select_item(int position) {
+ if (position != frequencies_adapter.selected_item) {
+ if (frequencies_adapter.selected_item >= 0)
+ frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+ if (position >= 0)
+ frequencies_view.setItemChecked(position, true);
+ frequencies_adapter.selected_item = position;
+ } else {
+ if (frequencies_adapter.selected_item >= 0)
+ frequencies_view.setItemChecked(frequencies_adapter.selected_item, false);
+ frequencies_adapter.selected_item = -1;
+ }
+ load_item();
+ }
+
+ private int insert_item(AltosFrequency frequency) {
+ FrequencyItem new_item = new FrequencyItem(frequency);
+ int pos;
+ for (pos = 0; pos < frequencies_adapter.getCount(); pos++) {
+ FrequencyItem item = frequencies_adapter.getItem(pos);
+ if (item.frequency.frequency == new_item.frequency.frequency) {
+ item.set_frequency(frequency);
+ return pos;
+ }
+ if (item.frequency.frequency > new_item.frequency.frequency)
+ break;
+ }
+ frequencies_adapter.insert(new_item, pos);
+ return pos;
+ }
+
+ private class FrequencyItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> av, View v, int position, long id) {
+ select_item(position);
+ }
+ }
+
+ private void hide_keyboard() {
+ InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
+ View view = getCurrentFocus();
+ if (view != null)
+ imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
+ }
+
+ private void set() {
+ String frequency_text = set_frequency.getEditableText().toString();
+ String description_text = set_description.getEditableText().toString();
+
+ try {
+ double f = AltosParse.parse_double_locale(frequency_text);
+
+ int pos = insert_item(new AltosFrequency(f, description_text));
+ frequencies_adapter.selected_item = -1;
+ select_item(pos);
+ changed = true;
+ } catch (ParseException pe) {
+ }
+ hide_keyboard();
+ }
+
+ private void remove() {
+ if (frequencies_adapter.selected_item >= 0) {
+ frequencies_adapter.remove(frequencies_adapter.getItem(frequencies_adapter.selected_item));
+ select_item(-1);
+ frequencies_view.setAdapter(frequencies_adapter);
+ changed = true;
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.manage_frequencies);
+
+ frequencies_view = (ListView) findViewById(R.id.frequencies);
+ frequencies_view.setClickable(true);
+
+ frequencies_adapter = new FrequencyAdapter(this, R.layout.frequency);
+
+ frequencies_view.setAdapter(frequencies_adapter);
+ frequencies_view.setOnItemClickListener(new FrequencyItemClickListener());
+
+ AltosFrequency[] frequencies = AltosPreferences.common_frequencies();
+ for (AltosFrequency frequency : frequencies)
+ insert_item(frequency);
+
+ set_frequency = (EditText) findViewById(R.id.set_frequency);
+ set_description = (EditText) findViewById(R.id.set_description);
+
+ set = (Button) findViewById(R.id.set);
+ set.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ set();
+ }
+ });
+
+ remove = (Button) findViewById(R.id.remove);
+ remove.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ remove();
+ }
+ });
+
+ done = (Button) findViewById(R.id.done);
+ done.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ done();
+ }
+ });
+
+ // Set result CANCELED incase the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ }
+}
import android.widget.*;
import android.widget.AdapterView.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class MapTypeActivity extends Activity {
private Button hybrid;
import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
/**
* This Activity appears as a dialog. It lists any paired devices and
}
AltosMap map;
- AltosMapLoader loader;
class PreloadMapImage implements AltosImage {
public void flush() {
public void paint(AltosMapTransform t) {
}
- public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size, 2);
+ public PreloadMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size, 2);
}
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new PreloadMapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public int width() {
AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n",
lat, lon, min, max, r, t);
- loader.load(lat, lon, min, max, r, t);
+ new AltosMapLoader(map, this, lat, lon, min, max, r, t);
} catch (ParseException e) {
AltosDebug.debug("PreloadMap load raised exception %s", e.toString());
}
map = new AltosMap(this);
- loader = new AltosMapLoader(map, this);
-
// Listen for GPS and Network position updates
LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.AltosDroid;
+
+import java.lang.ref.WeakReference;
+import java.util.*;
+import org.altusmetrum.AltosDroid.R;
+
+import android.app.Activity;
+import android.bluetooth.*;
+import android.content.*;
+import android.os.*;
+import android.view.*;
+import android.view.View.*;
+import android.widget.*;
+import android.widget.AdapterView.*;
+
+import org.altusmetrum.altoslib_10.*;
+
+public class SetupActivity extends Activity {
+ private Spinner select_rate;
+ private Spinner set_units;
+ private Spinner map_type;
+ private Spinner map_source;
+ private Button manage_frequencies;
+ private Button preload_maps;
+ private Button done;
+
+ private boolean is_bound;
+ private Messenger service = null;
+
+ public final static String EXTRA_SETUP_CHANGES = "setup_changes";
+
+ private ServiceConnection connection = new ServiceConnection() {
+ public void onServiceConnected(ComponentName className, IBinder binder) {
+ service = new Messenger(binder);
+ }
+
+ public void onServiceDisconnected(ComponentName className) {
+ // This is called when the connection with the service has been unexpectedly disconnected - process crashed.
+ service = null;
+ }
+ };
+
+ void doBindService() {
+ bindService(new Intent(this, TelemetryService.class), connection, Context.BIND_AUTO_CREATE);
+ is_bound = true;
+ }
+
+ void doUnbindService() {
+ if (is_bound) {
+ // If we have received the service, and hence registered with it, then now is the time to unregister.
+ unbindService(connection);
+ is_bound = false;
+ }
+ }
+
+ static final String[] rates = {
+ "38400",
+ "9600",
+ "2400",
+ };
+
+ static final String[] map_types = {
+ "Hybrid",
+ "Satellite",
+ "Roadmap",
+ "Terrain"
+ };
+
+ static final int[] map_type_values = {
+ AltosMap.maptype_hybrid,
+ AltosMap.maptype_satellite,
+ AltosMap.maptype_roadmap,
+ AltosMap.maptype_terrain,
+ };
+
+ static final String[] map_sources = {
+ "Online",
+ "Offline"
+ };
+
+ private int set_telemetry_rate;
+ private int set_map_source;
+ private int set_map_type;
+ private boolean set_imperial_units;
+
+ private int changes = 0;
+
+ private void add_change(int change) {
+ changes |= change;
+ }
+
+ private void done() {
+ Intent intent = new Intent();
+ if ((changes & AltosDroid.SETUP_BAUD) != 0)
+ AltosPreferences.set_telemetry_rate(1, set_telemetry_rate);
+ if ((changes & AltosDroid.SETUP_UNITS) != 0)
+ AltosPreferences.set_imperial_units(set_imperial_units);
+ if ((changes & AltosDroid.SETUP_MAP_SOURCE) != 0)
+ AltosDroidPreferences.set_map_source(set_map_source);
+ if ((changes & AltosDroid.SETUP_MAP_TYPE) != 0)
+ AltosPreferences.set_map_type(set_map_type);
+ intent.putExtra(EXTRA_SETUP_CHANGES, changes);
+ setResult(Activity.RESULT_OK, intent);
+ finish();
+ }
+
+ private void add_strings(Spinner spinner, String[] strings, int def) {
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item);
+
+ for (int i = 0; i < strings.length; i++)
+ adapter.add(strings[i]);
+
+ spinner.setAdapter(adapter);
+ if (def >= 0)
+ spinner.setSelection(def);
+ }
+
+ private int default_rate_pos() {
+ int default_rate = AltosPreferences.telemetry_rate(1);
+
+ for (int pos = 0; pos < rates.length; pos++) {
+ if (string_to_rate(rates[pos]) == default_rate)
+ return pos;
+ }
+ return -1;
+ }
+
+ private void setBaud(int baud) {
+ try {
+ service.send(Message.obtain(null, TelemetryService.MSG_SETBAUD, baud));
+ set_telemetry_rate = baud;
+ add_change(AltosDroid.SETUP_BAUD);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private int string_to_rate(String baud) {
+ int rate = AltosLib.ao_telemetry_rate_38400;
+ try {
+ int value = Integer.parseInt(baud);
+ switch (value) {
+ case 2400:
+ rate = AltosLib.ao_telemetry_rate_2400;
+ break;
+ case 9600:
+ rate = AltosLib.ao_telemetry_rate_9600;
+ break;
+ case 38400:
+ rate = AltosLib.ao_telemetry_rate_38400;
+ break;
+ }
+ } catch (NumberFormatException e) {
+ }
+ return rate;
+ }
+
+ private void setBaud(String baud) {
+ setBaud(string_to_rate(baud));
+ }
+
+ private void select_rate(int pos) {
+ setBaud(rates[pos]);
+ }
+
+ static final String[] units = {
+ "Metric",
+ "Imperial"
+ };
+
+ private int default_units_pos() {
+ boolean imperial = AltosPreferences.imperial_units();
+
+ if (imperial)
+ return 1;
+ return 0;
+ }
+
+ private void set_units(int pos) {
+ switch (pos) {
+ default:
+ set_imperial_units = false;
+ break;
+ case 1:
+ set_imperial_units = true;
+ break;
+ }
+ add_change(AltosDroid.SETUP_UNITS);
+ }
+
+ private int default_map_type_pos() {
+ int default_map_type = AltosPreferences.map_type();
+
+ for (int pos = 0; pos < map_types.length; pos++)
+ if (map_type_values[pos] == default_map_type)
+ return pos;
+ return 0;
+ }
+
+ private void select_map_type(int pos) {
+ set_map_type = map_type_values[pos];
+ add_change(AltosDroid.SETUP_MAP_TYPE);
+ }
+
+ private int default_map_source_pos() {
+ int default_source = AltosDroidPreferences.map_source();
+
+ switch (default_source) {
+ case AltosDroidPreferences.MAP_SOURCE_OFFLINE:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+
+ private void select_map_source(int pos) {
+ switch (pos) {
+ default:
+ set_map_source = AltosDroidPreferences.MAP_SOURCE_ONLINE;
+ break;
+ case 1:
+ set_map_source = AltosDroidPreferences.MAP_SOURCE_OFFLINE;
+ break;
+ }
+ add_change(AltosDroid.SETUP_MAP_SOURCE);
+ }
+
+ private void manage_frequencies(){
+ Intent intent = new Intent(this, ManageFrequenciesActivity.class);
+ startActivity(intent);
+ }
+
+ private void preload_maps(){
+ Intent intent = new Intent(this, PreloadMapActivity.class);
+ startActivity(intent);
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Setup the window
+ requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
+ setContentView(R.layout.setup);
+
+ select_rate = (Spinner) findViewById(R.id.select_rate);
+ add_strings(select_rate, rates, default_rate_pos());
+ select_rate.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_rate(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ set_units = (Spinner) findViewById(R.id.set_units);
+ add_strings(set_units, units, default_units_pos());
+ set_units.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ set_units(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ map_type = (Spinner) findViewById(R.id.map_type);
+ add_strings(map_type, map_types, default_map_type_pos());
+ map_type.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_map_type(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+ map_source = (Spinner) findViewById(R.id.map_source);
+ add_strings(map_source, map_sources, default_map_source_pos());
+ map_source.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
+ select_map_source(pos);
+ }
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ });
+
+
+ manage_frequencies = (Button) findViewById(R.id.manage_frequencies);
+ manage_frequencies.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ manage_frequencies();
+ }
+ });
+
+ preload_maps = (Button) findViewById(R.id.preload_maps);
+ preload_maps.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ preload_maps();
+ }
+ });
+
+ done = (Button) findViewById(R.id.done);
+ done.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ done();
+ }
+ });
+
+ // Set result for when the user backs out
+ setResult(Activity.RESULT_CANCELED);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ doBindService();
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ doUnbindService();
+ }
+}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
set_value(speed_view, AltosConvert.speed, 6, state.speed());
set_value(height_view, AltosConvert.height, 6, state.height());
set_value(max_speed_view, AltosConvert.speed, 6, state.max_speed());
- set_value(max_height_view, AltosConvert.speed, 6, state.max_height());
+ set_value(max_height_view, AltosConvert.height, 6, state.max_height());
if (from_receiver != null) {
elevation_view.setText(AltosDroid.number("%3.0f°", from_receiver.elevation));
set_value(range_view, AltosConvert.distance, 6, from_receiver.range);
import java.util.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.graphics.*;
import android.location.Location;
import android.content.*;
-public class TabMap extends AltosDroidTab {
+public class TabMap extends AltosDroidTab implements AltosDroidMapSourceListener {
AltosLatLon here;
map_offline.onCreateView(altos_droid);
map_online = new AltosMapOnline(view.getContext());
map_online.onCreateView(altos_droid);
- set_map_source(AltosDroidPreferences.map_source());
+ map_source_changed(AltosDroidPreferences.map_source());
+ AltosDroidPreferences.register_map_source_listener(this);
return view;
}
@Override
public void onDestroyView() {
super.onDestroyView();
+ map_offline.onDestroyView();
+ map_online.onDestroyView();
+ AltosDroidPreferences.unregister_map_source_listener(this);
}
public String tab_name() { return AltosDroid.tab_map_name; }
}
}
- @Override
- public void set_map_type(int map_type) {
- if (map_offline != null)
- map_offline.set_map_type(map_type);
- if (map_online != null)
- map_online.set_map_type(map_type);
- }
-
- @Override
- public void set_map_source(int map_source) {
+ public void map_source_changed(int map_source) {
this.map_source = map_source;
if (map_source == AltosDroidPreferences.MAP_SOURCE_OFFLINE) {
if (map_online != null)
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.app.Activity;
import android.os.Bundle;
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import java.util.concurrent.*;
import android.os.Handler;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class TelemetryReader extends Thread {
import android.os.RemoteException;
import android.os.Looper;
import android.widget.Toast;
-import android.location.Location;
-import android.location.LocationManager;
-import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
-public class TelemetryService extends Service implements LocationListener {
+public class TelemetryService extends Service implements AltosIdleMonitorListener {
static final int MSG_REGISTER_CLIENT = 1;
static final int MSG_UNREGISTER_CLIENT = 2;
static final int MSG_SETBAUD = 11;
static final int MSG_DISCONNECT = 12;
static final int MSG_DELETE_SERIAL = 13;
+ static final int MSG_BLUETOOTH_ENABLED = 14;
+ static final int MSG_MONITOR_IDLE_START= 15;
+ static final int MSG_MONITOR_IDLE_STOP = 16;
+ static final int MSG_REBOOT = 17;
+ static final int MSG_IGNITER_QUERY = 18;
+ static final int MSG_IGNITER_FIRE = 19;
// Unique Identification Number for the Notification.
// We use it on Notification start, and to cancel it.
// Last data seen; send to UI when it starts
private TelemetryState telemetry_state;
+ // Idle monitor if active
+ AltosIdleMonitor idle_monitor = null;
+
+ // Igniter bits
+ AltosIgnite ignite = null;
+ boolean ignite_running;
+
// Handler of incoming messages from clients.
static class IncomingHandler extends Handler {
private final WeakReference<TelemetryService> service;
@Override
public void handleMessage(Message msg) {
+ DeviceAddress address;
+
TelemetryService s = service.get();
AltosDroidLink bt = null;
if (s == null)
return;
+
switch (msg.what) {
/* Messages from application */
break;
case MSG_CONNECT:
AltosDebug.debug("Connect command received");
- DeviceAddress address = (DeviceAddress) msg.obj;
+ address = (DeviceAddress) msg.obj;
AltosDroidPreferences.set_active_device(address);
s.start_altos_bluetooth(address, false);
break;
s.telemetry_state.crc_errors = (Integer) msg.obj;
s.send_to_clients();
break;
+ case MSG_BLUETOOTH_ENABLED:
+ AltosDebug.debug("TelemetryService notes that BT is now enabled");
+ address = AltosDroidPreferences.active_device();
+ if (address != null && !address.address.startsWith("USB"))
+ s.start_altos_bluetooth(address, false);
+ break;
+ case MSG_MONITOR_IDLE_START:
+ AltosDebug.debug("start monitor idle");
+ s.start_idle_monitor();
+ break;
+ case MSG_MONITOR_IDLE_STOP:
+ AltosDebug.debug("stop monitor idle");
+ s.stop_idle_monitor();
+ break;
+ case MSG_REBOOT:
+ AltosDebug.debug("reboot");
+ s.reboot_remote();
+ break;
+ case MSG_IGNITER_QUERY:
+ AltosDebug.debug("igniter query");
+ s.igniter_query(msg.replyTo);
+ break;
+ case MSG_IGNITER_FIRE:
+ AltosDebug.debug("igniter fire");
+ s.igniter_fire((String) msg.obj);
+ break;
default:
super.handleMessage(msg);
}
telem.update_state(state);
telemetry_state.states.put(telem.serial, state);
if (state != null) {
- AltosPreferences.set_state(telem.serial, state, null);
+ AltosPreferences.set_state(state);
}
send_to_clients();
}
/* On connect, send the current state to the new client
*/
- send_to_client(client, message());
+ send_to_client(client);
+ send_idle_mode_to_client(client);
/* If we've got an address from a previous session, then
* go ahead and try to reconnect to the device
}
}
- private void send_to_client(Messenger client, Message m) {
+ private void send_to_client(Messenger client) {
+ Message m = message();
try {
client.send(m);
} catch (RemoteException e) {
}
private void send_to_clients() {
- Message m = message();
for (Messenger client : clients)
- send_to_client(client, m);
+ send_to_client(client);
}
- private void disconnect(boolean notify) {
- AltosDebug.debug("disconnect(): begin");
-
- telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
- telemetry_state.address = null;
+ private void send_idle_mode_to_client(Messenger client) {
+ Message m = Message.obtain(null, AltosDroid.MSG_IDLE_MODE, idle_monitor != null);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ AltosDebug.error("Client %s disappeared", client.toString());
+ remove_client(client);
+ }
+ }
- if (altos_link != null)
- altos_link.closing();
+ private void send_idle_mode_to_clients() {
+ for (Messenger client : clients)
+ send_idle_mode_to_client(client);
+ }
- stop_receiver_voltage_timer();
+ private void telemetry_start() {
+ if (telemetry_reader == null && idle_monitor == null && !ignite_running) {
+ telemetry_reader = new TelemetryReader(altos_link, handler);
+ telemetry_reader.start();
+ }
+ }
+ private void telemetry_stop() {
if (telemetry_reader != null) {
AltosDebug.debug("disconnect(): stopping TelemetryReader");
telemetry_reader.interrupt();
}
telemetry_reader = null;
}
+ }
+
+ private void disconnect(boolean notify) {
+ AltosDebug.debug("disconnect(): begin");
+
+ telemetry_state.connect = TelemetryState.CONNECT_DISCONNECTED;
+ telemetry_state.address = null;
+
+ if (idle_monitor != null)
+ stop_idle_monitor();
+
+ if (altos_link != null)
+ altos_link.closing();
+
+ stop_receiver_voltage_timer();
+
+ telemetry_stop();
if (telemetry_logger != null) {
AltosDebug.debug("disconnect(): stopping TelemetryLogger");
telemetry_logger.stop();
AltosDebug.debug("disconnect(): stopping AltosDroidLink");
altos_link.close();
altos_link = null;
+ ignite = null;
}
telemetry_state.config = null;
if (notify) {
}
private void start_altos_bluetooth(DeviceAddress address, boolean pause) {
- // Get the BLuetoothDevice object
- BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+ if (bluetooth_adapter == null || !bluetooth_adapter.isEnabled())
+ return;
disconnect(false);
+
+ // Get the BluetoothDevice object
+ BluetoothDevice device = bluetooth_adapter.getRemoteDevice(address.address);
+
this.address = address;
AltosDebug.debug("start_altos_bluetooth(): Connecting to %s (%s)", device.getName(), device.getAddress());
altos_link = new AltosBluetooth(device, handler, pause);
send_to_clients();
}
+ private void start_idle_monitor() {
+ if (altos_link != null && idle_monitor == null) {
+ telemetry_stop();
+ idle_monitor = new AltosIdleMonitor(this, altos_link, true, false);
+ idle_monitor.set_callsign(AltosPreferences.callsign());
+ idle_monitor.start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void stop_idle_monitor() {
+ if (idle_monitor != null) {
+ try {
+ idle_monitor.abort();
+ } catch (InterruptedException ie) {
+ }
+ idle_monitor = null;
+ telemetry_start();
+ send_idle_mode_to_clients();
+ }
+ }
+
+ private void reboot_remote() {
+ if (altos_link != null) {
+ stop_idle_monitor();
+ try {
+ altos_link.start_remote();
+ altos_link.printf("r eboot\n");
+ altos_link.flush_output();
+ } catch (TimeoutException te) {
+ } catch (InterruptedException ie) {
+ } finally {
+ try {
+ altos_link.stop_remote();
+ } catch (InterruptedException ie) {
+ }
+ }
+ }
+ }
+
+ private void ensure_ignite() {
+ if (ignite == null)
+ ignite = new AltosIgnite(altos_link, true, false);
+ }
+
+ private synchronized void igniter_query(Messenger client) {
+ ensure_ignite();
+ HashMap<String,Integer> status_map = null;
+ ignite_running = true;
+ try {
+ stop_idle_monitor();
+ try {
+ status_map = ignite.status();
+ } catch (InterruptedException ie) {
+ AltosDebug.debug("ignite.status interrupted");
+ } catch (TimeoutException te) {
+ AltosDebug.debug("ignite.status timeout");
+ }
+ } finally {
+ ignite_running = false;
+ }
+ Message m = Message.obtain(null, AltosDroid.MSG_IGNITER_STATUS, status_map);
+ try {
+ client.send(m);
+ } catch (RemoteException e) {
+ }
+ }
+
+ private synchronized void igniter_fire(String igniter) {
+ ensure_ignite();
+ ignite_running = true;
+ stop_idle_monitor();
+ try {
+ ignite.fire(igniter);
+ } catch (InterruptedException ie) {
+ } finally {
+ ignite_running = false;
+ }
+ }
+
// Timer for receiver battery voltage monitoring
Timer receiver_voltage_timer;
private void update_receiver_voltage() {
- if (altos_link != null) {
+ if (altos_link != null && idle_monitor == null && !ignite_running) {
try {
double voltage = altos_link.monitor_battery();
telemetry_state.receiver_battery = voltage;
+ send_to_clients();
} catch (InterruptedException ie) {
}
}
telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
telemetry_state.address = address;
- telemetry_reader = new TelemetryReader(altos_link, handler);
- telemetry_reader.start();
+ telemetry_start();
AltosDebug.debug("connected TelemetryReader started");
// Get local Bluetooth adapter
bluetooth_adapter = BluetoothAdapter.getDefaultAdapter();
- // If the adapter is null, then Bluetooth is not supported
- if (bluetooth_adapter == null) {
- Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
- }
-
telemetry_state = new TelemetryState();
// Create a reference to the NotificationManager so that we can update our notifcation text later
telemetry_state.latest_serial = AltosPreferences.latest_state();
for (int serial : serials) {
- AltosSavedState saved_state = AltosPreferences.state(serial);
+ AltosState saved_state = AltosPreferences.state(serial);
if (saved_state != null) {
- if (serial == 0) {
- serial = saved_state.state.serial;
- AltosPreferences.set_state(serial, saved_state.state, saved_state.listener_state);
- AltosPreferences.remove_state(0);
- }
if (telemetry_state.latest_serial == 0)
telemetry_state.latest_serial = serial;
- AltosDebug.debug("recovered old state serial %d flight %d\n",
+ AltosDebug.debug("recovered old state serial %d flight %d",
serial,
- saved_state.state.flight);
- if (saved_state.state.gps != null)
- AltosDebug.debug("\tposition %f,%f\n",
- saved_state.state.gps.lat,
- saved_state.state.gps.lon);
- telemetry_state.states.put(serial, saved_state.state);
+ saved_state.flight);
+ if (saved_state.gps != null)
+ AltosDebug.debug("\tposition %f,%f",
+ saved_state.gps.lat,
+ saved_state.gps.lon);
+ telemetry_state.states.put(serial, saved_state);
+ } else {
+ AltosDebug.debug("Failed to recover state for %d", serial);
}
}
-
- // Listen for GPS and Network position updates
- LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
-
- locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 1, this);
}
@Override
@Override
public void onDestroy() {
- // Stop listening for location updates
- ((LocationManager) getSystemService(Context.LOCATION_SERVICE)).removeUpdates(this);
-
// Stop the bluetooth Comms threads
disconnect(true);
return messenger.getBinder();
}
-
- public void onLocationChanged(Location location) {
- telemetry_state.location = location;
- AltosDebug.debug("location changed");
+ /* AltosIdleMonitorListener */
+ public void update(AltosState state, AltosListenerState listener_state) {
+ telemetry_state.states.put(state.serial, state);
+ telemetry_state.receiver_battery = listener_state.battery;
send_to_clients();
}
- public void onStatusChanged(String provider, int status, Bundle extras) {
+ public void failed() {
}
- public void onProviderEnabled(String provider) {
+ public void error(String reason) {
+ stop_idle_monitor();
}
-
- public void onProviderDisabled(String provider) {
- }
-
}
package org.altusmetrum.AltosDroid;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import android.location.Location;
public class TelemetryState {
int connect;
DeviceAddress address;
AltosConfigData config;
- Location location;
int crc_errors;
double receiver_battery;
double frequency;
connect = CONNECT_NONE;
config = null;
states = new HashMap<Integer,AltosState>();
- location = null;
crc_errors = 0;
receiver_battery = AltosLib.MISSING;
frequency = AltosPreferences.frequency(0);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosCRCException extends Exception {
public int rssi;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
}
+ public boolean mma655x_inverted() throws AltosUnknownProduct {
+ if (product.startsWith("EasyMega-v1"))
+ return false;
+ if (product.startsWith("TeleMetrum-v2"))
+ return true;
+ if (product.startsWith("TeleMega-v2"))
+ return false;
+ if (product.startsWith("TeleMega-v1"))
+ return false;
+ throw new AltosUnknownProduct(product);
+ }
+
public void get_values(AltosConfigValues source) throws AltosConfigDataException {
/* HAS_FLIGHT */
radio_enable = source.radio_enable();
if (callsign != null)
callsign = source.callsign();
- if (radio_calibration >= 0)
- radio_calibration = source.radio_calibration();
if (telemetry_rate >= 0)
telemetry_rate = source.telemetry_rate();
if (apogee_lockout >= 0)
link.printf("c L %d\n", apogee_lockout);
- /* Don't mess with radio calibration when remote */
- if (radio_calibration > 0 && !remote)
- link.printf("c f %d\n", radio_calibration);
-
/* HAS_RADIO */
if (has_frequency()) {
boolean has_frequency = radio_frequency >= 0;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosConfigDataException extends Exception {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosConfigValues {
/* set and get all of the dialog values */
public abstract void set_radio_calibration(int new_radio_calibration);
- public abstract int radio_calibration() throws AltosConfigDataException;
-
public abstract void set_radio_enable(int new_radio_enable);
public abstract int radio_enable();
/*
* Sensor data conversion functions
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosConvert {
/*
return miles_to_meters(mps) / 3600;
}
+ public static double mps_to_fps(double mps) {
+ return meters_to_miles(mps) * 5280;
+ }
+
+ public static double fps_to_mps(double mps) {
+ return miles_to_meters(mps) / 5280;
+ }
+
public static double meters_to_mach(double meters) {
return meters / 343; /* something close to mach at usual rocket sites */
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosDistance extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
eeprom = new AltosEepromTM(this, offset);
break;
case AltosLib.AO_LOG_FORMAT_TINY:
- eeprom = new AltosEepromTm(this, offset, state);
+ eeprom = new AltosEepromTMini(this, offset, state);
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
body = new AltosEepromIterable(AltosEepromTM.read(input));
break;
case AltosLib.AO_LOG_FORMAT_TINY:
- body = new AltosEepromIterable(AltosEepromTm.read(input));
+ body = new AltosEepromIterable(AltosEepromTMini.read(input));
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosEepromMonitor {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_10;
+
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosEepromTMini extends AltosEeprom {
+ public int i;
+ public int a;
+ public int b;
+
+ public static final int record_length = 2;
+
+ public void write(PrintStream out) {
+ out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public int record_length() { return record_length; }
+
+ public String string() {
+ return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
+ }
+
+ public void update_state(AltosState state) {
+ super.update_state(state);
+
+ switch (cmd) {
+ case AltosLib.AO_LOG_FLIGHT:
+ state.set_state(AltosLib.ao_flight_boost);
+ state.set_flight(b);
+ break;
+ case AltosLib.AO_LOG_PRESSURE:
+ if (tick == 0)
+ state.set_ground_pressure(AltosConvert.barometer_to_pressure(b));
+ else
+ state.set_pressure(AltosConvert.barometer_to_pressure(b));
+ break;
+ case AltosLib.AO_LOG_STATE:
+ state.set_state(a);
+ break;
+ }
+ }
+
+ public AltosEepromTMini (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
+ int value = chunk.data16(start);
+
+ int i = (chunk.address + start) / record_length;
+
+ cmd = chunk.data(start);
+ valid = true;
+
+ valid = !chunk.erased(start, record_length);
+
+ switch (i) {
+ case 0:
+ cmd = AltosLib.AO_LOG_FLIGHT;
+ tick = 0;
+ a = 0;
+ b = value;
+ break;
+ case 1:
+ cmd = AltosLib.AO_LOG_PRESSURE;
+ tick = 0;
+ a = 0;
+ b = value;
+ break;
+ default:
+ if ((value & 0x8000) != 0) {
+ cmd = AltosLib.AO_LOG_STATE;
+ tick = state.tick;
+ a = value & 0x7fff;
+ b = 0;
+ } else {
+ if (state.ascent)
+ tick = state.tick + 10;
+ else
+ tick = state.tick + 100;
+ cmd = AltosLib.AO_LOG_PRESSURE;
+ a = 0;
+ b = value;
+ }
+ break;
+ }
+ }
+
+ public AltosEepromTMini (String line) {
+ valid = false;
+ tick = 0;
+ a = 0;
+ b = 0;
+ if (line == null) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ try {
+ String[] tokens = line.split("\\s+");
+
+ if (tokens[0].length() == 1) {
+ if (tokens.length != 4) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ } else {
+ cmd = tokens[0].codePointAt(0);
+ tick = Integer.parseInt(tokens[1],16);
+ valid = true;
+ a = Integer.parseInt(tokens[2],16);
+ b = Integer.parseInt(tokens[3],16);
+ }
+ } else {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ } catch (NumberFormatException ne) {
+ cmd = AltosLib.AO_LOG_INVALID;
+ }
+ }
+ }
+
+ public AltosEepromTMini(int in_cmd, int in_tick, int in_a, int in_b) {
+ valid = true;
+ cmd = in_cmd;
+ tick = in_tick;
+ a = in_a;
+ b = in_b;
+ }
+
+ static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
+
+ for (;;) {
+ try {
+ String line = AltosLib.gets(input);
+ if (line == null)
+ break;
+ AltosEepromTMini tm = new AltosEepromTMini(line);
+ tms.add(tm);
+ } catch (IOException ie) {
+ break;
+ }
+ }
+
+ return tms;
+ }
+
+}
+++ /dev/null
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-package org.altusmetrum.altoslib_9;
-
-import java.io.*;
-import java.util.*;
-import java.text.*;
-
-public class AltosEepromTm extends AltosEeprom {
- public int i;
- public int a;
- public int b;
-
- public static final int record_length = 2;
-
- public void write(PrintStream out) {
- out.printf("%c %4x %4x %4x\n", cmd, tick, a, b);
- }
-
- public int record_length() { return record_length; }
-
- public String string() {
- return String.format("%c %4x %4x %4x\n", cmd, tick, a, b);
- }
-
- public void update_state(AltosState state) {
- super.update_state(state);
-
- switch (cmd) {
- case AltosLib.AO_LOG_FLIGHT:
- state.set_state(AltosLib.ao_flight_boost);
- state.set_flight(b);
- break;
- case AltosLib.AO_LOG_PRESSURE:
- if (tick == 0)
- state.set_ground_pressure(AltosConvert.barometer_to_pressure(b));
- else
- state.set_pressure(AltosConvert.barometer_to_pressure(b));
- break;
- case AltosLib.AO_LOG_STATE:
- state.set_state(a);
- break;
- }
- }
-
- public AltosEepromTm (AltosEepromChunk chunk, int start, AltosState state) throws ParseException {
- int value = chunk.data16(start);
-
- int i = (chunk.address + start) / record_length;
-
- cmd = chunk.data(start);
- valid = true;
-
- valid = !chunk.erased(start, record_length);
-
- switch (i) {
- case 0:
- cmd = AltosLib.AO_LOG_FLIGHT;
- tick = 0;
- a = 0;
- b = value;
- break;
- case 1:
- cmd = AltosLib.AO_LOG_PRESSURE;
- tick = 0;
- a = 0;
- b = value;
- break;
- default:
- if ((value & 0x8000) != 0) {
- cmd = AltosLib.AO_LOG_STATE;
- tick = state.tick;
- a = value & 0x7fff;
- b = 0;
- } else {
- if (state.ascent)
- tick = state.tick + 10;
- else
- tick = state.tick + 100;
- cmd = AltosLib.AO_LOG_PRESSURE;
- a = 0;
- b = value;
- }
- break;
- }
- }
-
- public AltosEepromTm (String line) {
- valid = false;
- tick = 0;
- a = 0;
- b = 0;
- if (line == null) {
- cmd = AltosLib.AO_LOG_INVALID;
- } else {
- try {
- String[] tokens = line.split("\\s+");
-
- if (tokens[0].length() == 1) {
- if (tokens.length != 4) {
- cmd = AltosLib.AO_LOG_INVALID;
- } else {
- cmd = tokens[0].codePointAt(0);
- tick = Integer.parseInt(tokens[1],16);
- valid = true;
- a = Integer.parseInt(tokens[2],16);
- b = Integer.parseInt(tokens[3],16);
- }
- } else {
- cmd = AltosLib.AO_LOG_INVALID;
- }
- } catch (NumberFormatException ne) {
- cmd = AltosLib.AO_LOG_INVALID;
- }
- }
- }
-
- public AltosEepromTm(int in_cmd, int in_tick, int in_a, int in_b) {
- valid = true;
- cmd = in_cmd;
- tick = in_tick;
- a = in_a;
- b = in_b;
- }
-
- static public LinkedList<AltosEeprom> read(FileInputStream input) {
- LinkedList<AltosEeprom> tms = new LinkedList<AltosEeprom>();
-
- for (;;) {
- try {
- String line = AltosLib.gets(input);
- if (line == null)
- break;
- AltosEepromTm tm = new AltosEepromTm(line);
- tms.add(tm);
- } catch (IOException ie) {
- break;
- }
- }
-
- return tms;
- }
-
-}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.File;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFlashListener {
public void position(String label, int percent);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
void reset();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
}
if (state == null)
- return 0;
+ return AltosLib.MISSING;
double landed_height = state.height();
boolean above = true;
- double landed_time = -1000;
+ double landed_time = AltosLib.MISSING;
for (AltosState s : states) {
state = s;
if (state.height() > landed_height + 10) {
above = true;
} else {
- if (above && state.height() < landed_height + 2) {
+ if (above && Math.abs(state.height() - landed_height) < 2) {
above = false;
landed_time = state.time;
}
}
}
- if (landed_time == -1000)
- landed_time = state.time;
return landed_time;
}
break;
}
if (state == null)
- return 0;
+ return AltosLib.MISSING;
- if (boost_time == AltosLib.MISSING)
- boost_time = state.time;
return boost_time;
}
has_imu = false;
has_mag = false;
has_orient = false;
+
+ for (int s = AltosLib.ao_flight_startup; s <= AltosLib.ao_flight_landed; s++) {
+ state_count[s] = 0;
+ state_speed[s] = 0.0;
+ state_accel[s] = 0.0;
+ }
+
for (AltosState state : states) {
if (serial == AltosLib.MISSING && state.serial != AltosLib.MISSING)
serial = state.serial;
has_flight_data = true;
int state_id = state.state();
- if (state.time >= boost_time && state_id < AltosLib.ao_flight_boost)
+ if (boost_time != AltosLib.MISSING && state.time >= boost_time && state_id < AltosLib.ao_flight_boost) {
state_id = AltosLib.ao_flight_boost;
- if (state.time >= landed_time && state_id < AltosLib.ao_flight_landed)
+ }
+ if (landed_time != AltosLib.MISSING && state.time >= landed_time && state_id < AltosLib.ao_flight_landed) {
state_id = AltosLib.ao_flight_landed;
+ }
+
if (state.gps != null && state.gps.locked) {
year = state.gps.year;
month = state.gps.month;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosFontListener {
void font_size_changed(int font_size);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
-public class AltosFrequency {
+import java.io.*;
+import java.util.*;
+import java.text.*;
+
+public class AltosFrequency implements Serializable {
public double frequency;
public String description;
frequency, description);
}
+ public String frequency_string() {
+ return String.format("%7.3f", frequency);
+ }
+
public boolean close(double f) {
double diff = Math.abs(frequency - f);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
+import java.text.*;
+import java.util.concurrent.*;
+import java.io.*;
-public class AltosGPSSat {
+public class AltosGPSSat implements Serializable {
public int svid;
public int c_n0;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.lang.Math;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosHeight extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.LinkedList;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosHexsym {
String name;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
static final int idle_sensor_tmini = 14;
static final int idle_sensor_tgps = 15;
- public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
+ public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct {
for (int idler : idlers) {
AltosIdle idle = null;
switch (idler) {
double frequency;
String callsign;
- public void update_state(AltosState state) throws InterruptedException {
+ public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct {
try {
+ boolean matched = false;
/* Fetch config data from remote */
AltosConfigData config_data = new AltosConfigData(link);
state.set_state(AltosLib.ao_flight_stateless);
for (AltosIdler idler : idlers) {
if (idler.matches(config_data)) {
idler.update_state(state, link, config_data);
+ matched = true;
break;
}
}
+ if (!matched)
+ throw new AltosUnknownProduct(config_data.product);
state.set_received_time(System.currentTimeMillis());
} catch (TimeoutException te) {
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.concurrent.*;
AltosIdleFetch fetch;
boolean remote;
+ boolean close_on_exit;
double frequency;
String callsign;
return link.reply_abort;
}
- boolean update_state(AltosState state) throws InterruptedException, TimeoutException {
+ boolean update_state(AltosState state) throws InterruptedException, TimeoutException, AltosUnknownProduct {
boolean worked = false;
boolean aborted = false;
update_state(state);
listener.update(state, listener_state);
} catch (TimeoutException te) {
+ } catch (AltosUnknownProduct ae) {
+ listener.error(String.format("Unknown product \"%s\"", ae.product));
}
if (link.has_error || link.reply_abort) {
listener.failed();
}
} catch (InterruptedException ie) {
}
- try {
- link.close();
- } catch (InterruptedException ie) {
+ if (close_on_exit) {
+ try {
+ link.close();
+ } catch (InterruptedException ie) {
+ }
}
}
- public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote)
- throws FileNotFoundException, InterruptedException, TimeoutException {
+ public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
listener = in_listener;
link = in_link;
remote = in_remote;
+ close_on_exit = in_close_on_exit;
listener_state = new AltosListenerState();
fetch = new AltosIdleFetch(link);
}
+
+ public AltosIdleMonitor(AltosIdleMonitorListener in_listener, AltosLink in_link, boolean in_remote) {
+ this(in_listener, in_link, in_remote, true);
+ }
}
+
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosIdleMonitorListener {
public void update(AltosState state, AltosListenerState listener_state);
+ public void error(String reason);
public void failed();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.io.*;
public class AltosIgnite {
AltosLink link;
boolean remote;
+ boolean close_on_exit;
boolean link_started;
boolean have_npyro = false;
int npyro;
public void close() throws InterruptedException {
stop_link();
- link.close();
+ if (close_on_exit)
+ link.close();
link = null;
}
- public AltosIgnite(AltosLink in_link, boolean in_remote)
- throws FileNotFoundException, TimeoutException, InterruptedException {
-
+ public AltosIgnite(AltosLink in_link, boolean in_remote, boolean in_close_on_exit) {
link = in_link;
remote = in_remote;
+ close_on_exit = in_close_on_exit;
+ }
+
+ public AltosIgnite(AltosLink in_link, boolean in_remote) {
+ this(in_link, in_remote, true);
}
-}
\ No newline at end of file
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLatLon {
public double lat;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLatitude extends AltosLocation {
public String pos() { return "N"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
public void run() {
try {
- url = new URL(AltosLib.launch_sites_url);
+ String path;
+
+ path = System.getenv(AltosLib.launch_sites_env);
+ if (path == null)
+ path = AltosLib.launch_sites_url;
+ url = new URL(path);
URLConnection uc = url.openConnection();
InputStreamReader in_stream = new InputStreamReader(uc.getInputStream(), AltosLib.unicode_set);
add(line);
}
} catch (Exception e) {
+ System.out.printf("file exception %s\n", e.toString());
} finally {
notify_complete();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.io.*;
};
public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
+ public static final String launch_sites_env = "LAUNCH_SITES";
// public static final String launch_sites_url = "file:///home/keithp/misc/text/altusmetrum/AltOS/launch-sites.txt";
public static final int ao_telemetry_standard_len = 32;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLine {
public String line;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.concurrent.*;
boolean can_cancel = can_cancel_reply();
String reply = null;
- if (!can_cancel && remote)
- System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
+// if (!can_cancel && remote)
+// System.out.printf("Uh-oh, reading remote serial device from swing thread\n");
if (remote && can_cancel) {
timeout = 500;
if (config_data.has_monitor_battery()) {
try {
- String[] items = adc();
- for (int i = 0; i < items.length;) {
- if (items[i].equals("batt")) {
- monitor_batt = Integer.parseInt(items[i+1]);
- i += 2;
- continue;
+ String[] items = adc();
+ for (int i = 0; i < items.length;) {
+ if (items[i].equals("batt")) {
+ monitor_batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
}
- i++;
- }
} catch (TimeoutException te) {
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public abstract class AltosLocation extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosLongitude extends AltosLocation {
public String pos() { return "E"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.*;
upper_left = floor(transform.screen_point(new AltosPointInt(0, 0)));
lower_right = floor(transform.screen_point(new AltosPointInt(width(), height())));
}
- for (AltosPointInt point : tiles.keySet()) {
+
+ Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+ while (keyEnumeration.hasMoreElements()) {
+ AltosPointInt point = keyEnumeration.nextElement();
if (point.x < upper_left.x || lower_right.x < point.x ||
point.y < upper_left.y || lower_right.y < point.y) {
tiles.remove(point);
if (!tiles.containsKey(point)) {
AltosLatLon ul = transform.lat_lon(point);
AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
- AltosMapTile tile = map_interface.new_tile(this, ul, center, zoom, maptype, px_size);
+ AltosMapTile tile = map_interface.new_tile(cache, ul, center, zoom, maptype, px_size);
+ tile.add_listener(this);
tiles.put(point, tile);
}
}
centre(lat, lon);
tiles.clear();
make_tiles();
- for (AltosMapTile tile : tiles.values()) {
- tile.add_store_listener(this);
- if (tile.store_status() != AltosMapTile.loading)
- listener.notify_tile(tile, tile.store_status());
- }
repaint();
}
/* AltosMapTileListener methods */
public synchronized void notify_tile(AltosMapTile tile, int status) {
- for (AltosPointInt point : tiles.keySet()) {
+ Enumeration<AltosPointInt> keyEnumeration = tiles.keys();
+
+ while (keyEnumeration.hasMoreElements()) {
+ AltosPointInt point = keyEnumeration.nextElement();
if (tile == tiles.get(point)) {
AltosPointInt screen = transform.screen(point);
repaint(screen.x, screen.y, AltosMap.px_size, AltosMap.px_size);
if (distance > drag_far)
dragged = true;
- if (transform == null) {
- debug("Transform not set in drag\n");
+ if (transform == null)
return;
- }
AltosLatLon new_centre = transform.screen_lat_lon(new AltosPointInt(width() / 2 - dx, height() / 2 - dy));
centre(new_centre);
private void drag_stop(int x, int y) {
if (!dragged) {
if (transform == null) {
- debug("Transform not set in stop\n");
return;
}
map_interface.select_object (transform.screen_lat_lon(new AltosPointInt(x,y)));
}
private void line_start(int x, int y) {
- if (line != null) {
+ if (line != null && transform != null) {
line.pressed(new AltosPointInt(x, y), transform);
repaint();
}
}
private void line(int x, int y) {
- if (line != null) {
+ if (line != null && transform != null) {
line.dragged(new AltosPointInt(x, y), transform);
repaint();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
public class AltosMapCache implements AltosMapCacheListener {
/* An entry in the MapCache */
- class MapCacheElement implements AltosMapStoreListener {
+ class MapCacheElement implements AltosMapTileListener {
AltosMapTile tile; /* Notify when image has been loaded */
AltosImage image;
- AltosMapStore store;
long used;
class loader implements Runnable {
public void run() {
- if (image != null)
- tile.notify_image(image);
- try {
- image = map_interface.load_image(store.file);
- } catch (Exception ex) {
+ if (image == null) {
+ try {
+ image = map_interface.load_image(tile.store.file);
+ } catch (Exception ex) {
+ }
}
- if (image == null)
- tile.set_status(AltosMapTile.failed);
- else
- tile.set_status(AltosMapTile.success);
tile.notify_image(image);
}
}
}
public boolean has_map() {
- return store.status() == AltosMapTile.success;
+ return tile.status == AltosMapTile.loaded;
}
- public synchronized void notify_store(AltosMapStore store, int status) {
- switch (status) {
- case AltosMapTile.loading:
- break;
- case AltosMapTile.success:
+ public synchronized void notify_tile(AltosMapTile tile, int status) {
+ if (status == AltosMapTile.fetched) {
+ System.out.printf("tile fetched, loading image\n");
load();
- break;
- default:
- tile.set_status(status);
- tile.notify_image(null);
}
}
- public MapCacheElement(AltosMapTile tile, AltosMapStore store) throws IOException {
+ public MapCacheElement(AltosMapTile tile) {
this.tile = tile;
this.image = null;
- this.store = store;
this.used = 0;
-
- int status = store.status();
- switch (status) {
- case AltosMapTile.loading:
- store.add_listener(this);
- break;
- case AltosMapTile.success:
- load();
- break;
- default:
- tile.set_status(status);
- tile.notify_image(null);
- break;
- }
+ tile.add_listener(this);
}
}
}
}
- public AltosImage get(AltosMapTile tile, AltosMapStore store, int width, int height) {
+ public AltosImage get(AltosMapTile tile) {
int oldest = -1;
long age = used;
oldest = i;
break;
}
- if (store.equals(element.store)) {
+ if (tile.store.equals(element.tile.store)) {
element.used = used++;
return element.image;
}
}
}
- try {
- element = new MapCacheElement(tile, store);
- element.used = used++;
- if (elements[oldest] != null)
- elements[oldest].flush();
+ element = new MapCacheElement(tile);
+ element.used = used++;
+ if (elements[oldest] != null)
+ elements[oldest].flush();
- elements[oldest] = element;
-
- if (element.image == null)
- tile.set_status(AltosMapTile.loading);
- else
- tile.set_status(AltosMapTile.success);
-
- return element.image;
- } catch (IOException e) {
- tile.set_status(AltosMapTile.failed);
- return null;
- }
+ elements[oldest] = element;
+ System.out.printf("AltosMapCache.get image ? %s\n",
+ element.image == null ? "false" : "true");
+ return element.image;
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapCacheListener {
public void map_cache_changed(int map_cache);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
public abstract AltosMapMark new_mark(double lat, double lon, int state);
- public abstract AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
+ public abstract AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size);
public abstract int width();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
import java.net.URL;
import java.net.URLConnection;
-public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListener {
+public class AltosMapLoader extends Thread implements AltosMapTileListener {
AltosMapLoaderListener listener;
double latitude, longitude;
for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) {
for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) {
- listener.debug("Make tile at %d, %d\n", x, y);
AltosPointInt point = new AltosPointInt(x, y);
AltosLatLon ul = transform.lat_lon(point);
AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2));
- AltosMapTile tile = map.map_interface.new_tile(this, ul, center, zoom, maptype, AltosMap.px_size);
- tile.add_store_listener(this);
- if (tile.store_status() != AltosMapTile.loading)
- notify_tile(tile, tile.store_status());
+ AltosMapTile tile = map.map_interface.new_tile(null, ul, center, zoom, maptype, AltosMap.px_size);
+ tile.add_listener(this);
}
}
}
do_load();
}
- private void start_load() {
+ public void run() {
cur_z = min_z;
int ntype = 0;
cur_type = next_type(0);
+ tiles_total = 0;
for (int z = min_z; z <= max_z; z++)
- tiles_total += tiles_per_layer(z);
+ tiles_total += tiles_per_layer(z) * ntype;
layers_total = (max_z - min_z + 1) * ntype;
layers_loaded = 0;
tiles_loaded_total = 0;
- listener.debug("total tiles %d\n", tiles_total);
+ listener.debug("total tiles %d layers %d\n", tiles_total, layers_total);
listener.loader_start(tiles_total);
do_load();
}
- public void load(double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
- listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
- latitude, longitude, min_z, max_z, radius, all_types);
- this.latitude = latitude;
- this.longitude = longitude;
- this.min_z = min_z;
- this.max_z = max_z;
- this.radius = radius;
- this.all_types = all_types;
- start_load();
- }
-
- public synchronized void notify_store(AltosMapStore store, int status) {
+ public synchronized void notify_tile(AltosMapTile tile, int status) {
boolean do_next = false;
- if (status == AltosMapTile.loading)
+ if (status == AltosMapTile.fetching)
return;
+ tile.remove_listener(this);
+
if (layers_loaded >= layers_total)
return;
++tiles_loaded_total;
++tiles_loaded_layer;
- listener.debug("total %d layer %d\n", tiles_loaded_total, tiles_loaded_layer);
+
+ listener.debug("AltosMapLoader.notify_tile status %d total %d of %d layer %d of %d\n",
+ status, tiles_loaded_total, tiles_total, tiles_loaded_layer, tiles_this_layer);
if (tiles_loaded_layer == tiles_this_layer) {
++layers_loaded;
listener.debug("%d layers loaded\n", layers_loaded);
- if (layers_loaded == layers_total) {
- listener.loader_done(tiles_total);
- return;
- } else {
- do_next = true;
- }
+ do_next = true;
}
- listener.loader_notify(tiles_loaded_total,
- tiles_total, store.file.toString());
- if (do_next)
- next_load();
- }
- public synchronized void notify_tile(AltosMapTile tile, int status) {
- notify_store(tile.store, status);
+ if (tiles_loaded_total == tiles_total)
+ listener.loader_done(tiles_total);
+ else {
+ listener.loader_notify(tiles_loaded_total,
+ tiles_total, tile.store.file.toString());
+ if (do_next)
+ next_load();
+ }
}
- public AltosMapCache cache() { return map.cache(); }
-
- public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener) {
+ public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener,
+ double latitude, double longitude, int min_z, int max_z, double radius, int all_types) {
+ listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n",
+ latitude, longitude, min_z, max_z, radius, all_types);
this.map = map;
this.listener = listener;
+ this.latitude = latitude;
+ this.longitude = longitude;
+ this.min_z = min_z;
+ this.max_z = max_z;
+ this.radius = radius;
+ this.all_types = all_types;
+ start();
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapLoaderListener {
public abstract void loader_start(int max);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosMapRectangle {
AltosLatLon ul, lr;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.net.*;
public synchronized void add_listener(AltosMapStoreListener listener) {
if (!listeners.contains(listener))
listeners.add(listener);
+ listener.notify_store(this, status);
}
public synchronized void remove_listener(AltosMapStoreListener listener) {
file.delete();
return AltosMapTile.bad_request;
}
- return AltosMapTile.success;
+ return AltosMapTile.fetched;
}
static Object fetch_lock = new Object();
static final long forbidden_interval = 60l * 1000l * 1000l * 1000l;
static final long google_maps_ratelimit_ms = 1200;
- static Object loader_lock = new Object();
+ static Object fetcher_lock = new Object();
static LinkedList<AltosMapStore> waiting = new LinkedList<AltosMapStore>();
static LinkedList<AltosMapStore> running = new LinkedList<AltosMapStore>();
- static final int concurrent_loaders = 128;
+ static final int concurrent_fetchers = 128;
- static void start_loaders() {
- while (!waiting.isEmpty() && running.size() < concurrent_loaders) {
+ static void start_fetchers() {
+ while (!waiting.isEmpty() && running.size() < concurrent_fetchers) {
AltosMapStore s = waiting.remove();
running.add(s);
- Thread lt = s.make_loader_thread();
+ Thread lt = s.make_fetcher_thread();
lt.start();
}
}
- void finish_loader() {
- synchronized(loader_lock) {
+ void finish_fetcher() {
+ synchronized(fetcher_lock) {
running.remove(this);
- start_loaders();
+ start_fetchers();
}
}
- void add_loader() {
- synchronized(loader_lock) {
+ void add_fetcher() {
+ synchronized(fetcher_lock) {
waiting.add(this);
- start_loaders();
+ start_fetchers();
}
}
- class loader implements Runnable {
+ class fetcher implements Runnable {
public void run() {
try {
if (file.exists()) {
- notify_listeners(AltosMapTile.success);
+ notify_listeners(AltosMapTile.fetched);
return;
}
synchronized (fetch_lock) {
long startTime = System.nanoTime();
new_status = fetch_url();
- if (new_status == AltosMapTile.success) {
+ if (new_status == AltosMapTile.fetched) {
long duration_ms = (System.nanoTime() - startTime) / 1000000;
if (duration_ms < google_maps_ratelimit_ms) {
try {
}
notify_listeners(new_status);
} finally {
- finish_loader();
+ finish_fetcher();
}
}
}
- private Thread make_loader_thread() {
- return new Thread(new loader());
+ private Thread make_fetcher_thread() {
+ return new Thread(new fetcher());
}
- private void load() {
- add_loader();
+ private void fetch() {
+ add_fetcher();
}
private AltosMapStore (String url, File file) {
this.file = file;
if (file.exists())
- status = AltosMapTile.success;
+ status = AltosMapTile.fetched;
else {
- status = AltosMapTile.loading;
- load();
+ status = AltosMapTile.fetching;
+ fetch();
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapStoreListener {
abstract void notify_store(AltosMapStore store, int status);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
-public abstract class AltosMapTile implements AltosFontListener {
- AltosMapTileListener listener;
+public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreListener {
+ LinkedList<AltosMapTileListener> listeners = new LinkedList<AltosMapTileListener>();
public AltosLatLon upper_left, center;
public int px_size;
int zoom;
int maptype;
int scale;
+ private AltosMapCache cache;
public AltosMapStore store;
- public AltosMapCache cache;
public int status;
- static public final int success = 0;
- static public final int loading = 1;
- static public final int failed = 2;
- static public final int bad_request = 3;
- static public final int forbidden = 4;
+ static public final int loaded = 0; /* loaded from file */
+ static public final int fetched = 1; /* downloaded to file */
+ static public final int fetching = 2; /* downloading from net */
+ static public final int failed = 3; /* loading from file failed */
+ static public final int bad_request = 4;/* downloading failed */
+ static public final int forbidden = 5; /* downloading failed */
private File map_file() {
double lat = center.lat;
public void font_size_changed(int font_size) {
}
- public void set_status(int status) {
+ private synchronized void notify_listeners(int status) {
this.status = status;
- listener.notify_tile(this, status);
+ for (AltosMapTileListener listener : listeners)
+ listener.notify_tile(this, status);
}
- public void notify_image(AltosImage image) {
- listener.notify_tile(this, status);
+ public void notify_store(AltosMapStore store, int status) {
+// System.out.printf("AltosMapTile.notify_store %d\n", status);
+ notify_listeners(status);
}
- public int store_status() {
- return store.status();
+ public void notify_image(AltosImage image) {
+ if (image == null)
+ status = failed;
+ else
+ status = loaded;
+ notify_listeners(status);
}
- public void add_store_listener(AltosMapStoreListener listener) {
- store.add_listener(listener);
+ public abstract void paint(AltosMapTransform t);
+
+ public AltosImage get_image() {
+ if (cache == null)
+ return null;
+ return cache.get(this);
}
- public void remove_store_listener(AltosMapStoreListener listener) {
- store.remove_listener(listener);
+ public synchronized void add_listener(AltosMapTileListener listener) {
+ if (!listeners.contains(listener))
+ listeners.add(listener);
+ listener.notify_tile(this, status);
}
- public abstract void paint(AltosMapTransform t);
+ public synchronized void remove_listener(AltosMapTileListener listener) {
+ listeners.remove(listener);
+ }
- public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
- this.listener = listener;
+ public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) {
+ this.cache = cache;
this.upper_left = upper_left;
- this.cache = listener.cache();
while (center.lon < -180.0)
center.lon += 360.0;
this.px_size = px_size;
this.scale = scale;
- status = AltosMapTile.loading;
store = AltosMapStore.get(map_url(), map_file());
+ store.add_listener(this);
}
- public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- this(listener, upper_left, center, zoom, maptype, px_size, 1);
+ public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ this(cache, upper_left, center, zoom, maptype, px_size, 1);
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapTileListener {
abstract public void notify_tile(AltosMapTile tile, int status);
-
- abstract public AltosMapCache cache();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.lang.Math;
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_10;
+
+public interface AltosMapTypeListener {
+ public void map_type_changed(int map_type);
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosMapZoomListener {
abstract public void zoom_changed(int zoom);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
public class AltosMma655x implements Cloneable {
- int accel;
+ private int accel;
public boolean parse_line(String line) throws NumberFormatException {
if (line.startsWith("MMA655X value")) {
return n;
}
- static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, AltosUnknownProduct {
try {
AltosMma655x mma655x = new AltosMma655x(link);
- if (mma655x != null)
- state.set_accel(mma655x.accel);
+ if (mma655x != null) {
+ int accel = mma655x.accel;
+ if (config_data.mma655x_inverted())
+ accel = 4095 - accel;
+ if (config_data.pad_orientation == 1)
+ accel = 4095 - accel;
+ state.set_accel(accel);
+ }
} catch (TimeoutException te) {
} catch (NumberFormatException ne) {
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosNoSymbol extends Exception {
public AltosNoSymbol(String name) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosOrient extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosPointDouble {
public double x, y;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosPointInt {
public int x, y;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
public final static String frequency_count = "COUNT";
public final static String frequency_format = "FREQUENCY-%d";
public final static String description_format = "DESCRIPTION-%d";
+ public final static String frequenciesPreference = "FREQUENCIES";
/* Units preference */
public static int map_cache = 9;
+ final static String mapTypePreference = "MAP-TYPE";
+ static int map_type;
+
public static AltosFrequency[] load_common_frequencies() {
+
AltosFrequency[] frequencies = null;
- boolean existing = false;
- existing = backend.nodeExists(common_frequencies_node_name);
- if (existing) {
- AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
- int count = node.getInt(frequency_count, 0);
+ frequencies = (AltosFrequency[]) backend.getSerializable(frequenciesPreference, null);
+
+ if (frequencies == null) {
+ if (backend.nodeExists(common_frequencies_node_name)) {
+ AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
+ int count = node.getInt(frequency_count, 0);
- frequencies = new AltosFrequency[count];
- for (int i = 0; i < count; i++) {
- double frequency;
- String description;
+ frequencies = new AltosFrequency[count];
+ for (int i = 0; i < count; i++) {
+ double frequency;
+ String description;
- frequency = node.getDouble(String.format(frequency_format, i), 0.0);
- description = node.getString(String.format(description_format, i), null);
- frequencies[i] = new AltosFrequency(frequency, description);
+ frequency = node.getDouble(String.format(frequency_format, i), 0.0);
+ description = node.getString(String.format(description_format, i), null);
+ frequencies[i] = new AltosFrequency(frequency, description);
+ }
}
- } else {
+ }
+
+ if (frequencies == null) {
frequencies = new AltosFrequency[10];
for (int i = 0; i < 10; i++) {
frequencies[i] = new AltosFrequency(434.550 + i * .1,
return frequencies;
}
- public static void save_common_frequencies(AltosFrequency[] frequencies) {
- AltosPreferencesBackend node = backend.node(common_frequencies_node_name);
-
- node.putInt(frequency_count, frequencies.length);
- for (int i = 0; i < frequencies.length; i++) {
- node.putDouble(String.format(frequency_format, i), frequencies[i].frequency);
- node.putString(String.format(description_format, i), frequencies[i].description);
- }
- }
public static int launcher_serial;
public static int launcher_channel;
map_cache = backend.getInt(mapCachePreference, 9);
map_cache_listeners = new LinkedList<AltosMapCacheListener>();
+ map_type = backend.getInt(mapTypePreference, AltosMap.maptype_hybrid);
}
public static void flush_preferences() {
}
}
- public static void set_state(int serial, AltosState state, AltosListenerState listener_state) {
-
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- try {
- ObjectOutputStream oos = new ObjectOutputStream(baos);
+ public static void set_state(AltosState state) {
- AltosSavedState saved_state = new AltosSavedState(state, listener_state);
- oos.writeObject(saved_state);
-
- byte[] bytes = baos.toByteArray();
-
- synchronized(backend) {
- backend.putBytes(String.format(statePreferenceFormat, serial), bytes);
- backend.putInt(statePreferenceLatest, serial);
- flush_preferences();
- }
- } catch (IOException ie) {
+ synchronized(backend) {
+ backend.putSerializable(String.format(statePreferenceFormat, state.serial), state);
+ backend.putInt(statePreferenceLatest, state.serial);
+ flush_preferences();
}
}
return latest;
}
- public static AltosSavedState state(int serial) {
- byte[] bytes = null;
-
+ public static AltosState state(int serial) {
synchronized(backend) {
- bytes = backend.getBytes(String.format(statePreferenceFormat, serial), null);
- }
-
- if (bytes == null)
- return null;
-
- ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
-
- try {
- ObjectInputStream ois = new ObjectInputStream(bais);
- AltosSavedState saved_state = (AltosSavedState) ois.readObject();
- return saved_state;
- } catch (IOException ie) {
- } catch (ClassNotFoundException ce) {
+ try {
+ return (AltosState) backend.getSerializable(String.format(statePreferenceFormat, serial), null);
+ } catch (Exception e) {
+ return null;
+ }
}
- return null;
}
public static void set_scanning_telemetry(int new_scanning_telemetry) {
public static void set_common_frequencies(AltosFrequency[] frequencies) {
synchronized(backend) {
common_frequencies = frequencies;
- save_common_frequencies(frequencies);
+ backend.putSerializable(frequenciesPreference, frequencies);
flush_preferences();
}
}
return map_cache;
}
}
+
+ static LinkedList<AltosMapTypeListener> map_type_listeners;
+
+ public static void set_map_type(int map_type) {
+ synchronized(backend) {
+ AltosPreferences.map_type = map_type;
+ backend.putInt(mapTypePreference, map_type);
+ flush_preferences();
+ }
+ if (map_type_listeners != null) {
+ for (AltosMapTypeListener l : map_type_listeners) {
+ l.map_type_changed(map_type);
+ }
+ }
+ }
+
+ public static int map_type() {
+ synchronized(backend) {
+ return map_type;
+ }
+ }
+
+ public static void register_map_type_listener(AltosMapTypeListener l) {
+ synchronized(backend) {
+ if (map_type_listeners == null)
+ map_type_listeners = new LinkedList<AltosMapTypeListener>();
+ map_type_listeners.add(l);
+ }
+ }
+
+ public static void unregister_map_type_listener(AltosMapTypeListener l) {
+ synchronized(backend) {
+ map_type_listeners.remove(l);
+ }
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
-import java.io.File;
+import java.io.*;
+import java.util.*;
+import java.text.*;
-public interface AltosPreferencesBackend {
+public abstract class AltosPreferencesBackend {
- public String getString(String key, String def);
- public void putString(String key, String value);
+ public abstract String getString(String key, String def);
+ public abstract void putString(String key, String value);
- public int getInt(String key, int def);
- public void putInt(String key, int value);
+ public abstract int getInt(String key, int def);
+ public abstract void putInt(String key, int value);
- public double getDouble(String key, double def);
- public void putDouble(String key, double value);
+ public abstract double getDouble(String key, double def);
+ public abstract void putDouble(String key, double value);
- public boolean getBoolean(String key, boolean def);
- public void putBoolean(String key, boolean value);
+ public abstract boolean getBoolean(String key, boolean def);
+ public abstract void putBoolean(String key, boolean value);
- public byte[] getBytes(String key, byte[] def);
- public void putBytes(String key, byte[] value);
+ public abstract byte[] getBytes(String key, byte[] def);
+ public abstract void putBytes(String key, byte[] value);
- public boolean nodeExists(String key);
- public AltosPreferencesBackend node(String key);
+ public Serializable getSerializable(String key, Serializable def) {
+ byte[] bytes = null;
- public String[] keys();
- public void remove(String key);
+ bytes = getBytes(key, null);
+ if (bytes == null)
+ return def;
- public void flush();
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
- public File homeDirectory();
+ try {
+ ObjectInputStream ois = new ObjectInputStream(bais);
+ Serializable object = (Serializable) ois.readObject();
+ return object;
+ } catch (IOException ie) {
+ debug("IO exception %s\n", ie.toString());
+ } catch (ClassNotFoundException ce) {
+ debug("ClassNotFoundException %s\n", ce.toString());
+ }
+ return def;
+ }
+
+ public void putSerializable(String key, Serializable object) {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+ oos.writeObject(object);
+ byte[] bytes = baos.toByteArray();
+
+ putBytes(key, bytes);
+ } catch (IOException ie) {
+ debug("set_state failed %s\n", ie.toString());
+ }
+ }
+
+ public abstract boolean nodeExists(String key);
+ public abstract AltosPreferencesBackend node(String key);
+
+ public abstract String[] keys();
+ public abstract void remove(String key);
+
+ public abstract void flush();
+
+ public abstract File homeDirectory();
+
+ public abstract void debug(String format, Object ... arguments);
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosQuaternion {
double r; /* real bit */
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosRectangle {
public int x, y, width, height;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosRotation {
private AltosQuaternion rotation;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosSpeed extends AltosUnits {
public double value(double v, boolean imperial_units) {
if (imperial_units)
- return AltosConvert.meters_to_mph(v);
+ return AltosConvert.mps_to_fps(v);
return v;
}
public double inverse(double v, boolean imperial_units) {
if (imperial_units)
- return AltosConvert.mph_to_meters(v);
+ return AltosConvert.fps_to_mps(v);
return v;
}
public String show_units(boolean imperial_units) {
if (imperial_units)
- return "mph";
+ return "fps";
return "m/s";
}
public String say_units(boolean imperial_units) {
if (imperial_units)
- return "miles per hour";
+ return "feet per second";
return "meters per second";
}
public int show_fraction(int width, boolean imperial_units) {
return width / 9;
}
-}
\ No newline at end of file
+}
* Track flight state from telemetry or eeprom data stream
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosStateUpdate {
- public void update_state(AltosState state) throws InterruptedException;
-}
\ No newline at end of file
+ public void update_state(AltosState state) throws InterruptedException, AltosUnknownProduct;
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryCompanion extends AltosTelemetryStandard {
AltosCompanion companion;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryLocation extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.util.HashMap;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int state;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
int accel;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryMini extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetryRaw extends AltosTelemetryStandard {
public AltosTelemetryRaw(int[] bytes) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetrySatellite extends AltosTelemetryStandard {
int channels;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTelemetrySensor extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public abstract class AltosTelemetryStandard extends AltosTelemetry {
int[] bytes;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosTemperature extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosUnitsListener {
public void units_changed(boolean imperial_units);
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package org.altusmetrum.altoslib_10;
+
+public class AltosUnknownProduct extends Exception {
+ public String product;
+
+ public AltosUnknownProduct (String in_product) {
+ product = in_product;
+ }
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosVersion {
public final static String version = "@VERSION@";
- public final static String google_maps_api_key = @GOOGLEKEY@;
+ public final static String google_maps_api_key = "@GOOGLEKEY@";
public static boolean has_google_maps_api_key() {
return google_maps_api_key != null && google_maps_api_key.length() > 1;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public class AltosVoltage extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
public interface AltosWriter {
AltosEepromDownload.java \
AltosEepromFile.java \
AltosEepromTM.java \
- AltosEepromTm.java \
+ AltosEepromTMini.java \
AltosEepromHeader.java \
AltosEepromIterable.java \
AltosEepromList.java \
AltosTelemetrySatellite.java \
AltosTelemetryStandard.java \
AltosUnitsListener.java \
+ AltosUnknownProduct.java \
AltosMs5607.java \
AltosIMU.java \
AltosMag.java \
AltosLaunchSites.java \
AltosMapLoaderListener.java \
AltosMapLoader.java \
+ AltosMapTypeListener.java \
AltosVersion.java
JAR=altoslib_$(ALTOSLIB_VERSION).jar
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class Altos extends AltosUILib {
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosAscent extends AltosUIFlightTab {
JLabel cur, max;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
private AltosFlightInfoTableModel model;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigPyroUI
extends AltosUIDialog
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigTD implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigTDUI
extends AltosUIDialog
import javax.swing.*;
import javax.swing.event.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigUI
extends AltosUIDialog
JComboBox<String> apogee_delay_value;
JComboBox<String> apogee_lockout_value;
AltosUIFreqList radio_frequency_value;
- JTextField radio_calibration_value;
+ JLabel radio_calibration_value;
JRadioButton radio_enable_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
return product != null && product.startsWith("TeleMetrum");
}
- void set_radio_calibration_tool_tip() {
- if (radio_calibration_value.isEnabled())
- radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
- else
- radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
- }
-
void set_radio_enable_tool_tip() {
if (radio_enable_value.isEnabled())
radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_calibration_value = new JTextField(String.format("%d", 1186611));
- radio_calibration_value.getDocument().addDocumentListener(this);
- if (remote)
- radio_calibration_value.setEnabled(false);
+ radio_calibration_value = new JLabel(String.format("%d", 1186611));
pane.add(radio_calibration_value, c);
- set_radio_calibration_tool_tip();
row++;
/* Radio Enable */
radio_calibration_value.setText(String.format("%d", new_radio_calibration));
}
- public int radio_calibration() throws AltosConfigDataException {
- return parse_int("radio calibration", radio_calibration_value.getText(), false);
- }
-
public void set_radio_enable(int new_radio_enable) {
radio_enable_label.setVisible(new_radio_enable >= 0);
radio_enable_value.setVisible(new_radio_enable >= 0);
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosConfigureUI
extends AltosUIConfigure
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosDescent extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
import java.text.*;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatusTableModel extends AbstractTableModel {
private String[] columnNames = {
package altosui;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatusUpdate implements ActionListener {
import javax.swing.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
AltosVoice voice;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import java.io.*;
import java.util.concurrent.*;
import java.util.Arrays;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
AltosDevice device;
SwingUtilities.invokeLater(r);
}
+ public void error(final String reason) {
+ Runnable r = new Runnable() {
+ public void run() {
+ disconnect();
+ JOptionPane.showMessageDialog(AltosIdleMonitorUI.this,
+ reason,
+ "Error fetching data",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
Container bag;
AltosUIFreqList frequencies;
JTextField callsign_value;
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIgniteUI
extends AltosUIDialog
int time_remaining;
boolean timer_running;
+ int poll_remaining;
+
LinkedBlockingQueue<String> command_queue;
class Igniter {
void set_ignite_status() {
getting_status = false;
+ poll_remaining = 2;
if (!visible) {
visible = true;
setVisible(true);
}
void poll_ignite_status() {
+ if (poll_remaining > 0) {
+ --poll_remaining;
+ return;
+ }
if (!getting_status) {
getting_status = true;
send_command("get_status");
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosIgnitor extends AltosUIFlightTab {
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosLanded extends AltosUIFlightTab implements ActionListener {
import java.io.*;
import java.util.concurrent.*;
import java.awt.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosLaunch {
AltosDevice device;
import java.io.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
class FireButton extends JButton {
protected void processMouseEvent(MouseEvent e) {
package altosui;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosPad extends AltosUIFlightTab {
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class AltosUI extends AltosUIFrame {
public AltosVoice voice = new AltosVoice();
; Definitions for Java Detection
-!define JRE_VERSION "1.6"
-!define JRE32_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52247&/jre-6u27-windows-i586.exe"
-!define JRE64_URL "http://javadl.sun.com/webapps/download/AutoDL?BundleId=52249&/jre-6u27-windows-x64.exe"
-
-Var JavaDownload
-Var JavaBits
+!define JAVA_VERSION "6.0"
+
+Function GetFileVersion
+ !define GetFileVersion `!insertmacro GetFileVersionCall`
+
+ !macro GetFileVersionCall _FILE _RESULT
+ Push `${_FILE}`
+ Call GetFileVersion
+ Pop ${_RESULT}
+ !macroend
+
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ ClearErrors
+
+ GetDllVersion '$0' $1 $2
+ IfErrors error
+ IntOp $3 $1 >> 16
+ IntOp $3 $3 & 0x0000FFFF
+ IntOp $4 $1 & 0x0000FFFF
+ IntOp $5 $2 >> 16
+ IntOp $5 $5 & 0x0000FFFF
+ IntOp $6 $2 & 0x0000FFFF
+ StrCpy $0 '$3.$4.$5.$6'
+ goto end
+
+ error:
+ SetErrors
+ StrCpy $0 ''
+
+ end:
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+FunctionEnd
-Function GetJRE
- ${If} ${RunningX64}
- StrCpy $JavaDownload ${JRE64_URL}
- StrCpy $JavaBits "64"
- ${Else}
- StrCpy $JavaDownload ${JRE32_URL}
- StrCpy $JavaBits "32"
- ${EndIf}
-
- MessageBox MB_OK "This product uses Java ${JRE_VERSION}, \
- $JavaBits bits, it will now \
- be downloaded and installed"
-
- StrCpy $2 "$TEMP\Java Runtime Environment.exe"
- nsisdl::download /TIMEOUT=30000 $JavaDownload $2
- Pop $R0 ;Get the return value
- StrCmp $R0 "success" +3
- MessageBox MB_OK "Download failed: $R0"
- Quit
- ExecWait $2
- Delete $2
+Function openLinkNewWindow
+ Push $3
+ Exch
+ Push $2
+ Exch
+ Push $1
+ Exch
+ Push $0
+ Exch
+
+ ReadRegStr $1 HKCU "Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.html\UserChoice" "Progid"
+ IfErrors iexplore
+
+ Goto foundbrowser
+iexplore:
+ StrCpy $1 "IE.AssocFile.HTM"
+
+foundbrowser:
+
+ StrCpy $2 "\shell\open\command"
+
+ StrCpy $3 $1$2
+
+ ReadRegStr $0 HKCR $3 ""
+
+# Get browser path
+ DetailPrint $0
+
+ StrCpy $2 '"'
+ StrCpy $1 $0 1
+ StrCmp $1 $2 +2 # if path is not enclosed in " look for space as final char
+ StrCpy $2 ' '
+ StrCpy $3 1
+ loop:
+ StrCpy $1 $0 1 $3
+ DetailPrint $1
+ StrCmp $1 $2 found
+ StrCmp $1 "" found
+ IntOp $3 $3 + 1
+ Goto loop
+
+ found:
+ StrCpy $1 $0 $3
+ StrCmp $2 " " +2
+ StrCpy $1 '$1"'
+
+ Pop $0
+ Exec '$1 $0'
+ Pop $0
+ Pop $1
+ Pop $2
+ Pop $3
FunctionEnd
+
+!macro _OpenURL URL
+Push "${URL}"
+Call openLinkNewWindow
+!macroend
+
+!define OpenURL '!insertmacro "_OpenURL"'
Function DoDetectJRE
- DetailPrint "Desired Java version ${JRE_VERSION}"
-
- ; Check in HKCU for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- IfErrors hkcuwow_version
-
- DetailPrint "HKEY_CURRENT_USER Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hkcuwow_version:
-
- ; Check in HKCU Wow6432Node for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKCU "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- Iferrors hklm_version
-
- DetailPrint "HKEY_CURRENT_USER Wow6432Node Java version $2"
+ DetailPrint "Desired Java version ${JAVA_VERSION}"
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hklm_version:
-
- ; Check in HKLM for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
+ SearchPath $0 javaw.exe
+ IfErrors no
- IfErrors hklmwow_version
-
- DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
-
- IntCmp $3 1 yes yes no
-
-hklmwow_version:
-
- ; Check in HKLM Wow6432Node for CurrentVersion
-
- ClearErrors
- ReadRegStr $2 HKLM "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment" \
- "CurrentVersion"
-
- Iferrors hkcu_any
-
- DetailPrint "HKEY_LOCAL_MACHINE Wow6432Node Java version $2"
-
- ${VersionCompare} $2 ${JRE_VERSION} $3
+ DetailPrint "Detected java in $0"
- IntCmp $3 1 yes yes no
+ ${GetFileVersion} "$0" $1
+ IfErrors no
-hkcu_any:
+ DetailPrint "Java version $1"
- ; Check in HKCU for any Java install
-
- StrCpy $0 0
-
-hkcu_any_loop:
- EnumRegKey $1 HKCU "SOFTWARE\JavaSoft" $0
-
- StrCmp $1 "Java Runtime Environment" found_hkcu
-
- StrCmp $1 "" hklm_any
-
- IntOp $0 $0 + 1
-
- Goto hkcu_any_loop
-
-found_hkcu:
-
- DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
- Goto maybe
-
-hklm_any:
-
- ; Check in HKCU for any Java install
-
- StrCpy $0 0
-
-hklm_any_loop:
- EnumRegKey $1 HKLM "SOFTWARE\JavaSoft" $0
-
- StrCmp $1 "Java Runtime Environment" found_hklm
-
- StrCmp $1 "" no
-
- IntOp $0 $0 + 1
-
- Goto hklm_any_loop
-
-found_hklm:
-
- DetailPrint "HKEY_CURRENT_USER has SOFTWARE\JavaSoft\$1"
-
- Goto maybe
+ ${VersionCompare} $1 ${JAVA_VERSION} $2
+ IntCmp $2 1 yes yes old
yes:
StrCpy $0 2
Goto done
-maybe:
+old:
StrCpy $0 1
Goto done
var quit
var skip
+Function GetJRE
+ ${OpenURL} "java.com"
+ MessageBox MB_OK "Click OK to continue after completing the Java Install."
+FunctionEnd
+
Function DetectJRE
Call DoDetectJRE
- IntCmp $0 1 ask_maybe ask_no yes
+ IntCmp $0 1 ask_old ask_no yes
ask_no:
- StrCpy $0 "No Java detected. Download and install?"
+ StrCpy $0 "Cannot find Java. Download and install?"
Goto ask
-ask_maybe:
- StrCpy $0 "Cannot determine installed Java version. Download and install?"
+ask_old:
+ StrCpy $0 "Java version appears to be too old. Download and install?"
Goto ask
ask:
MessageBox MB_YESNOCANCEL $0 IDYES do_java IDNO skip_java
-bail:
- Abort
-
do_java:
Call GetJRE
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTDevice extends altos_bt_device implements AltosDevice {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
AltosBTDevice current;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTKnown implements Iterable<AltosBTDevice> {
LinkedList<AltosBTDevice> devices = new LinkedList<AltosBTDevice>();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.basic.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable<AltosBTDevice> {
LinkedBlockingQueue<AltosBTDevice> found_devices;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosCSVUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.text.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
Frame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDataChooser extends JFileChooser {
JFrame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import libaltosJNI.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import java.awt.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import java.awt.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosDisplayThread extends Thread {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromDelete implements Runnable {
AltosEepromList flights;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromManage implements ActionListener {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
JFrame owner;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosEepromItem implements ActionListener {
AltosEepromLog log;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlashUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.table.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
}
new FlightStat(layout, y++, "Maximum speed",
String.format("%5.0f m/s", stats.max_speed),
- String.format("%5.0f mph", AltosConvert.meters_to_mph(stats.max_speed)),
+ String.format("%5.0f fps", AltosConvert.mps_to_fps(stats.max_speed)),
String.format("Mach %4.1f", AltosConvert.meters_to_mach(stats.max_speed)));
- if (stats.max_acceleration != AltosLib.MISSING) {
+ if (stats.max_acceleration != AltosLib.MISSING)
new FlightStat(layout, y++, "Maximum boost acceleration",
String.format("%5.0f m/s²", stats.max_acceleration),
String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.max_acceleration)),
String.format("%5.0f G", AltosConvert.meters_to_g(stats.max_acceleration)));
+ if (stats.state_accel[AltosLib.ao_flight_boost] != AltosLib.MISSING)
new FlightStat(layout, y++, "Average boost acceleration",
String.format("%5.0f m/s²", stats.state_accel[AltosLib.ao_flight_boost]),
String.format("%5.0f ft/s²", AltosConvert.meters_to_feet(stats.state_accel[AltosLib.ao_flight_boost])),
String.format("%5.0f G", AltosConvert.meters_to_g(stats.state_accel[AltosLib.ao_flight_boost])));
- }
if (stats.state_speed[AltosLib.ao_flight_drogue] != AltosLib.MISSING)
new FlightStat(layout, y++, "Drogue descent rate",
String.format("%5.0f m/s", stats.state_speed[AltosLib.ao_flight_drogue]),
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosGraphDataPoint implements AltosUIDataPoint {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
AltosGraphDataSet dataSet;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
private AltosFlightInfoTableModel model;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosPositionListener {
public void position_changed(int position);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosRomconfigUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosScanResult {
String callsign;
* Deal with TeleDongle on a serial port
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import libaltosJNI.*;
/*
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public class AltosSerialInUseException extends Exception {
public AltosDevice device;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class DelegatingRenderer implements ListCellRenderer<Object> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public class AltosUIDataMissing extends Exception {
public int id;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIDataPoint {
public abstract double x() throws AltosUIDataMissing;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIDataSet {
public abstract String name();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIFlightTab extends JComponent implements AltosFlightDisplay, HierarchyListener {
public GridBagLayout layout;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIFreqList extends JComboBox<AltosFrequency> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_9;
+package org.altusmetrum.altoslib_10;
import javax.swing.*;
import javax.imageio.ImageIO;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
JLabel label;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUILib extends AltosLib {
String OS = System.getProperty("os.name");
- if (OS.startsWith("Linux")) {
+ if (OS.startsWith("L") || OS.startsWith("W"))
has_bluetooth = true;
- }
initialized = true;
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
public interface AltosUIListener {
public void ui_changed(String look_and_feel);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.concurrent.*;
import javax.imageio.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, AltosMapInterface {
}
class MapTile extends AltosMapTile {
- public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- super(listener, upper_left, center, zoom, maptype, px_size);
+ public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ super(cache, upper_left, center, zoom, maptype, px_size);
}
public void paint(AltosMapTransform t) {
if (!g.hitClip(point.x, point.y, px_size, px_size))
return;
- AltosImage altos_image = cache.get(this, store, px_size, px_size);
-
+ AltosImage altos_image = get_image();
AltosUIImage ui_image = (AltosUIImage) altos_image;
-
- Image image = null;
+ Image image = null;
if (ui_image != null)
image = ui_image.image;
if (t.has_location()) {
String message = null;
switch (status) {
- case AltosMapTile.loading:
- message = "Loading...";
+ case AltosMapTile.fetching:
+ message = "Fetching...";
break;
case AltosMapTile.bad_request:
message = "Internal error";
return new MapMark(lat, lon, state);
}
- public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
- return new MapTile(listener, upper_left, center, zoom, maptype, px_size);
+ public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) {
+ return new MapTile(cache, upper_left, center, zoom, maptype, px_size);
}
public int width() {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.net.URL;
import java.net.URLConnection;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
class AltosUIMapPos extends Box {
AltosUIFrame owner;
JProgressBar pbar;
- AltosMapLoader loader;
-
JLabel site_list_label;
JComboBox<AltosLaunchSite> site_list;
}
public void debug(String format, Object ... arguments) {
- System.out.printf(format, arguments);
+ if (AltosSerial.debug)
+ System.out.printf(format, arguments);
}
r = r * 1000;
loading = true;
- loader.load(latitude, longitude, min_z, max_z, r, all_types());
+ new AltosMapLoader(map.map, this,
+ latitude, longitude,
+ min_z, max_z, r, all_types());
+
} catch (ParseException pe) {
load_button.setSelected(false);
}
map = new AltosUIMapNew();
- loader = new AltosMapLoader(map.map, this);
-
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.insets = i;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.*;
import java.awt.Component;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIPreferences extends AltosPreferences {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import javax.swing.filechooser.FileSystemView;
-public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
+public class AltosUIPreferencesBackend extends AltosPreferencesBackend {
private Preferences _preferences = null;
/* Use the file system view default directory */
return FileSystemView.getFileSystemView().getDefaultDirectory();
}
+
+ public void debug(String format, Object ... arguments) {
+ System.out.printf(format, arguments);
+ }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUIRateList extends JComboBox<String> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class AltosUITelemetryList extends JComboBox<String> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.util.*;
import libaltosJNI.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import com.sun.speech.freetts.Voice;
import com.sun.speech.freetts.VoiceManager;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.awt.*;
import java.awt.event.*;
*/
-package org.altusmetrum.altosuilib_9;
+package org.altusmetrum.altosuilib_10;
import java.lang.reflect.*;
import java.util.HashMap;
;;
esac
-../ao-tools/ao-cal-freq/ao-cal-freq --dev=$dev
+../ao-tools/ao-cal-freq/ao-cal-freq --tty=$dev
case $? in
0)
calline=`./get-radio-cal $dev`
echo""
echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ echo "\007"
ret=0
;;
esac
--- /dev/null
+#!/bin/sh
+
+if [ -x /usr/bin/dfu-util ]; then
+ DFU_UTIL=/usr/bin/dfu-util
+else
+ echo "Can't find dfu-util! Aborting."
+ exit 1
+fi
+
+if [ -x /usr/bin/ao-usbload ]; then
+ USBLOAD=/usr/bin/ao-usbload
+else
+ echo "Can't find ao-usbload! Aborting."
+ exit 1
+fi
+
+VERSION=1.0
+PRODUCT=ChaosKey
+
+echo "ChaosKey v$VERSION Turn-On and Calibration Program"
+echo "Copyright 2015 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\tChaosKey v$VERSION powered from USB"
+echo
+
+$DFU_UTIL -a 0 -s 0x08000000:leave -D ../src/chaoskey-v$VERSION/flash-loader/chaoskey-v$VERSION*.bin || exit 1
+
+sleep 2
+
+$USBLOAD --serial=1 ../src/chaoskey-v$VERSION/chaoskey-v$VERSION*.ihx || exit 1
+
+exit $?
ao-dumpflash ao-edit-telem ao-dump-up ao-elftohex \
ao-flash ao-usbload ao-test-igniter ao-test-baro \
ao-test-flash ao-cal-accel ao-test-gps ao-usbtrng \
- ao-cal-freq
+ ao-cal-freq ao-chaosread ao-makebin
if LIBSTLINK
SUBDIRS += ao-stmload
endif
--- /dev/null
+ao-chaosread
--- /dev/null
+bin_PROGRAMS=ao-chaosread
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_chaosread_LDADD=$(LIBUSB_LIBS)
+
+ao_chaosread_SOURCES = ao-chaosread.c
+
+man_MANS = ao-chaosread.1
--- /dev/null
+.\"
+.\" Copyright © 2016 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-chaosread" ""
+.SH NAME
+ao-chaosread \- read raw noise source from chaoskey
+.SH SYNOPSIS
+.B "ao-chaosread"
+.SH DESCRIPTION
+.I ao-chaosread
+reads ADC values from the noise source on the attached ChaosKey device.
+.SH OPTIONS
+.TP
+\-s serial | --serial serial
+This selects a ChaosKey by serial number instead of using the first
+one found.
+.SH USAGE
+.I ao-chaosread
+reads noise data.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libusb.h>
+#include <getopt.h>
+#include <string.h>
+#include <strings.h>
+
+#define CHAOS_SIZE 64
+
+#define CHAOS_VENDOR 0x1d50
+#define CHAOS_PRODUCT 0x60c6
+
+struct chaoskey {
+ libusb_context *ctx;
+ libusb_device_handle *handle;
+ int kernel_active;
+};
+
+libusb_device_handle *
+chaoskey_match(libusb_device *dev, char *match_serial)
+{
+ struct libusb_device_descriptor desc;
+ int ret;
+ int match_len;
+ char *device_serial = NULL;
+ libusb_device_handle *handle = NULL;
+
+ ret = libusb_get_device_descriptor(dev, &desc);
+ if (ret < 0) {
+ fprintf(stderr, "failed to get device descriptor: %s\n", libusb_strerror(ret));
+ return 0;
+ }
+
+ if (desc.idVendor != CHAOS_VENDOR)
+ return NULL;
+ if (desc.idProduct != CHAOS_PRODUCT)
+ return NULL;
+
+ ret = libusb_open(dev, &handle);
+
+ if (match_serial == NULL)
+ return handle;
+
+ if (ret < 0) {
+ fprintf(stderr, "failed to open device: %s\n", libusb_strerror(ret));
+ return NULL;
+ }
+
+ match_len = strlen(match_serial);
+ device_serial = malloc(match_len + 2);
+
+ if (!device_serial) {
+ fprintf(stderr, "malloc failed\n");
+ goto out;
+ }
+
+ ret = libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, device_serial, match_len + 1);
+
+ if (ret < 0) {
+ fprintf(stderr, "failed to get serial number: %s\n", libusb_strerror(ret));
+ goto out;
+ }
+
+ device_serial[ret] = '\0';
+
+ ret = strcmp(device_serial, match_serial);
+ free(device_serial);
+ if (ret)
+ goto out;
+
+ return handle;
+
+out:
+ free(device_serial);
+ if (handle)
+ libusb_close(handle);
+ return 0;
+}
+
+struct chaoskey *
+chaoskey_open(char *serial)
+{
+ struct chaoskey *ck;
+ int ret;
+ ssize_t num;
+ libusb_device **list;
+ libusb_device *device = NULL;
+ int d;
+
+ ck = calloc(sizeof (struct chaoskey), 1);
+ if (!ck)
+ goto out;
+ ret = libusb_init(&ck->ctx);
+ if (ret ) {
+ fprintf(stderr, "libusb_init failed: %s\n", libusb_strerror(ret));
+ goto out;
+ }
+
+ num = libusb_get_device_list(ck->ctx, &list);
+ if (num < 0) {
+ fprintf(stderr, "libusb_get_device_list failed: %s\n", libusb_strerror(num));
+ goto out;
+ }
+
+ for (d = 0; d < num; d++) {
+ libusb_device_handle *handle;
+
+ handle = chaoskey_match(list[d], serial);
+ if (handle) {
+ ck->handle = handle;
+ break;
+ }
+ }
+
+ libusb_free_device_list(list, 1);
+
+ if (!ck->handle) {
+ if (serial)
+ fprintf (stderr, "No chaoskey matching %s\n", serial);
+ else
+ fprintf (stderr, "No chaoskey\n");
+ goto out;
+ }
+
+ ck->kernel_active = libusb_kernel_driver_active(ck->handle, 0);
+ if (ck->kernel_active) {
+ ret = libusb_detach_kernel_driver(ck->handle, 0);
+ if (ret)
+ goto out;
+ }
+
+ ret = libusb_claim_interface(ck->handle, 0);
+ if (ret)
+ goto out;
+
+ return ck;
+out:
+ if (ck->kernel_active)
+ libusb_attach_kernel_driver(ck->handle, 0);
+ if (ck->ctx)
+ libusb_exit(ck->ctx);
+ free(ck);
+ return NULL;
+}
+
+void
+chaoskey_close(struct chaoskey *ck)
+{
+ libusb_release_interface(ck->handle, 0);
+ if (ck->kernel_active)
+ libusb_attach_kernel_driver(ck->handle, 0);
+ libusb_close(ck->handle);
+ libusb_exit(ck->ctx);
+ free(ck);
+}
+
+void
+chaoskey_transfer_callback(struct libusb_transfer *transfer)
+{
+ struct chaoskey *ck = transfer->user_data;
+}
+
+#define ENDPOINT 0x86
+
+int
+chaoskey_read(struct chaoskey *ck, uint8_t *buffer, int len)
+{
+ int total = 0;
+
+ while (len) {
+ int ret;
+ int transferred;
+
+ ret = libusb_bulk_transfer(ck->handle, ENDPOINT, buffer, len, &transferred, 10000);
+ if (ret) {
+ if (total)
+ return total;
+ else {
+ errno = EIO;
+ return -1;
+ }
+ }
+ len -= transferred;
+ buffer += transferred;
+ }
+}
+
+static const struct option options[] = {
+ { .name = "serial", .has_arg = 1, .val = 's' },
+ { .name = "length", .has_arg = 1, .val = 'l' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--serial=<serial>] [--length=<length>[kMG]]\n", program);
+ exit(1);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct chaoskey *ck;
+ char buf[1024];
+ int got;
+ int c;
+ char *serial = NULL;
+ char *length_string;
+ char *length_end;
+ unsigned long length = sizeof(buf);
+ int this_time;
+
+ while ((c = getopt_long(argc, argv, "s:l:", options, NULL)) != -1) {
+ switch (c) {
+ case 's':
+ serial = optarg;
+ break;
+ case 'l':
+ length_string = optarg;
+ length = strtoul(length_string, &length_end, 10);
+ if (!strcasecmp(length_end, "k"))
+ length *= 1024;
+ else if (!strcasecmp(length_end, "m"))
+ length *= 1024 * 1024;
+ else if (!strcasecmp(length_end, "g"))
+ length *= 1024 * 1024 * 1024;
+ else if (strlen(length_end))
+ usage(argv[0]);
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ck = chaoskey_open(serial);
+ if (!ck)
+ exit(1);
+
+ while (length) {
+ this_time = sizeof(buf);
+ if (length < sizeof(buf))
+ this_time = (int) length;
+ got = chaoskey_read(ck, buf, this_time);
+ if (got < 0) {
+ perror("read");
+ exit(1);
+ }
+ write(1, buf, got);
+ length -= got;
+ }
+ exit(0);
+}
}
}
-static const char *state_names[] = {
- "startup",
- "idle",
- "pad",
- "boost",
- "fast",
- "coast",
- "drogue",
- "main",
- "landed",
- "invalid"
-};
-
-
int
main (int argc, char **argv)
{
--- /dev/null
+bin_PROGRAMS=ao-makebin
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_ELFTOHEX_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_makebin_DEPENDENCIES = $(AO_ELFTOHEX_LIBS)
+
+ao_makebin_LDADD=$(AO_ELFTOHEX_LIBS) -lelf
+
+ao_makebin_SOURCES=ao-makebin.c
+
+man_MANS = ao-makebin.1
--- /dev/null
+.\"
+.\" Copyright © 2013 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 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, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-LOAD 1 "ao-makebin" ""
+.SH NAME
+ao-makebin \- construct raw binary file or DFU image from collection of ELF files
+.SH SYNOPSIS
+.B "ao-makebin"
+[\--base=\fIbase-address\fP]
+[\--output=\fIoutput.bin\fP]
+[\--dfu]
+[\--verbose]
+\fIinput.elf ...\fP
+.SH DESCRIPTION
+.I ao-makebin
+reads the specified .elf files and writes out a raw binary flash image
+.SH OPTIONS
+.TP
+\--base=\fIbase-address\fP
+This specifies the target address for the first byte of the file (default is 0)
+.TP
+\--output=\fIoutput.bin\fP
+This specifies the output file (default is stdout)
+.TP
+\--dfu
+Creates a DFU file (as documented by ST's UM0391 user manual) instead
+of a raw binary file.
+.TP
+\--verbose
+Dumps some debug information.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-elf.h"
+#include "ao-dfu.h"
+
+static const struct option options[] = {
+ { .name = "verbose", .has_arg = 0, .val = 'v' },
+ { .name = "output", .has_arg = 1, .val = 'o' },
+ { .name = "base", .has_arg = 1, .val = 'b' },
+ { .name = "align", .has_arg = 1, .val = 'a' },
+ { .name = "dfu", .has_arg = 0, .val = 'd' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<level>] [--output=<output.bin>] [--base=<base-address>] [--align=<align>] [--dfu] <input.elf> ...\n", program);
+ exit(1);
+}
+
+static int
+ends_with(char *whole, char *suffix)
+{
+ int whole_len = strlen(whole);
+ int suffix_len = strlen(suffix);
+
+ if (suffix_len > whole_len)
+ return 0;
+ return strcmp(whole + whole_len - suffix_len, suffix) == 0;
+}
+
+static struct ao_dfu_info dfu_info = {
+ .bcdDevice = 0x0000,
+ .idProduct = 0xdf11,
+ .idVendor = 0x0483,
+};
+
+int
+main (int argc, char **argv)
+{
+ char *output = NULL;
+ struct ao_hex_image *image = NULL;
+ struct ao_sym *file_symbols;
+ int num_file_symbols;
+ FILE *file;
+ int c;
+ uint32_t base = 0xffffffff;
+ uint32_t align = 0;
+ uint32_t length;
+ int verbose = 0;
+ int dfu = 0;
+
+ while ((c = getopt_long(argc, argv, "dvo:b:a:", options, NULL)) != -1) {
+ switch (c) {
+ case 'o':
+ output = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'b':
+ base = strtoul(optarg, NULL, 0);
+ break;
+ case 'a':
+ align = strtoul(optarg, NULL, 0);
+ break;
+ case 'd':
+ dfu = 1;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ while (argv[optind]) {
+ char *input = argv[optind];
+ struct ao_hex_image *tmp;
+
+ if (ends_with (input, ".ihx"))
+ tmp = ao_hex_load(input, &file_symbols, &num_file_symbols);
+ else
+ tmp = ao_load_elf(input, &file_symbols, &num_file_symbols);
+
+ if (!tmp)
+ usage(argv[0]);
+
+ if (verbose)
+ fprintf(stderr, "%s: 0x%x %d\n", input, tmp->address, tmp->length);
+
+ if (image) {
+ image = ao_hex_image_cat(image, tmp);
+ if (!image)
+ usage(argv[0]);
+ } else
+ image = tmp;
+ optind++;
+ }
+
+ if (base != 0xffffffff && base > image->address) {
+ fprintf(stderr, "requested base 0x%x is after image address 0x%x\n",
+ base, image->address);
+ usage(argv[0]);
+ }
+
+ if (verbose)
+ fprintf(stderr, "%s: base 0x%x length %d\n", output ? output : "<stdout>", image->address, image->length);
+
+ if (!output)
+ file = stdout;
+ else {
+ file = fopen(output, "w");
+ if (!file) {
+ perror(output);
+ exit(1);
+ }
+ }
+
+ if (dfu) {
+ if (!ao_dfu_write(file, &dfu_info, 1, image)) {
+ fprintf(stderr, "%s: dfu_write failed: %s\n", output, strerror(errno));
+ if (output)
+ unlink(output);
+ exit(1);
+ }
+ } else {
+ while (base < image->address) {
+ fputc(0xff, file);
+ base++;
+ }
+
+ if (fwrite(image->data, 1, image->length, file) != image->length) {
+ fprintf(stderr, "%s: failed to write bin file\n", output ? output : "<stdout>");
+ if (output)
+ unlink(output);
+ exit(1);
+ }
+
+ if (align) {
+ length = image->length;
+
+ while (length % align) {
+ fputc(0xff, file);
+ length++;
+ }
+ }
+ fflush(file);
+ }
+
+ exit(0);
+}
ao-editaltos.h \
ao-elf.c \
ao-elf.h \
+ ao-dfu.c \
+ ao-dfu.h \
ao-selfload.c \
ao-selfload.h \
ao-verbose.c \
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include "ao-hex.h"
+#include "ao-dfu.h"
+
+static uint32_t dfu_crc;
+static FILE *dfu_file;
+static int dfu_failed;
+static int dfu_error;
+
+static uint32_t update_crc(uint32_t crc, uint8_t byte)
+{
+ int j;
+ uint32_t mask;
+
+ crc = crc ^ byte;
+ for (j = 0; j < 8; j++) {
+ mask = -(crc & 1);
+ crc = (crc >> 1) ^ (0xEDB88320 & mask);
+ }
+ return crc;
+}
+
+static void dfu_init(FILE *file)
+{
+ dfu_crc = 0xffffffff;
+ dfu_file = file;
+ dfu_failed = 0;
+ dfu_error = 0;
+}
+
+static int dfu_fini(void)
+{
+ if (fflush(dfu_file) == EOF) {
+ if (!dfu_failed) {
+ dfu_failed = 1;
+ dfu_error = errno;
+ }
+ }
+ if (dfu_failed)
+ errno = dfu_error;
+ return !dfu_failed;
+}
+
+static void dfu_8(uint8_t byte) {
+ if (putc(byte, dfu_file) == EOF) {
+ if (!dfu_failed) {
+ dfu_failed = 1;
+ dfu_error = errno;
+ }
+ }
+ dfu_crc = update_crc(dfu_crc, byte);
+}
+
+static void dfu_pad(int len) {
+ while (len--)
+ dfu_8(0);
+}
+
+static void dfu_string(char *string) {
+ char c;
+
+ while ((c = *string++))
+ dfu_8((uint8_t) c);
+}
+
+static void dfu_string_pad(char *string, int len) {
+ char c;
+
+ while ((c = *string++)) {
+ dfu_8((uint8_t) c);
+ len--;
+ }
+ dfu_pad(len);
+}
+
+static void dfu_block(uint8_t *bytes, int len) {
+ while (len--)
+ dfu_8(*bytes++);
+}
+
+static void dfu_lsb16(uint16_t value) {
+ dfu_8(value);
+ dfu_8(value>>8);
+}
+
+static void dfu_lsb32(uint32_t value) {
+ dfu_8(value);
+ dfu_8(value >> 8);
+ dfu_8(value >> 16);
+ dfu_8(value >> 24);
+}
+
+static uint32_t dfu_image_size(struct ao_hex_image *image) {
+ return 8 + image->length;
+}
+
+static uint32_t dfu_images_size(int num_image, struct ao_hex_image images[])
+{
+ uint32_t size = 0;
+ int i;
+
+ for (i = 0; i < num_image; i++)
+ size += dfu_image_size(&images[i]);
+ return size;
+}
+
+static void dfu_image(struct ao_hex_image *image)
+{
+ dfu_lsb32(image->address);
+ dfu_lsb32(image->length);
+ dfu_block(image->data, image->length);
+}
+
+static void dfu_target(char *name, int num_image, struct ao_hex_image images[])
+{
+ uint32_t images_size = dfu_images_size(num_image, images);
+ int i;
+
+ dfu_string("Target");
+ dfu_8(0);
+ if (name) {
+ dfu_8(1);
+ dfu_pad(3);
+ dfu_string_pad(name, 255);
+ } else {
+ dfu_8(0);
+ dfu_pad(3);
+ dfu_pad(255);
+ }
+ dfu_lsb32(images_size);
+ dfu_lsb32(num_image);
+ for (i = 0; i < num_image; i++)
+ dfu_image(&images[i]);
+}
+
+static uint32_t dfu_target_size(int num_image, struct ao_hex_image images[])
+{
+ return 274 + dfu_images_size(num_image, images);
+}
+
+static uint32_t
+dfu_size(int num_image, struct ao_hex_image images[])
+{
+ uint32_t size = 0;
+ size += 11; /* DFU Prefix */
+
+ size += dfu_target_size(num_image, images);
+
+ return size;
+}
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[])
+{
+ uint32_t total_size;
+
+ total_size = dfu_size(num_image, images);
+
+ dfu_init(file);
+ /* DFU Prefix */
+ dfu_string(DFU_SIGNATURE);
+ dfu_8(0x01);
+ dfu_lsb32(total_size);
+ dfu_8(0x01);
+
+ dfu_target("ST...", num_image, images);
+
+ /* DFU Suffix */
+ dfu_lsb16(info->bcdDevice);
+ dfu_lsb16(info->idProduct);
+ dfu_lsb16(info->idVendor);
+ dfu_lsb16(DFU_SPEC_VERSION);
+ dfu_string("UFD");
+ dfu_8(16);
+ dfu_lsb32(dfu_crc);
+ return dfu_fini();
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_DFU_H_
+#define _AO_DFU_H_
+
+struct ao_dfu_info {
+ uint16_t bcdDevice;
+ uint16_t idProduct;
+ uint16_t idVendor;
+};
+
+#define DFU_SIGNATURE "DfuSe"
+#define DFU_SPEC_VERSION 0x011a
+
+#define DFU_TARGET_SIGNATURE "Target"
+
+int
+ao_dfu_write(FILE *file, struct ao_dfu_info *info, int num_image, struct ao_hex_image images[]);
+
+#endif /* _AO_DFU_H_ */
#endif
size_t nshdr;
size_t s;
-
+
if (elf_getshdrstrndx(e, &shstrndx) < 0)
return 0;
(uint32_t) phdr.p_filesz,
(uint32_t) phdr.p_memsz);
#endif
-
+
for (s = 0; s < nshdr; s++) {
scn = elf_getscn(e, s);
#endif
if (phdr.p_offset <= shdr.sh_offset && shdr.sh_offset < phdr.p_offset + phdr.p_filesz) {
-
+
if (shdr.sh_size == 0)
continue;
struct ao_sym *symbol;
int num_symbols = 0;
int size_symbols = 0;
-
+
extended_addr = 0;
for (i = 0; i < hex->nrecord; i++) {
record = hex->records[i];
free(image);
}
+uint32_t min(uint32_t a, uint32_t b) { return a < b ? a : b; }
+uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; }
+
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b)
+{
+ struct ao_hex_image *n;
+ uint32_t base, bound;
+ uint32_t length;
+
+ base = min(a->address, b->address);
+ bound = max(a->address + a->length, b->address + b->length);
+ length = bound - base;
+
+ n = calloc (sizeof (struct ao_hex_image) + length, 1);
+ if (!n)
+ return NULL;
+ n->address = base;
+ n->length = length;
+ memset(n->data, 0xff, length);
+ memcpy(n->data + a->address - n->address, a->data, a->length);
+ memcpy(n->data + b->address - n->address, b->data, b->length);
+ return n;
+}
+
int
ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b)
{
file = fopen (filename, "r");
if (!file)
return NULL;
-
+
hex_file = ao_hex_file_read(file, filename);
fclose(file);
if (!hex_file)
ao_hex_record_set_checksum(record);
hex_file->records[nrecord++] = record;
-
+
/* Add the symbols
*/
goto write_failed;
}
ret = true;
-
+
if (fflush(file) != 0)
ret = false;
write_failed:
struct ao_hex_image *
ao_hex_load(char *filename, struct ao_sym **symbols, int *num_symbols);
+struct ao_hex_image *
+ao_hex_image_cat(struct ao_hex_image *a, struct ao_hex_image *b);
+
int
ao_hex_image_equal(struct ao_hex_image *a, struct ao_hex_image *b);
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.6.2)
-ANDROID_VERSION=10
+AC_INIT([altos], 1.6.3)
+ANDROID_VERSION=11
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
dnl ==========================================================================
dnl Java library versions
-ALTOSUILIB_VERSION=9
-ALTOSLIB_VERSION=9
+ALTOSUILIB_VERSION=10
+ALTOSLIB_VERSION=10
AC_SUBST(ALTOSLIB_VERSION)
AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
ANDROID_RELEASE=no
if test "x$ANDROID_SDK" != "xno"; then
HAVE_ANDROID_SDK="yes"
- if test -f "$HOME/altusmetrumllc/release.keystore" -a -f "$HOME/altusmetrumllc/Passphrase"; then
+ if test -f "$HOME/altusmetrumllc/google-play-release.keystore" -a -f "$HOME/altusmetrumllc/google-play-passphrase"; then
ANDROID_RELEASE=yes
fi
else
[GOOGLEKEYFILE=$withval], [GOOGLEKEYFILE=$HOME/altusmetrumllc/google-maps-api-key])
if test -r "$GOOGLEKEYFILE" -a -s "$GOOGLEKEYFILE"; then
- GOOGLEKEY='"'`cat "$GOOGLEKEYFILE"`'"'
+ GOOGLEKEY=`cat "$GOOGLEKEYFILE"`
HAVE_GOOGLE_KEY="yes"
else
GOOGLEKEY='null'
ao-tools/ao-cal-freq/Makefile
ao-tools/ao-test-gps/Makefile
ao-tools/ao-usbtrng/Makefile
+ao-tools/ao-chaosread/Makefile
+ao-tools/ao-makebin/Makefile
ao-utils/Makefile
src/Version
])
#
RELNOTES_INC=\
+ release-notes-1.6.3.inc \
release-notes-1.6.2.inc \
release-notes-1.6.1.inc \
release-notes-1.6.inc \
doesn't, the most likely reason is that your Android
device doesn't support USB On-the-go.
- === Configuring AltosDroid
+ === AltosDroid Menu
+
+ The main AltosDroid menu has a selection of operation
+ and configuration options.
+
+ Connect a device::
+
+ Offers a menu of available TeleBT devices, and an
+ option to scan for additional devices.
+
+ Disconnect device::
+
+ Disconnects the current TeleBT or TeleDongle
+ device. You can reconnect TeleBT over bluetooth by
+ using Connect a Device. You can reconnect a USB device
+ by unplugging it and then plugging it back in.
- There are several configuration and operation
- parameters available in the AltosDroid menu.
-
Select radio frequency::
This selects which frequency to listen on by bringing
up a menu of pre-set radio frequencies. Pick the one
which matches your altimeter.
- Select data rate::
+ Select Tracker::
+
+ Switches the information displays to show data for a
+ different transmitting device. The map will always
+ show all of the devices in view. Trackers are shown
+ and selected by serial number, so make sure you note
+ the serial number of devices in each airframe.
+
+ Delete Track::
+
+ Deletes all information about a transmitting device.
+
+ Setup::
+
+ Offers additional configuration operations. See
+ <<_setup>>.
+
+ Idle Mode::
+
+ Communicate with an altimeter in Idle mode. See <<_idle_mode>>
+
+ Quit::
+
+ Shuts down AltosDroid.
+
+ === Setup
+
+ Telemetry Rate::
Altus Metrum transmitters can be configured to operate
at lower data rates to improve transmission range. If
you have configured your device to do this, this menu
item allows you to change the receiver to match.
- Change units::
-
- This toggles between metric and imperial units.
-
- Load maps::
+ Units::
- Brings up a dialog allowing you to download offline
- map tiles so that you can have maps available even if
- you have no network connectivity at the launch site.
+ Selects which units used to report values.
- Map type::
+ Map Type::
Displays a menu of map types and lets you select
one. Hybrid maps include satellite images with a
includes roads along with shadows indicating changes
in elevation, and other geographical features.
- Toggle Online/Offline maps::
+ Map Source::
- Switches between online and offline maps. Online maps
+ Select between online and offline maps. Online maps
will show a 'move to current position' icon in the
upper right corner, while offline maps will have
copyright information all over the map. Otherwise,
they're pretty similar.
- Select Tracker::
+ Preload Maps::
- Switches the information displays to show data for a
- different transmitting device. The map will always
- show all of the devices in view. Trackers are shown
- and selected by serial number, so make sure you note
- the serial number of devices in each airframe.
+ Brings up a dialog allowing you to download offline
+ map tiles so that you can have maps available even if
+ you have no network connectivity at the launch site.
+
+ Manage Frequencies::
- Delete Track::
+ This presents a dialog containing the current list of
+ frequencies that will be show in the 'Select radio
+ frequency' menu. You can change the label for existing
+ frequencies, delete or add new frequencies.
+
+ === Idle Mode
+
+ Callsign::
+
+ Lets you configure the callsign used by AltosDroid to
+ communicate with the flight computer. The callsign on
+ the two devices must match or the communication will
+ fail. This provides a modest amount of protection
+ against accidentally controlling another persons
+ flight computer.
+
+ Monitor::
+
+ This provides similar information to monitoring the
+ telemetry stream from a flight computer in flight
+ mode. The title of the application will change to
+ include (idle) so you can tell this mode is active.
+
+ Reboot::
+
+ Remotely reboots the flight computer. This is useful
+ when the flight computers turned on while the airframe
+ is horizontal and you want to restart the flight
+ computers in pad mode after raising the airframe to
+ vertical.
+
+ Fire Igniters::
+
+ Remotely control igniters for ground testing recovery
+ systems.
- Deletes all information about a transmitting device.
-
=== AltosDroid Flight Monitoring
AltosDroid is designed to mimic the AltosUI flight
Bearing::
- This is the aziumuth from true north for the rocket
+ This is the azimuth from true north for the rocket
from the android device. Use this in combination with
the Elevation value to help locate the rocket in the
sky, or at least to help point the antenna in the
Bearing::
- This is the aziumuth from true north for the rocket
+ This is the azimuth from true north for the rocket
from the android device. Use this in combination with
the Elevation value to help locate the rocket in the
sky, or at least to help point the antenna in the
Max Height::
- Shows the maximum height above launch pad.
+ Shows the maximum height above launch pad seen during
+ the flight.
Max Speed::
</legalnotice>
<revhistory>
<?dbhtml filename="altusmetrum-revhistory.html"?>
+ <revision>
+ <revnumber>1.6.3</revnumber>
+ <date>21 April 2016</date>
+ <revremark>
+ Minor release adding idle mode to AltosDroid and fixing various
+ host software bugs.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.6.2</revnumber>
<date>10 January 2016</date>
</legalnotice>
<revhistory>
<?dbhtml filename="easymini-revhistory.html"?>
+ <revision>
+ <revnumber>1.6.3</revnumber>
+ <date>21 April 2016</date>
+ <revremark>
+ Minor release fixing various host software bugs.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.6.2</revnumber>
<date>10 January 2016</date>
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.6.2.raw[]
--- /dev/null
+= Release Notes for Version 1.6.3
+:toc!:
+:doctype: article
+
+ Version 1.6.3 adds idle mode to AltosDroid and has bug fixes
+ for our host software on desktops, laptops an android devices
+ along with BlueTooth support for Windows.
+
+ == AltOS
+
+ AltOS fixes:
+
+ * Fix hardware flow control on TeleBT v3.0. RTS/CTS is
+ wired backwards on this board, switch from using the
+ hardware to driving these pins with software.
+
+ == AltosUI and TeleGPS Applications
+
+ AltosUI and TeleGPS New Features:
+
+ * Add BlueTooth support for Windows operating system. This
+ supports connections to TeleBT over BlueTooth rather than
+ just USB.
+
+ AltosUI and TeleGPS Fixes:
+
+ * Change Java detection and install on Windows. Detection is
+ now done by looking for the 'javaw.exe' program, and
+ installation by opening a browser on the java.com web site.
+
+ * Delay polling while the Fire Igniters is visible to allow
+ for TeleMega to report back complete status over the radio.
+
+ * Disallow changing RF calibration numbers in the
+ configuration UI. There's no good reason to change this from
+ the field, and recovering is really hard if you haven't
+ written down the right number.
+
+ * Fix USB device discovery on Mac OS X El Capitan. This makes
+ the connected Altus Metrum USB devices appear again.
+
+ * Fix acceleration data presented in MonitorIdle mode for
+ TeleMetrum v2.0 flight computers.
+
+ == AltosDroid
+
+ AltosDroid new features:
+
+ * Monitor Idle mode. Check state of flight computer while in
+ idle mode over the radio link
+
+ * Fire Igniters. Remotely fire ignires for recovery system
+ ground tests.
+
+ * Remote reboot. Cause the flight computer to reboot over the
+ radio link. This provides a method for switching the flight
+ computer from idle to flight mode without needing to reach
+ the power switch.
+
+ * Configurable frequency menu. Change the set of available
+ frequencies and provide more descriptive names.
+
+ AltosDroid bug fixes:
+
+ * Don't set target location if GPS hasn't locked yet.
+
+ * Fix saving target states so they can be reloaded when the
+ application restarts. When the application is shut down and
+ restarted, all previous target state information will be
+ restored (including GPS position if available).
+
+ * Fix crash on some Android devices for offline maps when
+ changing the map scale or location.
+
+ * Don't require USB OTG support. This kept the latest
+ AltosDroid from being offered on devices without USB device
+ support, although it can work without that just fine using
+ BlueTooth.
+
+ * Don't require bluetooth to be enabled. This allows the
+ application to operate with USB devices or just show old
+ data without turning on the bluetooth radio.
+
+ * Recover old tracker positions when restarting
+ application. This finally allows you to safely stop and
+ restart the application without losing the last known
+ location of any tracker.
+
+ == Documentation
+
+ * Document TeleMega and EasyMega additional pyro channel
+ continuity audio alert pattern.
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.6.2.raw[]
[appendix]
== Release Notes
+ :leveloffset: 2
+ include::release-notes-1.6.3.raw[]
+
+ <<<<
:leveloffset: 2
include::release-notes-1.6.2.raw[]
controlling the flight or transmitting telemetry
signals, but no record of the flight will be
stored in on-board flash.
+
+ |Additional Igniters
+ |four very short beeps
+ |Continuity indication for the four additional pyro
+ |channels on TeleMega and EasyMega. One high tone for
+ |no continuity, one low tone for continuity. These are
+ |produced after the continuity indicators for the two
+ |primary igniter channels.
+
|====
ifdef::radio[]
application-*.png
altusmetrum-*.png
+altusmetrum.xpm
+application-vnd.altusmetrum.micropeak.svg
*.rc
*.ico
*.icns
#
ifeq ($(OS),Linux)
-JAVA_CFLAGS=-I/usr/lib/jvm/java-6-openjdk/include
+OS_SRCS=libaltos_posix.c libaltos_linux.c
-OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS)
+JAVA_CFLAGS=-I/usr/lib/jvm/default-java/include -I/usr/lib/jvm/default-java/include/linux
+
+OS_LIB_CFLAGS=-DLINUX -DPOSIX_TTY $(JAVA_CFLAGS) -shared -fPIC
OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
#
ifeq ($(OS),Darwin)
+OS_SRCS=libaltos_posix.c libaltos_darwin.c
+
#OS_LIB_CFLAGS=\
# -DDARWIN -DPOSIX_TTY -arch i386 -arch x86_64 \
# --sysroot=/Developer/SDKs/MacOSX10.5.sdk -mmacosx-version-min=10.5 \
# -iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
# -iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-XCODE=/Applications/Xcode.app
-SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk
+XCODE=/Applications/Xcode-beta.app
+SDK=$(XCODE)/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk
MINVERSION=10.5
OS_LIB_CFLAGS=\
-iwithsysroot /System/Library/Frameworks/JavaVM.framework/Headers \
-iwithsysroot /System/Library/Frameworks/IOKit.framework/Headers \
-iwithsysroot /System/Library/Frameworks/CoreFoundation.framework/Headers
-OS_APP_CFLAGS=$(OS_LIB_CFLAGS)
+OS_APP_CFLAGS=$(OS_LIB_CFLAGS) -O0 -g
OS_LDFLAGS =\
-framework IOKit -framework CoreFoundation
#
ifneq (,$(findstring MINGW,$(OS)))
+OS_SRCS=libaltos_windows.c
+
CC=gcc
OS_LIB_CFLAGS = -DWINDOWS -mconsole -DBUILD_DLL
LDFLAGS=$(OS_LDFLAGS)
HEADERS=libaltos.h
-SRCS = libaltos.c $(SWIG_WRAP)
+SRCS = libaltos_common.c $(OS_SRCS) $(SWIG_WRAP)
OBJS = $(SRCS:%.c=%.o)
LIBS = $(DARWIN_LIBS)
$(CC) -o $@ $(OS_APP_CFLAGS) cjnitest.c $(LIBNAME) $(LIBS) $(LDFLAGS)
$(LIBNAME): $(OBJS)
- $(CC) -shared $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
+ $(CC) -shared -fPIC $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(LDFLAGS)
clean:
rm -f $(CLASSFILES) $(OBJS) $(LIBNAME) $(CJNITEST) cjnitest.o
JAVAC=javac
-AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE)
+AM_CFLAGS=-DLINUX -DPOSIX_TTY -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
AM_JAVACFLAGS=-target 1.6 -encoding UTF-8 -Xlint:deprecation -source 6
altoslibdir=$(libdir)/altos
libaltos_la_LDFLAGS=-version-info 1:0:1 -Wl,-znoexecstack
libaltos_la_SOURCES=\
- libaltos.c \
+ libaltos_common.c \
+ libaltos_posix.c \
+ libaltos_linux.c \
+ libaltos_wrap.c \
+ libaltos.h \
+ libaltos_posix.h \
+ libaltos_private.h
+
+WINDOWS_SRC=\
+ libaltos_common.c\
+ libaltos_windows.c\
libaltos_wrap.c
+WINDOWS_H=\
+ libaltos.h
+
noinst_PROGRAMS=cjnitest
cjnitest_SOURCES=cjnitest.c
MINGCC32=i686-w64-mingw32-gcc
MINGCC64=x86_64-w64-mingw32-gcc
-MINGFLAGS=-Wall -DWINDOWS -DBUILD_DLL -I$(JVM_INCLUDE)
-MINGLIBS=-lsetupapi
+MINGFLAGS=-Wall -Wextra -DWINDOWS -DBUILD_DLL -mconsole -I$(JVM_INCLUDE) -I$(JVM_INCLUDE)/linux
+MINGLIBS=-lsetupapi -lws2_32
fat: all altos.dll altos64.dll
-altos.dll: $(libaltos_la_SOURCES)
- $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+ $(MINGCC32) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
-altos64.dll: $(libaltos_la_SOURCES)
- $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(libaltos_la_SOURCES) $(MINGLIBS)
+altos64.dll: $(WINDOWS_SRC) $(WINDOWS_H)
+ $(MINGCC64) -o $@ $(MINGFLAGS) -shared $(WINDOWS_SRC) $(MINGLIBS)
clean-local:
-rm -rf libaltosJNI *.class *.java classlibaltos.stamp $(SWIG_FILE) libaltos_wrap.c altos.dll altos64.dll
+++ /dev/null
-/*
- * Copyright © 2010 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "libaltos.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
-
-#define USE_POLL
-
-PUBLIC int
-altos_init(void)
-{
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC void
-altos_fini(void)
-{
-}
-
-static struct altos_error last_error;
-
-static void
-altos_set_last_error(int code, char *string)
-{
- last_error.code = code;
- strncpy(last_error.string, string, sizeof (last_error.string) -1);
- last_error.string[sizeof(last_error.string)-1] = '\0';
-}
-
-PUBLIC void
-altos_get_last_error(struct altos_error *error)
-{
- *error = last_error;
-}
-
-#ifdef DARWIN
-
-#include <unistd.h>
-
-#undef USE_POLL
-
-/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
-static char *
-altos_strndup (const char *s, size_t n)
-{
- size_t len = strlen (s);
- char *ret;
-
- if (len <= n)
- return strdup (s);
- ret = malloc(n + 1);
- strncpy(ret, s, n);
- ret[n] = '\0';
- return ret;
-}
-
-#else
-#define altos_strndup strndup
-#endif
-
-#ifdef POSIX_TTY
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <termios.h>
-#include <errno.h>
-
-#define USB_BUF_SIZE 64
-
-struct altos_file {
- int fd;
-#ifdef USE_POLL
- int pipe[2];
-#else
- int out_fd;
-#endif
- unsigned char out_data[USB_BUF_SIZE];
- int out_used;
- unsigned char in_data[USB_BUF_SIZE];
- int in_used;
- int in_read;
-};
-
-static void
-altos_set_last_posix_error(void)
-{
- altos_set_last_error(errno, strerror(errno));
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
- struct altos_file *file = calloc (sizeof (struct altos_file), 1);
- int ret;
- struct termios term;
-
- if (!file) {
- altos_set_last_posix_error();
- return NULL;
- }
-
-// altos_set_last_error(12, "yeah yeah, failed again");
-// free(file);
-// return NULL;
-
- file->fd = open(device->path, O_RDWR | O_NOCTTY);
- if (file->fd < 0) {
- altos_set_last_posix_error();
- free(file);
- return NULL;
- }
-#ifdef USE_POLL
- pipe(file->pipe);
-#else
- file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
- if (file->out_fd < 0) {
- altos_set_last_posix_error();
- close(file->fd);
- free(file);
- return NULL;
- }
-#endif
- ret = tcgetattr(file->fd, &term);
- if (ret < 0) {
- altos_set_last_posix_error();
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- cfmakeraw(&term);
- cfsetospeed(&term, B9600);
- cfsetispeed(&term, B9600);
-#ifdef USE_POLL
- term.c_cc[VMIN] = 1;
- term.c_cc[VTIME] = 0;
-#else
- term.c_cc[VMIN] = 0;
- term.c_cc[VTIME] = 1;
-#endif
- ret = tcsetattr(file->fd, TCSAFLUSH, &term);
- if (ret < 0) {
- altos_set_last_posix_error();
- close(file->fd);
-#ifndef USE_POLL
- close(file->out_fd);
-#endif
- free(file);
- return NULL;
- }
- return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
- if (file->fd != -1) {
- int fd = file->fd;
- file->fd = -1;
-#ifdef USE_POLL
- write(file->pipe[1], "\r", 1);
-#else
- close(file->out_fd);
- file->out_fd = -1;
-#endif
- close(fd);
- }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
- altos_close(file);
- free(file);
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
- if (file->out_used && 0) {
- printf ("flush \"");
- fwrite(file->out_data, 1, file->out_used, stdout);
- printf ("\"\n");
- }
- while (file->out_used) {
- int ret;
-
- if (file->fd < 0)
- return -EBADF;
-#ifdef USE_POLL
- ret = write (file->fd, file->out_data, file->out_used);
-#else
- ret = write (file->out_fd, file->out_data, file->out_used);
-#endif
- if (ret < 0) {
- altos_set_last_posix_error();
- return -last_error.code;
- }
- if (ret) {
- memmove(file->out_data, file->out_data + ret,
- file->out_used - ret);
- file->out_used -= ret;
- }
- }
- return 0;
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret) {
- return ret;
- }
- }
- file->out_data[file->out_used++] = c;
- ret = 0;
- if (file->out_used == USB_BUF_SIZE)
- ret = altos_flush(file);
- return ret;
-}
-
-#ifdef USE_POLL
-#include <poll.h>
-#endif
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
- int ret;
-#ifdef USE_POLL
- struct pollfd fd[2];
-#endif
-
- if (timeout == 0)
- timeout = -1;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
-#ifdef USE_POLL
- fd[0].fd = file->fd;
- fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
- fd[1].fd = file->pipe[0];
- fd[1].events = POLLIN;
- ret = poll(fd, 2, timeout);
- if (ret < 0) {
- altos_set_last_posix_error();
- return LIBALTOS_ERROR;
- }
- if (ret == 0)
- return LIBALTOS_TIMEOUT;
-
- if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
- return LIBALTOS_ERROR;
- if (fd[0].revents & POLLIN)
-#endif
- {
- ret = read(file->fd, file->in_data, USB_BUF_SIZE);
- if (ret < 0) {
- altos_set_last_posix_error();
- return LIBALTOS_ERROR;
- }
- file->in_read = 0;
- file->in_used = ret;
-#ifndef USE_POLL
- if (ret == 0 && timeout > 0)
- return LIBALTOS_TIMEOUT;
-#endif
- }
- }
- if (file->in_used && 0) {
- printf ("fill \"");
- fwrite(file->in_data, 1, file->in_used, stdout);
- printf ("\"\n");
- }
- return 0;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
- int ret;
- while (file->in_read == file->in_used) {
- if (file->fd < 0)
- return LIBALTOS_ERROR;
- ret = altos_fill(file, timeout);
- if (ret)
- return ret;
- }
- return file->in_data[file->in_read++];
-}
-
-#endif /* POSIX_TTY */
-
-/*
- * Scan for Altus Metrum devices by looking through /sys
- */
-
-#ifdef LINUX
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <dirent.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <bluetooth/bluetooth.h>
-#include <bluetooth/hci.h>
-#include <bluetooth/hci_lib.h>
-#include <bluetooth/rfcomm.h>
-
-static char *
-cc_fullname (char *dir, char *file)
-{
- char *new;
- int dlen = strlen (dir);
- int flen = strlen (file);
- int slen = 0;
-
- if (dir[dlen-1] != '/')
- slen = 1;
- new = malloc (dlen + slen + flen + 1);
- if (!new)
- return 0;
- strcpy(new, dir);
- if (slen)
- strcat (new, "/");
- strcat(new, file);
- return new;
-}
-
-static char *
-cc_basename(char *file)
-{
- char *b;
-
- b = strrchr(file, '/');
- if (!b)
- return file;
- return b + 1;
-}
-
-static char *
-load_string(char *dir, char *file)
-{
- char *full = cc_fullname(dir, file);
- char line[4096];
- char *r;
- FILE *f;
- int rlen;
-
- f = fopen(full, "r");
- free(full);
- if (!f)
- return NULL;
- r = fgets(line, sizeof (line), f);
- fclose(f);
- if (!r)
- return NULL;
- rlen = strlen(r);
- if (r[rlen-1] == '\n')
- r[rlen-1] = '\0';
- return strdup(r);
-}
-
-static int
-load_hex(char *dir, char *file)
-{
- char *line;
- char *end;
- long i;
-
- line = load_string(dir, file);
- if (!line)
- return -1;
- i = strtol(line, &end, 16);
- free(line);
- if (end == line)
- return -1;
- return i;
-}
-
-static int
-load_dec(char *dir, char *file)
-{
- char *line;
- char *end;
- long i;
-
- line = load_string(dir, file);
- if (!line)
- return -1;
- i = strtol(line, &end, 10);
- free(line);
- if (end == line)
- return -1;
- return i;
-}
-
-static int
-dir_filter_tty_colon(const struct dirent *d)
-{
- return strncmp(d->d_name, "tty:", 4) == 0;
-}
-
-static int
-dir_filter_tty(const struct dirent *d)
-{
- return strncmp(d->d_name, "tty", 3) == 0;
-}
-
-struct altos_usbdev {
- char *sys;
- char *tty;
- char *manufacturer;
- char *product_name;
- int serial; /* AltOS always uses simple integer serial numbers */
- int idProduct;
- int idVendor;
-};
-
-static char *
-usb_tty(char *sys)
-{
- char *base;
- int num_configs;
- int config;
- struct dirent **namelist;
- int interface;
- int num_interfaces;
- char endpoint_base[20];
- char *endpoint_full;
- char *tty_dir;
- int ntty;
- char *tty;
-
- base = cc_basename(sys);
- num_configs = load_hex(sys, "bNumConfigurations");
- num_interfaces = load_hex(sys, "bNumInterfaces");
- for (config = 1; config <= num_configs; config++) {
- for (interface = 0; interface < num_interfaces; interface++) {
- sprintf(endpoint_base, "%s:%d.%d",
- base, config, interface);
- endpoint_full = cc_fullname(sys, endpoint_base);
-
-
- /* Check for tty:ttyACMx style names
- */
- ntty = scandir(endpoint_full, &namelist,
- dir_filter_tty_colon,
- alphasort);
- if (ntty > 0) {
- free(endpoint_full);
- tty = cc_fullname("/dev", namelist[0]->d_name + 4);
- free(namelist);
- return tty;
- }
-
- /* Check for tty/ttyACMx style names
- */
- tty_dir = cc_fullname(endpoint_full, "tty");
- ntty = scandir(tty_dir, &namelist,
- dir_filter_tty,
- alphasort);
- free (tty_dir);
- if (ntty > 0) {
- tty = cc_fullname("/dev", namelist[0]->d_name);
- free(endpoint_full);
- free(namelist);
- return tty;
- }
-
- /* Check for ttyACMx style names
- */
- ntty = scandir(endpoint_full, &namelist,
- dir_filter_tty,
- alphasort);
- free(endpoint_full);
- if (ntty > 0) {
- tty = cc_fullname("/dev", namelist[0]->d_name);
- free(namelist);
- return tty;
- }
-
- }
- }
- return NULL;
-}
-
-static struct altos_usbdev *
-usb_scan_device(char *sys)
-{
- struct altos_usbdev *usbdev;
- char *tty;
-
- tty = usb_tty(sys);
- if (!tty)
- return NULL;
- usbdev = calloc(1, sizeof (struct altos_usbdev));
- if (!usbdev)
- return NULL;
- usbdev->sys = strdup(sys);
- usbdev->manufacturer = load_string(sys, "manufacturer");
- usbdev->product_name = load_string(sys, "product");
- usbdev->serial = load_dec(sys, "serial");
- usbdev->idProduct = load_hex(sys, "idProduct");
- usbdev->idVendor = load_hex(sys, "idVendor");
- usbdev->tty = tty;
- return usbdev;
-}
-
-static void
-usbdev_free(struct altos_usbdev *usbdev)
-{
- free(usbdev->sys);
- free(usbdev->manufacturer);
- free(usbdev->product_name);
- /* this can get used as a return value */
- if (usbdev->tty)
- free(usbdev->tty);
- free(usbdev);
-}
-
-#define USB_DEVICES "/sys/bus/usb/devices"
-
-static int
-dir_filter_dev(const struct dirent *d)
-{
- const char *n = d->d_name;
- char c;
-
- while ((c = *n++)) {
- if (isdigit(c))
- continue;
- if (c == '-')
- continue;
- if (c == '.' && n != d->d_name + 1)
- continue;
- return 0;
- }
- return 1;
-}
-
-struct altos_list {
- struct altos_usbdev **dev;
- int current;
- int ndev;
-};
-
-struct altos_list *
-altos_list_start(void)
-{
- int e;
- struct dirent **ents;
- char *dir;
- struct altos_usbdev *dev;
- struct altos_list *devs;
- int n;
-
- devs = calloc(1, sizeof (struct altos_list));
- if (!devs)
- return NULL;
-
- n = scandir (USB_DEVICES, &ents,
- dir_filter_dev,
- alphasort);
- if (!n)
- return 0;
- for (e = 0; e < n; e++) {
- dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
- dev = usb_scan_device(dir);
- if (!dev)
- continue;
- free(dir);
- if (devs->dev)
- devs->dev = realloc(devs->dev,
- (devs->ndev + 1) * sizeof (struct usbdev *));
- else
- devs->dev = malloc (sizeof (struct usbdev *));
- devs->dev[devs->ndev++] = dev;
- }
- free(ents);
- devs->current = 0;
- return devs;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- return altos_list_start();
-}
-
-int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- struct altos_usbdev *dev;
- if (list->current >= list->ndev) {
- return 0;
- }
- dev = list->dev[list->current];
- strcpy(device->name, dev->product_name);
- device->vendor = dev->idVendor;
- device->product = dev->idProduct;
- strcpy(device->path, dev->tty);
- device->serial = dev->serial;
- list->current++;
- return 1;
-}
-
-void
-altos_list_finish(struct altos_list *usbdevs)
-{
- int i;
-
- if (!usbdevs)
- return;
- for (i = 0; i < usbdevs->ndev; i++)
- usbdev_free(usbdevs->dev[i]);
- free(usbdevs);
-}
-
-#include <dlfcn.h>
-
-static void *libbt;
-static int bt_initialized;
-
-static int init_bt(void) {
- if (!bt_initialized) {
- bt_initialized = 1;
- libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
- if (!libbt)
- printf("failed to find bluetooth library\n");
- }
- return libbt != NULL;
-}
-
-#define join(a,b) a ## b
-#define bt_func(name, ret, fail, formals, actuals) \
- static ret join(altos_, name) formals { \
- static ret (*name) formals; \
- if (!init_bt()) return fail; \
- name = dlsym(libbt, #name); \
- if (!name) return fail; \
- return name actuals; \
- }
-
-bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
-#define ba2str altos_ba2str
-
-bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
-#define str2ba altos_str2ba
-
-bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
-#define hci_read_remote_name altos_hci_read_remote_name
-
-bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
-#define hci_open_dev altos_hci_open_dev
-
-bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
-#define hci_get_route altos_hci_get_route
-
-bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
-#define hci_inquiry altos_hci_inquiry
-
-struct altos_bt_list {
- inquiry_info *ii;
- int sock;
- int dev_id;
- int rsp;
- int num_rsp;
-};
-
-#define INQUIRY_MAX_RSP 255
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
- struct altos_bt_list *bt_list;
-
- bt_list = calloc(1, sizeof (struct altos_bt_list));
- if (!bt_list)
- goto no_bt_list;
-
- bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
- if (!bt_list->ii)
- goto no_ii;
- bt_list->dev_id = hci_get_route(NULL);
- if (bt_list->dev_id < 0)
- goto no_dev_id;
-
- bt_list->sock = hci_open_dev(bt_list->dev_id);
- if (bt_list->sock < 0)
- goto no_sock;
-
- bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
- inquiry_time,
- INQUIRY_MAX_RSP,
- NULL,
- &bt_list->ii,
- IREQ_CACHE_FLUSH);
- if (bt_list->num_rsp < 0)
- goto no_rsp;
-
- bt_list->rsp = 0;
- return bt_list;
-
-no_rsp:
- close(bt_list->sock);
-no_sock:
-no_dev_id:
- free(bt_list->ii);
-no_ii:
- free(bt_list);
-no_bt_list:
- return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
- struct altos_bt_device *device)
-{
- inquiry_info *ii;
-
- if (bt_list->rsp >= bt_list->num_rsp)
- return 0;
-
- ii = &bt_list->ii[bt_list->rsp];
- if (ba2str(&ii->bdaddr, device->addr) < 0)
- return 0;
- memset(&device->name, '\0', sizeof (device->name));
- if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
- sizeof (device->name),
- device->name, 0) < 0) {
- strcpy(device->name, "[unknown]");
- }
- bt_list->rsp++;
- return 1;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
- close(bt_list->sock);
- free(bt_list->ii);
- free(bt_list);
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
- strncpy(device->name, name, sizeof (device->name));
- device->name[sizeof(device->name)-1] = '\0';
- strncpy(device->addr, addr, sizeof (device->addr));
- device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
- struct sockaddr_rc addr = { 0 };
- int status, i;
- struct altos_file *file;
-
- file = calloc(1, sizeof (struct altos_file));
- if (!file) {
- errno = ENOMEM;
- altos_set_last_posix_error();
- goto no_file;
- }
- addr.rc_family = AF_BLUETOOTH;
- addr.rc_channel = 1;
- if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
- altos_set_last_posix_error();
- goto no_sock;
- }
-
- for (i = 0; i < 5; i++) {
- file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
- if (file->fd < 0) {
- altos_set_last_posix_error();
- goto no_sock;
- }
-
- status = connect(file->fd,
- (struct sockaddr *)&addr,
- sizeof(addr));
- if (status >= 0 || errno != EBUSY)
- break;
- close(file->fd);
- usleep(100 * 1000);
- }
- if (status < 0) {
- altos_set_last_posix_error();
- goto no_link;
- }
- usleep(100 * 1000);
-
-#ifdef USE_POLL
- pipe(file->pipe);
-#else
- file->out_fd = dup(file->fd);
-#endif
- return file;
-no_link:
- close(file->fd);
-no_sock:
- free(file);
-no_file:
- return NULL;
-}
-
-#endif
-
-#ifdef DARWIN
-
-#include <IOKitLib.h>
-#include <IOKit/usb/USBspec.h>
-#include <sys/param.h>
-#include <paths.h>
-#include <CFNumber.h>
-#include <IOBSD.h>
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-struct altos_list {
- io_iterator_t iterator;
- int ftdi;
-};
-
-static int
-get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
-{
- CFTypeRef entry_as_string;
- Boolean got_string;
-
- entry_as_string = IORegistryEntrySearchCFProperty (object,
- kIOServicePlane,
- entry,
- kCFAllocatorDefault,
- kIORegistryIterateRecursively);
- if (entry_as_string) {
- got_string = CFStringGetCString(entry_as_string,
- result, result_len,
- kCFStringEncodingASCII);
-
- CFRelease(entry_as_string);
- if (got_string)
- return 1;
- }
- return 0;
-}
-
-static int
-get_number(io_object_t object, CFStringRef entry, int *result)
-{
- CFTypeRef entry_as_number;
- Boolean got_number;
-
- entry_as_number = IORegistryEntrySearchCFProperty (object,
- kIOServicePlane,
- entry,
- kCFAllocatorDefault,
- kIORegistryIterateRecursively);
- if (entry_as_number) {
- got_number = CFNumberGetValue(entry_as_number,
- kCFNumberIntType,
- result);
- if (got_number)
- return 1;
- }
- return 0;
-}
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
- struct altos_list *list = calloc (sizeof (struct altos_list), 1);
- CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
- io_iterator_t tdIterator;
- io_object_t tdObject;
- kern_return_t ret;
- int i;
-
- ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
- if (ret != kIOReturnSuccess) {
- free(list);
- return NULL;
- }
- list->ftdi = 0;
- return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- struct altos_list *list = altos_list_start();
-
- if (list)
- list->ftdi = 1;
- return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- io_object_t object;
- char serial_string[128];
-
- for (;;) {
- object = IOIteratorNext(list->iterator);
- if (!object)
- return 0;
-
- if (!get_number (object, CFSTR(kUSBVendorID), &device->vendor) ||
- !get_number (object, CFSTR(kUSBProductID), &device->product))
- continue;
- if (get_string (object, CFSTR("IOCalloutDevice"), device->path, sizeof (device->path)) &&
- get_string (object, CFSTR("USB Product Name"), device->name, sizeof (device->name)) &&
- get_string (object, CFSTR("USB Serial Number"), serial_string, sizeof (serial_string))) {
- device->serial = atoi(serial_string);
- return 1;
- }
- }
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
- IOObjectRelease (list->iterator);
- free(list);
-}
-
-struct altos_bt_list {
- int sock;
- int dev_id;
- int rsp;
- int num_rsp;
-};
-
-#define INQUIRY_MAX_RSP 255
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
- return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
- struct altos_bt_device *device)
-{
- return 0;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
- strncpy(device->name, name, sizeof (device->name));
- device->name[sizeof(device->name)-1] = '\0';
- strncpy(device->addr, addr, sizeof (device->addr));
- device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
- return NULL;
-}
-
-#endif
-
-
-#ifdef WINDOWS
-
-#include <stdlib.h>
-#include <windows.h>
-#include <setupapi.h>
-
-struct altos_list {
- HDEVINFO dev_info;
- int index;
- int ftdi;
-};
-
-#define USB_BUF_SIZE 64
-
-struct altos_file {
- HANDLE handle;
- unsigned char out_data[USB_BUF_SIZE];
- int out_used;
- unsigned char in_data[USB_BUF_SIZE];
- int in_used;
- int in_read;
- OVERLAPPED ov_read;
- BOOL pend_read;
- OVERLAPPED ov_write;
-};
-
-#include <stdarg.h>
-
-static void
-log_message(char *fmt, ...)
-{
- static FILE *log = NULL;
- va_list a;
-
- if (!log)
- log = fopen("\\temp\\altos.txt", "w");
- if (log) {
- SYSTEMTIME time;
- GetLocalTime(&time);
- fprintf (log, "%4d-%02d-%02d %2d:%02d:%02d. ",
- time.wYear, time.wMonth, time.wDay,
- time.wHour, time.wMinute, time.wSecond);
- va_start(a, fmt);
- vfprintf(log, fmt, a);
- va_end(a);
- fflush(log);
- }
-}
-
-static void
-_altos_set_last_windows_error(char *file, int line)
-{
- DWORD error = GetLastError();
- TCHAR message[1024];
- FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
- 0,
- error,
- 0,
- message,
- sizeof (message) / sizeof (TCHAR),
- NULL);
- if (error != ERROR_SUCCESS)
- log_message ("%s:%d %s\n", file, line, message);
- altos_set_last_error(error, message);
-}
-
-#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__)
-
-PUBLIC struct altos_list *
-altos_list_start(void)
-{
- struct altos_list *list = calloc(1, sizeof (struct altos_list));
-
- if (!list)
- return NULL;
- list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
- DIGCF_ALLCLASSES|DIGCF_PRESENT);
- if (list->dev_info == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- free(list);
- return NULL;
- }
- list->index = 0;
- list->ftdi = 0;
- return list;
-}
-
-PUBLIC struct altos_list *
-altos_ftdi_list_start(void)
-{
- struct altos_list *list = calloc(1, sizeof (struct altos_list));
-
- if (!list)
- return NULL;
- list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
- DIGCF_ALLCLASSES|DIGCF_PRESENT);
- if (list->dev_info == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- free(list);
- return NULL;
- }
- list->index = 0;
- list->ftdi = 1;
- return list;
-}
-
-PUBLIC int
-altos_list_next(struct altos_list *list, struct altos_device *device)
-{
- SP_DEVINFO_DATA dev_info_data;
- BYTE port[128];
- DWORD port_len;
- char friendlyname[256];
- BYTE symbolic[256];
- DWORD symbolic_len;
- HKEY dev_key;
- unsigned int vid, pid;
- int serial;
- HRESULT result;
- DWORD friendlyname_type;
- DWORD friendlyname_len;
- char instanceid[1024];
- DWORD instanceid_len;
-
- dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
- while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
- &dev_info_data))
- {
- list->index++;
-
- dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
- DICS_FLAG_GLOBAL, 0, DIREG_DEV,
- KEY_READ);
- if (dev_key == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- continue;
- }
-
- if (list->ftdi) {
- vid = 0x0403;
- pid = 0x6015;
- serial = 0;
- } else {
- vid = pid = serial = 0;
- /* Fetch symbolic name for this device and parse out
- * the vid/pid/serial info */
- symbolic_len = sizeof(symbolic);
- result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
- symbolic, &symbolic_len);
- if (result != 0) {
- altos_set_last_windows_error();
- } else {
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
- "%04X", &vid);
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
- "%04X", &pid);
- sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
- "%d", &serial);
- }
- if (vid == 0 || pid == 0 || serial == 0) {
- if (SetupDiGetDeviceInstanceId(list->dev_info,
- &dev_info_data,
- instanceid,
- sizeof (instanceid),
- &instanceid_len)) {
- sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
- "%04X", &vid);
- sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
- "%04X", &pid);
- sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
- "%d", &serial);
- } else {
- altos_set_last_windows_error();
- }
- }
- if (vid == 0 || pid == 0 || serial == 0) {
- RegCloseKey(dev_key);
- continue;
- }
- }
-
- /* Fetch the com port name */
- port_len = sizeof (port);
- result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
- port, &port_len);
- RegCloseKey(dev_key);
- if (result != 0) {
- altos_set_last_windows_error();
- continue;
- }
-
- /* Fetch the device description which is the device name,
- * with firmware that has unique USB ids */
- friendlyname_len = sizeof (friendlyname);
- if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
- &dev_info_data,
- SPDRP_FRIENDLYNAME,
- &friendlyname_type,
- (BYTE *)friendlyname,
- sizeof(friendlyname),
- &friendlyname_len))
- {
- altos_set_last_windows_error();
- continue;
- }
- device->vendor = vid;
- device->product = pid;
- device->serial = serial;
- strcpy(device->name, friendlyname);
-
- strcpy(device->path, (char *) port);
- return 1;
- }
- result = GetLastError();
- if (result != ERROR_NO_MORE_ITEMS)
- altos_set_last_windows_error();
- return 0;
-}
-
-PUBLIC void
-altos_list_finish(struct altos_list *list)
-{
- SetupDiDestroyDeviceInfoList(list->dev_info);
- free(list);
-}
-
-static int
-altos_queue_read(struct altos_file *file)
-{
- DWORD got;
- if (file->pend_read)
- return LIBALTOS_SUCCESS;
-
- if (!ReadFile(file->handle, file->in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
- if (GetLastError() != ERROR_IO_PENDING) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- file->pend_read = TRUE;
- } else {
- file->pend_read = FALSE;
- file->in_read = 0;
- file->in_used = got;
- }
- return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_wait_read(struct altos_file *file, int timeout)
-{
- DWORD ret;
- DWORD got;
-
- if (!file->pend_read)
- return LIBALTOS_SUCCESS;
-
- if (!timeout)
- timeout = INFINITE;
-
- ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
- switch (ret) {
- case WAIT_OBJECT_0:
- if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- file->pend_read = FALSE;
- file->in_read = 0;
- file->in_used = got;
- break;
- case WAIT_TIMEOUT:
- return LIBALTOS_TIMEOUT;
- break;
- default:
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- return LIBALTOS_SUCCESS;
-}
-
-static int
-altos_fill(struct altos_file *file, int timeout)
-{
- int ret;
-
- if (file->in_read < file->in_used)
- return LIBALTOS_SUCCESS;
-
- file->in_read = file->in_used = 0;
-
- ret = altos_queue_read(file);
- if (ret)
- return ret;
- ret = altos_wait_read(file, timeout);
- if (ret)
- return ret;
-
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_flush(struct altos_file *file)
-{
- DWORD put;
- unsigned char *data = file->out_data;
- int used = file->out_used;
- DWORD ret;
-
- while (used) {
- if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
- if (GetLastError() != ERROR_IO_PENDING) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
- switch (ret) {
- case WAIT_OBJECT_0:
- if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- break;
- default:
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- }
- data += put;
- used -= put;
- }
- file->out_used = 0;
- return LIBALTOS_SUCCESS;
-}
-
-static HANDLE
-open_serial(char *full_name)
-{
- HANDLE handle;
- DCB dcb;
-
- handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
- 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, NULL);
-
- if (handle == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- return INVALID_HANDLE_VALUE;
- }
-
- if (!GetCommState(handle, &dcb)) {
- altos_set_last_windows_error();
- CloseHandle(handle);
- return INVALID_HANDLE_VALUE;
- }
- dcb.BaudRate = CBR_9600;
- dcb.fBinary = TRUE;
- dcb.fParity = FALSE;
- dcb.fOutxCtsFlow = FALSE;
- dcb.fOutxDsrFlow = FALSE;
- dcb.fDtrControl = DTR_CONTROL_ENABLE;
- dcb.fDsrSensitivity = FALSE;
- dcb.fTXContinueOnXoff = FALSE;
- dcb.fOutX = FALSE;
- dcb.fInX = FALSE;
- dcb.fErrorChar = FALSE;
- dcb.fNull = FALSE;
- dcb.fRtsControl = RTS_CONTROL_ENABLE;
- dcb.fAbortOnError = FALSE;
- dcb.XonLim = 10;
- dcb.XoffLim = 10;
- dcb.ByteSize = 8;
- dcb.Parity = NOPARITY;
- dcb.StopBits = ONESTOPBIT;
- dcb.XonChar = 17;
- dcb.XoffChar = 19;
-#if 0
- dcb.ErrorChar = 0;
- dcb.EofChar = 0;
- dcb.EvtChar = 0;
-#endif
- if (!SetCommState(handle, &dcb)) {
- altos_set_last_windows_error();
- CloseHandle(handle);
- return INVALID_HANDLE_VALUE;
- }
- return handle;
-}
-
-PUBLIC struct altos_file *
-altos_open(struct altos_device *device)
-{
- struct altos_file *file = calloc (1, sizeof (struct altos_file));
- char full_name[64];
- COMMTIMEOUTS timeouts;
- int i;
-
- if (!file)
- return NULL;
-
- strcpy(full_name, "\\\\.\\");
- strcat(full_name, device->path);
-
- file->handle = INVALID_HANDLE_VALUE;
-
- for (i = 0; i < 5; i++) {
- file->handle = open_serial(full_name);
- if (file->handle != INVALID_HANDLE_VALUE)
- break;
- altos_set_last_windows_error();
- Sleep(100);
- }
-
- if (file->handle == INVALID_HANDLE_VALUE) {
- free(file);
- return NULL;
- }
-
- /* The FTDI driver doesn't appear to work right unless you open it twice */
- if (device->vendor == 0x0403) {
- CloseHandle(file->handle);
- file->handle = open_serial(full_name);
- if (file->handle == INVALID_HANDLE_VALUE) {
- free(file);
- return NULL;
- }
- }
-
- timeouts.ReadIntervalTimeout = MAXDWORD;
- timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
- timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
- timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 0;
- SetCommTimeouts(file->handle, &timeouts);
-
- file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- return file;
-}
-
-PUBLIC void
-altos_close(struct altos_file *file)
-{
- HANDLE handle = file->handle;
- if (handle != INVALID_HANDLE_VALUE) {
- HANDLE ov_read = file->ov_read.hEvent;
- HANDLE ov_write = file->ov_write.hEvent;
- file->handle = INVALID_HANDLE_VALUE;
- file->ov_read.hEvent = INVALID_HANDLE_VALUE;
- file->ov_write.hEvent = INVALID_HANDLE_VALUE;
- PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
- Sleep(100);
- CloseHandle(handle);
- file->handle = INVALID_HANDLE_VALUE;
- CloseHandle(ov_read);
- CloseHandle(ov_write);
- }
-}
-
-PUBLIC void
-altos_free(struct altos_file *file)
-{
- altos_close(file);
- free(file);
-}
-
-PUBLIC int
-altos_putchar(struct altos_file *file, char c)
-{
- int ret;
-
- if (file->out_used == USB_BUF_SIZE) {
- ret = altos_flush(file);
- if (ret)
- return ret;
- }
- file->out_data[file->out_used++] = c;
- if (file->out_used == USB_BUF_SIZE)
- return altos_flush(file);
- return LIBALTOS_SUCCESS;
-}
-
-PUBLIC int
-altos_getchar(struct altos_file *file, int timeout)
-{
- int ret;
- while (file->in_read == file->in_used) {
- if (file->handle == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- return LIBALTOS_ERROR;
- }
- ret = altos_fill(file, timeout);
- if (ret)
- return ret;
- }
- return file->in_data[file->in_read++];
-}
-
-struct altos_bt_list *
-altos_bt_list_start(int inquiry_time)
-{
- return NULL;
-}
-
-int
-altos_bt_list_next(struct altos_bt_list *bt_list,
- struct altos_bt_device *device)
-{
- return 0;
-}
-
-void
-altos_bt_list_finish(struct altos_bt_list *bt_list)
-{
- free(bt_list);
-}
-
-void
-altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
-{
- strncpy(device->name, name, sizeof (device->name));
- device->name[sizeof(device->name)-1] = '\0';
- strncpy(device->addr, addr, sizeof (device->addr));
- device->addr[sizeof(device->addr)-1] = '\0';
-}
-
-struct altos_file *
-altos_bt_open(struct altos_bt_device *device)
-{
- return NULL;
-}
-
-#endif
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+
+PUBLIC int
+altos_init(void)
+{
+ return LIBALTOS_SUCCESS;
+}
+
+PUBLIC void
+altos_fini(void)
+{
+}
+
+struct altos_error altos_last_error;
+
+void
+altos_set_last_error(int code, char *string)
+{
+ altos_last_error.code = code;
+ strncpy(altos_last_error.string, string, sizeof (altos_last_error.string) -1);
+ altos_last_error.string[sizeof(altos_last_error.string)-1] = '\0';
+}
+
+PUBLIC void
+altos_get_last_error(struct altos_error *error)
+{
+ *error = altos_last_error;
+}
+
+PUBLIC int
+altos_getchar(struct altos_file *file, int timeout)
+{
+ int ret;
+ while (file->in_read == file->in_used) {
+ ret = altos_fill(file, timeout);
+ if (ret)
+ return ret;
+ }
+ return file->in_data[file->in_read++];
+}
+
+PUBLIC int
+altos_putchar(struct altos_file *file, char c)
+{
+ int ret;
+
+ if (file->out_used == USB_BUF_SIZE) {
+ ret = altos_flush(file);
+ if (ret) {
+ return ret;
+ }
+ }
+ file->out_data[file->out_used++] = c;
+ ret = 0;
+ if (file->out_used == USB_BUF_SIZE)
+ ret = altos_flush(file);
+ return ret;
+}
+
+
+PUBLIC void
+altos_free(struct altos_file *file)
+{
+ altos_close(file);
+ free(file);
+}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <IOKitLib.h>
+#include <IOKit/usb/USBspec.h>
+#include <IOKit/serial/IOSerialKeys.h>
+#include <usb/IOUSBLib.h>
+#include <usb/USBSpec.h>
+#include <sys/param.h>
+#include <paths.h>
+#include <CFNumber.h>
+#include <IOBSD.h>
+
+/* Mac OS X don't have strndup even if _GNU_SOURCE is defined */
+char *
+altos_strndup (const char *s, size_t n)
+{
+ size_t len = strlen (s);
+ char *ret;
+
+ if (len <= n)
+ return strdup (s);
+ ret = malloc(n + 1);
+ strncpy(ret, s, n);
+ ret[n] = '\0';
+ return ret;
+}
+
+struct altos_list {
+ io_iterator_t iterator;
+ int ftdi;
+};
+
+static char *
+get_cfstring(CFTypeRef string, char result[512])
+{
+ Boolean got_string;
+
+ got_string = CFStringGetCString(string, result, 512, kCFStringEncodingASCII);
+ if (!got_string)
+ strcpy(result, "CFStringGetCString failed");
+ return result;
+}
+
+static int
+get_string(io_object_t object, CFStringRef entry, char *result, int result_len)
+{
+ CFTypeRef entry_as_string;
+ Boolean got_string;
+ char entry_string[512];
+
+ entry_as_string = IORegistryEntrySearchCFProperty (object,
+ kIOServicePlane,
+ entry,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively);
+ if (entry_as_string) {
+ got_string = CFStringGetCString(entry_as_string,
+ result, result_len,
+ kCFStringEncodingASCII);
+
+ CFRelease(entry_as_string);
+ if (got_string) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+get_number(io_object_t object, CFStringRef entry, int *result)
+{
+ CFTypeRef entry_as_number;
+ Boolean got_number;
+ char entry_string[512];
+
+ entry_as_number = IORegistryEntrySearchCFProperty (object,
+ kIOServicePlane,
+ entry,
+ kCFAllocatorDefault,
+ kIORegistryIterateRecursively);
+ if (entry_as_number) {
+ got_number = CFNumberGetValue(entry_as_number,
+ kCFNumberIntType,
+ result);
+ if (got_number) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+ struct altos_list *list = calloc (sizeof (struct altos_list), 1);
+ CFMutableDictionaryRef matching_dictionary;
+ io_iterator_t tdIterator;
+ io_object_t tdObject;
+ kern_return_t ret;
+ int i;
+
+ matching_dictionary = IOServiceMatching(kIOSerialBSDServiceValue);
+ if (matching_dictionary) {
+ CFDictionarySetValue(matching_dictionary,
+ CFSTR(kIOSerialBSDTypeKey),
+ CFSTR(kIOSerialBSDAllTypes));
+ }
+
+ ret = IOServiceGetMatchingServices(kIOMasterPortDefault, matching_dictionary, &list->iterator);
+ if (ret != kIOReturnSuccess) {
+ free(list);
+ return NULL;
+ }
+ list->ftdi = 0;
+ return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ struct altos_list *list = altos_list_start();
+
+ if (list)
+ list->ftdi = 1;
+ return list;
+}
+
+static io_service_t get_usb_object(io_object_t serial_device)
+{
+ io_iterator_t iterator;
+ io_service_t usb_device;
+ io_service_t service;
+ IOReturn status;
+
+ status = IORegistryEntryCreateIterator(serial_device,
+ kIOServicePlane,
+ kIORegistryIterateParents | kIORegistryIterateRecursively,
+ &iterator);
+
+ if (status != kIOReturnSuccess)
+ return 0;
+
+ while((service = IOIteratorNext(iterator))) {
+ io_name_t servicename;
+ status = IORegistryEntryGetNameInPlane(service, kIOServicePlane, servicename);
+
+ if (status == kIOReturnSuccess && IOObjectConformsTo(service, kIOUSBDeviceClassName)) {
+ IOObjectRelease(iterator);
+ return service;
+ }
+ IOObjectRelease(service);
+ }
+ IOObjectRelease(iterator);
+ return 0;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+
+ io_object_t object;
+ io_service_t usb_device;
+ char serial_string[128];
+
+ for (;;) {
+ object = IOIteratorNext(list->iterator);
+ if (!object) {
+ return 0;
+ }
+
+ usb_device = get_usb_object(object);
+
+ if (get_number (usb_device, CFSTR(kUSBVendorID), &device->vendor) &&
+ get_number (usb_device, CFSTR(kUSBProductID), &device->product) &&
+ get_string (object, CFSTR(kIOCalloutDeviceKey), device->path, sizeof (device->path)) &&
+ get_string (usb_device, CFSTR(kUSBProductString), device->name, sizeof (device->name)) &&
+ get_string (usb_device, CFSTR(kUSBSerialNumberString), serial_string, sizeof (serial_string))) {
+ device->serial = atoi(serial_string);
+ IOObjectRelease(object);
+ IOObjectRelease(usb_device);
+ return 1;
+ }
+ IOObjectRelease(object);
+ IOObjectRelease(usb_device);
+ }
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+ IOObjectRelease (list->iterator);
+ free(list);
+}
+
+struct altos_bt_list {
+ int sock;
+ int dev_id;
+ int rsp;
+ int num_rsp;
+};
+
+#define INQUIRY_MAX_RSP 255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ return 0;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ return NULL;
+}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#define _GNU_SOURCE
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+#include <ctype.h>
+#include <dirent.h>
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#include <bluetooth/rfcomm.h>
+
+static char *
+cc_fullname (char *dir, char *file)
+{
+ char *new;
+ int dlen = strlen (dir);
+ int flen = strlen (file);
+ int slen = 0;
+
+ if (dir[dlen-1] != '/')
+ slen = 1;
+ new = malloc (dlen + slen + flen + 1);
+ if (!new)
+ return 0;
+ strcpy(new, dir);
+ if (slen)
+ strcat (new, "/");
+ strcat(new, file);
+ return new;
+}
+
+static char *
+cc_basename(char *file)
+{
+ char *b;
+
+ b = strrchr(file, '/');
+ if (!b)
+ return file;
+ return b + 1;
+}
+
+static char *
+load_string(char *dir, char *file)
+{
+ char *full = cc_fullname(dir, file);
+ char line[4096];
+ char *r;
+ FILE *f;
+ int rlen;
+
+ f = fopen(full, "r");
+ free(full);
+ if (!f)
+ return NULL;
+ r = fgets(line, sizeof (line), f);
+ fclose(f);
+ if (!r)
+ return NULL;
+ rlen = strlen(r);
+ if (r[rlen-1] == '\n')
+ r[rlen-1] = '\0';
+ return strdup(r);
+}
+
+static int
+load_hex(char *dir, char *file)
+{
+ char *line;
+ char *end;
+ long i;
+
+ line = load_string(dir, file);
+ if (!line)
+ return -1;
+ i = strtol(line, &end, 16);
+ free(line);
+ if (end == line)
+ return -1;
+ return i;
+}
+
+static int
+load_dec(char *dir, char *file)
+{
+ char *line;
+ char *end;
+ long i;
+
+ line = load_string(dir, file);
+ if (!line)
+ return -1;
+ i = strtol(line, &end, 10);
+ free(line);
+ if (end == line)
+ return -1;
+ return i;
+}
+
+static int
+dir_filter_tty_colon(const struct dirent *d)
+{
+ return strncmp(d->d_name, "tty:", 4) == 0;
+}
+
+static int
+dir_filter_tty(const struct dirent *d)
+{
+ return strncmp(d->d_name, "tty", 3) == 0;
+}
+
+struct altos_usbdev {
+ char *sys;
+ char *tty;
+ char *manufacturer;
+ char *product_name;
+ int serial; /* AltOS always uses simple integer serial numbers */
+ int idProduct;
+ int idVendor;
+};
+
+static char *
+usb_tty(char *sys)
+{
+ char *base;
+ int num_configs;
+ int config;
+ struct dirent **namelist;
+ int interface;
+ int num_interfaces;
+ char endpoint_base[20];
+ char *endpoint_full;
+ char *tty_dir;
+ int ntty;
+ char *tty;
+
+ base = cc_basename(sys);
+ num_configs = load_hex(sys, "bNumConfigurations");
+ num_interfaces = load_hex(sys, "bNumInterfaces");
+ for (config = 1; config <= num_configs; config++) {
+ for (interface = 0; interface < num_interfaces; interface++) {
+ sprintf(endpoint_base, "%s:%d.%d",
+ base, config, interface);
+ endpoint_full = cc_fullname(sys, endpoint_base);
+
+
+ /* Check for tty:ttyACMx style names
+ */
+ ntty = scandir(endpoint_full, &namelist,
+ dir_filter_tty_colon,
+ alphasort);
+ if (ntty > 0) {
+ free(endpoint_full);
+ tty = cc_fullname("/dev", namelist[0]->d_name + 4);
+ free(namelist);
+ return tty;
+ }
+
+ /* Check for tty/ttyACMx style names
+ */
+ tty_dir = cc_fullname(endpoint_full, "tty");
+ ntty = scandir(tty_dir, &namelist,
+ dir_filter_tty,
+ alphasort);
+ free (tty_dir);
+ if (ntty > 0) {
+ tty = cc_fullname("/dev", namelist[0]->d_name);
+ free(endpoint_full);
+ free(namelist);
+ return tty;
+ }
+
+ /* Check for ttyACMx style names
+ */
+ ntty = scandir(endpoint_full, &namelist,
+ dir_filter_tty,
+ alphasort);
+ free(endpoint_full);
+ if (ntty > 0) {
+ tty = cc_fullname("/dev", namelist[0]->d_name);
+ free(namelist);
+ return tty;
+ }
+
+ }
+ }
+ return NULL;
+}
+
+static struct altos_usbdev *
+usb_scan_device(char *sys)
+{
+ struct altos_usbdev *usbdev;
+ char *tty;
+
+ tty = usb_tty(sys);
+ if (!tty)
+ return NULL;
+ usbdev = calloc(1, sizeof (struct altos_usbdev));
+ if (!usbdev)
+ return NULL;
+ usbdev->sys = strdup(sys);
+ usbdev->manufacturer = load_string(sys, "manufacturer");
+ usbdev->product_name = load_string(sys, "product");
+ usbdev->serial = load_dec(sys, "serial");
+ usbdev->idProduct = load_hex(sys, "idProduct");
+ usbdev->idVendor = load_hex(sys, "idVendor");
+ usbdev->tty = tty;
+ return usbdev;
+}
+
+static void
+usbdev_free(struct altos_usbdev *usbdev)
+{
+ free(usbdev->sys);
+ free(usbdev->manufacturer);
+ free(usbdev->product_name);
+ /* this can get used as a return value */
+ if (usbdev->tty)
+ free(usbdev->tty);
+ free(usbdev);
+}
+
+#define USB_DEVICES "/sys/bus/usb/devices"
+
+static int
+dir_filter_dev(const struct dirent *d)
+{
+ const char *n = d->d_name;
+ char c;
+
+ while ((c = *n++)) {
+ if (isdigit(c))
+ continue;
+ if (c == '-')
+ continue;
+ if (c == '.' && n != d->d_name + 1)
+ continue;
+ return 0;
+ }
+ return 1;
+}
+
+struct altos_list {
+ struct altos_usbdev **dev;
+ int current;
+ int ndev;
+};
+
+struct altos_list *
+altos_list_start(void)
+{
+ int e;
+ struct dirent **ents;
+ char *dir;
+ struct altos_usbdev *dev;
+ struct altos_list *devs;
+ int n;
+
+ devs = calloc(1, sizeof (struct altos_list));
+ if (!devs)
+ return NULL;
+
+ n = scandir (USB_DEVICES, &ents,
+ dir_filter_dev,
+ alphasort);
+ if (!n)
+ return 0;
+ for (e = 0; e < n; e++) {
+ dir = cc_fullname(USB_DEVICES, ents[e]->d_name);
+ dev = usb_scan_device(dir);
+ if (!dev)
+ continue;
+ free(dir);
+ if (devs->dev)
+ devs->dev = realloc(devs->dev,
+ (devs->ndev + 1) * sizeof (struct usbdev *));
+ else
+ devs->dev = malloc (sizeof (struct usbdev *));
+ devs->dev[devs->ndev++] = dev;
+ }
+ free(ents);
+ devs->current = 0;
+ return devs;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ return altos_list_start();
+}
+
+int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+ struct altos_usbdev *dev;
+ if (list->current >= list->ndev) {
+ return 0;
+ }
+ dev = list->dev[list->current];
+ strcpy(device->name, dev->product_name);
+ device->vendor = dev->idVendor;
+ device->product = dev->idProduct;
+ strcpy(device->path, dev->tty);
+ device->serial = dev->serial;
+ list->current++;
+ return 1;
+}
+
+void
+altos_list_finish(struct altos_list *usbdevs)
+{
+ int i;
+
+ if (!usbdevs)
+ return;
+ for (i = 0; i < usbdevs->ndev; i++)
+ usbdev_free(usbdevs->dev[i]);
+ free(usbdevs);
+}
+
+#include <dlfcn.h>
+
+static void *libbt;
+static int bt_initialized;
+
+static int init_bt(void) {
+ if (!bt_initialized) {
+ bt_initialized = 1;
+ libbt = dlopen("libbluetooth.so.3", RTLD_LAZY);
+ if (!libbt)
+ printf("failed to find bluetooth library\n");
+ }
+ return libbt != NULL;
+}
+
+#define join(a,b) a ## b
+#define bt_func(name, ret, fail, formals, actuals) \
+ static ret join(altos_, name) formals { \
+ static ret (*name) formals; \
+ if (!init_bt()) return fail; \
+ name = dlsym(libbt, #name); \
+ if (!name) return fail; \
+ return name actuals; \
+ }
+
+bt_func(ba2str, int, -1, (const bdaddr_t *ba, char *str), (ba, str))
+#define ba2str altos_ba2str
+
+bt_func(str2ba, int, -1, (const char *str, bdaddr_t *ba), (str, ba))
+#define str2ba altos_str2ba
+
+bt_func(hci_read_remote_name, int, -1, (int sock, const bdaddr_t *ba, int len, char *name, int timeout), (sock, ba, len, name, timeout))
+#define hci_read_remote_name altos_hci_read_remote_name
+
+bt_func(hci_open_dev, int, -1, (int dev_id), (dev_id))
+#define hci_open_dev altos_hci_open_dev
+
+bt_func(hci_get_route, int, -1, (bdaddr_t *bdaddr), (bdaddr))
+#define hci_get_route altos_hci_get_route
+
+bt_func(hci_inquiry, int, -1, (int adapter_id, int len, int max_rsp, const uint8_t *lap, inquiry_info **devs, long flags), (adapter_id, len, max_rsp, lap, devs, flags))
+#define hci_inquiry altos_hci_inquiry
+
+struct altos_bt_list {
+ inquiry_info *ii;
+ int sock;
+ int dev_id;
+ int rsp;
+ int num_rsp;
+};
+
+#define INQUIRY_MAX_RSP 255
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ struct altos_bt_list *bt_list;
+
+ bt_list = calloc(1, sizeof (struct altos_bt_list));
+ if (!bt_list)
+ goto no_bt_list;
+
+ bt_list->ii = calloc(INQUIRY_MAX_RSP, sizeof (inquiry_info));
+ if (!bt_list->ii)
+ goto no_ii;
+ bt_list->dev_id = hci_get_route(NULL);
+ if (bt_list->dev_id < 0)
+ goto no_dev_id;
+
+ bt_list->sock = hci_open_dev(bt_list->dev_id);
+ if (bt_list->sock < 0)
+ goto no_sock;
+
+ bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
+ inquiry_time,
+ INQUIRY_MAX_RSP,
+ NULL,
+ &bt_list->ii,
+ IREQ_CACHE_FLUSH);
+ if (bt_list->num_rsp < 0)
+ goto no_rsp;
+
+ bt_list->rsp = 0;
+ return bt_list;
+
+no_rsp:
+ close(bt_list->sock);
+no_sock:
+no_dev_id:
+ free(bt_list->ii);
+no_ii:
+ free(bt_list);
+no_bt_list:
+ return NULL;
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ inquiry_info *ii;
+
+ if (bt_list->rsp >= bt_list->num_rsp)
+ return 0;
+
+ ii = &bt_list->ii[bt_list->rsp];
+ if (ba2str(&ii->bdaddr, device->addr) < 0)
+ return 0;
+ memset(&device->name, '\0', sizeof (device->name));
+ if (hci_read_remote_name(bt_list->sock, &ii->bdaddr,
+ sizeof (device->name),
+ device->name, 0) < 0) {
+ strcpy(device->name, "[unknown]");
+ }
+ bt_list->rsp++;
+ return 1;
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ close(bt_list->sock);
+ free(bt_list->ii);
+ free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ struct sockaddr_rc addr = { 0 };
+ int status, i;
+ struct altos_file_posix *file;
+
+ file = calloc(1, sizeof (struct altos_file_posix));
+ if (!file) {
+ errno = ENOMEM;
+ altos_set_last_posix_error();
+ goto no_file;
+ }
+ addr.rc_family = AF_BLUETOOTH;
+ addr.rc_channel = 1;
+ if (str2ba(device->addr, &addr.rc_bdaddr) < 0) {
+ altos_set_last_posix_error();
+ goto no_sock;
+ }
+
+ for (i = 0; i < 5; i++) {
+ file->fd = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
+ if (file->fd < 0) {
+ altos_set_last_posix_error();
+ goto no_sock;
+ }
+
+ status = connect(file->fd,
+ (struct sockaddr *)&addr,
+ sizeof(addr));
+ if (status >= 0 || errno != EBUSY)
+ break;
+ close(file->fd);
+ usleep(100 * 1000);
+ }
+ if (status < 0) {
+ altos_set_last_posix_error();
+ goto no_link;
+ }
+ usleep(100 * 1000);
+
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = dup(file->fd);
+#endif
+ return &file->file;
+no_link:
+ close(file->fd);
+no_sock:
+ free(file);
+no_file:
+ return NULL;
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+#include "libaltos_posix.h"
+
+void
+altos_set_last_posix_error(void)
+{
+ altos_set_last_error(errno, strerror(errno));
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+ struct altos_file_posix *file = calloc (sizeof (struct altos_file_posix), 1);
+ int ret;
+ struct termios term;
+
+ if (!file) {
+ altos_set_last_posix_error();
+ return NULL;
+ }
+
+// altos_set_last_error(12, "yeah yeah, failed again");
+// free(file);
+// return NULL;
+
+ file->fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->fd < 0) {
+ altos_set_last_posix_error();
+ free(file);
+ return NULL;
+ }
+#ifdef USE_POLL
+ pipe(file->pipe);
+#else
+ file->out_fd = open(device->path, O_RDWR | O_NOCTTY);
+ if (file->out_fd < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+ free(file);
+ return NULL;
+ }
+#endif
+ ret = tcgetattr(file->fd, &term);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ cfmakeraw(&term);
+ cfsetospeed(&term, B9600);
+ cfsetispeed(&term, B9600);
+#ifdef USE_POLL
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+#else
+ term.c_cc[VMIN] = 0;
+ term.c_cc[VTIME] = 1;
+#endif
+ ret = tcsetattr(file->fd, TCSAFLUSH, &term);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ close(file->fd);
+#ifndef USE_POLL
+ close(file->out_fd);
+#endif
+ free(file);
+ return NULL;
+ }
+ return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ if (file->fd != -1) {
+ int fd = file->fd;
+ file->fd = -1;
+#ifdef USE_POLL
+ write(file->pipe[1], "\r", 1);
+#else
+ close(file->out_fd);
+ file->out_fd = -1;
+#endif
+ close(fd);
+ }
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ if (file->file.out_used && 0) {
+ printf ("flush \"");
+ fwrite(file->file.out_data, 1, file->file.out_used, stdout);
+ printf ("\"\n");
+ }
+ while (file->file.out_used) {
+ int ret;
+
+ if (file->fd < 0)
+ return -EBADF;
+#ifdef USE_POLL
+ ret = write (file->fd, file->file.out_data, file->file.out_used);
+#else
+ ret = write (file->out_fd, file->file.out_data, file->file.out_used);
+#endif
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return -altos_last_error.code;
+ }
+ if (ret) {
+ memmove(file->file.out_data, file->file.out_data + ret,
+ file->file.out_used - ret);
+ file->file.out_used -= ret;
+ }
+ }
+ return 0;
+}
+
+
+#ifdef USE_POLL
+#include <poll.h>
+#endif
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+ struct altos_file_posix *file = (struct altos_file_posix *) file_common;
+
+ int ret;
+#ifdef USE_POLL
+ struct pollfd fd[2];
+#endif
+ if (timeout == 0)
+ timeout = -1;
+ while (file->file.in_read == file->file.in_used) {
+ if (file->fd < 0)
+ return LIBALTOS_ERROR;
+#ifdef USE_POLL
+ fd[0].fd = file->fd;
+ fd[0].events = POLLIN|POLLERR|POLLHUP|POLLNVAL;
+ fd[1].fd = file->pipe[0];
+ fd[1].events = POLLIN;
+ ret = poll(fd, 2, timeout);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return LIBALTOS_ERROR;
+ }
+ if (ret == 0)
+ return LIBALTOS_TIMEOUT;
+
+ if (fd[0].revents & (POLLHUP|POLLERR|POLLNVAL))
+ return LIBALTOS_ERROR;
+ if (fd[0].revents & POLLIN)
+#endif
+ {
+ ret = read(file->fd, file->file.in_data, USB_BUF_SIZE);
+ if (ret < 0) {
+ altos_set_last_posix_error();
+ return LIBALTOS_ERROR;
+ }
+ file->file.in_read = 0;
+ file->file.in_used = ret;
+#ifndef USE_POLL
+ if (ret == 0 && timeout > 0)
+ return LIBALTOS_TIMEOUT;
+#endif
+ }
+ }
+ if (file->file.in_used && 0) {
+ printf ("fill \"");
+ fwrite(file->file.in_data, 1, file->file.in_used, stdout);
+ printf ("\"\n");
+ }
+ return 0;
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _LIBALTOS_POSIX_H_
+#define _LIBALTOS_POSIX_H_
+
+#include <fcntl.h>
+#include <termios.h>
+#include <errno.h>
+#include <unistd.h>
+
+struct altos_file_posix {
+ struct altos_file file;
+
+ int fd;
+#ifdef USE_POLL
+ int pipe[2];
+#else
+ int out_fd;
+#endif
+};
+
+void
+altos_set_last_posix_error(void);
+
+#endif /* _LIBALTOS_POSIX_H_ */
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _LIBALTOS_PRIVATE_H_
+#define _LIBALTOS_PRIVATE_H_
+
+#include "libaltos.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define BLUETOOTH_PRODUCT_TELEBT "TeleBT"
+
+#define USB_BUF_SIZE 64
+
+struct altos_file {
+ /* Shared data */
+ unsigned char out_data[USB_BUF_SIZE];
+ int out_used;
+ unsigned char in_data[USB_BUF_SIZE];
+ int in_used;
+ int in_read;
+};
+
+#ifdef LINUX
+#define USE_POLL
+#endif
+
+#ifdef DARWIN
+#include <unistd.h>
+
+#define strndup(s,n) altos_strndup(s,n)
+
+char *altos_strndup(const char *s, size_t n);
+
+#endif
+
+void
+altos_set_last_error(int code, char *string);
+
+extern struct altos_error altos_last_error;
+
+PUBLIC int
+altos_flush(struct altos_file *file);
+
+int
+altos_fill(struct altos_file *file, int timeout);
+
+#endif /* _LIBALTOS_PRIVATE_H_ */
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "libaltos_private.h"
+
+#include <winsock2.h>
+#include <windows.h>
+#include <setupapi.h>
+
+struct altos_list {
+ HDEVINFO dev_info;
+ int index;
+ int ftdi;
+};
+
+#define USB_BUF_SIZE 64
+
+struct altos_file_windows {
+ struct altos_file file;
+
+ BOOL is_winsock;
+ /* Data used by the regular I/O */
+ HANDLE handle;
+ OVERLAPPED ov_read;
+ BOOL pend_read;
+ OVERLAPPED ov_write;
+
+ /* Data used by winsock */
+ SOCKET socket;
+};
+
+#include <stdarg.h>
+
+static void
+log_message(char *fmt, ...)
+{
+ static FILE *log = NULL;
+ va_list a;
+
+ if (!log)
+ log = fopen("\\temp\\altos.txt", "w");
+ if (log) {
+ SYSTEMTIME time;
+ char buffer[4096];
+
+ GetLocalTime(&time);
+ sprintf (buffer, "%4d-%02d-%02d %2d:%02d:%02d. ",
+ time.wYear, time.wMonth, time.wDay,
+ time.wHour, time.wMinute, time.wSecond);
+ va_start(a, fmt);
+
+ vsprintf(buffer + strlen(buffer), fmt, a);
+ va_end(a);
+
+ fputs(buffer, log);
+ fflush(log);
+ fputs(buffer, stdout);
+ fflush(stdout);
+ }
+}
+
+static void
+_altos_set_last_windows_error(char *file, int line, DWORD error)
+{
+ TCHAR message[1024];
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+ 0,
+ error,
+ 0,
+ message,
+ sizeof (message) / sizeof (TCHAR),
+ NULL);
+ if (error != ERROR_SUCCESS)
+ log_message ("%s:%d (%d) %s\n", file, line, error, message);
+ altos_set_last_error(error, message);
+}
+
+#define altos_set_last_windows_error() _altos_set_last_windows_error(__FILE__, __LINE__, GetLastError())
+#define altos_set_last_winsock_error() _altos_set_last_windows_error(__FILE__, __LINE__, WSAGetLastError())
+
+PUBLIC struct altos_list *
+altos_list_start(void)
+{
+ struct altos_list *list = calloc(1, sizeof (struct altos_list));
+
+ if (!list)
+ return NULL;
+ list->dev_info = SetupDiGetClassDevs(NULL, "USB", NULL,
+ DIGCF_ALLCLASSES|DIGCF_PRESENT);
+ if (list->dev_info == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ free(list);
+ return NULL;
+ }
+ list->index = 0;
+ list->ftdi = 0;
+ return list;
+}
+
+PUBLIC struct altos_list *
+altos_ftdi_list_start(void)
+{
+ struct altos_list *list = calloc(1, sizeof (struct altos_list));
+
+ if (!list)
+ return NULL;
+ list->dev_info = SetupDiGetClassDevs(NULL, "FTDIBUS", NULL,
+ DIGCF_ALLCLASSES|DIGCF_PRESENT);
+ if (list->dev_info == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ free(list);
+ return NULL;
+ }
+ list->index = 0;
+ list->ftdi = 1;
+ return list;
+}
+
+PUBLIC int
+altos_list_next(struct altos_list *list, struct altos_device *device)
+{
+ SP_DEVINFO_DATA dev_info_data;
+ BYTE port[128];
+ DWORD port_len;
+ char friendlyname[256];
+ BYTE symbolic[256];
+ DWORD symbolic_len;
+ HKEY dev_key;
+ unsigned int vid, pid;
+ int serial;
+ HRESULT result;
+ DWORD friendlyname_type;
+ DWORD friendlyname_len;
+ char instanceid[1024];
+ DWORD instanceid_len;
+
+ dev_info_data.cbSize = sizeof (SP_DEVINFO_DATA);
+ while(SetupDiEnumDeviceInfo(list->dev_info, list->index,
+ &dev_info_data))
+ {
+ list->index++;
+
+ dev_key = SetupDiOpenDevRegKey(list->dev_info, &dev_info_data,
+ DICS_FLAG_GLOBAL, 0, DIREG_DEV,
+ KEY_READ);
+ if (dev_key == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ continue;
+ }
+
+ if (list->ftdi) {
+ vid = 0x0403;
+ pid = 0x6015;
+ serial = 0;
+ } else {
+ vid = pid = serial = 0;
+ /* Fetch symbolic name for this device and parse out
+ * the vid/pid/serial info */
+ symbolic_len = sizeof(symbolic);
+ result = RegQueryValueEx(dev_key, "SymbolicName", NULL, NULL,
+ symbolic, &symbolic_len);
+ if (result != 0) {
+ altos_set_last_windows_error();
+ } else {
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_") - 1,
+ "%04X", &vid);
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_") - 1,
+ "%04X", &pid);
+ sscanf((char *) symbolic + sizeof("\\??\\USB#VID_XXXX&PID_XXXX#") - 1,
+ "%d", &serial);
+ }
+ if (vid == 0 || pid == 0 || serial == 0) {
+ if (SetupDiGetDeviceInstanceId(list->dev_info,
+ &dev_info_data,
+ instanceid,
+ sizeof (instanceid),
+ &instanceid_len)) {
+ sscanf((char *) instanceid + sizeof("USB\\VID_") - 1,
+ "%04X", &vid);
+ sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_") - 1,
+ "%04X", &pid);
+ sscanf((char *) instanceid + sizeof("USB\\VID_XXXX&PID_XXXX\\") - 1,
+ "%d", &serial);
+ } else {
+ altos_set_last_windows_error();
+ }
+ }
+ if (vid == 0 || pid == 0 || serial == 0) {
+ RegCloseKey(dev_key);
+ continue;
+ }
+ }
+
+ /* Fetch the com port name */
+ port_len = sizeof (port);
+ result = RegQueryValueEx(dev_key, "PortName", NULL, NULL,
+ port, &port_len);
+ RegCloseKey(dev_key);
+ if (result != 0) {
+ altos_set_last_windows_error();
+ continue;
+ }
+
+ /* Fetch the device description which is the device name,
+ * with firmware that has unique USB ids */
+ friendlyname_len = sizeof (friendlyname);
+ if(!SetupDiGetDeviceRegistryProperty(list->dev_info,
+ &dev_info_data,
+ SPDRP_FRIENDLYNAME,
+ &friendlyname_type,
+ (BYTE *)friendlyname,
+ sizeof(friendlyname),
+ &friendlyname_len))
+ {
+ altos_set_last_windows_error();
+ continue;
+ }
+ device->vendor = vid;
+ device->product = pid;
+ device->serial = serial;
+ strcpy(device->name, friendlyname);
+
+ strcpy(device->path, (char *) port);
+ return 1;
+ }
+ result = GetLastError();
+ if (result != ERROR_NO_MORE_ITEMS)
+ altos_set_last_windows_error();
+ return 0;
+}
+
+PUBLIC void
+altos_list_finish(struct altos_list *list)
+{
+ SetupDiDestroyDeviceInfoList(list->dev_info);
+ free(list);
+}
+
+static int
+altos_queue_read(struct altos_file_windows *file)
+{
+ DWORD got;
+ if (file->pend_read)
+ return LIBALTOS_SUCCESS;
+
+ if (!ReadFile(file->handle, file->file.in_data, USB_BUF_SIZE, &got, &file->ov_read)) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ file->pend_read = TRUE;
+ } else {
+ file->pend_read = FALSE;
+ file->file.in_read = 0;
+ file->file.in_used = got;
+ }
+ return LIBALTOS_SUCCESS;
+}
+
+static int
+altos_wait_read(struct altos_file_windows *file, int timeout)
+{
+ DWORD ret;
+ DWORD got;
+
+ if (!file->pend_read)
+ return LIBALTOS_SUCCESS;
+
+ if (!timeout)
+ timeout = INFINITE;
+
+ ret = WaitForSingleObject(file->ov_read.hEvent, timeout);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_read, &got, FALSE)) {
+ if (GetLastError () != ERROR_OPERATION_ABORTED)
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ file->pend_read = FALSE;
+ file->file.in_read = 0;
+ file->file.in_used = got;
+ break;
+ case WAIT_TIMEOUT:
+ return LIBALTOS_TIMEOUT;
+ break;
+ default:
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ return LIBALTOS_SUCCESS;
+}
+
+int
+altos_fill(struct altos_file *file_common, int timeout)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ int ret;
+
+ if (file->file.in_read < file->file.in_used)
+ return LIBALTOS_SUCCESS;
+
+ file->file.in_read = file->file.in_used = 0;
+
+ if (file->is_winsock) {
+
+ for (;;) {
+ fd_set readfds;
+ TIMEVAL timeval;
+ int thistimeout;
+
+ /* Check to see if the socket has been closed */
+ if (file->socket == INVALID_SOCKET)
+ return LIBALTOS_ERROR;
+
+#define POLL_TIMEOUT 10000
+
+ /* Poll to see if the socket has been closed
+ * as select doesn't abort when that happens
+ */
+ if (timeout) {
+ thistimeout = timeout;
+ if (thistimeout > POLL_TIMEOUT)
+ thistimeout = POLL_TIMEOUT;
+ } else {
+ thistimeout = POLL_TIMEOUT;
+ }
+
+ timeval.tv_sec = thistimeout / 1000;
+ timeval.tv_usec = (thistimeout % 1000) * 1000;
+
+ FD_ZERO(&readfds);
+ FD_SET(file->socket, &readfds);
+
+ ret = select(1, &readfds, NULL, NULL, &timeval);
+
+ if (ret == 0) {
+ if (timeout) {
+ timeout -= thistimeout;
+ if (timeout == 0)
+ return LIBALTOS_TIMEOUT;
+ }
+ } else {
+ if (ret > 0)
+ break;
+
+ if (ret < 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ }
+ }
+
+ if (file->socket == INVALID_SOCKET) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+
+ ret = recv(file->socket, (char *) file->file.in_data, USB_BUF_SIZE, 0);
+
+ if (ret <= 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ file->file.in_read = 0;
+ file->file.in_used = ret;
+ } else {
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+
+ ret = altos_queue_read(file);
+ if (ret)
+ return ret;
+ ret = altos_wait_read(file, timeout);
+ if (ret)
+ return ret;
+ }
+
+ return LIBALTOS_SUCCESS;
+}
+
+PUBLIC int
+altos_flush(struct altos_file *file_common)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ unsigned char *data = file->file.out_data;
+ int used = file->file.out_used;
+
+ while (used) {
+ if (file->is_winsock) {
+ int put;
+
+ put = send(file->socket, (char *) data, used, 0);
+ if (put <= 0) {
+ altos_set_last_winsock_error();
+ return LIBALTOS_ERROR;
+ }
+ data += put;
+ used -= put;
+ } else {
+ DWORD put;
+ DWORD ret;
+ if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
+ if (GetLastError() != ERROR_IO_PENDING) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
+ switch (ret) {
+ case WAIT_OBJECT_0:
+ if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ break;
+ default:
+ altos_set_last_windows_error();
+ return LIBALTOS_ERROR;
+ }
+ }
+ data += put;
+ used -= put;
+ }
+ }
+ file->file.out_used = 0;
+ return LIBALTOS_SUCCESS;
+}
+
+static HANDLE
+open_serial(char *full_name)
+{
+ HANDLE handle;
+ DCB dcb;
+
+ handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!GetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ dcb.BaudRate = CBR_9600;
+ dcb.fBinary = TRUE;
+ dcb.fParity = FALSE;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
+ dcb.fDsrSensitivity = FALSE;
+ dcb.fTXContinueOnXoff = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fInX = FALSE;
+ dcb.fErrorChar = FALSE;
+ dcb.fNull = FALSE;
+ dcb.fRtsControl = RTS_CONTROL_ENABLE;
+ dcb.fAbortOnError = FALSE;
+ dcb.XonLim = 10;
+ dcb.XoffLim = 10;
+ dcb.ByteSize = 8;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+ dcb.XonChar = 17;
+ dcb.XoffChar = 19;
+#if 0
+ dcb.ErrorChar = 0;
+ dcb.EofChar = 0;
+ dcb.EvtChar = 0;
+#endif
+ if (!SetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ return handle;
+}
+
+PUBLIC struct altos_file *
+altos_open(struct altos_device *device)
+{
+ struct altos_file_windows *file = calloc (1, sizeof (struct altos_file_windows));
+ char full_name[64];
+ COMMTIMEOUTS timeouts;
+ int i;
+
+ if (!file)
+ return NULL;
+
+ strcpy(full_name, "\\\\.\\");
+ strcat(full_name, device->path);
+
+ file->handle = INVALID_HANDLE_VALUE;
+
+ for (i = 0; i < 5; i++) {
+ file->handle = open_serial(full_name);
+ if (file->handle != INVALID_HANDLE_VALUE)
+ break;
+ altos_set_last_windows_error();
+ Sleep(100);
+ }
+
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ free(file);
+ return NULL;
+ }
+
+ /* The FTDI driver doesn't appear to work right unless you open it twice */
+ if (device->vendor == 0x0403) {
+ CloseHandle(file->handle);
+ file->handle = open_serial(full_name);
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ free(file);
+ return NULL;
+ }
+ }
+
+ timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
+ timeouts.ReadTotalTimeoutConstant = 1 << 30; /* almost forever */
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ timeouts.WriteTotalTimeoutConstant = 0;
+ SetCommTimeouts(file->handle, &timeouts);
+
+ file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ return &file->file;
+}
+
+PUBLIC void
+altos_close(struct altos_file *file_common)
+{
+ struct altos_file_windows *file = (struct altos_file_windows *) file_common;
+
+ if (file->is_winsock) {
+ SOCKET socket = file->socket;
+ if (socket != INVALID_SOCKET) {
+ file->socket = INVALID_SOCKET;
+ closesocket(socket);
+ }
+ } else {
+ HANDLE handle = file->handle;
+ if (handle != INVALID_HANDLE_VALUE) {
+ HANDLE ov_read = file->ov_read.hEvent;
+ HANDLE ov_write = file->ov_write.hEvent;
+ file->handle = INVALID_HANDLE_VALUE;
+ file->ov_read.hEvent = INVALID_HANDLE_VALUE;
+ file->ov_write.hEvent = INVALID_HANDLE_VALUE;
+ PurgeComm(handle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR);
+ Sleep(100);
+ CloseHandle(handle);
+ file->handle = INVALID_HANDLE_VALUE;
+ CloseHandle(ov_read);
+ CloseHandle(ov_write);
+ }
+ }
+}
+
+#include <ws2bth.h>
+
+#define LUP_SET (LUP_RETURN_NAME| LUP_CONTAINERS | LUP_RETURN_ADDR | LUP_FLUSHCACHE |\
+ LUP_RETURN_TYPE | LUP_RETURN_BLOB | LUP_RES_SERVICE)
+
+struct altos_bt_list {
+ WSADATA WSAData;
+ HANDLE lookup;
+};
+
+struct altos_bt_list *
+altos_bt_list_start(int inquiry_time)
+{
+ struct altos_bt_list *bt_list;
+ WSAQUERYSET query_set;
+ int retCode;
+
+ /* Windows provides no way to set the time */
+ (void) inquiry_time;
+ bt_list = calloc(1, sizeof (struct altos_bt_list));
+ if (!bt_list) {
+ altos_set_last_windows_error();
+ return NULL;
+ }
+
+ if ((retCode = WSAStartup(MAKEWORD(2,2),&bt_list->WSAData)) != 0) {
+ altos_set_last_winsock_error();
+ free(bt_list);
+ return NULL;
+ }
+
+ memset(&query_set, '\0', sizeof (query_set));
+ query_set.dwSize = sizeof(WSAQUERYSET);
+ query_set.dwNameSpace = NS_BTH;
+
+ retCode = WSALookupServiceBegin(&query_set, LUP_SET, &bt_list->lookup);
+
+ if (retCode != 0) {
+ altos_set_last_winsock_error();
+ free(bt_list);
+ return NULL;
+ }
+ return bt_list;
+}
+
+static unsigned char get_byte(BTH_ADDR ba, int shift)
+{
+ return (ba >> ((5 - shift) << 3)) & 0xff;
+}
+
+static BTH_ADDR put_byte(unsigned char c, int shift)
+{
+ return ((BTH_ADDR) c) << ((5 - shift) << 3);
+}
+
+static void
+ba2str(BTH_ADDR ba, char *str)
+{
+
+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ get_byte(ba, 0),
+ get_byte(ba, 1),
+ get_byte(ba, 2),
+ get_byte(ba, 3),
+ get_byte(ba, 4),
+ get_byte(ba, 5));
+}
+
+static BTH_ADDR
+str2ba(char *str)
+{
+ unsigned int bytes[6];
+
+ sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ &bytes[0],
+ &bytes[1],
+ &bytes[2],
+ &bytes[3],
+ &bytes[4],
+ &bytes[5]);
+ return (put_byte(bytes[0], 0) |
+ put_byte(bytes[1], 1) |
+ put_byte(bytes[2], 2) |
+ put_byte(bytes[3], 3) |
+ put_byte(bytes[4], 4) |
+ put_byte(bytes[5], 5));
+}
+
+int
+altos_bt_list_next(struct altos_bt_list *bt_list,
+ struct altos_bt_device *device)
+{
+ for (;;) {
+ BYTE buffer[4096];
+ DWORD length = sizeof (buffer);;
+ WSAQUERYSET *results = (WSAQUERYSET *)buffer;
+ CSADDR_INFO *addr_info;
+ int retCode;
+ SOCKADDR_BTH *sockaddr_bth;
+
+ memset(buffer, '\0', sizeof(buffer));
+
+ retCode = WSALookupServiceNext(bt_list->lookup, LUP_SET, &length, results);
+
+ if (retCode != 0) {
+ int error = WSAGetLastError();
+ if (error != WSAENOMORE && error != WSA_E_NO_MORE)
+ altos_set_last_winsock_error();
+ return 0;
+ }
+
+ if (results->dwNumberOfCsAddrs > 0) {
+
+ addr_info = results->lpcsaBuffer;
+
+ strncpy(device->name, results->lpszServiceInstanceName, sizeof(device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+
+ sockaddr_bth = (SOCKADDR_BTH *) addr_info->RemoteAddr.lpSockaddr;
+
+ ba2str(sockaddr_bth->btAddr, device->addr);
+
+ return 1;
+ }
+ }
+}
+
+void
+altos_bt_list_finish(struct altos_bt_list *bt_list)
+{
+ WSALookupServiceEnd(bt_list->lookup);
+ free(bt_list);
+}
+
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+ strncpy(device->name, name, sizeof (device->name));
+ device->name[sizeof(device->name)-1] = '\0';
+ strncpy(device->addr, addr, sizeof (device->addr));
+ device->addr[sizeof(device->addr)-1] = '\0';
+}
+
+struct altos_file *
+altos_bt_open(struct altos_bt_device *device)
+{
+ struct altos_file_windows *file;
+ SOCKADDR_BTH sockaddr_bth;
+ int ret;
+
+ file = calloc(1, sizeof (struct altos_file_windows));
+ if (!file) {
+ return NULL;
+ }
+
+ file->is_winsock = TRUE;
+ file->socket = WSASocket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM, NULL, 0, WSA_FLAG_OVERLAPPED);
+
+ if (file->socket == INVALID_SOCKET) {
+ altos_set_last_winsock_error();
+ free(file);
+ return NULL;
+ }
+
+ memset(&sockaddr_bth, '\0', sizeof (sockaddr_bth));
+ sockaddr_bth.addressFamily = AF_BTH;
+ sockaddr_bth.btAddr = str2ba(device->addr);
+ sockaddr_bth.port = 1;
+
+ ret = connect(file->socket, (SOCKADDR *) &sockaddr_bth, sizeof (sockaddr_bth));
+
+ if (ret != 0) {
+ altos_set_last_winsock_error();
+ closesocket(file->socket);
+ free(file);
+ return NULL;
+ }
+ return &file->file;
+}
+
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
class MicroIterator implements Iterator<MicroDataPoint> {
int i;
package org.altusmetrum.micropeak;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDataPoint implements AltosUIDataPoint {
public double time;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDeviceDialog extends AltosDeviceDialog {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroDownload extends AltosUIDialog implements Runnable, ActionListener, MicroSerialLog, WindowListener {
MicroPeak owner;
import java.awt.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroExport extends JFileChooser {
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFile {
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFileChooser extends JFileChooser {
JFrame frame;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroFrame extends AltosUIFrame {
static String[] micro_icon_names = {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
import java.awt.*;
import java.io.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroRaw extends JTextArea {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroSave extends JFileChooser {
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroSerial extends InputStream {
SWIGTYPE_p_altos_file file;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public interface MicroSerialLog {
package org.altusmetrum.micropeak;
import java.io.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroStats {
double coast_height;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class MicroUSB extends altos_device implements AltosDevice {
; And the stuff to install
-Section "FTDI USB Driver"
- SetOutPath $INSTDIR
-
- File "CDM_v2.12.00_WHQL_Certified.exe"
-
- StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
- ExecWait $2
-SectionEnd
-
Section "Install Driver" InstDriver
InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
CreateShortCut "$DESKTOP\${REG_NAME}.lnk" "$INSTDIR\${WIN_APP_EXE}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
+Section "FTDI USB Driver"
+ SetOutPath $INSTDIR
+
+ File "CDM_v2.12.00_WHQL_Certified.exe"
+
+ StrCpy $2 "$INSTDIR\CDM_v2.12.00_WHQL_Certified.exe"
+ ExecWait $2
+SectionEnd
+
Section "Documentation"
SetOutPath $INSTDIR
telescience-v0.2 telescience-v0.2/flash-loader \
teledongle-v3.0 teledongle-v3.0/flash-loader \
teleballoon-v2.0 \
- telebt-v3.0 telebt-v3.0/flash-loader
+ telebt-v3.0 telebt-v3.0/flash-loader \
+ telelcotwo-v0.1 telelcotwo-v0.1/flash-loader \
+ telefiretwo-v0.1 telefiretwo-v0.1/flash-loader \
ARMM0DIRS=\
easymini-v1.0 easymini-v1.0/flash-loader \
- chaoskey-v0.1 chaoskey-v0.1/flash-loader
+ chaoskey-v0.1 chaoskey-v0.1/flash-loader \
+ chaoskey-v1.0 chaoskey-v1.0/flash-loader
AVRDIRS=\
telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 microkite
#define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v)
#define ao_gpio_set(port, bit, pin, v) ((pin) = (v))
#define ao_gpio_get(port, bit, pin) (pin)
-
+#define ao_gpio_get_bits(port) (port)
+#define ao_gpio_set_bits(port, bits) ((port) |= bits)
+#define ao_gpio_clr_bits(port, bits) ((port) &= ~bits)
ao_product.h \
ao_task.h \
ao_adc_fast.h \
+ ao_power.h \
stm32f0.h
#
ao_usb_stm.c \
ao_trng_send.c \
ao_task.c \
+ ao_power.c \
+ ao_gpio.c \
ao_product.c
-PRODUCT=ChaosKey-v0.1
+PRODUCT=ChaosKey-hw-0.3-sw-$(VERSION)
PRODUCT_DEF=-DCHAOSKEY_V_0_1
IDVENDOR=0x1d50
IDPRODUCT=0x60c6
#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+#define AO_POWER_MANAGEMENT 1
+#define AO_LED_POWER AO_LED_RED
+
#define HAS_BEEP 0
/* 48MHz clock based on USB */
#define AO_APB_PRESCALER 1
#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
-#define HAS_USB 1
-#define AO_USB_DIRECTIO 1
-#define AO_PA11_PA12_RMP 0
-#define AO_USB_INTERFACE_CLASS 0xff
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 1
+#define AO_PA11_PA12_RMP 0
+#define AO_USB_DEVICE_CLASS 0xff
+#define AO_USB_INTERFACE_CLASS_DATA 0xff
+#define AO_USB_HAS_OUT 0
+#define AO_USB_HAS_IN 1
+#define AO_USB_HAS_IN2 1
+#define AO_USB_HAS_INT 0
+#define USE_USB_STDIO 0
+#define AO_USB_SELF_POWER 0
+#define AO_USB_DEVICE_ID_SERIAL 1
#define IS_FLASH_LOADER 0
#define AO_NUM_ADC 1
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT 8
+
/* CRC */
#define AO_CRC_WIDTH 32
#define AO_CRC_INIT 0xffffffff
/* TRNG */
-#define AO_LED_TRNG_ACTIVE AO_LED_GREEN
+#define AO_LED_TRNG_COOKED AO_LED_GREEN
+#define AO_LED_TRNG_RAW AO_LED_GREEN
+
+/* Mode pin */
+#define AO_RAW_PORT (&stm_gpioa)
+#define AO_RAW_BIT 15
#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+chaoskey-*
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ ao_adc_fast.h \
+ ao_power.h \
+ stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_timer.c \
+ ao_panic.c \
+ ao_mutex.c \
+ ao_dma_stm.c \
+ ao_adc_fast.c \
+ ao_crc_stm.c \
+ ao_stdio.c \
+ ao_led.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_usb_stm.c \
+ ao_trng_send.c \
+ ao_task.c \
+ ao_power.c \
+ ao_gpio.c \
+ ao_product.c
+
+PRODUCT=ChaosKey-hw-1.0-sw-$(VERSION)
+PRODUCT_DEF=-DCHAOSKEY_V_1_0
+IDVENDOR=0x1d50
+IDPRODUCT=0x60c6
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=chaoskey-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_chaoskey.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -V $(IDVENDOR) -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_adc_fast.h>
+#include <ao_crc.h>
+#include <ao_trng_send.h>
+
+void main(void)
+{
+ ao_led_init(LEDS_AVAILABLE);
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+ ao_dma_init();
+ ao_adc_init();
+ ao_crc_init();
+
+ ao_usb_init();
+
+ ao_trng_send_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN
+#define LED_PORT (&stm_gpiob)
+#define LED_PIN_RED 4
+#define AO_LED_RED (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define AO_POWER_MANAGEMENT 1
+#define AO_LED_POWER AO_LED_RED
+
+#define HAS_BEEP 0
+
+/* 48MHz clock based on USB */
+#define AO_HSI48 1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER 1
+#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 1
+#define AO_PA11_PA12_RMP 1
+#define AO_USB_DEVICE_CLASS 0xff
+#define AO_USB_INTERFACE_CLASS_DATA 0xff
+#define AO_USB_HAS_OUT 0
+#define AO_USB_HAS_IN 1
+#define AO_USB_HAS_IN2 1
+#define AO_USB_HAS_INT 0
+#define AO_USB_SELF_POWER 0
+#define AO_USB_DEVICE_ID_SERIAL 1
+#define AO_USB_START_DISABLED 1
+#define USE_USB_STDIO 0
+
+#define IS_FLASH_LOADER 0
+
+/* ADC */
+
+#define AO_ADC_PIN0_PORT (&stm_gpioa)
+#define AO_ADC_PIN0_PIN 0
+#define AO_ADC_PIN0_CH 0
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC 1
+
+/* TRNG enable */
+
+#define AO_TRNG_ENABLE_PORT (&stm_gpioa)
+#define AO_TRNG_ENABLE_BIT 1
+
+/* CRC */
+#define AO_CRC_WIDTH 32
+#define AO_CRC_INIT 0xffffffff
+
+/* Mode pin */
+#define AO_RAW_PORT (&stm_gpioa)
+#define AO_RAW_BIT 15
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+chaoskey*
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=chaoskey-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 15
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+detherm-*
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stmf0/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ stm32f0.h
+
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_timer.c \
+ ao_panic.c \
+ ao_mutex.c \
+ ao_dma_stm.c \
+ ao_usb_stm.c \
+ ao_spi_stm.c \
+ ao_exti_stm.c \
+ ao_stdio.c \
+ ao_led.c \
+ ao_log.c \
+ ao_log_mini.c \
+ ao_sample.c \
+ ao_data.c \
+ ao_kalman.c \
+ ao_flight.c \
+ ao_report.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_ms5607.c \
+ ao_convert_pa.c \
+ ao_pwm.c \
+ ao_servo.c \
+ ao_task.c \
+ ao_config.c \
+ ao_cmd.c \
+ ao_product.c
+
+PRODUCT=Detherm-v1.0
+PRODUCT_DEF=-DDETHERM_V_1_0
+IDPRODUCT=0x0013
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=detherm-v1.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_detherm.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) -o $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2014 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_pwm.h>
+#include <ao_servo.h>
+
+void main(void)
+{
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_led_on(AO_LED_RED);
+
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+ ao_exti_init();
+
+ ao_dma_init();
+ ao_spi_init();
+ ao_usb_init();
+
+ ao_storage_init();
+ ao_ms5607_init();
+// ao_flight_init();
+ ao_pwm_init();
+ ao_servo_init();
+ ao_log_init();
+ ao_report_init();
+ ao_config_init();
+
+ ao_cmd_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+/*
+ * Copyright © 2015 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPAEN
+#define LED_PORT (&stm_gpioa)
+#define LED_PIN_RED 3
+#define AO_LED_RED (1 << LED_PIN_RED)
+
+#define LEDS_AVAILABLE (AO_LED_RED)
+
+#define HAS_BEEP 0
+
+/* 48MHz clock based on USB */
+//#define AO_HSI48 1
+#define AO_HSE 16000000
+#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3
+#define AO_PLLMUL 3
+#define AO_PLLDIV 1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER 1
+#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#define IS_FLASH_LOADER 0
+
+#define AO_DATA_RING 16
+
+#define HAS_ADC 0
+#define HAS_ACCEL 0
+#define HAS_GPS 0
+#define HAS_RADIO 0
+#define HAS_FLIGHT 1
+#define HAS_EEPROM 1
+#define HAS_LOG 1
+
+#define AO_LOG_FORMAT AO_LOG_FORMAT_DETHERM
+
+#define USE_INTERNAL_FLASH 0
+
+/* SPI */
+#define HAS_SPI_1 1
+#define HAS_SPI_2 0
+#define SPI_1_PA5_PA6_PA7 1
+#define SPI_1_PB3_PB4_PB5 1
+#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH
+
+/* MS5607 */
+#define HAS_MS5607 1
+
+#define AO_MS5607_CS_PORT (&stm_gpioa)
+#define AO_MS5607_CS_PIN 0
+#define AO_MS5607_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
+#define AO_MS5607_MISO_PORT (&stm_gpiob)
+#define AO_MS5607_MISO_PIN 4
+#define AO_MS5607_PRIVATE_PINS 1
+#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_6MHz
+
+/* Flash */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpioa)
+#define AO_M25_SPI_CS_MASK (1 << 4)
+#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+
+/* PWM */
+
+#define NUM_PWM 1
+#define AO_PWM_TIMER (&stm_tim3)
+#define AO_PWM_0_GPIO (&stm_gpiob)
+#define AO_PWM_0_PIN 1
+#define AO_PWM_0_CH 4
+#define PWM_MAX 20000
+#define AO_PWM_TIMER_ENABLE STM_RCC_APB1ENR_TIM3EN
+#define AO_PWM_TIMER_SCALE 32
+
+/* Servo */
+
+#define AO_SERVO_DIR_PORT (&stm_gpiob)
+#define AO_SERVO_DIR_BIT 0
+#define AO_SERVO_SPEED_PWM 0
+
+/* limit 2 */
+#define AO_SERVO_LIMIT_FORE_PORT (&stm_gpiob)
+#define AO_SERVO_LIMIT_FORE_BIT 6
+
+/* limit 1 */
+#define AO_SERVO_LIMIT_BACK_PORT (&stm_gpiob)
+#define AO_SERVO_LIMIT_BACK_BIT 7
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+detherm*
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=detherm-v1.0
+include $(TOPDIR)/stmf0/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_stm_pins.h>
+
+/* Pin 5 on debug connector */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 15
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+/* USB */
+#define HAS_USB 1
+#define AO_USB_DIRECTIO 0
+#define AO_PA11_PA12_RMP 1
+
+#endif /* _AO_PINS_H_ */
#include <ao.h>
#include <ao_button.h>
#include <ao_exti.h>
-#include <ao_debounce.h>
#if AO_EVENT
#include <ao_event.h>
#define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v)
#define ao_button_queue(b,v)
#endif
-#define AO_BUTTON_DEBOUNCE_HOLD 10
+#define AO_BUTTON_DEBOUNCE_INTERVAL AO_MS_TO_TICKS(50)
-static struct ao_debounce ao_button_debounce[AO_BUTTON_COUNT];
+struct ao_button_state {
+ AO_TICK_TYPE time;
+ uint8_t value;
+};
+
+static struct ao_button_state ao_button_state[AO_BUTTON_COUNT];
#define port(q) AO_BUTTON_ ## q ## _PORT
#define bit(q) AO_BUTTON_ ## q
#define ao_button_value(b) !ao_gpio_get(port(b), bit(b), pin(b))
static uint8_t
-_ao_button_get(struct ao_debounce *debounce)
+_ao_button_get(uint8_t b)
{
- uint8_t b = debounce - ao_button_debounce;
-
switch (b) {
#if AO_BUTTON_COUNT > 0
case 0: return ao_button_value(0);
}
static void
-_ao_button_set(struct ao_debounce *debounce, uint8_t value)
+_ao_button_check(uint8_t b)
{
- uint8_t b = debounce - ao_button_debounce;
-
- ao_button_queue(b, value);
-}
+ uint8_t value = _ao_button_get(b);
+ if (value != ao_button_state[b].value) {
+ AO_TICK_TYPE now = ao_time();
-#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b)))
+ if ((now - ao_button_state[b].time) >= AO_BUTTON_DEBOUNCE_INTERVAL) {
+ ao_button_state[b].value = value;
+ ao_button_queue(b, value);
+ }
+ ao_button_state[b].time = now;
+ }
+}
static void
-ao_button_debounce_init(struct ao_debounce *debounce) {
- ao_debounce_config(debounce,
- _ao_button_get,
- _ao_button_set,
- AO_BUTTON_DEBOUNCE_HOLD);
+_ao_button_init(uint8_t b)
+{
+ uint8_t m = ao_arch_irqsave();
+ uint8_t value = _ao_button_get(b);
+ ao_button_state[b].value = value;
+ ao_button_state[b].time = ao_time();
+ ao_button_queue(b, value);
+ ao_arch_irqrestore(m);
+
}
static void
uint8_t b;
for (b = 0; b < AO_BUTTON_COUNT; b++)
- _ao_debounce_start(&ao_button_debounce[b]);
+ _ao_button_check(b);
}
#define init(b) do { \
- ao_button_debounce_init(&ao_button_debounce[b]); \
ao_enable_port(port(b)); \
\
ao_exti_setup(port(b), bit(b), \
AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \
- ao_button_isr); \
+ ao_button_isr); \
ao_exti_enable(port(b), bit(b)); \
+ _ao_button_init(b); \
} while (0)
void
#if AO_BUTTON_COUNT > 4
init(4);
#endif
- ao_debounce_init();
}
#include <ao_exti.h>
#include <ao_fec.h>
#include <ao_packet.h>
+#if HAS_PAD
+#include <ao_pad.h>
+#endif
static uint8_t ao_radio_mutex;
#endif
#if PACKET_HAS_SLAVE
ao_packet_slave_stop();
+#endif
+#if HAS_PAD
+ ao_pad_disable();
#endif
ao_radio_get(0xff);
ao_radio_set_mode(AO_RADIO_MODE_TEST);
radio_on = 0;
#if HAS_MONITOR
ao_monitor_enable();
+#endif
+#if HAS_PAD
+ ao_pad_enable();
#endif
}
}
);
}
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout)
+{
+ uint8_t empty = 1;
+ ao_arch_critical(
+ while ((empty = ao_event_queue_empty()))
+ if (ao_sleep_for(&ao_event_queue, timeout))
+ break;
+ if (!empty) {
+ *ev = ao_event_queue[ao_event_queue_remove];
+ ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove);
+ }
+ );
+ return empty;
+}
+
/* called with interrupts disabled */
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value)
void
ao_event_get(struct ao_event *ev);
+uint8_t
+ao_event_get_for(struct ao_event *ev, uint16_t timeout);
+
void
ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value);
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_lco.h>
+#include <ao_event.h>
+#include <ao_lco_func.h>
+#include <ao_radio_cmac.h>
+
+#define DEBUG 1
+
+#if DEBUG
+static uint8_t ao_lco_debug;
+#define DEBUG_EVENT 1
+#define DEBUG_STATUS 2
+#define PRINTD(l, ...) do { if (!(ao_lco_debug & l)) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0)
+#else
+#define PRINTD(l,...)
+#endif
+
+#define AO_LCO_VALID_LAST 1
+#define AO_LCO_VALID_EVER 2
+
+static uint8_t ao_lco_suspended;
+static uint8_t ao_lco_selected;
+static uint8_t ao_lco_valid;
+static uint8_t ao_lco_channels;
+static uint16_t ao_lco_tick_offset;
+
+/* UI values */
+static uint8_t ao_lco_armed;
+static uint8_t ao_lco_firing;
+
+#define ao_lco_box (ao_config.pad_box)
+
+static struct ao_pad_query ao_pad_query;
+
+#define MASK_SIZE(n) (((n) + 7) >> 3)
+#define MASK_ID(n) ((n) >> 3)
+#define MASK_SHIFT(n) ((n) & 7)
+
+static void
+ao_lco_set_armed(int pad, int armed)
+{
+ uint8_t bit = (1 << pad);
+
+ if (armed) {
+ ao_lco_selected |= bit;
+ ao_lco_armed |= bit;
+ } else {
+ ao_lco_selected &= ~bit;
+ ao_lco_armed &= ~bit;
+ }
+ PRINTD(DEBUG_EVENT, "pad %d bit 0x%x armed %d ao_lco_selected 0x%x ao_lco_armed 0x%x\n",
+ pad, bit, armed, ao_lco_selected, ao_lco_armed);
+ ao_wakeup(&ao_lco_armed);
+}
+
+static void
+ao_lco_suspend(void)
+{
+ if (!ao_lco_suspended) {
+ PRINTD(DEBUG_EVENT, "suspend\n");
+ ao_lco_suspended = 1;
+ ao_lco_selected = 0;
+ ao_lco_armed = 0;
+ ao_wakeup(&ao_pad_query);
+ }
+}
+
+static void
+ao_lco_wakeup(void)
+{
+ if (ao_lco_suspended) {
+ ao_lco_suspended = 0;
+ ao_wakeup(&ao_lco_suspended);
+ }
+}
+
+static void
+ao_lco_input(void)
+{
+ static struct ao_event event;
+ uint8_t timeout;
+
+ ao_config_get();
+ for (;;) {
+ if (ao_config.pad_idle && !ao_lco_suspended) {
+ timeout = ao_event_get_for(&event, AO_SEC_TO_TICKS(ao_config.pad_idle));
+ if (timeout) {
+ ao_lco_suspend();
+ continue;
+ }
+ } else {
+ ao_event_get(&event);
+ }
+ ao_lco_wakeup();
+ PRINTD(DEBUG_EVENT, "event type %d unit %d value %d\n",
+ event.type, event.unit, event.value);
+ switch (event.type) {
+ case AO_EVENT_BUTTON:
+ switch (event.unit) {
+ case AO_BUTTON_ARM_0:
+ ao_lco_set_armed(0, event.value);
+ break;
+#if AO_BUTTON_ARM_NUM > 1
+ case AO_BUTTON_ARM_1:
+ ao_lco_set_armed(1, event.value);
+ break;
+#endif
+ case AO_BUTTON_FIRE:
+ if (ao_lco_armed) {
+ ao_lco_firing = event.value;
+ PRINTD(DEBUG_EVENT, "Firing %d\n", ao_lco_firing);
+ ao_wakeup(&ao_lco_armed);
+ }
+ break;
+ }
+ break;
+ }
+ }
+}
+
+static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = {
+#ifdef AO_LED_CONTINUITY_0
+ AO_LED_CONTINUITY_0,
+#endif
+#ifdef AO_LED_CONTINUITY_1
+ AO_LED_CONTINUITY_1,
+#endif
+#ifdef AO_LED_CONTINUITY_2
+ AO_LED_CONTINUITY_2,
+#endif
+#ifdef AO_LED_CONTINUITY_3
+ AO_LED_CONTINUITY_3,
+#endif
+#ifdef AO_LED_CONTINUITY_4
+ AO_LED_CONTINUITY_4,
+#endif
+#ifdef AO_LED_CONTINUITY_5
+ AO_LED_CONTINUITY_5,
+#endif
+#ifdef AO_LED_CONTINUITY_6
+ AO_LED_CONTINUITY_6,
+#endif
+#ifdef AO_LED_CONTINUITY_7
+ AO_LED_CONTINUITY_7,
+#endif
+};
+
+static uint8_t
+ao_lco_get_channels(void)
+{
+ int8_t r;
+
+ r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset);
+ if (r == AO_RADIO_CMAC_OK) {
+ ao_lco_channels = ao_pad_query.channels;
+ ao_lco_valid = AO_LCO_VALID_LAST | AO_LCO_VALID_EVER;
+ } else
+ ao_lco_valid &= ~AO_LCO_VALID_LAST;
+ PRINTD(DEBUG_STATUS, "ao_lco_get_channels() rssi %d valid %d ret %d offset %d\n", ao_radio_cmac_rssi, ao_lco_valid, r, ao_lco_tick_offset);
+ ao_wakeup(&ao_pad_query);
+ return ao_lco_valid;
+}
+
+static void
+ao_lco_igniter_status(void)
+{
+ uint8_t c;
+ uint8_t t = 0;
+
+ for (;;) {
+ ao_sleep(&ao_pad_query);
+ while (ao_lco_suspended) {
+ ao_led_off(AO_LED_GREEN|AO_LED_AMBER|AO_LED_RED|AO_LED_REMOTE_ARM);
+ for (c = 0; c < AO_LED_CONTINUITY_NUM; c++)
+ ao_led_off(continuity_led[c]);
+ ao_sleep(&ao_lco_suspended);
+ }
+ PRINTD(DEBUG_STATUS, "RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid);
+ if (!(ao_lco_valid & AO_LCO_VALID_LAST)) {
+ ao_led_on(AO_LED_RED);
+ ao_led_off(AO_LED_GREEN|AO_LED_AMBER);
+ continue;
+ }
+ if (ao_radio_cmac_rssi < -90) {
+ ao_led_on(AO_LED_AMBER);
+ ao_led_off(AO_LED_RED|AO_LED_GREEN);
+ } else {
+ ao_led_on(AO_LED_GREEN);
+ ao_led_off(AO_LED_RED|AO_LED_AMBER);
+ }
+ if (ao_pad_query.arm_status)
+ ao_led_on(AO_LED_REMOTE_ARM);
+ else
+ ao_led_off(AO_LED_REMOTE_ARM);
+
+ for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) {
+ uint8_t status;
+
+ if (ao_pad_query.channels & (1 << c))
+ status = ao_pad_query.igniter_status[c];
+ else
+ status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+ PRINTD(DEBUG_STATUS, "\tchannel %d status %d\n", c, status);
+ if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN)
+ ao_led_on(continuity_led[c]);
+ else
+ ao_led_off(continuity_led[c]);
+ }
+ t = 1-t;
+ }
+}
+
+static void
+ao_lco_arm_warn(void)
+{
+ int i;
+ for (;;) {
+ while (ao_lco_suspended)
+ ao_sleep(&ao_lco_suspended);
+ while (!ao_lco_armed)
+ ao_sleep(&ao_lco_armed);
+ for (i = 0; i < ao_lco_armed; i++) {
+ ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100));
+ ao_delay(AO_MS_TO_TICKS(100));
+ }
+ ao_delay(AO_MS_TO_TICKS(300));
+ }
+}
+
+static struct ao_task ao_lco_input_task;
+static struct ao_task ao_lco_monitor_task;
+static struct ao_task ao_lco_arm_warn_task;
+static struct ao_task ao_lco_igniter_status_task;
+
+static void
+ao_lco_monitor(void)
+{
+ uint16_t delay;
+
+ ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input");
+ ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn");
+ ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status");
+ ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200));
+ for (;;) {
+ while (ao_lco_suspended)
+ ao_sleep(&ao_lco_suspended);
+
+ PRINTD(DEBUG_STATUS, "monitor armed %d firing %d\n",
+ ao_lco_armed, ao_lco_firing);
+
+ if (ao_lco_armed && ao_lco_firing) {
+ ao_lco_ignite();
+ } else {
+ ao_lco_get_channels();
+ if (ao_lco_armed) {
+ if (ao_lco_selected) {
+ PRINTD(DEBUG_STATUS, "Arming pads %x\n",
+ ao_lco_selected);
+ if (ao_lco_valid & AO_LCO_VALID_EVER) {
+ ao_lco_arm(ao_lco_box, ao_lco_selected, ao_lco_tick_offset);
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+ }
+ }
+ }
+ if (ao_lco_armed && ao_lco_firing)
+ delay = AO_MS_TO_TICKS(100);
+ else {
+ delay = AO_SEC_TO_TICKS(1);
+ }
+ ao_sleep_for(&ao_lco_armed, delay);
+ }
+}
+
+#if DEBUG
+void
+ao_lco_set_debug(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status == ao_cmd_success)
+ ao_lco_debug = ao_cmd_lex_i;
+}
+
+__code struct ao_cmds ao_lco_cmds[] = {
+ { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" },
+ { 0, NULL }
+};
+#endif
+
+void
+ao_lco_init(void)
+{
+ ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor");
+#if DEBUG
+ ao_cmd_register(&ao_lco_cmds[0]);
+#endif
+}
__xdata struct ao_ms5607_prom ao_ms5607_prom;
static __xdata uint8_t ms5607_configured;
+#ifndef AO_MS5607_SPI_SPEED
+#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_FAST
+#endif
+
static void
ao_ms5607_start(void) {
- ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_SPI_SPEED_FAST);
+ ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_MS5607_SPI_SPEED);
}
static void
{
char c;
ao_packet_enable = 1;
+ ao_packet_tx_used = 0;
ao_cmd_white();
flush();
#ifdef AO_SIREN
ao_gpio_set(AO_SIREN_PORT, AO_SIREN_PIN, AO_SIREN, v);
#else
+#if HAS_BEEP
ao_beep(v ? AO_BEEP_MID : 0);
+#else
+ (void) v;
+#endif
#endif
}
{
#ifdef AO_STROBE
ao_gpio_set(AO_STROBE_PORT, AO_STROBE_PIN, AO_STROBE, v);
+#else
+ (void) v;
#endif
}
static void
ao_pad_run(void)
{
- uint8_t pins;
+ AO_PORT_TYPE pins;
for (;;) {
while (!ao_pad_ignite)
if (ao_pad_ignite & (1 << 3))
pins |= (1 << AO_PAD_PIN_3);
#endif
- AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | pins;
+ PRINTD("ignite pins 0x%x\n", pins);
+ ao_gpio_set_bits(AO_PAD_PORT, pins);
while (ao_pad_ignite) {
ao_pad_ignite = 0;
ao_delay(AO_PAD_FIRE_TIME);
}
- AO_PAD_PORT &= ~(AO_PAD_ALL_PINS);
+ ao_gpio_clr_bits(AO_PAD_PORT, pins);
+ PRINTD("turn off pins 0x%x\n", pins);
}
}
#define AO_PAD_ARM_SIREN_INTERVAL 200
+#ifndef AO_PYRO_R_PYRO_SENSE
+#define AO_PYRO_R_PYRO_SENSE 100
+#define AO_PYRO_R_SENSE_GND 27
+#define AO_FIRE_R_POWER_FET 100
+#define AO_FIRE_R_FET_SENSE 100
+#define AO_FIRE_R_SENSE_GND 27
+#endif
+
static void
ao_pad_monitor(void)
{
uint8_t sample;
__pdata uint8_t prev = 0, cur = 0;
__pdata uint8_t beeping = 0;
- __xdata struct ao_data *packet;
+ __xdata volatile struct ao_data *packet;
__pdata uint16_t arm_beep_time = 0;
sample = ao_data_head;
ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
);
+
packet = &ao_data_ring[sample];
sample = ao_data_ring_next(sample);
pyro = packet->adc.pyro;
-#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0))
+#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \
+ (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX)))
+
+
+#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \
+ (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX)))
/* convert ADC value to voltage in tenths, then add .2 for the diode drop */
query.battery = (packet->adc.batt + 96) / 192 + 2;
if (pyro > VOLTS_TO_PYRO(10)) {
query.arm_status = AO_PAD_ARM_STATUS_ARMED;
cur |= AO_LED_ARMED;
- } else if (pyro < VOLTS_TO_PYRO(5)) {
- query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
- arm_beep_time = 0;
- } else {
+#if AO_FIRE_R_POWER_FET
+ } else if (pyro > VOLTS_TO_PYRO(5)) {
if ((ao_time() % 100) < 50)
cur |= AO_LED_ARMED;
query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
arm_beep_time = 0;
+#endif
+ } else {
+ query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
+ arm_beep_time = 0;
}
if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2))
cur |= AO_LED_RED;
* 27k /
* gnd ---
*
+ * v_pyro \
+ * 200k igniter
+ * output /
+ * 200k \
+ * sense relay
+ * 22k /
+ * gnd ---
+ *
* If the relay is closed, then sense will be 0
* If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2
* If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro
*/
+#if AO_FIRE_R_POWER_FET
if (sense <= pyro / 8) {
status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;
if ((ao_time() % 100) < 50)
cur |= AO_LED_CONTINUITY(c);
- }
- else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
+ } else
+ if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
else if (pyro / 8 * 7 <= sense) {
status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
cur |= AO_LED_CONTINUITY(c);
}
+#else
+ if (sense >= pyro / 8 * 5) {
+ status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
+ cur |= AO_LED_CONTINUITY(c);
+ } else {
+ status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+ }
+#endif
query.igniter_status[c] = status;
}
if (cur != prev) {
l = byte & 0xf;
return h * 10 + l;
}
-#else
-#define ao_pad_read_box() 0
+#endif
+
+#if HAS_FIXED_PAD_BOX
+#define ao_pad_read_box() ao_config.pad_box
+#endif
+
+#ifdef PAD_BOX
+#define ao_pad_read_box() PAD_BOX
#endif
static void
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_servo.h"
+#include "ao_pwm.h"
+#include "ao_exti.h"
+
+static uint8_t limit_wakeup;
+
+static void
+ao_limit_isr(void)
+{
+ ao_wakeup(&limit_wakeup);
+}
+
+static void
+ao_limit_enable(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ ao_exti_enable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ else
+ ao_exti_enable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static void
+ao_limit_disable(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ ao_exti_disable(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ else
+ ao_exti_disable(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+}
+
+static uint8_t
+ao_limit_get(uint8_t dir)
+{
+ if (dir == AO_SERVO_FORE)
+ return !ao_gpio_get(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT, PIN);
+ else
+ return !ao_gpio_get(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT, PIN);
+}
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout)
+{
+ printf ("speed %d dir %d\n", speed, dir);
+
+ /* Turn on the motor */
+ ao_gpio_set(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, dir);
+ ao_pwm_set(AO_SERVO_SPEED_PWM, speed);
+
+ /* Wait until the limit sensor is triggered */
+ ao_arch_block_interrupts();
+ ao_limit_enable(dir);
+ while (!ao_limit_get(dir))
+ if (ao_sleep_for(&limit_wakeup, timeout))
+ break;
+ ao_limit_disable(dir);
+ ao_arch_release_interrupts();
+
+ /* Turn off the motor */
+ ao_pwm_set(AO_SERVO_SPEED_PWM, 0);
+}
+
+#define init_limit(p,b) do { \
+ ao_enable_port(p); \
+ ao_exti_setup(p, b, \
+ AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, \
+ ao_limit_isr); \
+ } while (0)
+
+
+static void
+ao_servo_cmd(void)
+{
+ uint8_t dir;
+ uint16_t speed;
+
+ ao_cmd_decimal();
+ dir = ao_cmd_lex_u32;
+ ao_cmd_decimal();
+ speed = ao_cmd_lex_u32;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+
+ printf("Run servo %d\n", dir);
+ ao_servo_run(speed, dir, AO_MS_TO_TICKS(200));
+}
+
+static const struct ao_cmds ao_servo_cmds[] = {
+ { ao_servo_cmd, "S <dir> <speed>\0Run servo in indicated direction" },
+ { 0, NULL },
+};
+
+
+void
+ao_servo_init(void)
+{
+ init_limit(AO_SERVO_LIMIT_FORE_PORT, AO_SERVO_LIMIT_FORE_BIT);
+ init_limit(AO_SERVO_LIMIT_BACK_PORT, AO_SERVO_LIMIT_BACK_BIT);
+ ao_enable_output(AO_SERVO_DIR_PORT, AO_SERVO_DIR_BIT, AO_SERVO_DIR_PIN, 0);
+ ao_cmd_register(&ao_servo_cmds[0]);
+}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_SERVO_H_
+#define _AO_SERVO_H_
+
+void
+ao_servo_run(uint16_t speed, uint8_t dir, uint16_t timeout);
+
+void
+ao_servo_init(void);
+
+#define AO_SERVO_FORE 0
+#define AO_SERVO_BACK 1
+
+/* To configure the servo:
+ *
+ * #define AO_SERVO_PWM <pwm index>
+ * #define AO_SERVO_DIR_PORT <gpio>
+ * #define AO_SERVO_DIR_PIN <pin>
+ * #define AO_SERVO_LIMIT_FORE_PORT <gpio>
+ * #define AO_SERVO_LIMIT_FORE_PIN <pin>
+ * #define AO_SERVO_LIMIT_BACK_PORT <gpio>
+ * #define AO_SERVO_LIMIT_BACK_PIN <pin>
+ */
+
+#endif /* _AO_SERVO_H_ */
#include <ao_adc_fast.h>
#include <ao_crc.h>
#include <ao_trng_send.h>
+#include <ao_exti.h>
+#include <ao_power.h>
+
+static struct ao_task ao_trng_send_task, ao_trng_send_raw_task;
+static uint8_t trng_running;
+static AO_TICK_TYPE trng_power_time;
+
+#define TRNG_ENABLE_DELAY AO_MS_TO_TICKS(100)
+
+static uint8_t random_mutex;
static void
-ao_trng_send(void)
+ao_trng_get_raw(uint16_t *buf)
+{
+ uint16_t i;
+ uint16_t t;
+ uint16_t v;
+
+ t = ao_adc_get(AO_USB_IN_SIZE>>1); /* one 16-bit value per two output bytes */
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ v = ao_adc_ring[t];
+ *buf++ = v;
+ t = (t + 1) & (AO_ADC_RING_SIZE - 1);
+ }
+ ao_adc_ack(AO_USB_IN_SIZE>>1);
+}
+
+static void
+ao_trng_send_raw(void)
{
static uint16_t *buffer[2];
int usb_buf_id;
+
+ if (!buffer[0]) {
+ buffer[0] = ao_usb_alloc();
+ buffer[1] = ao_usb_alloc();
+ if (!buffer[0])
+ ao_exit();
+ }
+
+ usb_buf_id = 0;
+
+ for (;;) {
+ ao_mutex_get(&random_mutex);
+ if (!trng_running) {
+ AO_TICK_TYPE delay;
+
+ delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+ if (delay > TRNG_ENABLE_DELAY)
+ delay = TRNG_ENABLE_DELAY;
+
+ /* Delay long enough for the HV power supply
+ * to stabilize so that the first bits we read
+ * aren't of poor quality
+ */
+ ao_delay(delay);
+ trng_running = TRUE;
+ }
+#ifdef AO_LED_TRNG_RAW
+ ao_led_on(AO_LED_TRNG_RAW);
+#endif
+ ao_trng_get_raw(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_RAW
+ ao_led_off(AO_LED_TRNG_RAW);
+#endif
+ ao_mutex_put(&random_mutex);
+ ao_usb_write2(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ usb_buf_id = 1-usb_buf_id;
+ }
+}
+
+/* Make sure there's at least 8 bits of variance in the samples */
+#define MIN_VARIANCE (128 * 128)
+
+/* Make sure the signal is spread around a bit */
+#define MAX_VARIANCE (512 * 512)
+
+#define ADD_STATS(value) do { \
+ sum += (value); \
+ sum2 += (value) * (value); \
+ } while(0)
+
+#define VARIANCE(n) ((sum2 - (sum / (n) * sum)) / (n))
+
+static int
+ao_trng_get_cooked(uint16_t *buf)
+{
uint16_t i;
- uint16_t *buf;
uint16_t t;
uint32_t *rnd = (uint32_t *) ao_adc_ring;
+ int32_t sum, sum2, var;
+
+ sum = sum2 = 0;
+ t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
+ for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
+ uint32_t v;
+ uint16_t v1, v2;
+
+ /* Fetch two values in one operation */
+ v = rnd[t];
+ t = (t + 1) & ((AO_ADC_RING_SIZE >> 1) - 1);
+
+ *buf++ = ao_crc_in_32_out_16(v);
+
+ v1 = v;
+ v2 = v >> 16;
+
+ ADD_STATS(v1);
+ ADD_STATS(v2);
+ }
+ ao_adc_ack(AO_USB_IN_SIZE);
+ var = VARIANCE(2 * AO_USB_IN_SIZE / sizeof (uint16_t));
+ return var >= MIN_VARIANCE && var <= MAX_VARIANCE;
+}
+
+#define AO_TRNG_START_WAIT 1024
+#define AO_TRNG_START_CHECK 32
+
+static void
+ao_trng_send(void)
+{
+ static uint16_t *buffer[2];
+ int usb_buf_id;
+ int good_bits;
+ int failed;
+ int s;
if (!buffer[0]) {
buffer[0] = ao_usb_alloc();
buffer[1] = ao_usb_alloc();
if (!buffer[0])
- return;
+ ao_exit();
}
usb_buf_id = 0;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+ trng_power_time = ao_time();
+
ao_crc_reset();
+ ao_delay(TRNG_ENABLE_DELAY);
+
+ for (s = 0; s < AO_TRNG_START_WAIT; s++) {
+ if (ao_trng_get_cooked(buffer[0]))
+ break;
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+
+ /* Validate the hardware before enabling USB */
+ failed = 0;
+ for (s = 0; s < AO_TRNG_START_CHECK; s++) {
+ if (!ao_trng_get_cooked(buffer[0])) {
+ failed++;
+ ao_delay(AO_MS_TO_TICKS(10));
+ }
+ }
+ if (failed > AO_TRNG_START_CHECK / 4)
+ ao_panic(AO_PANIC_DMA);
+
+ ao_add_task(&ao_trng_send_raw_task, ao_trng_send_raw, "trng_send_raw");
+
+#ifdef AO_USB_START_DISABLED
+ ao_usb_enable();
+#endif
+
for (;;) {
- ao_led_on(AO_LED_TRNG_ACTIVE);
- t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */
- buf = buffer[usb_buf_id];
- for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) {
- *buf++ = ao_crc_in_32_out_16(rnd[t]);
- t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1);
+ ao_mutex_get(&random_mutex);
+ if (!trng_running) {
+ AO_TICK_TYPE delay;
+
+ delay = trng_power_time + TRNG_ENABLE_DELAY - ao_time();
+ if (delay > TRNG_ENABLE_DELAY)
+ delay = TRNG_ENABLE_DELAY;
+
+ /* Delay long enough for the HV power supply
+ * to stabilize so that the first bits we read
+ * aren't of poor quality
+ */
+ ao_delay(delay);
+ trng_running = TRUE;
+ }
+#ifdef AO_LED_TRNG_COOKED
+ ao_led_on(AO_LED_TRNG_COOKED);
+#endif
+ good_bits = ao_trng_get_cooked(buffer[usb_buf_id]);
+#ifdef AO_LED_TRNG_COOKED
+ ao_led_off(AO_LED_TRNG_COOKED);
+#endif
+ ao_mutex_put(&random_mutex);
+ if (good_bits) {
+ ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ usb_buf_id = 1-usb_buf_id;
+ failed = 0;
+ } else {
+ failed++;
+ ao_delay(AO_MS_TO_TICKS(10));
+ if (failed > 10) {
+ ao_usb_disable();
+ ao_panic(AO_PANIC_DMA);
+ }
}
- ao_adc_ack(AO_USB_IN_SIZE);
- ao_led_off(AO_LED_TRNG_ACTIVE);
- ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
- usb_buf_id = 1-usb_buf_id;
}
}
-static struct ao_task ao_trng_send_task;
+#if AO_POWER_MANAGEMENT
+
+static void ao_trng_suspend(void *arg)
+{
+ (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+#endif
+ trng_running = FALSE;
+}
+
+static void ao_trng_resume(void *arg)
+{
+ (void) arg;
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_gpio_set(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 1);
+#endif
+ trng_power_time = ao_time();
+}
+
+static struct ao_power ao_trng_power = {
+ .suspend = ao_trng_suspend,
+ .resume = ao_trng_resume
+};
+
+#endif
void
ao_trng_send_init(void)
{
+#ifdef AO_TRNG_ENABLE_PORT
+ ao_enable_output(AO_TRNG_ENABLE_PORT, AO_TRNG_ENABLE_BIT, AO_TRNG_ENABLE_PIN, 0);
+ ao_power_register(&ao_trng_power);
+#endif
+ ao_enable_input(AO_RAW_PORT, AO_RAW_BIT, AO_EXTI_MODE_PULL_UP);
ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send");
}
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5
#define AO_MMA655X_CS_PORT (&stm_gpioc)
#define AO_MMA655X_CS_PIN 12
void
ao_clock_init(void);
+#if AO_POWER_MANAGEMENT
+/* Go to low power clock */
+void
+ao_clock_suspend(void);
+
+/* Restart full-speed clock */
+void
+ao_clock_resume(void);
+#endif
+
/*
* ao_mutex.c
*/
} while(0)
#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove)
+#define ao_fifo_mostly(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 3 / 4))
+#define ao_fifo_barely(f) ((((f).insert - (f).remove) & (AO_FIFO_SIZE-1)) >= (AO_FIFO_SIZE * 1 / 4))
#define ao_fifo_empty(f) ((f).insert == (f).remove)
#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE
#if HAS_APRS
if (minor < 22)
ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT;
+#endif
+#if HAS_FIXED_PAD_BOX
+ if (minor < 22)
+ ao_config.pad_box = 1;
+ if (minor < 23)
+ ao_config.pad_idle = 120;
#endif
ao_config.minor = AO_CONFIG_MINOR;
ao_config_dirty = 1;
}
#endif /* HAS_APRS */
+#if HAS_FIXED_PAD_BOX
+void
+ao_config_pad_box_show(void)
+{
+ printf ("Pad box: %d\n", ao_config.pad_box);
+}
+
+void
+ao_config_pad_box_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_box = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+
+void
+ao_config_pad_idle_show(void)
+{
+ printf ("Idle timeout: %d\n", ao_config.pad_idle);
+}
+
+void
+ao_config_pad_idle_set(void)
+{
+ ao_cmd_decimal();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ _ao_config_edit_start();
+ ao_config.pad_idle = ao_cmd_lex_i;
+ _ao_config_edit_finish();
+}
+#endif
+
struct ao_config_var {
__code char *str;
void (*set)(void) __reentrant;
ao_config_aprs_ssid_set, ao_config_aprs_ssid_show },
{ "C <0 compressed, 1 uncompressed>\0APRS format",
ao_config_aprs_format_set, ao_config_aprs_format_show },
+#endif
+#if HAS_FIXED_PAD_BOX
+ { "B <box>\0Set pad box (1-99)",
+ ao_config_pad_box_set, ao_config_pad_box_show },
+ { "i <seconds>\0Set idle timeout (0 disable)",
+ ao_config_pad_idle_set, ao_config_pad_idle_show },
#endif
{ "s\0Show",
ao_config_show, 0 },
#endif
#define AO_CONFIG_MAJOR 1
-#define AO_CONFIG_MINOR 22
+#define AO_CONFIG_MINOR 23
#define AO_AES_LEN 16
#if HAS_APRS
uint8_t aprs_format; /* minor version 22 */
#endif
+#if HAS_FIXED_PAD_BOX
+ uint8_t pad_box; /* minor version 22 */
+ uint8_t pad_idle; /* minor version 23 */
+#endif
};
#define AO_APRS_FORMAT_COMPRESSED 0
#define AO_ACCEL_INVERT 4095
+#ifndef AO_MMA655X_INVERT
+#error AO_MMA655X_INVERT not defined
+#endif
+
#define ao_data_accel(packet) ((packet)->mma655x)
#if AO_MMA655X_INVERT
#define ao_data_accel_cook(packet) (AO_ACCEL_INVERT - (packet)->mma655x)
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FAST_TIMER_H_
+#define _AO_FAST_TIMER_H_
+
+void
+ao_fast_timer_init(void);
+
+#ifndef AO_FAST_TIMER_MAX
+#define AO_FAST_TIMER_MAX 2
+#endif
+
+void
+ao_fast_timer_on(void (*callback)(void));
+
+void
+ao_fast_timer_off(void (*callback)(void));
+
+#endif /* _AO_FAST_TIMER_H_ */
{
ao_flight_state = ao_flight_landed;
+#if HAS_ADC
/* turn off the ADC capture */
ao_timer_set_adc_interval(0);
+#endif
ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
}
#define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */
#define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */
#define AO_LOG_FORMAT_TELEMEGA 10 /* 32 byte typed telemega records with 32 bit gyro cal */
+#define AO_LOG_FORMAT_DETHERM 11 /* 16-byte MS5607 baro only, no ADC */
#define AO_LOG_FORMAT_NONE 127 /* No log at all */
extern __code uint8_t ao_log_format;
ao_data_ring[ao_log_data_pos].ms5607_raw.pres);
ao_log_pack24(log.u.sensor.temp,
ao_data_ring[ao_log_data_pos].ms5607_raw.temp);
+#if AO_LOG_FORMAT != AO_LOG_FORMAT_DETHERM
log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a;
log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m;
log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt;
+#endif
ao_log_mini(&log);
if (ao_log_state <= ao_flight_coast)
next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT;
{
uint8_t i = 0, j = 0;
- while (n--)
+ while (n--) {
+#ifdef AO_PANIC_DELAY_SCALE
+ uint8_t s = AO_PANIC_DELAY_SCALE;
+ while (s--)
+#endif
while (--j)
while (--i)
ao_arch_nop();
+ }
}
void
ao_arch_block_interrupts();
for (;;) {
ao_panic_delay(20);
+#if HAS_BEEP
for (n = 0; n < 5; n++) {
- ao_led_on(AO_LED_PANIC);
ao_beep(AO_BEEP_HIGH);
ao_panic_delay(1);
- ao_led_off(AO_LED_PANIC);
ao_beep(AO_BEEP_LOW);
ao_panic_delay(1);
}
ao_beep(AO_BEEP_OFF);
ao_panic_delay(2);
+#endif
#ifdef SDCC
#pragma disable_warning 126
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_power.h>
+
+static struct ao_power *head, *tail;
+
+void
+ao_power_register(struct ao_power *power)
+{
+ if (power->registered)
+ return;
+ power->registered = TRUE;
+ if (tail) {
+ tail->next = power;
+ power->prev = tail;
+ tail = power;
+ } else {
+ head = tail = power;
+ }
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
+void
+ao_power_unregister(struct ao_power *power)
+{
+ if (!power->registered)
+ return;
+ power->registered = FALSE;
+ if (power->prev)
+ power->prev->next = power->next;
+ else
+ head = power->next;
+ if (power->next)
+ power->next->prev = power->prev;
+ else
+ tail = power->prev;
+}
+
+void
+ao_power_suspend(void)
+{
+ struct ao_power *p;
+
+#ifdef AO_LED_POWER
+ ao_led_off(AO_LED_POWER);
+#endif
+ for (p = tail; p; p = p->prev)
+ p->suspend(p->arg);
+}
+
+void
+ao_power_resume(void)
+{
+ struct ao_power *p;
+
+ for (p = head; p; p = p->next)
+ p->resume(p->arg);
+#ifdef AO_LED_POWER
+ ao_led_on(AO_LED_POWER);
+#endif
+}
+
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_POWER_H_
+#define _AO_POWER_H_
+
+#if AO_POWER_MANAGEMENT
+
+struct ao_power {
+ struct ao_power *prev, *next;
+
+ void (*suspend)(void *arg);
+ void (*resume)(void *arg);
+ void *arg;
+ uint8_t registered;
+};
+
+void
+ao_power_register(struct ao_power *power);
+
+void
+ao_power_unregister(struct ao_power *power);
+
+void
+ao_power_suspend(void);
+
+void
+ao_power_resume(void);
+
+#else /* AO_POWER_MANAGEMENT */
+
+#define ao_power_register(power)
+#define ao_power_unregister(power)
+#define ao_power_suspend()
+#define ao_power_resume()
+
+#endif /* else AO_POWER_MANAGEMENT */
+
+#endif /* _AO_POWER_H_ */
#define AO_USB_MAX_POWER 100
#endif
-#ifndef AO_USB_INTERFACE_CLASS
-#define AO_USB_INTERFACE_CLASS 0x02
+#ifndef AO_USB_SELF_POWER
+#define AO_USB_SELF_POWER 1
+#endif
+
+#define AO_USB_DEVICE_CLASS_COMMUNICATION 0x02
+#define AO_USB_INTERFACE_CLASS_CONTROL_CDC 0x02
+#define AO_USB_INTERFACE_CLASS_DATA_CDC 0x0A
+
+#ifndef AO_USB_DEVICE_CLASS
+#define AO_USB_DEVICE_CLASS AO_USB_DEVICE_CLASS_COMMUNICATION
+#endif
+
+#ifndef AO_USB_INTERFACE_CLASS_DATA
+#define AO_USB_INTERFACE_CLASS_CONTROL AO_USB_INTERFACE_CLASS_CONTROL_CDC
+#define AO_USB_INTERFACE_CLASS_DATA AO_USB_INTERFACE_CLASS_DATA_CDC
#endif
#include "ao_usb.h"
+
+#define HEADER_LEN 9
+#define CONTROL_CLASS_LEN 35
+#define DATA_LEN (9 + 7 * AO_USB_HAS_OUT + 7 * AO_USB_HAS_IN + 7 * AO_USB_HAS_IN2)
+
+#define TOTAL_LENGTH (HEADER_LEN + AO_USB_HAS_INT * CONTROL_CLASS_LEN + DATA_LEN)
+#define NUM_INTERFACES (AO_USB_HAS_INT + 1)
+
/* USB descriptors in one giant block of bytes */
AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] =
{
0x12,
AO_USB_DESC_DEVICE,
LE_WORD(0x0110), /* bcdUSB */
- 0x02, /* bDeviceClass */
+ AO_USB_DEVICE_CLASS, /* bDeviceClass */
0x00, /* bDeviceSubClass */
0x00, /* bDeviceProtocol */
AO_USB_CONTROL_SIZE, /* bMaxPacketSize */
/* Configuration descriptor */
0x09,
AO_USB_DESC_CONFIGURATION,
- LE_WORD(67), /* wTotalLength */
- 0x02, /* bNumInterfaces */
+ LE_WORD(TOTAL_LENGTH), /* wTotalLength */
+ NUM_INTERFACES, /* bNumInterfaces */
0x01, /* bConfigurationValue */
0x00, /* iConfiguration */
- 0xC0, /* bmAttributes */
+ 0x80 | (AO_USB_SELF_POWER << 6), /* bmAttributes */
AO_USB_MAX_POWER >> 1, /* bMaxPower, 2mA units */
+#if AO_USB_HAS_INT
/* Control class interface */
0x09,
AO_USB_DESC_INTERFACE,
0x00, /* bInterfaceNumber */
0x00, /* bAlternateSetting */
0x01, /* bNumEndPoints */
- AO_USB_INTERFACE_CLASS, /* bInterfaceClass */
+ AO_USB_INTERFACE_CLASS_CONTROL, /* bInterfaceClass */
0x02, /* bInterfaceSubClass */
0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */
0x00, /* iInterface */
0x03, /* bmAttributes = intr */
LE_WORD(8), /* wMaxPacketSize */
0xff, /* bInterval */
+#endif
/* Data class interface descriptor */
0x09,
AO_USB_DESC_INTERFACE,
- 0x01, /* bInterfaceNumber */
- 0x00, /* bAlternateSetting */
- 0x02, /* bNumEndPoints */
- 0x0A, /* bInterfaceClass = data */
- 0x00, /* bInterfaceSubClass */
- 0x00, /* bInterfaceProtocol */
- 0x00, /* iInterface */
-
+ AO_USB_HAS_INT, /* bInterfaceNumber */
+ 0x00, /* bAlternateSetting */
+ AO_USB_HAS_OUT + AO_USB_HAS_IN + AO_USB_HAS_IN2, /* bNumEndPoints */
+ AO_USB_INTERFACE_CLASS_DATA, /* bInterfaceClass = data */
+ 0x00, /* bInterfaceSubClass */
+ 0x00, /* bInterfaceProtocol */
+ 0x00, /* iInterface */
+
+#if AO_USB_HAS_OUT
/* Data EP OUT */
0x07,
AO_USB_DESC_ENDPOINT,
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+#if AO_USB_HAS_IN
/* Data EP in */
0x07,
AO_USB_DESC_ENDPOINT,
0x02, /* bmAttributes = bulk */
LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
0x00, /* bInterval */
+#endif
+
+#if AO_USB_HAS_IN2
+ /* Data EP in 2 */
+ 0x07,
+ AO_USB_DESC_ENDPOINT,
+ AO_USB_IN2_EP|0x80, /* bEndpointAddress */
+ 0x02, /* bmAttributes = bulk */
+ LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */
+ 0x00, /* bInterval */
+#endif
/* String descriptors */
0x04,
*/
if (ao_cur_task->wchan == NULL)
ao_task_to_run_queue(ao_cur_task);
- ao_cur_task = NULL;
for (;;) {
ao_arch_memory_barrier();
if (!ao_list_is_empty(&run_queue))
void
ao_wakeup(__xdata void *wchan) __reentrant
{
+ ao_validate_cur_stack();
#if HAS_TASK_QUEUE
struct ao_task *sleep, *next;
struct ao_list *sleep_queue;
}
ao_arch_irqrestore(flags);
#else
+ {
uint8_t i;
for (i = 0; i < ao_num_tasks; i++)
if (ao_tasks[i]->wchan == wchan)
ao_tasks[i]->wchan = NULL;
+ }
#endif
ao_check_stack();
}
extern __xdata struct ao_task *__data ao_cur_task;
extern __data uint8_t ao_task_minimize_latency; /* Reduce IRQ latency */
+#ifndef HAS_ARCH_VALIDATE_CUR_STACK
+#define ao_validate_cur_stack()
+#endif
+
/*
ao_task.c
*/
#ifndef AO_USB_OUT_EP
#define AO_USB_OUT_EP 4
#define AO_USB_IN_EP 5
+#define AO_USB_IN2_EP 6
+#endif
+
+#ifndef AO_USB_HAS_OUT
+#define AO_USB_HAS_OUT 1
+#endif
+
+#ifndef AO_USB_HAS_IN
+#define AO_USB_HAS_IN 1
+#endif
+
+#ifndef AO_USB_HAS_INT
+#define AO_USB_HAS_INT 1
+#endif
+
+#ifndef AO_USB_HAS_IN2
+#define AO_USB_HAS_IN2 0
#endif
/*
void
ao_spi_init(void);
+static inline void
+ao_spi_send_sync(const void *block, uint16_t len, uint8_t spi_index)
+{
+ ao_spi_send(block, len, spi_index);
+}
+
+static inline void ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+ struct lpc_ssp *lpc_ssp;
+ switch (spi_index) {
+ case 0:
+ lpc_ssp = &lpc_ssp0;
+ break;
+ case 1:
+ lpc_ssp = &lpc_ssp1;
+ break;
+ }
+ lpc_ssp->dr = byte;
+ while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0);
+ (void) lpc_ssp->dr;
+}
+
#define ao_spi_init_cs(port, mask) do { \
uint8_t __bit__; \
for (__bit__ = 0; __bit__ < 32; __bit__++) { \
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_fast_timer.h>
+
+static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void);
+static uint8_t ao_fast_timer_count;
+static uint8_t ao_fast_timer_users;
+
+static void
+ao_fast_timer_enable(void)
+{
+ lpc_ct16b0.tcr = ((1 << LPC_CT16B_TCR_CEN) |
+ (1 << LPC_CT16B_TCR_CRST));
+}
+
+static void
+ao_fast_timer_disable(void)
+{
+ lpc_ct16b0.tcr = ((0 << LPC_CT16B_TCR_CEN) |
+ (0 << LPC_CT16B_TCR_CRST));
+}
+
+void
+ao_fast_timer_on(void (*callback)(void))
+{
+ ao_fast_timer_callback[ao_fast_timer_count] = callback;
+ if (!ao_fast_timer_count++)
+ ao_fast_timer_enable();
+}
+
+void
+ao_fast_timer_off(void (*callback)(void))
+{
+ uint8_t n;
+
+ for (n = 0; n < ao_fast_timer_count; n++)
+ if (ao_fast_timer_callback[n] == callback) {
+ for (; n < ao_fast_timer_count-1; n++) {
+ ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1];
+ }
+ if (!--ao_fast_timer_count)
+ ao_fast_timer_disable();
+ break;
+ }
+}
+
+void lpc_ct16b0_isr(void)
+{
+ uint32_t v = lpc_ct16b0.ir;
+ int i;
+
+ lpc_ct16b0.ir = v;
+ if (v & (1 << LPC_CT16B_IR_MR0INT)) {
+ for (i = 0; i < ao_fast_timer_count; i++)
+ (*ao_fast_timer_callback[i])();
+ }
+}
+
+#ifndef FAST_TIMER_FREQ
+#define FAST_TIMER_FREQ 10000
+#endif
+
+#define TIMER_FAST (AO_LPC_SYSCLK / FAST_TIMER_FREQ)
+
+void
+ao_fast_timer_init(void)
+{
+ if (!ao_fast_timer_users) {
+
+ lpc_nvic_set_enable(LPC_ISR_CT16B0_POS);
+ lpc_nvic_set_priority(LPC_ISR_CT16B0_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
+ /* Turn on 16-bit timer CT16B0 */
+
+ lpc_scb.sysahbclkctrl |= 1 << LPC_SCB_SYSAHBCLKCTRL_CT16B0;
+
+ /* Disable timer */
+ lpc_ct16b0.tcr = 0;
+
+ /* scale factor 1 */
+ lpc_ct16b0.pr = 0;
+ lpc_ct16b0.pc = 0;
+
+ lpc_ct16b0.mcr = ((1 << LPC_CT16B_MCR_MR0I) |
+ (1 << LPC_CT16B_MCR_MR0R));
+
+ lpc_ct16b0.mr[0] = TIMER_FAST;
+
+ ao_fast_timer_disable();
+ }
+ if (ao_fast_timer_users == AO_FAST_TIMER_MAX)
+ ao_panic(AO_PANIC_FAST_TIMER);
+ ao_fast_timer_users++;
+}
+
(1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) |
(1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) |
(1 << LPC_SCB_SYSAHBCLKCTRL_IOCON));
-
+
/* Enable the brown-out detection at the highest voltage to
* make sure the flash part remains happy
*/
/* Turn the IRC clock back on */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD);
ao_clock_delay();
-
+
/* Switch to the IRC clock */
lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL;
lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA);
lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA);
while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA)))
;
-
+
/* Switch USB to the main clock */
lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL);
lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA);
lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA);
while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA)))
;
-
+
/* Find a PLL post divider ratio that gets the FCCO in range */
for (p = 0; p < 4; p++)
if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN)
lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA);
while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA)))
;
-
+
/* Turn on the PLL */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD);
/* Wait for it to lock */
-
+
for (i = 0; i < 20000; i++)
if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK))
break;
lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA);
while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA)))
;
-
+
/* Power down everything we don't need */
lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) |
(1 << LPC_SCB_PDRUNCFG_IRC_PD) |
vuint32_t mainclksel; /* 0x70 */
vuint32_t mainclkuen;
vuint32_t sysahbclkdiv;
- uint32_t r7c;
+ uint32_t r7c;
vuint32_t sysahbclkctrl; /* 0x80 */
uint32_t r84[3];
uint32_t rcc;
uint32_t rd0[4];
-
+
vuint32_t clkoutsel; /* 0xe0 */
vuint32_t clkoutuen;
vuint32_t clkoutdiv;
uint32_t rec;
-
+
uint32_t rf0[4]; /* 0xf0 */
-
+
vuint32_t pioporcap0; /* 0x100 */
vuint32_t pioporcap1;
uint32_t r102[2];
uint32_t r120[4]; /* 0x120 */
uint32_t r130[4]; /* 0x130 */
uint32_t r140[4]; /* 0x140 */
-
+
vuint32_t bodctrl; /* 0x150 */
vuint32_t systckcal;
uint32_t r158[2];
uint32_t r240[12 * 4]; /* 0x240 */
uint32_t r300[15 * 4]; /* 0x300 */
-
+
uint32_t r3f0; /* 0x3f0 */
vuint32_t device_id;
};
vuint32_t word[0x40]; /* 0x1000 */
uint8_t r1100[0x2000 - 0x1100];
-
+
vuint32_t dir[2]; /* 0x2000 */
uint8_t r2008[0x2080 - 0x2008];
return (lpc_nvic.iser >> irq) & 1;
}
-
+
static inline void
lpc_nvic_set_pending(int irq) {
lpc_nvic.ispr = (1 << irq);
#define LPC_ADC_STAT_OVERRUN 8
#define LPC_ADC_STAT_ADINT 16
+struct lpc_ct16b {
+ vuint32_t ir; /* 0x00 */
+ vuint32_t tcr;
+ vuint32_t tc;
+ vuint32_t pr;
+
+ vuint32_t pc; /* 0x10 */
+ vuint32_t mcr;
+ vuint32_t mr[4]; /* 0x18 */
+ vuint32_t ccr; /* 0x28 */
+ vuint32_t cr0;
+
+ vuint32_t cr1_0; /* 0x30 (only for ct16b0 */
+ vuint32_t cr1_1; /* 0x34 (only for ct16b1 */
+ uint32_t r38;
+ vuint32_t emr;
+
+ uint8_t r40[0x70 - 0x40];
+
+ vuint32_t ctcr; /* 0x70 */
+ vuint32_t pwmc;
+};
+
+extern struct lpc_ct16b lpc_ct16b0, lpc_ct16b1;
+
+#define lpc_ct16b0 (*(struct lpc_ct16b *) 0x4000c000)
+#define lpc_ct16b1 (*(struct lpc_ct16b *) 0x40010000)
+
+#define LPC_CT16B_IR_MR0INT 0
+#define LPC_CT16B_IR_MR1INT 1
+#define LPC_CT16B_IR_MR2INT 2
+#define LPC_CT16B_IR_MR3INT 3
+#define LPC_CT16B_IR_CR0INT 4
+#define LPC_CT16B0_IR_CR1INT 6
+#define LPC_CT16B1_IR_CR1INT 5
+
+#define LPC_CT16B_TCR_CEN 0
+#define LPC_CT16B_TCR_CRST 1
+
+#define LPC_CT16B_MCR_MR0I 0
+#define LPC_CT16B_MCR_MR0R 1
+#define LPC_CT16B_MCR_MR0S 2
+#define LPC_CT16B_MCR_MR1I 3
+#define LPC_CT16B_MCR_MR1R 4
+#define LPC_CT16B_MCR_MR1S 5
+#define LPC_CT16B_MCR_MR2I 6
+#define LPC_CT16B_MCR_MR2R 7
+#define LPC_CT16B_MCR_MR2S 8
+#define LPC_CT16B_MCR_MR3I 9
+#define LPC_CT16B_MCR_MR3R 10
+#define LPC_CT16B_MCR_MR3S 11
+
+#define LPC_CT16B_CCR_CAP0RE 0
+#define LPC_CT16B_CCR_CAP0FE 1
+#define LPC_CT16B_CCR_CAP0I 2
+#define LPC_CT16B0_CCR_CAP1RE 6
+#define LPC_CT16B0_CCR_CAP1FE 7
+#define LPC_CT16B0_CCR_CAP1I 8
+#define LPC_CT16B1_CCR_CAP1RE 3
+#define LPC_CT16B1_CCR_CAP1FE 4
+#define LPC_CT16B1_CCR_CAP1I 5
+
+#define LPC_CT16B_EMR_EM0 0
+#define LPC_CT16B_EMR_EM1 1
+#define LPC_CT16B_EMR_EM2 2
+#define LPC_CT16B_EMR_EM3 3
+#define LPC_CT16B_EMR_EMC0 4
+#define LPC_CT16B_EMR_EMC1 6
+#define LPC_CT16B_EMR_EMC2 8
+#define LPC_CT16B_EMR_EMC3 10
+
+#define LPC_CT16B_EMR_EMC_NOTHING 0
+#define LPC_CT16B_EMR_EMC_CLEAR 1
+#define LPC_CT16B_EMR_EMC_SET 2
+#define LPC_CT16B_EMR_EMC_TOGGLE 3
+
+#define LPC_CT16B_CCR_CTM 0
+#define LPC_CT16B_CCR_CTM_TIMER 0
+#define LPC_CT16B_CCR_CTM_COUNTER_RISING 1
+#define LPC_CT16B_CCR_CTM_COUNTER_FALLING 2
+#define LPC_CT16B_CCR_CTM_COUNTER_BOTH 3
+#define LPC_CT16B_CCR_CIS 2
+#define LPC_CT16B_CCR_CIS_CAP0 0
+#define LPC_CT16B0_CCR_CIS_CAP1 2
+#define LPC_CT16B1_CCR_CIS_CAP1 1
+#define LPC_CT16B_CCR_ENCC 4
+#define LPC_CT16B_CCR_SELCC 5
+#define LPC_CT16B_CCR_SELCC_RISING_CAP0 0
+#define LPC_CT16B_CCR_SELCC_FALLING_CAP0 1
+#define LPC_CT16B0_CCR_SELCC_RISING_CAP1 4
+#define LPC_CT16B0_CCR_SELCC_FALLING_CAP1 5
+#define LPC_CT16B1_CCR_SELCC_RISING_CAP1 2
+#define LPC_CT16B1_CCR_SELCC_FALLING_CAP1 3
+#define LPC_CT16B_CCR_
+
+#define LPC_CT16B_PWMC_PWMEN0 0
+#define LPC_CT16B_PWMC_PWMEN1 1
+#define LPC_CT16B_PWMC_PWMEN2 2
+#define LPC_CT16B_PWMC_PWMEN3 3
+
struct lpc_ct32b {
vuint32_t ir; /* 0x00 */
vuint32_t tcr;
vuint32_t tc;
vuint32_t pr;
-
+
vuint32_t pc; /* 0x10 */
vuint32_t mcr;
vuint32_t mr[4]; /* 0x18 */
vuint32_t ccr; /* 0x28 */
vuint32_t cr0;
-
+
vuint32_t cr1_0; /* 0x30 (only for ct32b0 */
vuint32_t cr1_1; /* 0x34 (only for ct32b1 */
uint32_t r38;
lpc_usb_sram = 0x20004000;
lpc_usb_endpoint = 0x20004700;
lpc_usart = 0x40008000;
+lpc_ct16b0 = 0x4000c000;
+lpc_ct16b1 = 0x40010000;
lpc_ct32b0 = 0x40014000;
lpc_ct32b1 = 0x40018000;
lpc_adc = 0x4001c000;
* STM32L definitions and code fragments for AltOS
*/
+#ifndef AO_STACK_SIZE
#define AO_STACK_SIZE 512
+#endif
#define AO_LED_TYPE uint16_t
void
ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
+static inline void
+ao_spi_send_byte(uint8_t byte, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi;
+
+ switch (AO_SPI_INDEX(spi_index)) {
+ case 0:
+ stm_spi = &stm_spi1;
+ break;
+ case 1:
+ stm_spi = &stm_spi2;
+ break;
+ }
+
+ stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) |
+ (0 << STM_SPI_CR2_RXNEIE) |
+ (0 << STM_SPI_CR2_ERRIE) |
+ (0 << STM_SPI_CR2_SSOE) |
+ (0 << STM_SPI_CR2_TXDMAEN) |
+ (0 << STM_SPI_CR2_RXDMAEN));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+ stm_spi->dr = byte;
+}
+
void
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
#define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
+#define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits)
+
+#define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits);
+
+
#define ao_enable_output(port,bit,pin,v) do { \
ao_enable_port(port); \
ao_gpio_set(port, bit, pin, v); \
void
ao_i2c_init(void);
+#if USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_SW_FLOW 1
+#else
+#define HAS_SERIAL_SW_FLOW 0
+#endif
+
+#if USE_SERIAL_1_FLOW && !USE_SERIAL_1_SW_FLOW || USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW || USE_SERIAL_3_FLOW && !USE_SERIAL_3_SW_FLOW
+#define HAS_SERIAL_HW_FLOW 1
+#else
+#define HAS_SERIAL_HW_FLOW 0
+#endif
+
/* ao_serial_stm.c */
struct ao_stm_usart {
struct ao_fifo rx_fifo;
struct ao_fifo tx_fifo;
struct stm_usart *reg;
- uint8_t tx_started;
+ uint8_t tx_running;
+ uint8_t draining;
+#if HAS_SERIAL_SW_FLOW
+ /* RTS - 0 if we have FIFO space, 1 if not
+ * CTS - 0 if we can send, 0 if not
+ */
+ struct stm_gpio *gpio_rts;
+ struct stm_gpio *gpio_cts;
+ uint8_t pin_rts;
+ uint8_t pin_cts;
+ uint8_t rts;
+#endif
};
#if HAS_SERIAL_1
#define HAS_SAMPLE_PROFILE 0
#endif
+#if DEBUG
+#define HAS_ARCH_VALIDATE_CUR_STACK 1
+
+static inline void
+ao_validate_cur_stack(void)
+{
+ uint8_t *psp;
+
+ asm("mrs %0,psp" : "=&r" (psp));
+ if (ao_cur_task &&
+ psp <= ao_cur_task->stack &&
+ psp >= ao_cur_task->stack - 256)
+ ao_panic(AO_PANIC_STACK);
+}
+#endif
+
#if !HAS_SAMPLE_PROFILE
#define HAS_ARCH_START_SCHEDULER 1
+++ /dev/null
-/*
- * Copyright © 2013 Keith Packard <keithp@keithp.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * 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, write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#ifndef _AO_FAST_TIMER_H_
-#define _AO_FAST_TIMER_H_
-
-void
-ao_fast_timer_init(void);
-
-#ifndef AO_FAST_TIMER_MAX
-#define AO_FAST_TIMER_MAX 2
-#endif
-
-void
-ao_fast_timer_on(void (*callback)(void));
-
-void
-ao_fast_timer_off(void (*callback)(void));
-
-#endif /* _AO_FAST_TIMER_H_ */
*/
#include <ao.h>
+#include <ao_exti.h>
void
ao_debug_out(char c)
stm_usart1.dr = c;
}
-static void
+static int
_ao_usart_tx_start(struct ao_stm_usart *usart)
{
- if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started)
- {
- usart->tx_started = 1;
- ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+ if (!ao_fifo_empty(usart->tx_fifo)) {
+#if HAS_SERIAL_SW_FLOW
+ if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts, foo) == 1) {
+ ao_exti_enable(usart->gpio_cts, usart->pin_cts);
+ return 0;
+ }
+#endif
+ if (usart->reg->sr & (1 << STM_USART_SR_TXE))
+ {
+ usart->tx_running = 1;
+ usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE);
+ ao_fifo_remove(usart->tx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->tx_fifo);
+ return 1;
+ }
}
+ return 0;
}
+#if HAS_SERIAL_SW_FLOW
static void
-ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+_ao_usart_cts(struct ao_stm_usart *usart)
{
- uint32_t sr;
-
- sr = usart->reg->sr;
- usart->reg->sr = 0;
+ if (_ao_usart_tx_start(usart))
+ ao_exti_disable(usart->gpio_cts, usart->pin_cts);
+}
+#endif
- if (sr & (1 << STM_USART_SR_RXNE)) {
- char c = usart->reg->dr;
- if (!ao_fifo_full(usart->rx_fifo))
- ao_fifo_insert(usart->rx_fifo, c);
- ao_wakeup(&usart->rx_fifo);
- if (stdin)
- ao_wakeup(&ao_stdin_ready);
+static void
+_ao_usart_rx(struct ao_stm_usart *usart, int stdin)
+{
+ if (usart->reg->sr & (1 << STM_USART_SR_RXNE)) {
+ if (!ao_fifo_full(usart->rx_fifo)) {
+ ao_fifo_insert(usart->rx_fifo, usart->reg->dr);
+ ao_wakeup(&usart->rx_fifo);
+ if (stdin)
+ ao_wakeup(&ao_stdin_ready);
+#if HAS_SERIAL_SW_FLOW
+ /* If the fifo is nearly full, turn off RTS and wait
+ * for it to drain a bunch
+ */
+ if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, usart->pin_rts, 1);
+ usart->rts = 0;
+ }
+#endif
+ } else {
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE);
+ }
}
- if (sr & (1 << STM_USART_SR_TC)) {
- usart->tx_started = 0;
- _ao_usart_tx_start(usart);
- ao_wakeup(&usart->tx_fifo);
+}
+
+static void
+ao_usart_isr(struct ao_stm_usart *usart, int stdin)
+{
+ _ao_usart_rx(usart, stdin);
+
+ if (!_ao_usart_tx_start(usart))
+ usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE);
+
+ if (usart->reg->sr & (1 << STM_USART_SR_TC)) {
+ usart->tx_running = 0;
+ usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE);
+ if (usart->draining) {
+ usart->draining = 0;
+ ao_wakeup(&usart->tx_fifo);
+ }
}
}
-int
+static int
_ao_usart_pollchar(struct ao_stm_usart *usart)
{
int c;
else {
uint8_t u;
ao_fifo_remove(usart->rx_fifo,u);
+ if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) {
+ if (ao_fifo_barely(usart->rx_fifo))
+ usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE);
+ }
+#if HAS_SERIAL_SW_FLOW
+ /* If we've cleared RTS, check if there's space now and turn it back on */
+ if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) {
+ ao_gpio_set(usart->gpio_rts, usart->pin_rts, foo, 0);
+ usart->rts = 1;
+ }
+#endif
c = u;
}
return c;
}
-char
+static char
ao_usart_getchar(struct ao_stm_usart *usart)
{
int c;
return ao_sleep_for(&usart->rx_fifo, timeout);
}
-void
+static void
ao_usart_putchar(struct ao_stm_usart *usart, char c)
{
ao_arch_block_interrupts();
ao_arch_release_interrupts();
}
-void
+static void
ao_usart_drain(struct ao_stm_usart *usart)
{
ao_arch_block_interrupts();
- while (!ao_fifo_empty(usart->tx_fifo))
+ while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) {
+ usart->draining = 1;
ao_sleep(&usart->tx_fifo);
+ }
ao_arch_release_interrupts();
}
},
};
-void
+static void
ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed)
{
if (speed > AO_SERIAL_SPEED_115200)
usart->reg->brr = ao_usart_speeds[speed].brr;
}
-void
+static void
ao_usart_init(struct ao_stm_usart *usart)
{
usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) |
(0 << STM_USART_CR1_PS) |
(0 << STM_USART_CR1_PEIE) |
(0 << STM_USART_CR1_TXEIE) |
- (1 << STM_USART_CR1_TCIE) |
+ (0 << STM_USART_CR1_TCIE) |
(1 << STM_USART_CR1_RXNEIE) |
(0 << STM_USART_CR1_IDLEIE) |
(1 << STM_USART_CR1_TE) |
ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
}
-void
+#if HAS_SERIAL_HW_FLOW
+static void
ao_usart_set_flow(struct ao_stm_usart *usart)
{
usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
(1 << STM_USART_CR3_RTSE));
}
+#endif
#if HAS_SERIAL_1
void
ao_serial1_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart1);
ao_usart_set_speed(&ao_stm_usart1, speed);
}
#endif /* HAS_SERIAL_1 */
void
ao_serial2_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart2);
ao_usart_set_speed(&ao_stm_usart2, speed);
}
+
+#if HAS_SERIAL_SW_FLOW
+void
+ao_serial2_cts(void)
+{
+ _ao_usart_cts(&ao_stm_usart2);
+}
+#endif
+
#endif /* HAS_SERIAL_2 */
#if HAS_SERIAL_3
struct ao_stm_usart ao_stm_usart3;
-void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); }
+void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); }
char
ao_serial3_getchar(void)
void
ao_serial3_set_speed(uint8_t speed)
{
+ ao_usart_drain(&ao_stm_usart3);
ao_usart_set_speed(&ao_stm_usart3, speed);
}
+
+void
+ao_serial3_drain(void)
+{
+ ao_usart_drain(&ao_stm_usart3);
+}
#endif /* HAS_SERIAL_3 */
+#if HAS_SERIAL_SW_FLOW
+static void
+ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart,
+ void (*isr)(void),
+ struct stm_gpio *port_rts,
+ int pin_rts,
+ struct stm_gpio *port_cts,
+ int pin_cts)
+{
+ /* Pull RTS low to note that there's space in the FIFO
+ */
+ ao_enable_output(port_rts, pin_rts, foo, 0);
+ usart->gpio_rts = port_rts;
+ usart->pin_rts = pin_rts;
+ usart->rts = 1;
+
+ ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr);
+ usart->gpio_cts = port_cts;
+ usart->pin_cts = pin_cts;
+}
+#endif
+
void
ao_serial_init(void)
{
stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7);
stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7);
-#if USE_SERIAL_2_FLOW
+# if USE_SERIAL_2_FLOW
+# if USE_SERIAL_2_SW_FLOW
+ ao_serial_set_sw_rts_cts(&ao_stm_usart2,
+ ao_serial2_cts,
+ SERIAL_2_PORT_RTS,
+ SERIAL_2_PIN_RTS,
+ SERIAL_2_PORT_CTS,
+ SERIAL_2_PIN_CTS);
+# else
stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7);
stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7);
-#endif
+# endif
+# endif
#else
#if SERIAL_2_PD5_PD6
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
ao_stm_usart2.reg = &stm_usart2;
ao_usart_init(&ao_stm_usart2);
-#if USE_SERIAL_2_FLOW
+#if USE_SERIAL_2_FLOW && !USE_SERIAL_2_SW_FLOW
ao_usart_set_flow(&ao_stm_usart2);
#endif
void stm_systick_isr(void)
{
+ ao_validate_cur_stack();
if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
++ao_tick_count;
#if HAS_TASK_QUEUE
gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);
}
+static inline void
+stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = bits;
+}
+
+static inline void
+stm_gpio_clr_bits(struct stm_gpio *gpio, uint16_t bits) {
+ gpio->bsrr = ((uint32_t) bits) << 16;
+}
+
static inline uint8_t
stm_gpio_get(struct stm_gpio *gpio, int pin) {
return (gpio->idr >> pin) & 1;
PROGNAME=altos-flash
PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
+BIN=$(HARDWARE)-$(PROGNAME)-$(VERSION).bin
+
+MAKEBIN=$(TOPDIR)/../ao-tools/ao-makebin/ao-makebin
+FLASH_ADDR=0x08000000
+
+all: $(PROG) $(BIN)
$(PROG): Makefile $(OBJ) altos-loader.ld
$(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+$(BIN): $(PROG)
+ $(MAKEBIN) --output=$@ --base=$(FLASH_ADDR) $(PROG)
+
ao_product.h: ao-make-product.5c $(TOPDIR)/Version
$(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
$(OBJ): $(INC)
-all: $(PROG)
-
distclean: clean
clean:
(1 << STM_DMA_CCR_MINC) |
(0 << STM_DMA_CCR_PINC) |
(0 << STM_DMA_CCR_CIRC) |
- (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR));
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
ao_adc_init(void)
{
uint32_t chselr;
- int i;
/* Reset ADC */
stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST);
/* Shortest sample time */
stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP;
+ /* Turn off enable and start */
+ stm_adc.cr &= ~((1 << STM_ADC_CR_ADEN) | (1 << STM_ADC_CR_ADSTART));
+
/* Calibrate */
stm_adc.cr |= (1 << STM_ADC_CR_ADCAL);
- for (i = 0; i < 0xf000; i++) {
- if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0)
- break;
- }
+ while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0)
+ ;
/* Enable */
stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
* STM32F0 definitions and code fragments for AltOS
*/
+#ifndef AO_STACK_SIZE
#define AO_STACK_SIZE 512
+#endif
#define AO_LED_TYPE uint16_t
#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER)
#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER)
#define AO_SYSTICK (AO_HCLK)
+#define AO_PANIC_DELAY_SCALE (AO_SYSCLK / 12000000)
#if AO_APB1_PRESCALER == 1
#define AO_TIM23467_CLK AO_PCLK1
#define AO_TIM91011_CLK (2 * AO_PCLK2)
#endif
-#define AO_STM_NVIC_HIGH_PRIORITY 4
-#define AO_STM_NVIC_CLOCK_PRIORITY 6
-#define AO_STM_NVIC_MED_PRIORITY 8
-#define AO_STM_NVIC_LOW_PRIORITY 10
+#define AO_STM_NVIC_HIGH_PRIORITY (0 << 6)
+#define AO_STM_NVIC_CLOCK_PRIORITY (1 << 6)
+#define AO_STM_NVIC_MED_PRIORITY (2 << 6)
+#define AO_STM_NVIC_LOW_PRIORITY (3 << 6)
void ao_lcd_stm_init(void);
#ifndef _AO_ARCH_FUNCS_H_
#define _AO_ARCH_FUNCS_H_
+#include <ao_power.h>
+
/* ao_spi_stm.c
*/
-/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
+/* PCLK is set to 48MHz (HCLK 48MHz, HPRE 1, PPRE 1) */
-#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2
-#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4
-#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8
-#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16
-#define AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32
-#define AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64
-#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128
-#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256
+#define AO_SPI_SPEED_24MHz STM_SPI_CR1_BR_PCLK_2
+#define AO_SPI_SPEED_12MHz STM_SPI_CR1_BR_PCLK_4
+#define AO_SPI_SPEED_6MHz STM_SPI_CR1_BR_PCLK_8
+#define AO_SPI_SPEED_3MHz STM_SPI_CR1_BR_PCLK_16
+#define AO_SPI_SPEED_1500kHz STM_SPI_CR1_BR_PCLK_32
+#define AO_SPI_SPEED_750kHz STM_SPI_CR1_BR_PCLK_64
+#define AO_SPI_SPEED_375kHz STM_SPI_CR1_BR_PCLK_128
+#define AO_SPI_SPEED_187500Hz STM_SPI_CR1_BR_PCLK_256
-#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz
+#define AO_SPI_SPEED_FAST AO_SPI_SPEED_24MHz
/* Companion bus wants something no faster than 200kHz */
-#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz
+#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_187500Hz
#define AO_SPI_CONFIG_1 0x00
#define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1
#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<bit),bus,speed)
#define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
-#define ao_enable_port(port) do { \
- if ((port) == &stm_gpioa) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \
- else if ((port) == &stm_gpiob) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \
- else if ((port) == &stm_gpioc) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \
- else if ((port) == &stm_gpiof) \
- stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \
- } while (0)
+extern struct ao_power ao_power_gpioa;
+extern struct ao_power ao_power_gpiob;
+extern struct ao_power ao_power_gpioc;
+extern struct ao_power ao_power_gpiof;
-#define ao_disable_port(port) do { \
- if ((port) == &stm_gpioa) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \
- else if ((port) == &stm_gpiob) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \
- else if ((port) == &stm_gpioc) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \
- else if ((port) == &stm_gpiof) \
- stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \
- } while (0)
+static inline void ao_enable_port(struct stm_gpio *port)
+{
+ if ((port) == &stm_gpioa) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ ao_power_register(&ao_power_gpioa);
+ } else if ((port) == &stm_gpiob) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ ao_power_register(&ao_power_gpiob);
+ } else if ((port) == &stm_gpioc) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+ ao_power_register(&ao_power_gpioc);
+ } else if ((port) == &stm_gpiof) {
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+ ao_power_register(&ao_power_gpiof);
+ }
+}
+
+static inline void ao_disable_port(struct stm_gpio *port)
+{
+ if ((port) == &stm_gpioa) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+ ao_power_unregister(&ao_power_gpioa);
+ } else if ((port) == &stm_gpiob) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+ ao_power_unregister(&ao_power_gpiob);
+ } else if ((port) == &stm_gpioc) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+ ao_power_unregister(&ao_power_gpioc);
+ } else if ((port) == &stm_gpiof) {
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+ ao_power_unregister(&ao_power_gpiof);
+ }
+}
#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
} while (0)
#define ao_enable_cs(port,bit) do { \
- stm_gpio_set((port), bit, 1); \
- stm_moder_set((port), bit, STM_MODER_OUTPUT); \
+ ao_enable_output(port, bit, pin, 1); \
} while (0)
#define ao_spi_init_cs(port, mask) do { \
void
ao_usb_write(uint16_t *buffer, uint16_t len);
+
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len);
#endif /* AO_USB_DIRECTIO */
#endif /* _AO_ARCH_FUNCS_H_ */
static uint8_t ao_dma_mutex[STM_NUM_DMA];
static uint8_t ao_dma_active;
-#define id(ch) STM_DMA_INDEX(ch)
-#define id_mask(id) (STM_DMA_ISR_MASK << (id))
-#define ch_mask(ch) id_mask(id(ch))
+#define ch_mask(id) (STM_DMA_ISR_MASK << STM_DMA_ISR(id))
static void
ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
/* Ack them */
stm_dma.ifcr = isr;
for (index = low_index; index <= high_index; index++) {
- if (isr & id_mask(index)) {
+ if (isr & ch_mask(index)) {
if (ao_dma_config[index].isr)
(*ao_dma_config[index].isr)(index);
else {
}
}
-void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); }
-void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); }
-void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); }
+void stm_dma_ch1_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(1),
+ STM_DMA_INDEX(1),
+ ch_mask(STM_DMA_INDEX(1)));
+}
+
+void stm_dma_ch2_3_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(2),
+ STM_DMA_INDEX(3),
+ ch_mask(STM_DMA_INDEX(2)) |
+ ch_mask(STM_DMA_INDEX(3)));
+}
+
+void stm_dma1_ch4_5_6_isr(void) {
+ ao_dma_isr(STM_DMA_INDEX(4), STM_DMA_INDEX(6),
+ ch_mask(STM_DMA_INDEX(4)) |
+ ch_mask(STM_DMA_INDEX(5)) |
+ ch_mask(STM_DMA_INDEX(6)));
+}
void
ao_dma_set_transfer(uint8_t index,
if (ao_dma_active++ == 0)
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);
);
- stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+ ao_dma_config[index].isr = NULL;
+ ao_dma_done[index] = 0;
stm_dma.channel[index].cndtr = count;
stm_dma.channel[index].cpar = peripheral;
stm_dma.channel[index].cmar = memory;
- ao_dma_config[index].isr = NULL;
+ stm_dma.channel[index].ccr = ccr;
}
void
void
ao_dma_start(uint8_t index)
{
- ao_dma_done[index] = 0;
stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
}
#define AO_EXTI_PIN_NOCONFIGURE 64
void
-ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)());
+ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void));
void
ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode);
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+
+static void (*ao_exti_callback[16])(void);
+
+uint32_t ao_last_exti;
+
+static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) {
+ uint16_t pending = (ao_last_exti = stm_exti.pr) & mask;
+ uint8_t pin;
+ static uint16_t last_mask;
+ static uint8_t last_pin;
+
+ if (pending == last_mask) {
+ stm_exti.pr = last_mask;
+ (*ao_exti_callback[last_pin])();
+ return;
+ }
+ stm_exti.pr = pending;
+ for (pin = first; pin <= last; pin++)
+ if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) {
+ last_mask = (1 << pin);
+ last_pin = pin;
+ (*ao_exti_callback[pin])();
+ }
+}
+
+void stm_exti0_1_isr(void) { ao_exti_range_isr(0, 1, 0x0003); }
+void stm_exti2_3_isr(void) { ao_exti_range_isr(2, 3, 0x000c); }
+void stm_exti4_15_isr(void) { ao_exti_range_isr(4, 15, 0xfff0); }
+
+void
+ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) {
+ uint32_t mask = 1 << pin;
+ uint32_t pupdr;
+ uint8_t irq;
+ uint8_t prio;
+
+ ao_exti_callback[pin] = callback;
+
+ /* configure gpio to interrupt routing */
+ stm_exticr_set(gpio, pin);
+
+ if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) {
+ /* configure pin as input, setting selected pull-up/down mode */
+ stm_moder_set(gpio, pin, STM_MODER_INPUT);
+ switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) {
+ case 0:
+ default:
+ pupdr = STM_PUPDR_NONE;
+ break;
+ case AO_EXTI_MODE_PULL_UP:
+ pupdr = STM_PUPDR_PULL_UP;
+ break;
+ case AO_EXTI_MODE_PULL_DOWN:
+ pupdr = STM_PUPDR_PULL_DOWN;
+ break;
+ }
+ stm_pupdr_set(gpio, pin, pupdr);
+ }
+
+ /* Set interrupt mask and rising/falling mode */
+ stm_exti.imr &= ~mask;
+ if (mode & AO_EXTI_MODE_RISING)
+ stm_exti.rtsr |= mask;
+ else
+ stm_exti.rtsr &= ~mask;
+ if (mode & AO_EXTI_MODE_FALLING)
+ stm_exti.ftsr |= mask;
+ else
+ stm_exti.ftsr &= ~mask;
+
+ if (pin <= 1)
+ irq = STM_ISR_EXTI0_1_POS;
+ else if (pin <= 3)
+ irq = STM_ISR_EXTI2_3_POS;
+ else
+ irq = STM_ISR_EXTI4_15_POS;
+
+ /* Set priority */
+ prio = AO_STM_NVIC_MED_PRIORITY;
+ if (mode & AO_EXTI_PRIORITY_LOW)
+ prio = AO_STM_NVIC_LOW_PRIORITY;
+ else if (mode & AO_EXTI_PRIORITY_HIGH)
+ prio = AO_STM_NVIC_HIGH_PRIORITY;
+
+ stm_nvic_set_priority(irq, prio);
+ stm_nvic_set_enable(irq);
+}
+
+void
+ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) {
+ (void) gpio;
+
+ uint32_t mask = 1 << pin;
+
+ if (mode & AO_EXTI_MODE_RISING)
+ stm_exti.rtsr |= mask;
+ else
+ stm_exti.rtsr &= ~mask;
+ if (mode & AO_EXTI_MODE_FALLING)
+ stm_exti.ftsr |= mask;
+ else
+ stm_exti.ftsr &= ~mask;
+}
+
+void
+ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) {
+ (void) gpio;
+ ao_exti_callback[pin] = callback;
+}
+
+void
+ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) {
+ uint32_t mask = (1 << pin);
+ (void) gpio;
+ stm_exti.pr = mask;
+ stm_exti.imr |= (1 << pin);
+}
+
+void
+ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) {
+ uint32_t mask = (1 << pin);
+ (void) gpio;
+ stm_exti.imr &= ~mask;
+ stm_exti.pr = mask;
+}
+
+void
+ao_exti_init(void)
+{
+}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+
+static void
+ao_gpio_suspend(void *arg)
+{
+ struct stm_gpio *port = arg;
+ if (port == &stm_gpioa)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN);
+ else if ((port) == &stm_gpiob)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN);
+ else if ((port) == &stm_gpioc)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN);
+ else if ((port) == &stm_gpiof)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+static void
+ao_gpio_resume(void *arg)
+{
+ struct stm_gpio *port = arg;
+ if (port == &stm_gpioa)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ else if ((port) == &stm_gpiob)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ else if ((port) == &stm_gpioc)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN);
+ else if ((port) == &stm_gpiof)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN);
+}
+
+struct ao_power ao_power_gpioa = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpioa
+};
+
+struct ao_power ao_power_gpiob = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpiob
+};
+
+struct ao_power ao_power_gpioc = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpioc
+};
+
+struct ao_power ao_power_gpiof = {
+ .suspend = ao_gpio_suspend,
+ .resume = ao_gpio_resume,
+ .arg = &stm_gpiof
+};
+
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include "ao_pwm.h"
+
+static uint8_t pwm_running;
+
+static uint16_t pwm_value[NUM_PWM];
+
+static void
+ao_pwm_up(void)
+{
+ if (pwm_running++ == 0) {
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ tim->ccr1 = 0;
+ tim->ccr2 = 0;
+ tim->ccr3 = 0;
+ tim->ccr4 = 0;
+ tim->arr = PWM_MAX - 1; /* turn on the timer */
+ tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+ (0 << STM_TIM23_CR1_ARPE) |
+ (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+ (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+ (0 << STM_TIM23_CR1_OPM) |
+ (0 << STM_TIM23_CR1_URS) |
+ (0 << STM_TIM23_CR1_UDIS) |
+ (1 << STM_TIM23_CR1_CEN));
+
+ /* Set the timer running */
+ tim->egr = (1 << STM_TIM23_EGR_UG);
+ }
+}
+
+static void
+ao_pwm_down(void)
+{
+ if (--pwm_running == 0) {
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ tim->arr = 0;
+ tim->cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) |
+ (0 << STM_TIM23_CR1_ARPE) |
+ (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) |
+ (STM_TIM23_CR1_DIR_UP << STM_TIM23_CR1_DIR) |
+ (0 << STM_TIM23_CR1_OPM) |
+ (0 << STM_TIM23_CR1_URS) |
+ (0 << STM_TIM23_CR1_UDIS) |
+ (0 << STM_TIM23_CR1_CEN));
+
+ /* Stop the timer */
+ tim->egr = (1 << STM_TIM23_EGR_UG);
+ }
+}
+
+void
+ao_pwm_set(uint8_t pwm, uint16_t value)
+{
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+ uint8_t ch = AO_PWM_0_CH;
+
+ if (value > PWM_MAX)
+ value = PWM_MAX;
+ if (value != 0) {
+ if (pwm_value[pwm] == 0)
+ ao_pwm_up();
+ }
+#if NUM_PWM > 1
+ switch (pwm) {
+ case 0:
+ ch = AO_PWM_0_CH;
+ break;
+ case 1:
+ ch = AO_PWM_0_CH;
+ break;
+#if NUM_PWM > 2
+ case 2:
+ ch = AO_PWM_0_CH;
+ break;
+#endif
+#if NUM_PWM > 3
+ case 3:
+ ch = AO_PWM_0_CH;
+ break;
+#endif
+ }
+#endif
+
+ switch (ch) {
+ case 1:
+ tim->ccr1 = value;
+ break;
+ case 2:
+ tim->ccr2 = value;
+ break;
+ case 3:
+ tim->ccr3 = value;
+ break;
+ case 4:
+ tim->ccr4 = value;
+ break;
+ }
+ if (value == 0) {
+ if (pwm_value[pwm] != 0)
+ ao_pwm_down();
+ }
+ pwm_value[pwm] = value;
+}
+
+static void
+ao_pwm_cmd(void)
+{
+ uint8_t ch;
+ uint16_t val;
+
+ ao_cmd_decimal();
+ ch = ao_cmd_lex_u32;
+ ao_cmd_decimal();
+ val = ao_cmd_lex_u32;
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+
+ printf("Set channel %d to %d\n", ch, val);
+ ao_pwm_set(ch, val);
+}
+
+static const struct ao_cmds ao_pwm_cmds[] = {
+ { ao_pwm_cmd, "P <ch> <val>\0Set PWM ch to val" },
+ { 0, NULL },
+};
+
+void
+ao_pwm_init(void)
+{
+ struct stm_tim23 *tim = AO_PWM_TIMER;
+
+ stm_rcc.apb1enr |= (1 << AO_PWM_TIMER_ENABLE);
+
+ tim->cr1 = 0;
+ tim->psc = AO_PWM_TIMER_SCALE - 1;
+ tim->cnt = 0;
+ tim->ccer = ((1 << STM_TIM23_CCER_CC1E) |
+ (0 << STM_TIM23_CCER_CC1P) |
+ (1 << STM_TIM23_CCER_CC2E) |
+ (0 << STM_TIM23_CCER_CC2P) |
+ (1 << STM_TIM23_CCER_CC3E) |
+ (0 << STM_TIM23_CCER_CC3P) |
+ (1 << STM_TIM23_CCER_CC4E) |
+ (0 << STM_TIM23_CCER_CC4P));
+
+ tim->ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) |
+ (STM_TIM23_CCMR1_OC2M_PWM_MODE_1 << STM_TIM23_CCMR1_OC2M) |
+ (0 << STM_TIM23_CCMR1_OC2PE) |
+ (0 << STM_TIM23_CCMR1_OC2FE) |
+ (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) |
+
+ (0 << STM_TIM23_CCMR1_OC1CE) |
+ (STM_TIM23_CCMR1_OC1M_PWM_MODE_1 << STM_TIM23_CCMR1_OC1M) |
+ (0 << STM_TIM23_CCMR1_OC1PE) |
+ (0 << STM_TIM23_CCMR1_OC1FE) |
+ (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S));
+
+
+ tim->ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) |
+ (STM_TIM23_CCMR2_OC4M_PWM_MODE_1 << STM_TIM23_CCMR2_OC4M) |
+ (0 << STM_TIM23_CCMR2_OC4PE) |
+ (0 << STM_TIM23_CCMR2_OC4FE) |
+ (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) |
+
+ (0 << STM_TIM23_CCMR2_OC3CE) |
+ (STM_TIM23_CCMR2_OC3M_PWM_MODE_1 << STM_TIM23_CCMR2_OC3M) |
+ (0 << STM_TIM23_CCMR2_OC3PE) |
+ (0 << STM_TIM23_CCMR2_OC3FE) |
+ (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S));
+ tim->egr = 0;
+
+ tim->sr = 0;
+ tim->dier = 0;
+ tim->smcr = 0;
+ tim->cr2 = ((0 << STM_TIM23_CR2_TI1S) |
+ (STM_TIM23_CR2_MMS_RESET<< STM_TIM23_CR2_MMS) |
+ (0 << STM_TIM23_CR2_CCDS));
+
+ stm_afr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_0_GPIO, AO_PWM_0_PIN, STM_OSPEEDR_MEDIUM);
+#if NUM_PWM > 1
+ stm_afr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_1_GPIO, AO_PWM_1_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 2
+ stm_afr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_2_GPIO, AO_PWM_2_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+#if NUM_PWM > 3
+ stm_afr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_AFR_AF1);
+ stm_ospeedr_set(AO_PWM_3_GPIO, AO_PWM_3_PIN, STM_OSPEEDR_MEDIUM);
+#endif
+ ao_cmd_register(&ao_pwm_cmds[0]);
+}
--- /dev/null
+/*
+ * Copyright © 2016 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+
+struct ao_spi_stm_info {
+ uint8_t miso_dma_index;
+ uint8_t mosi_dma_index;
+ struct stm_spi *stm_spi;
+};
+
+static uint8_t ao_spi_mutex[STM_NUM_SPI];
+static uint8_t ao_spi_index[STM_NUM_SPI];
+
+static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = {
+ {
+ .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX),
+ .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX),
+ &stm_spi1
+ },
+ {
+ .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX),
+ .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX),
+ &stm_spi2
+ }
+};
+
+static uint8_t spi_dev_null;
+
+
+
+#define SPI_CR2 ((0 << STM_SPI_CR2_LDMA_TX) | \
+ (0 << STM_SPI_CR2_LDMA_RX) | \
+ (1 << STM_SPI_CR2_FRXTH) | \
+ (STM_SPI_CR2_DS_8 << STM_SPI_CR2_DS) | \
+ (0 << STM_SPI_CR2_TXEIE) | \
+ (0 << STM_SPI_CR2_RXNEIE) | \
+ (0 << STM_SPI_CR2_ERRIE) | \
+ (STM_SPI_CR2_FRF_MOTOROLA << STM_SPI_CR2_FRF) | \
+ (0 << STM_SPI_CR2_NSSP) | \
+ (0 << STM_SPI_CR2_SSOE))
+
+#define SPI_CR2_DMA (SPI_CR2 | \
+ (1 << STM_SPI_CR2_TXDMAEN) | \
+ (1 << STM_SPI_CR2_RXDMAEN))
+
+#define SPI_CR2_SYNC (SPI_CR2 | \
+ (0 << STM_SPI_CR2_TXDMAEN) | \
+ (0 << STM_SPI_CR2_RXDMAEN))
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up the transmit DMA to deliver data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ (void *) block,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA -- when this is done, we know the SPI unit
+ * is idle. Without this, we'd have to poll waiting for the BSY bit to
+ * be cleared
+ */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up the transmit DMA to deliver data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ &value,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA -- when this is done, we know the SPI unit
+ * is idle. Without this, we'd have to poll waiting for the BSY bit to
+ * be cleared
+ */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index)
+{
+ uint8_t *b = block;
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+
+ stm_spi->cr2 = SPI_CR2_SYNC;
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ while (len--) {
+ while (!(stm_spi->sr & (1 << STM_SPI_SR_TXE)));
+ stm_spi->dr = *b++;
+ }
+}
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ spi_dev_null = 0xff;
+
+ /* Set up transmit DMA to make the SPI hardware actually run */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ &spi_dev_null,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (0 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA to capture data */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ block,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ /* Wait until the SPI unit is done */
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index)
+{
+ struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi;
+ uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index;
+ uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index;
+
+ /* Set up transmit DMA to send data */
+ ao_dma_set_transfer(mosi_dma_index,
+ &stm_spi->dr,
+ out,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR) |
+ (0 << STM_DMA_CCR_TCIE));
+
+ /* Clear RXNE */
+ (void) stm_spi->dr;
+
+ /* Set up the receive DMA to capture data */
+ ao_dma_set_transfer(miso_dma_index,
+ &stm_spi->dr,
+ in,
+ len,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) |
+ (1 << STM_DMA_CCR_MINC) |
+ (0 << STM_DMA_CCR_PINC) |
+ (0 << STM_DMA_CCR_CIRC) |
+ (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR) |
+ (1 << STM_DMA_CCR_TCIE));
+
+ stm_spi->cr2 = SPI_CR2_DMA;
+ ao_dma_start(miso_dma_index);
+ ao_dma_start(mosi_dma_index);
+
+ /* Wait until the SPI unit is done */
+ ao_arch_critical(
+ while (!ao_dma_done[miso_dma_index])
+ ao_sleep(&ao_dma_done[miso_dma_index]);
+ );
+
+ ao_dma_done_transfer(mosi_dma_index);
+ ao_dma_done_transfer(miso_dma_index);
+}
+
+static void
+ao_spi_disable_index(uint8_t spi_index)
+{
+ /* Disable current config
+ */
+ switch (AO_SPI_INDEX(spi_index)) {
+ case STM_SPI_INDEX(1):
+ switch (spi_index) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_gpio_set(&stm_gpioa, 5, 1);
+ stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT);
+ break;
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_gpio_set(&stm_gpiob, 3, 1);
+ stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT);
+ break;
+ }
+ break;
+ case STM_SPI_INDEX(2):
+ switch (spi_index) {
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_gpio_set(&stm_gpiob, 13, 1);
+ stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT);
+ stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT);
+ stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT);
+ break;
+ }
+ break;
+ }
+}
+
+static void
+ao_spi_enable_index(uint8_t spi_index)
+{
+ switch (AO_SPI_INDEX(spi_index)) {
+ case STM_SPI_INDEX(1):
+ switch (spi_index) {
+ case AO_SPI_1_PA5_PA6_PA7:
+ stm_afr_set(&stm_gpioa, 5, STM_AFR_AF0);
+ stm_afr_set(&stm_gpioa, 6, STM_AFR_AF0);
+ stm_afr_set(&stm_gpioa, 7, STM_AFR_AF0);
+ break;
+ case AO_SPI_1_PB3_PB4_PB5:
+ stm_afr_set(&stm_gpiob, 3, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 4, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 5, STM_AFR_AF0);
+ break;
+ }
+ break;
+ case STM_SPI_INDEX(2):
+ switch (spi_index) {
+ case AO_SPI_2_PB13_PB14_PB15:
+ stm_afr_set(&stm_gpiob, 13, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 14, STM_AFR_AF0);
+ stm_afr_set(&stm_gpiob, 15, STM_AFR_AF0);
+ break;
+ }
+ break;
+ }
+}
+
+static void
+ao_spi_config(uint8_t spi_index, uint32_t speed)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ stm_spi->cr2 = SPI_CR2;
+ stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */
+ (0 << STM_SPI_CR1_BIDIOE) |
+ (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */
+ (0 << STM_SPI_CR1_CRCNEXT) |
+ (0 << STM_SPI_CR1_CRCL) |
+ (0 << STM_SPI_CR1_RXONLY) |
+ (1 << STM_SPI_CR1_SSM) | /* Software SS handling */
+ (1 << STM_SPI_CR1_SSI) | /* ... */
+ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */
+ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */
+ (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */
+ (1 << STM_SPI_CR1_MSTR) |
+ (0 << STM_SPI_CR1_CPOL) | /* Format 0 */
+ (0 << STM_SPI_CR1_CPHA));
+
+ if (spi_index != ao_spi_index[id]) {
+
+ /* Disable old config
+ */
+ ao_spi_disable_index(ao_spi_index[id]);
+
+ /* Enable new config
+ */
+ ao_spi_enable_index(spi_index);
+
+ /* Remember current config
+ */
+ ao_spi_index[id] = spi_index;
+ }
+}
+
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+
+ if (!ao_mutex_try(&ao_spi_mutex[id], task_id))
+ return 0;
+ ao_spi_config(spi_index, speed);
+ return 1;
+}
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ ao_mutex_get(&ao_spi_mutex[id]);
+ ao_spi_config(spi_index, speed);
+}
+
+void
+ao_spi_put(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ stm_spi->cr1 = 0;
+ ao_mutex_put(&ao_spi_mutex[id]);
+}
+
+static void
+ao_spi_channel_init(uint8_t spi_index)
+{
+ uint8_t id = AO_SPI_INDEX(spi_index);
+ struct stm_spi *stm_spi = ao_spi_stm_info[id].stm_spi;
+
+ ao_spi_disable_index(spi_index);
+
+ stm_spi->cr1 = 0;
+ (void) stm_spi->sr;
+ stm_spi->cr2 = SPI_CR2_SYNC;
+}
+
+void
+ao_spi_init(void)
+{
+#if HAS_SPI_1
+# if SPI_1_PA5_PA6_PA7
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN);
+ stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
+# endif
+# if SPI_1_PB3_PB4_PB5
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
+# endif
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
+ ao_spi_index[0] = AO_SPI_CONFIG_NONE;
+ ao_spi_channel_init(STM_SPI_INDEX(1));
+#endif
+
+#if HAS_SPI_2
+# if SPI_2_PB10_PB13_PB14
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN);
+ stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
+# endif
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
+ ao_spi_index[1] = AO_SPI_CONFIG_NONE;
+ ao_spi_channel_init(STM_SPI_INDEX(2));
+#endif
+}
#if AO_DATA_ALL
if (++ao_data_count == ao_data_interval) {
ao_data_count = 0;
+#if HAS_ADC
#if HAS_FAKE_FLIGHT
if (ao_fake_flight_active)
ao_fake_flight_poll();
else
#endif
ao_adc_poll();
+#endif
#if (AO_DATA_ALL & ~(AO_DATA_ADC))
ao_wakeup((void *) &ao_data_count);
#endif
#endif
+#if AO_HSI48
static void
ao_clock_enable_crs(void)
{
(0 << STM_CRS_CR_ERRIE) |
(0 << STM_CRS_CR_SYNCWARNIE) |
(0 << STM_CRS_CR_SYNCOKIE));
-
}
+#endif
-void
-ao_clock_init(void)
+static void
+ao_clock_hsi(void)
{
- uint32_t cfgr;
-
- /* Switch to HSI while messing about */
stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
ao_arch_nop();
/* reset PLLON, CSSON, HSEBYP, HSEON */
stm_rcc.cr &= 0x0000ffff;
+}
- /* Disable all interrupts */
- stm_rcc.cir = 0;
-
+static void
+ao_clock_normal_start(void)
+{
#if AO_HSE
-#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSE
-#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSE
+ uint32_t cfgr;
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_PLL
+#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_PLL
#define STM_PLLSRC AO_HSE
-#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 1
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK STM_RCC_CFGR_PLLSRC_HSE
#if AO_HSE_BYPASS
stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP);
stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
asm("nop");
+
+#ifdef STM_PLLSRC
+ /* Disable the PLL */
+ stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON);
+ while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))
+ asm("nop");
+
+ /* PLLVCO to 48MHz (for USB) -> PLLMUL = 3 */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
+ cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL);
+
+ /* PLL source */
+ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
+ cfgr |= (STM_RCC_CFGR_PLLSRC_TARGET_CLOCK << STM_RCC_CFGR_PLLSRC);
+ stm_rcc.cfgr = cfgr;
+
+ /* Disable pre divider */
+ stm_rcc.cfgr2 = (STM_RCC_CFGR2_PREDIV_1 << STM_RCC_CFGR2_PREDIV);
+
+ /* Enable the PLL and wait for it */
+ stm_rcc.cr |= (1 << STM_RCC_CR_PLLON);
+ while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)))
+ asm("nop");
+
+#endif
+
#endif
#define STM_PLLSRC STM_HSI
#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 0
#endif
+}
+
+static void
+ao_clock_normal_switch(void)
+{
+ uint32_t cfgr;
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
+ cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
+ stm_rcc.cfgr = cfgr;
+ for (;;) {
+ uint32_t c, part, mask, val;
+
+ c = stm_rcc.cfgr;
+ mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
+ val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
+ part = c & mask;
+ if (part == val)
+ break;
+ }
+#if !AO_HSI && !AO_NEED_HSI
+ /* Turn off the HSI clock */
+ stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
+#endif
#ifdef STM_PLLSRC
-#error No code for PLL initialization yet
+ /* USB PLL source */
+ stm_rcc.cfgr3 |= (1 << STM_RCC_CFGR3_USBSW);
#endif
+}
+
+void
+ao_clock_init(void)
+{
+ uint32_t cfgr;
+
+ /* Switch to HSI while messing about */
+ ao_clock_hsi();
+
+ /* Disable all interrupts */
+ stm_rcc.cir = 0;
+
+ /* Start high speed clock */
+ ao_clock_normal_start();
/* Set flash latency to tolerate 48MHz SYSCLK -> 1 wait state */
stm_rcc.cfgr = cfgr;
/* Switch to the desired system clock */
-
- cfgr = stm_rcc.cfgr;
- cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
- cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW);
- stm_rcc.cfgr = cfgr;
- for (;;) {
- uint32_t c, part, mask, val;
-
- c = stm_rcc.cfgr;
- mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
- val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS);
- part = c & mask;
- if (part == val)
- break;
- }
+ ao_clock_normal_switch();
/* Clear reset flags */
stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
-#if !AO_HSI && !AO_NEED_HSI
- /* Turn off the HSI clock */
- stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
-#endif
#if DEBUG_THE_CLOCK
/* Output SYSCLK on PA8 for measurments */
stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);
#endif
}
+
+#if AO_POWER_MANAGEMENT
+void
+ao_clock_suspend(void)
+{
+ ao_clock_hsi();
+}
+
+void
+ao_clock_resume(void)
+{
+ ao_clock_normal_start();
+ ao_clock_normal_switch();
+}
+#endif
#include "ao.h"
#include "ao_usb.h"
#include "ao_product.h"
+#include "ao_power.h"
#define USB_DEBUG 0
+#define USB_STATUS 0
#define USB_DEBUG_DATA 0
#define USB_ECHO 0
#error "must define AO_PA11_PA12_RMP"
#endif
+#ifndef AO_POWER_MANAGEMENT
+#define AO_POWER_MANAGEMENT 0
+#endif
+
#ifndef USE_USB_STDIO
#define USE_USB_STDIO 1
#endif
static uint16_t *ao_usb_ep0_tx_buffer;
static uint16_t *ao_usb_ep0_rx_buffer;
+#if AO_USB_HAS_INT
/* Pointer to interrupt buffer in USB memory */
static uint16_t ao_usb_int_tx_offset;
+#endif
/* Pointer to bulk data tx/rx buffers in USB memory */
+#if AO_USB_HAS_IN
static uint16_t ao_usb_in_tx_offset;
static uint16_t *ao_usb_in_tx_buffer;
-static uint16_t ao_usb_out_rx_offset;
-static uint16_t *ao_usb_out_rx_buffer;
/* System ram shadow of USB buffer; writing individual bytes is
* too much of a pain (sigh) */
static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE];
static uint8_t ao_usb_tx_count;
+#endif
+#if AO_USB_HAS_OUT
+static uint16_t ao_usb_out_rx_offset;
+static uint16_t *ao_usb_out_rx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
+#endif
+#if AO_USB_HAS_IN2
+static uint16_t ao_usb_in2_tx_offset;
+static uint16_t *ao_usb_in2_tx_buffer;
+
+/* System ram shadow of USB buffer; writing individual bytes is
+ * too much of a pain (sigh) */
+static uint8_t ao_usb_tx2_buffer[AO_USB_IN_SIZE];
+static uint8_t ao_usb_tx2_count;
+#endif
+
/*
* End point register indices
*/
#define AO_USB_INT_EPR 1
#define AO_USB_OUT_EPR 2
#define AO_USB_IN_EPR 3
+#define AO_USB_IN2_EPR 4
/* Marks when we don't need to send an IN packet.
* This happens only when the last IN packet is not full,
*/
static uint8_t ao_usb_in_pending;
+#if AO_USB_HAS_IN2
+/* Marks when we have delivered an IN packet to the hardware
+ * and it has not been received yet. ao_sleep on this address
+ * to wait for it to be delivered.
+ */
+static uint8_t ao_usb_in2_pending;
+static uint16_t in2_count;
+static uint8_t ao_usb_in2_flushed;
+#endif
+
/* Marks when an OUT packet has been received by the hardware
* but not pulled to the shadow buffer.
*/
uint8_t ao_usb_running;
static uint8_t ao_usb_configuration;
-#define AO_USB_EP0_GOT_RESET 1
-#define AO_USB_EP0_GOT_SETUP 2
-#define AO_USB_EP0_GOT_RX_DATA 4
-#define AO_USB_EP0_GOT_TX_ACK 8
+#define AO_USB_EP0_GOT_SETUP 1
+#define AO_USB_EP0_GOT_RX_DATA 2
+#define AO_USB_EP0_GOT_TX_ACK 4
static uint8_t ao_usb_ep0_receive;
static uint8_t ao_usb_address;
ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
+
+#if AO_USB_HAS_INT
ao_usb_int_tx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_INT_SIZE;
+#endif
+#if AO_USB_HAS_OUT
ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_out_rx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_OUT_SIZE;
+#endif
+#if AO_USB_HAS_IN
ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
ao_usb_in_tx_offset = ao_usb_sram_addr;
ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
+
+#if AO_USB_HAS_IN2
+ ao_usb_in2_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+ ao_usb_in2_tx_offset = ao_usb_sram_addr;
+ ao_usb_sram_addr += AO_USB_IN_SIZE;
+#endif
}
static void
{
debug ("ao_usb_set_configuration\n");
+#if AO_USB_HAS_INT
/* Set up the INT end point */
ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_int_tx_offset;
ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0;
STM_USB_EPR_EP_TYPE_INTERRUPT,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
+#if AO_USB_HAS_OUT
/* Set up the OUT end point */
ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_out_rx_offset;
ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_VALID,
STM_USB_EPR_STAT_TX_DISABLED);
+#endif
+#if AO_USB_HAS_IN
/* Set up the IN end point */
ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset;
ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0;
STM_USB_EPR_EP_TYPE_BULK,
STM_USB_EPR_STAT_RX_DISABLED,
STM_USB_EPR_STAT_TX_NAK);
+#endif
+
+#if AO_USB_HAS_IN2
+ /* Set up the IN2 end point */
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in2_tx_offset;
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = 0;
+
+ ao_usb_init_ep(AO_USB_IN2_EPR,
+ AO_USB_IN2_EP,
+ STM_USB_EPR_EP_TYPE_BULK,
+ STM_USB_EPR_STAT_RX_DISABLED,
+ STM_USB_EPR_STAT_TX_NAK);
+#endif
ao_usb_running = 1;
#if AO_USB_DIRECTIO
static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
+#if AO_USB_DEVICE_ID_SERIAL
+static uint8_t ao_usb_serial[2 + 48];
+
+/* Convert a 32-bit value to 8 hexidecimal UCS2 characters */
+static void
+hex_to_ucs2(uint32_t in, uint8_t *out)
+{
+ int i;
+
+ for (i = 28; i >= 0; i -= 4) {
+ uint8_t bits = (in >> i) & 0xf;
+ *out++ = ((bits < 10) ? '0' : ('a' - 10)) + bits;
+ *out++ = 0;
+ }
+}
+
+/* Encode the device ID (96 bits) in hexidecimal to use as a device
+ * serial number
+ */
+static void
+ao_usb_serial_init(void)
+{
+ ao_usb_serial[0] = 50; /* length */
+ ao_usb_serial[1] = AO_USB_DESC_STRING;
+ hex_to_ucs2(stm_device_id.u_id0, ao_usb_serial + 2 + 0);
+ hex_to_ucs2(stm_device_id.u_id1, ao_usb_serial + 2 + 16);
+ hex_to_ucs2(stm_device_id.u_id2, ao_usb_serial + 2 + 32);
+}
+#endif
+
/* Walk through the list of descriptors and find a match
*/
static void
len = descriptor[2];
else
len = descriptor[0];
+#if AO_USB_DEVICE_ID_SERIAL
+ /* Slightly hacky - the serial number is string 3 */
+ if (type == AO_USB_DESC_STRING && (value & 0xff) == 3) {
+ descriptor = ao_usb_serial;
+ len = sizeof (ao_usb_serial);
+ }
+#endif
ao_usb_ep0_in_set(descriptor, len);
break;
}
ao_usb_ep0_handle(uint8_t receive)
{
ao_usb_ep0_receive = 0;
- if (receive & AO_USB_EP0_GOT_RESET) {
- debug ("\treset\n");
- ao_usb_set_ep0();
- return;
- }
if (receive & AO_USB_EP0_GOT_SETUP) {
debug ("\tsetup\n");
ao_usb_ep0_setup();
}
}
+#if AO_POWER_MANAGEMENT
+void
+ao_usb_suspend(void)
+{
+ stm_usb.cntr |= (1 << STM_USB_CNTR_FSUSP);
+ ao_power_suspend();
+ stm_usb.cntr |= (1 << STM_USB_CNTR_LP_MODE);
+ ao_clock_suspend();
+}
+
+void
+ao_usb_wakeup(void)
+{
+ ao_clock_resume();
+ stm_usb.cntr &= ~(1 << STM_USB_CNTR_FSUSP);
+ ao_power_resume();
+}
+#endif
+
void
stm_usb_isr(void)
{
ao_wakeup(&ao_usb_in_pending);
}
break;
+#if AO_USB_HAS_IN2
+ case AO_USB_IN2_EPR:
+ ++in2_count;
+ _tx_dbg1("TX2 ISR", epr);
+ if (ao_usb_epr_ctr_tx(epr)) {
+ ao_usb_in2_pending = 0;
+ ao_wakeup(&ao_usb_in2_pending);
+ }
+ break;
+#endif
case AO_USB_INT_EPR:
++int_count;
if (ao_usb_epr_ctr_tx(epr))
if (istr & (1 << STM_USB_ISTR_RESET)) {
++reset_count;
- ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET;
- ao_usb_ep0_handle(ao_usb_ep0_receive);
+ debug ("\treset\n");
+ ao_usb_set_ep0();
}
-
+#if AO_POWER_MANAGEMENT
+ if (istr & (1 << STM_USB_ISTR_SUSP)) {
+ debug ("\tsuspend\n");
+ ao_usb_suspend();
+ }
+ if (istr & (1 << STM_USB_ISTR_WKUP)) {
+ debug ("\twakeup\n");
+ ao_usb_wakeup();
+ }
+#endif
}
+#if AO_USB_HAS_IN
/* Queue the current IN buffer for transmission */
static void
_ao_usb_in_send(void)
}
ao_arch_release_interrupts();
}
+#endif
+
+#if AO_USB_HAS_IN2
+/* Queue the current IN buffer for transmission */
+static void
+_ao_usb_in2_send(void)
+{
+ _tx_dbg0("in2_send start");
+ debug ("send2 %d\n", ao_usb_tx_count);
+ while (ao_usb_in2_pending)
+ ao_sleep(&ao_usb_in2_pending);
+ ao_usb_in2_pending = 1;
+ if (ao_usb_tx2_count != AO_USB_IN_SIZE)
+ ao_usb_in2_flushed = 1;
+ ao_usb_copy_tx(ao_usb_tx2_buffer, ao_usb_in2_tx_buffer, ao_usb_tx2_count);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_in_tx_offset;
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = ao_usb_tx_count;
+ ao_usb_tx2_count = 0;
+ _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+ _tx_dbg0("in2_send end");
+}
+
+/* Wait for a free IN buffer. Interrupts are blocked */
+static void
+_ao_usb_in2_wait(void)
+{
+ for (;;) {
+ /* Check if the current buffer is writable */
+ if (ao_usb_tx2_count < AO_USB_IN_SIZE)
+ break;
+
+ _tx_dbg0("in2_wait top");
+ /* Wait for an IN buffer to be ready */
+ while (ao_usb_in2_pending)
+ ao_sleep(&ao_usb_in2_pending);
+ _tx_dbg0("in_wait bottom");
+ }
+}
+
+void
+ao_usb_flush2(void)
+{
+ if (!ao_usb_running)
+ return;
+
+ /* Anytime we've sent a character since
+ * the last time we flushed, we'll need
+ * to send a packet -- the only other time
+ * we would send a packet is when that
+ * packet was full, in which case we now
+ * want to send an empty packet
+ */
+ ao_arch_block_interrupts();
+ while (!ao_usb_in2_flushed) {
+ _tx_dbg0("flush2 top");
+ _ao_usb_in2_send();
+ _tx_dbg0("flush2 end");
+ }
+ ao_arch_release_interrupts();
+}
+
+void
+ao_usb_putchar2(char c)
+{
+ if (!ao_usb_running)
+ return;
+
+ ao_arch_block_interrupts();
+ _ao_usb_in2_wait();
+ ao_usb_in2_flushed = 0;
+ ao_usb_tx2_buffer[ao_usb_tx2_count++] = (uint8_t) c;
+
+ /* Send the packet when full */
+ if (ao_usb_tx2_count == AO_USB_IN_SIZE) {
+ _tx_dbg0("putchar2 full");
+ _ao_usb_in2_send();
+ _tx_dbg0("putchar2 flushed");
+ }
+ ao_arch_release_interrupts();
+}
+#endif
+
+#if AO_USB_HAS_OUT
static void
_ao_usb_out_recv(void)
{
ao_arch_release_interrupts();
return c;
}
+#endif
#if AO_USB_DIRECTIO
uint16_t *
_ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
ao_arch_release_interrupts();
}
+
+#if AO_USB_HAS_IN2
+void
+ao_usb_write2(uint16_t *buffer, uint16_t len)
+{
+ ao_arch_block_interrupts();
+
+ /* Wait for everything to be ready at the same time */
+ for (;;) {
+ /* Make sure USB is connected */
+ if (!ao_usb_running) {
+ ao_sleep(&ao_usb_running);
+ continue;
+ }
+
+ /* Flush any pending regular I/O */
+ if (ao_usb_tx2_count) {
+ _ao_usb_in2_send();
+ continue;
+ }
+
+ /* Wait for an idle IN buffer */
+ if (ao_usb_in2_pending) {
+ ao_sleep(&ao_usb_in2_pending);
+ continue;
+ }
+ break;
+ }
+
+ ao_usb_in2_pending = 1;
+ ao_usb_in2_flushed = (len != AO_USB_IN_SIZE);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer);
+ ao_usb_bdt[AO_USB_IN2_EPR].single.count_tx = len;
+ _ao_usb_set_stat_tx(AO_USB_IN2_EPR, STM_USB_EPR_STAT_TX_VALID);
+ ao_arch_release_interrupts();
+}
+#endif
#endif
void
stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) |
(0 << STM_USB_CNTR_PMAOVRM) |
(0 << STM_USB_CNTR_ERRM) |
- (0 << STM_USB_CNTR_WKUPM) |
- (0 << STM_USB_CNTR_SUSPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_WKUPM) |
+ (AO_POWER_MANAGEMENT << STM_USB_CNTR_SUSPM) |
(1 << STM_USB_CNTR_RESETM) |
(0 << STM_USB_CNTR_SOFM) |
(0 << STM_USB_CNTR_ESOFM) |
}
#endif
-#if USB_DEBUG
+#if USB_STATUS
static void
ao_usb_irq(void)
{
/* Set PA11/PA12 remapping bit */
stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP);
+#ifndef AO_USB_START_DISABLED
ao_usb_enable();
+#endif
+
+#if AO_USB_DEVICE_ID_SERIAL
+ ao_usb_serial_init();
+#endif
debug ("ao_usb_init\n");
ao_usb_ep0_state = AO_USB_EP0_IDLE;
#if USB_ECHO
ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo");
#endif
-#if USB_DEBUG
+#if USB_STATUS
ao_cmd_register(&ao_usb_cmds[0]);
#endif
#if !USB_ECHO
/* calibration data in system memory */
stm_cal = 0x1ffff7b8;
stm_flash_size_04x = 0x1ffff7cc;
-stm_device_id = 0x1ff80050;
+stm_device_id = 0x1ffff7ac;
#define STM_RCC_CR2_HSI14RDY 1
#define STM_RCC_CR2_HSI14ON 0
+#define STM_RCC_CFGR2_PREDIV 0
+#define STM_RCC_CFGR2_PREDIV_1 0x0
+#define STM_RCC_CFGR2_PREDIV_2 0x1
+#define STM_RCC_CFGR2_PREDIV_3 0x2
+#define STM_RCC_CFGR2_PREDIV_4 0x3
+#define STM_RCC_CFGR2_PREDIV_5 0x4
+#define STM_RCC_CFGR2_PREDIV_6 0x5
+#define STM_RCC_CFGR2_PREDIV_7 0x6
+#define STM_RCC_CFGR2_PREDIV_8 0x7
+#define STM_RCC_CFGR2_PREDIV_9 0x8
+#define STM_RCC_CFGR2_PREDIV_10 0x9
+#define STM_RCC_CFGR2_PREDIV_11 0xa
+#define STM_RCC_CFGR2_PREDIV_12 0xb
+#define STM_RCC_CFGR2_PREDIV_13 0xc
+#define STM_RCC_CFGR2_PREDIV_14 0xd
+#define STM_RCC_CFGR2_PREDIV_15 0xe
+#define STM_RCC_CFGR2_PREDIV_16 0xf
+
#define STM_RCC_CFGR3_USART3SW 18
#define STM_RCC_CFGR3_USART2SW 16
#define STM_RCC_CFGR3_ADCSW 8
#define STM_ISR_TSC_POS 8
#define STM_ISR_DMA_CH1_POS 9
#define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS 10
-#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS 11
+#define STM_ISR_DMA_CH4_5_6_7_DMA2_CH3_4_5_POS 11
#define STM_ISR_ADC_COMP_POS 12
#define STM_ISR_TIM1_BRK_UP_TRG_COM_POS 13
#define STM_ISR_TIM1_CC_POS 14
struct stm_syscfg {
vuint32_t cfgr1;
+ uint32_t reserved_04;
vuint32_t exticr[4];
vuint32_t cfgr2;
+ uint8_t reserved_1c[0x80-0x1c];
+ vuint32_t itline[31];
};
extern struct stm_syscfg stm_syscfg;
#define STM_SYSCFG_CFGR1_MEM_MODE_SRAM 3
#define STM_SYSCFG_CFGR1_MEM_MODE_MASK 3
-#if 0
+#define STM_SYSCFG_EXTICR_PA 0
+#define STM_SYSCFG_EXTICR_PB 1
+#define STM_SYSCFG_EXTICR_PC 2
+#define STM_SYSCFG_EXTICR_PD 3
+#define STM_SYSCFG_EXTICR_PE 4
+#define STM_SYSCFG_EXTICR_PF 5
+
static inline void
stm_exticr_set(struct stm_gpio *gpio, int pin) {
uint8_t reg = pin >> 2;
stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
}
-#endif
-
struct stm_dma_channel {
vuint32_t ccr;
vuint32_t reserved;
};
-#define STM_NUM_DMA 6
+#define STM_NUM_DMA 5
struct stm_dma {
vuint32_t isr;
extern struct stm_dma stm_dma;
-/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh)
+/* DMA channels go from 1 to 5, instead of 0 to 4 (sigh)
*/
#define STM_DMA_INDEX(channel) ((channel) - 1)
#define STM_SPI_CR1_BIDIOE 14
#define STM_SPI_CR1_CRCEN 13
#define STM_SPI_CR1_CRCNEXT 12
-#define STM_SPI_CR1_DFF 11
+#define STM_SPI_CR1_CRCL 11
#define STM_SPI_CR1_RXONLY 10
#define STM_SPI_CR1_SSM 9
#define STM_SPI_CR1_SSI 8
#define STM_SPI_CR1_CPOL 1
#define STM_SPI_CR1_CPHA 0
+#define STM_SPI_CR2_LDMA_TX 14
+#define STM_SPI_CR2_LDMA_RX 13
+#define STM_SPI_CR2_FRXTH 12
+#define STM_SPI_CR2_DS 8
+#define STM_SPI_CR2_DS_4 0x3
+#define STM_SPI_CR2_DS_5 0x4
+#define STM_SPI_CR2_DS_6 0x5
+#define STM_SPI_CR2_DS_7 0x6
+#define STM_SPI_CR2_DS_8 0x7
+#define STM_SPI_CR2_DS_9 0x8
+#define STM_SPI_CR2_DS_10 0x9
+#define STM_SPI_CR2_DS_11 0xa
+#define STM_SPI_CR2_DS_12 0xb
+#define STM_SPI_CR2_DS_13 0xc
+#define STM_SPI_CR2_DS_14 0xd
+#define STM_SPI_CR2_DS_15 0xe
+#define STM_SPI_CR2_DS_16 0xf
#define STM_SPI_CR2_TXEIE 7
#define STM_SPI_CR2_RXNEIE 6
#define STM_SPI_CR2_ERRIE 5
+#define STM_SPI_CR2_FRF 4
+# define STM_SPI_CR2_FRF_MOTOROLA 0
+# define STM_SPI_CR2_FRF_TI 1
+#define STM_SPI_CR2_NSSP 3
#define STM_SPI_CR2_SSOE 2
#define STM_SPI_CR2_TXDMAEN 1
#define STM_SPI_CR2_RXDMAEN 0
+#define STM_SPI_SR_FTLVL 11
+#define STM_SPI_SR_FRLVL 9
+#define STM_SPI_SR_FRE 8
#define STM_SPI_SR_BSY 7
#define STM_SPI_SR_OVR 6
#define STM_SPI_SR_MODF 5
#define STM_SPI_SR_CRCERR 4
+#define STM_SPI_SR_UDR 3
+#define STM_SPI_SR_CHSIDE 2
#define STM_SPI_SR_TXE 1
#define STM_SPI_SR_RXNE 0
#define STM_I2C_CCR_CCR 0
#define STM_I2C_CCR_MASK 0x7ff
-struct stm_tim234 {
+struct stm_tim23 {
vuint32_t cr1;
vuint32_t cr2;
vuint32_t smcr;
uint32_t reserved_44;
vuint32_t dcr;
vuint32_t dmar;
-
- uint32_t reserved_50;
};
-extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4;
-
-#define STM_TIM234_CR1_CKD 8
-#define STM_TIM234_CR1_CKD_1 0
-#define STM_TIM234_CR1_CKD_2 1
-#define STM_TIM234_CR1_CKD_4 2
-#define STM_TIM234_CR1_CKD_MASK 3
-#define STM_TIM234_CR1_ARPE 7
-#define STM_TIM234_CR1_CMS 5
-#define STM_TIM234_CR1_CMS_EDGE 0
-#define STM_TIM234_CR1_CMS_CENTER_1 1
-#define STM_TIM234_CR1_CMS_CENTER_2 2
-#define STM_TIM234_CR1_CMS_CENTER_3 3
-#define STM_TIM234_CR1_CMS_MASK 3
-#define STM_TIM234_CR1_DIR 4
-#define STM_TIM234_CR1_DIR_UP 0
-#define STM_TIM234_CR1_DIR_DOWN 1
-#define STM_TIM234_CR1_OPM 3
-#define STM_TIM234_CR1_URS 2
-#define STM_TIM234_CR1_UDIS 1
-#define STM_TIM234_CR1_CEN 0
-
-#define STM_TIM234_CR2_TI1S 7
-#define STM_TIM234_CR2_MMS 4
-#define STM_TIM234_CR2_MMS_RESET 0
-#define STM_TIM234_CR2_MMS_ENABLE 1
-#define STM_TIM234_CR2_MMS_UPDATE 2
-#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3
-#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4
-#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5
-#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6
-#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7
-#define STM_TIM234_CR2_MMS_MASK 7
-#define STM_TIM234_CR2_CCDS 3
-
-#define STM_TIM234_SMCR_ETP 15
-#define STM_TIM234_SMCR_ECE 14
-#define STM_TIM234_SMCR_ETPS 12
-#define STM_TIM234_SMCR_ETPS_OFF 0
-#define STM_TIM234_SMCR_ETPS_DIV_2 1
-#define STM_TIM234_SMCR_ETPS_DIV_4 2
-#define STM_TIM234_SMCR_ETPS_DIV_8 3
-#define STM_TIM234_SMCR_ETPS_MASK 3
-#define STM_TIM234_SMCR_ETF 8
-#define STM_TIM234_SMCR_ETF_NONE 0
-#define STM_TIM234_SMCR_ETF_INT_N_2 1
-#define STM_TIM234_SMCR_ETF_INT_N_4 2
-#define STM_TIM234_SMCR_ETF_INT_N_8 3
-#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4
-#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5
-#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6
-#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7
-#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8
-#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9
-#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10
-#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11
-#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12
-#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13
-#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14
-#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15
-#define STM_TIM234_SMCR_ETF_MASK 15
-#define STM_TIM234_SMCR_MSM 7
-#define STM_TIM234_SMCR_TS 4
-#define STM_TIM234_SMCR_TS_ITR0 0
-#define STM_TIM234_SMCR_TS_ITR1 1
-#define STM_TIM234_SMCR_TS_ITR2 2
-#define STM_TIM234_SMCR_TS_ITR3 3
-#define STM_TIM234_SMCR_TS_TI1F_ED 4
-#define STM_TIM234_SMCR_TS_TI1FP1 5
-#define STM_TIM234_SMCR_TS_TI2FP2 6
-#define STM_TIM234_SMCR_TS_ETRF 7
-#define STM_TIM234_SMCR_TS_MASK 7
-#define STM_TIM234_SMCR_OCCS 3
-#define STM_TIM234_SMCR_SMS 0
-#define STM_TIM234_SMCR_SMS_DISABLE 0
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2
-#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3
-#define STM_TIM234_SMCR_SMS_RESET_MODE 4
-#define STM_TIM234_SMCR_SMS_GATED_MODE 5
-#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6
-#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7
-#define STM_TIM234_SMCR_SMS_MASK 7
-
-#define STM_TIM234_SR_CC4OF 12
-#define STM_TIM234_SR_CC3OF 11
-#define STM_TIM234_SR_CC2OF 10
-#define STM_TIM234_SR_CC1OF 9
-#define STM_TIM234_SR_TIF 6
-#define STM_TIM234_SR_CC4IF 4
-#define STM_TIM234_SR_CC3IF 3
-#define STM_TIM234_SR_CC2IF 2
-#define STM_TIM234_SR_CC1IF 1
-#define STM_TIM234_SR_UIF 0
-
-#define STM_TIM234_EGR_TG 6
-#define STM_TIM234_EGR_CC4G 4
-#define STM_TIM234_EGR_CC3G 3
-#define STM_TIM234_EGR_CC2G 2
-#define STM_TIM234_EGR_CC1G 1
-#define STM_TIM234_EGR_UG 0
-
-#define STM_TIM234_CCMR1_OC2CE 15
-#define STM_TIM234_CCMR1_OC2M 12
-#define STM_TIM234_CCMR1_OC2M_FROZEN 0
-#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR1_OC2M_TOGGLE 3
-#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4
-#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5
-#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6
-#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7
-#define STM_TIM234_CCMR1_OC2M_MASK 7
-#define STM_TIM234_CCMR1_OC2PE 11
-#define STM_TIM234_CCMR1_OC2FE 10
-#define STM_TIM234_CCMR1_CC2S 8
-#define STM_TIM234_CCMR1_CC2S_OUTPUT 0
-#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1
-#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2
-#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3
-#define STM_TIM234_CCMR1_CC2S_MASK 3
-
-#define STM_TIM234_CCMR1_OC1CE 7
-#define STM_TIM234_CCMR1_OC1M 4
-#define STM_TIM234_CCMR1_OC1M_FROZEN 0
-#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR1_OC1M_TOGGLE 3
-#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4
-#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5
-#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6
-#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7
-#define STM_TIM234_CCMR1_OC1M_MASK 7
-#define STM_TIM234_CCMR1_OC1PE 11
-#define STM_TIM234_CCMR1_OC1FE 2
-#define STM_TIM234_CCMR1_CC1S 0
-#define STM_TIM234_CCMR1_CC1S_OUTPUT 0
-#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1
-#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2
-#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3
-#define STM_TIM234_CCMR1_CC1S_MASK 3
-
-#define STM_TIM234_CCMR2_OC4CE 15
-#define STM_TIM234_CCMR2_OC4M 12
-#define STM_TIM234_CCMR2_OC4M_FROZEN 0
-#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR2_OC4M_TOGGLE 3
-#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4
-#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5
-#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6
-#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7
-#define STM_TIM234_CCMR2_OC4M_MASK 7
-#define STM_TIM234_CCMR2_OC4PE 11
-#define STM_TIM234_CCMR2_OC4FE 10
-#define STM_TIM234_CCMR2_CC4S 8
-#define STM_TIM234_CCMR2_CC4S_OUTPUT 0
-#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1
-#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2
-#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3
-#define STM_TIM234_CCMR2_CC4S_MASK 3
-
-#define STM_TIM234_CCMR2_OC3CE 7
-#define STM_TIM234_CCMR2_OC3M 4
-#define STM_TIM234_CCMR2_OC3M_FROZEN 0
-#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1
-#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2
-#define STM_TIM234_CCMR2_OC3M_TOGGLE 3
-#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4
-#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5
-#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6
-#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7
-#define STM_TIM234_CCMR2_OC3M_MASK 7
-#define STM_TIM234_CCMR2_OC3PE 11
-#define STM_TIM234_CCMR2_OC3FE 2
-#define STM_TIM234_CCMR2_CC3S 0
-#define STM_TIM234_CCMR2_CC3S_OUTPUT 0
-#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1
-#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2
-#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3
-#define STM_TIM234_CCMR2_CC3S_MASK 3
-
-#define STM_TIM234_CCER_CC4NP 15
-#define STM_TIM234_CCER_CC4P 13
-#define STM_TIM234_CCER_CC4E 12
-#define STM_TIM234_CCER_CC3NP 11
-#define STM_TIM234_CCER_CC3P 9
-#define STM_TIM234_CCER_CC3E 8
-#define STM_TIM234_CCER_CC2NP 7
-#define STM_TIM234_CCER_CC2P 5
-#define STM_TIM234_CCER_CC2E 4
-#define STM_TIM234_CCER_CC1NP 3
-#define STM_TIM234_CCER_CC1P 1
-#define STM_TIM234_CCER_CC1E 0
+extern struct stm_tim23 stm_tim2, stm_tim3;
+
+#define stm_tim3 (*(struct stm_tim23 *) 0x40000400)
+#define stm_tim2 (*(struct stm_tim23 *) 0x40000000)
+
+#define STM_TIM23_CR1_CKD 8
+#define STM_TIM23_CR1_CKD_1 0
+#define STM_TIM23_CR1_CKD_2 1
+#define STM_TIM23_CR1_CKD_4 2
+#define STM_TIM23_CR1_CKD_MASK 3
+#define STM_TIM23_CR1_ARPE 7
+#define STM_TIM23_CR1_CMS 5
+#define STM_TIM23_CR1_CMS_EDGE 0
+#define STM_TIM23_CR1_CMS_CENTER_1 1
+#define STM_TIM23_CR1_CMS_CENTER_2 2
+#define STM_TIM23_CR1_CMS_CENTER_3 3
+#define STM_TIM23_CR1_CMS_MASK 3
+#define STM_TIM23_CR1_DIR 4
+#define STM_TIM23_CR1_DIR_UP 0
+#define STM_TIM23_CR1_DIR_DOWN 1
+#define STM_TIM23_CR1_OPM 3
+#define STM_TIM23_CR1_URS 2
+#define STM_TIM23_CR1_UDIS 1
+#define STM_TIM23_CR1_CEN 0
+
+#define STM_TIM23_CR2_TI1S 7
+#define STM_TIM23_CR2_MMS 4
+#define STM_TIM23_CR2_MMS_RESET 0
+#define STM_TIM23_CR2_MMS_ENABLE 1
+#define STM_TIM23_CR2_MMS_UPDATE 2
+#define STM_TIM23_CR2_MMS_COMPARE_PULSE 3
+#define STM_TIM23_CR2_MMS_COMPARE_OC1REF 4
+#define STM_TIM23_CR2_MMS_COMPARE_OC2REF 5
+#define STM_TIM23_CR2_MMS_COMPARE_OC3REF 6
+#define STM_TIM23_CR2_MMS_COMPARE_OC4REF 7
+#define STM_TIM23_CR2_MMS_MASK 7
+#define STM_TIM23_CR2_CCDS 3
+
+#define STM_TIM23_SMCR_ETP 15
+#define STM_TIM23_SMCR_ECE 14
+#define STM_TIM23_SMCR_ETPS 12
+#define STM_TIM23_SMCR_ETPS_OFF 0
+#define STM_TIM23_SMCR_ETPS_DIV_2 1
+#define STM_TIM23_SMCR_ETPS_DIV_4 2
+#define STM_TIM23_SMCR_ETPS_DIV_8 3
+#define STM_TIM23_SMCR_ETPS_MASK 3
+#define STM_TIM23_SMCR_ETF 8
+#define STM_TIM23_SMCR_ETF_NONE 0
+#define STM_TIM23_SMCR_ETF_INT_N_2 1
+#define STM_TIM23_SMCR_ETF_INT_N_4 2
+#define STM_TIM23_SMCR_ETF_INT_N_8 3
+#define STM_TIM23_SMCR_ETF_DTS_2_N_6 4
+#define STM_TIM23_SMCR_ETF_DTS_2_N_8 5
+#define STM_TIM23_SMCR_ETF_DTS_4_N_6 6
+#define STM_TIM23_SMCR_ETF_DTS_4_N_8 7
+#define STM_TIM23_SMCR_ETF_DTS_8_N_6 8
+#define STM_TIM23_SMCR_ETF_DTS_8_N_8 9
+#define STM_TIM23_SMCR_ETF_DTS_16_N_5 10
+#define STM_TIM23_SMCR_ETF_DTS_16_N_6 11
+#define STM_TIM23_SMCR_ETF_DTS_16_N_8 12
+#define STM_TIM23_SMCR_ETF_DTS_32_N_5 13
+#define STM_TIM23_SMCR_ETF_DTS_32_N_6 14
+#define STM_TIM23_SMCR_ETF_DTS_32_N_8 15
+#define STM_TIM23_SMCR_ETF_MASK 15
+#define STM_TIM23_SMCR_MSM 7
+#define STM_TIM23_SMCR_TS 4
+#define STM_TIM23_SMCR_TS_ITR0 0
+#define STM_TIM23_SMCR_TS_ITR1 1
+#define STM_TIM23_SMCR_TS_ITR2 2
+#define STM_TIM23_SMCR_TS_ITR3 3
+#define STM_TIM23_SMCR_TS_TI1F_ED 4
+#define STM_TIM23_SMCR_TS_TI1FP1 5
+#define STM_TIM23_SMCR_TS_TI2FP2 6
+#define STM_TIM23_SMCR_TS_ETRF 7
+#define STM_TIM23_SMCR_TS_MASK 7
+#define STM_TIM23_SMCR_OCCS 3
+#define STM_TIM23_SMCR_SMS 0
+#define STM_TIM23_SMCR_SMS_DISABLE 0
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_1 1
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_2 2
+#define STM_TIM23_SMCR_SMS_ENCODER_MODE_3 3
+#define STM_TIM23_SMCR_SMS_RESET_MODE 4
+#define STM_TIM23_SMCR_SMS_GATED_MODE 5
+#define STM_TIM23_SMCR_SMS_TRIGGER_MODE 6
+#define STM_TIM23_SMCR_SMS_EXTERNAL_CLOCK 7
+#define STM_TIM23_SMCR_SMS_MASK 7
+
+#define STM_TIM23_SR_CC4OF 12
+#define STM_TIM23_SR_CC3OF 11
+#define STM_TIM23_SR_CC2OF 10
+#define STM_TIM23_SR_CC1OF 9
+#define STM_TIM23_SR_TIF 6
+#define STM_TIM23_SR_CC4IF 4
+#define STM_TIM23_SR_CC3IF 3
+#define STM_TIM23_SR_CC2IF 2
+#define STM_TIM23_SR_CC1IF 1
+#define STM_TIM23_SR_UIF 0
+
+#define STM_TIM23_EGR_TG 6
+#define STM_TIM23_EGR_CC4G 4
+#define STM_TIM23_EGR_CC3G 3
+#define STM_TIM23_EGR_CC2G 2
+#define STM_TIM23_EGR_CC1G 1
+#define STM_TIM23_EGR_UG 0
+
+#define STM_TIM23_CCMR1_OC2CE 15
+#define STM_TIM23_CCMR1_OC2M 12
+#define STM_TIM23_CCMR1_OC2M_FROZEN 0
+#define STM_TIM23_CCMR1_OC2M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR1_OC2M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR1_OC2M_TOGGLE 3
+#define STM_TIM23_CCMR1_OC2M_FORCE_LOW 4
+#define STM_TIM23_CCMR1_OC2M_FORCE_HIGH 5
+#define STM_TIM23_CCMR1_OC2M_PWM_MODE_1 6
+#define STM_TIM23_CCMR1_OC2M_PWM_MODE_2 7
+#define STM_TIM23_CCMR1_OC2M_MASK 7
+#define STM_TIM23_CCMR1_OC2PE 11
+#define STM_TIM23_CCMR1_OC2FE 10
+#define STM_TIM23_CCMR1_CC2S 8
+#define STM_TIM23_CCMR1_CC2S_OUTPUT 0
+#define STM_TIM23_CCMR1_CC2S_INPUT_TI2 1
+#define STM_TIM23_CCMR1_CC2S_INPUT_TI1 2
+#define STM_TIM23_CCMR1_CC2S_INPUT_TRC 3
+#define STM_TIM23_CCMR1_CC2S_MASK 3
+
+#define STM_TIM23_CCMR1_OC1CE 7
+#define STM_TIM23_CCMR1_OC1M 4
+#define STM_TIM23_CCMR1_OC1M_FROZEN 0
+#define STM_TIM23_CCMR1_OC1M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR1_OC1M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR1_OC1M_TOGGLE 3
+#define STM_TIM23_CCMR1_OC1M_FORCE_LOW 4
+#define STM_TIM23_CCMR1_OC1M_FORCE_HIGH 5
+#define STM_TIM23_CCMR1_OC1M_PWM_MODE_1 6
+#define STM_TIM23_CCMR1_OC1M_PWM_MODE_2 7
+#define STM_TIM23_CCMR1_OC1M_MASK 7
+#define STM_TIM23_CCMR1_OC1PE 11
+#define STM_TIM23_CCMR1_OC1FE 2
+#define STM_TIM23_CCMR1_CC1S 0
+#define STM_TIM23_CCMR1_CC1S_OUTPUT 0
+#define STM_TIM23_CCMR1_CC1S_INPUT_TI1 1
+#define STM_TIM23_CCMR1_CC1S_INPUT_TI2 2
+#define STM_TIM23_CCMR1_CC1S_INPUT_TRC 3
+#define STM_TIM23_CCMR1_CC1S_MASK 3
+
+#define STM_TIM23_CCMR2_OC4CE 15
+#define STM_TIM23_CCMR2_OC4M 12
+#define STM_TIM23_CCMR2_OC4M_FROZEN 0
+#define STM_TIM23_CCMR2_OC4M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR2_OC4M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR2_OC4M_TOGGLE 3
+#define STM_TIM23_CCMR2_OC4M_FORCE_LOW 4
+#define STM_TIM23_CCMR2_OC4M_FORCE_HIGH 5
+#define STM_TIM23_CCMR2_OC4M_PWM_MODE_1 6
+#define STM_TIM23_CCMR2_OC4M_PWM_MODE_2 7
+#define STM_TIM23_CCMR2_OC4M_MASK 7
+#define STM_TIM23_CCMR2_OC4PE 11
+#define STM_TIM23_CCMR2_OC4FE 10
+#define STM_TIM23_CCMR2_CC4S 8
+#define STM_TIM23_CCMR2_CC4S_OUTPUT 0
+#define STM_TIM23_CCMR2_CC4S_INPUT_TI4 1
+#define STM_TIM23_CCMR2_CC4S_INPUT_TI3 2
+#define STM_TIM23_CCMR2_CC4S_INPUT_TRC 3
+#define STM_TIM23_CCMR2_CC4S_MASK 3
+
+#define STM_TIM23_CCMR2_OC3CE 7
+#define STM_TIM23_CCMR2_OC3M 4
+#define STM_TIM23_CCMR2_OC3M_FROZEN 0
+#define STM_TIM23_CCMR2_OC3M_SET_HIGH_ON_MATCH 1
+#define STM_TIM23_CCMR2_OC3M_SET_LOW_ON_MATCH 2
+#define STM_TIM23_CCMR2_OC3M_TOGGLE 3
+#define STM_TIM23_CCMR2_OC3M_FORCE_LOW 4
+#define STM_TIM23_CCMR2_OC3M_FORCE_HIGH 5
+#define STM_TIM23_CCMR2_OC3M_PWM_MODE_1 6
+#define STM_TIM23_CCMR2_OC3M_PWM_MODE_2 7
+#define STM_TIM23_CCMR2_OC3M_MASK 7
+#define STM_TIM23_CCMR2_OC3PE 11
+#define STM_TIM23_CCMR2_OC3FE 2
+#define STM_TIM23_CCMR2_CC3S 0
+#define STM_TIM23_CCMR2_CC3S_OUTPUT 0
+#define STM_TIM23_CCMR2_CC3S_INPUT_TI3 1
+#define STM_TIM23_CCMR2_CC3S_INPUT_TI4 2
+#define STM_TIM23_CCMR2_CC3S_INPUT_TRC 3
+#define STM_TIM23_CCMR2_CC3S_MASK 3
+
+#define STM_TIM23_CCER_CC4NP 15
+#define STM_TIM23_CCER_CC4P 13
+#define STM_TIM23_CCER_CC4E 12
+#define STM_TIM23_CCER_CC3NP 11
+#define STM_TIM23_CCER_CC3P 9
+#define STM_TIM23_CCER_CC3E 8
+#define STM_TIM23_CCER_CC2NP 7
+#define STM_TIM23_CCER_CC2P 5
+#define STM_TIM23_CCER_CC2E 4
+#define STM_TIM23_CCER_CC1NP 3
+#define STM_TIM23_CCER_CC1P 1
+#define STM_TIM23_CCER_CC1E 0
struct stm_usb {
struct {
--- /dev/null
+ao_product.h
+telebt-*.elf
#define USE_SERIAL_2_STDIN 1
#define DELAY_SERIAL_2_STDIN 1
#define USE_SERIAL_2_FLOW 1
+#define USE_SERIAL_2_SW_FLOW 1
#define SERIAL_2_PA2_PA3 1
#define SERIAL_2_PD5_PD6 0
+#define SERIAL_2_PORT_RTS (&stm_gpioa)
+#define SERIAL_2_PIN_RTS 0
+#define SERIAL_2_PORT_CTS (&stm_gpioa)
+#define SERIAL_2_PIN_CTS 1
#define HAS_SERIAL_3 0
#define USE_SERIAL_3_STDIN 0
ao_clock_init();
ao_task_init();
- ao_serial_init();
ao_led_init(LEDS_AVAILABLE);
ao_led_on(AO_LED_RED);
ao_timer_init();
#define PACKET_HAS_MASTER 0
#define PACKET_HAS_SLAVE 0
+#define PAD_BOX 0
+
#define AO_LED_CONTINUITY(c) (1 << ((c) + 2))
#define AO_LED_CONTINUITY_MASK (0xc)
#define AO_LED_ARMED 0x10
--- /dev/null
+telefiretwo-*
+ao_product.h
--- /dev/null
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pad.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_adc_stm.c \
+ ao_data.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_eeprom_stm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_pad.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+ ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.1
+PRODUCT_DEF=-DTELEFIRETWO_V_0_1
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.1
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
+
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+
+#define HAS_FLIGHT 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_GPS 0
+#define HAS_SERIAL_1 0
+#define HAS_ADC 1
+#define HAS_DBG 0
+#define HAS_EEPROM 1
+#define HAS_LOG 0
+#define HAS_PAD 1
+#define USE_INTERNAL_FLASH 1
+#define IGNITE_ON_P0 0
+#define PACKET_HAS_MASTER 0
+#define PACKET_HAS_SLAVE 0
+#define AO_DATA_RING 32
+#define HAS_FIXED_PAD_BOX 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiob)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x7 << 3)
+#define LED_PIN_CONT_1 3
+#define LED_PIN_CONT_0 4
+#define LED_PIN_ARMED 5
+
+#define AO_LED_ARMED (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c) (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x3 << 3)
+
+#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+#define SPI_CS_PORT P1
+#define SPI_CS_SEL P1SEL
+#define SPI_CS_DIR P1DIR
+
+#define SPI_CONST 0x00
+
+#define AO_PAD_NUM 2
+#define AO_PAD_PORT (&stm_gpiob)
+
+#define AO_PAD_PIN_0 9
+#define AO_PAD_ADC_0 0
+
+#define AO_PAD_PIN_1 8
+#define AO_PAD_ADC_1 1
+
+#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1))
+#define AO_PAD_ALL_CHANNELS ((1 << 0) | (1 << 1))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED 3524
+#define AO_PAD_NO_IGNITER 16904
+#define AO_PAD_GOOD_IGNITER 22514
+
+#define AO_PAD_ADC_PYRO 8
+#define AO_PAD_ADC_BATT 2
+
+#define AO_ADC_FIRST_PIN 0
+
+#define AO_NUM_ADC 4
+
+#define AO_ADC_SQ1 AO_PAD_ADC_0
+#define AO_ADC_SQ2 AO_PAD_ADC_1
+#define AO_ADC_SQ3 AO_PAD_ADC_PYRO
+#define AO_ADC_SQ4 AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE 200
+#define AO_PYRO_R_SENSE_GND 22
+
+#define AO_FIRE_R_POWER_FET 0
+#define AO_FIRE_R_FET_SENSE 200
+#define AO_FIRE_R_SENSE_GND 22
+
+#define HAS_ADC_TEMP 0
+
+struct ao_adc {
+ int16_t sense[AO_PAD_NUM];
+ int16_t pyro;
+ int16_t batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf ("tick: %5u 0: %5d 1: %5d pyro: %5d batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], \
+ (p)->adc.sense[1], \
+ (p)->adc.pyro, \
+ (p)->adc.batt)
+
+#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \
+ (1 << AO_PAD_ADC_1) | \
+ (1 << AO_PAD_ADC_PYRO) | \
+ (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_task_init();
+
+ ao_timer_init();
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_adc_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_pad_init();
+
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+*.elf
+*.ihx
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+telefiretwo-*
+ao_product.h
--- /dev/null
+#
+# TeleFire build file
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pad.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_adc_stm.c \
+ ao_data.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_pad.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT_SRC = \
+ ao_telefiretwo.c
+
+PRODUCT=TeleFire-v0.2
+PRODUCT_DEF=-DTELEFIRETWO_V_0_2
+IDPRODUCT=0x000f
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME = telefiretwo-v0.2
+PROG = $(PROGNAME)-$(VERSION).elf
+HEX = $(PROGNAME)-$(VERSION).ihx
+
+SRC = $(ALTOS_SRC) $(PRODUCT_SRC)
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
+
--- /dev/null
+/*
+ * Copyright © 2010 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+
+#define HAS_FLIGHT 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_CHANNEL 4
+#define HAS_GPS 0
+#define HAS_SERIAL_1 0
+#define HAS_ADC 1
+#define HAS_DBG 0
+#define HAS_EEPROM 1
+#define HAS_LOG 0
+#define HAS_PAD 1
+#define USE_INTERNAL_FLASH 1
+#define IGNITE_ON_P0 0
+#define PACKET_HAS_MASTER 0
+#define PACKET_HAS_SLAVE 0
+#define AO_DATA_RING 32
+#define HAS_FIXED_PAD_BOX 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiob)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 4-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x3 << 4)
+#define LED_PIN_CONT_0 4
+#define LED_PIN_ARMED 5
+
+#define AO_LED_ARMED (1 << LED_PIN_ARMED)
+#define AO_LED_CONTINUITY(c) (1 << (4 - (c)))
+#define AO_LED_CONTINUITY_MASK (0x1 << 4)
+
+#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK)
+
+/* Alarm A */
+#define AO_SIREN
+#define AO_SIREN_PORT (&stm_gpiob)
+#define AO_SIREN_PIN 8
+
+/* Alarm B */
+#define AO_STROBE
+#define AO_STROBE_PORT (&stm_gpiob)
+#define AO_STROBE_PIN 9
+
+#define SPI_CONST 0x00
+
+#define AO_PAD_NUM 1
+#define AO_PAD_PORT (&stm_gpioa)
+
+#define AO_PAD_PIN_0 1
+#define AO_PAD_ADC_0 0
+
+#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0))
+#define AO_PAD_ALL_CHANNELS ((1 << 0))
+
+/* test these values with real igniters */
+#define AO_PAD_RELAY_CLOSED 3524
+#define AO_PAD_NO_IGNITER 16904
+#define AO_PAD_GOOD_IGNITER 22514
+
+#define AO_PAD_ADC_PYRO 2
+#define AO_PAD_ADC_BATT 8
+
+#define AO_ADC_FIRST_PIN 0
+
+#define AO_NUM_ADC 3
+
+#define AO_ADC_SQ1 AO_PAD_ADC_0
+#define AO_ADC_SQ2 AO_PAD_ADC_PYRO
+#define AO_ADC_SQ3 AO_PAD_ADC_BATT
+
+#define AO_PYRO_R_PYRO_SENSE 200
+#define AO_PYRO_R_SENSE_GND 22
+
+#define AO_FIRE_R_POWER_FET 0
+#define AO_FIRE_R_FET_SENSE 200
+#define AO_FIRE_R_SENSE_GND 22
+
+#define HAS_ADC_TEMP 0
+
+struct ao_adc {
+ int16_t sense[AO_PAD_NUM];
+ int16_t pyro;
+ int16_t batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf ("tick: %5u 0: %5d pyro: %5d batt %5d\n", \
+ (p)->tick, \
+ (p)->adc.sense[0], \
+ (p)->adc.pyro, \
+ (p)->adc.batt)
+
+#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \
+ (1 << AO_PAD_ADC_PYRO) | \
+ (1 << AO_PAD_ADC_BATT))
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_pad.h>
+#include <ao_exti.h>
+#include <ao_radio_cmac_cmd.h>
+
+void
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+
+ ao_task_init();
+
+ ao_timer_init();
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_adc_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_pad_init();
+
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+}
--- /dev/null
+*.elf
+*.ihx
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telefiretwo-v0.2
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpiob
+#define AO_BOOT_APPLICATION_PIN 6
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
ao_radio_spi.h \
ao_radio_cmac.h \
ao_cc1120_CC1120.h \
- ao_debounce.h \
stm32l.h
#
ao_fec_tx.c \
ao_fec_rx.c \
ao_seven_segment.c \
- ao_debounce.c \
ao_quadrature.c \
ao_button.c \
ao_event.c \
ao_radio_cmac.h \
ao_cc1200_CC1200.h \
ao_cc1200.h \
- ao_debounce.h \
stm32l.h
#
ao_fec_tx.c \
ao_fec_rx.c \
ao_seven_segment.c \
- ao_debounce.c \
ao_quadrature.c \
ao_button.c \
ao_event.c \
--- /dev/null
+ao_product.h
+telelco*.elf
--- /dev/null
+#
+# AltOS build for TeleLCO
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_companion.h \
+ ao_data.h \
+ ao_sample.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_radio_spi.h \
+ ao_radio_cmac.h \
+ ao_cc1200_CC1200.h \
+ ao_cc1200.h \
+ stm32l.h
+
+#
+# Common AltOS sources
+#
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_beep_stm.c \
+ ao_eeprom_stm.c \
+ ao_fast_timer.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_cc1200.c \
+ ao_radio_cmac.c \
+ ao_aes.c \
+ ao_aes_tables.c \
+ ao_fec_tx.c \
+ ao_fec_rx.c \
+ ao_button.c \
+ ao_event.c \
+ ao_lco_two.c \
+ ao_lco_func.c \
+ ao_lco_cmd.c \
+ ao_radio_cmac_cmd.c
+
+PRODUCT=TeleLCOTwo-v0.1
+PRODUCT_DEF=-DTELELCOTWO
+IDPRODUCT=0x0023
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g
+
+PROGNAME=telelcotwo-v0.1
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telelcotwo.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG) $(HEX)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+$(OBJ): $(INC)
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+#define AO_CC1200_FOSC 40000000
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 1
+#define BEEPER_CHANNEL 4
+#define HAS_RADIO 1
+#define HAS_RADIO_RATE 1
+#define HAS_TELEMETRY 0
+#define HAS_AES 1
+#define HAS_FIXED_PAD_BOX 1
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+
+#define HAS_SPI_2 1 /* CC1200 */
+#define SPI_2_PB13_PB14_PB15 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_GPIO (&stm_gpiod)
+#define SPI_2_SCK 13
+#define SPI_2_MISO 14
+#define SPI_2_MOSI 15
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+
+#define HAS_I2C_2 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 0
+
+#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */
+
+/*
+ * Radio is a cc1200 connected via SPI
+ */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioa)
+#define AO_CC1200_SPI_CS_PIN 7
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpiob)
+#define AO_CC1200_INT_PIN (11)
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpiob)
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN
+
+/* Port A, pins 4-6 */
+#define LED_PORT_0_SHIFT 4
+#define LED_PORT_0_MASK 0x7
+
+#define LED_PIN_GREEN 0
+#define LED_PIN_AMBER 1
+#define LED_PIN_RED 2
+
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_AMBER (1 << LED_PIN_AMBER)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+/* Port B, pins 3-5 */
+#define LED_PORT_1_SHIFT 0
+#define LED_PORT_1_MASK (0x7 << 3)
+
+#define LED_PIN_CONTINUITY_1 3
+#define LED_PIN_CONTINUITY_0 4
+#define LED_PIN_REMOTE_ARM 5
+
+#define AO_LED_CONTINUITY_1 (1 << LED_PIN_CONTINUITY_1)
+#define AO_LED_CONTINUITY_0 (1 << LED_PIN_CONTINUITY_0)
+
+#define AO_LED_CONTINUITY_NUM 2
+
+#define AO_LED_REMOTE_ARM (1 << LED_PIN_REMOTE_ARM)
+
+#define LEDS_AVAILABLE (AO_LED_RED | \
+ AO_LED_AMBER | \
+ AO_LED_GREEN | \
+ AO_LED_CONTINUITY_1 | \
+ AO_LED_CONTINUITY_0 | \
+ AO_LED_REMOTE_ARM)
+
+/*
+ * Use event queue for input devices
+ */
+
+#define AO_EVENT 1
+
+/*
+ * Buttons
+ */
+
+#define AO_BUTTON_COUNT 3
+#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP
+
+#define AO_BUTTON_0_PORT &stm_gpioa
+#define AO_BUTTON_0 0
+
+#define AO_BUTTON_ARM_0 0
+
+#define AO_BUTTON_1_PORT &stm_gpioa
+#define AO_BUTTON_1 1
+
+#define AO_BUTTON_ARM_1 1
+
+#define AO_BUTTON_ARM_NUM 2
+
+#define AO_BUTTON_2_PORT &stm_gpioa
+#define AO_BUTTON_2 2
+
+#define AO_BUTTON_FIRE 2
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_companion.h>
+#include <ao_profile.h>
+#include <ao_pyro.h>
+#include <ao_aes.h>
+#include <ao_button.h>
+#include <ao_lco.h>
+#include <ao_lco_cmd.h>
+#include <ao_radio_cmac_cmd.h>
+#include <ao_eeprom.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_GREEN);
+ ao_beep_init();
+ ao_task_init();
+
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_button_init();
+
+ ao_eeprom_init();
+
+ ao_radio_init();
+
+ ao_usb_init();
+
+ ao_config_init();
+
+ ao_lco_init();
+ ao_lco_cmd_init();
+// ao_radio_cmac_cmd_init();
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telelcotwo-v0.1
+include $(TOPDIR)/stm/Makefile-flash.defs
--- /dev/null
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+/* External crystal at 8MHz */
+#define AO_HSE 8000000
+
+#include <ao_flash_stm_pins.h>
+
+/* Fire switch. Press at power on to get boot loader */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 2
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#endif /* _AO_PINS_H_ */
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
*/
#define HAS_MMA655X 1
+#define AO_MMA655X_INVERT 0
#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15
#define AO_MMA655X_CS_PORT (&stm_gpiod)
#define AO_MMA655X_CS_PIN 4
--- /dev/null
+telerepeat-*
+ao_product.h
--- /dev/null
+--directory=../cc1111:../product:../kernel:../drivers:.
+
--- /dev/null
+gnuplot -persist << EOF
+set ylabel "altitude (m)"
+set y2label "error"
+set xlabel "time (s)"
+set xtics border out nomirror
+set ytics border out nomirror
+set y2tics border out nomirror
+plot "$1" using 1:3 with lines axes x1y1 title "raw height",\
+"$1" using 1:21 with lines axes x1y2 title "error"
+EOF
import java.util.concurrent.*;
import java.util.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPS
extends AltosUIFrame
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSConfigUI
extends AltosUIDialog
JLabel version_value;
JLabel serial_value;
AltosUIFreqList radio_frequency_value;
- JTextField radio_calibration_value;
+ JLabel radio_calibration_value;
JRadioButton radio_enable_value;
AltosUIRateList rate_value;
JComboBox<String> aprs_interval_value;
return product != null && product.startsWith("TeleGPS");
}
- void set_radio_calibration_tool_tip() {
- if (radio_calibration_value.isEnabled())
- radio_calibration_value.setToolTipText("Tune radio output to match desired frequency");
- else
- radio_calibration_value.setToolTipText("Cannot tune radio while connected over packet mode");
- }
-
void set_radio_enable_tool_tip() {
if (radio_enable_value.isEnabled())
radio_enable_value.setToolTipText("Enable/Disable telemetry and RDF transmissions");
c.anchor = GridBagConstraints.LINE_START;
c.insets = ir;
c.ipady = 5;
- radio_calibration_value = new JTextField(String.format("%d", 1186611));
- radio_calibration_value.getDocument().addDocumentListener(this);
+ radio_calibration_value = new JLabel(String.format("%d", 1186611));
pane.add(radio_calibration_value, c);
- set_radio_calibration_tool_tip();
row++;
/* Radio Enable */
}
}
- public int radio_calibration() throws AltosConfigDataException {
- return parse_int("radio calibration", radio_calibration_value.getText(), false);
- }
-
public void set_radio_enable(int new_radio_enable) {
if (new_radio_enable >= 0) {
radio_enable_value.setSelected(new_radio_enable > 0);
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSDisplayThread extends Thread {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSInfo extends AltosUIFlightTab {
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSPreferences
extends AltosUIConfigure
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSState extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_9.*;
-import org.altusmetrum.altosuilib_9.*;
+import org.altusmetrum.altoslib_10.*;
+import org.altusmetrum.altosuilib_10.*;
public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
package org.altusmetrum.telegps;
import java.awt.event.*;
-import org.altusmetrum.altoslib_9.*;
+import org.altusmetrum.altoslib_10.*;
public class TeleGPSStatusUpdate implements ActionListener {