-commit d16e60858427bf7dbe83a858728ebf097a09207a
+commit 26f61380ce6b4df80fa0b5a8a242cef79d5ae339
Author: Bdale Garbee <bdale@gag.com>
-Date: Sat Sep 13 11:29:19 2014 -0600
+Date: Sat Feb 7 22:23:38 2015 -0700
- ignore cal_values file in bringup directory
+ document addition of TeleDongle to the set of ARM targets to save binaries for
-commit 40885ae5e6be66faf08cdb9b481d1d998856ca4b
+commit 4231d68bae69d9a7d1f52205002db452cd5f986d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 20:42:15 2015 -0800
+
+ Bump java library versions
+
+ Lots of minor API/ABI changes; make sure people can install both 1.5
+ and 1.6 at the same time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c72d83ccd207b5300a90f2e84de6c5c96642478c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 20:36:10 2015 -0800
+
+ altosuilib: Don't offer to graph some GPS details that TM doesn't log
+
+ When using a TM eeprom file, various minor GPS details are logged
+ (course, ground speed, climb rate, etc). Make sure these aren't
+ offered up for graphing.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 426bacbbd6e0573b143e7c48d71db977e53181fc
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 20:22:19 2015 -0800
+
+ altosuilib: Get the Eeprom download progress bar working again
+
+ The eeprom download code wasn't computing the start of each state
+ transition correctly, so the progress bar was snapping to the end of
+ the chunk for each state.
+
+ Invalid state values would snap the bar to the right side.
+
+ Landed state wasn't ever seen, so the bar would not ever fill.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit aea188e4227993c508c7045d02f2bc87abd4e428
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 18:10:34 2015 -0800
+
+ doc: update 1.6 release notes with recent bug fixes
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0dd733efdbb66535889aafecbba45f49266ed886
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 17:49:39 2015 -0800
+
+ altosuilib: Set the icon and title of the telemetry scanning dialog
+
+ Just need to call 'super' to get the window configured correctly.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9d5a6914982a29d22103e0202735c9e01ee9e831
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 17:35:15 2015 -0800
+
+ altoslib: Clear saved TelemetryReader state instead of resetting in ScanUI
+
+ Instead of attempting to mash the saved state from AltosScanUI, just
+ throw it away in AltosTelemetryReader.reset. Much cleaner, and more reliable.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cbc9ecd960d0dd27a2275b4550c30c5c88ccf5bb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 17:09:40 2015 -0800
+
+ altosuilib: Reset telemetry state after processing it
+
+ This avoids re-using stale state after switching telemetry reception
+ parameters around, which otherwise generates spurious entries for the
+ wrong frequencies in the scan results list.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c0ce45100dd205f59cd84465138c74d9b31df0bb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 17:08:03 2015 -0800
+
+ altoslib: Drop telemetry packets processed while monitoring is disabled
+
+ A lag between the thread queuing telemetry packets and one pulling
+ them out can result in stale telemetry data being returned to the
+ reader. Fix this by dropping telemetry read while monitoring is disabled.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8a2be4d36a3b116d82529805430c5fb665688267
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 15:09:57 2015 -0800
+
+ altosuilib: Wait for product data while scanning
+
+ Now that Altos only sends config information once every 5 seconds, we
+ want to keep waiting for that if we're receiving packets successfully.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e70f3dca01b15b75b0b8795eb71bd12817af4800
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 14:43:11 2015 -0800
+
+ altoslib: Mark listener as 'not running' on EOF.
+
+ This adds a 'running' member to the AltosListenerState class, and when
+ the replay reader reaches EOF, marks the listener as no longer
+ running.
+
+ AltosUI and TeleGPS now display 'done' in the 'Age' field when this
+ occurs, to let the user know that the replay is over.
+
+ Also make sure that the display timers are stopped when this happens,
+ or when the window is closed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 08f07d0af123e1c307bc4c0c973da07fae8246b1
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 14:40:17 2015 -0800
+
+ altosui: Remove the dregs of AltosDroid load-old-telem code
+
+ AltosDroid used to scan the old .telem file to return to the previous
+ flight state on restart. Now it just loads the old state object
+ instead, a vast improvement in performance.
+
+ To do that, there were some changes in the altoslib code
+ required. This patch just removes those, fixing replay bugs in TeleGPS
+ along the way.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0d08c427188f7b748d9ea7651143bc843e9c2691
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 13:09:18 2015 -0800
+
+ altos: ao_packet_getchar needs to return 'int' so AO_READ_AGAIN works
+
+ With ao_packet_getchar returning 'char', AO_READ_AGAIN would get
+ converted to 0xff instead of -1 on return, making ao_packet_echo
+ either produce a bogus character on output, breaking command
+ responses, or wedge and never exit when the link was dropped.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4a5c64bef6952f25cadebc3e1f9909a5f513e015
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 02:37:36 2015 -0800
+
+ Update version 1.6 release notes with more bug fixes
+
+ A few bugs found during release testing are notable enough to be
+ included in the release notes.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 211cb482e4da04dc032432abc236ef8b5a5e732f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 01:30:21 2015 -0800
+
+ altos: Separate out ao_tracker force from dbg
+
+ Allow enabling telemetry when USB is connected without also enabling
+ the motion debugging output.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f9f235bce84df3a6c0261e9d256aac544f87f70f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 01:05:57 2015 -0800
+
+ altos/lpc: Give up on interrupt-driven SPI driver
+
+ There are just too many limitations in when interrupts are delivered
+ to make them useful. Instead, just drive the SPI directly with the
+ CPU. At higher spi speeds (6Mhz or more), it's probably faster to do
+ it this way anyways.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4b52f67abd0f9ed6d8208556007d75e7ee735cf0
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Feb 7 01:05:03 2015 -0800
+
+ altos/drivers: Increase SPI speed of CC115L to 6MHz
+
+ The datasheet says that the maximum for back-to-back data is 6.5MHz.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ba22e2dbf87b139f0349f4dd8a7e6046514f5bad
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 23:50:49 2015 -0800
+
+ altoslib: Initialize GPS data to MISSING for Monitor Idle mode
+
+ Make sure any un-set values are flagged correctly for the Monitor Idle
+ UI by using the init() method.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 31fd32cd75f4f22458f0dc82823934672e16b988
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 21:50:47 2015 -0800
+
+ altoslib: Use 'stateless' for Monitor Idle
+
+ This reflects the lack of flight state progression during Monitor Idle
+ and ensures that the GPS 'ready' indicator will light after 10 solid
+ GPS fixes.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 449c6731b1977c7623dd006ec2db56f383f8d85a
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 20:45:28 2015 -0800
+
+ altoslib: Support TeleGPS for Monitor Idle
+
+ TeleGPS has ADC and GPS values, so build the necessary ADC parser and
+ then hook up GPS parsing.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 58f06706383418ebfa56d88ba51411e6185e09df
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 20:40:05 2015 -0800
+
+ altosuilib: Don't show 'Sats in view' for TeleGPS eeprom graphing
+
+ We don't log the visible sats from TeleGPS, only the basic GPS
+ info. Have AltosFlightStats track whether sat info is present, then
+ use that to elide the Sats In View graph entry as needed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 35ad1833b10595564de84c88f44a214b1c134ccf
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 20:36:44 2015 -0800
+
+ altosuilib: EEProm download from TeleGPS doesn't have states
+
+ As TeleGPS doesn't have flight states, the EEProm download progress
+ bar shouldn't show 'state invalid', and it should use a different
+ scale for each block.
+
+ Fix this by having AltosConfigData know which devices have state based
+ on their log format, then mark the progress bar state limits as
+ 'invalid/invalid' instead of 'boost/landed'. Then have the progress
+ bar use that to set a more reasonable scale for each block.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 66e7a8081c07d0d96a31ae34963d430f06dccdfb
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 04:45:17 2015 -0800
+
+ altoslib: Store MS5607 data in AltosConfigData for use by AltosMs5607
+
+ When doing 'Monitor Idle', we fetch new config data each iteration and
+ pass that to each of the readers, including ms5607. Instead of
+ re-fetching the config data there, just store the ms5607 parameters
+ when we fetch it the first time and copy it over.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 14d524782af4f06d7f3722dcc852772ec493c2cc
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 03:36:10 2015 -0800
+
+ Package TeleDongle-v3.0 firmware with TeleGPS and AltosUI apps
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit df47839824dd4e708c22fbf8f4a3054b9c45b9c3
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 03:34:30 2015 -0800
+
+ altosuilib: New teledongle and telebt devices are not pair-programmed
+
+ Only list telebt-v1 and teledongle-v0 as pair-programmed devices so
+ that newer versions go through the self-programming process
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 21ff52befb27decc4b23458315620c47d7a07b21
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 03:33:28 2015 -0800
+
+ micropeak: Install Windows AltusMetrum driver bits
+
+ Make AltOS-based µPUSB devices work with MicroPeak
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a3f26f6d0c7574b8cdaecbccd7cfe89aaeb736b0
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 03:32:27 2015 -0800
+
+ micropeak: Support both FTDI and Altus Metrum USB IDs
+
+ The windows driver only returns FTDI devices when
+ altos_ftdi_list_start is invoked, so we need to call both that and the
+ regular altos_list_start to get all of the devices.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cc707432c6eaedb9587bb63ac570146b356b6bfd
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 03:31:07 2015 -0800
+
+ micropeak: Fix file association registry install on Windows
+
+ Need to invoke DisableX64FSRedirection before setting file association
+ registry entries or Windows won't find our application.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1fc5c8625f649b43d93f23a5fa1ba16773f2d0db
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 03:03:58 2015 -0800
+
+ windows: Look for current Java version in \SOFTWARE\Wow6432Node
+
+ I have no idea what this is, but I found the Java version down in
+ there...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 83d3d967f576a57285d40e77c4a17303edeef4f1
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 03:03:00 2015 -0800
+
+ Add 'keithp-fat' target for uploading temporary builds to keithp's machine
+
+ This lets me quickly prepare a new test version for Windows/Mac in a
+ single command.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7a7d60d72e2e742fbc364489721f356806966c03
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Feb 6 01:29:56 2015 -0800
+
+ libaltos: Use more SetupDi API to get Windows 7 listing devices
+
+ My Windows 7 box doesn't include 'SymbolicName' in the registry, but
+ SetupDiGetDeviceInstanceId *does* return something that includes
+ vid/pid/serial, so use that in preference.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 98db372758470cdaf7b517d670a7ce9186c787bc
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Feb 5 22:25:35 2015 -0800
+
+ Update docs for 1.6
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9fac8b639d2142c90eb95771cda1f6559e987db2
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jan 16 22:09:26 2015 +1300
+
+ altos/lpc: Double buffer USB data transfers
+
+ This allocates twice the space in the USB memory so that transactions
+ can be double buffered without using separate CPU memory.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+ Conflicts:
+ src/lpc/ao_usb_lpc.c
+
+commit 0671b3c8c24c9f33be77a10315c4669f33c516d7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Feb 5 16:08:44 2015 -0800
+
+ altos/lpc: Clean up USB endpoint access functions
+
+ The USB device endpoints can have two pointers in them, but we use
+ only the first. Fix the access functions to take an index as to which
+ we want so that we can disable the other address registers with them
+ instead of requiring open-coded access.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a01ce949611b0c18df54c3f3877a43d27699c258
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Feb 5 15:34:05 2015 -0800
+
+ altos/easymini-v1.0: Shrink stack to deal with USB changes
+
+ Reverting the USB double buffering means using more RAM, need to
+ shrink the EasyMini stack to accomodate that.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2bde76fe852d7908a968168580be4cd4dc0333d6
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Feb 5 15:01:03 2015 -0800
+
+ altos/teledongle-v3.0: Shrink stacks to 320 bytes to fit in ram
+
+ The old USB code had static in/out buffers in ram
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5bf39f674b3d5ee98b55f42562a5ba1a9328ff07
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Feb 5 14:56:13 2015 -0800
+
+ Revert LPC usb performance improvements
+
+ There's something screwy going on, sticking garbage in the input
+ buffer at boot time
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef69872c824668146a3876f1f3d0d2e51d3e4c8d
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Feb 5 14:54:27 2015 -0800
+
+ Revert "altos/lpc: Fix double-buffered USB changes"
+
+ This reverts commit 41a0604ad1ea1a03e2db7d41731dbadf466b45db.
+
+commit aeca3b46bc1726a06952cc2ff86f50c6d80ed1e1
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Feb 4 22:55:24 2015 -0800
+
+ ao-bringup: Add turnon_teledonglev3
+
+ TeleDongle v3 uses the LPC11U14 processor which has no on-chip eeprom,
+ so we must reflash the device to set the default radio calibration value.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bc41ab47b928b837724f8bc6b84d0b5b47c25df3
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Feb 4 20:33:04 2015 -0800
+
+ altos: Rename teledongle-v1.9 as teledongle-v3.0
+
+ No hardware changes from the 1.9 prototypes to the 3.0 final version.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit dbafa16cfa897b2a5c6cf455cf8675e83eb0d7d6
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Feb 4 20:30:15 2015 -0800
+
+ altos/telebt-v3.0: Set initial radio cal to a sensible value
+
+ CC1200 uses a different xtal than CC1120, so the default calibration
+ needs to change. This value hit 434.550 on SN 2407, so it seems like a
+ reasonable place to start.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit be443d8d50ad8f59a74bf2f4e810a7359ff72132
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:57:14 2015 +0100
+
+ altos/telebt-v3.0: Add monitor bits
+
+ Will be useful to actually be able to receive telemetry
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6eb145d48cfcabf757093433bd2314a80e490a17
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:46:40 2015 +0100
+
+ altos/usbtrng-v2.0: Select PA11/PA12 mapping config value
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8f9e192e9d1c6fab9843939ff9117f6bb3725943
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:44:52 2015 +0100
+
+ altos/stmf0: Support PA11/PA12 remapping
+
+ Small pin-count versions of the STMF0 can remap PA11/PA12 on the same
+ pins as PA9/PA10. These are used by USB, so have the USB driver deal
+ with remapping them.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 466d3e977ca279f97944141fcc12c04f4f58212e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:44:07 2015 +0100
+
+ altos/telebt-v3.0: Turn red LED off after initialization
+
+ This lets the user know the device successfully initialized.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 845ae016d700c37948e053ead5f7e2778356fda3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:43:06 2015 +0100
+
+ altos/telebt-v3.0: Fix stdio setup for BTM
+
+ Make sure the BTM module is allowed to be included in stdio, but delay
+ adding that until the BT link is running.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a138e05ae6241a6743ca9f64528124f5f6c8e0ee
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:42:01 2015 +0100
+
+ altos: Always include a check for stdio overflow
+
+ For some reason, the check for running out of space to record stdio
+ devices was disabled when only one device was expected.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 870428a909025988a8cd834755ea166e2d1e34ca
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:39:17 2015 +0100
+
+ altos/btm: Add fancier debug. Pull serial reset port low.
+
+ Adds an interactive debugging mode to help diagnose BTM issues.
+
+ Discovered that the serial reset pin on the BTM needs to be pulled low
+ for the device to work correctly.
+
+ Leave the bt link interrupt disabled until things are initialized.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 44a503a8cf3778cad5469c592e8ccbae58e44b97
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Feb 1 16:36:51 2015 +0100
+
+ altos/stm: Add ability to delay STDIO usage for serial ports
+
+ Bluetooth needs to delay adding the serial port to stdio until the
+ link is up and running. The cc1111 serial driver had
+ DELAY_SERIAL_*_STDIN bits which have been added to the STM serial driver.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 252211e9e54a1e6f4efe2df6382ce60c909de70c
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jan 30 14:04:50 2015 +0100
+
+ And, also add the TeleBT v3.0 flash loader Makefile
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bfa5c70a827ac8be23ca48797edc14e13461d6ac
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jan 30 14:03:55 2015 +0100
+
+ Oops, forgot the TeleBT-v3.0 Makefile
+
+ git doesn't warn about files named 'Makefile' because they're supposed
+ to be generated...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 8ca1f234586225caea1040bc229b63491dadc1cb
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 27 20:41:15 2015 -0800
+
+ altos/stmf0: Re-implement fast ADC code for stmf0
+
+ This creates a ring buffer for ADC data so that ADC fetching can run
+ in parallel with other activities.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3749426af1e900a1b3354922fdd7e8b3bfa38084
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 27 17:18:42 2015 -0800
+
+ altos/usbtrng-v2.0: Use stmf042 hardware CRC unit
+
+ Switch from software to hardware for CRC computation. I think this
+ must be faster, right?
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a95d6776dea86cdc4bdc3512505ba7e75365c127
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 27 16:55:27 2015 -0800
+
+ altos/stmf0: Add CRC driver
+
+ Sets up the stm32f0 CRC hardware, exposing inline functions to access
+ it. DMA access is possible, but usbtrng can't use that.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 79f3434013650fe4e3d76e5eb56a10000ee34249
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Jan 27 09:36:19 2015 -0800
+
+ altos/stmf0: Remove remaining stm32l bits from stm32f0 code
+
+ These were left over from the stm32f0 initial implementation work; now
+ it's more useful to list only the bits which are valid.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit bf08397202860a73417cd1711012eb3e33f308c3
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jan 26 22:23:19 2015 -0800
+
+ ao-tools: Add ao-usbtrng to dump RNG data for testing
+
+ ao-usbtrng reads a specified number of kilobytes of random data from
+ a random number generator.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ee91e1da606c8a8fade278a3aeae9c1cc9014b84
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jan 26 22:22:00 2015 -0800
+
+ altos/stm: Fix typo in stm32l.h
+
+ This crept in while working on the stmf0 bits. oops.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ac1a58af4d281a9bc3572dc503982a94e439a4c1
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jan 26 22:16:18 2015 -0800
+
+ altos/usbtrng-v2.0: Add random output command
+
+ Read chunks of random ADC data, do some CRC16 computations to de-bias
+ and merge 4 bytes of input data into 2 bytes of output data, then dump
+ that out over USB.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 729bb7a405460db8d44c9ff6ee903b28c7499a02
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jan 26 22:14:57 2015 -0800
+
+ altos/stmf0: Add ADC and DMA APIs
+
+ The ADC api is what USBtrng wants; a way to repeatedly read a single
+ ADC input as fast as possible.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a01effc2f64c757c907e0f4937b4d3710b97bde0
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jan 26 22:12:40 2015 -0800
+
+ altos/stmf0: Add faster USB path
+
+ This adds a way to allocate private USB buffers for sending data
+ without needing to copy it again. It requires ensuring that all
+ accesses are 16 bits aligned to 16 bit boundaries.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e1d5bcb1968e280b8ebdf6c8b12e8a87167fd890
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Jan 26 22:10:47 2015 -0800
+
+ altos/stmf0: Fix linker scripts to make ao_boot work
+
+ The flash loader ended up assuming ao_boot was at the start of ram,
+ while the application stuck it after the interrupt table (where it
+ needs to go).
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 32c68670af9f8aa690c64d64502e559c0df0c1db
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jan 25 19:58:38 2015 -0800
+
+ ao-tools: Add --wait option to ao-usbload
+
+ This waits forever for USB writes to complete, instead of timing out
+ after five seconds. Useful when debugging the device.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02b07a202839d6e68b3f0db7f8965478661db140
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jan 25 19:37:05 2015 -0800
+
+ altos: Add flash-loader to usbtrng-v2.0
+
+ Uses the new STM32F042 flash loading bits.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit df881bce8576f091b2d8cb53b8ce8a43aeedecde
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jan 25 19:35:19 2015 -0800
+
+ altos: Add self-flash support for STM32F042 processor
+
+ Also moves the usual address for applications out of the way of the
+ flash loader.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02e1058fa52ee7c867ea6c9031ebb9e21d14889c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jan 25 16:43:48 2015 -0800
+
+ altos: USBtrng v2.0 hardware bringup
+
+ Gets the USB connection running and blinks the LEDs.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 02f03df6d089cafae99f8ce15dcbd87f6e78d749
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Jan 25 16:42:39 2015 -0800
+
+ altos: Initial STMF04x support
+
+ Basic clock configuration, OS support, LED and USB drivers.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0e7d1c89fea98eabca738f10cbfebec631be3bb7
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Jan 24 11:18:59 2015 -0800
+
+ altos: Add support for TeleBT v3.0
+
+ Add support to the BTM driver for non-CC1111 interrupts
+ Add HW flow control to STM serial driver
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 41a0604ad1ea1a03e2db7d41731dbadf466b45db
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jan 22 21:31:45 2015 -0800
+
+ altos/lpc: Fix double-buffered USB changes
+
+ These got merged when we were down in Auckland, but before they'd been
+ finished. Transmitting worked fine, but receiving was mis-configuring
+ the OUT buffer size in the hardware.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 291eec859606b73b43072cd2debfbb92659e0d95
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Jan 22 20:34:43 2015 -0800
+
+ altos: Get rid of some accidental debug code
+
+ I was debugging the accelerometer calibration code and left some
+ printfs in it, which made TM run out of flash space.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e05e0c6b71a1df65f188e00622e9632eb27510fd
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Jan 16 22:09:26 2015 +1300
+
+ Set version to 1.5.9.1
+
+commit 2a053d3d157e00b6a6406f4f78ddb8e298b6c4b7
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 22 17:27:09 2014 -0800
+
+ altos/lpc: Switch LPC SPI driver to interrupt-driven
+
+ This improves performance for SPI transfers, while allowing other
+ tasks to get work done during longer SPI transfers.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 213a6604ec225e843f30244e6f94d0ebb3d27e46
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 22 17:11:51 2014 -0800
+
+ altos: Adjust CC1200 RSSI reporting value
+
+ On the test setup, we were about 13dB off, so tweak the settings to
+ suit. This result wasn't tested; it's just a rough offset until we get
+ a production run of TeleDongle boards back to do more systematic
+ measurements.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 014dcc1f179237dc247fafa4a2cff91809260681
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Dec 22 17:10:33 2014 -0800
+
+ altos: Document cc115l power measured at RF setting 0x03 as -31.75dBm
+
+ We built a custom TeleGPS load for radio sensitivity measurements with
+ the lowest documented power level setting (0x03), and measured the
+ power out at that value of -31.75dBm on the test board.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cf09ee2a4b093c56b64260c3db3f5e07143aa888
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Dec 9 21:44:53 2014 -0800
+
+ ao-bringup: Clear pending output before setting frequency.
+
+ Maybe this will unwedge things
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5b7ec0c69343db3793c0317939b5eff1f2d04752
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Dec 6 15:08:53 2014 -0800
+
+ micropeak: Support µPUSB with our own USB ids
+
+ This matches the new µPUSB id as well as the FTDI USB id.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7e52ef59082cb2afdba498233c429321c37a6ac3
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Dec 6 15:08:29 2014 -0800
+
+ altoslib: Add usbtrng, usbrelay and mpusb USB ids
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7339d2379713b5b7e4c4fe6bad89ed93f9d39e82
+Merge: d1f9121 b6462ca
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sat Dec 6 15:39:53 2014 -0700
+
+ Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos
+
+commit d1f9121593fe30b924223e89ef4d596b5bec2b25
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sat Dec 6 15:39:35 2014 -0700
+
+ improve test procedures for TeleMega
+
+commit b6462ca3a7e99fe390ec97f94c23d36fab8c294d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 23 18:56:40 2014 -0800
+
+ altos/cc1200: With PQT wide open, we can't use PQT_REACHED for start
+
+ Because we're allowing even signals only weakly correlated with the
+ preamble through to sync detection, we can't use the PQT_REACHED
+ symbol to tell when a packet header has been seen. Instead, just look
+ for SYNC_FOUND.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 0e3eeaf59688dac92eb3a27d589923126cb34e00
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 23 18:50:57 2014 -0800
+
+ altos/cc1200: Open up preamble detect to improve sensitivity
+
+ Increase soft decision PQT value to max (15) to ensure that we detect
+ even weak packets.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit eabeb76a2a9acb624ae364c4f0f315bfc3549d98
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 23 18:31:15 2014 -0800
+
+ altos/cc1200: Wait for packet to be placed in FIFO during receive
+
+ This changes the receive code to use MCU_STATUS, waiting for
+ MARC_STATUS1 to indicate that the packet is in the fifo before reading
+ it out.
+
+ It also fixes the receive timeout code to keep receiving if the
+ preamble or sync have been seen when the timeout fires. This makes
+ TeleLCO able to use short timeouts during scanning while still
+ successfully receiving packets.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2163f6e6b341b7840f03e89d568699b8ea186435
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 16 16:39:18 2014 -0800
+
+ altos/teledongle-v1.8: Make this the same as teledongle v1.9
+
+ Remove RSSI LED blinking, add CRC error LED
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 54f7ab842a8cba3003cd5a9deb2515151263ca2e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 16 16:38:12 2014 -0800
+
+ altos: Allow TeleMega to be built without MPU6000
+
+ Robert Braibish's board has a dead MPU6000; this fix lets the TeleMega
+ firmware build without that driver so the rest of the board could be verified.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f16ea9abfaac9eee3b0935c586e383ae046d6cf5
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 16 16:37:15 2014 -0800
+
+ altosui: Remove duplicate AltosUIPreferencesBackend.java
+
+ There's a copy in altosuilib
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit abdf3177293c57e659017b64819c13f11c126011
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 16 13:41:27 2014 -0800
+
+ altos/microsplash: fix .gitignore to ignore resulting binary
+
+commit 97a321692c2e41a1d3f77fb541780ada945eff52
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 16 13:40:15 2014 -0800
+
+ Add AltosDroid release note for version 1.5
+
+commit 47956ac01397c0a7fafc6b0a4840113186924b2e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Nov 16 13:17:55 2014 -0800
+
+ altosdroid: East and West were flipped in all GPS output
+
+ East is positive, West is negative
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 5aae1446026a08bf8f09c56b960545eff30a8bd1
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Nov 15 22:52:42 2014 -0800
+
+ altosdroid: Save AltosState and restore at startup
+
+ Instead of re-parsing the old logfile, save the current state in the
+ preferences database and restore at restart of the
+ TelemetryService. This makes the state get restored even before the BT
+ connection is recovered.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 52ce23327bd81e2d40a1817442e75bd6b60ffe95
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Nov 15 22:50:31 2014 -0800
+
+ altoslib: add AltosPreferences state save/restore interfaces
+
+ This serializes an entire AltosState object and stores it in the
+ preferences database for later retrieval. AltosDroid uses this to
+ recover the old state data when restarting.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a488da3ca72fe0778b2d79a8cac935621d1d789d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Nov 15 22:49:06 2014 -0800
+
+ altosdroid: TabMap needs to expose () constructor
+
+ Otherwise we get an exception at startup time for some reason.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit deda23963586eb07a32f9a3c83a0355178e19340
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Nov 15 22:48:15 2014 -0800
+
+ altoslib: Add getBytes/putBytes interface to AltosPreferencesBackend
+
+ This lets us store arbitrary binary data in the preferences database
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e5dd00ef0014364fc059970cc020f209b3b16cf8
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Nov 15 22:46:01 2014 -0800
+
+ altosdroid: Don't display MISSING flight number
+
+ Just check and clear the entry if we end up seeing that value
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 60edcfe410e7fa848813d6c1ed8dc9808887d041
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Nov 15 16:03:32 2014 -0800
+
+ altoslib: Make AltosState serializable
+
+ This involved making every class it references serializable as well
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4d4fee0b0091a1b6257a06f62b1078778cdb417f
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Nov 10 14:41:17 2014 -0800
+
+ altoslib: Missing headers for mag sensor in CSV output
+
+ Kelsey Black <nmonic@gmail.com> reported that the TeleMega CSV output
+ was missing the header labels for the mag sensor data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 437eba2ff27b2b7dfd0f363819b9a43ab8b28ead
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 20:04:47 2014 -0800
+
+ altos: Reset interrupt flags before TX in CC1200 driver
+
+ Failing to reset the flags set during interrupt leads to
+ short-circuiting transmission and not a lot of packets going out.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7f742824673e5e6034defdb09b66d4d56eb8d4fe
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 16:05:49 2014 -0800
+
+ altos/teledongle-v1.9: Switch to NXP processor as on prototype boards
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6a082d9b5ed169b9d4153885f3535987e5ae5d84
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 16:04:56 2014 -0800
+
+ altos/lpc: Disable JTAG when using pins for GPIO
+
+ JTAG is enabled by default, making those pins not support GPIO unless
+ specifically configured.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 58db263cc835be0abb972654c2d7369718c88b37
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 16:04:14 2014 -0800
+
+ altos/lpc: Declare SPI send parameters as const
+
+ This matches STM
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d3dd45b060c996153ff8195bd371e9e1f3b15efb
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 16:02:47 2014 -0800
+
+ altos: Use other TeleDongle LED for CRC-invalid packet reporting
+
+ Instead of blinking out some fake-o RSSI indication, just blink the
+ red LED when a packet with a bad CRC is received.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2313cdacefb2139bc68cd98e782c54d706af0704
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 16:02:07 2014 -0800
+
+ altosuilib: GPS errors are recorded in floating point, not integers
+
+ Fix the format used to present them in the info table.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2f0ff9675017655846a8abc617b4dc9a3666d0b9
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 16:01:24 2014 -0800
+
+ altos: Use AO_SPO_SPEED_FAST for CC1200
+
+ This asks for the fastest available SPI speed, instead of fixing it to
+ 8MHz, which may not be supported on every architecture.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 80a0397dde2f787fb20fd2520b274b826c68ed5a
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 16:00:06 2014 -0800
+
+ altos: Stop attempting to ramp power on CC115L
+
+ The PA register on the 115L isn't in any way monotonic, making the old
+ code broken. Just rempve it instead of fixing it; we don't ramp
+ anywhere else...
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2e5ffd839fe5be99359e4c86a96f03148bac698
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 15:58:42 2014 -0800
+
+ altos: Declare port register type only in arch header
+
+ Instead of defaulting to 8 bits, explicitly require declaration of the
+ type of the port register for each architecture.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2060d6ca222a04608e598baf59757f12ea2ec70
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Nov 6 13:27:29 2014 -0800
+
+ Move teledongle 1.9 to 1.8; there's a new 1.9
+
+ 1.9 is now the lpc11u14-based form-factor prototype board.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b67556949aa080fc5e70771e972de880e44eca12
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Nov 5 22:11:44 2014 -0800
+
+ altos: Rename microwater to microsplash
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b0e903a76276e33f531eade42ac721c9490c6758
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Oct 30 21:59:45 2014 -0700
+
+ altosui: Pop up 'Connecting' dialog during Monitor Idle
+
+ This was a bit harder than expected as I had to wire up a way to shut
+ down the whole monitor idle window when you clicked on the cancel button.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ef00182c79bd7a56fbc5d782cb8f4aa0079bb86f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 25 21:14:25 2014 -0700
+
+ altos: Increase CC1200 SPI data rate to 8MHz
+
+ This got set to 125kHz to make debugging with a logic analyzer easier
+ and never changed back to a reasonable speed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4d51570ed8776461d084726149923c5be43d622e
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 25 19:56:25 2014 -0700
+
+ altos: Fix up telemetry delay computations
+
+ With RDF, APRS and telemetry all being sent at varying rates,
+ computing when to send the next radio data is not as simple as sending
+ telemetry and then figuring out whether to send RDF and/or APRS.
+
+ Fix this by computing times for the next telemetry/rdf/aprs packet,
+ and only sending each when that time has passed. Compute the delay
+ until the next radio activity as the minimum time to any transmission.
+
+ This also adds code to the config bits to reset the radio times
+ whenever something changes that might affect which radio data to send
+ next.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c831f1ffb378c20b7513d209d60cdd5dee9db85b
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 25 17:44:48 2014 -0700
+
+ altos: Perform cc1200 calibration less often. Tweak radio params
+
+ This performs calibration after every 4 operations, or when the
+ frequency changes. This reduces the time it takes to get to receive
+ mode.
+
+ This also makes the sync and preamble qualifiers more strict to reject
+ bad packets.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 3f7263f57b1b697d92ed6c3d62956e5bdfc11f24
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 25 11:20:44 2014 -0700
+
+ altos: Remove old AO_SEND_ALL_BARO bits
+
+ This was used for testing the original TeleMini which couldn't log
+ data at full speed.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ae4be19f8ab0899a879a10aec28dc381f44dd2c7
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 25 10:21:30 2014 -0700
+
+ altos: Build TeleDongle v1.9 by default
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 51ef3fad6435c0b21945d48fbbaa5a4c092c4960
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 25 10:20:07 2014 -0700
+
+ altos: Increase PQT value for cc1200 improving sensitivity
+
+ The PQT value indicates how 'good' the preamble is; higher values
+ allow a lower quality of preamble to pass the test, permitting more
+ packets to be decoded.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9102183b40f0b32d4fb6d24502b79a6431184310
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 25 10:17:48 2014 -0700
+
+ altos: Sort out ao_gps_print altitude fetching
+
+ ao_gps_print is used by both teledongle/telebt and the host-based GPS
+ test code. The first instance uses the old internal GPS structure,
+ containing just a 16-bit altitude while the second uses an
+ ao_telemetry structure, which contains 32 bits split into two
+ members.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit cb83b5432e1320726ad496ded78cced7274618b0
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Oct 7 05:36:18 2014 +0200
+
+ altos/teledongle-v1.9: Add remaining code to complete the project
+
+ This turns the prototype board into a full teledongle
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 4a3fe79266a77f8fc001117f49db1d2f14f9e6b6
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Oct 7 05:34:06 2014 +0200
+
+ altos: Complete cc1200 driver
+
+ Deal with differences between cc1120 and cc1200, including built-in
+ packet support and various register changes.
+
+ This now works to send and receive telemetry, as well as send APRS and
+ RDF.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7fea8b245cdccc1ec77aa559433952f339676473
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Oct 7 05:35:10 2014 +0200
+
+ altos: Expose telemetry altitude macros even without GPS
+
+ This allows for APRS testing in the new teledongle code
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 484b530a16a54ca8fde412c3f466bfe7eed978cd
+Author: Keith Packard <keithp@keithp.com>
+Date: Tue Oct 7 05:32:00 2014 +0200
+
+ altos: Mark STM ao_spi_send as taking const pointer
+
+ We don't write to this, so let it be const for type checking
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit c17dff05b70d98e3193e8e68cc9599f3a30270b5
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Oct 24 19:10:45 2014 -0700
+
+ ao-tools/ao-send-telem: Add verbose, fake and rate options
+
+ Verbose dumps some data while sending packets.
+ Fake sends constructed packets, once every 500ms.
+ Rate sets the transmit bit rate.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e2562ee43b8558df0836217ea3a187b36e2669b3
+Author: Keith Packard <keithp@keithp.com>
+Date: Wed Oct 15 16:10:11 2014 -0700
+
+ altosuilib: Try to detect the architecture when loading JNI lib
+
+ Look at sun.arch.data.model and os.arch to try and load the right
+ libaltos file the first time.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 88df7cd314269fa1debe226b49b7e4e9dc238d8e
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Oct 24 21:21:19 2014 -0700
+
+ altoslib: synchronize access to serial debug output list
+
+ This list is access by both the receiver and the monitor task, so it
+ needs to be locked to prevent collisions.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 221824b038bf18ca43a38c82d18b0ae9586ba565
+Author: Bdale Garbee <bdale@gag.com>
+Date: Thu Oct 9 13:11:16 2014 -0600
+
+ document pyro current limits in an appendix
+
+commit ffda6989e856e66a1bea253e82cb70f51ada3e7a
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Oct 5 00:07:10 2014 -0700
+
+ altos: Add prototype TeleDongle v1.9 code
+
+ Lights up the hardware, sends carrier and RDF tones. A bit more cc1200
+ work to be done still.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 27a467d802a80a33ea20eb5cda2558d03caa2c00
+Author: Keith Packard <keithp@keithp.com>
+Date: Sun Oct 5 00:03:28 2014 -0700
+
+ altos: Copy cc1120 driver to cc1200 driver and hack a bit
+
+ The cc1200 is similar to the cc1120, although many registers have
+ changed.
+
+ This driver can send a bare carrier and an RDF tone, but does not yet
+ receive or transmit telemetry data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 62628c8b429d06ee834f0b6511c430cbeaab9303
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 4 00:30:54 2014 -0700
+
+ altos: Fix syntax error with ao_log_mega change.
+
+ Missed a semi-colon.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 00ae706dab6e8fddef4c5730a17c433a022228b7
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 4 00:11:13 2014 -0700
+
+ altoslib: Compute tilt angle from eeprom data
+
+ This copies the computation of tilt angle from the firmware so that
+ post-flight analysis can also show the data.
+
+ This change also renames all of the imu values to make them easier to
+ understand:
+
+ accel gyro axis
+
+ along roll length of the board
+ across pitch across the board
+ through yaw through the board.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit a757fd5af53f5721a949181372548afa4757d6c9
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 4 00:10:03 2014 -0700
+
+ altosui: Update 'Imperial Units' checkbox when units change
+
+ If you have two graphs running, make sure the imperial units
+ checkboxes agree.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 656d8fe17532ca6c7d1d43996f187df2f14f5395
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 4 00:07:39 2014 -0700
+
+ altoslib: Deal with new Mega log format that has 32-bit gyro cal
+
+ This adds parsing for the new log format type to get all 32 bits of
+ the gyro calibration data.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9521dc63671b69065d27fc1ccba6d20cc90643cb
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Oct 4 00:04:39 2014 -0700
+
+ altos: Record 32-bits for gyro calibration values
+
+ The gyro ground calibration values are scaled by 512 to provide a bit
+ more precision for the computations. This means they don't fit in 16
+ bits, so change the format of the flight log record. Also change the
+ reported format so that AltosUI has a chance of figuring it out.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 95d9248da78f86240dbe77e2c206420dc509c9cf
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Sep 29 12:57:27 2014 -0700
+
+ altosui: Check for map and stats table when changing units/fonts in graph
+
+ AltosGraphUI wasn't making sure the map and stats tables were present
+ before attempting to adjust font size and units.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 40c5535b65a75374fb1dbbd994c29324db814f5b
+Author: Keith Packard <keithp@keithp.com>
+Date: Mon Sep 29 12:56:04 2014 -0700
+
+ altos: Handle antenna down in ao_flight_test
+
+ Parse the Pad orientation config value and flip the accelerometer
+ value back around in antenna down configuration.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b97a125a9f8bd9619833647a9b6aa6329103e136
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 26 22:58:13 2014 -0700
+
+ ao-bringup: Auto-select programmer for teledongle turnon
+
+ Bdale's programmer is SN 100, Keith's is SN 186. Use the username to
+ figure out which one to use.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit b4eba3f3a58a9c35e3699ff14405b997c1318d91
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 26 22:53:39 2014 -0700
+
+ altos: Make sure we drop the SPI mutex when aborting cc1120 recv
+
+ The cc1120 receive code is 'twisty', in that it acquires the SPI mutex
+ in the middle of an interrupt handler so that it can quickly start the
+ radio when the signal comes in. This means we have to be careful to
+ drop that mutex in all paths which leave the receive code, including
+ when the packet receive is aborted mid-way through the process.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 22661ba69b8919116092382f1f5aa0dc79d02cc9
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sat Sep 13 17:56:51 2014 -0600
+
+ store cal value correctly even when we didn't need to change it
+
+commit b0eb63205223e2982d0ded08503c3f128420270f
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 13 15:59:18 2014 -0700
+
+ altosdroid: Update notebook to reflect current status
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 9dc426756742fb967fdd21e1fcec54edeb4b12ac
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 13 15:52:56 2014 -0700
+
+ altosui: Bring up main window when doing --replay or --graph
+
+ This shows the main window when replaying or graphing files so that
+ you can interact with that, changing the global configuration or doing
+ other stuff.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 75d5368cb2a95f3f7385952669a14765460f549d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 13 15:51:50 2014 -0700
+
+ altosui: Fix --replay to run in realtime after boost
+
+ I added the ability to rapidly replay files for AltosDroid to recover
+ from a crash, but didn't change AltosUI to use realtime mode again.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 04b5cc37659b1b3d6b62f1ef17b17c0492434cba
+Author: Bdale Garbee <bdale@gag.com>
+Date: Sat Sep 13 16:37:42 2014 -0600
+
+ reflect filename changes in LLC repo
+
+commit 93d1cedc94358ebf5c2af537a25a242f6c19954c
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 13 15:23:40 2014 -0700
+
+ altosdroid: Automatically sign the released version if the key is available
+
+ Look in ~/altusmetrumllc for release.keystore and Passphrase and
+ enable building and signing of the release binary.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 2731486c12678a7d3bd7ec79e74a2fcaf20845bd
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 13 13:38:31 2014 -0700
+
+ altosdroid: Update version code and name for 1.5
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e151c144fcdb1da96e715f29c049dc4869e1d53d
+Author: Keith Packard <keithp@keithp.com>
+Date: Sat Sep 13 13:00:58 2014 -0700
+
+ Mark master branch as past the 1.5 point
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit ff7c006e50515040d43399899fac26a3fe26d8a7
Author: Bdale Garbee <bdale@gag.com>
-Date: Sat Sep 13 11:28:19 2014 -0600
+Date: Sat Sep 13 12:31:08 2014 -0600
+
+ updated to reflect changes from 1.5 release
+
+commit 20d640ec504afbfdb69dba1b241d84af1e62abed
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 12 20:58:26 2014 -0700
+
+ ao-bringup: Improve igniter testing. Add TeleMega and TeleMetrum testing.
+
+ The script lets you re-try each one when they fail, which is nice if
+ you're hand-holding the setup.
+
+ The TeleMetrum and TeleMega tests are adapted from the EasyMega tests
+ and are hooked up to the turnon scripts.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit e0077866138a1e29ede7181e39f04860b866543a
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 12 20:57:05 2014 -0700
+
+ ao-tools/ao-test-igniter: Remove bogus printf
+
+ This must have been left over from testing; it prints "device (null)",
+ which isn't very useful.
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 6681d31929266fec9711b3d89a4f074cd2afcc6e
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 12 20:56:29 2014 -0700
+
+ ao-tools/ao-test-gps: Improve output formatting
+
+ Add a newline before printing out the flags and sats at exit time
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit f2d045570d2cda0abde67a68506cb3fc2e119ec3
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 12 17:22:37 2014 -0700
+
+ ao-bringup: Use C version of ao-test-gps in test-telegps
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit d0e597789ac298b108ea04cc1a2c999bcf14bc9c
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 12 17:22:03 2014 -0700
+
+ ao-tools: Add ao-test-gps program
+
+ This waits for GPS to report lock
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit def036794f1460a5457e6b86350712c336e296d6
+Author: Keith Packard <keithp@keithp.com>
+Date: Fri Sep 12 16:38:59 2014 -0700
+
+ ao-bringup: Use C version of test-flash for telegps
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 1630a8e458f174d6df1aa30ff30e3f02a10bdbf7
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Sep 11 19:59:58 2014 -0700
- need multi-arch in fat build
+ altosui: Ignore built .desktop file
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
-commit e969172a81e24f70c349b10f429e69817900c307
+commit 807e62ccebc83eb6427a63431d06effa074e5e76
Author: Keith Packard <keithp@keithp.com>
Date: Thu Sep 11 19:56:13 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 800f3377b1a374ad5cf826aa897efdcb08059040
+commit d7ad490a33900a788b15d1600ebaa2a71e6f35ff
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Sep 11 15:57:21 2014 -0700
+
+ altos: Add smaller altitude table file to .gitignore
+
+ Signed-off-by: Keith Packard <keithp@keithp.com>
+
+commit 7ad8921b164103629b246c25860297454aa7ec6b
+Author: Keith Packard <keithp@keithp.com>
+Date: Thu Sep 11 15:56:14 2014 -0700
+
+ altos/test: Add TMv2 test program to .gitignore
+
+commit 0cedc27e22a9fbc9ccfe1b403c84d728bb23220d
Author: Keith Packard <keithp@keithp.com>
Date: Thu Sep 11 15:00:25 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 793588e218102204e69755a16bc32ea5c67f29c7
+commit 6dafd7bf947d892e430cd565eb92a3366abb3604
Author: Keith Packard <keithp@keithp.com>
Date: Thu Sep 11 14:23:29 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 19730b872c61f34724b0f187f71cccb6a65251dd
+commit 368c7d583380b4453f432d5a965a1e4c45a92f92
Author: Keith Packard <keithp@keithp.com>
Date: Thu Sep 11 14:14:07 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 10e31d84ee5cdf10248988079df91354ae6ed612
-Author: Bdale Garbee <bdale@gag.com>
-Date: Wed Sep 10 01:33:33 2014 -0600
-
- update changelog for release
-
-commit 05e4094411f861bf29bea2e9c39c1b66f8f267f8
-Merge: acb2791 2ee937b
-Author: Bdale Garbee <bdale@gag.com>
-Date: Wed Sep 10 01:32:27 2014 -0600
-
- Merge branch 'master' into branch-1.5
-
commit 2ee937b603b181bb24768eb4d0e2f918a5377fd3
Author: Bdale Garbee <bdale@gag.com>
Date: Wed Sep 10 01:29:56 2014 -0600
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit acb279125c0fa377c8b1dbbb8634fba60f7f845b
-Author: Bdale Garbee <bdale@gag.com>
-Date: Wed Sep 10 00:05:07 2014 -0600
-
- update ChangeLog
-
-commit 5de00e9e39cff2d3b409c2ce99caa994f0a36202
-Merge: b3fba98 a72b768
-Author: Bdale Garbee <bdale@gag.com>
-Date: Wed Sep 10 00:02:57 2014 -0600
-
- Merge branch 'master' into branch-1.5
-
commit a72b7683606d3e741043011c929482a0a168a5c9
Author: Bdale Garbee <bdale@gag.com>
Date: Tue Sep 9 23:44:45 2014 -0600
more build dependencies for processing icons
-commit b3fba989a84db7d904e09a8f47e3a86d4e0f9577
-Merge: 28bd505 1fb200d
-Author: Bdale Garbee <bdale@gag.com>
-Date: Wed Sep 10 00:01:33 2014 -0600
-
- Merge branch 'master' into branch-1.5
-
commit 1fb200d18cc385230b3af574816ec354682cc5c9
Author: Keith Packard <keithp@keithp.com>
Date: Tue Sep 9 23:00:14 2014 -0700
Signed-off-by: Keith Packard <keithp@keithp.com>
-commit 28bd5057252e61bc5b1a35a00bc1f9fdfde097f7
-Author: Bdale Garbee <bdale@gag.com>
-Date: Tue Sep 9 23:23:27 2014 -0600
-
- updated ChangeLog for 1.5 release
-
-commit 45f50ad3a8ce69c708974711a5939c42a74bf53b
-Author: Bdale Garbee <bdale@gag.com>
-Date: Tue Sep 9 23:22:58 2014 -0600
-
- releasing version 1.5
-
commit a8c799c48a52bf13466536db627b66bfe2a435cd
Author: Keith Packard <keithp@keithp.com>
Date: Tue Sep 9 09:38:03 2014 -0700
fat:
cd src && $(MAKE) all
cd doc && $(MAKE) all
- cd libaltos && $(MAKE) all
+ cd libaltos && $(MAKE) fat
cd altoslib && $(MAKE) all
cd altosuilib && $(MAKE) all
cd icon && $(MAKE) fat
cd micropeak && $(MAKE) fat
cd telegps && $(MAKE) fat
+fat_linux = \
+ altosui/Altos-Linux-$(VERSION).sh altosui/Altos-Linux-$(VERSION).tar.bz2 \
+ telegps/TeleGPS-Linux-$(VERSION).sh telegps/TeleGPS-Linux-$(VERSION).tar.bz2 \
+ micropeak/MicroPeak-Linux-$(VERSION).sh micropeak/MicroPeak-Linux-$(VERSION).tar.bz2
+
+fat_mac = \
+ altosui/Altos-Mac-$(VERSION).dmg \
+ telegps/TeleGPS-Mac-$(VERSION).dmg \
+ micropeak/MicroPeak-Mac-$(VERSION).dmg
+
+fat_windows = \
+ altosui/Altos-Windows-$(VERSION_DASH).exe \
+ telegps/TeleGPS-Windows-$(VERSION_DASH).exe \
+ micropeak/MicroPeak-Windows-$(VERSION_DASH).exe
+
+keithp-fat: fat
+ scp -p $(fat_linux) $(fat_mac) $(fat_windows) keithp.com:public_html/altos-$(VERSION)
+
set-java-versions:
$(top_srcdir)/fix-java-versions org.altusmetrum.altoslib=$(ALTOSLIB_VERSION) org.altusmetrum.altosuilib=$(ALTOSUILIB_VERSION)
this pushes packages for each platform to web site
# store a stable copy of ARM binaries for production use
- cp src/easymini-v1.0/*.elf \
+ cp src/easymega-v1.0/*.elf \
+ src/easymini-v1.0/*.elf \
+ src/teledongle-v3.0/*.elf \
src/telegps-v1.0/*.elf \
src/telemega-v1.0/*.elf \
src/telemetrum-v2.0/*.elf \
~/altusmetrumllc/Binaries/
- cp src/easymini-v1.0/flash-loader/*.elf \
+ cp src/easymega-v1.0/flash-loader/*.elf \
+ src/easymini-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/telemetrum-v2.0/flash-loader/*.elf \
and move the MicroPeak installers from AltOS/releases to there
- create /home/bdale/web/altusmetrum/TeleGPS/releases/<rev>,
- and move the MicroPeak installers from AltOS/releases to there
+ and move the TeleGPS installers from AltOS/releases to there
- go edit ~/web/altusmetrum/AltOS/releases/<rev>.mdwn,
/home/bdale/web/altusmetrum/MicroPeak/releases/<rev>.mdwn, and
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.altusmetrum.AltosDroid"
- android:versionCode="5"
- android:versionName="1.3">
+ android:versionCode="6"
+ android:versionName="1.5">
<uses-sdk android:targetSdkVersion="10" android:minSdkVersion="10"/>
<!-- Google Maps -->
<uses-feature android:glEsVersion="0x00020000" android:required="true"/>
if ANDROID
-all_target=bin/AltosDroid-debug.apk bin/AltosDroid-release-unsigned.apk
+all_target=bin/AltosDroid-debug.apk
+if ANDROID_RELEASE
+all_target+=bin/AltosDroid-release.apk
+endif
else
all_target=
endif
bin/AltosDroid-release.apk: bin/AltosDroid-release-unsigned.apk
jarsigner -sigalg SHA1withDSA -digestalg SHA1 \
- -keystore release.keystore \
+ -keystore ~/altusmetrumllc/google-play-release.keystore \
+ -storepass:file ~/altusmetrumllc/google-play-passphrase \
-signedjar bin/AltosDroid-release-signed.apk \
bin/AltosDroid-release-unsigned.apk AltosDroid
$(ZIPALIGN) -f 4 \
*) Channel scanning. Provide the ability to search for telemetry
signals like AltosUI does.
- *) Highlight current frequency in the frequency list.
-
- Placed current frequency in title bar
-
*) Random frequency selection. Provide some mechanism to input
arbitrary radio frequencies. Could be like AltosUI which allows
you to edit the list of frequencies and assign names to them,
*) Select satellite imaging mode
+ *) TeleBT battery voltage
+
+ *) Deal with long bluetooth list. Currently, a list longer than
+ the screen makes it impossible to use entries off the bottom.
+
+ *) Pickle/unpickle state instead of reloading entire history from
+ file. Current restart time is lengthy.
+
+Completed features
+
+ *) Highlight current frequency in the frequency list.
+
+ Placed current frequency in title bar
+
*) Remember most-recently-used TBT and frequency, perhaps
auto-connect at startup.
Done
- *) TeleBT battery voltage
--- /dev/null
+Version 1.5
+
+ * TeleGPS support
+ * Reloads previous flight data at startup
+ * Fixes crash when touching map
+ * Reconnect to TeleBT at startup
+ * Remember radio settings
//import android.os.Message;
import android.util.Log;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosBluetooth extends AltosLink {
import android.app.AlertDialog;
import android.location.Location;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosDroid extends FragmentActivity implements AltosUnitsListener {
// Debugging
}
if (saved_state == null || state.flight != saved_state.flight) {
Log.d(TAG, "update flight");
- mFlightView.setText(String.format("%d", state.flight));
+ if (state.flight == AltosLib.MISSING)
+ mFlightView.setText("");
+ else
+ mFlightView.setText(String.format("%d", state.flight));
}
if (saved_state == null || state.state != saved_state.state) {
Log.d(TAG, "update state");
package org.altusmetrum.AltosDroid;
import android.content.Context;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosDroidPreferences extends AltosPreferences {
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Environment;
+import android.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosDroidPreferencesBackend implements AltosPreferencesBackend {
public final static String NAME = "org.altusmetrum.AltosDroid";
return prefs.getString(key, def);
}
+ public byte[] getBytes(String key, byte[] def) {
+ String save = prefs.getString(key, null);
+
+ if (save == null)
+ return def;
+
+ byte[] bytes = Base64.decode(save, Base64.DEFAULT);
+ return bytes;
+ }
+
public void putBoolean(String key, boolean value) {
editor.putBoolean(key, value);
}
editor.putString(key, value);
}
+ public void putBytes(String key, byte[] bytes) {
+ String save = Base64.encodeToString(bytes, Base64.DEFAULT);
+ editor.putString(key, save);
+ }
+
public void remove(String key) {
editor.remove(key);
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import android.location.Location;
import android.app.Activity;
import android.graphics.Color;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosVoice {
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import android.app.Activity;
import android.os.Bundle;
if (state.gps != null) {
mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
- mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+ mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
} else {
mLatitudeView.setText("");
mLongitudeView.setText("");
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import android.app.Activity;
import android.os.Bundle;
}
if (state.gps != null) {
mLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
- mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+ mLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
}
mApogeeVoltageView.setText(AltosDroid.number("%4.2f V", state.apogee_voltage));
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import android.app.Activity;
import android.os.Bundle;
}
if (state != null && state.gps != null) {
mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
- mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+ mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
}
if (receiver != null) {
mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
- mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
+ mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
}
if (state != null) {
import java.util.Arrays;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
}
if (state.gps != null) {
mTargetLatitudeView.setText(AltosDroid.pos(state.gps.lat, "N", "S"));
- mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "W", "E"));
+ mTargetLongitudeView.setText(AltosDroid.pos(state.gps.lon, "E", "W"));
if (state.gps.locked && state.gps.nsat >= 4)
center (state.gps.lat, state.gps.lon, 10);
}
else
accuracy = 1000;
mReceiverLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
- mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
+ mReceiverLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
center (receiver.getLatitude(), receiver.getLongitude(), accuracy);
}
}
+
+ public TabMap() {
+ }
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import android.app.Activity;
import android.os.Bundle;
if (receiver.hasAltitude())
altitude = receiver.getAltitude();
mPadLatitudeView.setText(AltosDroid.pos(receiver.getLatitude(), "N", "S"));
- mPadLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "W", "E"));
+ mPadLongitudeView.setText(AltosDroid.pos(receiver.getLongitude(), "E", "W"));
set_value(mPadAltitudeView, AltosConvert.height, 6, altitude);
}
}
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.util.Log;
import android.os.Handler;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class TelemetryReader extends Thread {
AltosLink link;
AltosState state = null;
- AltosFlightReader stacked;
-
LinkedBlockingQueue<AltosLine> telemQueue;
public AltosState read() throws ParseException, AltosCRCException, InterruptedException, IOException {
public void close() {
state = null;
- if (stacked != null) {
- stacked.close(false);
- stacked = null;
- }
link.remove_monitor(telemQueue);
link = null;
telemQueue.clear();
AltosState state = null;
try {
- if (D) Log.d(TAG, "starting reader");
- while (stacked != null) {
- AltosState stacked_state = null;
- try {
- stacked_state = stacked.read();
- } catch (ParseException pe) {
- continue;
- } catch (AltosCRCException ce) {
- continue;
- }
- if (stacked_state != null)
- state = stacked_state;
- else
- stacked = null;
- }
- if (state != null) {
- if (D) Log.d(TAG, "Send initial state");
- handler.obtainMessage(TelemetryService.MSG_TELEMETRY, state).sendToTarget();
- }
if (D) Log.d(TAG, "starting loop");
while (telemQueue != null) {
try {
}
}
- public TelemetryReader (AltosLink in_link, Handler in_handler, AltosFlightReader in_stacked) {
+ public TelemetryReader (AltosLink in_link, Handler in_handler, AltosState in_state) {
if (D) Log.d(TAG, "connected TelemetryReader create started");
link = in_link;
handler = in_handler;
- stacked = in_stacked;
- state = null;
+ state = in_state;
telemQueue = new LinkedBlockingQueue<AltosLine>();
link.add_monitor(telemQueue);
link.set_telemetry(AltosLib.ao_telemetry_standard);
if (D) Log.d(TAG, "connected TelemetryReader created");
}
-
- private static AltosFlightReader existing_data(AltosLink link) {
- if (link == null)
- return null;
-
- File file = AltosPreferences.logfile(link.serial);
- if (file != null) {
- AltosStateIterable iterable = AltosStateIterable.iterable(file);
- if (iterable != null)
- return new AltosReplayReader(iterable.iterator(), file, false);
- }
- return null;
- }
-
- public TelemetryReader(AltosLink link, Handler handler) {
- this(link, handler, existing_data(link));
- }
}
import android.location.LocationListener;
import android.location.Criteria;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class TelemetryService extends Service implements LocationListener {
case MSG_TELEMETRY:
// forward telemetry messages
s.telemetry_state.state = (AltosState) msg.obj;
+ if (s.telemetry_state.state != null) {
+ if (D) Log.d(TAG, "Save state");
+ AltosPreferences.set_state(0, s.telemetry_state.state, null);
+ }
if (D) Log.d(TAG, "MSG_TELEMETRY");
s.sendMessageToClients();
break;
private Message message() {
if (telemetry_state == null)
Log.d(TAG, "telemetry_state null!");
+ if (telemetry_state.state == null)
+ Log.d(TAG, "telemetry_state.state null!");
return Message.obtain(null, AltosDroid.MSG_STATE, telemetry_state);
}
if (D) Log.d(TAG, "connected bluetooth configured");
telemetry_state.connect = TelemetryState.CONNECT_CONNECTED;
- mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler);
+ mTelemetryReader = new TelemetryReader(mAltosBluetooth, mHandler, telemetry_state.state);
mTelemetryReader.start();
if (D) Log.d(TAG, "connected TelemetryReader started");
telemetry_state.connect = TelemetryState.CONNECT_READY;
+ AltosSavedState saved_state = AltosPreferences.state(0);
+
+ if (saved_state != null) {
+ if (D) Log.d(TAG, String.format("recovered old state flight %d\n", saved_state.state.flight));
+ telemetry_state.state = saved_state.state;
+ }
+
// Start our timer - first event in 10 seconds, then every 10 seconds after that.
timer.scheduleAtFixedRate(new TimerTask(){ public void run() {onTimerTick();}}, 10000L, 10000L);
package org.altusmetrum.AltosDroid;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import android.location.Location;
public class TelemetryState {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
-public class AltosAccel extends AltosUnits {
+import java.io.*;
+
+public class AltosAccel extends AltosUnits implements Serializable {
public double value(double v, boolean imperial_units) {
if (imperial_units)
public int show_fraction(int width, boolean imperial_units) {
return width / 9;
}
-}
\ No newline at end of file
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosCRCException extends Exception {
public int rssi;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
}
void write_advanced_header() {
- out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z");
+ out.printf("accel_x,accel_y,accel_z,gyro_x,gyro_y,gyro_z,mag_x,mag_y,mag_z");
}
void write_advanced(AltosState state) {
- AltosIMU imu = state.imu;
- AltosMag mag = state.mag;
-
- if (imu == null)
- imu = new AltosIMU();
- if (mag == null)
- mag = new AltosMag();
out.printf("%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f,%7.2f",
- imu.accel_x, imu.accel_y, imu.accel_z,
- imu.gyro_x, imu.gyro_y, imu.gyro_z,
- mag.x, mag.y, mag.z);
+ state.accel_along(), state.accel_across(), state.accel_through(),
+ state.gyro_roll(), state.gyro_pitch(), state.gyro_yaw(),
+ state.mag_along(), state.mag_across(), state.mag_through());
}
void write_gps_header() {
has_basic = true;
if (state.battery_voltage != AltosLib.MISSING)
has_battery = true;
- if (state.imu != null || state.mag != null)
+ if (state.accel_across() != AltosLib.MISSING)
has_advanced = true;
if (state.gps != null) {
has_gps = true;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
-public class AltosCompanion {
+import java.io.*;
+
+public class AltosCompanion implements Serializable {
public final static int board_id_telescience = 0x0a;
public final static int MAX_CHANNELS = 12;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.*;
import java.text.*;
public int tracker_motion;
public int tracker_interval;
+ /* HAS_GYRO */
+ public int accel_zero_along, accel_zero_across, accel_zero_through;
+
+ /* ms5607 data */
+ public int ms5607_reserved;
+ public int ms5607_sens;
+ public int ms5607_off;
+ public int ms5607_tcs;
+ public int ms5607_tco;
+ public int ms5607_tref;
+ public int ms5607_tempsens;
+ public int ms5607_crc;
+
public static String get_string(String line, String label) throws ParseException {
if (line.startsWith(label)) {
String quoted = line.substring(label.length()).trim();
storage_size = -1;
storage_erase_unit = -1;
stored_flight = 0;
+
+ accel_zero_along = -1;
+ accel_zero_across = -1;
+ accel_zero_through = -1;
}
public void parse_line(String line) {
/* Version also contains MS5607 info, which we ignore here */
+ try { ms5607_reserved = get_int(line, "ms5607 reserved:"); } catch (Exception e) {}
+ try { ms5607_sens = get_int(line, "ms5607 sens:"); } catch (Exception e) {}
+ try { ms5607_off = get_int(line, "ms5607 off:"); } catch (Exception e) {}
+ try { ms5607_tcs = get_int(line, "ms5607 tcs:"); } catch (Exception e) {}
+ try { ms5607_tco = get_int(line, "ms5607 tco:"); } catch (Exception e) {}
+ try { ms5607_tref = get_int(line, "ms5607 tref:"); } catch (Exception e) {}
+ try { ms5607_tempsens = get_int(line, "ms5607 tempsens:"); } catch (Exception e) {}
+ try { ms5607_crc = get_int(line, "ms5607 crc:"); } catch (Exception e) {}
+
/* Config show replies */
/* HAS_FLIGHT */
/* Log listing replies */
try { get_int(line, "flight"); stored_flight++; } catch (Exception e) {}
+
+ /* HAS_GYRO */
+ try {
+ if (line.startsWith("IMU call along")) {
+ String[] bits = line.split("\\s+");
+ if (bits.length >= 8) {
+ accel_zero_along = Integer.parseInt(bits[3]);
+ accel_zero_across = Integer.parseInt(bits[5]);
+ accel_zero_through = Integer.parseInt(bits[7]);
+ }
+ }
+ } catch (Exception e) {}
}
public AltosConfigData() {
dest.set_tracker_interval(tracker_interval);
}
+ public boolean log_has_state() {
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEGPS:
+ return false;
+ }
+ return true;
+ }
+
public void save(AltosLink link, boolean remote) throws InterruptedException, TimeoutException {
/* HAS_FLIGHT */
if (tracker_motion >= 0 && tracker_interval >= 0)
link.printf("c t %d %d\n", tracker_motion, tracker_interval);
+ /* HAS_GYRO */
+ /* UI doesn't support accel cal */
+
link.printf("c w\n");
link.flush_output();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosConfigDataException extends Exception {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public interface AltosConfigValues {
/* set and get all of the dialog values */
/*
* Sensor data conversion functions
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosConvert {
/*
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosDistance extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
import java.util.concurrent.*;
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
break;
case AltosLib.AO_LOG_FORMAT_TELEMEGA:
- eeprom = new AltosEepromMega(this, offset);
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+ eeprom = new AltosEepromMega(this, offset, log_format);
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
eeprom = new AltosEepromMetrum2(this, offset);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
}
boolean done;
- boolean start;
+ int prev_state;
+ int state_block;
void LogEeprom(AltosEeprom r) throws IOException {
if (r.cmd != AltosLib.AO_LOG_INVALID) {
state = new AltosState();
done = false;
- start = true;
if (flights.config_data.serial < 0)
throw new IOException("no serial number found");
/* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */
state_block = log.start_block;
+ prev_state = AltosLib.ao_flight_startup;
for (block = log.start_block; !done && block < log.end_block; block++) {
- monitor.set_value(state.state_name(),
- state.state,
- block - state_block,
- block - log.start_block);
-
AltosEepromChunk eechunk = new AltosEepromChunk(link, block, block == log.start_block);
/*
}
CaptureEeprom (eechunk, log_format);
+
+ if (state.state != prev_state && state.state != AltosLib.ao_flight_invalid) {
+ state_block = block;
+ prev_state = state.state;
+ }
+
+ monitor.set_value(state.state_name(),
+ state.state,
+ block - state_block,
+ block - log.start_block);
}
CheckFile(true);
if (eeprom_file != null) {
flights = given_flights;
success = false;
- monitor.set_states(AltosLib.ao_flight_boost, AltosLib.ao_flight_landed);
+ if (flights.config_data.log_has_state())
+ monitor.set_states(AltosLib.ao_flight_boost, AltosLib.ao_flight_landed);
+ else
+ monitor.set_states(AltosLib.ao_flight_invalid, AltosLib.ao_flight_invalid);
monitor.start();
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
case AltosLib.AO_LOG_FORMAT_TELEMETRY:
case AltosLib.AO_LOG_FORMAT_TELESCIENCE:
case AltosLib.AO_LOG_FORMAT_TELEMEGA:
- body = new AltosEepromIterable(AltosEepromMega.read(input));
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+ body = new AltosEepromIterable(AltosEepromMega.read(input, start.log_format));
break;
case AltosLib.AO_LOG_FORMAT_TELEMETRUM:
body = new AltosEepromIterable(AltosEepromMetrum2.read(input));
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
public int cmd;
public String data;
- public int config_a, config_b;
+ public int config_a, config_b, config_c;
public boolean last;
public boolean valid;
state.make_baro();
state.baro.crc = config_a;
break;
+ case AltosLib.AO_LOG_IMU_CAL:
+ state.set_accel_zero(config_a, config_b, config_c);
+ break;
case AltosLib.AO_LOG_SOFTWARE_VERSION:
state.set_firmware_version(data);
break;
case AltosLib.AO_LOG_APOGEE_LOCKOUT:
case AltosLib.AO_LOG_RADIO_RATE:
case AltosLib.AO_LOG_IGNITE_MODE:
+ break;
case AltosLib.AO_LOG_PAD_ORIENTATION:
+ state.set_pad_orientation(config_a);
+ break;
case AltosLib.AO_LOG_RADIO_ENABLE:
case AltosLib.AO_LOG_AES_KEY:
case AltosLib.AO_LOG_APRS:
case AltosLib.AO_LOG_BARO_CRC:
out.printf ("# Baro crc: %d\n", config_a);
break;
+ case AltosLib.AO_LOG_IMU_CAL:
+ out.printf ("# IMU cal: %d %d %d\n", config_a, config_b, config_c);
+ break;
case AltosLib.AO_LOG_FREQUENCY:
case AltosLib.AO_LOG_APOGEE_LOCKOUT:
case AltosLib.AO_LOG_RADIO_RATE:
case AltosLib.AO_LOG_IGNITE_MODE:
+ break;
case AltosLib.AO_LOG_PAD_ORIENTATION:
+ out.printf("# Pad orientation: %d\n", config_a);
+ break;
case AltosLib.AO_LOG_RADIO_ENABLE:
case AltosLib.AO_LOG_AES_KEY:
case AltosLib.AO_LOG_APRS:
cmd = AltosLib.AO_LOG_INVALID;
data = tokens[2];
}
+ } else if (tokens[0].equals("IMU") && tokens[1].equals("cal")) {
+ cmd = AltosLib.AO_LOG_IMU_CAL;
+ config_a = Integer.parseInt(tokens[3]);
+ config_b = Integer.parseInt(tokens[5]);
+ config_c = Integer.parseInt(tokens[7]);
+ } else if (tokens[0].equals("Pad") && tokens[1].equals("orientation:")) {
+ cmd = AltosLib.AO_LOG_PAD_ORIENTATION;
+ config_a = Integer.parseInt(tokens[2]);
} else
valid = false;
} catch (Exception e) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
public static final int max_sat = 12;
+ private int log_format;
+
public int record_length() { return record_length; }
/* AO_LOG_FLIGHT elements */
public int ground_accel_along() { return data16(8); }
public int ground_accel_across() { return data16(10); }
public int ground_accel_through() { return data16(12); }
- public int ground_roll() { return data16(14); }
- public int ground_pitch() { return data16(16); }
- public int ground_yaw() { return data16(18); }
+ public int ground_roll() {
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ return data32(16);
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+ return data16(14);
+ default:
+ return AltosLib.MISSING;
+ }
+ }
+ public int ground_pitch() {
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ return data32(20);
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+ return data16(16);
+ default:
+ return AltosLib.MISSING;
+ }
+ }
+ public int ground_yaw() {
+ switch (log_format) {
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA:
+ return data32(24);
+ case AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD:
+ return data16(18);
+ default:
+ return AltosLib.MISSING;
+ }
+ }
/* AO_LOG_STATE elements */
public int state() { return data16(0); }
public int svid(int n) { return data8(2 + n * 2); }
public int c_n(int n) { return data8(2 + n * 2 + 1); }
- public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException {
+ public AltosEepromMega (AltosEepromChunk chunk, int start, int log_format) throws ParseException {
+ this.log_format = log_format;
parse_chunk(chunk, start);
}
state.set_flight(flight());
state.set_ground_accel(ground_accel());
state.set_ground_pressure(ground_pres());
+ state.set_accel_ground(ground_accel_along(),
+ ground_accel_across(),
+ ground_accel_through());
+ state.set_gyro_zero(ground_roll() / 512.0,
+ ground_pitch() / 512.0,
+ ground_yaw() / 512.0);
break;
case AltosLib.AO_LOG_STATE:
state.set_tick(tick);
state.set_tick(tick);
state.set_ms5607(pres(), temp());
- AltosIMU imu = new AltosIMU();
- imu.accel_x = AltosIMU.convert_accel(accel_x());
- imu.accel_y = AltosIMU.convert_accel(accel_y());
- imu.accel_z = AltosIMU.convert_accel(accel_z());
+ AltosIMU imu = new AltosIMU(accel_y(), /* along */
+ accel_x(), /* across */
+ accel_z(), /* through */
+ gyro_y(), /* roll */
+ gyro_x(), /* pitch */
+ gyro_z()); /* yaw */
- imu.gyro_x = AltosIMU.convert_gyro(gyro_x());
- imu.gyro_y = AltosIMU.convert_gyro(gyro_y());
- imu.gyro_z = AltosIMU.convert_gyro(gyro_z());
- state.imu = imu;
+ if (log_format == AltosLib.AO_LOG_FORMAT_TELEMEGA_OLD)
+ state.check_imu_wrap(imu);
- AltosMag mag = new AltosMag();
- mag.x = AltosMag.convert_gauss(mag_x());
- mag.y = AltosMag.convert_gauss(mag_y());
- mag.z = AltosMag.convert_gauss(mag_z());
+ state.set_imu(imu);
- state.mag = mag;
+ state.set_mag(new AltosMag(mag_x(),
+ mag_y(),
+ mag_z()));
state.set_accel(accel());
}
}
- public AltosEepromMega (String line) {
+ public AltosEepromMega (String line, int log_format) {
+ this.log_format = log_format;
parse_string(line);
}
- static public LinkedList<AltosEeprom> read(FileInputStream input) {
+ static public LinkedList<AltosEeprom> read(FileInputStream input, int log_format) {
LinkedList<AltosEeprom> megas = new LinkedList<AltosEeprom>();
for (;;) {
if (line == null)
break;
try {
- AltosEepromMega mega = new AltosEepromMega(line);
+ AltosEepromMega mega = new AltosEepromMega(line, log_format);
if (mega.cmd != AltosLib.AO_LOG_INVALID)
megas.add(mega);
} catch (Exception e) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public interface AltosEepromMonitor {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.File;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public interface AltosFlashListener {
public void position(String label, int percent);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
public double pad_lat, pad_lon;
public boolean has_flight_data;
public boolean has_gps;
+ public boolean has_gps_sats;
+ public boolean has_gps_detail;
public boolean has_flight_adc;
public boolean has_battery;
public boolean has_rssi;
lat = lon = AltosLib.MISSING;
has_flight_data = false;
has_gps = false;
+ has_gps_sats = false;
has_flight_adc = false;
has_battery = false;
has_rssi = false;
lat = state.gps.lat;
lon = state.gps.lon;
has_gps = true;
+ if (state.gps.cc_gps_sat != null)
+ has_gps_sats = true;
+ if (state.gps.course != AltosLib.MISSING)
+ has_gps_detail = true;
}
if (state.imu != null)
has_imu = true;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosFrequency {
public double frequency;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
import java.util.concurrent.*;
+import java.io.*;
-public class AltosGPS implements Cloneable {
+public class AltosGPS implements Cloneable, Serializable {
public final static int MISSING = AltosLib.MISSING;
public AltosGPS (AltosLink link, AltosConfigData config_data) throws TimeoutException, InterruptedException {
boolean says_done = config_data.compare_version("1.0") >= 0;
+ init();
link.printf("g\n");
for (;;) {
String line = link.get_reply_no_dialog(5000);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosGPSSat {
public int svid;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.lang.Math;
+import java.io.*;
-public class AltosGreatCircle implements Cloneable {
+public class AltosGreatCircle implements Cloneable, Serializable {
public double distance;
public double bearing;
public double range;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosHeight extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.LinkedList;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosHexsym {
String name;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.*;
+import java.io.*;
-public class AltosIMU implements Cloneable {
- public double accel_x;
- public double accel_y;
- public double accel_z;
+public class AltosIMU implements Cloneable, Serializable {
+ public int accel_along;
+ public int accel_across;
+ public int accel_through;
- public double gyro_x;
- public double gyro_y;
- public double gyro_z;
+ public int gyro_roll;
+ public int gyro_pitch;
+ public int gyro_yaw;
-/*
- * XXX use ground measurements to adjust values
-
- public double ground_accel_x;
- public double ground_accel_y;
- public double ground_accel_z;
-
- public double ground_gyro_x;
- public double ground_gyro_y;
- public double ground_gyro_z;
-*/
-
- public static int counts_per_g = 2048;
+ public static double counts_per_g = 2048.0;
- public static double convert_accel(int counts) {
- return (double) counts / (double) counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION);
+ public static double convert_accel(double counts) {
+ return counts / counts_per_g * (-AltosConvert.GRAVITATIONAL_ACCELERATION);
}
public static double counts_per_degsec = 16.4;
- public static double convert_gyro(int counts) {
- return (double) counts / counts_per_degsec;
+ public static double convert_gyro(double counts) {
+ return counts / counts_per_degsec;
}
public boolean parse_string(String line) {
String[] items = line.split("\\s+");
if (items.length >= 8) {
- accel_x = convert_accel(Integer.parseInt(items[1]));
- accel_y = convert_accel(Integer.parseInt(items[2]));
- accel_z = convert_accel(Integer.parseInt(items[3]));
- gyro_x = convert_gyro(Integer.parseInt(items[5]));
- gyro_y = convert_gyro(Integer.parseInt(items[6]));
- gyro_z = convert_gyro(Integer.parseInt(items[7]));
+ accel_along = Integer.parseInt(items[1]);
+ accel_across = Integer.parseInt(items[2]);
+ accel_through = Integer.parseInt(items[3]);
+ gyro_roll = Integer.parseInt(items[5]);
+ gyro_pitch = Integer.parseInt(items[6]);
+ gyro_yaw = Integer.parseInt(items[7]);
}
return true;
}
public AltosIMU clone() {
AltosIMU n = new AltosIMU();
- n.accel_x = accel_x;
- n.accel_y = accel_y;
- n.accel_z = accel_z;
+ n.accel_along = accel_along;
+ n.accel_across = accel_across;
+ n.accel_through = accel_through;
- n.gyro_x = gyro_x;
- n.gyro_y = gyro_y;
- n.gyro_z = gyro_z;
+ n.gyro_roll = gyro_roll;
+ n.gyro_pitch = gyro_pitch;
+ n.gyro_yaw = gyro_yaw;
return n;
}
}
public AltosIMU() {
- accel_x = AltosLib.MISSING;
- accel_y = AltosLib.MISSING;
- accel_z = AltosLib.MISSING;
+ accel_along = AltosLib.MISSING;
+ accel_across = AltosLib.MISSING;
+ accel_through = AltosLib.MISSING;
+
+ gyro_roll = AltosLib.MISSING;
+ gyro_pitch = AltosLib.MISSING;
+ gyro_yaw = AltosLib.MISSING;
+ }
+
+ public AltosIMU(int accel_along, int accel_across, int accel_through,
+ int gyro_roll, int gyro_pitch, int gyro_yaw) {
+
+ this.accel_along = accel_along;
+ this.accel_across = accel_across;
+ this.accel_through = accel_through;
- gyro_x = AltosLib.MISSING;
- gyro_y = AltosLib.MISSING;
- gyro_z = AltosLib.MISSING;
+ this.gyro_roll = gyro_roll;
+ this.gyro_pitch = gyro_pitch;
+ this.gyro_yaw = gyro_yaw;
}
public AltosIMU(AltosLink link) throws InterruptedException, TimeoutException {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
static final int idle_sensor_mega = 12;
static final int idle_sensor_emini = 13;
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 {
for (int idler : idlers) {
break;
case idle_sensor_tmini:
AltosSensorTMini.update_state(state, link, config_data);
+ break;
+ case idle_sensor_tgps:
+ AltosSensorTGPS.update_state(state, link, config_data);
+ break;
}
if (idle != null)
idle.update_state(state);
AltosIdler.idle_ms5607, AltosIdler.idle_mma655x,
AltosIdler.idle_imu, AltosIdler.idle_mag,
AltosIdler.idle_sensor_mega),
+ new AltosIdler("TeleGPS",
+ AltosIdler.idle_gps,
+ AltosIdler.idle_sensor_tgps),
};
AltosLink link;
public void update_state(AltosState state) throws InterruptedException {
try {
+ /* Fetch config data from remote */
AltosConfigData config_data = new AltosConfigData(link);
- state.set_state(AltosLib.ao_flight_startup);
+ state.set_state(AltosLib.ao_flight_stateless);
state.set_serial(config_data.serial);
state.set_callsign(config_data.callsign);
state.set_ground_accel(config_data.accel_cal_plus);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.concurrent.*;
AltosConfigData config_data;
AltosGPS gps;
- int AltosRSSI() throws TimeoutException, InterruptedException {
- link.printf("s\n");
- String line = link.get_reply_no_dialog(5000);
- if (line == null)
- throw new TimeoutException();
- String[] items = line.split("\\s+");
- if (items.length < 2)
- return 0;
- if (!items[0].equals("RSSI:"))
- return 0;
- int rssi = Integer.parseInt(items[1]);
- return rssi;
- }
-
void start_link() throws InterruptedException, TimeoutException {
if (remote) {
link.set_radio_frequency(frequency);
link.flush_input();
}
- void stop_link() throws InterruptedException, TimeoutException {
+ boolean stop_link() throws InterruptedException, TimeoutException {
if (remote)
link.stop_remote();
+ return link.reply_abort;
}
- void update_state(AltosState state) throws InterruptedException, TimeoutException {
+ boolean update_state(AltosState state) throws InterruptedException, TimeoutException {
boolean worked = false;
+ boolean aborted = false;
try {
start_link();
fetch.update_state(state);
- worked = true;
+ if (!link.has_error && !link.reply_abort)
+ worked = true;
} finally {
- stop_link();
+ aborted = stop_link();
if (worked) {
if (remote)
state.set_rssi(link.rssi(), 0);
listener_state.battery = link.monitor_battery();
}
}
+ return aborted;
}
public void set_frequency(double in_frequency) {
public void run() {
AltosState state = new AltosState();
try {
- while (!link.has_error) {
+ for (;;) {
try {
link.config_data();
update_state(state);
listener.update(state, listener_state);
} catch (TimeoutException te) {
}
+ if (link.has_error || link.reply_abort) {
+ listener.failed();
+ break;
+ }
Thread.sleep(1000);
}
} catch (InterruptedException ie) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public interface AltosIdleMonitorListener {
public void update(AltosState state, AltosListenerState listener_state);
-}
\ No newline at end of file
+ public void failed();
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.*;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosLatitude extends AltosLocation {
public String pos() { return "N"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.*;
import java.io.*;
public static final int AO_LOG_BARO_TREF = 3006;
public static final int AO_LOG_BARO_TEMPSENS = 3007;
public static final int AO_LOG_BARO_CRC = 3008;
+ public static final int AO_LOG_IMU_CAL = 3009;
public static final int AO_LOG_SOFTWARE_VERSION = 9999;
public final static int product_easymini = 0x0026;
public final static int product_telemini = 0x0027;
public final static int product_easymega = 0x0028;
+ public final static int product_usbtrng = 0x0029;
+ public final static int product_usbrelay = 0x002a;
+ public final static int product_mpusb = 0x002b;
public final static int product_altusmetrum_min = 0x000a;
public final static int product_altusmetrum_max = 0x002c;
};
public static final String launch_sites_url = "http://www.altusmetrum.org/AltOS/launch-sites.txt";
+// 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;
public static final int ao_telemetry_0_9_len = 95;
public static final int AO_LOG_FORMAT_TINY = 2;
public static final int AO_LOG_FORMAT_TELEMETRY = 3;
public static final int AO_LOG_FORMAT_TELESCIENCE = 4;
- public static final int AO_LOG_FORMAT_TELEMEGA = 5;
+ public static final int AO_LOG_FORMAT_TELEMEGA_OLD = 5;
public static final int AO_LOG_FORMAT_EASYMINI = 6;
public static final int AO_LOG_FORMAT_TELEMETRUM = 7;
public static final int AO_LOG_FORMAT_TELEMINI = 8;
public static final int AO_LOG_FORMAT_TELEGPS = 9;
+ public static final int AO_LOG_FORMAT_TELEMEGA = 10;
public static final int AO_LOG_FORMAT_NONE = 127;
public static boolean isspace(int c) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosLine {
public String line;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.concurrent.*;
public void printf(String format, Object ... arguments) {
String line = String.format(format, arguments);
- if (debug)
- pending_output.add(line);
+ if (debug) {
+ synchronized (pending_output) {
+ pending_output.add(line);
+ }
+ }
try {
print(line);
} catch (InterruptedException ie) {
binary_queue.put(dup);
}
- public void flush_output() {
+ public synchronized void flush_output() {
if (pending_output == null)
return;
- for (String s : pending_output)
- System.out.print(s);
- pending_output.clear();
+ synchronized (pending_output) {
+ for (String s : pending_output)
+ System.out.print(s);
+ pending_output.clear();
+ }
}
public void flush_input(int timeout) throws InterruptedException {
flush_output();
}
- public void set_monitor(boolean monitor) {
+ public synchronized void set_monitor(boolean monitor) {
monitor_mode = monitor;
if (monitor)
printf("m %x\n", telemetry_len());
flush_output();
}
+ public synchronized boolean get_monitor() {
+ return monitor_mode;
+ }
+
private void set_channel(int channel) {
if (monitor_mode)
printf("m 0\nc r %d\nm %x\n",
public void set_callsign(String callsign) {
this.callsign = callsign;
- printf ("c c %s\n", callsign);
- flush_output();
+ if (callsign != null) {
+ printf ("c c %s\n", callsign);
+ flush_output();
+ }
}
public boolean is_loader() throws InterruptedException {
if (telemetry_rate < 0)
telemetry_rate = AltosPreferences.telemetry_rate(serial);
set_telemetry_rate(telemetry_rate);
- if (callsign.equals(""))
+ if (callsign == null || callsign.equals(""))
callsign = AltosPreferences.callsign();
set_callsign(callsign);
printf("p\nE 0\n");
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
-public class AltosListenerState {
+import java.io.*;
+
+public class AltosListenerState implements Serializable {
public int crc_errors;
public double battery;
+ public boolean running;
public AltosListenerState() {
crc_errors = 0;
battery = AltosLib.MISSING;
+ running = true;
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public abstract class AltosLocation extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosLongitude extends AltosLocation {
public String pos() { return "E"; }
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.*;
+import java.io.*;
-public class AltosMag implements Cloneable {
- public double x;
- public double y;
- public double z;
+public class AltosMag implements Cloneable, Serializable {
+ public int along;
+ public int across;
+ public int through;
public static double counts_per_gauss = 1090;
- public static double convert_gauss(int counts) {
- return (double) counts / counts_per_gauss;
+ public static double convert_gauss(double counts) {
+ return counts / counts_per_gauss;
}
public boolean parse_string(String line) {
// if (line.startsWith("Syntax error")) {
-// x = y = z = 0;
+// along = across = through = 0;
// return true;
// }
String[] items = line.split("\\s+");
if (items.length >= 6) {
- x = convert_gauss(Integer.parseInt(items[1]));
- y = convert_gauss(Integer.parseInt(items[3]));
- z = convert_gauss(Integer.parseInt(items[5]));
+ along = Integer.parseInt(items[1]);
+ across = Integer.parseInt(items[3]);
+ through = Integer.parseInt(items[5]);
}
return true;
}
public AltosMag clone() {
AltosMag n = new AltosMag();
- n.x = x;
- n.y = y;
- n.z = z;
+ n.along = along;
+ n.across = across;
+ n.through = through;
return n;
}
public AltosMag() {
- x = AltosLib.MISSING;
- y = AltosLib.MISSING;
- z = AltosLib.MISSING;
+ along = AltosLib.MISSING;
+ across = AltosLib.MISSING;
+ through = AltosLib.MISSING;
+ }
+
+ public AltosMag(int along, int across, int through) {
+ this.along = along;
+ this.across = across;
+ this.through = through;
}
static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.*;
+import java.io.*;
-public class AltosMs5607 {
+public class AltosMs5607 implements Serializable {
public int reserved;
public int sens;
public int off;
static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
try {
- AltosMs5607 ms5607 = new AltosMs5607(link);
+ AltosMs5607 ms5607 = new AltosMs5607(link, config_data);
if (ms5607 != null) {
state.set_ms5607(ms5607);
cc = AltosLib.MISSING;
}
- public AltosMs5607 (AltosLink link) throws InterruptedException, TimeoutException {
+ public AltosMs5607 (AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException {
this();
- link.printf("c s\nB\n");
+ reserved = config_data.ms5607_reserved;
+ sens = config_data.ms5607_sens;
+ off = config_data.ms5607_off;
+ tcs = config_data.ms5607_tcs;
+ tco = config_data.ms5607_tco;
+ tref = config_data.ms5607_tref;
+ tempsens = config_data.ms5607_tempsens;
+ crc = config_data.ms5607_crc;
+ link.printf("B\n");
for (;;) {
String line = link.get_reply_no_dialog(5000);
if (line == null) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosNoSymbol extends Exception {
public AltosNoSymbol(String name) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosOrient extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
/* log file format preference name */
public final static String logfilePreferenceFormat = "LOGFILE-%d";
+ /* state preference name */
+ public final static String statePreferenceFormat = "STATE-%d";
+
/* voice preference name */
public final static String voicePreference = "VOICE";
}
}
+ public static void set_state(int serial, AltosState state, AltosListenerState listener_state) {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ try {
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+
+ 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);
+ flush_preferences();
+ }
+ } catch (IOException ie) {
+ }
+ }
+
+ public static AltosSavedState state(int serial) {
+ byte[] bytes = null;
+
+ 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) {
+ }
+ return null;
+ }
+
public static void set_scanning_telemetry(int new_scanning_telemetry) {
synchronized (backend) {
scanning_telemetry = new_scanning_telemetry;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.File;
public boolean getBoolean(String key, boolean def);
public void putBoolean(String key, boolean value);
+ public byte[] getBytes(String key, byte[] def);
+ public void putBytes(String key, byte[] value);
+
public boolean nodeExists(String key);
public AltosPreferencesBackend node(String key);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.*;
import java.text.*;
--- /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.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+public class AltosQuaternion {
+ double r; /* real bit */
+ double x, y, z; /* imaginary bits */
+
+ public AltosQuaternion multiply(AltosQuaternion b) {
+ return new AltosQuaternion(
+ this.r * b.r - this.x * b.x - this.y * b.y - this.z * b.z,
+ this.r * b.x + this.x * b.r + this.y * b.z - this.z * b.y,
+ this.r * b.y - this.x * b.z + this.y * b.r + this.z * b.x,
+ this.r * b.z + this.x * b.y - this.y * b.x + this.z * b.r);
+ }
+
+ public AltosQuaternion conjugate() {
+ return new AltosQuaternion(
+ this.r,
+ -this.x,
+ -this.y,
+ -this.z);
+ }
+
+ public double normal() {
+ return (this.r * this.r +
+ this.x * this.x +
+ this.y * this.y +
+ this.z * this.z);
+ }
+
+ public AltosQuaternion scale(double b) {
+ return new AltosQuaternion(
+ this.r * b,
+ this.x * b,
+ this.y * b,
+ this.z * b);
+ }
+
+ public AltosQuaternion normalize() {
+ double n = normal();
+ if (n <= 0)
+ return this;
+ return scale(1/Math.sqrt(n));
+ }
+
+ public double dot(AltosQuaternion b) {
+ return (this.r * b.r +
+ this.x * b.x +
+ this.y * b.y +
+ this.z * b.z);
+ }
+
+ public AltosQuaternion rotate(AltosQuaternion b) {
+ return (b.multiply(this)).multiply(b.conjugate());
+ }
+
+ public AltosQuaternion vectors_to_rotation(AltosQuaternion b) {
+ /*
+ * The cross product will point orthogonally to the two
+ * vectors, forming our rotation axis. The length will be
+ * sin(θ), so these values are already multiplied by that.
+ */
+
+ double x = this.y * b.z - this.z * b.y;
+ double y = this.z * b.x - this.x * b.z;
+ double z = this.x * b.y - this.y * b.x;
+
+ double s_2 = x*x + y*y + z*z;
+ double s = Math.sqrt(s_2);
+
+ /* cos(θ) = a · b / (|a| |b|).
+ *
+ * a and b are both unit vectors, so the divisor is one
+ */
+ double c = this.x*b.x + this.y*b.y + this.z*b.z;
+
+ double c_half = Math.sqrt ((1 + c) / 2);
+ double s_half = Math.sqrt ((1 - c) / 2);
+
+ /*
+ * Divide out the sine factor from the
+ * cross product, then multiply in the
+ * half sine factor needed for the quaternion
+ */
+ double s_scale = s_half / s;
+
+ AltosQuaternion r = new AltosQuaternion(c_half,
+ x * s_scale,
+ y * s_scale,
+ z * s_scale);
+ return r.normalize();
+ }
+
+ public AltosQuaternion(double r, double x, double y, double z) {
+ this.r = r;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+
+ public AltosQuaternion(AltosQuaternion q) {
+ this.r = q.r;
+ this.x = q.x;
+ this.y = q.y;
+ this.z = q.z;
+ }
+
+ static public AltosQuaternion vector(double x, double y, double z) {
+ return new AltosQuaternion(0, x, y, z);
+ }
+
+ static public AltosQuaternion rotation(double x, double y, double z,
+ double s, double c) {
+ return new AltosQuaternion(c,
+ s*x,
+ s*y,
+ s*z);
+ }
+
+ static public AltosQuaternion zero_rotation() {
+ return new AltosQuaternion(1, 0, 0, 0);
+ }
+
+ static public AltosQuaternion half_euler(double x, double y, double z) {
+ double s_x = Math.sin(x), c_x = Math.cos(x);
+ double s_y = Math.sin(y), c_y = Math.cos(y);
+ double s_z = Math.sin(z), c_z = Math.cos(z);;
+
+ return new AltosQuaternion(c_x * c_y * c_z + s_x * s_y * s_z,
+ s_x * c_y * c_z - c_x * s_y * s_z,
+ c_x * s_y * c_z + s_x * c_y * s_z,
+ c_x * c_y * s_z - s_x * s_y * c_z);
+ }
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
public class AltosReplayReader extends AltosFlightReader {
Iterator<AltosState> iterator;
File file;
- boolean real_time;
public AltosState read() {
if (iterator.hasNext())
public void update(AltosState state) throws InterruptedException {
/* Make it run in realtime after the rocket leaves the pad */
- if (real_time && state.state > AltosLib.ao_flight_pad && state.time_change > 0)
- Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
+ if (state.state > AltosLib.ao_flight_pad && state.time_change > 0)
+ Thread.sleep((int) (Math.min(state.time_change,10) * 100));
state.set_received_time(System.currentTimeMillis());
}
public File backing_file() { return file; }
- public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file,
- boolean in_real_time) {
+ public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
iterator = in_iterator;
file = in_file;
- real_time = in_real_time;
name = file.getName();
}
-
- public AltosReplayReader(Iterator<AltosState> in_iterator, File in_file) {
- this(in_iterator, in_file, false);
- }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
--- /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.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+public class AltosRotation {
+ private AltosQuaternion rotation;
+
+ public double tilt() {
+ double rotz = rotation.z * rotation.z - rotation.y * rotation.y - rotation.x * rotation.x + rotation.r * rotation.r;
+
+ double tilt = Math.acos(rotz) * 180.0 / Math.PI;
+ return tilt;
+ }
+
+ public void rotate(double dt, double x, double y, double z) {
+ AltosQuaternion rot = AltosQuaternion.half_euler(x * dt, y * dt, z * dt);
+ rotation = rot.multiply(rotation).normalize();
+ }
+
+ /* Clone an existing rotation value */
+ public AltosRotation (AltosRotation old) {
+ this.rotation = new AltosQuaternion(old.rotation);
+ }
+
+ /* Create a new rotation value given an acceleration vector pointing down */
+ public AltosRotation(double x,
+ double y,
+ double z,
+ int pad_orientation) {
+ AltosQuaternion orient = AltosQuaternion.vector(x, y, z).normalize();
+ double sky = pad_orientation == 0 ? 1 : -1;
+ AltosQuaternion up = new AltosQuaternion(0, 0, 0, sky);
+ rotation = up.vectors_to_rotation(orient);
+ }
+}
--- /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.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+import java.io.*;
+
+public class AltosSavedState implements Serializable {
+ public AltosState state;
+ public AltosListenerState listener_state;
+
+ public AltosSavedState(AltosState state, AltosListenerState listener_state) {
+ this.state = state;
+ this.listener_state = listener_state;
+ }
+}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.TimeoutException;
--- /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.
+ */
+
+package org.altusmetrum.altoslib_6;
+
+import java.util.concurrent.TimeoutException;
+
+public class AltosSensorTGPS {
+ public int tick;
+ public int batt;
+
+ static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException {
+ try {
+ AltosSensorTGPS sensor_tgps = new AltosSensorTGPS(link);
+
+ if (sensor_tgps == null)
+ return;
+ state.set_battery_voltage(AltosConvert.tele_gps_voltage(sensor_tgps.batt));
+
+ } catch (TimeoutException te) {
+ }
+ }
+
+ public AltosSensorTGPS(AltosLink link) throws InterruptedException, TimeoutException {
+ String[] items = link.adc();
+ for (int i = 0; i < items.length - 1;) {
+ if (items[i].equals("tick:")) {
+ tick = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ if (items[i].equals("batt:")) {
+ batt = Integer.parseInt(items[i+1]);
+ i += 2;
+ continue;
+ }
+ i++;
+ }
+ }
+}
+
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.util.concurrent.TimeoutException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosSpeed extends AltosUnits {
* Track flight state from telemetry or eeprom data stream
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
-public class AltosState implements Cloneable {
+import java.io.*;
+
+public class AltosState implements Cloneable, Serializable {
public static final int set_position = 1;
public static final int set_gps = 2;
private int prev_tick;
public int boost_tick;
- class AltosValue {
- private double value;
- private double prev_value;
+ class AltosValue implements Serializable{
+ double value;
+ double prev_value;
private double max_value;
private double set_time;
private double prev_set_time;
}
}
- class AltosCValue {
- AltosValue measured;
- AltosValue computed;
+ class AltosCValue implements Serializable {
+
+ class AltosIValue extends AltosValue implements Serializable {
+ boolean can_max() {
+ return c_can_max();
+ }
+ };
+
+ public AltosIValue measured;
+ public AltosIValue computed;
+
+ boolean can_max() { return true; }
+
+ boolean c_can_max() { return can_max(); }
double value() {
double v = measured.value();
}
AltosCValue() {
- measured = new AltosValue();
- computed = new AltosValue();
+ measured = new AltosIValue();
+ computed = new AltosIValue();
}
}
ground_altitude.set_measured(a, time);
}
- class AltosGpsGroundAltitude extends AltosValue {
+ class AltosGpsGroundAltitude extends AltosValue implements Serializable {
void set(double a, double t) {
super.set(a, t);
pad_alt = value();
gps_ground_altitude.set(a, time);
}
- class AltosGroundPressure extends AltosCValue {
+ class AltosGroundPressure extends AltosCValue implements Serializable {
void set_filtered(double p, double time) {
computed.set_filtered(p, time);
if (!is_measured())
ground_pressure.set_measured(pressure, time);
}
- class AltosAltitude extends AltosCValue {
+ class AltosAltitude extends AltosCValue implements Serializable {
private void set_speed(AltosValue v) {
if (!acceleration.is_measured() || !ascent)
private AltosAltitude altitude;
- class AltosGpsAltitude extends AltosValue {
+ class AltosGpsAltitude extends AltosValue implements Serializable {
private void set_gps_height() {
double a = value();
return gps_speed.max();
}
- class AltosPressure extends AltosValue {
+ class AltosPressure extends AltosValue implements Serializable {
void set(double p, double time) {
super.set(p, time);
if (state == AltosLib.ao_flight_pad)
return AltosLib.MISSING;
}
- class AltosSpeed extends AltosCValue {
+ class AltosSpeed extends AltosCValue implements Serializable {
boolean can_max() {
return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
return AltosLib.MISSING;
}
- class AltosAccel extends AltosCValue {
+ class AltosAccel extends AltosCValue implements Serializable {
boolean can_max() {
return state < AltosLib.ao_flight_fast || state == AltosLib.ao_flight_stateless;
return acceleration.max();
}
- public AltosValue orient;
+ public AltosCValue orient;
public void set_orient(double new_orient) {
- orient.set(new_orient, time);
+ orient.set_measured(new_orient, time);
}
public double orient() {
pressure = new AltosPressure();
speed = new AltosSpeed();
acceleration = new AltosAccel();
- orient = new AltosValue();
+ orient = new AltosCValue();
temperature = AltosLib.MISSING;
battery_voltage = AltosLib.MISSING;
gps_pending = false;
imu = null;
+ last_imu_time = AltosLib.MISSING;
+ rotation = null;
+ ground_rotation = null;
+
mag = null;
+ accel_zero_along = AltosLib.MISSING;
+ accel_zero_across = AltosLib.MISSING;
+ accel_zero_through = AltosLib.MISSING;
+
+ accel_ground_along = AltosLib.MISSING;
+ accel_ground_across = AltosLib.MISSING;
+ accel_ground_through = AltosLib.MISSING;
+
+ pad_orientation = AltosLib.MISSING;
+
+ gyro_zero_roll = AltosLib.MISSING;
+ gyro_zero_pitch = AltosLib.MISSING;
+ gyro_zero_yaw = AltosLib.MISSING;
set_npad(0);
ngps = 0;
imu = old.imu.clone();
else
imu = null;
+ last_imu_time = old.last_imu_time;
+
+ if (old.rotation != null)
+ rotation = new AltosRotation (old.rotation);
+
+ if (old.ground_rotation != null) {
+ ground_rotation = new AltosRotation(old.ground_rotation);
+ }
+
+ accel_zero_along = old.accel_zero_along;
+ accel_zero_across = old.accel_zero_across;
+ accel_zero_through = old.accel_zero_through;
+
+ accel_ground_along = old.accel_ground_along;
+ accel_ground_across = old.accel_ground_across;
+ accel_ground_through = old.accel_ground_through;
+ pad_orientation = old.pad_orientation;
+
+ gyro_zero_roll = old.gyro_zero_roll;
+ gyro_zero_pitch = old.gyro_zero_pitch;
+ gyro_zero_yaw = old.gyro_zero_yaw;
if (old.mag != null)
mag = old.mag.clone();
}
}
+
+ public double accel_zero_along;
+ public double accel_zero_across;
+ public double accel_zero_through;
+
+ public AltosRotation rotation;
+ public AltosRotation ground_rotation;
+
+ public void set_accel_zero(double zero_along, double zero_across, double zero_through) {
+ if (zero_along != AltosLib.MISSING) {
+ accel_zero_along = zero_along;
+ accel_zero_across = zero_across;
+ accel_zero_through = zero_through;
+ }
+ }
+
+ public int pad_orientation;
+
+ public double accel_ground_along, accel_ground_across, accel_ground_through;
+
+ void update_pad_rotation() {
+ if (pad_orientation != AltosLib.MISSING && accel_ground_along != AltosLib.MISSING) {
+ rotation = new AltosRotation(AltosIMU.convert_accel(accel_ground_across - accel_zero_across),
+ AltosIMU.convert_accel(accel_ground_through - accel_zero_through),
+ AltosIMU.convert_accel(accel_ground_along - accel_zero_along),
+ pad_orientation);
+ ground_rotation = rotation;
+ orient.set_computed(rotation.tilt(), time);
+ }
+ }
+
+ public void set_accel_ground(double ground_along, double ground_across, double ground_through) {
+ accel_ground_along = ground_along;
+ accel_ground_across = ground_across;
+ accel_ground_through = ground_through;
+ update_pad_rotation();
+ }
+
+ public void set_pad_orientation(int pad_orientation) {
+ this.pad_orientation = pad_orientation;
+ update_pad_rotation();
+ }
+
+ public double gyro_zero_roll;
+ public double gyro_zero_pitch;
+ public double gyro_zero_yaw;
+
+ public void set_gyro_zero(double roll, double pitch, double yaw) {
+ if (roll != AltosLib.MISSING) {
+ gyro_zero_roll = roll;
+ gyro_zero_pitch = pitch;
+ gyro_zero_yaw = yaw;
+ }
+ }
+
+ public double last_imu_time;
+
+ private double radians(double degrees) {
+ if (degrees == AltosLib.MISSING)
+ return AltosLib.MISSING;
+ return degrees * Math.PI / 180.0;
+ }
+
+ private void update_orient() {
+ if (last_imu_time != AltosLib.MISSING) {
+ double t = time - last_imu_time;
+
+ double pitch = radians(gyro_pitch());
+ double yaw = radians(gyro_yaw());
+ double roll = radians(gyro_roll());
+
+ if (t > 0 & pitch != AltosLib.MISSING && rotation != null) {
+ rotation.rotate(t, pitch, yaw, roll);
+ orient.set_computed(rotation.tilt(), time);
+ }
+ }
+ last_imu_time = time;
+ }
+
public void set_imu(AltosIMU imu) {
if (imu != null)
imu = imu.clone();
this.imu = imu;
+ update_orient();
+ }
+
+ private double gyro_zero_overflow(double first) {
+ double v = first / 128.0;
+ if (v < 0)
+ v = Math.ceil(v);
+ else
+ v = Math.floor(v);
+ return v * 128.0;
+ }
+
+ public void check_imu_wrap(AltosIMU imu) {
+ if (this.imu == null) {
+ gyro_zero_roll += gyro_zero_overflow(imu.gyro_roll);
+ gyro_zero_pitch += gyro_zero_overflow(imu.gyro_pitch);
+ gyro_zero_yaw += gyro_zero_overflow(imu.gyro_yaw);
+ }
+ }
+
+ public double accel_along() {
+ if (imu != null && accel_zero_along != AltosLib.MISSING)
+ return AltosIMU.convert_accel(imu.accel_along - accel_zero_along);
+ return AltosLib.MISSING;
+ }
+
+ public double accel_across() {
+ if (imu != null && accel_zero_across != AltosLib.MISSING)
+ return AltosIMU.convert_accel(imu.accel_across - accel_zero_across);
+ return AltosLib.MISSING;
+ }
+
+ public double accel_through() {
+ if (imu != null && accel_zero_through != AltosLib.MISSING)
+ return AltosIMU.convert_accel(imu.accel_through - accel_zero_through);
+ return AltosLib.MISSING;
+ }
+
+ public double gyro_roll() {
+ if (imu != null && gyro_zero_roll != AltosLib.MISSING) {
+ return AltosIMU.convert_gyro(imu.gyro_roll - gyro_zero_roll);
+ }
+ return AltosLib.MISSING;
+ }
+
+ public double gyro_pitch() {
+ if (imu != null && gyro_zero_pitch != AltosLib.MISSING) {
+ return AltosIMU.convert_gyro(imu.gyro_pitch - gyro_zero_pitch);
+ }
+ return AltosLib.MISSING;
+ }
+
+ public double gyro_yaw() {
+ if (imu != null && gyro_zero_yaw != AltosLib.MISSING) {
+ return AltosIMU.convert_gyro(imu.gyro_yaw - gyro_zero_yaw);
+ }
+ return AltosLib.MISSING;
}
public void set_mag(AltosMag mag) {
this.mag = mag.clone();
}
+ public double mag_along() {
+ if (mag != null)
+ return AltosMag.convert_gauss(mag.along);
+ return AltosLib.MISSING;
+ }
+
+ public double mag_across() {
+ if (mag != null)
+ return AltosMag.convert_gauss(mag.across);
+ return AltosLib.MISSING;
+ }
+
+ public double mag_through() {
+ if (mag != null)
+ return AltosMag.convert_gauss(mag.through);
+ return AltosLib.MISSING;
+ }
+
public AltosMs5607 make_baro() {
if (baro == null)
baro = new AltosMs5607();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public interface AltosStateUpdate {
public void update_state(AltosState state) throws InterruptedException;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryConfiguration extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.io.*;
import java.util.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryLocation extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
import java.util.HashMap;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryMegaData extends AltosTelemetryStandard {
int state;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryMegaSensor extends AltosTelemetryStandard {
int accel;
state.set_orient(orient);
- AltosIMU imu = new AltosIMU();
+ state.set_imu(new AltosIMU(accel_y, /* along */
+ accel_x, /* across */
+ accel_z, /* through */
+ gyro_y, /* along */
+ gyro_x, /* across */
+ gyro_z)); /* through */
- imu.accel_x = AltosIMU.convert_accel(accel_x);
- imu.accel_y = AltosIMU.convert_accel(accel_y);
- imu.accel_z = AltosIMU.convert_accel(accel_z);
-
- imu.gyro_x = AltosIMU.convert_gyro(gyro_x);
- imu.gyro_y = AltosIMU.convert_gyro(gyro_y);
- imu.gyro_z = AltosIMU.convert_gyro(gyro_z);
-
- state.imu = imu;
-
- AltosMag mag = new AltosMag();
-
- mag.x = AltosMag.convert_gauss(mag_x);
- mag.y = AltosMag.convert_gauss(mag_y);
- mag.z = AltosMag.convert_gauss(mag_z);
-
- state.mag = mag;
+ state.set_mag(new AltosMag(mag_x, mag_y, mag_z));
}
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryMetrumData extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryMini extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetryRaw extends AltosTelemetryStandard {
public AltosTelemetryRaw(int[] bytes) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
import java.text.*;
import java.io.*;
int telemetry;
int telemetry_rate;
AltosState state = null;
- AltosFlightReader stacked;
LinkedBlockingQueue<AltosLine> telem;
public AltosState read() throws InterruptedException, ParseException, AltosCRCException, IOException {
- if (stacked != null) {
- state = stacked.read();
- if (state != null)
- return state;
- stacked = null;
- }
- AltosLine l = telem.take();
- if (l.line == null)
- throw new IOException("IO error");
+ AltosLine l;
+ do {
+ l = telem.take();
+ if (l.line == null)
+ throw new IOException("IO error");
+ } while (!link.get_monitor());
AltosTelemetry telem = AltosTelemetry.parse(l.line);
if (state == null)
state = new AltosState();
public void reset() {
flush();
+ state = null;
}
public void close(boolean interrupted) {
- if (stacked != null) {
- stacked.close(interrupted);
- stacked = null;
- }
-
link.remove_monitor(telem);
log.close();
try {
return link.monitor_battery();
}
- public AltosTelemetryReader (AltosLink in_link, AltosFlightReader in_stacked)
+ public AltosTelemetryReader (AltosLink in_link)
throws IOException, InterruptedException, TimeoutException {
link = in_link;
- stacked = in_stacked;
boolean success = false;
try {
log = new AltosLog(link);
close(true);
}
}
-
- private static AltosFlightReader existing_data(AltosLink link) {
- if (link == null)
- return null;
-
- File file = AltosPreferences.logfile(link.serial);
- if (file != null) {
- AltosStateIterable iterable = AltosStateIterable.iterable(file);
- if (iterable != null)
- return new AltosReplayReader(iterable.iterator(), file, false);
- }
- return null;
- }
-
- public AltosTelemetryReader(AltosLink link)
- throws IOException, InterruptedException, TimeoutException {
- this(link, null);
- }
}
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetrySatellite extends AltosTelemetryStandard {
int channels;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTelemetrySensor extends AltosTelemetryStandard {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public abstract class AltosTelemetryStandard extends AltosTelemetry {
int[] bytes;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosTemperature extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public abstract class AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public interface AltosUnitsListener {
public void units_changed(boolean imperial_units);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public class AltosVoltage extends AltosUnits {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altoslib_5;
+package org.altusmetrum.altoslib_6;
public interface AltosWriter {
AltosProgrammer.java \
AltosReplayReader.java \
AltosRomconfig.java \
+ AltosSavedState.java \
AltosSelfFlash.java \
AltosSensorMM.java \
AltosSensorEMini.java \
AltosSensorTMini.java \
AltosSensorMega.java \
AltosSensorMetrum.java \
+ AltosSensorTGPS.java \
AltosState.java \
AltosStateIterable.java \
AltosStateUpdate.java \
AltosLatitude.java \
AltosLongitude.java \
AltosPyro.java \
- AltosWriter.java
+ AltosWriter.java \
+ AltosQuaternion.java \
+ AltosRotation.java
JAR=altoslib_$(ALTOSLIB_VERSION).jar
Altos-Linux-*.sh
Altos-Mac-*.zip
Altos-Windows-*.exe
-.desktop
+*.desktop
*.dll
*.dylib
*.so
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class Altos extends AltosUILib {
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosAscent extends AltosUIFlightTab {
JLabel cur, max;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosCompanionInfo extends JTable implements AltosFlightDisplay {
private AltosFlightInfoTableModel model;
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosConfigPyroUI
extends AltosUIDialog
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosConfigTD implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosConfigTDUI
extends AltosUIDialog
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosConfigUI
extends AltosUIDialog
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosConfigureUI
extends AltosUIConfigure
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosDescent extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosFlightStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
long last_secs = -1;
void show(AltosState state, AltosListenerState listener_state) {
- long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
- if (secs != last_secs) {
- value.setText(String.format("%d", secs));
- last_secs = secs;
+ if (listener_state.running) {
+ long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
+ if (secs != last_secs) {
+ value.setText(String.format("%d", secs));
+ last_secs = secs;
+ }
+ } else {
+ value.setText("done");
}
}
flight_state.show(state, listener_state);
rssi.show(state, listener_state);
last_packet.show(state, listener_state);
+ if (!listener_state.running)
+ stop();
}
public int height() {
public String getName() { return "Flight Status"; }
+ AltosFlightStatusUpdate status_update;
+ javax.swing.Timer timer;
+
+ public void start(AltosFlightStatusUpdate status_update) {
+ this.status_update = status_update;
+ timer = new javax.swing.Timer(100, status_update);
+ timer.start();
+ }
+
+ public void stop() {
+ if (timer != null) {
+ timer.stop();
+ timer = null;
+ }
+ }
+
public AltosFlightStatus() {
layout = new GridBagLayout();
import java.text.*;
import java.util.prefs.*;
import java.util.concurrent.LinkedBlockingQueue;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosFlightStatusTableModel extends AbstractTableModel {
private String[] columnNames = {
package altosui;
import java.awt.event.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosFlightStatusUpdate implements ActionListener {
import javax.swing.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay {
AltosVoice voice;
public void show(AltosState state, AltosListenerState listener_state) {
status_update.saved_state = state;
+ status_update.saved_listener_state = listener_state;
if (state == null)
state = new AltosState();
AltosUIPreferences.register_font_listener(this);
AltosPreferences.register_units_listener(this);
+ status_update = new AltosFlightStatusUpdate(flightStatus);
+
+ flightStatus.start(status_update);
+
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
+ flightStatus.stop();
disconnect();
setVisible(false);
dispose();
thread = new AltosDisplayThread(this, voice, this, reader);
- status_update = new AltosFlightStatusUpdate(flightStatus);
-
- new javax.swing.Timer(100, status_update).start();
-
thread.start();
}
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
}
public void font_size_changed(int font_size) {
- map.font_size_changed(font_size);
- statsTable.font_size_changed(font_size);
+ if (map != null)
+ map.font_size_changed(font_size);
+ if (statsTable != null)
+ statsTable.font_size_changed(font_size);
}
public void units_changed(boolean imperial_units) {
- map.units_changed(imperial_units);
+ if (map != null)
+ map.units_changed(imperial_units);
+ if (enable != null)
+ enable.units_changed(imperial_units);
}
AltosGraphUI(AltosStateIterable states, File file) throws InterruptedException, IOException {
import java.io.*;
import java.util.concurrent.*;
import java.util.Arrays;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDisplay, AltosIdleMonitorListener, DocumentListener {
AltosDevice device;
SwingUtilities.invokeLater(r);
}
+ public void failed() {
+ Runnable r = new Runnable() {
+ public void run() {
+ close();
+ }
+ };
+ SwingUtilities.invokeLater(r);
+ }
+
Container bag;
AltosUIFreqList frequencies;
JTextField callsign_value;
}
}
+ private void close() {
+ try {
+ disconnect();
+ } catch (Exception ex) {
+ System.out.printf("Exception %s\n", ex.toString());
+ for (StackTraceElement el : ex.getStackTrace())
+ System.out.printf("%s\n", el.toString());
+ }
+ setVisible(false);
+ dispose();
+ AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
+ }
+
public AltosIdleMonitorUI(JFrame in_owner)
throws FileNotFoundException, TimeoutException, InterruptedException {
serial = device.getSerial();
- AltosLink link;
+ AltosSerial link;
try {
link = new AltosSerial(device);
+ link.set_frame(this);
} catch (Exception ex) {
idle_exception(in_owner, ex);
return;
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
- try {
- disconnect();
- } catch (Exception ex) {
- System.out.printf("Exception %s\n", ex.toString());
- for (StackTraceElement el : ex.getStackTrace())
- System.out.printf("%s\n", el.toString());
- }
- setVisible(false);
- dispose();
- AltosUIPreferences.unregister_font_listener(AltosIdleMonitorUI.this);
+ close();
}
});
import java.text.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosIgniteUI
extends AltosUIDialog
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosIgnitor extends AltosUIFlightTab {
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosLanded extends AltosUIFlightTab implements ActionListener {
import java.io.*;
import java.util.concurrent.*;
import java.awt.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosLaunch {
AltosDevice device;
import java.io.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
class FireButton extends JButton {
protected void processMouseEvent(MouseEvent e) {
package altosui;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosPad extends AltosUIFlightTab {
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class AltosUI extends AltosUIFrame {
public AltosVoice voice = new AltosVoice();
if (reader == null)
return false;
AltosFlightUI flight_ui = new AltosFlightUI(new AltosVoice(), reader);
- flight_ui.set_exit_on_close();
return true;
}
public static void help(int code) {
System.out.printf("Usage: altosui [OPTION]... [FILE]...\n");
System.out.printf(" Options:\n");
- System.out.printf(" --fetchmaps <lat> <lon>\tpre-fetch maps for site map view\n");
System.out.printf(" --replay <filename>\t\trelive the glory of past flights \n");
System.out.printf(" --graph <filename>\t\tgraph a flight\n");
+ System.out.printf(" --summary <filename>\t\tText summary of a flight\n");
System.out.printf(" --csv\tgenerate comma separated output for spreadsheets, etc\n");
System.out.printf(" --kml\tgenerate KML output for use with Google Earth\n");
System.exit(code);
UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
} catch (Exception e) {
}
+ AltosUI altosui = null;
+
/* Handle batch-mode */
if (args.length == 0) {
- AltosUI altosui = new AltosUI();
-
+ altosui = new AltosUI();
java.util.List<AltosDevice> devices = AltosUSBDevice.list(Altos.product_basestation);
if (devices != null)
for (AltosDevice device : devices)
switch (process) {
case process_none:
case process_graph:
+ if (altosui == null)
+ altosui = new AltosUI();
if (!process_graph(file))
++errors;
break;
case process_replay:
+ if (altosui == null)
+ altosui = new AltosUI();
if (!process_replay(file))
++errors;
break;
+++ /dev/null
-/*
- * Copyright © 2012 Mike Beattie <mike@ethernal.org>
- *
- * 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 altosui;
-
-import java.io.File;
-import java.util.prefs.*;
-import org.altusmetrum.altoslib_5.*;
-import javax.swing.filechooser.FileSystemView;
-
-public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
-
- private Preferences _preferences = null;
-
- public AltosUIPreferencesBackend() {
- _preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
- }
-
- public AltosUIPreferencesBackend(Preferences in_preferences) {
- _preferences = in_preferences;
- }
-
- public String getString(String key, String def) {
- return _preferences.get(key, def);
- }
- public void putString(String key, String value) {
- _preferences.put(key, value);
- }
-
- public int getInt(String key, int def) {
- return _preferences.getInt(key, def);
- }
- public void putInt(String key, int value) {
- _preferences.putInt(key, value);
- }
-
- public double getDouble(String key, double def) {
- return _preferences.getDouble(key, def);
- }
- public void putDouble(String key, double value) {
- _preferences.putDouble(key, value);
- }
-
- public boolean getBoolean(String key, boolean def) {
- return _preferences.getBoolean(key, def);
- }
- public void putBoolean(String key, boolean value) {
- _preferences.putBoolean(key, value);
- }
-
- public boolean nodeExists(String key) {
- try {
- return _preferences.nodeExists(key);
- } catch (BackingStoreException be) {
- return false;
- }
- }
-
- public AltosPreferencesBackend node(String key) {
- return new AltosUIPreferencesBackend(_preferences.node(key));
- }
-
- public String[] keys() {
- try {
- return _preferences.keys();
- } catch (BackingStoreException be) {
- return null;
- }
- }
-
- public void remove(String key) {
- _preferences.remove(key);
- }
-
- public void flush() {
- try {
- _preferences.flush();
- } catch (BackingStoreException ee) {
- System.err.printf("Cannot save preferences\n");
- }
- }
-
- public File homeDirectory() {
- /* Use the file system view default directory */
- return FileSystemView.getFileSystemView().getDefaultDirectory();
- }
-}
ReadRegStr $2 HKCU "SOFTWARE\JavaSoft\Java Runtime Environment" \
"CurrentVersion"
- IfErrors hklm_version
+ IfErrors hkcuwow_version
DetailPrint "HKEY_CURRENT_USER Java version $2"
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"
+
+ ${VersionCompare} $2 ${JRE_VERSION} $3
+
+ IntCmp $3 1 yes yes no
+
hklm_version:
; Check in HKLM for CurrentVersion
ReadRegStr $2 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" \
"CurrentVersion"
- IfErrors hkcu_any
+ IfErrors hklmwow_version
DetailPrint "HKEY_LOCAL_MACHINE Java version $2"
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
+
+ IntCmp $3 1 yes yes no
+
hkcu_any:
; Check in HKCU for any Java install
AltosLaunchUI.java \
AltosLanded.java \
AltosPad.java \
- AltosUIPreferencesBackend.java \
AltosUI.java \
AltosGraphUI.java
# Firmware
FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
-FIRMWARE_TD=$(FIRMWARE_TD_0_2)
+FIRMWARE_TD_3_0=$(top_srcdir)/src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx
+FIRMWARE_TD=$(FIRMWARE_TD_0_2) $(FIRMWARE_TD_3_0)
FIRMWARE_TM_1_0=$(top_srcdir)/src/telemetrum-v1.0/telemetrum-v1.0-$(VERSION).ihx
FIRMWARE_TM_1_1=$(top_srcdir)/src/telemetrum-v1.1/telemetrum-v1.1-$(VERSION).ihx
File "../icon/${WIN_APP_ICON}"
- CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
+ CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
Section "${REG_NAME} Desktop Shortcut"
File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx"
File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
+ File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
File "../src/telemega-v1.0/telemega-v1.0-${VERSION}.ihx"
File "../src/easymini-v1.0/easymini-v1.0-${VERSION}.ihx"
DeleteRegKey HKCR ".telem\${PROG_ID_EEPROM}"
DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
+ SearchPath $1 "javaw.exe"
+
; .eeprom elements
WriteRegStr HKCR "${PROG_ID_EEPROM}" "" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_EEPROM}" "FriendlyTypeName" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer" "" "${PROG_ID_EEPROM}"
WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" "" '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
- WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+ WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
WriteRegStr HKCR ".eeprom" "" "${PROG_ID_EEPROM}"
WriteRegStr HKCR ".eeprom" "PerceivedType" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_TELEM}" "FriendlyTypeName" "Altus Metrum Telemetry File"
WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer" "" "${PROG_ID_TELEM}"
WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" "" '"$INSTDIR\${WIN_TELEM_EXE}",-101'
- WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+ WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
WriteRegStr HKCR ".telem" "" "${PROG_ID_TELEM}"
WriteRegStr HKCR ".telem" "PerceivedType" "Altus Metrum Telemetry File"
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosBTDevice extends altos_bt_device implements AltosDevice {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
AltosBTDevice current;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
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_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.basic.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
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_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosCSVUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
class AltosEditFreqUI extends AltosUIDialog implements ActionListener {
Frame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosDataChooser extends JFileChooser {
JFrame frame;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import libaltosJNI.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
import java.awt.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
import java.awt.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosDisplayThread extends Thread {
for (;;) {
try {
state = reader.read();
- if (state == null)
+ if (state == null) {
+ listener_state.running = false;
break;
+ }
reader.update(state);
show_safely();
told = tell();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosEepromDelete implements Runnable {
AltosEepromList flights;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosEepromManage implements ActionListener {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosEepromMonitorUI extends AltosUIDialog implements AltosEepromMonitor {
JFrame owner;
int min_state, max_state;
ActionListener listener;
+ static final int progress_max = 10000;
+
public AltosEepromMonitorUI(JFrame owner) {
super (owner, "Download Flight Data", false);
pbar = new JProgressBar();
pbar.setMinimum(0);
- pbar.setMaximum(1000);
+ pbar.setMaximum(progress_max);
pbar.setValue(0);
pbar.setString("startup");
pbar.setStringPainted(true);
}
private void set_value_internal(String state_name, int state, int state_block, int block) {
- if (state_block > 100)
- state_block = 100;
- if (state < min_state) state = min_state;
- if (state >= max_state) state = max_state - 1;
- state -= min_state;
+ double pos;
+ String s;
+
+ if (min_state == AltosLib.ao_flight_invalid) {
+ int lblock = block;
+ if (lblock > 1000)
+ lblock = 1000;
+ pos = lblock / 1000.0;
+ s = String.format("block %d", block);
+ } else {
+ if (state == AltosLib.ao_flight_invalid)
+ state = 0;
+ if (state_block > 100)
+ state_block = 100;
+ if (state < min_state) state = min_state;
+ if (state > max_state) state = max_state;
+
+ if (state == max_state)
+ state_block = 0;
+
+ state -= min_state;
- int pos = state * 100 + state_block;
+ int nstate = max_state - min_state;
+
+ double spos = (double) state / (double) nstate;
+ double bpos = state_block / 100.0;
+
+ pos = spos + bpos / nstate;
+
+ s = String.format("block %d state %s", block, state_name);
+ }
- pbar.setString(String.format("block %d state %s", block, state_name));
- pbar.setValue(pos);
+ pbar.setString(s);
+ pbar.setValue((int) (pos * progress_max));
}
public void set_value(String in_state_name, int in_state, int in_state_block, int in_block) {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
class AltosEepromItem implements ActionListener {
AltosEepromLog log;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosFlashUI
extends AltosUIDialog
private static String[] pair_programmed = {
"teleballoon",
- "telebt",
- "teledongle",
+ "telebt-v1",
+ "teledongle-v0",
"telefire",
"telemetrum-v0",
"telemetrum-v1",
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public interface AltosFlightDisplay extends AltosUnitsListener, AltosFontListener {
void reset();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.table.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosFlightStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosFontListener {
void font_size_changed(int font_size);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
gps_nsat_solution_color,
false,
nsat_axis);
- addSeries("GPS Satellites in View",
- AltosGraphDataPoint.data_gps_nsat_view,
- nsat_units,
- gps_nsat_view_color,
- false,
- nsat_axis);
- addSeries("GPS Course",
- AltosGraphDataPoint.data_gps_course,
- orient_units,
- gps_course_color,
- false,
- course_axis);
- addSeries("GPS Ground Speed",
- AltosGraphDataPoint.data_gps_ground_speed,
- AltosConvert.speed,
- gps_ground_speed_color,
- enable_gps,
- speed_axis);
- addSeries("GPS Climb Rate",
- AltosGraphDataPoint.data_gps_climb_rate,
- AltosConvert.speed,
- gps_climb_rate_color,
- enable_gps,
- speed_axis);
+ if (stats.has_gps_sats) {
+ addSeries("GPS Satellites in View",
+ AltosGraphDataPoint.data_gps_nsat_view,
+ nsat_units,
+ gps_nsat_view_color,
+ false,
+ nsat_axis);
+ }
+ if (stats.has_gps_detail) {
+ addSeries("GPS Course",
+ AltosGraphDataPoint.data_gps_course,
+ orient_units,
+ gps_course_color,
+ false,
+ course_axis);
+ addSeries("GPS Ground Speed",
+ AltosGraphDataPoint.data_gps_ground_speed,
+ AltosConvert.speed,
+ gps_ground_speed_color,
+ enable_gps,
+ speed_axis);
+ addSeries("GPS Climb Rate",
+ AltosGraphDataPoint.data_gps_climb_rate,
+ AltosConvert.speed,
+ gps_climb_rate_color,
+ enable_gps,
+ speed_axis);
+ }
addSeries("GPS Position DOP",
AltosGraphDataPoint.data_gps_pdop,
dop_units,
gps_pdop_color,
false,
dop_axis);
- addSeries("GPS Horizontal DOP",
- AltosGraphDataPoint.data_gps_hdop,
- dop_units,
- gps_hdop_color,
- false,
- dop_axis);
- addSeries("GPS Vertical DOP",
- AltosGraphDataPoint.data_gps_vdop,
- dop_units,
- gps_vdop_color,
- false,
- dop_axis);
+ if (stats.has_gps_detail) {
+ addSeries("GPS Horizontal DOP",
+ AltosGraphDataPoint.data_gps_hdop,
+ dop_units,
+ gps_hdop_color,
+ false,
+ dop_axis);
+ addSeries("GPS Vertical DOP",
+ AltosGraphDataPoint.data_gps_vdop,
+ dop_units,
+ gps_vdop_color,
+ false,
+ dop_axis);
+ }
}
if (stats.has_rssi)
addSeries("Received Signal Strength",
}
if (stats.has_imu) {
- addSeries("Acceleration X",
- AltosGraphDataPoint.data_accel_x,
+ addSeries("Acceleration Along",
+ AltosGraphDataPoint.data_accel_along,
AltosConvert.accel,
accel_x_color,
false,
accel_axis);
- addSeries("Acceleration Y",
- AltosGraphDataPoint.data_accel_y,
+ addSeries("Acceleration Across",
+ AltosGraphDataPoint.data_accel_across,
AltosConvert.accel,
accel_y_color,
false,
accel_axis);
- addSeries("Acceleration Z",
- AltosGraphDataPoint.data_accel_z,
+ addSeries("Acceleration Through",
+ AltosGraphDataPoint.data_accel_through,
AltosConvert.accel,
accel_z_color,
false,
accel_axis);
- addSeries("Rotation Rate X",
- AltosGraphDataPoint.data_gyro_x,
+ addSeries("Roll Rate",
+ AltosGraphDataPoint.data_gyro_roll,
gyro_units,
gyro_x_color,
false,
gyro_axis);
- addSeries("Rotation Rate Y",
- AltosGraphDataPoint.data_gyro_y,
+ addSeries("Pitch Rate",
+ AltosGraphDataPoint.data_gyro_pitch,
gyro_units,
gyro_y_color,
false,
gyro_axis);
- addSeries("Rotation Rate Z",
- AltosGraphDataPoint.data_gyro_z,
+ addSeries("Yaw Rate",
+ AltosGraphDataPoint.data_gyro_yaw,
gyro_units,
gyro_z_color,
false,
gyro_axis);
}
if (stats.has_mag) {
- addSeries("Magnetometer X",
- AltosGraphDataPoint.data_mag_x,
+ addSeries("Magnetometer Along",
+ AltosGraphDataPoint.data_mag_along,
mag_units,
mag_x_color,
false,
mag_axis);
- addSeries("Magnetometer Y",
- AltosGraphDataPoint.data_mag_y,
+ addSeries("Magnetometer Across",
+ AltosGraphDataPoint.data_mag_across,
mag_units,
mag_y_color,
false,
mag_axis);
- addSeries("Magnetometer Z",
- AltosGraphDataPoint.data_mag_z,
+ addSeries("Magnetometer Through",
+ AltosGraphDataPoint.data_mag_through,
mag_units,
mag_z_color,
false,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosGraphDataPoint implements AltosUIDataPoint {
public static final int data_range = 14;
public static final int data_distance = 15;
public static final int data_pressure = 16;
- public static final int data_accel_x = 17;
- public static final int data_accel_y = 18;
- public static final int data_accel_z = 19;
- public static final int data_gyro_x = 20;
- public static final int data_gyro_y = 21;
- public static final int data_gyro_z = 22;
- public static final int data_mag_x = 23;
- public static final int data_mag_y = 24;
- public static final int data_mag_z = 25;
+ public static final int data_accel_along = 17;
+ public static final int data_accel_across = 18;
+ public static final int data_accel_through = 19;
+ public static final int data_gyro_roll = 20;
+ public static final int data_gyro_pitch = 21;
+ public static final int data_gyro_yaw = 22;
+ public static final int data_mag_along = 23;
+ public static final int data_mag_across = 24;
+ public static final int data_mag_through = 25;
public static final int data_orient = 26;
public static final int data_gps_course = 27;
public static final int data_gps_ground_speed = 28;
y = state.pressure();
break;
- case data_accel_x:
- case data_accel_y:
- case data_accel_z:
- case data_gyro_x:
- case data_gyro_y:
- case data_gyro_z:
- AltosIMU imu = state.imu;
- if (imu == null)
- break;
- switch (index) {
- case data_accel_x:
- y = imu.accel_x;
- break;
- case data_accel_y:
- y = imu.accel_y;
- break;
- case data_accel_z:
- y = imu.accel_z;
- break;
- case data_gyro_x:
- y = imu.gyro_x;
- break;
- case data_gyro_y:
- y = imu.gyro_y;
- break;
- case data_gyro_z:
- y = imu.gyro_z;
- break;
- }
+ case data_accel_along:
+ y = state.accel_along();
break;
- case data_mag_x:
- case data_mag_y:
- case data_mag_z:
- AltosMag mag = state.mag;
- if (mag == null)
- break;
- switch (index) {
- case data_mag_x:
- y = mag.x;
- break;
- case data_mag_y:
- y = mag.y;
- break;
- case data_mag_z:
- y = mag.z;
- break;
- }
+ case data_accel_across:
+ y = state.accel_across();
+ break;
+ case data_accel_through:
+ y = state.accel_through();
+ break;
+ case data_gyro_roll:
+ y = state.gyro_roll();
+ break;
+ case data_gyro_pitch:
+ y = state.gyro_pitch();
+ break;
+ case data_gyro_yaw:
+ y = state.gyro_yaw();
+ break;
+ case data_mag_along:
+ y = state.mag_along();
+ break;
+ case data_mag_across:
+ y = state.mag_across();
+ break;
+ case data_mag_through:
+ y = state.mag_through();
break;
case data_orient:
y = state.orient();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
class AltosGraphIterator implements Iterator<AltosUIDataPoint> {
AltosGraphDataSet dataSet;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosInfoTable extends JTable implements AltosFlightDisplay, HierarchyListener {
private AltosFlightInfoTableModel model;
state.gps.climb_rate);
if (state.gps.h_error != AltosLib.MISSING && state.gps.v_error != AltosLib.MISSING)
- info_add_row(1, "GPS error", "%6d m(h)%3d m(v)",
+ info_add_row(1, "GPS error", "%6.0f m(h)%6.0f m(v)",
state.gps.h_error, state.gps.v_error);
if (state.gps.pdop != AltosLib.MISSING &&
state.gps.hdop != AltosLib.MISSING &&
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import javax.swing.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosPositionListener {
public void position_changed(int position);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosRomconfigUI
extends AltosUIDialog
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.text.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
class AltosScanResult {
String callsign;
Thread thread;
AltosFrequency[] frequencies;
int frequency_index;
+ int packet_count;
+ int tick_count;
void scan_exception(Exception e) {
if (e instanceof FileNotFoundException) {
AltosState state = reader.read();
if (state == null)
continue;
+ packet_count++;
if (state.flight != AltosLib.MISSING) {
final AltosScanResult result = new AltosScanResult(state.callsign,
state.serial,
void next() throws InterruptedException, TimeoutException {
reader.set_monitor(false);
- /* Let any pending input from the last configuration drain out */
- Thread.sleep(100);
-
if (select_rate) {
boolean wrapped = false;
do {
return;
}
}
+ packet_count = 0;
+ tick_count = 0;
++frequency_index;
if (frequency_index >= frequencies.length)
frequency_index = 0;
}
void tick_timer() throws InterruptedException, TimeoutException {
- next();
+ ++tick_count;
+ if (packet_count == 0 || tick_count > 5)
+ next();
}
public void actionPerformed(ActionEvent e) {
if (r != null) {
if (device != null) {
if (reader != null) {
- System.out.printf("frequency %g rate %d\n", r.frequency.frequency, r.rate);
reader.set_telemetry(r.telemetry);
reader.set_telemetry_rate(r.rate);
reader.set_frequency(r.frequency.frequency);
}
public AltosScanUI(AltosUIFrame in_owner, boolean in_select_telemetry) {
+ super(in_owner, "Scan Telemetry", false);
owner = in_owner;
select_telemetry = in_select_telemetry;
* Deal with TeleDongle on a serial port
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.*;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import libaltosJNI.*;
/*
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public class AltosSerialInUseException extends Exception {
public AltosDevice device;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public class AltosUIDataMissing extends Exception {
public int id;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosUIDataPoint {
public abstract double x() throws AltosUIDataMissing;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosUIDataSet {
public abstract String name();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
public class AltosUIEnable extends Container {
- Insets il, ir;
- int y;
- int x;
+ Insets il, ir;
+ int y;
+ int x;
+ JCheckBox imperial_units;
static final int max_rows = 14;
+ public void units_changed(boolean imperial_units) {
+ if (this.imperial_units != null) {
+ this.imperial_units.setSelected(imperial_units);
+ }
+ }
+
class GraphElement implements ActionListener {
AltosUIGrapher grapher;
JCheckBox enable;
/* Imperial units setting */
/* Add label */
- JCheckBox imperial_units = new JCheckBox("Imperial Units", AltosUIPreferences.imperial_units());
+ imperial_units = new JCheckBox("Imperial Units", AltosUIPreferences.imperial_units());
imperial_units.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JCheckBox item = (JCheckBox) e.getSource();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
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_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIFreqList extends JComboBox<AltosFrequency> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public abstract class AltosUIIndicator implements AltosFontListener, AltosUnitsListener {
JLabel label;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUILatLon {
public double lat;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import libaltosJNI.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUILib extends AltosLib {
static public boolean loaded_library = false;
static public boolean has_bluetooth = false;
- static final String[] library_names = { "altos", "altos32", "altos64" };
+ static final String[] library_names_32 = { "altos", "altos32", "altos64" };
+ static final String[] library_names_64 = { "altos", "altos64", "altos32" };
public static boolean load_library() {
if (!initialized) {
- for (String name : library_names) {
+ String model = System.getProperty("sun.arch.data.model", "missing");
+ boolean is_64 = false;
+ if (model.equals("64")) {
+ is_64 = true;
+ } else if (model.equals("32")) {
+ ;
+ } else {
+ String arch = System.getProperty("os.arch", "missing");
+ if (arch.endsWith("64"))
+ is_64 = true;
+ }
+ for (String name : is_64 ? library_names_64 : library_names_32) {
try {
System.loadLibrary(name);
libaltos.altos_init();
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
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_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIMap extends JComponent implements AltosFlightDisplay, AltosUIMapZoomListener {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
import javax.imageio.ImageIO;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosUIMapCacheListener {
public void map_cache_changed(int map_cache);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
import javax.imageio.ImageIO;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIMapLine {
AltosUILatLon start, end;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIMapMark {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
class PathPoint {
AltosUILatLon lat_lon;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.lang.Math;
import java.net.URL;
import java.net.URLConnection;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
class AltosUIMapPos extends Box {
AltosUIFrame owner;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public class AltosUIMapRectangle {
AltosUILatLon ul, lr;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.net.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosUIMapStoreListener {
abstract void notify_store(AltosUIMapStore store, int status);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import java.awt.RenderingHints.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIMapTile {
AltosUIMapTileListener listener;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosUIMapTileListener {
abstract public void notify_tile(AltosUIMapTile tile, int status);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIMapTransform {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;
import java.util.concurrent.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIMapView extends Component implements MouseMotionListener, MouseListener, MouseWheelListener, ComponentListener, AltosUIMapTileListener, AltosUIMapStoreListener {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public interface AltosUIMapZoomListener {
abstract public void zoom_changed(int zoom);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.*;
import java.awt.Component;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIPreferences extends AltosPreferences {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.File;
import java.util.prefs.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import javax.swing.filechooser.FileSystemView;
public class AltosUIPreferencesBackend implements AltosPreferencesBackend {
_preferences.putBoolean(key, value);
}
+ public byte[] getBytes(String key, byte[] def) {
+ return _preferences.getByteArray(key, def);
+ }
+
+ public void putBytes(String key, byte[] value) {
+ _preferences.putByteArray(key, value);
+ }
+
public boolean nodeExists(String key) {
try {
return _preferences.nodeExists(key);
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUIRateList extends JComboBox<String> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.io.*;
import java.util.ArrayList;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.util.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class AltosUITelemetryList extends JComboBox<String> {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public abstract class AltosUIUnitsIndicator extends AltosUIIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
public class AltosUIVersion {
public final static String version = "@VERSION@";
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public abstract class AltosUIVoltageIndicator extends AltosUIUnitsIndicator {
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.util.*;
import libaltosJNI.*;
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
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_3;
+package org.altusmetrum.altosuilib_6;
import java.awt.*;
import java.awt.event.*;
*/
-package org.altusmetrum.altosuilib_3;
+package org.altusmetrum.altosuilib_6;
import java.lang.reflect.*;
import java.util.HashMap;
echo 'C 0' > $dev
+ calline=`./get-radio-cal $dev`
+ CURRENT_CAL=`echo $calline | awk '{print $2}'`
+ CURRENT_FREQ=`echo $calline | awk '{print $4}'`
+ CAL_VALUE=$CURRENT_CAL
+
case "$FREQ" in
"")
echo $SERIAL","$CAL_VALUE >> cal_values
exit 0
;;
*)
- calline=`./get-radio-cal $dev`
- CURRENT_CAL=`echo $calline | awk '{print $2}'`
- CURRENT_FREQ=`echo $calline | awk '{print $4}'`
-
echo "Current radio calibration "$CURRENT_CAL
echo "Current radio frequency "$CURRENT_FREQ
echo "Programming flash with cal value " $CAL_VALUE
+ dd if=$dev iflag=nonblock
+
cat << EOF > $dev
c f $CAL_VALUE
c w
--- /dev/null
+#!/bin/sh
+
+case $# in
+2)
+ dev="$1"
+ serial="$2"
+ ;;
+*)
+ echo "Usage: $0 <device> <serial>"
+ exit 1;
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+while true; do
+
+ dd if=$dev iflag=nonblock of=/dev/null > /dev/null 2>&1
+
+ echo 'C 1' > $dev
+
+ echo -n "Generating RF carrier. Please enter measured frequency [enter for done]: "
+
+ read FREQ
+
+ echo 'C 0' > $dev
+
+ calline=`./get-radio-cal $dev`
+ CURRENT_CAL=`echo $calline | awk '{print $2}'`
+ CURRENT_FREQ=`echo $calline | awk '{print $4}'`
+ CAL_VALUE=$CURRENT_CAL
+
+ case "$FREQ" in
+ "")
+ echo $serial","$CAL_VALUE >> cal_values
+ exit 0
+ ;;
+ *)
+ echo "Current radio calibration "$CURRENT_CAL
+ echo "Current radio frequency "$CURRENT_FREQ
+
+ CAL_VALUE=`nickle -e "floor($CURRENT_FREQ / $FREQ * $CURRENT_CAL + 0.5)"`
+
+ echo "Setting cal value" $CAL_VALUE
+
+ dd if=$dev iflag=nonblock of=/dev/null > /dev/null 2>&1
+
+ cat << EOF > $dev
+c f $CAL_VALUE
+EOF
+ ;;
+ esac
+done
+
"$PRODUCT-v$VERSION")
echo "Testing $product $serial $dev"
+ echo ""
- for igniter in drogue main 0 1 2 3; do
- echo "Testing $igniter igniter."
- echo -n "Press enter to continue..."
- read foo < /dev/tty
- ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
-
- case $? in
- 0)
- ;;
- *)
- echo "failed"
- exit 1
- ;;
- esac
- done
+ ./test-igniters $dev drogue main 0 1 2 3
+ echo""
echo "Testing baro sensor"
../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
echo "failed"
exit 1
esac
+ echo""
FLASHSIZE=8388608
echo "failed"
exit 1
esac
+ echo""
echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
ret=0
;;
- *)
- echo "Skipping $product $serial $dev"
- ;;
esac
done
"$PRODUCT-v$VERSION")
echo "Testing $product $serial $dev"
-
- echo "Testing igniters. Both should flash"
- ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" drogue main
-
- case $? in
- 0)
- ;;
- *)
- echo "failed"
- exit 1
- esac
+ echo ""
+
+ ./test-igniters "$dev" drogue main
+ echo ""
echo "Testing baro sensor"
../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
echo "failed"
exit 1
esac
+ echo""
FLASHSIZE=1048576
echo "failed"
exit 1
esac
+ echo""
echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
ret=0
;;
- *)
- echo "Skipping $product $serial $dev"
- ;;
esac
done
--- /dev/null
+#!/bin/sh
+
+dev="$1"
+shift
+
+for igniter in "$@"; do
+ pass="n"
+ while [ $pass != "y" ]; do
+ echo -n "Testing $igniter igniter. Press enter to continue..."
+ read foo < /dev/tty
+ ../ao-tools/ao-test-igniter/ao-test-igniter --tty="$dev" $igniter
+
+ case $? in
+ 0)
+ echo "pass"
+ pass="y"
+ ;;
+ *)
+ echo "Failed. Try again."
+ ;;
+ esac
+ done
+done
+
+exit 0
FLASHSIZE=2097152
echo "Testing flash"
- ./test-flash "$dev" "$FLASHSIZE"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
case $? in
0)
esac
echo "Testing GPS"
- ./test-gps "$dev"
+ ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
case $? in
0)
--- /dev/null
+#!/bin/sh
+
+VERSION=1.0
+PRODUCT=TeleMega
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+
+ ./test-igniters $dev main drogue 3 0 1 2
+ echo""
+
+ echo "Testing baro sensor"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ FLASHSIZE=8388608
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "Testing GPS"
+ ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ ret=0
+ ;;
+ esac
+done
--- /dev/null
+#!/bin/sh
+
+VERSION=2.0
+PRODUCT=TeleMetrum
+BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'`
+
+echo "$PRODUCT-v$VERSION Test Program"
+echo "Copyright 2014 by Keith Packard. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT v$VERSION powered from USB"
+echo
+
+ret=1
+ao-list | while read product serial dev; do
+ case "$product" in
+ "$PRODUCT-v$VERSION")
+
+ echo "Testing $product $serial $dev"
+ echo ""
+
+ ./test-igniters "$dev" drogue main
+ echo ""
+
+ echo "Testing baro sensor"
+ ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ FLASHSIZE=8388608
+
+ echo "Testing flash"
+ ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "Testing GPS"
+ ../ao-tools/ao-test-gps/ao-test-gps --tty="$dev"
+
+ case $? in
+ 0)
+ ;;
+ *)
+ echo "failed"
+ exit 1
+ esac
+ echo""
+
+ echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship
+ ret=0
+ ;;
+ esac
+done
echo $RAWLOAD
-$RAWLOAD -D 100 -r ao_led_blink.ihx
+case $USER in
+ bdale)
+ programmer=100
+ ;;
+ keithp)
+ programmer=186
+ ;;
+esac
+
+$RAWLOAD -D $programmer -r ao_led_blink.ihx
echo "LEDs should be blinking"
sleep 5
-$RAWLOAD -D 100 -r ao_radio_xmit.ihx
+$RAWLOAD -D $programmer -r ao_radio_xmit.ihx
echo -n "Generating RF carrier. Please enter measured frequency: "
read FREQ
CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"`
echo "Programming flash with cal value " $CAL_VALUE
-$AOLOAD -D 100 --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL
+$AOLOAD -D $programmer --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL
echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE
echo $SERIAL","$CAL_VALUE >> cal_values
--- /dev/null
+#!/bin/sh
+
+if [ -x ../ao-tools/ao-flash/ao-flash-lpc ]; then
+ FLASH_LPC=../ao-tools/ao-flash/ao-flash-lpc
+elif [ -x /usr/bin/ao-flash-lpc ]; then
+ FLASH_LPC=/usr/bin/ao-flash-lpc
+else
+ echo "Can't find ao-flash-lpc! 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
+
+PRODUCT=teledongle
+PRODUCT_NAME=TeleDongle
+VERSION=3.0
+
+echo "$PRODUCT_NAME v$VERSION Turn-On and Calibration Program"
+echo "Copyright © 2015 by Bdale Garbee. Released under GPL v2"
+echo
+echo "Expectations:"
+echo "\t$PRODUCT_NAME v$VERSION powered from USB"
+echo "\t\twith ST-Link-V2 cabled to debug header"
+echo "\t\twith coax from UHF to frequency counter"
+echo
+echo -n "$PRODUCT_NAME-$VERSION serial number: "
+read SERIAL
+
+BINARIES=$HOME/altusmetrumllc/Binaries
+
+LOADER="$BINARIES/loaders/$PRODUCT-v$VERSION-"*.elf
+ALTOS="$BINARIES/$PRODUCT-v$VERSION"*.elf
+
+$FLASH_LPC $LOADER || exit 1
+
+sleep 2
+
+$USBLOAD --serial=$SERIAL $ALTOS || exit 1
+
+sleep 5
+
+dev=`ao-list | awk '/TeleDongle-v'"$VERSION"'/ { print $3; exit(0); }'`
+
+case "$dev" in
+/dev/tty*)
+ echo "TeleDongle found on $dev"
+ ;;
+*)
+ echo 'No TeleDongle-v'"$VERSION"' found'
+ exit 1
+ ;;
+esac
+
+echo 'E 0' > $dev
+
+./cal-freq-file $dev $SERIAL
+
+case $? in
+ 0)
+ ;;
+ *)
+ echo "Frequency calibration failed"
+ exit 1
+ ;;
+esac
+
+CAL_VALUE=`grep "^$SERIAL," cal_values | tail -1 | sed 's/^[^,]*,//'`
+
+case "$CAL_VALUE" in
+ [1-9]*)
+ ;;
+ *)
+ echo "Invalid calibration value: $CAL_VALUE"
+ exit 1
+ ;;
+esac
+
+echo "Reflashing with calibration: $CAL_VALUE"
+
+$USBLOAD --cal=$CAL_VALUE --tty=$dev $ALTOS || exit 1
+
+echo "$PRODUCT_NAME-v$VERSION $SERIAL is ready to ship"
+
+exit $?
#!/bin/sh
if [ -x /usr/bin/ao-flash-stm ]; then
- STMLOAD=/usr/bin/ao-flash-stm
+ FLASH_STM=/usr/bin/ao-flash-stm
else
echo "Can't find ao-flash-stm! Aborting."
exit 1
echo "Copyright 2014 by Bdale Garbee. Released under GPL v2"
echo
echo "Expectations:"
-echo "\tTeleMega v$VERSIOn powered from USB"
+echo "\tTeleMega v$VERSION powered from USB"
echo "\t\twith ST-Link-V2 cabled to debug header"
echo "\t\twith coax from UHF to frequency counter"
echo
echo -n "TeleMega-$VERSION serial number: "
read SERIAL
-echo $STMLOAD
+echo $FLASH_STM
-$STMLOAD $REPO/loaders/telemega-v$VERSION*.elf || exit 1
+$FLASH_STM $REPO/loaders/telemega-v$VERSION*.elf || exit 1
-sleep 2
+sleep 5
$USBLOAD --serial=$SERIAL $REPO/telemega-v$VERSION*.elf || exit 1
-sleep 2
+sleep 5
dev=`ao-list | awk '/TeleMega-v'"$VERSION"'/ { print $3; exit(0); }'`
../ao-tools/ao-cal-accel/ao-cal-accel $dev
echo 'E 1' > $dev
+
+./test-telemega
+
+exit $?
../ao-tools/ao-cal-accel/ao-cal-accel $dev
echo 'E 1' > $dev
+
+./test-telemetrum
+
+exit $?
ao-load ao-telem ao-send-telem ao-sky-flash \
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-flash ao-cal-accel ao-test-gps ao-usbtrng
if LIBSTLINK
SUBDIRS += ao-stmload
endif
{ .name = "device", .has_arg = 1, .val = 'D' },
{ .name = "frequency", .has_arg = 1, .val = 'F' },
{ .name = "realtime", .has_arg = 0, .val = 'R' },
+ { .name = "verbose", .has_arg = 0, .val = 'v' },
+ { .name = "fake", .has_arg = 0, .val = 'f' },
{ 0, 0, 0, 0},
};
static void usage(char *program)
{
- fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--frequency <kHz>] [--realtime] file.telem ...\n", program);
+ fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--frequency <kHz>] [--realtime] [--verbose] [--fake] file.telem ...\n", program);
exit(1);
}
for (i = 0; i < 0x20; i++)
cc_usb_printf(cc, "%02x", b[i]);
cc_usb_sync(cc);
-}
+}
static void
do_delay(uint16_t now, uint16_t then)
uint16_t last_tick;
int started;
int realtime = 0;
-
+ int verbose = 0;
+ int fake = 0;
+ int rate = 0;
- while ((c = getopt_long(argc, argv, "RT:D:F:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "vRfT:D:F:r:", options, NULL)) != -1) {
switch (c) {
case 'T':
tty = optarg;
case 'R':
realtime = 1;
break;
+ case 'v':
+ verbose++;
+ break;
+ case 'f':
+ fake++;
+ break;
+ case 'r':
+ rate = atoi(optarg);
+ switch (rate) {
+ case 38400:
+ rate = 0;
+ break;
+ case 9600:
+ rate = 1;
+ break;
+ case 2400:
+ rate = 2;
+ break;
+ default:
+ fprintf(stderr, "Rate %d isn't 38400, 9600 or 2400\n", rate);
+ usage(argv[0]);
+ break;
+ }
+ break;
default:
usage(argv[0]);
break;
cc_usb_printf(cc, "m 0\n");
cc_usb_printf(cc, "c F %d\n", freq);
- for (i = optind; i < argc; i++) {
- file = fopen(argv[i], "r");
- if (!file) {
- perror(argv[i]);
- ret++;
- continue;
+ cc_usb_printf(cc, "c T %d\n", rate);
+
+ if (fake) {
+ union ao_telemetry_all telem;
+ uint16_t tick;
+ int i;
+
+ memset(&telem, '\0', sizeof (telem));
+ telem.generic.serial = 1;
+ telem.generic.type = 0;
+ for (i = 0; i < sizeof (telem.generic.payload); i++)
+ telem.generic.payload[i] = i & 7;
+ for (;;) {
+ telem.generic.tick += 50;
+ send_telem(cc, &telem);
+ do_delay(50, 0);
}
- started = 0;
- last_tick = 0;
- while (fgets(line, sizeof (line), file)) {
- union ao_telemetry_all telem;
-
- if (cc_telemetry_parse(line, &telem)) {
- /*
- * Skip packets with CRC errors.
- */
- if ((telem.generic.status & (1 << 7)) == 0)
- continue;
-
- if (started) {
- do_delay(telem.generic.tick, last_tick);
- last_tick = telem.generic.tick;
- send_telem(cc, &telem);
- } else {
- enum ao_flight_state state = packet_state(&telem);
- add_telem(&telem);
- if (ao_flight_pad < state && state < ao_flight_landed) {
- printf ("started\n");
- started = 1;
- last_tick = send_queued(cc, realtime);
+ } else {
+ for (i = optind; i < argc; i++) {
+ file = fopen(argv[i], "r");
+ if (!file) {
+ perror(argv[i]);
+ ret++;
+ continue;
+ }
+ started = 0;
+ last_tick = 0;
+ while (fgets(line, sizeof (line), file)) {
+ union ao_telemetry_all telem;
+
+ if (cc_telemetry_parse(line, &telem)) {
+ /*
+ * Skip packets with CRC errors.
+ */
+ if ((telem.generic.status & (1 << 7)) == 0)
+ continue;
+
+ if (verbose)
+ printf ("type %4d\n", telem.generic.type);
+
+ if (started || realtime) {
+ do_delay(telem.generic.tick, last_tick);
+ last_tick = telem.generic.tick;
+ send_telem(cc, &telem);
+ } else {
+ enum ao_flight_state state = packet_state(&telem);
+ printf ("\tstate %4d\n", state);
+ add_telem(&telem);
+ if (ao_flight_pad < state && state < ao_flight_landed) {
+ printf ("started\n");
+ started = 1;
+ last_tick = send_queued(cc, realtime);
+ }
}
}
}
- }
- fclose (file);
+ fclose (file);
+ }
}
return ret;
}
--- /dev/null
+ao-test-gps
--- /dev/null
+bin_PROGRAMS=ao-test-gps
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_test_gps_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_test_gps_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_test_gps_SOURCES=ao-test-gps.c
+
+man_MANS = ao-test-gps.1
--- /dev/null
+.\"
+.\" Copyright © 2009 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-test-gps" ""
+.SH NAME
+ao-test-baro \- test AltOS tracker GPS receiver
+.SH SYNOPSIS
+.B "ao-test-gps"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIgps-name...\fP
+.SH DESCRIPTION
+.I ao-test-gps
+Waits for the GPS receiver to report lock.
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMega:2
+.br
+TeleMega
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-test-gps
+opens the target device and waits for it to report GPS lock.
+.SH AUTHOR
+Keith Packard
--- /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 <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] main|drogue\n", program);
+ exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+/* cc_usb_printf(cc, "a\n"); */
+ cc_usb_close(cc);
+ exit (code);
+}
+
+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 int
+starts_with(char *whole, char *prefix)
+{
+ int whole_len = strlen(whole);
+ int prefix_len = strlen(prefix);
+
+ if (prefix_len > whole_len)
+ return 0;
+ return strncmp(whole, prefix, prefix_len) == 0;
+}
+
+static char **
+tok(char *line) {
+ char **strs = malloc (sizeof (char *)), *str;
+ int n = 0;
+
+ while ((str = strtok(line, " \t"))) {
+ line = NULL;
+ strs = realloc(strs, (n + 2) * sizeof (char *));
+ strs[n] = strdup(str);
+ n++;
+ }
+ strs[n] = '\0';
+ return strs;
+}
+
+static void
+free_strs(char **strs) {
+ char *str;
+ int i;
+
+ for (i = 0; (str = strs[i]) != NULL; i++)
+ free(str);
+ free(strs);
+}
+
+struct gps {
+ struct gps *next;
+ char **strs;
+};
+
+static struct gps *
+gps(struct cc_usb *usb)
+{
+ struct gps *head = NULL, **tail = &head;
+ cc_usb_printf(usb, "g\nv\n");
+ for (;;) {
+ char line[512];
+ struct gps *b;
+
+ cc_usb_getline(usb, line, sizeof (line));
+ b = malloc (sizeof (struct gps));
+ b->strs = tok(line);
+ b->next = NULL;
+ *tail = b;
+ tail = &b->next;
+ if (strstr(line, "software-version"))
+ break;
+ }
+ return head;
+}
+
+static void
+free_gps(struct gps *b) {
+ struct gps *n;
+
+ while (b) {
+ n = b->next;
+ free_strs(b->strs);
+ free(b);
+ b = n;
+ }
+}
+
+char **
+find_gps(struct gps *b, char *word0) {
+ int i;
+ for (;b; b = b->next)
+ if (b->strs[0] && !strcmp(b->strs[0], word0))
+ return b->strs;
+ return NULL;
+}
+
+int
+do_gps(struct cc_usb *usb) {
+ int count = 0;
+
+ for (;;) {
+ struct gps *b = gps(usb);
+ char **flags = find_gps(b, "Flags:");
+ char **sats = find_gps(b, "Sats:");
+ int actual_flags = strtol(flags[1], NULL, 0);
+ int actual_sats = strtol(sats[1], NULL, 0);
+
+ if (actual_flags & (1 << 4)) {
+ printf("\n");
+ printf("Flags: %s (0x%x)\n", flags[1], actual_flags);
+ printf("Sats: %s (%d)\n", sats[1], actual_sats);
+ break;
+ }
+
+ free_gps(b);
+ printf("%d", actual_sats);
+ ++count;
+ if (count >= 50) {
+ putchar('\n');
+ count = 0;
+ }
+ else if (count % 10 == 0)
+ putchar(' ');
+ fflush(stdout);
+ sleep(1);
+ }
+ return 1;
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device = NULL;
+ char *filename;
+ Elf *e;
+ unsigned int s;
+ int i;
+ int c;
+ int tries;
+ struct cc_usb *cc = NULL;
+ char *tty = NULL;
+ int success;
+ int verbose = 0;
+ int ret = 0;
+
+ while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ ao_verbose = verbose;
+
+ if (verbose > 1)
+ ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleGPS");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(tty);
+
+ if (!cc)
+ exit(1);
+
+ if (!do_gps(cc))
+ ret = 1;
+ done(cc, ret);
+}
if (verbose > 1)
ccdbg_add_debug(CC_DEBUG_BITBANG);
- printf ("device %s\n", device);
if (!tty)
tty = cc_usbdevs_find_by_arg(device, "TeleMega-v1.0");
if (!tty)
{ .name = "cal", .has_arg = 1, .val = 'c' },
{ .name = "serial", .has_arg = 1, .val = 's' },
{ .name = "verbose", .has_arg = 1, .val = 'v' },
+ { .name = "wait", .has_arg = 0, .val = 'w' },
{ 0, 0, 0, 0},
};
static void usage(char *program)
{
- fprintf(stderr, "usage: %s [--raw] [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] file.{elf,ihx}\n", program);
+ fprintf(stderr, "usage: %s [--raw] [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] [--cal=<radio-cal>] [--serial=<serial>] [--wait] file.{elf,ihx}\n", program);
exit(1);
}
uint32_t flash_base, flash_bound;
int has_flash_size = 0;
- while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ while ((c = getopt_long(argc, argv, "wrT:D:c:s:v:", options, NULL)) != -1) {
switch (c) {
case 'T':
tty = optarg;
case 'r':
raw = 1;
break;
+ case 'w':
+ cc_default_timeout = -1;
+ break;
case 'c':
cal = strtoul(optarg, &cal_end, 10);
if (cal_end == optarg || *cal_end != '\0')
this_tty = cc_usbdevs_find_by_arg(device, "AltosFlash");
if (!this_tty)
this_tty = cc_usbdevs_find_by_arg(device, "TeleMega");
+ if (!this_tty)
+ this_tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
+ if (!this_tty)
+ this_tty = cc_usbdevs_find_by_arg(device, "TeleGPS");
if (!this_tty)
this_tty = getenv("ALTOS_TTY");
if (!this_tty)
--- /dev/null
+ao-usbtrng
--- /dev/null
+bin_PROGRAMS=ao-usbtrng
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+
+ao_usbtrng_DEPENDENCIES = $(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_usbtrng_LDADD=$(top_builddir)/ao-tools/lib/libao-tools.a $(LIBUSB_LIBS)
+
+ao_usbtrng_SOURCES=ao-usbtrng.c
+
+man_MANS = ao-usbtrng.1
--- /dev/null
+.\"
+.\" Copyright © 2009 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-usbtrng" ""
+.SH NAME
+ao-usbtrng \- dump random numbers from USBtrng
+.SH SYNOPSIS
+.B "ao-usbtrng"
+[\-T \fItty-device\fP]
+[\--tty \fItty-device\fP]
+[\-D \fIaltos-device\fP]
+[\--device \fIaltos-device\fP]
+\fIkbytes\fP
+.SH DESCRIPTION
+.I ao-usbtrng
+dumps random numbers from a USBtrng device
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device the debugger uses to communicate with
+the target device. The special name 'BITBANG' directs ao-dbg to use
+the cp2103 connection, otherwise this should be a usb serial port
+connected to a suitable cc1111 debug node.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+usbtrng:2
+.br
+usbtrng
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.SH USAGE
+.I ao-usbtrng
+opens the target device and reads the specified number of kbytes of
+random data.
+.SH AUTHOR
+Keith Packard
--- /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 <err.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdbool.h>
+#include "ao-elf.h"
+#include "ccdbg.h"
+#include "cc-usb.h"
+#include "cc.h"
+#include "ao-verbose.h"
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "raw", .has_arg = 0, .val = 'r' },
+ { .name = "verbose", .has_arg = 1, .val = 'v' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--verbose=<verbose>] [--device=<device>] [-tty=<tty>] <kbytes>\n", program);
+ exit(1);
+}
+
+void
+done(struct cc_usb *cc, int code)
+{
+ cc_usb_close(cc);
+ exit (code);
+}
+
+int
+main (int argc, char **argv)
+{
+ char *device = NULL;
+ char *filename;
+ Elf *e;
+ unsigned int s;
+ int i;
+ int c;
+ int tries;
+ struct cc_usb *cc = NULL;
+ char *tty = NULL;
+ int success;
+ int verbose = 0;
+ int ret = 0;
+ int expected_size;
+ int kbytes;
+ uint8_t bits[1024];
+
+ while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+
+ if (!argv[optind])
+ usage(argv[0]);
+
+ kbytes = atoi(argv[optind]);
+ if (kbytes < 1)
+ kbytes = 1;
+
+ ao_verbose = verbose;
+
+ if (verbose > 1)
+ ccdbg_add_debug(CC_DEBUG_BITBANG);
+
+ if (!tty)
+ tty = cc_usbdevs_find_by_arg(device, "usbtrng");
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(tty);
+
+ if (!cc)
+ exit(1);
+
+ cc_usb_printf(cc, "f %d\n", kbytes);
+
+ while (kbytes--) {
+ int i;
+ for (i = 0; i < 1024; i++)
+ bits[i] = cc_usb_getchar(cc);
+ write(1, bits, 1024);
+ }
+
+ done(cc, ret);
+}
}
}
+int cc_default_timeout = 5000;
+
/*
* Flush pending writes, fill pending reads
*/
void
cc_usb_sync(struct cc_usb *cc)
{
- if (_cc_usb_sync(cc, 0, 5000) < 0) {
+ if (_cc_usb_sync(cc, 0, cc_default_timeout) < 0) {
fprintf(stderr, "USB link timeout\n");
exit(1);
}
cc_usb_getchar_timeout(struct cc_usb *cc, int timeout)
{
while (cc->in_pos == cc->in_count) {
- if (_cc_usb_sync(cc, timeout, 5000) < 0) {
+ if (_cc_usb_sync(cc, timeout, cc_default_timeout) < 0) {
fprintf(stderr, "USB link timeout\n");
exit(1);
}
int
cc_usb_getchar(struct cc_usb *cc)
{
- return cc_usb_getchar_timeout(cc, 5000);
+ return cc_usb_getchar_timeout(cc, cc_default_timeout);
}
void
cc_usb_printf(cc, "\nc F %d\nc c %s\np\nE 0\n", freq, call);
do {
cc->in_count = cc->in_pos = 0;
- _cc_usb_sync(cc, 100, 5000);
+ _cc_usb_sync(cc, 100, cc_default_timeout);
} while (cc->in_count > 0);
cc->remote = 1;
}
cc_usb_printf(cc, "\nE 0\nm 0\n");
do {
cc->in_count = cc->in_pos = 0;
- _cc_usb_sync(cc, 100, 5000);
+ _cc_usb_sync(cc, 100, cc_default_timeout);
} while (cc->in_count > 0);
return cc;
}
struct cc_usb;
+extern int cc_default_timeout;
+
struct cc_usb *
cc_usb_open(char *tty);
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.5)
+AC_INIT([altos], 1.6)
AC_CONFIG_SRCDIR([src/kernel/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
dnl ==========================================================================
dnl Java library versions
-ALTOSUILIB_VERSION=3
-ALTOSLIB_VERSION=5
+ALTOSUILIB_VERSION=6
+ALTOSLIB_VERSION=6
AC_SUBST(ALTOSLIB_VERSION)
AC_DEFINE(ALTOSLIB_VERSION,$ALTOSLIB_VERSION,[Version of the AltosLib package])
fi
fi
+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
+ ANDROID_RELEASE=yes
+ fi
else
HAVE_ANDROID_SDK="no"
fi
AM_CONDITIONAL([ANDROID], [test x$ANDROID_SDK != xno])
+AM_CONDITIONAL([ANDROID_RELEASE], [test x$ANDROID_RELEASE = xyes])
AC_SUBST(ANDROID_SDK)
ao-tools/ao-test-baro/Makefile
ao-tools/ao-test-flash/Makefile
ao-tools/ao-cal-accel/Makefile
+ao-tools/ao-test-gps/Makefile
+ao-tools/ao-usbtrng/Makefile
ao-utils/Makefile
src/Version
])
echo " AVR compiler................: ${AVR_CC} ${AVR_OBJCOPY}"
echo " AVR support.................: ${HAVE_AVR_CC}"
echo " Android support.............: ${HAVE_ANDROID_SDK}"
+echo " Android release support.....: ${ANDROID_RELEASE}"
echo " STlink support..............: ${HAVE_STLINK}"
echo " Local pdclib................: ${HAVE_PDCLIB}"
echo " i386 and amd64 libaltos.....: ${MULTI_ARCH}"
release-notes-1.3.2.html \
release-notes-1.4.html \
release-notes-1.4.1.html \
- release-notes-1.5.html
+ release-notes-1.5.html \
+ release-notes-1.6.html
PICTURES=\
altosui.png \
<surname>Towns</surname>
</author>
<copyright>
- <year>2014</year>
+ <year>2015</year>
<holder>Bdale Garbee and Keith Packard</holder>
</copyright>
<mediaobject>
</para>
</legalnotice>
<revhistory>
+ <revision>
+ <revnumber>1.6</revnumber>
+ <date>8 January 2015</date>
+ <revremark>
+ Major release adding TeleDongle v3.0 support.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.5</revnumber>
<date>6 September 2014</date>
channels and integrated gyroscopes for staging/air-start inhibit.
</para>
<para>
- TeleDongle was our first ground station, providing a USB to RF
+ TeleDongle v0.2 was our first ground station, providing a USB to RF
interfaces for communicating with the altimeters. Combined with
your choice of antenna and notebook computer, TeleDongle and our
associated user interface software form a complete ground
station capable of logging and displaying in-flight telemetry,
aiding rocket recovery, then processing and archiving flight
- data for analysis and review.
+ data for analysis and review. The latest version, TeleDongle
+ v3, has all new electronics with a higher performance radio
+ for improved range.
</para>
<para>
For a slightly more portable ground station experience that also
<listitem>
<para>
The Received Signal Strength Indicator value. This lets
- you know how strong a signal TeleDongle is receiving. The
- radio inside TeleDongle operates down to about -99dBm;
- weaker signals may not be receivable. The packet link uses
+ you know how strong a signal TeleDongle is receiving. At
+ the default data rate, 38400 bps, in bench testing, the
+ radio inside TeleDongle v0.2 operates down to about
+ -106dBm, while the v3 radio works down to about -111dBm.
+ Weaker signals, or an environment with radio noise may
+ cause the data to not be received. The packet link uses
error detection and correction techniques which prevent
incorrect data from being reported.
</para>
<title>Flash Image</title>
<para>
This reprograms Altus Metrum devices with new
- firmware. TeleMetrum v1.x, TeleDongle, TeleMini and TeleBT are
- all reprogrammed by using another similar unit as a
- programming dongle (pair programming). TeleMega, EasyMega, TeleMetrum v2
- and EasyMini are all programmed directly over their USB ports
- (self programming). Please read the directions for flashing
- devices in the Updating Device Firmware chapter below.
+ firmware. TeleMetrum v1.x, TeleDongle v0.2, TeleMini and
+ TeleBT are all reprogrammed by using another similar unit as a
+ programming dongle (pair programming). TeleMega, EasyMega,
+ TeleMetrum v2, EasyMini and TeleDongle v3 are all programmed
+ directly over their USB ports (self programming). Please read
+ the directions for flashing devices in the Updating Device
+ Firmware chapter below.
</para>
</section>
<section>
<chapter>
<title>Updating Device Firmware</title>
<para>
- TeleMega, TeleMetrum v2, EasyMega and EasyMini are all programmed directly
- over their USB connectors (self programming). TeleMetrum v1, TeleMini and
- TeleDongle are all programmed by using another device as a
- programmer (pair programming). It's important to recognize which
- kind of devices you have before trying to reprogram them.
+ TeleMega, TeleMetrum v2, EasyMega, EasyMini and TeleDongle v3
+ are all programmed directly over their USB connectors (self
+ programming). TeleMetrum v1, TeleMini and TeleDongle v0.2 are
+ all programmed by using another device as a programmer (pair
+ programming). It's important to recognize which kind of devices
+ you have before trying to reprogram them.
</para>
<para>
You may wish to begin by ensuring you have current firmware images.
version from <ulink url="http://www.altusmetrum.org/AltOS/"/>.
</para>
<para>
- If you need to update the firmware on a TeleDongle, we recommend
+ If you need to update the firmware on a TeleDongle v0.2, we recommend
updating the altimeter first, before updating TeleDongle. However,
note that TeleDongle rarely need to be updated. Any firmware version
1.0.1 or later will work, version 1.2.1 may have improved receiver
</para>
<section>
<title>
- Updating TeleMega, TeleMetrum v2, EasyMega or EasyMini Firmware
+ Updating TeleMega, TeleMetrum v2, EasyMega, EasyMini or
+ TeleDongle v3 Firmware
</title>
<orderedlist inheritnum='inherit' numeration='arabic'>
<listitem>
<para>
- Attach a battery and power switch to the target
+ Attach a battery if necessary and power switch to the target
device. Power up the device.
</para>
</listitem>
<listitem>
<para>
Verify that the device is working by using the 'Configure
- Altimeter' item to check over the configuration.
+ Altimeter' or 'Configure Groundstation' item to check over
+ the configuration.
</para>
</listitem>
</orderedlist>
</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>TeleDongle v3</term>
+ <listitem>
+ <para>
+ Connect pin 32 on the CPU to ground. Pin 32 is closest
+ to the USB wires on the row of pins towards the center
+ of the board. Ground is available on the capacitor
+ next to it, on the end towards the USB wires.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
<para>
Once you've located the right pins:
<title>Pair Programming</title>
<para>
The big concept to understand is that you have to use a
- TeleMega, TeleMetrum or TeleDongle as a programmer to update a
- pair programmed device. Due to limited memory resources in the
- cc1111, we don't support programming directly over USB for these
- devices.
+ TeleMetrum v1.0, TeleBT v1.0 or TeleDongle v0.2 as a
+ programmer to update a pair programmed device. Due to limited
+ memory resources in the cc1111, we don't support programming
+ directly over USB for these devices.
</para>
</section>
<section>
</listitem>
<listitem>
<para>
- Take the 2 screws out of the TeleDongle case to get access
- to the circuit board.
+ Take the 2 screws out of the TeleDongle v0.2 or TeleBT v1.0
+ case to get access to the circuit board.
</para>
</listitem>
<listitem>
<para>
Plug the 8-pin end of the programming cable to the
- matching connector on the TeleDongle, and the 4-pin end to the
+ matching connector on the TeleDongle v0.2 or TeleBT v1.0, and the 4-pin end to the
matching connector on the TeleMetrum.
Note that each MicroMaTch connector has an alignment pin that
goes through a hole in the PC board when you have the cable
</listitem>
<listitem>
<para>
- Plug the TeleDongle into your computer's USB port, and power
+ Plug the TeleDongle v0.2 or TeleBT v1.0 into your computer's USB port, and power
up the TeleMetrum.
</para>
</listitem>
</listitem>
<listitem>
<para>
- Pick the TeleDongle device from the list, identifying it as the
+ Pick the TeleDongle v0.2 or TeleBT v1.0 device from the list, identifying it as the
programming device.
</para>
</listitem>
</listitem>
<listitem>
<para>
- Take the 2 screws out of the TeleDongle case to get access
+ Take the 2 screws out of the TeleDongle v0.2 or TeleBT v1.0 case to get access
to the circuit board.
</para>
</listitem>
<listitem>
<para>
Plug the 8-pin end of the programming cable to the matching
- connector on the TeleDongle, and the 4-pins into the holes
+ connector on the TeleDongle v0.2 or TeleBT v1.0, and the 4-pins into the holes
in the TeleMini circuit board. Note that the MicroMaTch
connector has an alignment pin that goes through a hole in
the PC board when you have the cable oriented correctly, and
</listitem>
<listitem>
<para>
- Plug the TeleDongle into your computer's USB port, and power
+ Plug the TeleDongle v0.2 or TeleBT v1.0 into your computer's USB port, and power
up the TeleMini
</para>
</listitem>
</listitem>
<listitem>
<para>
- Pick the TeleDongle device from the list, identifying it as the
+ Pick the TeleDongle v0.2 or TeleBT v1.0 device from the list, identifying it as the
programming device.
</para>
</listitem>
</orderedlist>
</section>
<section>
- <title>Updating TeleDongle Firmware</title>
+ <title>Updating TeleDongle v0.2 Firmware</title>
<para>
- Updating TeleDongle's firmware is just like updating TeleMetrum or TeleMini
- firmware, but you use either a TeleMetrum or another TeleDongle as the programmer.
+ Updating TeleDongle v0.2 firmware is just like updating
+ TeleMetrum v1.x or TeleMini
+ firmware, but you use either a TeleMetrum v1.x, TeleDongle
+ v0.2 or TeleBT v1.0 as the programmer.
</para>
<orderedlist inheritnum='inherit' numeration='arabic'>
<listitem>
<listitem>
<para>
Find the USB cable that you got as part of the starter kit, and
- plug the “mini” end in to the mating connector on TeleMetrum or TeleDongle.
+ plug the “mini” end in to the mating connector on TeleMetrum
+ v1.x, TeleDongle v0.2 or TeleBT v1.0.
</para>
</listitem>
<listitem>
<para>
- Take the 2 screws out of the TeleDongle case to get access
+ Take the 2 screws out of the TeleDongle v0.2 or TeleBT v1.0 case to get access
to the circuit board.
</para>
</listitem>
<para>
Plug the 8-pin end of the programming cable to the
matching connector on the programmer, and the 4-pin end to the
- matching connector on the TeleDongle.
+ matching connector on the TeleDongle v0.2.
Note that each MicroMaTch connector has an alignment pin that
goes through a hole in the PC board when you have the cable
oriented correctly.
</listitem>
<listitem>
<para>
- Attach a battery to the TeleMetrum board if you're using one.
+ Attach a battery to the TeleMetrum v1.x board if you're using one.
</para>
</listitem>
<listitem>
</listitem>
<listitem>
<para>
- Select the image you want put on the TeleDongle, which should have a
+ Select the image you want put on the TeleDongle v0.2, which should have a
name in the form teledongle-v0.2-1.0.0.ihx. It should be visible
in the default directory, if not you may have to poke around
your system to find it.
<para>
Make sure the configuration parameters are reasonable
looking. If the serial number and/or RF configuration
- values aren't right, you'll need to change them. The TeleDongle
+ values aren't right, you'll need to change them. The
+ TeleDongle v0.2
serial number is on the “bottom” of the circuit board, and can
usually be read through the translucent blue plastic case without
needing to remove the board from the case.
<listitem>
<para>
Hit the 'OK' button and the software should proceed to flash
- the TeleDongle with new firmware, showing a progress bar.
+ the TeleDongle v0.2 with new firmware, showing a progress bar.
</para>
</listitem>
<listitem>
<para>
- Confirm that the TeleDongle board seems to have updated OK, which you
+ Confirm that the TeleDongle v0.2 board seems to have updated OK, which you
can do by plugging in to it over USB and using a terminal program
to connect to the board and issue the 'v' command to check
the version, etc. Once you're happy, remove the programming cable
- and put the cover back on the TeleDongle.
+ and put the cover back on the TeleDongle v0.2.
</para>
</listitem>
<listitem>
</para>
</section>
</appendix>
+ <appendix>
+ <title>Igniter Current</title>
+ <para>
+ The question "how much igniter current can Altus Metrum products
+ handle?" comes up fairly frequently. The short answer is "more than
+ you're likely to need", the remainder of this appendix provides a
+ longer answer.
+ </para>
+ <section>
+ <title>Current Products</title>
+ <para>
+ The FET switches we're using on all of our current products that
+ have pyro channels are the Vishay Siliconix Si7232DN. These parts
+ have exceptionally low Rds(on) values, better than 0.02 ohms! That
+ means they aren't making a lot of heat... and the limit on current
+ is "package limited", meaning it's all about how much you can heat
+ the die before something breaks.
+ </para>
+ <para>
+ Cutting to the chase, the Si7232DN specs are 25 amps <emphasis>continuous</emphasis> at
+ 20V at a temperature of 25C. In pulsed mode, they're rated for 40A.
+ However, those specs are a little mis-leading because it really is
+ all about the heat generated... you can get something like 85A
+ through one briefly. Note that a typical commercial e-match only
+ needed about 13 microseconds to fire in tests on my bench a couple
+ years ago!
+ </para>
+ <para>
+ So a great plan is to use something like an e-match as the initiator
+ and build up pyrogen(s) as required to actually light what you're
+ trying to light... But if you want to use a high-current igniter,
+ we can probably handle it!
+ </para>
+ </section>
+ <section>
+ <title>Version 1 Products</title>
+ <para>
+ The FET switches used on TeleMetrum v1 and TeleMini v1 products
+ were Fairchild FDS9926A. The Rds(on) values under our operating
+ conditions are on the order of 0.04 ohms. These parts were rated
+ for a continuous current-carrying capacity of 6.5A, and a pulsed
+ current capacity of 20A.
+ </para>
+ <para>
+ As with the more modern parts, the real limit is based on the heat
+ generated in the part during the firing interval. So, while the
+ specs on these parts aren't as good as the ones we use on current
+ products, they were still great, and we never had a complaint about
+ current carrying capacity with any of our v1 boards.
+ </para>
+ </section>
+ </appendix>
<appendix>
<title>Release Notes</title>
<simplesect>
- <title>Version 1.4.1</title>
+ <title>Version 1.6</title>
<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
- href="release-notes-1.4.1.xsl"
+ href="release-notes-1.6.xsl"
xpointer="xpointer(/article/*)"/>
</simplesect>
<simplesect>
href="release-notes-1.5.xsl"
xpointer="xpointer(/article/*)"/>
</simplesect>
+ <simplesect>
+ <title>Version 1.4.1</title>
+ <xi:include
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="release-notes-1.4.1.xsl"
+ xpointer="xpointer(/article/*)"/>
+ </simplesect>
<simplesect>
<title>Version 1.4</title>
<xi:include
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
+
+<article>
+ <para>
+ Version 1.6 includes support for our updated TeleDongle v3.0
+ product and bug fixes in in the flight software for all our boards
+ and ground station interfaces.
+ </para>
+ <para>
+ AltOS New Features
+ <itemizedlist>
+ <listitem>
+ <para>
+ Add support for TeleDongle v3.0 boards.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltOS Fixes
+ <itemizedlist>
+ <listitem>
+ <para>
+ Don't beep out the continuity twice by accident in idle mode.
+ If the battery voltage report takes longer than the initialiation
+ sequence, the igniter continuity would get reported twice.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Record all 32 bits of gyro calibration data in TeleMega and
+ EasyMega log files. This fixes computation of the gyro rates
+ in AltosUI.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Change TeleDongle LED usage. Green LED flashes when valid
+ packet is received. Red LED flashes when invalid packet is
+ received.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Replace LPC11U14 SPI driver with non-interrupt version. The
+ interrupt code would occasionally wedge on long transfers
+ if interrupts were blocked for too long. This affects all
+ released TeleGPS products; if you have a TeleGPS device,
+ you'll want to reflash the firmware.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltosUI and TeleGPS New Features
+ <itemizedlist>
+ <listitem>
+ <para>
+ Compute tilt angle from TeleMega and EasyMega log
+ files. This duplicates the quaternion-based angle tracking
+ code from the flight firmware inside the ground station
+ software so that post-flight analysis can include evaluation
+ of the tilt angle.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Shows the tool button window when starting with a data file
+ specified. This means that opening a data file from the file
+ manager will now bring up the main window to let you operate
+ the whole application.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltosUI Fixes
+ <itemizedlist>
+ <listitem>
+ <para>
+ Show the 'Connecting' dialog when using Monitor Idle. Lets
+ you cancel the Monitor Idle startup when connecting over the
+ radio link.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Make 'Monitor Idle' work for TeleGPS devices when connected
+ over USB. It's nice for testing without needing to broadcast
+ over the radio.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Use different Windows API to discover USB devices. This
+ works better on my Windows 7 box, and will be used if the
+ older API fails to provide the necessary information.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Look in more places in the registry to try and identify the
+ installed Java version on Windows. If you install the
+ default 32-bit version of Windows on a 64-bit OS, the Java
+ registry information is hiding \SOFTWARE\Wow6432Node for
+ some reason.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ Fix file association on Windows by searching for the
+ javaw.exe program instead of assuming it is in
+ %SYSTEMROOT%. This makes double-clicking on Altus Metrum
+ data files in the file manager work correctly.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ When replaying a file, put 'done' in the Age field when we
+ reach the end of the file, instead of continuing to count forever.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ In the Scan Channels code, wait for five seconds if we see
+ any packet. This is needed because AltOS now sends the
+ callsign, serial number and flight number only once every
+ five seconds these days.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ In the Scan Channels code, reset pending flight state
+ information each time we change channels. This avoids having
+ flight computers appear on multiple frequencies by accident.
+ </para>
+ </listitem>
+ </itemizedlist>
+ </para>
+</article>
<surname>Packard</surname>
</author>
<copyright>
- <year>2014</year>
+ <year>2015</year>
<holder>Bdale Garbee and Keith Packard</holder>
</copyright>
<mediaobject>
</para>
</legalnotice>
<revhistory>
+ <revision>
+ <revnumber>1.6</revnumber>
+ <date>8 January 2015</date>
+ <revremark>
+ Major release adding TeleDongle v3.0 support.
+ </revremark>
+ </revision>
<revision>
<revnumber>1.4.1</revnumber>
<date>20 June 2014</date>
<appendix>
<title>Release Notes</title>
<simplesect>
- <title>Version 1.41</title>
+ <title>Version 1.6</title>
+ <xi:include
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ href="release-notes-1.6.xsl"
+ xpointer="xpointer(/article/*)"/>
+ </simplesect>
+ <simplesect>
+ <title>Version 1.4.1</title>
<xi:include
xmlns:xi="http://www.w3.org/2001/XInclude"
href="release-notes-1.4.1.xsl"
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,
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);
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;
}
- vid = pid = serial = 0;
- 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);
}
/* Fetch the com port name */
import java.lang.*;
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
class MicroIterator implements Iterator<MicroDataPoint> {
int i;
package org.altusmetrum.micropeak;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroDataPoint implements AltosUIDataPoint {
public double time;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroDeviceDialog extends AltosDeviceDialog {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
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_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroExport extends JFileChooser {
import java.io.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroFile {
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroFileChooser extends JFileChooser {
JFrame frame;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroFrame extends AltosUIFrame {
static String[] micro_icon_names = {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
import org.jfree.ui.*;
import org.jfree.chart.*;
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroPeak extends MicroFrame implements ActionListener, ItemListener {
import java.awt.*;
import java.io.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroRaw extends JTextArea {
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroSave extends JFileChooser {
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroSerial extends InputStream {
SWIGTYPE_p_altos_file file;
import java.util.*;
import java.io.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public interface MicroSerialLog {
package org.altusmetrum.micropeak;
import java.io.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroStats {
double coast_height;
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroStatsTable extends JComponent implements AltosFontListener {
GridBagLayout layout;
import java.util.*;
import libaltosJNI.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class MicroUSB extends altos_device implements AltosDevice {
return libaltos.altos_open(this);
}
+ private boolean isFTDI() {
+ int vid = getVendor();
+ int pid = getProduct();
+ if (vid == 0x0403 && pid == 0x6015)
+ return true;
+ return false;
+ }
+
private boolean isMicro() {
- if (getVendor() != 0x0403)
- return false;
- if (getProduct() != 0x6015)
- return false;
- return true;
+ int vid = getVendor();
+ int pid = getProduct();
+ if (vid == AltosLib.vendor_altusmetrum &&
+ pid == AltosLib.product_mpusb)
+ return true;
+ return false;
}
public boolean matchProduct(int product) {
- return isMicro();
+ return isFTDI() || isMicro();
}
static java.util.List<MicroUSB> list() {
if (!load_library())
return null;
- SWIGTYPE_p_altos_list list = libaltos.altos_ftdi_list_start();
-
ArrayList<MicroUSB> device_list = new ArrayList<MicroUSB>();
+
+ SWIGTYPE_p_altos_list list;
+
+ list = libaltos.altos_ftdi_list_start();
+
+ if (list != null) {
+ for (;;) {
+ MicroUSB device = new MicroUSB();
+ if (libaltos.altos_list_next(list, device) == 0)
+ break;
+ if (device.isFTDI())
+ device_list.add(device);
+ }
+ libaltos.altos_list_finish(list);
+ }
+
+ list = libaltos.altos_list_start();
+
if (list != null) {
for (;;) {
MicroUSB device = new MicroUSB();
return device_list;
}
-}
\ No newline at end of file
+}
ExecWait $2
SectionEnd
+Section "Install Driver" InstDriver
+
+ InstDrv::InitDriverSetup /NOUNLOAD {4D36E96D-E325-11CE-BFC1-08002BE10318} AltusMetrumSerial
+ Pop $0
+ DetailPrint "InitDriverSetup: $0"
+ InstDrv::DeleteOemInfFiles /NOUNLOAD
+ InstDrv::CreateDevice /NOUNLOAD
+
+ SetOutPath $INSTDIR
+ File "../altusmetrum.inf"
+ File "../altusmetrum.cat"
+
+ ${DisableX64FSRedirection}
+ IfFileExists $WINDIR\System32\PnPutil.exe 0 nopnp
+ ${DisableX64FSRedirection}
+ nsExec::ExecToLog '"$WINDIR\System32\PnPutil.exe" -i -a "$INSTDIR\altusmetrum.inf"'
+ Goto done
+nopnp:
+ InstDrv::InstallDriver /NOUNLOAD "$INSTDIR\altusmetrum.inf"
+done:
+
+SectionEnd
+
Section "${REG_NAME} Application"
Call DetectJRE
File "../icon/${WIN_APP_ICON}"
- CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
+ CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
Section "${REG_NAME} Desktop Shortcut"
Section "File Associations"
+ ${DisableX64FSRedirection}
+
SetOutPath $INSTDIR
File "../icon/${WIN_APP_EXE}"
File "../icon/${WIN_MPD_EXE}"
+ SearchPath $1 "javaw.exe"
+
; application elements
DeleteRegKey HKCR "${PROG_ID}"
WriteRegStr HKCR "${PROG_ID_MPD}" "FriendlyTypeName" "MicroPeak Data File"
WriteRegStr HKCR "${PROG_ID_MPD}\CurVer" "" "${PROG_ID_MPD}"
WriteRegStr HKCR "${PROG_ID_MPD}\DefaultIcon" "" '"$INSTDIR\${WIN_MPD_EXE}",-101'
- WriteRegExpandStr HKCR "${PROG_ID_MPD}\shell\play\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+ WriteRegExpandStr HKCR "${PROG_ID_MPD}\shell\play\command" "" '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
; .mpd elements
Makedefs
altitude.h
altitude-pa.h
+altitude-pa-small.h
ao_whiten.h
telegps-v1.0 telegps-v1.0/flash-loader \
telelco-v0.2 telelco-v0.2/flash-loader \
telescience-v0.2 telescience-v0.2/flash-loader \
- teleballoon-v2.0
+ teledongle-v3.0 teledongle-v3.0/flash-loader \
+ teleballoon-v2.0 \
+ telebt-v3.0 telebt-v3.0/flash-loader
ARMM0DIRS=\
easymini-v1.0 easymini-v1.0/flash-loader
#define AO_STACK_SIZE 116
+#define AO_PORT_TYPE uint8_t
+
/* Various definitions to make GCC look more like SDCC */
#define ao_arch_naked_declare __attribute__((naked))
#define AO_STACK_SIZE 116
#endif
+#define AO_PORT_TYPE uint8_t
+
/* Various definitions to make GCC look more like SDCC */
#define ao_arch_naked_declare __attribute__((naked))
#define AO_STACK_END 0xfe
#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1)
+#define AO_PORT_TYPE uint8_t
+
#define ao_arch_reboot() do { \
WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \
ao_delay(AO_SEC_TO_TICKS(2)); \
*/
#include "ao.h"
+#ifdef AO_BTM_INT_PORT
+#include <ao_exti.h>
+#endif
#ifndef ao_serial_btm_getchar
#define ao_serial_btm_putchar ao_serial1_putchar
#define _ao_serial_btm_pollchar _ao_serial1_pollchar
+#define _ao_serial_btm_sleep() ao_sleep((void *) &ao_serial1_rx_fifo)
#define ao_serial_btm_set_speed ao_serial1_set_speed
#define ao_serial_btm_drain ao_serial1_drain
-#define ao_serial_btm_rx_fifo ao_serial1_rx_fifo
#endif
int8_t ao_btm_stdio;
#if BT_DEBUG
__xdata char ao_btm_buffer[256];
-int ao_btm_ptr;
+uint16_t ao_btm_ptr;
char ao_btm_dir;
static void
putchar(ao_btm_buffer[i]);
}
putchar('\n');
+ ao_cmd_decimal();
+ if (ao_cmd_status == ao_cmd_success && ao_cmd_lex_i)
+ ao_btm_ptr = 0;
+ ao_cmd_status = ao_cmd_success;
}
static void
ao_cmd_status = ao_cmd_syntax_error;
}
+static uint8_t ao_btm_enable;
+
+static void
+ao_btm_do_echo(void)
+{
+ int c;
+ while (ao_btm_enable) {
+ ao_arch_block_interrupts();
+ while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable)
+ _ao_serial_btm_sleep();
+ ao_arch_release_interrupts();
+ if (c != AO_READ_AGAIN) {
+ putchar(c);
+ flush();
+ }
+ }
+ ao_exit();
+}
+
+static struct ao_task ao_btm_echo_task;
+
+static void
+ao_btm_send(void)
+{
+ int c;
+ ao_btm_enable = 1;
+ ao_add_task(&ao_btm_echo_task, ao_btm_do_echo, "btm-echo");
+ while ((c = getchar()) != '~') {
+ ao_serial_btm_putchar(c);
+ }
+ ao_btm_enable = 0;
+ ao_wakeup((void *) &ao_serial_btm_rx_fifo);
+}
+
__code struct ao_cmds ao_btm_cmds[] = {
{ ao_btm_dump, "d\0Dump btm buffer." },
{ ao_btm_speed, "s <19200,57600>\0Set btm serial speed." },
+ { ao_btm_send, "S\0BTM interactive mode. ~ to exit." },
{ 0, NULL },
};
ao_arch_block_interrupts();
while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) {
ao_alarm(AO_MS_TO_TICKS(10));
- c = ao_sleep(&ao_serial_btm_rx_fifo);
+ c = _ao_serial_btm_sleep();
ao_clear_alarm();
if (c) {
c = AO_READ_AGAIN;
{
uint8_t ao_btm_reply_len = 0;
int c;
+ uint8_t l;
while ((c = ao_btm_getchar()) != AO_READ_AGAIN) {
ao_btm_log_in_char(c);
if (c == '\r' || c == '\n')
break;
}
- for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);)
- ao_btm_reply[c++] = '\0';
+ for (l = ao_btm_reply_len; l < sizeof (ao_btm_reply);)
+ ao_btm_reply[l++] = '\0';
return ao_btm_reply_len;
}
{
char c;
- while (c = *cmd++)
+ while ((c = *cmd++) != '\0')
ao_btm_putchar(c);
}
return 0;
}
+#if BT_LINK_ON_P2
+#define BT_PICTL_ICON PICTL_P2ICON
+#define BT_PIFG P2IFG
+#define BT_PDIR P2DIR
+#define BT_PINP P2INP
+#define BT_IEN2_PIE IEN2_P2IE
+#define BT_CC1111 1
+#endif
+#if BT_LINK_ON_P1
+#define BT_PICTL_ICON PICTL_P1ICON
+#define BT_PIFG P1IFG
+#define BT_PDIR P1DIR
+#define BT_PINP P1INP
+#define BT_IEN2_PIE IEN2_P1IE
+#define BT_CC1111 1
+#endif
+
+void
+ao_btm_check_link()
+{
+#if BT_CC1111
+ ao_arch_critical(
+ /* Check the pin and configure the interrupt detector to wait for the
+ * pin to flip the other way
+ */
+ if (BT_LINK_PIN) {
+ ao_btm_connected = 0;
+ PICTL |= BT_PICTL_ICON;
+ } else {
+ ao_btm_connected = 1;
+ PICTL &= ~BT_PICTL_ICON;
+ }
+ );
+#else
+ ao_arch_block_interrupts();
+ if (ao_gpio_get(AO_BTM_INT_PORT, AO_BTM_INT_PIN, AO_BTM_INT) == 0) {
+ ao_btm_connected = 1;
+ } else {
+ ao_btm_connected = 0;
+ }
+ ao_arch_release_interrupts();
+#endif
+}
+
+__xdata struct ao_task ao_btm_task;
+
/*
* A thread to initialize the bluetooth device and
* hang around to blink the LED when connected
NULL);
ao_btm_echo(0);
+ /* Check current pin state */
+ ao_btm_check_link();
+
+#ifdef AO_BTM_INT_PORT
+ ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN);
+#endif
+
for (;;) {
while (!ao_btm_connected)
ao_sleep(&ao_btm_connected);
}
}
-__xdata struct ao_task ao_btm_task;
-
-#if BT_LINK_ON_P2
-#define BT_PICTL_ICON PICTL_P2ICON
-#define BT_PIFG P2IFG
-#define BT_PDIR P2DIR
-#define BT_PINP P2INP
-#define BT_IEN2_PIE IEN2_P2IE
-#endif
-#if BT_LINK_ON_P1
-#define BT_PICTL_ICON PICTL_P1ICON
-#define BT_PIFG P1IFG
-#define BT_PDIR P1DIR
-#define BT_PINP P1INP
-#define BT_IEN2_PIE IEN2_P1IE
-#endif
-
-void
-ao_btm_check_link()
-{
- ao_arch_critical(
- /* Check the pin and configure the interrupt detector to wait for the
- * pin to flip the other way
- */
- if (BT_LINK_PIN) {
- ao_btm_connected = 0;
- PICTL |= BT_PICTL_ICON;
- } else {
- ao_btm_connected = 1;
- PICTL &= ~BT_PICTL_ICON;
- }
- );
-}
+#if BT_CC1111
void
ao_btm_isr(void)
#if BT_LINK_ON_P1
}
BT_PIFG = 0;
}
+#endif
+
+#ifdef AO_BTM_INT_PORT
+void
+ao_btm_isr(void)
+{
+ ao_btm_check_link();
+ ao_wakeup(&ao_btm_connected);
+}
+#endif
void
ao_btm_init (void)
ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200);
+#ifdef AO_BTM_RESET_PORT
+ ao_enable_output(AO_BTM_RESET_PORT,AO_BTM_RESET_PIN,AO_BTM_RESET,0);
+#endif
+
+#ifdef AO_BTM_INT_PORT
+ ao_enable_port(AO_BTM_INT_PORT);
+ ao_exti_setup(AO_BTM_INT_PORT, AO_BTM_INT_PIN,
+ AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_LOW,
+ ao_btm_isr);
+#endif
+
+#if BT_CC1111
#if BT_LINK_ON_P1
/*
* Configure ser reset line
/* Enable interrupts */
IEN2 |= BT_IEN2_PIE;
-
- /* Check current pin state */
- ao_btm_check_link();
+#endif
#if BT_LINK_ON_P2
/* Eable the pin interrupt */
ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN,
AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
- ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
- ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
-
rx_starting = 1;
rx_task_id = ao_cur_task->task_id;
+ ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr);
+ ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+
ao_radio_strobe(CC1120_SRX);
if (timeout)
ao_clear_alarm();
if (ao_radio_abort) {
+ if (rx_task_id_save == 0)
+ ao_radio_burst_read_stop();
ret = 0;
- rx_task_id = 0;
goto abort;
}
#define FOSC 26000000
-#define ao_radio_select() ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_SPI_SPEED_1MHz)
+#define ao_radio_select() ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_SPI_SPEED_6MHz)
#define ao_radio_deselect() ao_spi_put_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS)
#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC115L_SPI_BUS)
#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC115L_SPI_BUS)
}
/* Flush any pending TX bytes */
ao_radio_strobe(CC115L_SFTX);
+ /* Make sure the RF calibration is current */
+ ao_radio_strobe(CC115L_SCAL);
}
/*
static const uint16_t packet_setup[] = {
CC115L_MDMCFG3, (PACKET_DRATE_M),
- CC115L_MDMCFG2, (0x00 |
- (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
+ CC115L_MDMCFG2, ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
(0 << CC115L_MDMCFG2_MANCHESTER_EN) |
(CC115L_MDMCFG2_SYNC_MODE_16BITS << CC115L_MDMCFG2_SYNC_MODE)),
};
/*
- * RDF deviation is 5kHz
+ * RDF deviation is 3kHz
*
* fdev = fosc >> 17 * (8 + dev_m) << dev_e
*
- * 26e6 / (2 ** 17) * (8 + 4) * (2 ** 1) = 4761Hz
+ * 26e6 / (2 ** 17) * (8 + 7) * (2 ** 0) = 2975
*/
-#define RDF_DEV_E 1
-#define RDF_DEV_M 4
+#define RDF_DEV_E 0
+#define RDF_DEV_M 7
/*
* For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
CC115L_MDMCFG4, ((0xf << 4) |
(RDF_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
CC115L_MDMCFG3, (RDF_DRATE_M),
- CC115L_MDMCFG2, (0x00 |
- (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
+ CC115L_MDMCFG2, ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
(0 << CC115L_MDMCFG2_MANCHESTER_EN) |
(CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)),
};
CC115L_MDMCFG4, ((0xf << 4) |
(APRS_DRATE_E << CC115L_MDMCFG4_DRATE_E)),
CC115L_MDMCFG3, (APRS_DRATE_M),
- CC115L_MDMCFG2, (0x00 |
- (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
+ CC115L_MDMCFG2, ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) |
(0 << CC115L_MDMCFG2_MANCHESTER_EN) |
(CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)),
};
AO_CC115L_DONE_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_PA_PD | (1 << CC115L_IOCFG_GPIO_INV),
CC115L_FIFOTHR, 0x47, /* TX FIFO Thresholds */
- CC115L_MDMCFG1, (0x00 |
- (CC115L_MDMCFG1_NUM_PREAMBLE_4 << CC115L_MDMCFG1_NUM_PREAMBLE) |
- (1 << CC115L_MDMCFG1_CHANSPC_E)),
+ CC115L_MDMCFG1, /* Modem Configuration */
+ ((CC115L_MDMCFG1_NUM_PREAMBLE_4 << CC115L_MDMCFG1_NUM_PREAMBLE) |
+ (1 << CC115L_MDMCFG1_CHANSPC_E)),
CC115L_MDMCFG0, 248, /* Channel spacing M value (100kHz channels) */
+ CC115L_MCSM1, 0x30, /* Main Radio Control State Machine Configuration */
CC115L_MCSM0, 0x38, /* Main Radio Control State Machine Configuration */
CC115L_RESERVED_0X20, 0xfb, /* Use setting from SmartRF Studio */
+ CC115L_FREND0, 0x10, /* Front End TX Configuration */
CC115L_FSCAL3, 0xe9, /* Frequency Synthesizer Calibration */
CC115L_FSCAL2, 0x2a, /* Frequency Synthesizer Calibration */
CC115L_FSCAL1, 0x00, /* Frequency Synthesizer Calibration */
CC115L_FSCAL0, 0x1f, /* Frequency Synthesizer Calibration */
+ CC115L_RESERVED_0X29, 0x59, /* RESERVED */
+ CC115L_RESERVED_0X2A, 0x7f, /* RESERVED */
+ CC115L_RESERVED_0X2B, 0x3f, /* RESERVED */
CC115L_TEST2, 0x81, /* Various Test Settings */
CC115L_TEST1, 0x35, /* Various Test Settings */
CC115L_TEST0, 0x09, /* Various Test Settings */
static uint8_t ao_radio_configured = 0;
+#if HAS_RADIO_POWER
+#define RADIO_POWER ao_config.radio_power
+#else
+
+#if 0
+#define RADIO_POWER 0x03 /* -31.75dBm on the test board */
+#endif
+
+#define RADIO_POWER 0xc0 /* full power */
+
+#endif
+
static void
ao_radio_setup(void)
{
ao_config_get();
+ ao_radio_reg_write(CC115L_PA, RADIO_POWER);
+
ao_radio_strobe(CC115L_SCAL);
ao_radio_configured = 1;
ao_radio_reg_write(CC115L_FREQ1, ao_config.radio_setting >> 8);
ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting);
last_radio_setting = ao_config.radio_setting;
+ /* Make sure the RF calibration is current */
+ ao_radio_strobe(CC115L_SCAL);
}
if (ao_config.radio_rate != last_radio_rate) {
ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX;
#define POWER_STEP 0x08
-#if HAS_RADIO_POWER
-#define RADIO_POWER ao_config.radio_power
-#else
-#define RADIO_POWER 0xc0
-#endif
-
static void
ao_radio_stx(void)
{
- uint8_t power;
ao_radio_pa_on();
- ao_radio_reg_write(CC115L_PA, 0);
ao_radio_strobe(CC115L_STX);
- for (power = POWER_STEP; power < RADIO_POWER; power += POWER_STEP)
- ao_radio_reg_write(CC115L_PA, power);
- if (power != RADIO_POWER)
- ao_radio_reg_write(CC115L_PA, RADIO_POWER);
}
static void
--- /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_cc1200.h>
+#include <ao_exti.h>
+#include <ao_fec.h>
+#include <ao_packet.h>
+
+static uint8_t ao_radio_mutex;
+
+static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */
+static uint8_t ao_radio_abort; /* radio operation should abort */
+
+int8_t ao_radio_rssi; /* Last received RSSI value */
+
+#ifndef CC1200_DEBUG
+#define CC1200_DEBUG 0
+#endif
+
+#ifndef CC1200_LOW_LEVEL_DEBUG
+#define CC1200_LOW_LEVEL_DEBUG 0
+#endif
+
+#define CC1200_TRACE 0
+#define CC1200_APRS_TRACE 0
+
+extern const uint32_t ao_radio_cal;
+
+#define FOSC 40000000
+
+#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_FAST)
+#define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS)
+#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS)
+#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS)
+#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS)
+#define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS)
+
+static uint8_t
+ao_radio_reg_read(uint16_t addr)
+{
+ uint8_t data[2];
+ uint8_t d;
+
+#if CC1200_TRACE
+ printf("\t\tao_radio_reg_read (%04x): ", addr); flush();
+#endif
+ if (CC1200_IS_EXTENDED(addr)) {
+ data[0] = ((1 << CC1200_READ) |
+ (0 << CC1200_BURST) |
+ CC1200_EXTENDED);
+ data[1] = addr;
+ d = 2;
+ } else {
+ data[0] = ((1 << CC1200_READ) |
+ (0 << CC1200_BURST) |
+ addr);
+ d = 1;
+ }
+ ao_radio_select();
+ ao_radio_spi_send(data, d);
+ ao_radio_spi_recv(data, 1);
+ ao_radio_deselect();
+#if CC1200_TRACE
+ printf (" %02x\n", data[0]);
+#endif
+ return data[0];
+}
+
+static void
+ao_radio_reg_write(uint16_t addr, uint8_t value)
+{
+ uint8_t data[3];
+ uint8_t d;
+
+#if CC1200_TRACE
+ printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value);
+#endif
+ if (CC1200_IS_EXTENDED(addr)) {
+ data[0] = ((0 << CC1200_READ) |
+ (0 << CC1200_BURST) |
+ CC1200_EXTENDED);
+ data[1] = addr;
+ d = 2;
+ } else {
+ data[0] = ((0 << CC1200_READ) |
+ (0 << CC1200_BURST) |
+ addr);
+ d = 1;
+ }
+ data[d] = value;
+ ao_radio_select();
+ ao_radio_spi_send(data, d+1);
+ ao_radio_deselect();
+#if CC1200_TRACE
+ (void) ao_radio_reg_read(addr);
+#endif
+}
+
+static uint8_t
+ao_radio_strobe(uint8_t addr)
+{
+ uint8_t in;
+
+#if CC1200_TRACE
+ printf("\t\tao_radio_strobe (%02x): ", addr); flush();
+#endif
+ ao_radio_select();
+ ao_radio_duplex(&addr, &in, 1);
+ ao_radio_deselect();
+#if CC1200_TRACE
+ printf("%02x\n", in); flush();
+#endif
+ return in;
+}
+
+static uint8_t
+ao_radio_fifo_read(uint8_t *data, uint8_t len)
+{
+ uint8_t addr = ((1 << CC1200_READ) |
+ (1 << CC1200_BURST) |
+ CC1200_FIFO);
+ uint8_t status;
+
+ ao_radio_select();
+ ao_radio_duplex(&addr, &status, 1);
+ ao_radio_spi_recv(data, len);
+ ao_radio_deselect();
+ return status;
+}
+
+static uint8_t
+ao_radio_fifo_write_start(void)
+{
+ uint8_t addr = ((0 << CC1200_READ) |
+ (1 << CC1200_BURST) |
+ CC1200_FIFO);
+ uint8_t status;
+
+ ao_radio_select();
+ ao_radio_duplex(&addr, &status, 1);
+ return status;
+}
+
+static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) {
+ ao_radio_deselect();
+ return status;
+}
+
+static uint8_t
+ao_radio_fifo_write(const uint8_t *data, uint8_t len)
+{
+ uint8_t status = ao_radio_fifo_write_start();
+ ao_radio_spi_send(data, len);
+ return ao_radio_fifo_write_stop(status);
+}
+
+static uint8_t
+ao_radio_fifo_write_fixed(uint8_t data, uint8_t len)
+{
+ uint8_t status = ao_radio_fifo_write_start();
+ ao_radio_spi_send_fixed(data, len);
+ return ao_radio_fifo_write_stop(status);
+}
+
+static uint8_t
+ao_radio_tx_fifo_space(void)
+{
+ return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES);
+}
+
+static uint8_t
+ao_radio_status(void)
+{
+ return ao_radio_strobe (CC1200_SNOP);
+}
+
+void
+ao_radio_recv_abort(void)
+{
+ ao_radio_abort = 1;
+ ao_wakeup(&ao_radio_wake);
+}
+
+#define ao_radio_rdf_value 0x55
+
+static void
+ao_radio_isr(void)
+{
+ ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+ ao_radio_wake = 1;
+ ao_wakeup(&ao_radio_wake);
+}
+
+static void
+ao_radio_start_tx(void)
+{
+ ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+ ao_radio_strobe(CC1200_STX);
+}
+
+static void
+ao_radio_start_rx(void)
+{
+ ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+ ao_radio_strobe(CC1200_SRX);
+}
+
+static void
+ao_radio_idle(void)
+{
+ for (;;) {
+ uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
+ if (state == CC1200_STATUS_STATE_IDLE)
+ break;
+ if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR)
+ ao_radio_strobe(CC1200_SFTX);
+ if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR)
+ ao_radio_strobe(CC1200_SFRX);
+ }
+ /* Flush any pending data in the fifos */
+ ao_radio_strobe(CC1200_SFTX);
+ ao_radio_strobe(CC1200_SFRX);
+ /* Make sure the RF calibration is current */
+ ao_radio_strobe(CC1200_SCAL);
+}
+
+/*
+ * Packet deviation
+ *
+ * fdev = fosc >> 22 * (256 + dev_m) << dev_e
+ *
+ * Deviation for 38400 baud should be 20.5kHz:
+ *
+ * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz
+ *
+ * Deviation for 9600 baud should be 5.125kHz:
+ *
+ * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz
+ *
+ * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and
+ * cc115l can't do that, so we'll use 1.5kHz instead:
+ *
+ * 40e6 / (2 ** 21) * (79) = 1506Hz
+ */
+
+#define PACKET_DEV_M_384 13
+#define PACKET_DEV_E_384 3
+
+#define PACKET_DEV_M_96 13
+#define PACKET_DEV_E_96 1
+
+#define PACKET_DEV_M_24 79
+#define PACKET_DEV_E_24 0
+
+/*
+ * For our packet data
+ *
+ * (2**20 + DATARATE_M) * 2 ** DATARATE_E
+ * Rdata = -------------------------------------- * fosc
+ * 2 ** 39
+ *
+ * Given the bit period of the baseband, T, the bandwidth of the
+ * baseband signal is B = 1/(2T). The overall bandwidth of the
+ * modulated signal is then Channel bandwidth = 2Δf + 2B.
+ *
+ * 38400 -- 2 * 20500 + 38400 = 79.4 kHz
+ * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz
+ * 2400 -- 2 * 1.5 + 2400 = 5.4 khz
+ *
+ * Symbol rate 38400 Baud:
+ *
+ * DATARATE_M = 1013008
+ * DATARATE_E = 8
+ * CHANBW = 104.16667
+ *
+ * Symbol rate 9600 Baud:
+ *
+ * DATARATE_M = 1013008
+ * DATARATE_E = 6
+ * CHANBW = 26.042 (round to 19.8)
+ *
+ * Symbol rate 2400 Baud:
+ *
+ * DATARATE_M = 1013008
+ * DATARATE_E = 4
+ * CHANBW = 5.0 (round to 9.5)
+ */
+
+#define PACKET_SYMBOL_RATE_M 1013008
+
+#define PACKET_SYMBOL_RATE_E_384 8
+
+/* 200 / 2 = 100 */
+#define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+ (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_SYMBOL_RATE_E_96 6
+/* 200 / 10 = 20 */
+#define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+ (16 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+#define PACKET_SYMBOL_RATE_E_24 4
+/* 200 / 25 = 8 */
+#define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \
+ (44 << CC1200_CHAN_BW_BB_CIC_DECFACT))
+
+static const uint16_t packet_setup[] = {
+ CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff),
+ CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff),
+ CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
+ ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+ (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+ (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+ CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
+ ((1 << CC1200_PKT_CFG1_FEC_EN) |
+ (1 << CC1200_PKT_CFG1_WHITE_DATA) |
+ (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+ (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+ (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
+ (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
+ CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+ (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+};
+
+static const uint16_t packet_setup_384[] = {
+ CC1200_DEVIATION_M, PACKET_DEV_M_384,
+ CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+ (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)),
+ CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) |
+ (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+ CC1200_CHAN_BW, PACKET_CHAN_BW_384,
+ CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
+ ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+ (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+ (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
+ (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+static const uint16_t packet_setup_96[] = {
+ CC1200_DEVIATION_M, PACKET_DEV_M_96,
+ CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+ (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)),
+ CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) |
+ (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+ CC1200_CHAN_BW, PACKET_CHAN_BW_96,
+ CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
+ ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+ (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+ (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) |
+ (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+static const uint16_t packet_setup_24[] = {
+ CC1200_DEVIATION_M, PACKET_DEV_M_24,
+ CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+ (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)),
+ CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) |
+ (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+ CC1200_CHAN_BW, PACKET_CHAN_BW_24,
+ CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
+ ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+ (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+ (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) |
+ (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+/*
+ * RDF deviation is 3kHz
+ *
+ * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
+ * fdev = fosc >> 21 * dev_m dev_e == 0
+ *
+ * 40e6 / (2 ** 21) * 157 = 2995Hz
+ */
+
+#define RDF_DEV_E 0
+#define RDF_DEV_M 157
+
+/*
+ * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone)
+ *
+ * (2**20 + DATARATE_M) * 2 ** DATARATE_E
+ * Rdata = -------------------------------------- * fosc
+ * 2 ** 39
+ *
+ * DATARATE_M = 669411
+ * DATARATE_E = 4
+ *
+ * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes
+ */
+#define RDF_SYMBOL_RATE_E 4
+#define RDF_SYMBOL_RATE_M 669411
+#define RDF_PACKET_LEN 50
+
+static const uint16_t rdf_setup[] = {
+ CC1200_DEVIATION_M, RDF_DEV_M,
+ CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+ (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
+ CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
+ (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+ CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff),
+ CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff),
+ CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
+ ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+ (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+ (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+ CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
+ ((0 << CC1200_PKT_CFG1_FEC_EN) |
+ (0 << CC1200_PKT_CFG1_WHITE_DATA) |
+ (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+ (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+ (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
+ (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
+ CC1200_PREAMBLE_CFG1,
+ ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+ (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+ CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
+ ((0 << CC1200_MDMCFG2_ASK_SHAPE) |
+ (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+ (12 << CC1200_MDMCFG2_UPSAMPLER_P) |
+ (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+/*
+ * APRS deviation is 3kHz
+ *
+ * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0
+ * fdev = fosc >> 21 * dev_m dev_e == 0
+ *
+ * 40e6 / (2 ** 21) * 157 = 2995Hz
+ */
+
+#define APRS_DEV_E 0
+#define APRS_DEV_M 157
+
+/*
+ * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate)
+ *
+ * (2**20 + DATARATE_M) * 2 ** DATARATE_E
+ * Rdata = -------------------------------------- * fosc
+ * 2 ** 39
+ *
+ * DATARATE_M = 1013008
+ * DATARATE_E = 6
+ *
+ * Rdata = 9599.998593330383301
+ *
+ */
+#define APRS_SYMBOL_RATE_E 6
+#define APRS_SYMBOL_RATE_M 1013008
+
+static const uint16_t aprs_setup[] = {
+ CC1200_DEVIATION_M, APRS_DEV_M,
+ CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+ (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)),
+ CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
+ (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+ CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
+ CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
+ CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
+ ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+ (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+ (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+ CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
+ ((0 << CC1200_PKT_CFG1_FEC_EN) |
+ (0 << CC1200_PKT_CFG1_WHITE_DATA) |
+ (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+ (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+ (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
+ (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
+ CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
+ ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
+ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
+ (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
+ (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
+ CC1200_PREAMBLE_CFG1,
+ ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+ (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+ CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
+ ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+ (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+ (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
+ (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+};
+
+/*
+ * For Test mode, we want an unmodulated carrier. To do that, we
+ * set the deviation to zero and enable a preamble so that the radio
+ * turns on before we send any data
+ */
+
+static const uint16_t test_setup[] = {
+ CC1200_DEVIATION_M, 0,
+ CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) |
+ (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) |
+ (0 << CC1200_MODCFG_DEV_E_DEV_E)),
+ CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) |
+ (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)),
+ CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff),
+ CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff),
+ CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+ (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+ CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) |
+ (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+ (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) |
+ (0 << CC1200_PKT_CFG1_APPEND_STATUS)),
+ CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) |
+ (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)),
+};
+
+#define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
+ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
+ (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
+ (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
+
+#define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \
+ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \
+ (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \
+ (0 << CC1200_PKT_CFG0_UART_SWAP_EN))
+
+static uint16_t ao_radio_mode;
+
+#define AO_RADIO_MODE_BITS_PACKET 1
+#define AO_RADIO_MODE_BITS_TX_BUF 4
+#define AO_RADIO_MODE_BITS_TX_FINISH 8
+#define AO_RADIO_MODE_BITS_RX 16
+#define AO_RADIO_MODE_BITS_RDF 32
+#define AO_RADIO_MODE_BITS_APRS 64
+#define AO_RADIO_MODE_BITS_TEST 128
+#define AO_RADIO_MODE_BITS_INFINITE 256
+#define AO_RADIO_MODE_BITS_FIXED 512
+
+#define AO_RADIO_MODE_NONE 0
+#define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
+#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX)
+#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
+#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
+#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF)
+#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH)
+#define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF)
+
+static void
+_ao_radio_set_regs(const uint16_t *regs, int nreg)
+{
+ int i;
+
+ for (i = 0; i < nreg; i++) {
+ ao_radio_reg_write(regs[0], regs[1]);
+ regs += 2;
+ }
+}
+
+#define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1)
+
+static void
+ao_radio_set_mode(uint16_t new_mode)
+{
+ uint16_t changes;
+
+ if (new_mode == ao_radio_mode)
+ return;
+
+ changes = new_mode & (~ao_radio_mode);
+
+ if (changes & AO_RADIO_MODE_BITS_PACKET) {
+ ao_radio_set_regs(packet_setup);
+
+ switch (ao_config.radio_rate) {
+ default:
+ case AO_RADIO_RATE_38400:
+ ao_radio_set_regs(packet_setup_384);
+ break;
+ case AO_RADIO_RATE_9600:
+ ao_radio_set_regs(packet_setup_96);
+ break;
+ case AO_RADIO_RATE_2400:
+ ao_radio_set_regs(packet_setup_24);
+ break;
+ }
+ }
+
+ if (changes & AO_RADIO_MODE_BITS_TX_BUF) {
+ ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR);
+ ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
+ }
+
+ if (changes & AO_RADIO_MODE_BITS_TX_FINISH) {
+ ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX);
+ ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH);
+ }
+
+ if (changes & AO_RADIO_MODE_BITS_RX) {
+ ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP);
+ ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH);
+ }
+
+ if (changes & AO_RADIO_MODE_BITS_RDF)
+ ao_radio_set_regs(rdf_setup);
+
+ if (changes & AO_RADIO_MODE_BITS_APRS)
+ ao_radio_set_regs(aprs_setup);
+
+ if (changes & AO_RADIO_MODE_BITS_TEST)
+ ao_radio_set_regs(test_setup);
+
+ if (changes & AO_RADIO_MODE_BITS_INFINITE)
+ ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE);
+
+ if (changes & AO_RADIO_MODE_BITS_FIXED)
+ ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED);
+
+ ao_radio_mode = new_mode;
+}
+
+static const uint16_t radio_setup[] = {
+#include "ao_cc1200_CC1200.h"
+};
+
+static uint8_t ao_radio_configured = 0;
+
+static void
+ao_radio_setup(void)
+{
+ ao_radio_strobe(CC1200_SRES);
+
+ ao_radio_set_regs(radio_setup);
+
+ ao_radio_mode = 0;
+
+ ao_radio_idle();
+
+ ao_config_get();
+
+ ao_radio_configured = 1;
+}
+
+static void
+ao_radio_set_len(uint8_t len)
+{
+ static uint8_t last_len;
+
+ if (len != last_len) {
+ ao_radio_reg_write(CC1200_PKT_LEN, len);
+ last_len = len;
+ }
+}
+
+static void
+ao_radio_get(uint8_t len)
+{
+ static uint32_t last_radio_setting;
+ static uint8_t last_radio_rate;
+
+ ao_mutex_get(&ao_radio_mutex);
+
+ if (!ao_radio_configured)
+ ao_radio_setup();
+ if (ao_config.radio_setting != last_radio_setting) {
+ ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16);
+ ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8);
+ ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting);
+ last_radio_setting = ao_config.radio_setting;
+ ao_radio_strobe(CC1200_SCAL);
+ }
+ if (ao_config.radio_rate != last_radio_rate) {
+ ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET;
+ last_radio_rate = ao_config.radio_rate;
+ }
+ ao_radio_set_len(len);
+}
+
+#define ao_radio_put() ao_mutex_put(&ao_radio_mutex)
+
+static inline uint8_t
+ao_radio_state(void)
+{
+ return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK;
+}
+
+#if CC1200_DEBUG
+void
+ao_radio_show_state(char *where)
+{
+ printf("%s: state %d len %d rxbytes %d\n",
+ where, ao_radio_state(),
+ ao_radio_reg_read(CC1200_PKT_LEN),
+ ao_radio_reg_read(CC1200_NUM_RXBYTES));
+}
+#else
+#define ao_radio_show_state(where)
+#endif
+
+/* Wait for the radio to signal an interrupt
+ */
+static void
+ao_radio_wait_isr(uint16_t timeout)
+{
+ if (timeout)
+ ao_alarm(timeout);
+
+ ao_arch_block_interrupts();
+ while (!ao_radio_wake && !ao_radio_abort)
+ if (ao_sleep(&ao_radio_wake))
+ ao_radio_abort = 1;
+ ao_arch_release_interrupts();
+
+ if (timeout)
+ ao_clear_alarm();
+}
+
+static void
+ao_rdf_start(uint8_t len)
+{
+ ao_radio_abort = 0;
+ ao_radio_get(len);
+
+ ao_radio_set_mode(AO_RADIO_MODE_RDF);
+ ao_radio_wake = 0;
+}
+
+static void
+ao_radio_run(void)
+{
+ ao_radio_wake = 0;
+ ao_radio_abort = 0;
+ ao_radio_start_tx();
+ ao_radio_wait_isr(0);
+ if (!ao_radio_wake)
+ ao_radio_idle();
+ ao_radio_put();
+}
+
+void
+ao_radio_rdf(void)
+{
+ ao_rdf_start(AO_RADIO_RDF_LEN);
+
+ ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN);
+
+ ao_radio_run();
+}
+
+void
+ao_radio_continuity(uint8_t c)
+{
+ uint8_t i;
+ uint8_t status;
+
+ ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN);
+
+ status = ao_radio_fifo_write_start();
+ for (i = 0; i < 3; i++) {
+ ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
+ if (i < c)
+ ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN);
+ else
+ ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN);
+ }
+ ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN);
+ status = ao_radio_fifo_write_stop(status);
+ (void) status;
+ ao_radio_run();
+}
+
+void
+ao_radio_rdf_abort(void)
+{
+ ao_radio_abort = 1;
+ ao_wakeup(&ao_radio_wake);
+}
+
+static void
+ao_radio_test_cmd(void)
+{
+ uint8_t mode = 2;
+ static uint8_t radio_on;
+ ao_cmd_white();
+ if (ao_cmd_lex_c != '\n') {
+ ao_cmd_decimal();
+ mode = (uint8_t) ao_cmd_lex_u32;
+ }
+ mode++;
+ if ((mode & 2) && !radio_on) {
+#if HAS_MONITOR
+ ao_monitor_disable();
+#endif
+#if PACKET_HAS_SLAVE
+ ao_packet_slave_stop();
+#endif
+ ao_radio_get(0xff);
+ ao_radio_set_mode(AO_RADIO_MODE_TEST);
+ ao_radio_strobe(CC1200_STX);
+#if CC1200_TRACE
+ { int t;
+ for (t = 0; t < 10; t++) {
+ printf ("status: %02x\n", ao_radio_status());
+ ao_delay(AO_MS_TO_TICKS(100));
+ }
+ }
+#endif
+ radio_on = 1;
+ }
+ if (mode == 3) {
+ printf ("Hit a character to stop..."); flush();
+ getchar();
+ putchar('\n');
+ }
+ if ((mode & 1) && radio_on) {
+ ao_radio_idle();
+ ao_radio_put();
+ radio_on = 0;
+#if HAS_MONITOR
+ ao_monitor_enable();
+#endif
+ }
+}
+
+void
+ao_radio_send(const void *d, uint8_t size)
+{
+ ao_radio_get(size);
+ ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX);
+
+ ao_radio_fifo_write(d, size);
+
+ ao_radio_run();
+}
+
+
+#define AO_RADIO_LOTS 64
+
+void
+ao_radio_send_aprs(ao_radio_fill_func fill)
+{
+ uint8_t buf[AO_RADIO_LOTS], *b;
+ int cnt;
+ int total = 0;
+ uint8_t done = 0;
+ uint8_t started = 0;
+ uint8_t fifo_space;
+
+ ao_radio_abort = 0;
+ ao_radio_get(0xff);
+ fifo_space = CC1200_FIFO_SIZE;
+ while (!done) {
+ cnt = (*fill)(buf, sizeof(buf));
+ if (cnt < 0) {
+ done = 1;
+ cnt = -cnt;
+ }
+#if CC1200_APRS_TRACE
+ printf("APRS fill %d bytes done %d\n", cnt, done);
+#endif
+ total += cnt;
+
+ /* At the last buffer, set the total length */
+ if (done)
+ ao_radio_set_len(total & 0xff);
+
+ b = buf;
+ while (cnt) {
+ uint8_t this_len = cnt;
+
+ /* Wait for some space in the fifo */
+ while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) {
+#if CC1200_APRS_TRACE
+ printf("APRS space %d cnt %d\n", fifo_space, cnt); flush();
+#endif
+ ao_radio_wake = 0;
+ ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
+ }
+ if (ao_radio_abort)
+ break;
+ if (this_len > fifo_space)
+ this_len = fifo_space;
+
+ cnt -= this_len;
+
+ if (done) {
+ if (cnt)
+ ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF);
+ else
+ ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH);
+ } else
+ ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF);
+
+ ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN);
+
+ ao_radio_fifo_write(b, this_len);
+ b += this_len;
+#if CC1200_APRS_TRACE
+ printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space());
+#endif
+ if (!started) {
+#if CC1200_APRS_TRACE
+ printf("APRS start\n");
+#endif
+ ao_radio_strobe(CC1200_STX);
+#if CC1200_APRS_TRACE
+ { int t;
+ for (t = 0; t < 20; t++) {
+ uint8_t status = ao_radio_status();
+ uint8_t space = ao_radio_tx_fifo_space();
+ printf ("status: %02x fifo %d\n", status, space);
+ if ((status >> 4) == 2)
+ break;
+ ao_delay(AO_MS_TO_TICKS(0));
+ }
+ }
+#endif
+ started = 1;
+ }
+ }
+ if (ao_radio_abort) {
+ ao_radio_idle();
+ break;
+ }
+ }
+ /* Wait for the transmitter to go idle */
+ ao_radio_wake = 0;
+#if CC1200_APRS_TRACE
+ printf("APRS wait idle\n"); flush();
+#endif
+ ao_radio_wait_isr(AO_MS_TO_TICKS(1000));
+#if CC1200_APRS_TRACE
+ printf("APRS abort %d\n", ao_radio_abort);
+#endif
+ ao_radio_put();
+}
+
+#if 0
+static uint8_t
+ao_radio_marc_state(void)
+{
+ return ao_radio_reg_read(CC1200_MARCSTATE);
+}
+
+static uint8_t
+ao_radio_modem_status1(void)
+{
+ return ao_radio_reg_read(CC1200_MODEM_STATUS1);
+}
+
+static uint8_t
+ao_radio_modem_status0(void)
+{
+ return ao_radio_reg_read(CC1200_MODEM_STATUS0);
+}
+
+struct ao_radio_state {
+ char where[4];
+ uint8_t marc_state;
+ uint8_t marc_status1;
+ uint8_t marc_status0;
+ uint8_t modem_status1;
+ uint8_t modem_status0;
+};
+
+static void
+ao_radio_fill_state(char *where, struct ao_radio_state *s)
+{
+ strcpy(s->where, where);
+ s->marc_state = ao_radio_marc_state();
+ s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
+ s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0);
+ s->modem_status1 = ao_radio_modem_status1();
+ s->modem_status0 = ao_radio_modem_status0();
+}
+
+static void
+ao_radio_dump_state(struct ao_radio_state *s)
+{
+ printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n",
+ s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0);
+}
+#endif
+
+uint8_t
+ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout)
+{
+ uint8_t success = 0;
+
+ ao_radio_abort = 0;
+ ao_radio_get(size - 2);
+ ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX);
+ ao_radio_wake = 0;
+ ao_radio_start_rx();
+
+ while (!ao_radio_abort) {
+ ao_radio_wait_isr(timeout);
+ if (ao_radio_wake) {
+ uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1);
+
+ /* Check the receiver status to see what happened
+ */
+ switch (marc_status1) {
+ case CC1200_MARC_STATUS1_RX_FINISHED:
+ case CC1200_MARC_STATUS1_ADDRESS:
+ case CC1200_MARC_STATUS1_CRC:
+ /* Normal return, go fetch the bytes from the FIFO
+ * and give them back to the caller
+ */
+ success = 1;
+ break;
+ case CC1200_MARC_STATUS1_RX_TIMEOUT:
+ case CC1200_MARC_STATUS1_RX_TERMINATION:
+ case CC1200_MARC_STATUS1_EWOR_SYNC_LOST:
+ case CC1200_MARC_STATUS1_MAXIMUM_LENGTH:
+ case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW:
+ case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW:
+ /* Something weird happened; reset the radio and
+ * return failure
+ */
+ success = 0;
+ break;
+ default:
+ /* some other status; go wait for the radio to do something useful
+ */
+ continue;
+ }
+ break;
+ } else {
+ uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1);
+
+ /* Check to see if the packet header has been seen, in which case we'll
+ * want to keep waiting for the rest of the packet to appear
+ */
+ if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND))
+ {
+ ao_radio_abort = 0;
+
+ /* Set a timeout based on the packet length so that we make sure to
+ * wait long enough to receive the whole thing.
+ *
+ * timeout = bits * FEC expansion / rate
+ */
+ switch (ao_config.radio_rate) {
+ default:
+ case AO_RADIO_RATE_38400:
+ timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1;
+ break;
+ case AO_RADIO_RATE_9600:
+ timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1;
+ break;
+ case AO_RADIO_RATE_2400:
+ timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (success) {
+ int8_t rssi;
+ uint8_t status;
+
+ status = ao_radio_fifo_read(d, size);
+ (void) status;
+ rssi = ((int8_t *) d)[size - 2];
+ ao_radio_rssi = rssi;
+
+ /* Bound it to the representable range */
+ if (rssi > -11)
+ rssi = -11;
+
+ /* Write it back to the packet */
+ ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi);
+ } else {
+ ao_radio_idle();
+ ao_radio_rssi = 0;
+ }
+
+ ao_radio_put();
+ return success;
+}
+
+
+#if CC1200_DEBUG
+static char *cc1200_state_name[] = {
+ [CC1200_STATUS_STATE_IDLE] = "IDLE",
+ [CC1200_STATUS_STATE_RX] = "RX",
+ [CC1200_STATUS_STATE_TX] = "TX",
+ [CC1200_STATUS_STATE_FSTXON] = "FSTXON",
+ [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE",
+ [CC1200_STATUS_STATE_SETTLING] = "SETTLING",
+ [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR",
+ [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR",
+};
+
+struct ao_cc1200_reg {
+ uint16_t addr;
+ char *name;
+};
+
+static const struct ao_cc1200_reg ao_cc1200_reg[] = {
+ { .addr = CC1200_IOCFG3, .name = "IOCFG3" },
+ { .addr = CC1200_IOCFG2, .name = "IOCFG2" },
+ { .addr = CC1200_IOCFG1, .name = "IOCFG1" },
+ { .addr = CC1200_IOCFG0, .name = "IOCFG0" },
+ { .addr = CC1200_SYNC3, .name = "SYNC3" },
+ { .addr = CC1200_SYNC2, .name = "SYNC2" },
+ { .addr = CC1200_SYNC1, .name = "SYNC1" },
+ { .addr = CC1200_SYNC0, .name = "SYNC0" },
+ { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" },
+ { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" },
+ { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" },
+ { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" },
+ { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" },
+ { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" },
+ { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" },
+ { .addr = CC1200_IQIC, .name = "IQIC" },
+ { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" },
+ { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" },
+ { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" },
+ { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" },
+ { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" },
+ { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" },
+ { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" },
+ { .addr = CC1200_AGC_REF, .name = "AGC_REF" },
+ { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" },
+ { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" },
+ { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" },
+ { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" },
+ { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" },
+ { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" },
+ { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" },
+ { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" },
+ { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" },
+ { .addr = CC1200_FS_CFG, .name = "FS_CFG" },
+ { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" },
+ { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" },
+ { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" },
+ { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" },
+ { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" },
+ { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" },
+ { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" },
+ { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" },
+ { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" },
+ { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" },
+ { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" },
+ { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" },
+ { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" },
+ { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" },
+ { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" },
+ { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" },
+ { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" },
+ { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" },
+ { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" },
+ { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" },
+ { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" },
+ { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" },
+ { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" },
+ { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" },
+ { .addr = CC1200_FREQ2, .name = "FREQ2" },
+ { .addr = CC1200_FREQ1, .name = "FREQ1" },
+ { .addr = CC1200_FREQ0, .name = "FREQ0" },
+ { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" },
+ { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" },
+ { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" },
+ { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" },
+ { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" },
+ { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" },
+ { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" },
+ { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" },
+ { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" },
+ { .addr = CC1200_FS_CHP, .name = "FS_CHP" },
+ { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" },
+ { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" },
+ { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" },
+ { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" },
+ { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" },
+ { .addr = CC1200_FS_LBI, .name = "FS_LBI" },
+ { .addr = CC1200_FS_PFD, .name = "FS_PFD" },
+ { .addr = CC1200_FS_PRE, .name = "FS_PRE" },
+ { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" },
+ { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" },
+ { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" },
+ { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" },
+ { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" },
+ { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" },
+ { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" },
+ { .addr = CC1200_GBIAS6, .name = "GBIAS6" },
+ { .addr = CC1200_GBIAS5, .name = "GBIAS5" },
+ { .addr = CC1200_GBIAS4, .name = "GBIAS4" },
+ { .addr = CC1200_GBIAS3, .name = "GBIAS3" },
+ { .addr = CC1200_GBIAS2, .name = "GBIAS2" },
+ { .addr = CC1200_GBIAS1, .name = "GBIAS1" },
+ { .addr = CC1200_GBIAS0, .name = "GBIAS0" },
+ { .addr = CC1200_IFAMP, .name = "IFAMP" },
+ { .addr = CC1200_LNA, .name = "LNA" },
+ { .addr = CC1200_RXMIX, .name = "RXMIX" },
+ { .addr = CC1200_XOSC5, .name = "XOSC5" },
+ { .addr = CC1200_XOSC4, .name = "XOSC4" },
+ { .addr = CC1200_XOSC3, .name = "XOSC3" },
+ { .addr = CC1200_XOSC2, .name = "XOSC2" },
+ { .addr = CC1200_XOSC1, .name = "XOSC1" },
+ { .addr = CC1200_XOSC0, .name = "XOSC0" },
+ { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" },
+ { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" },
+ { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" },
+ { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" },
+ { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" },
+ { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" },
+ { .addr = CC1200_BIST, .name = "BIST" },
+ { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" },
+ { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" },
+ { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" },
+ { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" },
+ { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" },
+ { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" },
+ { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" },
+ { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" },
+ { .addr = CC1200_RSSI1, .name = "RSSI1" },
+ { .addr = CC1200_RSSI0, .name = "RSSI0" },
+ { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" },
+ { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" },
+ { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" },
+ { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" },
+ { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" },
+ { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" },
+ { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" },
+ { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" },
+ { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" },
+ { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" },
+ { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" },
+ { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" },
+ { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" },
+ { .addr = CC1200_RNDGEN, .name = "RNDGEN" },
+ { .addr = CC1200_MAGN2, .name = "MAGN2" },
+ { .addr = CC1200_MAGN1, .name = "MAGN1" },
+ { .addr = CC1200_MAGN0, .name = "MAGN0" },
+ { .addr = CC1200_ANG1, .name = "ANG1" },
+ { .addr = CC1200_ANG0, .name = "ANG0" },
+ { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" },
+ { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" },
+ { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" },
+ { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" },
+ { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" },
+ { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" },
+ { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" },
+ { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" },
+ { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" },
+ { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" },
+ { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" },
+ { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" },
+ { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" },
+ { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" },
+ { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" },
+ { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" },
+ { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" },
+ { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" },
+ { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" },
+ { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" },
+ { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" },
+ { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" },
+ { .addr = CC1200_ATEST, .name = "ATEST" },
+ { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" },
+ { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" },
+ { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" },
+ { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" },
+ { .addr = CC1200_RXFIRST, .name = "RXFIRST" },
+ { .addr = CC1200_TXFIRST, .name = "TXFIRST" },
+ { .addr = CC1200_RXLAST, .name = "RXLAST" },
+ { .addr = CC1200_TXLAST, .name = "TXLAST" },
+ { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" },
+ { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" },
+ { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" },
+ { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" },
+};
+
+#define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0])
+
+static uint8_t
+ao_radio_get_marc_status(void)
+{
+ return ao_radio_reg_read(CC1200_MARC_STATUS1);
+}
+
+static void ao_radio_show(void) {
+ uint8_t status;
+ unsigned int i;
+
+ ao_mutex_get(&ao_radio_mutex);
+ status = ao_radio_status();
+ printf ("Status: %02x\n", status);
+ printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1);
+ printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]);
+ printf ("MARC: %02x\n", ao_radio_get_marc_status());
+
+ for (i = 0; i < AO_NUM_CC1200_REG; i++)
+ printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name);
+
+ ao_radio_put();
+}
+
+static void ao_radio_beep(void) {
+ ao_radio_rdf();
+}
+
+static void ao_radio_packet(void) {
+ static const uint8_t packet[] = {
+#if 1
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+#else
+ 3, 1, 2, 3
+#endif
+ };
+
+ ao_radio_send(packet, sizeof (packet));
+}
+
+void
+ao_radio_test_recv(void)
+{
+ uint8_t bytes[34];
+ uint8_t b;
+
+ if (ao_radio_recv(bytes, 34, 0)) {
+ if (bytes[33] & 0x80)
+ printf ("CRC OK");
+ else
+ printf ("CRC BAD");
+ printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32]));
+ for (b = 0; b < 32; b++)
+ printf (" %02x", bytes[b]);
+
+ printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]);
+ printf ("\n");
+ }
+}
+
+#if HAS_APRS
+#include <ao_aprs.h>
+
+static void
+ao_radio_aprs(void)
+{
+#if PACKET_HAS_SLAVE
+ ao_packet_slave_stop();
+#endif
+ ao_aprs_send();
+}
+#endif
+#endif
+
+#if CC1200_LOW_LEVEL_DEBUG
+static void
+ao_radio_strobe_test(void)
+{
+ uint8_t r;
+
+ ao_cmd_hex();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ r = ao_radio_strobe(ao_cmd_lex_i);
+ printf ("Strobe %02x -> %02x (rdy %d state %d)\n",
+ ao_cmd_lex_i,
+ r,
+ r >> 7,
+ (r >> 4) & 0x7);
+}
+
+static void
+ao_radio_write_test(void)
+{
+ uint16_t addr;
+ uint8_t data;
+
+ ao_cmd_hex();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ addr = ao_cmd_lex_i;
+ ao_cmd_hex();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ data = ao_cmd_lex_i;
+ printf ("Write %04x = %02x\n", addr, data);
+ ao_radio_reg_write(addr, data);
+}
+
+static void
+ao_radio_read_test(void)
+{
+ uint16_t addr;
+ uint8_t data;
+
+ ao_cmd_hex();
+ if (ao_cmd_status != ao_cmd_success)
+ return;
+ addr = ao_cmd_lex_i;
+ data = ao_radio_reg_read(addr);
+ printf ("Read %04x = %02x\n", addr, data);
+}
+#endif
+
+static const struct ao_cmds ao_radio_cmds[] = {
+ { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" },
+#if CC1200_DEBUG
+#if HAS_APRS
+ { ao_radio_aprs, "G\0Send APRS packet" },
+#endif
+ { ao_radio_show, "R\0Show CC1200 status" },
+ { ao_radio_beep, "b\0Emit an RDF beacon" },
+ { ao_radio_packet, "p\0Send a test packet" },
+ { ao_radio_test_recv, "q\0Recv a test packet" },
+#endif
+#if CC1200_LOW_LEVEL_DEBUG
+ { ao_radio_strobe_test, "A <value>\0Strobe radio" },
+ { ao_radio_write_test, "W <addr> <value>\0Write radio reg" },
+ { ao_radio_read_test, "B <addr>\0Read radio reg" },
+#endif
+ { 0, NULL }
+};
+
+void
+ao_radio_init(void)
+{
+ ao_radio_configured = 0;
+ ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN));
+
+#if 0
+ AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN));
+ for (i = 0; i < 10000; i++) {
+ if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0)
+ break;
+ }
+ AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN);
+ if (i == 10000)
+ ao_panic(AO_PANIC_SELF_TEST_CC1200);
+#endif
+
+ /* Enable the EXTI interrupt for the appropriate pin */
+ ao_enable_port(AO_CC1200_INT_PORT);
+ ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN,
+ AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH,
+ ao_radio_isr);
+
+ ao_cmd_register(&ao_radio_cmds[0]);
+}
--- /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_CC1200_H_
+#define _AO_CC1200_H_
+
+#define CC1200_READ (7)
+#define CC1200_BURST (6)
+
+/* Register space */
+#define CC1200_IOCFG3 0x00
+#define CC1200_IOCFG_GPIO_ATRAN 7
+#define CC1200_IOCFG_GPIO_INV 6
+#define CC1200_IOCFG_GPIO_CFG 0
+#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR 0
+#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1
+#define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR 2
+#define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR_PKT 3
+#define CC1200_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4
+#define CC1200_IOCFG_GPIO_CFG_TXFIFO_UNDERFLOW 5
+#define CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX 6
+#define CC1200_IOCFG_GPIO_CFG_CRC_OK 7
+#define CC1200_IOCFG_GPIO_CFG_SERIAL_CLK 8
+#define CC1200_IOCFG_GPIO_CFG_SERIAL_RX 9
+#define CC1200_IOCFG_GPIO_CFG_PQT_REACHED 11
+#define CC1200_IOCFG_GPIO_CFG_PQT_VALID 12
+#define CC1200_IOCFG_GPIO_CFG_RSSI_VALID 13
+#define CC1200_IOCFG_GPIO3_CFG_RSSI_UPDATE 14
+#define CC1200_IOCFG_GPIO2_CFG_RSSI_UPDATE 14
+#define CC1200_IOCFG_GPIO1_CFG_AGC_HOLD 14
+#define CC1200_IOCFG_GPIO0_CFG_AGC_UPDATE 14
+#define CC1200_IOCFG_GPIO3_CFG_CGA_STATUS 15
+#define CC1200_IOCFG_GPIO2_CFG_TXONCCA_DONE 15
+#define CC1200_IOCFG_GPIO1_CFG_CCA_STATUS 15
+#define CC1200_IOCFG_GPIO0_CFG_TXONCCA_FAILED 15
+#define CC1200_IOCFG_GPIO_CFG_CARRIER_SENSE_VALID 16
+#define CC1200_IOCFG_GPIO_CFG_CARRIER_SENSE 17
+#define CC1200_IOCFG_GPIO3_CFG_DSSS_CLK 18
+#define CC1200_IOCFG_GPIO2_CFG_DSSS_DATA0 18
+#define CC1200_IOCFG_GPIO1_CFG_DSSS_CLK 18
+#define CC1200_IOCFG_GPIO0_CFG_DSSS_DATA1 18
+#define CC1200_IOCFG_GPIO_CFG_PKT_CRC_OK 19
+#define CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP 20
+#define CC1200_IOCFG_GPIO_CFG_SYNC_LOW0_HIGH1 21
+#define CC1200_IOCFG_GPIO_CFG_LNA_PA_REG_PD 23
+#define CC1200_IOCFG_GPIO_CFG_LNA_PD 24
+#define CC1200_IOCFG_GPIO_CFG_PA_RD 25
+#define CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG 26
+#define CC1200_IOCFG_GPIO_CFG_IMAGE_FOUND 28
+#define CC1200_IOCFG_GPIO_CFG_CLKEN_SOFT 29
+#define CC1200_IOCFG_GPIO_CFG_SOFT_TX_DATA_CLK 30
+#define CC1200_IOCFG_GPIO_CFG_RSSI_STEP_FOUND 33
+#define CC1200_IOCFG_GPIO_CFG_RSSI_STEP_EVENT 34
+#define CC1200_IOCFG_GPIO_CFG_ANTENNA_SELECT 36
+#define CC1200_IOCFG_GPIO_CFG_MARC_2PIN_STATUS1 37
+#define CC1200_IOCFG_GPIO_CFG_MARC_2PIN_STATUS0 38
+#define CC1200_IOCFG_GPIO2_CFG_TXFIFO_OVERFLOW 39
+#define CC1200_IOCFG_GPIO0_CFG_RXFIFO_UNDERFLOW 39
+#define CC1200_IOCFG_GPIO3_CFG_MAGN_VALID 40
+#define CC1200_IOCFG_GPIO2_CFG_CHFILT_VALID 40
+#define CC1200_IOCFG_GPIO1_CFG_RCC_CAL_VALID 40
+#define CC1200_IOCFG_GPIO0_CFG_CHFILTER_STARTUP_VALID 40
+#define CC1200_IOCFG_GPIO3_CFG_COLLISION_FOUND 41
+#define CC1200_IOCFG_GPIO2_CFG_SYNC_EVENT 41
+#define CC1200_IOCFG_GPIO1_CFG_COLLISION_FOUND 41
+#define CC1200_IOCFG_GPIO0_CFG_COLLISION_EVENT 41
+#define CC1200_IOCFG_GPIO_CFG_PA_RAMP_UP 42
+#define CC1200_IOCFG_GPIO3_CFG_CRC_FAILED 43
+#define CC1200_IOCFG_GPIO2_CFG_LENGTH_FAILED 43
+#define CC1200_IOCFG_GPIO1_CFG_ADDR_FAILED 43
+#define CC1200_IOCFG_GPIO0_CFG_UART_FRAMING_ERROR 43
+#define CC1200_IOCFG_GPIO_CFG_AGC_STABLE_GAIN 44
+#define CC1200_IOCFG_GPIO_CFG_AGC_UPDATE 45
+#define CC1200_IOCFG_GPIO3_CFG_ADC_CLOCK 46
+#define CC1200_IOCFG_GPIO2_CFG_ADC_Q_DATA_SAMPLE 46
+#define CC1200_IOCFG_GPIO1_CFG_ADC_CLOCK 46
+#define CC1200_IOCFG_GPIO0_CFG_ADC_I_DATA_SAMPLE 46
+#define CC1200_IOCFG_GPIO_CFG_HIGHZ 48
+#define CC1200_IOCFG_GPIO_CFG_EXT_CLOCK 49
+#define CC1200_IOCFG_GPIO_CFG_CHIP_RDY 50
+#define CC1200_IOCFG_GPIO_CFG_HW0 51
+#define CC1200_IOCFG_GPIO_CFG_CLOCK_32K 54
+#define CC1200_IOCFG_GPIO_CFG_WOR_EVENT0 55
+#define CC1200_IOCFG_GPIO_CFG_WOR_EVENT1 56
+#define CC1200_IOCFG_GPIO_CFG_WOR_EVENT2 57
+#define CC1200_IOCFG_GPIO_CFG_XOSC_STABLE 59
+#define CC1200_IOCFG_GPIO_CFG_EXT_OSC_EN 60
+#define CC1200_IOCFG_GPIO_CFG_MASK 0x3f
+
+#define CC1200_IOCFG2 0x01
+#define CC1200_IOCFG1 0x02
+#define CC1200_IOCFG0 0x03
+#define CC1200_SYNC3 0x04
+#define CC1200_SYNC2 0x05
+#define CC1200_SYNC1 0x06
+#define CC1200_SYNC0 0x07
+
+#define CC1200_SYNC_CFG1 0x08
+
+#define CC1200_SYNC_CFG1_SYNC_MODE 5
+#define CC1200_SYNC_CFG1_SYNC_MODE_NONE 0
+#define CC1200_SYNC_CFG1_SYNC_MODE_11_BITS 1
+#define CC1200_SYNC_CFG1_SYNC_MODE_16_BITS 2
+#define CC1200_SYNC_CFG1_SYNC_MODE_18_BITS 3
+#define CC1200_SYNC_CFG1_SYNC_MODE_24_BITS 4
+#define CC1200_SYNC_CFG1_SYNC_MODE_32_BITS 5
+#define CC1200_SYNC_CFG1_SYNC_MODE_16H_BITS 6
+#define CC1200_SYNC_CFG1_SYNC_MODE_16D_BITS 7
+#define CC1200_SYNC_CFG1_SYNC_MODE_MASK 7
+
+#define CC1200_SYNC_CFG1_SYNC_THR 0
+#define CC1200_SYNC_CFG1_SYNC_MASK 0x1f
+
+#define CC1200_SYNC_CFG0 0x09
+#define CC1200_SYNC_CFG0_AUTO_CLEAR 5
+#define CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION 4
+#define CC1200_SYNC_CFG0_PQT_GATING_EN 3
+#define CC1200_SYNC_CFG0_EXT_SYNC_DETECT 2
+
+#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK 0
+#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_1 0
+#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_2 1
+#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_3 2
+#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_DISABLED 3
+#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_MASK 3
+
+#define CC1200_DEVIATION_M 0x0a
+#define CC1200_MODCFG_DEV_E 0x0b
+#define CC1200_MODCFG_DEV_E_MODEM_MODE 6
+#define CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL 0
+#define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_REPEAT 1
+#define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_PN 2
+#define CC1200_MODCFG_DEV_E_MODEM_MODE_CARRIER_SENSE 3
+#define CC1200_MODCFG_DEV_E_MODEM_MODE_MASK 3
+#define CC1200_MODCFG_DEV_E_MOD_FORMAT 3
+#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0
+#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1
+#define CC1200_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3
+#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4
+#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5
+#define CC1200_MODCFG_DEV_E_MOD_FORMAT_MASK 7
+#define CC1200_MODCFG_DEV_E_DEV_E 0
+#define CC1200_MODCFG_DEV_E_DEV_E_MASK 7
+
+#define CC1200_DCFILT_CFG 0x0c
+#define CC1200_PREAMBLE_CFG1 0x0d
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE 2
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE 0
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_0_5_BYTE 1
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_1_BYTE 2
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_1_5_BYTE 3
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_2_BYTES 4
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_3_BYTES 5
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES 6
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_5_BYTES 7
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_6_BYTES 8
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_7_BYTES 9
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_8_BYTES 10
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_12_BYTES 11
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_24_BYTES 12
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_30_BYTES 13
+#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_MASK 0xf
+
+#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD 0
+#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA 0
+#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_55 1
+#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_33 2
+#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_CC 3
+#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_MASK 3
+
+#define CC1200_PREAMBLE_CFG0 0x0e
+#define CC1200_PREAMBLE_CFG0_PQT_EN 7
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT 4
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 0
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_12 1
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_13 2
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_15 3
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_16 4
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_17 5
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_24 6
+#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_32 7
+#define CC1200_PREAMBLE_CFG0_PQT 0
+#define CC1200_PREAMBLE_CFG0_PQT_MASK 0xf
+
+#define CC1200_IQIC 0x0f
+#define CC1200_CHAN_BW 0x10
+#define CC1200_CHAN_BW_ADC_CIC_DECFACT 6
+#define CC1200_CHAN_BW_ADC_CIC_DECFACT_12 0
+#define CC1200_CHAN_BW_ADC_CIC_DECFACT_24 1
+#define CC1200_CHAN_BW_ADC_CIC_DECFACT_48 2
+#define CC1200_CHAN_BW_BB_CIC_DECFACT 0
+
+#define CC1200_MDMCFG1 0x11
+#define CC1200_MDMCFG1_CARRIER_SENSE_GATE 7
+#define CC1200_MDMCFG1_FIFO_EN 6
+#define CC1200_MDMCFG1_MANCHESTER_EN 5
+#define CC1200_MDMCFG1_INVERT_DATA_EN 4
+#define CC1200_MDMCFG1_COLLISION_DETECT_EN 3
+#define CC1200_MDMCFG1_DVGA_GAIN 1
+#define CC1200_MDMCFG1_DVGA_GAIN_0 0
+#define CC1200_MDMCFG1_DVGA_GAIN_3 1
+#define CC1200_MDMCFG1_DVGA_GAIN_6 2
+#define CC1200_MDMCFG1_DVGA_GAIN_9 3
+#define CC1200_MDMCFG1_DVGA_GAIN_MASK 3
+#define CC1200_MDMCFG1_SINGLE_ADC_EN 0
+
+#define CC1200_MDMCFG0 0x12
+#define CC1200_MDMCFG0_TRANSPARENT_MODE_EN 6
+#define CC1200_MDMCFG0_TRANSPARENT_INTFACT 4
+#define CC1200_MDMCFG0_DATA_FILTER_EN 3
+#define CC1200_MDMCFG0_VITERBI_EN 2
+
+#define CC1200_SYMBOL_RATE2 0x13
+#define CC1200_SYMBOL_RATE2_DATARATE_E 4
+#define CC1200_SYMBOL_RATE2_DATARATE_E_MASK 0xf
+#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16 0
+#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK 0xf
+
+#define CC1200_SYMBOL_RATE1 0x14
+#define CC1200_SYMBOL_RATE0 0x15
+#define CC1200_AGC_REF 0x16
+#define CC1200_AGC_CS_THR 0x17
+#define CC1200_AGC_GAIN_ADJUST 0x18
+
+#define CC1200_AGC_CFG3 0x19
+#define CC1200_AGC_CFG3_RSSI_STEP_THR 7
+#define CC1200_AGC_CFG3_AGC_MIN_GAIN 0
+#define CC1200_AGC_CFG3_AGC_MIN_GAIN_MASK 0x1f
+
+#define CC1200_AGC_CFG2 0x1a
+#define CC1200_AGC_CFG2_START_PREVIOUS_GAIN_EN 7
+#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE 5
+#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_OPTIMIZE_LINEARITY 0
+#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_NORMAL 1
+#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_LOW_POWER 2
+#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_MASK 3
+#define CC1200_AGC_CFG2_AGC_MAX_GAIN 0
+#define CC1200_AGC_CFG2_AGC_MAX_MASK 0x1f
+
+#define CC1200_AGC_CFG1 0x1b
+#define CC1200_AGC_CFG1_RSSI_STEP_THR 6
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE 3
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE_8 0
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE_16 1
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE_32 2
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE_64 3
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE_128 4
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE_256 5
+#define CC1200_AGC_CFG1_AGC_WIN_SIZE_MASK 7
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT 0
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_24 0
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_32 1
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_40 2
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_48 3
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_64 4
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_80 5
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_96 6
+#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_127 7
+
+#define CC1200_AGC_CFG0 0x1c
+
+#define CC1200_AGC_CFG0_AGC_HYST_LEVEL 6
+#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_2 0
+#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_4 1
+#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_7 2
+#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_10 3
+
+#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT 4
+#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_60 0
+#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_30 1
+#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_18 2
+#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_9 3
+
+#define CC1200_AGC_CFG0_RSSI_VALID_CNT 2
+#define CC1200_AGC_CFG0_RSSI_VALID_CNT_2 0
+#define CC1200_AGC_CFG0_RSSI_VALID_CNT_3 1
+#define CC1200_AGC_CFG0_RSSI_VALID_CNT_5 2
+#define CC1200_AGC_CFG0_RSSI_VALID_CNT_9 3
+
+#define CC1200_AGC_CFG0_AGC_ASK_DECAY 0
+#define CC1200_AGC_CFG0_AGC_ASK_DECAY_1200 0
+#define CC1200_AGC_CFG0_AGC_ASK_DECAY_2400 1
+#define CC1200_AGC_CFG0_AGC_ASK_DECAY_4700 2
+#define CC1200_AGC_CFG0_AGC_ASK_DECAY_9500 3
+
+#define CC1200_FIFO_CFG 0x1d
+#define CC1200_FIFO_CFG_CRC_AUTOFLUSH 7
+#define CC1200_FIFO_CFG_FIFO_THR 0
+
+#define CC1200_DEV_ADDR 0x1e
+#define CC1200_SETTLING_CFG 0x1f
+#define CC1200_SETTLING_CFG_FS_AUTOCAL 3
+#define CC1200_SETTLING_CFG_FS_AUTOCAL_NEVER 0
+#define CC1200_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON 1
+#define CC1200_SETTLING_CFG_FS_AUTOCAL_ON_TO_IDLE 2
+#define CC1200_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME 3
+#define CC1200_SETTLING_CFG_FS_AUTOCAL_MASK 3
+#define CC1200_SETTLING_CFG_LOCK_TIME 1
+#define CC1200_SETTLING_CFG_LOCK_TIME_50_20 0
+#define CC1200_SETTLING_CFG_LOCK_TIME_75_30 1
+#define CC1200_SETTLING_CFG_LOCK_TIME_100_40 2
+#define CC1200_SETTLING_CFG_LOCK_TIME_150_60 3
+#define CC1200_SETTLING_CFG_LOCK_TIME_MASK 3
+#define CC1200_SETTLING_CFG_FSREG_TIME 0
+#define CC1200_SETTLING_CFG_FSREG_TIME_30 0
+#define CC1200_SETTLING_CFG_FSREG_TIME_60 1
+#define CC1200_SETTLING_CFG_FSREG_TIME_MASK 1
+
+#define CC1200_FS_CFG 0x20
+#define CC1200_FS_CFG_LOCK_EN 4
+#define CC1200_FS_CFG_FSD_BANDSELECT 0
+#define CC1200_FS_CFG_FSD_BANDSELECT_820_960 2
+#define CC1200_FS_CFG_FSD_BANDSELECT_410_480 4
+#define CC1200_FS_CFG_FSD_BANDSELECT_273_320 6
+#define CC1200_FS_CFG_FSD_BANDSELECT_205_240 8
+#define CC1200_FS_CFG_FSD_BANDSELECT_164_192 10
+#define CC1200_FS_CFG_FSD_BANDSELECT_136_160 11
+#define CC1200_FS_CFG_FSD_BANDSELECT_MASK 0xf
+
+#define CC1200_WOR_CFG1 0x21
+#define CC1200_WOR_CFG0 0x22
+#define CC1200_WOR_EVENT0_MSB 0x23
+#define CC1200_WOR_EVENT0_LSB 0x24
+#define CC1200_RXDCM_TIME 0x25
+#define CC1200_PKT_CFG2 0x26
+#define CC1200_PKT_CFG2_BYTE_SWAP_EN 6
+#define CC1200_PKT_CFG2_FG_MODE_EN 5
+#define CC1200_PKT_CFG2_CCA_MODE 2
+#define CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR 0
+#define CC1200_PKT_CFG2_CCA_MODE_RSSI_THRESHOLD 1
+#define CC1200_PKT_CFG2_CCA_MODE_NOT_RECEIVING 2
+#define CC1200_PKT_CFG2_CCA_MODE_RSSI_OR_NOT 3
+#define CC1200_PKT_CFG2_CCA_MODE_RSSI_AND_ETSI_LBT 4
+#define CC1200_PKT_CFG2_CCA_MODE_MASK 7
+#define CC1200_PKT_CFG2_PKT_FORMAT 0
+#define CC1200_PKT_CFG2_PKT_FORMAT_NORMAL 0
+#define CC1200_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL 1
+#define CC1200_PKT_CFG2_PKT_FORMAT_RANDOM 2
+#define CC1200_PKT_CFG2_PKT_FORMAT_TRANSPARENT_SERIAL 3
+#define CC1200_PKT_CFG2_PKT_FORMAT_MASK 3
+
+#define CC1200_PKT_CFG1 0x27
+#define CC1200_PKT_CFG1_FEC_EN 7
+#define CC1200_PKT_CFG1_WHITE_DATA 6
+#define CC1200_PKT_CFG1_PN9_SWAP_EN 5
+#define CC1200_PKT_CFG1_ADDR_CHECK_CFG 3
+#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE 0
+#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_CHECK 1
+#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_BROADCAST 2
+#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_FF_BROADCAST 3
+#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_MASK 3
+#define CC1200_PKT_CFG1_CRC_CFG 1
+#define CC1200_PKT_CFG1_CRC_CFG_DISABLED 0
+#define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES 1
+#define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ZEROS 2
+#define CC1200_PKT_CFG1_CRC_CFG_MASK 3
+#define CC1200_PKT_CFG1_APPEND_STATUS 0
+
+#define CC1200_PKT_CFG0 0x28
+#define CC1200_PKT_CFG0_RESERVED7 7
+#define CC1200_PKT_CFG0_LENGTH_CONFIG 5
+#define CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED 0
+#define CC1200_PKT_CFG0_LENGTH_CONFIG_VARIABLE 1
+#define CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE 2
+#define CC1200_PKT_CFG0_LENGTH_CONFIG_VARIABLE_5LSB 3
+#define CC1200_PKT_CFG0_LENGTH_CONFIG_MASK 3
+#define CC1200_PKT_CFG0_PKG_BIT_LEN 2
+#define CC1200_PKT_CFG0_PKG_BIT_LEN_MASK 7
+#define CC1200_PKT_CFG0_UART_MODE_EN 1
+#define CC1200_PKT_CFG0_UART_SWAP_EN 0
+
+#define CC1200_RFEND_CFG1 0x29
+#define CC1200_RFEND_CFG1_RXOFF_MODE 4
+#define CC1200_RFEND_CFG1_RXOFF_MODE_IDLE 0
+#define CC1200_RFEND_CFG1_RXOFF_MODE_FSTXON 1
+#define CC1200_RFEND_CFG1_RXOFF_MODE_TX 2
+#define CC1200_RFEND_CFG1_RXOFF_MODE_RX 3
+#define CC1200_RFEND_CFG1_RX_TIME 1
+#define CC1200_RFEND_CFG1_RX_TIME_INFINITE 7
+#define CC1200_RFEND_CFG1_RX_TIME_QUAL 0
+#define CC1200_RFEND_CFG0 0x2a
+#define CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN 6
+#define CC1200_RFEND_CFG0_TXOFF_MODE 4
+#define CC1200_RFEND_CFG0_TXOFF_MODE_IDLE 0
+#define CC1200_RFEND_CFG0_TXOFF_MODE_FSTXON 1
+#define CC1200_RFEND_CFG0_TXOFF_MODE_TX 2
+#define CC1200_RFEND_CFG0_TXOFF_MODE_RX 3
+#define CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN 3
+#define CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG 0
+#define CC1200_PA_CFG1 0x2b
+#define CC1200_PA_CFG0 0x2c
+#define CC1200_ASK_CFG 0x2d
+#define CC1200_PKT_LEN 0x2e
+
+#define CC1200_EXTENDED 0x2f
+
+/* Command strobes */
+#define CC1200_SRES 0x30
+#define CC1200_SFSTXON 0x31
+#define CC1200_SXOFF 0x32
+#define CC1200_SCAL 0x33
+#define CC1200_SRX 0x34
+#define CC1200_STX 0x35
+#define CC1200_SIDLE 0x36
+#define CC1200_SAFC 0x37
+#define CC1200_SWOR 0x38
+#define CC1200_SPWD 0x39
+#define CC1200_SFRX 0x3a
+#define CC1200_SFTX 0x3b
+#define CC1200_SWORRST 0x3c
+#define CC1200_SNOP 0x3d
+
+#define CC1200_DIRECT_FIFO 0x3e
+#define CC1200_FIFO 0x3f
+
+#define CC1200_FIFO_SIZE 128
+
+/* Extended register space */
+
+#define CC1200_EXTENDED_BIT 0x8000
+
+#define CC1200_IS_EXTENDED(r) ((r) & CC1200_EXTENDED_BIT)
+
+#define CC1200_IF_MIX_CFG (CC1200_EXTENDED_BIT | 0x00)
+#define CC1200_FREQOFF_CFG (CC1200_EXTENDED_BIT | 0x01)
+#define CC1200_TOC_CFG (CC1200_EXTENDED_BIT | 0x02)
+#define CC1200_MARC_SPARE (CC1200_EXTENDED_BIT | 0x03)
+#define CC1200_ECG_CFG (CC1200_EXTENDED_BIT | 0x04)
+#define CC1200_MDMCFG2 (CC1200_EXTENDED_BIT | 0x05)
+
+#define CC1200_MDMCFG2_ASK_SHAPE 6
+#define CC1200_MDMCFG2_ASK_SHAPE_8 0
+#define CC1200_MDMCFG2_ASK_SHAPE_16 1
+#define CC1200_MDMCFG2_ASK_SHAPE_32 2
+#define CC1200_MDMCFG2_ASK_SHAPE_128 3
+#define CC1200_MDMCFG2_SYMBOL_MAP_CFG 4
+#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 0
+#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_1 1
+#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_2 2
+#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_3 3
+#define CC1200_MDMCFG2_UPSAMPLER_P 1
+#define CC1200_MDMCFG2_UPSAMPLER_P_1 0
+#define CC1200_MDMCFG2_UPSAMPLER_P_2 1
+#define CC1200_MDMCFG2_UPSAMPLER_P_4 2
+#define CC1200_MDMCFG2_UPSAMPLER_P_8 3
+#define CC1200_MDMCFG2_UPSAMPLER_P_16 4
+#define CC1200_MDMCFG2_UPSAMPLER_P_32 5
+#define CC1200_MDMCFG2_UPSAMPLER_P_64 6
+#define CC1200_MDMCFG2_CFM_DATA_EN 0
+
+#define CC1200_EXT_CTRL (CC1200_EXTENDED_BIT | 0x06)
+#define CC1200_RCCAL_FINE (CC1200_EXTENDED_BIT | 0x07)
+#define CC1200_RCCAL_COARSE (CC1200_EXTENDED_BIT | 0x08)
+#define CC1200_RCCAL_OFFSET (CC1200_EXTENDED_BIT | 0x09)
+#define CC1200_FREQOFF1 (CC1200_EXTENDED_BIT | 0x0A)
+#define CC1200_FREQOFF0 (CC1200_EXTENDED_BIT | 0x0B)
+#define CC1200_FREQ2 (CC1200_EXTENDED_BIT | 0x0C)
+#define CC1200_FREQ1 (CC1200_EXTENDED_BIT | 0x0D)
+#define CC1200_FREQ0 (CC1200_EXTENDED_BIT | 0x0E)
+#define CC1200_IF_ADC2 (CC1200_EXTENDED_BIT | 0x0F)
+#define CC1200_IF_ADC1 (CC1200_EXTENDED_BIT | 0x10)
+#define CC1200_IF_ADC0 (CC1200_EXTENDED_BIT | 0x11)
+#define CC1200_FS_DIG1 (CC1200_EXTENDED_BIT | 0x12)
+#define CC1200_FS_DIG0 (CC1200_EXTENDED_BIT | 0x13)
+#define CC1200_FS_CAL3 (CC1200_EXTENDED_BIT | 0x14)
+#define CC1200_FS_CAL2 (CC1200_EXTENDED_BIT | 0x15)
+#define CC1200_FS_CAL1 (CC1200_EXTENDED_BIT | 0x16)
+#define CC1200_FS_CAL0 (CC1200_EXTENDED_BIT | 0x17)
+#define CC1200_FS_CHP (CC1200_EXTENDED_BIT | 0x18)
+#define CC1200_FS_DIVTWO (CC1200_EXTENDED_BIT | 0x19)
+#define CC1200_FS_DSM1 (CC1200_EXTENDED_BIT | 0x1A)
+#define CC1200_FS_DSM0 (CC1200_EXTENDED_BIT | 0x1B)
+#define CC1200_FS_DVC1 (CC1200_EXTENDED_BIT | 0x1C)
+#define CC1200_FS_DVC0 (CC1200_EXTENDED_BIT | 0x1D)
+#define CC1200_FS_LBI (CC1200_EXTENDED_BIT | 0x1E)
+#define CC1200_FS_PFD (CC1200_EXTENDED_BIT | 0x1F)
+#define CC1200_FS_PRE (CC1200_EXTENDED_BIT | 0x20)
+#define CC1200_FS_REG_DIV_CML (CC1200_EXTENDED_BIT | 0x21)
+#define CC1200_FS_SPARE (CC1200_EXTENDED_BIT | 0x22)
+#define CC1200_FS_VCO4 (CC1200_EXTENDED_BIT | 0x23)
+#define CC1200_FS_VCO3 (CC1200_EXTENDED_BIT | 0x24)
+#define CC1200_FS_VCO2 (CC1200_EXTENDED_BIT | 0x25)
+#define CC1200_FS_VCO1 (CC1200_EXTENDED_BIT | 0x26)
+#define CC1200_FS_VCO0 (CC1200_EXTENDED_BIT | 0x27)
+#define CC1200_GBIAS6 (CC1200_EXTENDED_BIT | 0x28)
+#define CC1200_GBIAS5 (CC1200_EXTENDED_BIT | 0x29)
+#define CC1200_GBIAS4 (CC1200_EXTENDED_BIT | 0x2A)
+#define CC1200_GBIAS3 (CC1200_EXTENDED_BIT | 0x2B)
+#define CC1200_GBIAS2 (CC1200_EXTENDED_BIT | 0x2C)
+#define CC1200_GBIAS1 (CC1200_EXTENDED_BIT | 0x2D)
+#define CC1200_GBIAS0 (CC1200_EXTENDED_BIT | 0x2E)
+#define CC1200_IFAMP (CC1200_EXTENDED_BIT | 0x2F)
+#define CC1200_LNA (CC1200_EXTENDED_BIT | 0x30)
+#define CC1200_RXMIX (CC1200_EXTENDED_BIT | 0x31)
+#define CC1200_XOSC5 (CC1200_EXTENDED_BIT | 0x32)
+#define CC1200_XOSC4 (CC1200_EXTENDED_BIT | 0x33)
+#define CC1200_XOSC3 (CC1200_EXTENDED_BIT | 0x34)
+#define CC1200_XOSC2 (CC1200_EXTENDED_BIT | 0x35)
+#define CC1200_XOSC1 (CC1200_EXTENDED_BIT | 0x36)
+#define CC1200_XOSC0 (CC1200_EXTENDED_BIT | 0x37)
+#define CC1200_ANALOG_SPARE (CC1200_EXTENDED_BIT | 0x38)
+#define CC1200_PA_CFG3 (CC1200_EXTENDED_BIT | 0x39)
+#define CC1200_WOR_TIME1 (CC1200_EXTENDED_BIT | 0x64)
+#define CC1200_WOR_TIME0 (CC1200_EXTENDED_BIT | 0x65)
+#define CC1200_WOR_CAPTURE1 (CC1200_EXTENDED_BIT | 0x66)
+#define CC1200_WOR_CAPTURE0 (CC1200_EXTENDED_BIT | 0x67)
+#define CC1200_BIST (CC1200_EXTENDED_BIT | 0x68)
+#define CC1200_DCFILTOFFSET_I1 (CC1200_EXTENDED_BIT | 0x69)
+#define CC1200_DCFILTOFFSET_I0 (CC1200_EXTENDED_BIT | 0x6A)
+#define CC1200_DCFILTOFFSET_Q1 (CC1200_EXTENDED_BIT | 0x6B)
+#define CC1200_DCFILTOFFSET_Q0 (CC1200_EXTENDED_BIT | 0x6C)
+#define CC1200_IQIE_I1 (CC1200_EXTENDED_BIT | 0x6D)
+#define CC1200_IQIE_I0 (CC1200_EXTENDED_BIT | 0x6E)
+#define CC1200_IQIE_Q1 (CC1200_EXTENDED_BIT | 0x6f)
+#define CC1200_IQIE_Q0 (CC1200_EXTENDED_BIT | 0x70)
+#define CC1200_RSSI1 (CC1200_EXTENDED_BIT | 0x71)
+#define CC1200_RSSI0 (CC1200_EXTENDED_BIT | 0x72)
+#define CC1200_MARCSTATE (CC1200_EXTENDED_BIT | 0x73)
+#define CC1200_LQI_VAL (CC1200_EXTENDED_BIT | 0x74)
+#define CC1200_PQT_SYNC_ERR (CC1200_EXTENDED_BIT | 0x75)
+#define CC1200_DEM_STATUS (CC1200_EXTENDED_BIT | 0x76)
+#define CC1200_FREQOFF_EST1 (CC1200_EXTENDED_BIT | 0x77)
+#define CC1200_FREQOFF_EST0 (CC1200_EXTENDED_BIT | 0x78)
+#define CC1200_AGC_GAIN3 (CC1200_EXTENDED_BIT | 0x79)
+#define CC1200_AGC_GAIN2 (CC1200_EXTENDED_BIT | 0x7a)
+#define CC1200_AGC_GAIN1 (CC1200_EXTENDED_BIT | 0x7b)
+#define CC1200_AGC_GAIN0 (CC1200_EXTENDED_BIT | 0x7c)
+#define CC1200_SOFT_RX_DATA_OUT (CC1200_EXTENDED_BIT | 0x7d)
+#define CC1200_SOFT_TX_DATA_IN (CC1200_EXTENDED_BIT | 0x7e)
+#define CC1200_ASK_SOFT_RX_DATA (CC1200_EXTENDED_BIT | 0x7f)
+#define CC1200_RNDGEN (CC1200_EXTENDED_BIT | 0x80)
+#define CC1200_MAGN2 (CC1200_EXTENDED_BIT | 0x81)
+#define CC1200_MAGN1 (CC1200_EXTENDED_BIT | 0x82)
+#define CC1200_MAGN0 (CC1200_EXTENDED_BIT | 0x83)
+#define CC1200_ANG1 (CC1200_EXTENDED_BIT | 0x84)
+#define CC1200_ANG0 (CC1200_EXTENDED_BIT | 0x85)
+#define CC1200_CHFILT_I2 (CC1200_EXTENDED_BIT | 0x86)
+#define CC1200_CHFILT_I1 (CC1200_EXTENDED_BIT | 0x87)
+#define CC1200_CHFILT_I0 (CC1200_EXTENDED_BIT | 0x88)
+#define CC1200_CHFILT_Q2 (CC1200_EXTENDED_BIT | 0x89)
+#define CC1200_CHFILT_Q1 (CC1200_EXTENDED_BIT | 0x8a)
+#define CC1200_CHFILT_Q0 (CC1200_EXTENDED_BIT | 0x8b)
+#define CC1200_GPIO_STATUS (CC1200_EXTENDED_BIT | 0x8c)
+#define CC1200_FSCAL_CTRL (CC1200_EXTENDED_BIT | 0x8d)
+#define CC1200_PHASE_ADJUST (CC1200_EXTENDED_BIT | 0x8e)
+#define CC1200_PARTNUMBER (CC1200_EXTENDED_BIT | 0x8f)
+#define CC1200_PARTVERSION (CC1200_EXTENDED_BIT | 0x90)
+#define CC1200_SERIAL_STATUS (CC1200_EXTENDED_BIT | 0x91)
+#define CC1200_MODEM_STATUS1 (CC1200_EXTENDED_BIT | 0x92)
+#define CC1200_MODEM_STATUS1_SYNC_FOUND 7
+#define CC1200_MODEM_STATUS1_RXFIFO_FULL 6
+#define CC1200_MODEM_STATUS1_RXFIFO_THR 5
+#define CC1200_MODEM_STATUS1_RXFIFO_EMPTY 4
+#define CC1200_MODEM_STATUS1_RXFIFO_OVERFLOW 3
+#define CC1200_MODEM_STATUS1_RXFIFO_UNDERFLOW 2
+#define CC1200_MODEM_STATUS1_PQT_REACHED 1
+#define CC1200_MODEM_STATUS1_PQT_VALID 0
+
+#define CC1200_MODEM_STATUS0 (CC1200_EXTENDED_BIT | 0x93)
+#define CC1200_MODEM_STATUS0_FEC_RX_OVERFLOW 6
+#define CC1200_MODEM_STATUS0_SYNC_SENT 4
+#define CC1200_MODEM_STATUS0_TXFIFO_FULL 3
+#define CC1200_MODEM_STATUS0_TXFIFO_THR 2
+#define CC1200_MODEM_STATUS0_TXFIFO_OVERFLOW 1
+#define CC1200_MODEM_STATUS0_TXFIFO_UNDERFLOW 0
+
+#define CC1200_MARC_STATUS1 (CC1200_EXTENDED_BIT | 0x94)
+#define CC1200_MARC_STATUS1_NO_FAILURE 0
+#define CC1200_MARC_STATUS1_RX_TIMEOUT 1
+#define CC1200_MARC_STATUS1_RX_TERMINATION 2
+#define CC1200_MARC_STATUS1_EWOR_SYNC_LOST 3
+#define CC1200_MARC_STATUS1_MAXIMUM_LENGTH 4
+#define CC1200_MARC_STATUS1_ADDRESS 5
+#define CC1200_MARC_STATUS1_CRC 6
+#define CC1200_MARC_STATUS1_TX_FIFO_OVERFLOW 7
+#define CC1200_MARC_STATUS1_TX_FIFO_UNDERFLOW 8
+#define CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW 9
+#define CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW 10
+#define CC1200_MARC_STATUS1_TX_ON_CCA_FAILED 11
+#define CC1200_MARC_STATUS1_TX_FINISHED 0x40
+#define CC1200_MARC_STATUS1_RX_FINISHED 0x80
+#define CC1200_MARC_STATUS0 (CC1200_EXTENDED_BIT | 0x95)
+#define CC1200_PA_IFAMP_TEST (CC1200_EXTENDED_BIT | 0x96)
+#define CC1200_FSRF_TEST (CC1200_EXTENDED_BIT | 0x97)
+#define CC1200_PRE_TEST (CC1200_EXTENDED_BIT | 0x98)
+#define CC1200_PRE_OVR (CC1200_EXTENDED_BIT | 0x99)
+#define CC1200_ADC_TEST (CC1200_EXTENDED_BIT | 0x9a)
+#define CC1200_DVC_TEST (CC1200_EXTENDED_BIT | 0x9b)
+#define CC1200_ATEST (CC1200_EXTENDED_BIT | 0x9c)
+#define CC1200_ATEST_LVDS (CC1200_EXTENDED_BIT | 0x9d)
+#define CC1200_ATEST_MODE (CC1200_EXTENDED_BIT | 0x9e)
+#define CC1200_XOSC_TEST1 (CC1200_EXTENDED_BIT | 0x9f)
+#define CC1200_XOSC_TEST0 (CC1200_EXTENDED_BIT | 0xa0)
+#define CC1200_RXFIRST (CC1200_EXTENDED_BIT | 0xd2)
+#define CC1200_TXFIRST (CC1200_EXTENDED_BIT | 0xd3)
+#define CC1200_RXLAST (CC1200_EXTENDED_BIT | 0xd4)
+#define CC1200_TXLAST (CC1200_EXTENDED_BIT | 0xd5)
+#define CC1200_NUM_TXBYTES (CC1200_EXTENDED_BIT | 0xd6)
+#define CC1200_NUM_RXBYTES (CC1200_EXTENDED_BIT | 0xd7)
+#define CC1200_FIFO_NUM_TXBYTES (CC1200_EXTENDED_BIT | 0xd8)
+#define CC1200_FIFO_NUM_RXBYTES (CC1200_EXTENDED_BIT | 0xd9)
+#define CC1200_RXFIFO_PRE_BUF (CC1200_EXTENDED_BIT | 0xda)
+#define CC1200_AES_WORKSPACE_0 (CC1200_EXTENDED_BIT | 0xe0)
+
+/* Status byte */
+#define CC1200_STATUS_CHIP_RDY 7
+#define CC1200_STATUS_STATE 4
+#define CC1200_STATUS_STATE_IDLE 0
+#define CC1200_STATUS_STATE_RX 1
+#define CC1200_STATUS_STATE_TX 2
+#define CC1200_STATUS_STATE_FSTXON 3
+#define CC1200_STATUS_STATE_CALIBRATE 4
+#define CC1200_STATUS_STATE_SETTLING 5
+#define CC1200_STATUS_STATE_RX_FIFO_ERROR 6
+#define CC1200_STATUS_STATE_TX_FIFO_ERROR 7
+#define CC1200_STATUS_STATE_MASK 7
+
+#endif /* _AO_CC1200_H_ */
--- /dev/null
+/***************************************************************
+ * SmartRF Studio(tm) Export
+ *
+ * Radio register settings specifed with address, value
+ *
+ * RF device: CC1200
+ *
+ ***************************************************************/
+
+/*
+ * Values affecting receive sensitivity:
+ *
+ *
+ * PQT - sets how good the preamble needs to look before
+ * we start looking for a sync word
+ * SYNC_THR - sets how good the sync needs to be before we
+ * start decoding a packet
+ */
+
+/* Values depending on data rate
+ *
+ * DCFILT_BW_SETTLE
+ * DCFILT_BW
+ */
+
+#ifndef AO_CC1200_AGC_GAIN_ADJUST
+#define AO_CC1200_AGC_GAIN_ADJUST -94
+#endif
+
+ CC1200_IOCFG2, 0x06, /* GPIO2 IO Pin Configuration */
+ CC1200_SYNC3, 0xD3, /* Sync Word Configuration [23:16] */
+ CC1200_SYNC2, 0x91, /* Sync Word Configuration [23:16] */
+ CC1200_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */
+ CC1200_SYNC0, 0x91, /* Sync Word Configuration [7:0] */
+ CC1200_SYNC_CFG1, /* Sync Word Detection Configuration Reg. 1 */
+ ((CC1200_SYNC_CFG1_SYNC_MODE_16_BITS << CC1200_SYNC_CFG1_SYNC_MODE) |
+ (11 << CC1200_SYNC_CFG1_SYNC_THR)),
+ CC1200_SYNC_CFG0, /* Sync Word Detection Configuration Reg. 0 */
+ ((1 << CC1200_SYNC_CFG0_AUTO_CLEAR) |
+ (0 << CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION) |
+ (1 << CC1200_SYNC_CFG0_PQT_GATING_EN) |
+ (0 << CC1200_SYNC_CFG0_EXT_SYNC_DETECT) |
+ (CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_DISABLED << CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK)),
+ CC1200_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */
+ CC1200_DCFILT_CFG, 0x5d, /* Digital DC Removal Configuration */
+ CC1200_PREAMBLE_CFG0, /* Preamble Detection Configuration Reg. 0 */
+ ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) |
+ (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) |
+ (15 << CC1200_PREAMBLE_CFG0_PQT)),
+ CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */
+ CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */
+ CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */
+ CC1200_MDMCFG0, 0x05, /* General Modem Parameter Configuration Reg. 0 */
+ CC1200_SYMBOL_RATE2, 0x93, /* Symbol Rate Configuration Exponent and Mantissa [1.. */
+ CC1200_AGC_REF, 0x27, /* AGC Reference Level Configuration */
+ CC1200_AGC_CS_THR, 0xec, /* Carrier Sense Threshold Configuration */
+ CC1200_AGC_GAIN_ADJUST, /* RSSI adjustment */
+ AO_CC1200_AGC_GAIN_ADJUST,
+ CC1200_AGC_CFG1, 0x51, /* Automatic Gain Control Configuration Reg. 1 */
+ CC1200_AGC_CFG0, 0x87, /* Automatic Gain Control Configuration Reg. 0 */
+ CC1200_FIFO_CFG, 0x40, /* FIFO Configuration */
+ CC1200_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */
+ ((CC1200_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME << CC1200_SETTLING_CFG_FS_AUTOCAL) |
+ (CC1200_SETTLING_CFG_LOCK_TIME_75_30 << CC1200_SETTLING_CFG_LOCK_TIME) |
+ (CC1200_SETTLING_CFG_FSREG_TIME_60 << CC1200_SETTLING_CFG_FSREG_TIME)),
+ CC1200_FS_CFG, /* Frequency Synthesizer Configuration */
+ ((1 << CC1200_FS_CFG_LOCK_EN) |
+ (CC1200_FS_CFG_FSD_BANDSELECT_410_480 << CC1200_FS_CFG_FSD_BANDSELECT)),
+ CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */
+ ((0 << CC1200_PKT_CFG2_FG_MODE_EN) |
+ (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) |
+ (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)),
+ CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */
+ ((1 << CC1200_PKT_CFG1_FEC_EN) |
+ (1 << CC1200_PKT_CFG1_WHITE_DATA) |
+ (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) |
+ (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) |
+ (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) |
+ (1 << CC1200_PKT_CFG1_APPEND_STATUS)),
+ CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */
+ ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) |
+ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) |
+ (0 << CC1200_PKT_CFG0_UART_MODE_EN) |
+ (0 << CC1200_PKT_CFG0_UART_SWAP_EN)),
+ CC1200_RFEND_CFG1, /* RFEND Configuration Reg. 1 */
+ ((CC1200_RFEND_CFG1_RXOFF_MODE_IDLE << CC1200_RFEND_CFG1_RXOFF_MODE) |
+ (CC1200_RFEND_CFG1_RX_TIME_INFINITE << CC1200_RFEND_CFG1_RX_TIME) |
+ (0 << CC1200_RFEND_CFG1_RX_TIME_QUAL)),
+ CC1200_RFEND_CFG0, /* RFEND Configuration Reg. 0 */
+ ((0 << CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN) |
+ (CC1200_RFEND_CFG0_TXOFF_MODE_IDLE << CC1200_RFEND_CFG0_TXOFF_MODE) |
+ (1 << CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN) |
+ (0 << CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG)),
+ CC1200_PA_CFG1, 0x3f, /* Power Amplifier Configuration Reg. 1 */
+ CC1200_PA_CFG0, 0x53, /* Power Amplifier Configuration Reg. 0 */
+ CC1200_PKT_LEN, 0xff, /* Packet Length Configuration */
+ CC1200_IF_MIX_CFG, 0x1c, /* IF Mix Configuration */
+ CC1200_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */
+ CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */
+ ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) |
+ (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) |
+ (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) |
+ (0 << CC1200_MDMCFG2_CFM_DATA_EN)),
+ CC1200_FREQ2, 0x6c, /* Frequency Configuration [23:16] */
+ CC1200_FREQ1, 0xa3, /* Frequency Configuration [15:8] */
+ CC1200_FREQ0, 0x33, /* Frequency Configuration [7:0] */
+ CC1200_IF_ADC1, 0xee, /* Analog to Digital Converter Configuration Reg. 1 */
+ CC1200_IF_ADC0, 0x10, /* Analog to Digital Converter Configuration Reg. 0 */
+ CC1200_FS_DIG1, 0x07, /* Frequency Synthesizer Digital Reg. 1 */
+ CC1200_FS_DIG0, 0xaf, /* Frequency Synthesizer Digital Reg. 0 */
+ CC1200_FS_CAL1, 0x40, /* Frequency Synthesizer Calibration Reg. 1 */
+ CC1200_FS_CAL0, 0x0e, /* Frequency Synthesizer Calibration Reg. 0 */
+ CC1200_FS_DIVTWO, 0x03, /* Frequency Synthesizer Divide by 2 */
+ CC1200_FS_DSM0, 0x33, /* FS Digital Synthesizer Module Configuration Reg. 0 */
+ CC1200_FS_DVC0, 0x17, /* Frequency Synthesizer Divider Chain Configuration .. */
+ CC1200_FS_PFD, 0x00, /* Frequency Synthesizer Phase Frequency Detector Con.. */
+ CC1200_FS_PRE, 0x6e, /* Frequency Synthesizer Prescaler Configuration */
+ CC1200_FS_REG_DIV_CML, 0x1c, /* Frequency Synthesizer Divider Regulator Configurat.. */
+ CC1200_FS_SPARE, 0xac, /* Frequency Synthesizer Spare */
+ CC1200_FS_VCO0, 0xb5, /* FS Voltage Controlled Oscillator Configuration Reg.. */
+ CC1200_XOSC5, 0x0e, /* Crystal Oscillator Configuration Reg. 5 */
+ CC1200_XOSC1, 0x03, /* Crystal Oscillator Configuration Reg. 1 */
#include "ao.h"
-static char
+static int
ao_packet_getchar(void)
{
int c;
#define HAS_BEEP 1
#define HAS_BATTERY_REPORT 1
-#define AO_STACK_SIZE 384
+#define AO_STACK_SIZE 376
#define IS_FLASH_LOADER 0
#define HAS_TASK 1
#endif
-#ifndef AO_PORT_TYPE
-#define AO_PORT_TYPE uint8_t
-#endif
-
typedef AO_PORT_TYPE ao_port_t;
#if HAS_TASK
#define AO_PANIC_BUFIO 15 /* Mis-using bufio API */
#define AO_PANIC_EXTI 16 /* Mis-using exti API */
#define AO_PANIC_FAST_TIMER 17 /* Mis-using fast timer API */
+#define AO_PANIC_ADC 18 /* Mis-using ADC interface */
#define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */
#define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */
#define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */
/* Set delay between telemetry reports (0 to disable) */
-#ifdef AO_SEND_ALL_BARO
-#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100)
-#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(100)
-#else
#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000)
#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100)
#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000)
-#endif
void
ao_telemetry_reset_interval(void);
extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING];
#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1))
+#define ao_monitor_ring_prev(n) (((n) - 1) & (AO_MONITOR_RING - 1))
extern __data uint8_t ao_monitoring;
extern __data uint8_t ao_monitor_head;
}
_ao_config_edit_start();
ao_config.radio_rate = ao_cmd_lex_i;
+ _ao_config_edit_finish();
#if HAS_TELEMETRY
ao_telemetry_reset_interval();
#endif
- _ao_config_edit_finish();
#if HAS_RADIO_RECV
ao_radio_recv_abort();
#endif
_ao_config_edit_start();
ao_config.radio_enable = ao_cmd_lex_i;
_ao_config_edit_finish();
+#if HAS_TELEMETRY && HAS_RADIO_RATE
+ ao_telemetry_reset_interval();
+#endif
}
#endif /* HAS_RADIO */
_ao_config_edit_start();
ao_config.aprs_interval = ao_cmd_lex_i;
_ao_config_edit_finish();
+ ao_telemetry_reset_interval();
}
#endif /* HAS_APRS */
ao_config.tracker_motion = m;
ao_config.tracker_interval = i;
_ao_config_edit_finish();
+#if HAS_TELEMETRY
+ ao_telemetry_reset_interval();
+#endif
}
#endif /* HAS_TRACKER */
#endif
#include "ao_telem.h"
-#ifndef AO_TELEMETRY_LOCATION_ALTITUDE
-#define AO_TELEMETRY_LOCATION_ALTITUDE(l) ((l)->altitude)
+#ifndef AO_GPS_ORIG_ALTITUDE
+#define AO_GPS_ORIG_ALTITUDE(l) ((l)->altitude)
#endif
void
AO_TELEM_GPS_ALTITUDE " %d ",
(long) gps_data->latitude,
(long) gps_data->longitude,
- AO_TELEMETRY_LOCATION_ALTITUDE(gps_data));
+ AO_GPS_ORIG_ALTITUDE(gps_data));
if (gps_data->flags & AO_GPS_DATE_VALID)
printf(AO_TELEM_GPS_YEAR " %d "
#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */
#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */
#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */
-#define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */
+#define AO_LOG_FORMAT_TELEMEGA_OLD 5 /* 32 byte typed telemega records */
#define AO_LOG_FORMAT_EASYMINI 6 /* 16-byte MS5607 baro only, 3.0V supply */
#define AO_LOG_FORMAT_TELEMETRUM 7 /* 16-byte typed telemetrum records */
#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_NONE 127 /* No log at all */
extern __code uint8_t ao_log_format;
uint16_t tick; /* 2 */
union { /* 4 */
/* AO_LOG_FLIGHT */
+ struct {
+ uint16_t flight; /* 4 */
+ int16_t ground_accel; /* 6 */
+ uint32_t ground_pres; /* 8 */
+ int16_t ground_accel_along; /* 12 */
+ int16_t ground_accel_across; /* 14 */
+ int16_t ground_accel_through; /* 16 */
+ int16_t pad_18; /* 18 */
+ int32_t ground_roll; /* 20 */
+ int32_t ground_pitch; /* 24 */
+ int32_t ground_yaw; /* 28 */
+ } flight; /* 32 */
struct {
uint16_t flight; /* 4 */
int16_t ground_accel; /* 6 */
int16_t ground_roll; /* 18 */
int16_t ground_pitch; /* 20 */
int16_t ground_yaw; /* 22 */
- } flight; /* 24 */
+ } flight_old; /* 24 */
/* AO_LOG_STATE */
struct {
uint16_t state;
void
ao_monitor_blink(void)
{
+#ifdef AO_MONITOR_BAD
+ uint8_t *recv;
+#endif
for (;;) {
ao_sleep(DATA_TO_XDATA(&ao_monitor_head));
- ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100));
+#ifdef AO_MONITOR_BAD
+ recv = (uint8_t *) &ao_monitor_ring[ao_monitor_ring_prev(ao_monitor_head)];
+ if (ao_monitoring && !(recv[ao_monitoring + 1] & AO_RADIO_STATUS_CRC_OK))
+ ao_led_for(AO_MONITOR_BAD, AO_MS_TO_TICKS(100));
+ else
+#endif
+ ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100));
}
}
#endif
int
_ao_serial0_pollchar(void);
+uint8_t
+_ao_serial0_sleep(void);
+
void
ao_serial0_putchar(char c);
int
_ao_serial1_pollchar(void);
+uint8_t
+_ao_serial1_sleep(void);
+
void
ao_serial1_putchar(char c);
int
_ao_serial2_pollchar(void);
+uint8_t
+_ao_serial2_sleep(void);
+
void
ao_serial2_putchar(char c);
int
_ao_serial3_pollchar(void);
+uint8_t
+_ao_serial3_sleep(void);
+
void
ao_serial3_putchar(char c);
void (*putchar)(char),
void (*flush)(void)) __reentrant
{
-#if AO_NUM_STDIOS > 1
if (ao_num_stdios == AO_NUM_STDIOS)
ao_panic(AO_PANIC_STDIO);
-#endif
ao_stdios[ao_num_stdios]._pollchar = _pollchar;
ao_stdios[ao_num_stdios].putchar = putchar;
ao_stdios[ao_num_stdios].flush = flush;
#include "ao_log.h"
#include "ao_product.h"
-#ifndef HAS_RDF
-#define HAS_RDF 1
-#endif
-
static __pdata uint16_t ao_telemetry_interval;
#if HAS_RADIO_RATE
static __xdata uint16_t ao_telemetry_desired_interval;
#endif
+/* TeleMetrum v1.0 just doesn't have enough space to
+ * manage the more complicated telemetry scheduling, so
+ * it loses the ability to disable telem/rdf separately
+ */
+
+#if defined(TELEMETRUM_V_1_0)
+#define SIMPLIFY
+#endif
+
+#ifdef SIMPLIFY
+#define ao_telemetry_time time
+#define RDF_SPACE __pdata
+#else
+#define RDF_SPACE __xdata
+static __pdata uint16_t ao_telemetry_time;
+#endif
+
#if HAS_RDF
-static __pdata uint8_t ao_rdf = 0;
-static __pdata uint16_t ao_rdf_time;
+static RDF_SPACE uint8_t ao_rdf = 0;
+static RDF_SPACE uint16_t ao_rdf_time;
#endif
#if HAS_APRS
telemetry.generic.tick = packet->tick;
telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR;
+#if HAS_MPU6000
telemetry.mega_sensor.orient = ao_sample_orient;
+#endif
telemetry.mega_sensor.accel = ao_data_accel(packet);
telemetry.mega_sensor.pres = ao_data_pres(packet);
telemetry.mega_sensor.temp = ao_data_temp(packet);
#endif /* AO_SEND_MINI */
-#ifdef AO_SEND_ALL_BARO
-static uint8_t ao_baro_sample;
-
-static void
-ao_send_baro(void)
-{
- uint8_t sample = ao_sample_data;
- uint8_t samples = (sample - ao_baro_sample) & (AO_DATA_RING - 1);
-
- if (samples > 12) {
- ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_DATA_RING - 1);
- samples = 12;
- }
- telemetry.generic.tick = ao_data_ring[sample].tick;
- telemetry.generic.type = AO_TELEMETRY_BARO;
- telemetry.baro.samples = samples;
- for (sample = 0; sample < samples; sample++) {
- telemetry.baro.baro[sample] = ao_data_ring[ao_baro_sample].adc.pres;
- ao_baro_sample = ao_data_ring_next(ao_baro_sample);
- }
- ao_radio_send(&telemetry, sizeof (telemetry));
-}
-#endif
-
static __pdata int8_t ao_telemetry_config_max;
static __pdata int8_t ao_telemetry_config_cur;
#if HAS_GPS
+static __pdata int8_t ao_telemetry_gps_max;
static __pdata int8_t ao_telemetry_loc_cur;
static __pdata int8_t ao_telemetry_sat_cur;
telemetry.location.tick = ao_gps_tick;
ao_mutex_put(&ao_gps_mutex);
ao_radio_send(&telemetry, sizeof (telemetry));
- ao_telemetry_loc_cur = ao_telemetry_config_max;
+ ao_telemetry_loc_cur = ao_telemetry_gps_max;
}
}
AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info));
ao_mutex_put(&ao_gps_mutex);
ao_radio_send(&telemetry, sizeof (telemetry));
- ao_telemetry_sat_cur = ao_telemetry_config_max;
+ ao_telemetry_sat_cur = ao_telemetry_gps_max;
}
}
#endif
while (ao_telemetry_interval == 0)
ao_sleep(&telemetry);
time = ao_time();
+ ao_telemetry_time = time;
#if HAS_RDF
ao_rdf_time = time;
#endif
ao_aprs_time = time;
#endif
while (ao_telemetry_interval) {
-#if HAS_APRS
+ time = ao_time() + AO_SEC_TO_TICKS(100);
+#ifndef SIMPLIFY
if (!(ao_config.radio_enable & AO_RADIO_DISABLE_TELEMETRY))
#endif
{
-#ifdef AO_SEND_ALL_BARO
- ao_send_baro();
+#ifndef SIMPLIFY
+ if ( (int16_t) (ao_time() - ao_telemetry_time) >= 0)
#endif
-
-#if HAS_FLIGHT
+ {
+ ao_telemetry_time = ao_time() + ao_telemetry_interval;
# ifdef AO_SEND_MEGA
- ao_send_mega_sensor();
- ao_send_mega_data();
+ ao_send_mega_sensor();
+ ao_send_mega_data();
# endif
# ifdef AO_SEND_METRUM
- ao_send_metrum_sensor();
- ao_send_metrum_data();
+ ao_send_metrum_sensor();
+ ao_send_metrum_data();
# endif
# ifdef AO_SEND_MINI
- ao_send_mini();
+ ao_send_mini();
# endif
# ifdef AO_TELEMETRY_SENSOR
- ao_send_sensor();
+ ao_send_sensor();
# endif
-#endif /* HAS_FLIGHT */
-
#if HAS_COMPANION
- if (ao_companion_running)
- ao_send_companion();
+ if (ao_companion_running)
+ ao_send_companion();
#endif
- ao_send_configuration();
#if HAS_GPS
- ao_send_location();
- ao_send_satellite();
+ ao_send_location();
+ ao_send_satellite();
+#endif
+ ao_send_configuration();
+ }
+#ifndef SIMPLIFY
+ time = ao_telemetry_time;
#endif
}
-#ifndef AO_SEND_ALL_BARO
#if HAS_RDF
- if (ao_rdf &&
-#if HAS_APRS
- !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF) &&
-#endif /* HAS_APRS */
- (int16_t) (ao_time() - ao_rdf_time) >= 0)
+ if (ao_rdf
+#ifndef SIMPLIFY
+ && !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF)
+#endif
+ )
{
+ if ((int16_t) (ao_time() - ao_rdf_time) >= 0) {
#if HAS_IGNITE_REPORT
- uint8_t c;
-#endif /* HAS_IGNITE_REPORT */
- ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;
+ uint8_t c;
+#endif
+ ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS;
#if HAS_IGNITE_REPORT
- if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter()))
- ao_radio_continuity(c);
- else
-#endif /* HAS_IGNITE_REPORT*/
- ao_radio_rdf();
+ if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter()))
+ ao_radio_continuity(c);
+ else
+#endif
+ ao_radio_rdf();
+ }
+#ifndef SIMPLIFY
+ if ((int16_t) (time - ao_rdf_time) > 0)
+ time = ao_rdf_time;
+#endif
}
#endif /* HAS_RDF */
#if HAS_APRS
- if (ao_config.aprs_interval != 0 &&
- (int16_t) (ao_time() - ao_aprs_time) >= 0)
- {
- ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);
- ao_aprs_send();
+ if (ao_config.aprs_interval != 0) {
+ if ((int16_t) (ao_time() - ao_aprs_time) >= 0) {
+ ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval);
+ ao_aprs_send();
+ }
+ if ((int16_t) (time - ao_aprs_time) > 0)
+ time = ao_aprs_time;
}
#endif /* HAS_APRS */
-#endif /* !AO_SEND_ALL_BARO */
- time += ao_telemetry_interval;
delay = time - ao_time();
if (delay > 0) {
ao_alarm(delay);
ao_sleep(&telemetry);
ao_clear_alarm();
}
- else
- time = ao_time();
}
}
}
ao_telemetry_companion_cur = cur;
#endif
- ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval;
-#if HAS_COMPANION
- if (ao_telemetry_config_max > cur)
- cur++;
- ao_telemetry_config_cur = cur;
-#endif
-
#if HAS_GPS
- if (ao_telemetry_config_max > cur)
+ ao_telemetry_gps_max = AO_SEC_TO_TICKS(1) / interval;
+ if (ao_telemetry_gps_max > cur)
cur++;
ao_telemetry_loc_cur = cur;
- if (ao_telemetry_config_max > cur)
+ if (ao_telemetry_gps_max > cur)
cur++;
ao_telemetry_sat_cur = cur;
#endif
+
+ ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval;
+ if (ao_telemetry_config_max > cur)
+ cur++;
+ ao_telemetry_config_cur = cur;
+
+#ifndef SIMPLIFY
+ ao_telemetry_time =
+#if HAS_RDF
+ ao_rdf_time =
+#endif
+#if HAS_APRS
+ ao_aprs_time =
+#endif
+ ao_time();
+#endif
ao_wakeup(&telemetry);
}
/* 32 */
};
-#if HAS_GPS
-
#ifndef HAS_WIDE_GPS
#define HAS_WIDE_GPS 1
#endif
+#ifdef HAS_TELEMETRY
+#ifndef HAS_RDF
+#define HAS_RDF 1
+#endif
+#endif
+
#if HAS_WIDE_GPS
typedef int32_t gps_alt_t;
#define AO_TELEMETRY_LOCATION_ALTITUDE(l) (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
(l)->altitude_low = (a)))
#endif /* HAS_WIDE_GPS */
-#endif /* HAS_GPS */
-
#define AO_TELEMETRY_SATELLITE 0x06
struct ao_telemetry_satellite_info {
if (height < 0)
height = -height;
- if (ao_tracker_force_telem)
+ if (ao_tracker_force_telem > 1)
printf("head %d ring %d ground_distance %d height %d\n", gps_head, ring, ground_distance, height);
if (ground_distance > ao_config.tracker_motion ||
height > (ao_config.tracker_motion << 1))
break;
}
}
- if (ao_tracker_force_telem) {
+ if (ao_tracker_force_telem > 1) {
printf ("moving %d started %d\n", moving, log_started);
flush();
}
static void
ao_tracker_set_telem(void)
{
- uint8_t telem;
ao_cmd_hex();
- telem = ao_cmd_lex_i;
if (ao_cmd_status == ao_cmd_success)
- ao_tracker_force_telem = telem;
+ ao_tracker_force_telem = ao_cmd_lex_i;
ao_cmd_status = ao_cmd_success;
printf ("flight: %d\n", ao_flight_number);
printf ("force_telem: %d\n", ao_tracker_force_telem);
}
static const struct ao_cmds ao_tracker_cmds[] = {
- { ao_tracker_set_telem, "t <d>\0Set telem on USB" },
+ { ao_tracker_set_telem, "t <d>\0Set telem on USB (0 off, 1 on, 2 dbg)" },
{ 0, NULL },
};
/* SPI definitions */
#define AO_SPI_SPEED_12MHz 4
+#define AO_SPI_SPEED_8MHz 6
#define AO_SPI_SPEED_6MHz 8
#define AO_SPI_SPEED_4MHz 12
#define AO_SPI_SPEED_2MHz 24
#define AO_SPI_SPEED_1MHz 48
#define AO_SPI_SPEED_500kHz 96
#define AO_SPI_SPEED_250kHz 192
+#define AO_SPI_SPEED_125kHz 384
+#define AO_SPI_SPEED_62500Hz 768
#define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz
#define ao_gpio_get(port, bit, pin) (lpc_gpio.byte[lpc_all_bit(port,bit)])
+#define PORT0_JTAG_REGS ((1 << 11) | (1 << 12) | (1 << 14))
+
+static inline void lpc_set_gpio(int port, int bit) {
+ if (port == 0 && (1 << bit) & (PORT0_JTAG_REGS)) {
+ vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit));
+
+ *_ioconf = (*_ioconf & ~LPC_IOCONF_FUNC_MASK) | LPC_IOCONF_FUNC_PIO0_11;
+ }
+}
+
#define ao_enable_output(port,bit,pin,v) do { \
ao_enable_port(port); \
+ lpc_set_gpio(port,bit); \
ao_gpio_set(port, bit, pin, v); \
lpc_gpio.dir[port] |= (1 << bit); \
} while (0)
#define ao_enable_input(port,bit,mode) do { \
ao_enable_port(port); \
+ lpc_set_gpio(port,bit); \
lpc_gpio.dir[port] &= ~(1 << bit); \
ao_gpio_set_mode(port,bit,mode); \
} while (0)
ao_spi_put(uint8_t spi_index);
void
-ao_spi_send(void *block, uint16_t len, uint8_t spi_index);
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index);
void
ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
void
-ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index);
-
-extern uint16_t ao_spi_speed[LPC_NUM_SPI];
+ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index);
void
ao_spi_init(void);
ao_led_init(AO_PORT_TYPE enable)
{
ao_led_enable = enable;
- lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO);
+ ao_enable_port(LED_PORT);
+ if (LED_PORT == 0) {
+ if (enable & (1 << 11))
+ lpc_ioconf.pio0_11 = LPC_IOCONF_FUNC_PIO0_11 | (1 << LPC_IOCONF_ADMODE);
+ if (enable & (1 << 12))
+ lpc_ioconf.pio0_12 = LPC_IOCONF_FUNC_PIO0_12 | (1 << LPC_IOCONF_ADMODE);
+ if (enable & (1 << 14))
+ lpc_ioconf.pio0_14 = LPC_IOCONF_FUNC_PIO0_14 | (1 << LPC_IOCONF_ADMODE);
+ }
lpc_gpio.dir[LED_PORT] |= enable;
+ ao_led_off(enable);
}
static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 };
-#define tx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_TNF))) != (1 << LPC_SSP_SR_TNF)
-#define rx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_RNE))) != (1 << LPC_SSP_SR_RNE)
-
#define spi_loop(len, put, get) do { \
while (len--) { \
- /* Wait for space in the fifo */ \
- while (tx_busy(lpc_ssp)) \
- ; \
- \
/* send a byte */ \
lpc_ssp->dr = put; \
- \
- /* Wait for byte to appear in the fifo */ \
- while (rx_busy(lpc_ssp)) \
+ /* wait for the received byte to appear */ \
+ while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0) \
; \
- \
- /* recv a byte */ \
+ /* receive a byte */ \
get lpc_ssp->dr; \
} \
+ /* Wait for the SSP to go idle (it already should be) */ \
+ while (lpc_ssp->sr & (1 << LPC_SSP_SR_BSY)); \
} while (0)
void
-ao_spi_send(void *block, uint16_t len, uint8_t id)
+ao_spi_send(const void *block, uint16_t len, uint8_t id)
{
- uint8_t *b = block;
struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
+ const uint8_t *o = block;
- spi_loop(len, *b++, (void));
+ spi_loop(len, *o++, (void));
}
void
void
ao_spi_recv(void *block, uint16_t len, uint8_t id)
{
- uint8_t *b = block;
struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
+ uint8_t *i = block;
- spi_loop(len, 0xff, *b++ =);
+ spi_loop(len, 0xff, *i++ =);
}
void
-ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t id)
+ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t id)
{
- uint8_t *o = out;
- uint8_t *i = in;
struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
+ const uint8_t *o = out;
+ uint8_t *i = in;
spi_loop(len, *o++, *i++ =);
}
struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
ao_mutex_get(&ao_spi_mutex[id]);
-
+
/* Set the clock prescale */
lpc_ssp->cpsr = speed;
}
struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id];
uint8_t d;
+ /* Clear interrupt registers */
+ lpc_ssp->imsc = 0;
+ lpc_ssp->ris = 0;
+ lpc_ssp->mis = 0;
+
lpc_ssp->cr0 = ((LPC_SSP_CR0_DSS_8 << LPC_SSP_CR0_DSS) |
(LPC_SSP_CR0_FRF_SPI << LPC_SSP_CR0_FRF) |
(0 << LPC_SSP_CR0_CPOL) |
lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP0_RST_N);
lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP0_RST_N);
ao_spi_channel_init(0);
-#endif
+#endif
#if HAS_SPI_1
#ifndef HAS_MOSI1
#error "No pin specified for MOSI1"
#endif
-
+
/* Enable the device */
lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP1);
static uint8_t *ao_usb_ep0_rx_buffer;
/* Pointer to bulk data tx/rx buffers in USB memory */
-static uint8_t *ao_usb_in_tx_buffer;
-static uint8_t *ao_usb_out_rx_buffer;
-
-/* Our data buffers */
-static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE];
+static uint8_t *ao_usb_in_tx_buffer[2];
+static uint8_t ao_usb_in_tx_cur;
static uint8_t ao_usb_tx_count;
-static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
+static uint8_t *ao_usb_out_rx_buffer[2];
+static uint8_t ao_usb_out_rx_cur;
static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
extern struct lpc_usb_endpoint lpc_usb_endpoint;
}
static inline vuint32_t *
-ao_usb_epn_out(uint8_t n)
+ao_usb_epn_out(uint8_t n, uint8_t i)
{
- return &lpc_usb_endpoint.epn[n-1].out[0];
+ return &lpc_usb_endpoint.epn[n-1].out[i];
}
static inline vuint32_t *
-ao_usb_epn_in(uint8_t n)
+ao_usb_epn_in(uint8_t n, uint8_t i)
{
- return &lpc_usb_endpoint.epn[n-1].in[0];
+ return &lpc_usb_endpoint.epn[n-1].in[i];
}
#if UNUSED
static void
ao_usb_set_epn_out(uint8_t n, uint8_t *addr, uint16_t nbytes)
{
- ao_usb_set_ep(ao_usb_epn_out(n), addr, nbytes);
+ ao_usb_set_ep(ao_usb_epn_out(n, 0), addr, nbytes);
}
static inline uint16_t
ao_usb_epn_out_count(uint8_t n)
{
- return ao_usb_ep_count(ao_usb_epn_out(n));
+ return ao_usb_ep_count(ao_usb_epn_out(n, 0));
}
static inline uint16_t
ao_usb_epn_in_count(uint8_t n)
{
- return ao_usb_ep_count(ao_usb_epn_in(n));
+ return ao_usb_ep_count(ao_usb_epn_in(n, 0));
}
static uint8_t *
ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes)
{
uint8_t *addr = ao_usb_alloc_sram(nbytes);
-
+
ao_usb_set_ep(ep, addr, set_nbytes);
return addr;
}
}
static void
-ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr)
+ao_usb_enable_epn(uint8_t n,
+ uint16_t out_bytes, uint8_t *out_addrs[2],
+ uint16_t in_bytes, uint8_t *in_addrs[2])
{
uint8_t *addr;
- addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_bytes);
- if (out_addr)
- *out_addr = addr;
- ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]);
+ addr = ao_usb_enable_ep(ao_usb_epn_out(n, 0), out_bytes * 2, out_bytes);
+ if (out_addrs) {
+ out_addrs[0] = addr;
+ out_addrs[1] = addr + out_bytes;
+ }
+ ao_usb_disable_ep(ao_usb_epn_out(n, 1));
- addr = ao_usb_enable_ep(ao_usb_epn_in(n), in_bytes, 0);
- if (in_addr)
- *in_addr = addr;
- ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]);
+ addr = ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_bytes * 2, 0);
+ if (in_addrs) {
+ in_addrs[0] = addr;
+ in_addrs[1] = addr + in_bytes;
+ }
+ ao_usb_disable_ep(ao_usb_epn_in(n, 1));
}
static void
ao_usb_disable_epn(uint8_t n)
{
- ao_usb_disable_ep(ao_usb_epn_out(n));
- ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]);
- ao_usb_disable_ep(ao_usb_epn_in(n));
- ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]);
+ ao_usb_disable_ep(ao_usb_epn_out(n, 0));
+ ao_usb_disable_ep(ao_usb_epn_out(n, 1));
+ ao_usb_disable_ep(ao_usb_epn_in(n, 0));
+ ao_usb_disable_ep(ao_usb_epn_in(n, 1));
}
static void
/* Set up the INT end point */
ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL);
-
+
/* Set up the OUT end point */
- ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL);
+ ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, ao_usb_out_rx_buffer, 0, NULL);
+
+ /* Set the current RX pointer to the *other* buffer so that when buffer 0 gets
+ * data, we'll switch to it and pull bytes from there
+ */
+ ao_usb_out_rx_cur = 1;
/* Set up the IN end point */
- ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer);
+ ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, ao_usb_in_tx_buffer);
+ ao_usb_in_tx_cur = 0;
ao_usb_running = 1;
}
ao_usb_in_pending = 1;
if (ao_usb_tx_count != AO_USB_IN_SIZE)
ao_usb_in_flushed = 1;
- memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count);
- ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer, ao_usb_tx_count);
+ ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP, 0), ao_usb_in_tx_buffer[ao_usb_in_tx_cur], ao_usb_tx_count);
+ ao_usb_in_tx_cur = 1 - ao_usb_in_tx_cur;
ao_usb_tx_count = 0;
_tx_dbg0("in_send end");
}
_ao_usb_in_wait();
ao_usb_in_flushed = 0;
- ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c;
+ ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c;
/* Send the packet when full */
if (ao_usb_tx_count == AO_USB_IN_SIZE) {
_rx_dbg1("out_recv count", ao_usb_rx_count);
debug ("recv %d\n", ao_usb_rx_count);
- debug_data("Fill OUT len %d:", ao_usb_rx_count);
- memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count);
- debug_data("\n");
+ debug_data("Fill OUT len %d\n", ao_usb_rx_count);
ao_usb_rx_pos = 0;
+ ao_usb_out_rx_cur = 1 - ao_usb_out_rx_cur;
/* ACK the packet */
- ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE);
+ ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_out_rx_cur], AO_USB_OUT_SIZE);
}
int
}
/* Pull a character out of the fifo */
- c = ao_usb_rx_buffer[ao_usb_rx_pos++];
+ c = ao_usb_out_rx_buffer[ao_usb_out_rx_cur][ao_usb_rx_pos++];
return c;
}
/* Enable USB PHY */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD);
-
+
/* Turn on USB PLL */
lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD);
dbg[dbg_i].primask = primask;
#if TX_DBG
dbg[dbg_i].in_count = in_count;
- dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP);
+ dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP, 0);
dbg[dbg_i].in_pending = ao_usb_in_pending;
dbg[dbg_i].tx_count = ao_usb_tx_count;
dbg[dbg_i].in_flushed = ao_usb_in_flushed;
dbg[dbg_i].rx_count = ao_usb_rx_count;
dbg[dbg_i].rx_pos = ao_usb_rx_pos;
dbg[dbg_i].out_avail = ao_usb_out_avail;
- dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP);
+ dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP, 0);
#endif
if (++dbg_i == NUM_USB_DBG)
dbg_i = 0;
--- /dev/null
+ao_product.h
+microsplash-*
--- /dev/null
+#
+# Tiny AltOS build
+#
+#
+vpath % ../attiny:../drivers:../kernel:../product:..
+vpath ao-make-product.5c ../util
+vpath make-altitude-pa ../util
+
+include ../avr/Makefile.defs
+
+PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
+PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
+
+MCU=attiny85
+DUDECPUTYPE=t85
+#PROGRAMMER=stk500v2 -P usb
+LOADSLOW=-i 32 -B 32
+LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
+
+#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
+
+ALTOS_SRC = \
+ ao_micropeak.c \
+ ao_spi_attiny.c \
+ ao_led.c \
+ ao_clock.c \
+ ao_ms5607.c \
+ ao_exti.c \
+ ao_convert_pa.c \
+ ao_report_micro.c \
+ ao_notask.c \
+ ao_eeprom_tiny.c \
+ ao_panic.c \
+ ao_log_micro.c \
+ ao_async.c \
+ ao_microflight.c \
+ ao_microkalman.c
+
+INC=\
+ ao.h \
+ ao_pins.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_exti.h \
+ ao_ms5607.h \
+ ao_log_micro.h \
+ ao_micropeak.h \
+ altitude-pa.h
+
+IDPRODUCT=0
+PRODUCT=MicroSplash-v0.1
+PRODUCT_DEF=-DMICROPEAK
+CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
+CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
+
+NICKLE=nickle
+
+PROG=microsplash-v1.0
+
+SRC=$(ALTOS_SRC)
+OBJ=$(SRC:.c=.o)
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf " $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+all: $(PROG) $(PROG).hex
+
+CHECK=sh ../util/check-avr-mem
+
+$(PROG): Makefile $(OBJ)
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
+ $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
+
+$(PROG).hex: $(PROG)
+ avr-size $(PROG)
+ $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
+
+
+load: $(PROG).hex
+ $(LOADCMD) $(LOADARG)$(PROG).hex
+
+load-slow: $(PROG).hex
+ $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex
+
+ao_product.h: ao-make-product.5c ../Version
+ $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+ao_product.o: ao_product.c ao_product.h
+
+%.o : %.c $(INC)
+ $(call quiet,CC) -c $(CFLAGS) $<
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROG) $(PROG).hex
+ rm -f ao_product.h
+
+
+publish: $(PROG).hex
+ cp -a $(PROG).hex $(PUBLISH_FILE)
+
+load-product:
+ $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
+
+load-product-slow:
+ $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
+
+../altitude-pa.h: make-altitude-pa
+ nickle $< > $@
+
+install:
+
+uninstall:
+
+$(OBJ): ao_product.h $(INC)
--- /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.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+#include <avr/pgmspace.h>
+
+#define AO_LED_ORANGE (1<<4)
+#define AO_LED_SERIAL 4
+#define AO_LED_PANIC AO_LED_ORANGE
+#define AO_LED_REPORT AO_LED_ORANGE
+#define LEDS_AVAILABLE (AO_LED_ORANGE)
+#define USE_SERIAL_1_STDIN 0
+#define HAS_USB 0
+#define PACKET_HAS_SLAVE 0
+#define HAS_SERIAL_1 0
+#define HAS_TASK 0
+#define HAS_MS5607 1
+#define HAS_MS5611 0
+#define HAS_EEPROM 0
+#define HAS_BEEP 0
+#define AVR_CLOCK 250000UL
+
+/* SPI */
+#define SPI_PORT PORTB
+#define SPI_PIN PINB
+#define SPI_DIR DDRB
+#define AO_MS5607_CS_PORT PORTB
+#define AO_MS5607_CS_PIN 3
+
+/* MS5607 */
+#define AO_MS5607_SPI_INDEX 0
+#define AO_MS5607_MISO_PORT PORTB
+#define AO_MS5607_MISO_PIN 0
+#define AO_MS5607_BARO_OVERSAMPLE 4096
+#define AO_MS5607_TEMP_OVERSAMPLE 1024
+
+/* I2C */
+#define I2C_PORT PORTB
+#define I2C_PIN PINB
+#define I2C_DIR DDRB
+#define I2C_PIN_SCL PINB2
+#define I2C_PIN_SDA PINB0
+
+#define AO_CONST_ATTRIB PROGMEM
+typedef int32_t alt_t;
+#define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o]))
+
+#define AO_ALT_VALUE(x) ((x) * (alt_t) 10)
+
+/* Pressure change (in Pa) to detect boost */
+#ifndef BOOST_DETECT
+#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */
+#endif
+
+#endif /* _AO_PINS_H_ */
+++ /dev/null
-ao_product.h
-microwater-*
+++ /dev/null
-#
-# Tiny AltOS build
-#
-#
-vpath % ../attiny:../drivers:../kernel:../product:..
-vpath ao-make-product.5c ../util
-vpath make-altitude-pa ../util
-
-include ../avr/Makefile.defs
-
-PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries
-PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex
-
-MCU=attiny85
-DUDECPUTYPE=t85
-#PROGRAMMER=stk500v2 -P usb
-LOADSLOW=-i 32 -B 32
-LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w:
-
-#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x
-
-ALTOS_SRC = \
- ao_micropeak.c \
- ao_spi_attiny.c \
- ao_led.c \
- ao_clock.c \
- ao_ms5607.c \
- ao_exti.c \
- ao_convert_pa.c \
- ao_report_micro.c \
- ao_notask.c \
- ao_eeprom_tiny.c \
- ao_panic.c \
- ao_log_micro.c \
- ao_async.c \
- ao_microflight.c \
- ao_microkalman.c
-
-INC=\
- ao.h \
- ao_pins.h \
- ao_arch.h \
- ao_arch_funcs.h \
- ao_exti.h \
- ao_ms5607.h \
- ao_log_micro.h \
- ao_micropeak.h \
- altitude-pa.h
-
-IDPRODUCT=0
-PRODUCT=MicroWater-v0.1
-PRODUCT_DEF=-DMICROPEAK
-CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product
-CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY
-
-NICKLE=nickle
-
-PROG=microwater-v0.1
-
-SRC=$(ALTOS_SRC)
-OBJ=$(SRC:.c=.o)
-
-V=0
-# The user has explicitly enabled quiet compilation.
-ifeq ($(V),0)
-quiet = @printf " $1 $2 $@\n"; $($1)
-endif
-# Otherwise, print the full command line.
-quiet ?= $($1)
-
-all: $(PROG) $(PROG).hex
-
-CHECK=sh ../util/check-avr-mem
-
-$(PROG): Makefile $(OBJ)
- $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ)
- $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1)
-
-$(PROG).hex: $(PROG)
- avr-size $(PROG)
- $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@
-
-
-load: $(PROG).hex
- $(LOADCMD) $(LOADARG)$(PROG).hex
-
-load-slow: $(PROG).hex
- $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex
-
-ao_product.h: ao-make-product.5c ../Version
- $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
-
-ao_product.o: ao_product.c ao_product.h
-
-%.o : %.c $(INC)
- $(call quiet,CC) -c $(CFLAGS) $<
-
-distclean: clean
-
-clean:
- rm -f *.o $(PROG) $(PROG).hex
- rm -f ao_product.h
-
-
-publish: $(PROG).hex
- cp -a $(PROG).hex $(PUBLISH_FILE)
-
-load-product:
- $(LOADCMD) $(LOADARG)$(PUBLISH_FILE)
-
-load-product-slow:
- $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE)
-
-../altitude-pa.h: make-altitude-pa
- nickle $< > $@
-
-install:
-
-uninstall:
-
-$(OBJ): ao_product.h $(INC)
+++ /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.
- */
-
-#ifndef _AO_PINS_H_
-#define _AO_PINS_H_
-#include <avr/pgmspace.h>
-
-#define AO_LED_ORANGE (1<<4)
-#define AO_LED_SERIAL 4
-#define AO_LED_PANIC AO_LED_ORANGE
-#define AO_LED_REPORT AO_LED_ORANGE
-#define LEDS_AVAILABLE (AO_LED_ORANGE)
-#define USE_SERIAL_1_STDIN 0
-#define HAS_USB 0
-#define PACKET_HAS_SLAVE 0
-#define HAS_SERIAL_1 0
-#define HAS_TASK 0
-#define HAS_MS5607 1
-#define HAS_MS5611 0
-#define HAS_EEPROM 0
-#define HAS_BEEP 0
-#define AVR_CLOCK 250000UL
-
-/* SPI */
-#define SPI_PORT PORTB
-#define SPI_PIN PINB
-#define SPI_DIR DDRB
-#define AO_MS5607_CS_PORT PORTB
-#define AO_MS5607_CS_PIN 3
-
-/* MS5607 */
-#define AO_MS5607_SPI_INDEX 0
-#define AO_MS5607_MISO_PORT PORTB
-#define AO_MS5607_MISO_PIN 0
-#define AO_MS5607_BARO_OVERSAMPLE 4096
-#define AO_MS5607_TEMP_OVERSAMPLE 1024
-
-/* I2C */
-#define I2C_PORT PORTB
-#define I2C_PIN PINB
-#define I2C_DIR DDRB
-#define I2C_PIN_SCL PINB2
-#define I2C_PIN_SDA PINB0
-
-#define AO_CONST_ATTRIB PROGMEM
-typedef int32_t alt_t;
-#define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o]))
-
-#define AO_ALT_VALUE(x) ((x) * (alt_t) 10)
-
-/* Pressure change (in Pa) to detect boost */
-#ifndef BOOST_DETECT
-#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */
-#endif
-
-#endif /* _AO_PINS_H_ */
ao_spi_put(uint8_t spi_index);
void
-ao_spi_send(void *block, uint16_t len, uint8_t spi_index);
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index);
void
ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
stm_moder_set(port, bit, STM_MODER_OUTPUT); \
stm_otyper_set(port, bit, STM_OTYPER_PUSH_PULL); \
} while (0)
-
+
void
ao_led_init(uint16_t enable)
{
_ao_usart_pollchar(struct ao_stm_usart *usart)
{
int c;
-
+
if (ao_fifo_empty(usart->rx_fifo))
c = AO_READ_AGAIN;
else {
return (char) c;
}
+static inline uint8_t
+_ao_usart_sleep(struct ao_stm_usart *usart)
+{
+ return ao_sleep(&usart->rx_fifo);
+}
+
void
ao_usart_putchar(struct ao_stm_usart *usart, char c)
{
ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600);
}
+void
+ao_usart_set_flow(struct ao_stm_usart *usart)
+{
+ usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) |
+ (1 << STM_USART_CR3_RTSE));
+}
+
#if HAS_SERIAL_1
struct ao_stm_usart ao_stm_usart1;
return _ao_usart_pollchar(&ao_stm_usart1);
}
+uint8_t
+_ao_serial1_sleep(void)
+{
+ return _ao_usart_sleep(&ao_stm_usart1);
+}
+
+void
+ao_serial1_drain(void)
+{
+ ao_usart_drain(&ao_stm_usart1);
+}
+
void
ao_serial1_set_speed(uint8_t speed)
{
return _ao_usart_pollchar(&ao_stm_usart2);
}
+uint8_t
+_ao_serial2_sleep(void)
+{
+ return _ao_usart_sleep(&ao_stm_usart2);
+}
+
+void
+ao_serial2_drain(void)
+{
+ ao_usart_drain(&ao_stm_usart2);
+}
+
void
ao_serial2_set_speed(uint8_t speed)
{
return _ao_usart_pollchar(&ao_stm_usart3);
}
+uint8_t
+_ao_serial3_sleep(void)
+{
+ return _ao_usart_sleep(&ao_stm_usart3);
+}
+
void
ao_serial3_set_speed(uint8_t speed)
{
stm_nvic_set_enable(STM_ISR_USART1_POS);
stm_nvic_set_priority(STM_ISR_USART1_POS, 4);
-#if USE_SERIAL_1_STDIN
+#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN
ao_add_stdio(_ao_serial1_pollchar,
ao_serial1_putchar,
NULL);
stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7);
stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7);
+#if USE_SERIAL_2_FLOW
+ stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7);
+ stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7);
+#endif
#else
#if SERIAL_2_PD5_PD6
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
stm_afr_set(&stm_gpiod, 5, STM_AFR_AF7);
stm_afr_set(&stm_gpiod, 6, STM_AFR_AF7);
+#if USE_SERIAL_2_FLOW
+#error "Don't know how to set flowcontrol for serial 2 on PD"
+#endif
#else
#error "No SERIAL_2 port configuration specified"
-#endif
+#endif
#endif
/* Enable USART */
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN);
ao_stm_usart2.reg = &stm_usart2;
ao_usart_init(&ao_stm_usart2);
+#if USE_SERIAL_2_FLOW
+ ao_usart_set_flow(&ao_stm_usart2);
+#endif
stm_nvic_set_enable(STM_ISR_USART2_POS);
stm_nvic_set_priority(STM_ISR_USART2_POS, 4);
-#if USE_SERIAL_2_STDIN
+#if USE_SERIAL_2_STDIN && !DELAY_SERIAL_2_STDIN
ao_add_stdio(_ao_serial2_pollchar,
ao_serial2_putchar,
NULL);
stm_nvic_set_enable(STM_ISR_USART3_POS);
stm_nvic_set_priority(STM_ISR_USART3_POS, 4);
-#if USE_SERIAL_3_STDIN
+#if USE_SERIAL_3_STDIN && !DELAY_SERIAL_3_STDIN
ao_add_stdio(_ao_serial3_pollchar,
ao_serial3_putchar,
NULL);
#endif
#endif
}
-
-
static uint8_t spi_dev_null;
void
-ao_spi_send(void *block, uint16_t len, uint8_t spi_index)
+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;
/* Set up the transmit DMA to deliver data */
ao_dma_set_transfer(mosi_dma_index,
&stm_spi->dr,
- block,
+ (void *) block,
len,
(0 << STM_DMA_CCR_MEM2MEM) |
(STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) |
--- /dev/null
+include $(TOPDIR)/stmf0/Makefile-stmf0.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_flash_pins.h \
+ ao_flash_stm_pins.h \
+ ao_flash_task.h \
+ ao_pins.h \
+ ao_product.h \
+ Makefile
+
+#
+# Common AltOS sources
+#
+SRC = \
+ ao_interrupt.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_boot_pin.c \
+ ao_product.c \
+ ao_notask.c \
+ ao_timer.c \
+ ao_usb_stm.c \
+ ao_flash_stm.c \
+ ao_flash_task.c \
+ ao_flash_loader_stm.c
+
+OBJ=$(SRC:.c=.o)
+
+PRODUCT=AltosFlash
+PRODUCT_DEF=-DALTOS_FLASH
+IDPRODUCT=0x000a
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld
+
+PROGNAME=altos-flash
+PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
+
+$(PROG): Makefile $(OBJ) altos-loader.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+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:
+ rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+include $(TOPDIR)/Makedefs
+
+vpath % $(TOPDIR)/stmf0:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR):$(TOPDIR)/math
+vpath make-altitude $(TOPDIR)/util
+vpath make-kalman $(TOPDIR)/util
+vpath kalman.5c $(TOPDIR)/kalman
+vpath kalman_filter.5c $(TOPDIR)/kalman
+vpath load_csv.5c $(TOPDIR)/kalman
+vpath matrix.5c $(TOPDIR)/kalman
+vpath ao-make-product.5c $(TOPDIR)/util
+
+.SUFFIXES: .elf .ihx
+
+.elf.ihx:
+ $(ELFTOHEX) --output=$@ $*.elf
+
+ifndef VERSION
+include $(TOPDIR)/Version
+endif
+
+ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex
+CC=$(ARM_CC)
+
+WARN_FLAGS=-Wall -Wextra -Werror
+
+AO_CFLAGS=-I. -I$(TOPDIR)/stmf0 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math $(PDCLIB_INCLUDES)
+STMF0_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\
+ -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS)
+
+NICKLE=nickle
+
+LIBS=$(PDCLIB_LIBS_M0) -lgcc
+
+V=0
+# The user has explicitly enabled quiet compilation.
+ifeq ($(V),0)
+quiet = @printf " $1 $2 $@\n"; $($1)
+endif
+# Otherwise, print the full command line.
+quiet ?= $($1)
+
+.c.o:
+ $(call quiet,CC) -c $(CFLAGS) -o $@ $<
--- /dev/null
+ifndef TOPDIR
+TOPDIR=..
+endif
+
+include $(TOPDIR)/stmf0/Makefile-stmf0.defs
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos.ld
+
+.DEFAULT_GOAL=all
--- /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.
+ */
+
+MEMORY {
+ rom : ORIGIN = 0x08000000, LENGTH = 4K
+ ram : ORIGIN = 0x20000000, LENGTH = 6K
+}
+
+INCLUDE registers.ld
+
+EXTERN (stm_interrupt_vector)
+
+SECTIONS {
+ /*
+ * Rom contents
+ */
+
+ .interrupt : {
+ __text_start__ = .;
+ *(.interrupt) /* Interrupt vectors */
+ } > rom
+
+ .text ORIGIN(rom) + 0x100 : {
+ ao_romconfig.o(.romconfig*)
+ ao_product.o(.romconfig*)
+
+ *(.text*) /* Executable code */
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ *(.rodata*) /* Constants */
+ } > rom
+ __text_end__ = .;
+
+ /* Boot data which must live at the start of ram so that
+ * the application and bootloader share the same addresses.
+ * This must be all uninitialized data
+ */
+ .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : {
+ __boot_start__ = .;
+ *(.boot)
+ __boot_end__ = .;
+ } >ram
+
+ /* Functions placed in RAM (required for flashing)
+ *
+ * Align to 8 bytes as that's what the ARM likes text
+ * segment alignments to be, and if we don't, then
+ * we end up with a mismatch between the location in
+ * ROM and the desired location in RAM. I don't
+ * entirely understand this, but at least this appears
+ * to work...
+ */
+
+ .textram BLOCK(8): {
+ __data_start__ = .;
+ __text_ram_start__ = .;
+ *(.ramtext)
+ __text_ram_end = .;
+ } >ram AT>rom
+
+ /* Data -- relocated to RAM, but written to ROM
+ */
+ .data : {
+ *(.data) /* initialized data */
+ __data_end__ = .;
+ } >ram AT>rom
+
+
+ .bss : {
+ __bss_start__ = .;
+ *(.bss)
+ *(COMMON)
+ __bss_end__ = .;
+ } >ram
+
+ PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
+ PROVIDE(end = .);
+}
+
+ENTRY(start);
+
+
--- /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.
+ */
+
+MEMORY {
+ rom (rx) : ORIGIN = 0x08001000, LENGTH = 28K
+ ram (!w) : ORIGIN = 0x20000000, LENGTH = 6k - 128
+ stack (!w) : ORIGIN = 0x20000000 + 6k - 128, LENGTH = 128
+}
+
+INCLUDE registers.ld
+
+EXTERN (stm_interrupt_vector)
+
+SECTIONS {
+ /*
+ * Rom contents
+ */
+
+ .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
+ __interrupt_start__ = .;
+ __interrupt_rom__ = ORIGIN(rom);
+ *(.interrupt) /* Interrupt vectors */
+ __interrupt_end__ = .;
+ } > ram
+
+ .text ORIGIN(rom) + 0x100 : {
+ __text_start__ = .;
+
+ /* Ick. What I want is to specify the
+ * addresses of some global constants so
+ * that I can find them across versions
+ * of the application. I can't figure out
+ * how to make gnu ld do that, so instead
+ * we just load the two files that include
+ * these defines in the right order here and
+ * expect things to 'just work'. Don't change
+ * the contents of those files, ok?
+ */
+ ao_romconfig.o(.romconfig*)
+ ao_product.o(.romconfig*)
+
+ *(.text*) /* Executable code */
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ *(.rodata*) /* Constants */
+
+ } > rom
+ __text_end__ = .;
+
+ /* Boot data which must live at the start of ram so that
+ * the application and bootloader share the same addresses.
+ * This must be all uninitialized data
+ */
+ .boot (NOLOAD) : {
+ __boot_start__ = .;
+ *(.boot)
+ . = ALIGN(4);
+ __boot_end__ = .;
+ } >ram
+
+ /* Data -- relocated to RAM, but written to ROM
+ */
+ .data : {
+ __data_start__ = .;
+ *(.data) /* initialized data */
+ . = ALIGN(4);
+ __data_end__ = .;
+ } >ram AT>rom
+
+ .bss : {
+ __bss_start__ = .;
+ *(.bss)
+ *(COMMON)
+ . = ALIGN(4);
+ __bss_end__ = .;
+ } >ram
+
+ PROVIDE(end = .);
+
+ PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
+}
+
+ENTRY(start);
+
+
--- /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.
+ */
+
+#include <ao.h>
+#include <ao_adc_fast.h>
+
+uint16_t ao_adc_ring[AO_ADC_RING_SIZE];
+
+uint16_t ao_adc_ring_head, ao_adc_ring_tail;
+uint8_t ao_adc_running;
+
+/*
+ * Callback from DMA ISR
+ *
+ * Mark time in ring, shut down DMA engine
+ */
+static void ao_adc_dma_done(int index)
+{
+ (void) index;
+ ao_adc_ring_head += AO_ADC_RING_CHUNK;
+ if (ao_adc_ring_head == AO_ADC_RING_SIZE)
+ ao_adc_ring_head = 0;
+ ao_adc_running = 0;
+ ao_wakeup(&ao_adc_ring_head);
+ ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+}
+
+void
+_ao_adc_start(void)
+{
+ uint16_t *buf;
+
+ if (ao_adc_running)
+ return;
+ if (_ao_adc_space() < AO_ADC_RING_CHUNK)
+ return;
+ ao_adc_running = 1;
+ buf = ao_adc_ring + ao_adc_ring_head;
+ stm_adc.isr = 0;
+ ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1),
+ &stm_adc.dr,
+ buf,
+ AO_ADC_RING_CHUNK,
+ (0 << STM_DMA_CCR_MEM2MEM) |
+ (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) |
+ (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) |
+ (STM_DMA_CCR_PSIZE_16 << 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));
+ 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));
+
+ stm_adc.cr |= (1 << STM_ADC_CR_ADSTART);
+}
+
+void
+ao_adc_init(void)
+{
+ uint32_t chselr;
+ int i;
+
+ /* Reset ADC */
+ stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST);
+ stm_rcc.apb2rstr &= ~(1 << STM_RCC_APB2RSTR_ADCRST);
+
+ /* Turn on ADC pins */
+ stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR;
+
+#ifdef AO_ADC_PIN0_PORT
+ stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN1_PORT
+ stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN2_PORT
+ stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN3_PORT
+ stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN4_PORT
+ stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN5_PORT
+ stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN6_PORT
+ stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN7_PORT
+ stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG);
+#endif
+#ifdef AO_ADC_PIN24_PORT
+ #error "Too many ADC ports"
+#endif
+
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN);
+
+ chselr = 0;
+#if AO_NUM_ADC > 0
+ chselr |= (1 << AO_ADC_PIN0_CH);
+#endif
+#if AO_NUM_ADC > 1
+ chselr |= (1 << AO_ADC_PIN1_CH);
+#endif
+#if AO_NUM_ADC > 2
+ chselr |= (1 << AO_ADC_PIN2_CH);
+#endif
+#if AO_NUM_ADC > 3
+ chselr |= (1 << AO_ADC_PIN3_CH);
+#endif
+#if AO_NUM_ADC > 4
+ chselr |= (1 << AO_ADC_PIN4_CH);
+#endif
+#if AO_NUM_ADC > 5
+ chselr |= (1 << AO_ADC_PIN5_CH);
+#endif
+#if AO_NUM_ADC > 6
+ chselr |= (1 << AO_ADC_PIN6_CH);
+#endif
+#if AO_NUM_ADC > 7
+ chselr |= (1 << AO_ADC_PIN7_CH);
+#endif
+#if AO_NUM_ADC > 8
+#error Need more ADC defines
+#endif
+ stm_adc.chselr = chselr;
+
+ /* Set the clock */
+ stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE;
+
+ /* Shortest sample time */
+ stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP;
+
+ /* 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;
+ }
+
+ /* Enable */
+ stm_adc.cr |= (1 << STM_ADC_CR_ADEN);
+ while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0)
+ ;
+
+ stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) |
+ (0 << STM_ADC_CFGR1_AWDEN) |
+ (0 << STM_ADC_CFGR1_AWDSGL) |
+ (0 << STM_ADC_CFGR1_DISCEN) |
+ (0 << STM_ADC_CFGR1_AUTOOFF) |
+ (1 << STM_ADC_CFGR1_WAIT) |
+ (1 << STM_ADC_CFGR1_CONT) |
+ (0 << STM_ADC_CFGR1_OVRMOD) |
+ (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) |
+ (0 << STM_ADC_CFGR1_ALIGN) |
+ (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) |
+ (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) |
+ (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) |
+ (1 << STM_ADC_CFGR1_DMAEN));
+ stm_adc.ccr = 0;
+
+ /* Clear any stale status bits */
+ stm_adc.isr = 0;
+
+ /* Turn on syscfg */
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+ /* Set ADC to use DMA channel 1 (option 1) */
+ stm_syscfg.cfgr1 &= ~(1 << STM_SYSCFG_CFGR1_ADC_DMA_RMP);
+
+ ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1));
+ ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done);
+}
--- /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_ADC_FAST_H_
+#define _AO_ADC_FAST_H_
+
+void
+ao_adc_read(uint16_t *dest, int len);
+
+void
+ao_adc_init(void);
+
+/* Total ring size in samples */
+#define AO_ADC_RING_SIZE 256
+/* Number of samples fetched per ao_adc_start call */
+#define AO_ADC_RING_CHUNK (AO_ADC_RING_SIZE >> 1)
+
+extern uint16_t ao_adc_ring[AO_ADC_RING_SIZE];
+
+#define ao_adc_ring_step(pos,inc) (((pos) + (inc)) & (AO_ADC_RING_SIZE - 1))
+
+extern uint16_t ao_adc_ring_head, ao_adc_ring_tail;
+extern uint8_t ao_adc_running;
+
+void
+_ao_adc_start(void);
+
+static inline uint16_t
+_ao_adc_remain(void)
+{
+ if (ao_adc_ring_tail > ao_adc_ring_head)
+ return AO_ADC_RING_SIZE - ao_adc_ring_tail;
+ return ao_adc_ring_head - ao_adc_ring_tail;
+}
+
+static inline uint16_t
+_ao_adc_space(void)
+{
+ if (ao_adc_ring_head == ao_adc_ring_tail)
+ return AO_ADC_RING_SIZE;
+ if (ao_adc_ring_head > ao_adc_ring_tail)
+ return AO_ADC_RING_SIZE - ao_adc_ring_head;
+ return ao_adc_ring_tail - ao_adc_ring_head;
+}
+
+static inline uint16_t *
+ao_adc_get(uint16_t n)
+{
+ if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE)
+ ao_panic(AO_PANIC_ADC);
+ ao_arch_block_interrupts();
+ while (_ao_adc_remain() < n) {
+ if (!ao_adc_running)
+ _ao_adc_start();
+ ao_sleep(&ao_adc_ring_head);
+ }
+ ao_arch_release_interrupts();
+ return &ao_adc_ring[ao_adc_ring_tail];
+}
+
+static inline void
+ao_adc_ack(uint16_t n)
+{
+ if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE)
+ ao_panic(AO_PANIC_ADC);
+ ao_arch_block_interrupts();
+ ao_adc_ring_tail += n;
+ if (ao_adc_ring_tail == AO_ADC_RING_SIZE)
+ ao_adc_ring_tail = 0;
+ if (!ao_adc_running && _ao_adc_space() >= AO_ADC_RING_CHUNK)
+ _ao_adc_start();
+ ao_arch_release_interrupts();
+}
+
+#endif /* _AO_ADC_FAST_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.
+ */
+
+#ifndef _AO_ARCH_H_
+#define _AO_ARCH_H_
+
+#include <stdio.h>
+#include <stm32f0.h>
+
+/*
+ * STM32F0 definitions and code fragments for AltOS
+ */
+
+#define AO_STACK_SIZE 512
+
+#define AO_LED_TYPE uint16_t
+
+#ifndef AO_TICK_TYPE
+#define AO_TICK_TYPE uint16_t
+#define AO_TICK_SIGNED int16_t
+#endif
+
+#define AO_PORT_TYPE uint16_t
+
+/* Various definitions to make GCC look more like SDCC */
+
+#define ao_arch_naked_declare __attribute__((naked))
+#define ao_arch_naked_define
+#define __pdata
+#define __data
+#define __xdata
+#define __code const
+#define __reentrant
+#define __interrupt(n)
+#define __at(n)
+
+#define ao_arch_reboot() \
+ (stm_scb.aircr = ((STM_SCB_AIRCR_VECTKEY_KEY << STM_SCB_AIRCR_VECTKEY) | \
+ (1 << STM_SCB_AIRCR_SYSRESETREQ)))
+
+#define ao_arch_nop() asm("nop")
+
+#define ao_arch_interrupt(n) /* nothing */
+
+#undef putchar
+#undef getchar
+#define putchar(c) ao_putchar(c)
+#define getchar ao_getchar
+
+extern void putchar(char c);
+extern char getchar(void);
+extern void ao_avr_stdio_init(void);
+
+
+/*
+ * ao_romconfig.c
+ */
+
+#define AO_ROMCONFIG_VERSION 2
+
+#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const
+
+extern const uint16_t ao_romconfig_version;
+extern const uint16_t ao_romconfig_check;
+extern const uint16_t ao_serial_number;
+extern const uint32_t ao_radio_cal;
+
+#define ao_arch_task_members\
+ uint32_t *sp; /* saved stack pointer */
+
+#define ao_arch_block_interrupts() asm("cpsid i")
+#define ao_arch_release_interrupts() asm("cpsie i")
+
+/*
+ * ao_timer.c
+ *
+ * For the stm32f042, we want to use the USB-based HSI48 clock
+ */
+
+#if AO_HSI48
+
+#define AO_SYSCLK 48000000
+#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER)
+
+#endif
+
+#if AO_HSE || AO_HSI
+
+#if AO_HSE
+#define AO_PLLSRC AO_HSE
+#else
+#define AO_PLLSRC STM_HSI_FREQ
+#endif
+
+#define AO_PLLVCO (AO_PLLSRC * AO_PLLMUL)
+#define AO_SYSCLK (AO_PLLVCO / AO_PLLDIV)
+
+#endif
+
+#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER)
+#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER)
+#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER)
+#define AO_SYSTICK (AO_HCLK)
+
+#if AO_APB1_PRESCALER == 1
+#define AO_TIM23467_CLK AO_PCLK1
+#else
+#define AO_TIM23467_CLK (2 * AO_PCLK1)
+#endif
+
+#if AO_APB2_PRESCALER == 1
+#define AO_TIM91011_CLK AO_PCLK2
+#else
+#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
+
+void ao_lcd_stm_init(void);
+
+void ao_lcd_font_init(void);
+
+void ao_lcd_font_string(char *s);
+
+extern const uint32_t ao_radio_cal;
+
+void
+ao_adc_init();
+
+/* ADC maximum reported value */
+#define AO_ADC_MAX 4095
+
+#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x08001000)
+#define AO_BOOT_APPLICATION_BOUND ((uint32_t *) (0x08000000 + stm_flash_size()))
+#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x08000000)
+#define HAS_BOOT_LOADER 1
+
+#endif /* _AO_ARCH_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.
+ */
+
+#ifndef _AO_ARCH_FUNCS_H_
+#define _AO_ARCH_FUNCS_H_
+
+/* ao_spi_stm.c
+ */
+
+/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
+
+#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_FAST AO_SPI_SPEED_8MHz
+
+/* Companion bus wants something no faster than 200kHz */
+
+#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz
+
+#define AO_SPI_CONFIG_1 0x00
+#define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1
+#define AO_SPI_2_CONFIG_PB13_PB14_PB15 AO_SPI_CONFIG_1
+
+#define AO_SPI_CONFIG_2 0x04
+#define AO_SPI_1_CONFIG_PB3_PB4_PB5 AO_SPI_CONFIG_2
+#define AO_SPI_2_CONFIG_PD1_PD3_PD4 AO_SPI_CONFIG_2
+
+#define AO_SPI_CONFIG_3 0x08
+#define AO_SPI_1_CONFIG_PE13_PE14_PE15 AO_SPI_CONFIG_3
+
+#define AO_SPI_CONFIG_NONE 0x0c
+
+#define AO_SPI_INDEX_MASK 0x01
+#define AO_SPI_CONFIG_MASK 0x0c
+
+#define AO_SPI_1_PA5_PA6_PA7 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA5_PA6_PA7)
+#define AO_SPI_1_PB3_PB4_PB5 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PB3_PB4_PB5)
+#define AO_SPI_1_PE13_PE14_PE15 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PE13_PE14_PE15)
+
+#define AO_SPI_2_PB13_PB14_PB15 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PB13_PB14_PB15)
+#define AO_SPI_2_PD1_PD3_PD4 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PD1_PD3_PD4)
+
+#define AO_SPI_INDEX(id) ((id) & AO_SPI_INDEX_MASK)
+#define AO_SPI_CONFIG(id) ((id) & AO_SPI_CONFIG_MASK)
+
+uint8_t
+ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id);
+
+void
+ao_spi_get(uint8_t spi_index, uint32_t speed);
+
+void
+ao_spi_put(uint8_t spi_index);
+
+void
+ao_spi_send(const void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_recv(void *block, uint16_t len, uint8_t spi_index);
+
+void
+ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index);
+
+extern uint16_t ao_spi_speed[STM_NUM_SPI];
+
+void
+ao_spi_init(void);
+
+#define ao_spi_set_cs(reg,mask) ((reg)->bsrr = ((uint32_t) (mask)) << 16)
+#define ao_spi_clr_cs(reg,mask) ((reg)->bsrr = (mask))
+
+#define ao_spi_get_mask(reg,mask,bus, speed) do { \
+ ao_spi_get(bus, speed); \
+ ao_spi_set_cs(reg,mask); \
+ } while (0)
+
+static inline uint8_t
+ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id)
+{
+ if (!ao_spi_try_get(bus, speed, task_id))
+ return 0;
+ ao_spi_set_cs(reg, mask);
+ return 1;
+}
+
+#define ao_spi_put_mask(reg,mask,bus) do { \
+ ao_spi_clr_cs(reg,mask); \
+ ao_spi_put(bus); \
+ } while (0)
+
+#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)
+
+#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)
+
+#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
+
+#define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
+
+#define ao_enable_output(port,bit,pin,v) do { \
+ ao_enable_port(port); \
+ ao_gpio_set(port, bit, pin, v); \
+ stm_moder_set(port, bit, STM_MODER_OUTPUT);\
+ } while (0)
+
+#define ao_gpio_set_mode(port,bit,mode) do { \
+ if (mode == AO_EXTI_MODE_PULL_UP) \
+ stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP); \
+ else if (mode == AO_EXTI_MODE_PULL_DOWN) \
+ stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN); \
+ else \
+ stm_pupdr_set(port, bit, STM_PUPDR_NONE); \
+ } while (0)
+
+#define ao_enable_input(port,bit,mode) do { \
+ ao_enable_port(port); \
+ stm_moder_set(port, bit, STM_MODER_INPUT); \
+ ao_gpio_set_mode(port, bit, mode); \
+ } while (0)
+
+#define ao_enable_cs(port,bit) do { \
+ stm_gpio_set((port), bit, 1); \
+ stm_moder_set((port), bit, STM_MODER_OUTPUT); \
+ } while (0)
+
+#define ao_spi_init_cs(port, mask) do { \
+ ao_enable_port(port); \
+ if ((mask) & 0x0001) ao_enable_cs(port, 0); \
+ if ((mask) & 0x0002) ao_enable_cs(port, 1); \
+ if ((mask) & 0x0004) ao_enable_cs(port, 2); \
+ if ((mask) & 0x0008) ao_enable_cs(port, 3); \
+ if ((mask) & 0x0010) ao_enable_cs(port, 4); \
+ if ((mask) & 0x0020) ao_enable_cs(port, 5); \
+ if ((mask) & 0x0040) ao_enable_cs(port, 6); \
+ if ((mask) & 0x0080) ao_enable_cs(port, 7); \
+ if ((mask) & 0x0100) ao_enable_cs(port, 8); \
+ if ((mask) & 0x0200) ao_enable_cs(port, 9); \
+ if ((mask) & 0x0400) ao_enable_cs(port, 10);\
+ if ((mask) & 0x0800) ao_enable_cs(port, 11);\
+ if ((mask) & 0x1000) ao_enable_cs(port, 12);\
+ if ((mask) & 0x2000) ao_enable_cs(port, 13);\
+ if ((mask) & 0x4000) ao_enable_cs(port, 14);\
+ if ((mask) & 0x8000) ao_enable_cs(port, 15);\
+ } while (0)
+
+/* ao_dma_stm.c
+ */
+
+extern uint8_t ao_dma_done[STM_NUM_DMA];
+
+void
+ao_dma_set_transfer(uint8_t index,
+ volatile void *peripheral,
+ void *memory,
+ uint16_t count,
+ uint32_t ccr);
+
+void
+ao_dma_set_isr(uint8_t index, void (*isr)(int index));
+
+void
+ao_dma_start(uint8_t index);
+
+void
+ao_dma_done_transfer(uint8_t index);
+
+void
+ao_dma_abort(uint8_t index);
+
+void
+ao_dma_alloc(uint8_t index);
+
+void
+ao_dma_init(void);
+
+/* ao_i2c_stm.c */
+
+void
+ao_i2c_get(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_start(uint8_t i2c_index, uint16_t address);
+
+void
+ao_i2c_put(uint8_t i2c_index);
+
+uint8_t
+ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+uint8_t
+ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop);
+
+void
+ao_i2c_init(void);
+
+/* 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;
+};
+
+#if HAS_SERIAL_1
+extern struct ao_stm_usart ao_stm_usart1;
+#endif
+
+#if HAS_SERIAL_2
+extern struct ao_stm_usart ao_stm_usart2;
+#endif
+
+#if HAS_SERIAL_3
+extern struct ao_stm_usart ao_stm_usart3;
+#endif
+
+#define ARM_PUSH32(stack, val) (*(--(stack)) = (val))
+
+typedef uint32_t ao_arch_irq_t;
+
+static inline uint32_t
+ao_arch_irqsave(void) {
+ uint32_t primask;
+ asm("mrs %0,primask" : "=&r" (primask));
+ ao_arch_block_interrupts();
+ return primask;
+}
+
+static inline void
+ao_arch_irqrestore(uint32_t primask) {
+ asm("msr primask,%0" : : "r" (primask));
+}
+
+static inline void
+ao_arch_memory_barrier() {
+ asm volatile("" ::: "memory");
+}
+
+#if HAS_TASK
+static inline void
+ao_arch_init_stack(struct ao_task *task, void *start)
+{
+ uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE);
+ uint32_t a = (uint32_t) start;
+ int i;
+
+ /* Return address (goes into LR) */
+ ARM_PUSH32(sp, a);
+
+ /* Clear register values r0-r7 */
+ i = 8;
+ while (i--)
+ ARM_PUSH32(sp, 0);
+
+ /* APSR */
+ ARM_PUSH32(sp, 0);
+
+ /* PRIMASK with interrupts enabled */
+ ARM_PUSH32(sp, 0);
+
+ task->sp = sp;
+}
+
+static inline void ao_arch_save_regs(void) {
+ /* Save general registers */
+ asm("push {r0-r7,lr}\n");
+
+ /* Save APSR */
+ asm("mrs r0,apsr");
+ asm("push {r0}");
+
+ /* Save PRIMASK */
+ asm("mrs r0,primask");
+ asm("push {r0}");
+}
+
+static inline void ao_arch_save_stack(void) {
+ uint32_t *sp;
+ asm("mov %0,sp" : "=&r" (sp) );
+ ao_cur_task->sp = (sp);
+ if ((uint8_t *) sp < &ao_cur_task->stack[0])
+ ao_panic (AO_PANIC_STACK);
+}
+
+static inline void ao_arch_restore_stack(void) {
+ uint32_t sp;
+ sp = (uint32_t) ao_cur_task->sp;
+
+ /* Switch stacks */
+ asm("mov sp, %0" : : "r" (sp) );
+
+ /* Restore PRIMASK */
+ asm("pop {r0}");
+ asm("msr primask,r0");
+
+ /* Restore APSR */
+ asm("pop {r0}");
+ asm("msr apsr_nczvq,r0");
+
+ /* Restore general registers */
+ asm("pop {r0-r7,pc}\n");
+}
+
+#ifndef HAS_SAMPLE_PROFILE
+#define HAS_SAMPLE_PROFILE 0
+#endif
+
+#if !HAS_SAMPLE_PROFILE
+#define HAS_ARCH_START_SCHEDULER 1
+
+static inline void ao_arch_start_scheduler(void) {
+ uint32_t sp;
+ uint32_t control;
+
+ asm("mrs %0,msp" : "=&r" (sp));
+ asm("msr psp,%0" : : "r" (sp));
+ asm("mrs %0,control" : "=&r" (control));
+ control |= (1 << 1);
+ asm("msr control,%0" : : "r" (control));
+ asm("isb");
+}
+#endif
+
+#define ao_arch_isr_stack()
+
+#endif
+
+#define ao_arch_wait_interrupt() do { \
+ asm("\twfi\n"); \
+ ao_arch_release_interrupts(); \
+ asm(".global ao_idle_loc\nao_idle_loc:"); \
+ ao_arch_block_interrupts(); \
+ } while (0)
+
+#define ao_arch_critical(b) do { \
+ uint32_t __mask = ao_arch_irqsave(); \
+ do { b } while (0); \
+ ao_arch_irqrestore(__mask); \
+ } while (0)
+
+/* ao_usb_stm.c */
+
+#if AO_USB_DIRECTIO
+uint16_t *
+ao_usb_alloc(void);
+
+void
+ao_usb_free(uint16_t *buffer);
+
+void
+ao_usb_write(uint16_t *buffer, uint16_t len);
+#endif /* AO_USB_DIRECTIO */
+
+#endif /* _AO_ARCH_FUNCS_H_ */
--- /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.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+
+void
+ao_boot_chain(uint32_t *base)
+{
+ uint32_t sp;
+ uint32_t pc;
+
+ sp = base[0];
+ pc = base[1];
+ if (0x08000100 <= pc && pc <= 0x08200000 && (pc & 1) == 1) {
+ asm ("mov sp, %0" : : "r" (sp));
+ asm ("mov lr, %0" : : "r" (pc));
+ asm ("bx lr");
+ }
+}
+
+#define AO_BOOT_SIGNAL 0x5a5aa5a5
+#define AO_BOOT_CHECK 0xc3c33c3c
+
+struct ao_boot {
+ uint32_t *base;
+ uint32_t signal;
+ uint32_t check;
+};
+
+static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
+
+int
+ao_boot_check_chain(void)
+{
+ if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) {
+ ao_boot.signal = 0;
+ ao_boot.check = 0;
+ if (ao_boot.base == AO_BOOT_FORCE_LOADER)
+ return 0;
+ ao_boot_chain(ao_boot.base);
+ }
+ return 1;
+}
+
+void
+ao_boot_reboot(uint32_t *base)
+{
+ ao_boot.base = base;
+ ao_boot.signal = AO_BOOT_SIGNAL;
+ ao_boot.check = AO_BOOT_CHECK;
+ ao_arch_reboot();
+}
--- /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.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+#include <ao_exti.h>
+
+void
+ao_boot_check_pin(void)
+{
+ uint16_t v;
+
+ /* Enable power interface clock */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+
+ /* Enable the input pin */
+ ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN,
+ AO_BOOT_APPLICATION_MODE);
+
+ for (v = 0; v < 100; v++)
+ ao_arch_nop();
+
+ /* Read the value */
+ v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN);
+
+ /* Reset the chip to turn off the port and the power interface clock */
+ ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0);
+ ao_disable_port(&AO_BOOT_APPLICATION_GPIO);
+ stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN);
+ if (v == AO_BOOT_APPLICATION_VALUE)
+ ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+}
--- /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_CRC_H_
+#define _AO_CRC_H_
+
+#define AO_CRC_16_CCITT 0x1021
+#define AO_CRC_16_CDMA2000 0xc867
+#define AO_CRC_16_DECT 0x0589
+#define AO_CRC_16_T10_DIF 0x8bb7
+#define AO_CRC_16_DNP 0x3d65
+#define AO_CRC_16_ANSI 0x8005
+#define AO_CRC_16_DEFAULT AO_CRC_16_ANSI
+
+#define AO_CRC_32_ANSI 0x04c11db7
+#define AO_CRC_32_C 0x1edc6f41
+
+#define AO_CRC_32_DEFAULT AO_CRC_32_ANSI
+
+static inline uint16_t
+ao_crc_in_32_out_16(uint32_t v) {
+ stm_crc.dr.u32 = v;
+ return stm_crc.dr.u16;
+}
+
+static inline uint16_t
+ao_crc_in_16_out_16(uint16_t v) {
+ stm_crc.dr.u16 = v;
+ return stm_crc.dr.u16;
+}
+
+static inline uint16_t
+ao_crc_in_8_out_16(uint8_t v) {
+ stm_crc.dr.u8 = v;
+ return stm_crc.dr.u16;
+}
+
+void
+ao_crc_reset(void);
+
+void
+ao_crc_init(void);
+
+#endif /* _AO_CRC_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"
+
+struct ao_dma_config {
+ void (*isr)(int index);
+};
+
+uint8_t ao_dma_done[STM_NUM_DMA];
+
+static struct ao_dma_config ao_dma_config[STM_NUM_DMA];
+static uint8_t ao_dma_allocated[STM_NUM_DMA];
+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))
+
+static void
+ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) {
+ /* Get channel interrupt bits */
+ uint32_t isr = stm_dma.isr & mask;
+ uint8_t index;
+
+ /* Ack them */
+ stm_dma.ifcr = isr;
+ for (index = low_index; index <= high_index; index++) {
+ if (isr & id_mask(index)) {
+ if (ao_dma_config[index].isr)
+ (*ao_dma_config[index].isr)(index);
+ else {
+ ao_dma_done[index] = 1;
+ ao_wakeup(&ao_dma_done[index]);
+ }
+ }
+ }
+}
+
+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
+ao_dma_set_transfer(uint8_t index,
+ volatile void *peripheral,
+ void *memory,
+ uint16_t count,
+ uint32_t ccr)
+{
+ if (ao_dma_allocated[index]) {
+ if (ao_dma_mutex[index])
+ ao_panic(AO_PANIC_DMA);
+ ao_dma_mutex[index] = 1;
+ } else
+ ao_mutex_get(&ao_dma_mutex[index]);
+ ao_arch_critical(
+ if (ao_dma_active++ == 0)
+ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN);
+ );
+ stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE);
+ stm_dma.channel[index].cndtr = count;
+ stm_dma.channel[index].cpar = peripheral;
+ stm_dma.channel[index].cmar = memory;
+ ao_dma_config[index].isr = NULL;
+}
+
+void
+ao_dma_set_isr(uint8_t index, void (*isr)(int))
+{
+ ao_dma_config[index].isr = isr;
+}
+
+void
+ao_dma_start(uint8_t index)
+{
+ ao_dma_done[index] = 0;
+ stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN);
+}
+
+void
+ao_dma_done_transfer(uint8_t index)
+{
+ stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+ ao_arch_critical(
+ if (--ao_dma_active == 0)
+ stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMAEN);
+ );
+ if (ao_dma_allocated[index])
+ ao_dma_mutex[index] = 0;
+ else
+ ao_mutex_put(&ao_dma_mutex[index]);
+}
+
+void
+ao_dma_abort(uint8_t index)
+{
+ stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN);
+ ao_wakeup(&ao_dma_done[index]);
+}
+
+void
+ao_dma_alloc(uint8_t index)
+{
+ if (ao_dma_allocated[index])
+ ao_panic(AO_PANIC_DMA);
+ ao_dma_allocated[index] = 1;
+}
+
+#define STM_NUM_DMA_ISR 3
+
+void
+ao_dma_init(void)
+{
+ int isr_id;
+ int index;
+
+ for (isr_id = 0; isr_id < STM_NUM_DMA_ISR; isr_id++) {
+ stm_nvic_set_enable(STM_ISR_DMA_CH1_POS + isr_id);
+ stm_nvic_set_priority(STM_ISR_DMA_CH1_POS + isr_id, 4);
+ }
+ for (index = 0; index < STM_NUM_DMA; index++) {
+ ao_dma_allocated[index] = 0;
+ ao_dma_mutex[index] = 0;
+ }
+}
--- /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_FLASH_STM_H_
+#define _AO_FLASH_STM_H_
+
+void
+ao_flash_erase_page(uint32_t *page);
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src);
+
+#endif /* _AO_FLASH_STM_H_ */
--- /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.
+ */
+
+#include "ao.h"
+#include <ao_exti.h>
+#include <ao_boot.h>
+#include <ao_flash_task.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+ ao_usb_init();
+
+#if HAS_TICK
+ ao_timer_init();
+#endif
+
+#ifdef AO_FLASH_LOADER_INIT
+ AO_FLASH_LOADER_INIT;
+#endif
+ ao_flash_task();
+ return 0;
+}
--- /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.
+ */
+
+#include <ao.h>
+#include <ao_flash.h>
+
+static uint8_t
+ao_flash_is_locked(void)
+{
+ return (stm_flash.cr & (1 << STM_FLASH_CR_LOCK)) != 0;
+}
+
+static void
+ao_flash_unlock(void)
+{
+ if (!ao_flash_is_locked())
+ return;
+
+ /* Unlock FLASH_CR register */
+ stm_flash.keyr = STM_FLASH_KEYR_KEY1;
+ stm_flash.keyr = STM_FLASH_KEYR_KEY2;
+ if (ao_flash_is_locked())
+ ao_panic(AO_PANIC_FLASH);
+}
+
+static void
+ao_flash_lock(void)
+{
+ stm_flash.cr |= (1 << STM_FLASH_CR_LOCK);
+}
+
+static void
+ao_flash_wait_bsy(void)
+{
+ while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
+ ;
+}
+
+static void __attribute__ ((section(".ramtext"),noinline))
+_ao_flash_erase_page(uint32_t *page)
+{
+ stm_flash.cr |= (1 << STM_FLASH_CR_PER);
+
+ stm_flash.ar = (uintptr_t) page;
+
+ stm_flash.cr |= (1 << STM_FLASH_CR_STRT);
+
+ ao_flash_wait_bsy();
+
+ stm_flash.cr &= ~(1 << STM_FLASH_CR_PER);
+}
+
+static uint32_t
+stm_flash_page_size(void)
+{
+ uint16_t dev_id = stm_dev_id();
+
+ switch (dev_id) {
+ case 0x440: /* stm32f05x */
+ case 0x444: /* stm32f03x */
+ case 0x445: /* stm32f04x */
+ return 1024;
+ case 0x442: /* stm32f09x */
+ case 0x448: /* stm32f07x */
+ return 2048;
+ }
+ ao_panic(AO_PANIC_FLASH);
+ return 0;
+}
+
+void
+ao_flash_erase_page(uint32_t *page)
+{
+ /* Erase the whole page at the start. This assumes we'll be flashing things
+ * in memory order
+ */
+
+ if ((uintptr_t) page & (stm_flash_page_size() - 1))
+ return;
+
+ ao_arch_block_interrupts();
+ ao_flash_unlock();
+
+ _ao_flash_erase_page(page);
+
+ ao_flash_lock();
+ ao_arch_release_interrupts();
+}
+
+static void __attribute__ ((section(".ramtext"), noinline))
+_ao_flash_page(uint16_t *dst, uint16_t *src)
+{
+ uint8_t i;
+
+ stm_flash.cr |= (1 << STM_FLASH_CR_PG);
+
+ for (i = 0; i < 128; i++) {
+ *dst++ = *src++;
+ ao_flash_wait_bsy();
+ }
+
+ stm_flash.cr &= ~(1 << STM_FLASH_CR_PG);
+}
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src)
+{
+ ao_flash_erase_page(page);
+
+ ao_arch_block_interrupts();
+ ao_flash_unlock();
+
+ _ao_flash_page((uint16_t *) page, (uint16_t *) src);
+
+ ao_flash_lock();
+ ao_arch_release_interrupts();
+}
--- /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_FLASH_STM_PINS_H_
+#define _AO_FLASH_STM_PINS_H_
+
+#include <ao_flash_pins.h>
+
+/* 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_NEED_HSI 1
+
+#endif /* _AO_FLASH_STM_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 "stm32f0.h"
+#include <string.h>
+#include <ao_boot.h>
+
+#ifndef IS_FLASH_LOADER
+#error Should define IS_FLASH_LOADER
+#define IS_FLASH_LOADER 0
+#endif
+
+#if !IS_FLASH_LOADER
+#define RELOCATE_INTERRUPT 1
+#endif
+
+extern void main(void);
+extern char __stack__;
+extern char __text_start__, __text_end__;
+extern char __data_start__, __data_end__;
+extern char __bss_start__, __bss_end__;
+#if RELOCATE_INTERRUPT
+extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__;
+#endif
+
+/* Interrupt functions */
+
+void stm_halt_isr(void)
+{
+ ao_panic(AO_PANIC_CRASH);
+}
+
+void stm_ignore_isr(void)
+{
+}
+
+const void *stm_interrupt_vector[];
+
+uint32_t
+stm_flash_size(void) {
+ uint16_t dev_id = stm_dev_id();
+ uint16_t kbytes = 0;
+
+ switch (dev_id) {
+ case 0x445:
+ kbytes = stm_flash_size_04x.f_size;
+ break;
+ }
+ return (uint32_t) kbytes * 1024;
+}
+
+void start(void)
+{
+#ifdef AO_BOOT_CHAIN
+ if (ao_boot_check_chain()) {
+#ifdef AO_BOOT_PIN
+ ao_boot_check_pin();
+#endif
+ }
+#endif
+#if RELOCATE_INTERRUPT
+ /* Turn on syscfg */
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+ memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
+ stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
+ (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE);
+#endif
+ memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
+ memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
+ main();
+}
+
+#define STRINGIFY(x) #x
+
+#define isr(name) \
+ void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
+ _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr))
+
+#define isr_halt(name) \
+ void __attribute__ ((weak)) stm_ ## name ## _isr(void); \
+ _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr))
+
+isr(nmi)
+isr_halt(hardfault)
+isr_halt(memmanage)
+isr_halt(busfault)
+isr_halt(usagefault)
+isr(svc)
+isr(debugmon)
+isr(pendsv)
+isr(systick)
+isr(wwdg)
+isr(pvd)
+isr(rtc)
+isr(flash)
+isr(rcc_crs)
+isr(exti0_1)
+isr(exti2_3)
+isr(exti4_15)
+isr(tsc)
+isr(dma_ch1)
+isr(dma_ch2_3)
+isr(dma_ch4_5_6)
+isr(adc_comp)
+isr(tim1_brk_up_trg_com)
+isr(tim1_cc)
+isr(tim2)
+isr(tim3)
+isr(tim6_dac)
+isr(tim7)
+isr(tim14)
+isr(tim15)
+isr(tim16)
+isr(tim17)
+isr(i2c1)
+isr(i2c2)
+isr(spi1)
+isr(spi2)
+isr(usart1)
+isr(usart2)
+isr(usart3_4_5_6_7_8)
+isr(cec_can)
+isr(usb)
+
+#define i(addr,name) [(addr)/4] = stm_ ## name ## _isr
+
+__attribute__ ((section(".interrupt")))
+const void *stm_interrupt_vector[] = {
+ [0] = &__stack__,
+ [1] = start,
+ i(0x08, nmi),
+ i(0x0c, hardfault),
+ i(0x2c, svc),
+ i(0x30, debugmon),
+ i(0x38, pendsv),
+ i(0x3c, systick),
+ i(0x40, wwdg), /* IRQ0 */
+ i(0x44, pvd),
+ i(0x48, rtc),
+ i(0x4c, flash),
+ i(0x50, rcc_crs),
+ i(0x54, exti0_1),
+ i(0x58, exti2_3),
+ i(0x5c, exti4_15),
+ i(0x60, tsc),
+ i(0x64, dma_ch1),
+ i(0x68, dma_ch2_3),
+ i(0x6c, dma_ch4_5_6),
+ i(0x70, adc_comp),
+ i(0x74, tim1_brk_up_trg_com),
+ i(0x78, tim1_cc),
+ i(0x7c, tim2),
+ i(0x80, tim3),
+ i(0x84, tim6_dac),
+ i(0x88, tim7),
+ i(0x8c, tim14),
+ i(0x90, tim15),
+ i(0x94, tim16),
+ i(0x98, tim17),
+ i(0x9c, i2c1),
+ i(0xa0, i2c2),
+ i(0xa4, spi1),
+ i(0xa8, spi2),
+ i(0xac, usart1),
+ i(0xb0, usart2),
+ i(0xb4, usart3_4_5_6_7_8),
+ i(0xb8, cec_can),
+ i(0xbc, usb),
+};
--- /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"
+
+__pdata uint16_t ao_led_enable;
+
+void
+ao_led_on(uint16_t colors)
+{
+#ifdef LED_PORT
+ LED_PORT->bsrr = (colors & ao_led_enable);
+#else
+#ifdef LED_PORT_0
+ LED_PORT_0->bsrr = ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
+#endif
+#ifdef LED_PORT_1
+ LED_PORT_1->bsrr = ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
+#endif
+#endif
+}
+
+void
+ao_led_off(uint16_t colors)
+{
+#ifdef LED_PORT
+ LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16;
+#else
+#ifdef LED_PORT_0
+ LED_PORT_0->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_0_MASK) << (LED_PORT_0_SHIFT + 16);
+#endif
+#ifdef LED_PORT_1
+ LED_PORT_1->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_1_MASK) << (LED_PORT_1_SHIFT + 16);
+#endif
+#endif
+}
+
+void
+ao_led_set(uint16_t colors)
+{
+ uint16_t on = colors & ao_led_enable;
+ uint16_t off = ~colors & ao_led_enable;
+
+ ao_led_off(off);
+ ao_led_on(on);
+}
+
+void
+ao_led_toggle(uint16_t colors)
+{
+#ifdef LED_PORT
+ LED_PORT->odr ^= (colors & ao_led_enable);
+#else
+#ifdef LED_PORT_0
+ LED_PORT_0->odr ^= ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
+#endif
+#ifdef LED_PORT_1
+ LED_PORT_1->odr ^= ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
+#endif
+#endif
+}
+
+void
+ao_led_for(uint16_t colors, uint16_t ticks) __reentrant
+{
+ ao_led_on(colors);
+ ao_delay(ticks);
+ ao_led_off(colors);
+}
+
+#define init_led_pin(port, bit) do { \
+ stm_moder_set(port, bit, STM_MODER_OUTPUT); \
+ stm_otyper_set(port, bit, STM_OTYPER_PUSH_PULL); \
+ } while (0)
+
+void
+ao_led_init(uint16_t enable)
+{
+ int bit;
+
+ ao_led_enable = enable;
+#ifdef LED_PORT
+ stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE);
+ LED_PORT->odr &= ~enable;
+#else
+#ifdef LED_PORT_0
+ stm_rcc.ahbenr |= (1 << LED_PORT_0_ENABLE);
+ LED_PORT_0->odr &= ~((enable & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT;
+#endif
+#ifdef LED_PORT_1
+ stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE);
+ LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT;
+#endif
+#endif
+ for (bit = 0; bit < 16; bit++) {
+ if (enable & (1 << bit)) {
+#ifdef LED_PORT
+ init_led_pin(LED_PORT, bit);
+#else
+#ifdef LED_PORT_0
+ if (LED_PORT_0_MASK & (1 << bit))
+ init_led_pin(LED_PORT_0, bit + LED_PORT_0_SHIFT);
+#endif
+#ifdef LED_PORT_1
+ if (LED_PORT_1_MASK & (1 << bit))
+ init_led_pin(LED_PORT_1, bit + LED_PORT_1_SHIFT);
+#endif
+#endif
+ }
+ }
+}
--- /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"
+
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION;
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION;
+AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0;
+#ifndef AO_RADIO_CAL_DEFAULT
+#define AO_RADIO_CAL_DEFAULT 0x01020304
+#endif
+AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT;
+
--- /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_task.h>
+#if HAS_FAKE_FLIGHT
+#include <ao_fake_flight.h>
+#endif
+
+#ifndef HAS_TICK
+#define HAS_TICK 1
+#endif
+
+#if HAS_TICK
+volatile AO_TICK_TYPE ao_tick_count;
+
+AO_TICK_TYPE
+ao_time(void)
+{
+ return ao_tick_count;
+}
+
+#if AO_DATA_ALL
+volatile __data uint8_t ao_data_interval = 1;
+volatile __data uint8_t ao_data_count;
+#endif
+
+void stm_systick_isr(void)
+{
+ if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) {
+ ++ao_tick_count;
+#if HAS_TASK_QUEUE
+ if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0)
+ ao_task_check_alarm((uint16_t) ao_tick_count);
+#endif
+#if AO_DATA_ALL
+ if (++ao_data_count == ao_data_interval) {
+ ao_data_count = 0;
+#if HAS_FAKE_FLIGHT
+ if (ao_fake_flight_active)
+ ao_fake_flight_poll();
+ else
+#endif
+ ao_adc_poll();
+#if (AO_DATA_ALL & ~(AO_DATA_ADC))
+ ao_wakeup((void *) &ao_data_count);
+#endif
+ }
+#endif
+#ifdef AO_TIMER_HOOK
+ AO_TIMER_HOOK;
+#endif
+ }
+}
+
+#if HAS_ADC
+void
+ao_timer_set_adc_interval(uint8_t interval)
+{
+ ao_arch_critical(
+ ao_data_interval = interval;
+ ao_data_count = 0;
+ );
+}
+#endif
+
+#define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1)
+
+void
+ao_timer_init(void)
+{
+ stm_systick.rvr = SYSTICK_RELOAD;
+ stm_systick.cvr = 0;
+ stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) |
+ (1 << STM_SYSTICK_CSR_TICKINT) |
+ (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE));
+}
+
+#endif
+
+static void
+ao_clock_enable_crs(void)
+{
+ /* Enable crs interface clock */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_CRSEN);
+
+ /* Disable error counter */
+ stm_crs.cr = ((stm_crs.cr & (1 << 4)) |
+ (32 << STM_CRS_CR_TRIM) |
+ (0 << STM_CRS_CR_SWSYNC) |
+ (0 << STM_CRS_CR_AUTOTRIMEN) |
+ (0 << STM_CRS_CR_CEN) |
+ (0 << STM_CRS_CR_ESYNCIE) |
+ (0 << STM_CRS_CR_ERRIE) |
+ (0 << STM_CRS_CR_SYNCWARNIE) |
+ (0 << STM_CRS_CR_SYNCOKIE));
+
+ /* Configure for USB source */
+ stm_crs.cfgr = ((stm_crs.cfgr & ((1 << 30) | (1 << 27))) |
+ (0 << STM_CRS_CFGR_SYNCPOL) |
+ (STM_CRS_CFGR_SYNCSRC_USB << STM_CRS_CFGR_SYNCSRC) |
+ (STM_CRS_CFGR_SYNCDIV_1 << STM_CRS_CFGR_SYNCDIV) |
+ (0x22 << STM_CRS_CFGR_FELIM) |
+ (((48000000 / 1000) - 1) << STM_CRS_CFGR_RELOAD));
+
+ /* Enable error counter, set auto trim */
+ stm_crs.cr = ((stm_crs.cr & (1 << 4)) |
+ (32 << STM_CRS_CR_TRIM) |
+ (0 << STM_CRS_CR_SWSYNC) |
+ (1 << STM_CRS_CR_AUTOTRIMEN) |
+ (1 << STM_CRS_CR_CEN) |
+ (0 << STM_CRS_CR_ESYNCIE) |
+ (0 << STM_CRS_CR_ERRIE) |
+ (0 << STM_CRS_CR_SYNCWARNIE) |
+ (0 << STM_CRS_CR_SYNCOKIE));
+
+}
+
+void
+ao_clock_init(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();
+
+ stm_rcc.cfgr = (stm_rcc.cfgr & ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW)) |
+ (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW);
+
+ /* wait for system to switch to HSI */
+ while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
+ (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS))
+ ao_arch_nop();
+
+ /* reset the clock config, leaving us running on the HSI */
+ stm_rcc.cfgr &= (uint32_t)0x0000000f;
+
+ /* reset PLLON, CSSON, HSEBYP, HSEON */
+ stm_rcc.cr &= 0x0000ffff;
+
+ /* Disable all interrupts */
+ stm_rcc.cir = 0;
+
+#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
+#define STM_PLLSRC AO_HSE
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 1
+
+#if AO_HSE_BYPASS
+ stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP);
+#else
+ stm_rcc.cr &= ~(1 << STM_RCC_CR_HSEBYP);
+#endif
+ /* Enable HSE clock */
+ stm_rcc.cr |= (1 << STM_RCC_CR_HSEON);
+ while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY)))
+ asm("nop");
+#endif
+
+
+#if AO_HSI48
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSI48
+#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSI48
+
+ /* Turn HSI48 clock on */
+ stm_rcc.cr2 |= (1 << STM_RCC_CR2_HSI48ON);
+
+ /* Wait for clock to stabilize */
+ while ((stm_rcc.cr2 & (1 << STM_RCC_CR2_HSI48RDY)) == 0)
+ ao_arch_nop();
+
+ ao_clock_enable_crs();
+#endif
+
+#ifndef STM_RCC_CFGR_SWS_TARGET_CLOCK
+#define STM_HSI 16000000
+#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSI
+#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSI
+#define STM_PLLSRC STM_HSI
+#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 0
+#endif
+
+#ifdef STM_PLLSRC
+#error No code for PLL initialization yet
+#endif
+
+ /* Set flash latency to tolerate 48MHz SYSCLK -> 1 wait state */
+
+ /* Enable prefetch */
+ stm_flash.acr |= (1 << STM_FLASH_ACR_PRFTBE);
+
+ /* Enable 1 wait state so the CPU can run at 48MHz */
+ stm_flash.acr |= (STM_FLASH_ACR_LATENCY_1 << STM_FLASH_ACR_LATENCY);
+
+ /* Enable power interface clock */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+
+ /* HCLK to 48MHz -> AHB prescaler = /1 */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE);
+ cfgr |= (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE);
+ stm_rcc.cfgr = cfgr;
+ while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) !=
+ (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE))
+ ao_arch_nop();
+
+ /* APB Prescaler = AO_APB_PRESCALER */
+ cfgr = stm_rcc.cfgr;
+ cfgr &= ~(STM_RCC_CFGR_PPRE_MASK << STM_RCC_CFGR_PPRE);
+ cfgr |= (AO_RCC_CFGR_PPRE_DIV << STM_RCC_CFGR_PPRE);
+ 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;
+ }
+
+ /* 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.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
+
+ stm_afr_set(&stm_gpioa, 8, STM_AFR_AF0);
+ stm_moder_set(&stm_gpioa, 8, STM_MODER_ALTERNATE);
+ stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_40MHz);
+
+ stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE);
+ stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL);
+#endif
+}
--- /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_usb.h"
+#include "ao_product.h"
+
+#define USB_DEBUG 0
+#define USB_DEBUG_DATA 0
+#define USB_ECHO 0
+
+#ifndef AO_PA11_PA12_RMP
+#error "must define AO_PA11_PA12_RMP"
+#endif
+
+#ifndef USE_USB_STDIO
+#define USE_USB_STDIO 1
+#endif
+
+#if USE_USB_STDIO
+#define AO_USB_OUT_SLEEP_ADDR (&ao_stdin_ready)
+#else
+#define AO_USB_OUT_SLEEP_ADDR (&ao_usb_out_avail)
+#endif
+
+#if USB_DEBUG
+#define debug(format, args...) printf(format, ## args);
+#else
+#define debug(format, args...)
+#endif
+
+#if USB_DEBUG_DATA
+#define debug_data(format, args...) printf(format, ## args);
+#else
+#define debug_data(format, args...)
+#endif
+
+struct ao_usb_setup {
+ uint8_t dir_type_recip;
+ uint8_t request;
+ uint16_t value;
+ uint16_t index;
+ uint16_t length;
+} ao_usb_setup;
+
+static uint8_t ao_usb_ep0_state;
+
+/* Pending EP0 IN data */
+static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */
+static uint8_t ao_usb_ep0_in_len; /* Remaining amount */
+
+/* Temp buffer for smaller EP0 in data */
+static uint8_t ao_usb_ep0_in_buf[2];
+
+/* Pending EP0 OUT data */
+static uint8_t *ao_usb_ep0_out_data;
+static uint8_t ao_usb_ep0_out_len;
+
+/*
+ * Objects allocated in special USB memory
+ */
+
+/* Buffer description tables */
+static union stm_usb_bdt *ao_usb_bdt;
+/* USB address of end of allocated storage */
+static uint16_t ao_usb_sram_addr;
+
+/* Pointer to ep0 tx/rx buffers in USB memory */
+static uint16_t *ao_usb_ep0_tx_buffer;
+static uint16_t *ao_usb_ep0_rx_buffer;
+
+/* Pointer to bulk data tx/rx buffers in USB memory */
+static uint16_t ao_usb_in_tx_offset;
+static uint16_t *ao_usb_in_tx_buffer;
+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;
+
+static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE];
+static uint8_t ao_usb_rx_count, ao_usb_rx_pos;
+
+/*
+ * End point register indices
+ */
+
+#define AO_USB_CONTROL_EPR 0
+#define AO_USB_INT_EPR 1
+#define AO_USB_OUT_EPR 2
+#define AO_USB_IN_EPR 3
+
+/* Marks when we don't need to send an IN packet.
+ * This happens only when the last IN packet is not full,
+ * otherwise the host will expect to keep seeing packets.
+ * Send a zero-length packet as required
+ */
+static uint8_t ao_usb_in_flushed;
+
+/* 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_in_pending;
+
+/* Marks when an OUT packet has been received by the hardware
+ * but not pulled to the shadow buffer.
+ */
+static uint8_t ao_usb_out_avail;
+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
+
+static uint8_t ao_usb_ep0_receive;
+static uint8_t ao_usb_address;
+static uint8_t ao_usb_address_pending;
+
+static inline uint32_t set_toggle(uint32_t current_value,
+ uint32_t mask,
+ uint32_t desired_value)
+{
+ return (current_value ^ desired_value) & mask;
+}
+
+static inline uint16_t *ao_usb_packet_buffer_addr(uint16_t sram_addr)
+{
+ return (uint16_t *) (stm_usb_sram + sram_addr);
+}
+
+#if AO_USB_DIRECTIO
+static inline uint16_t ao_usb_packet_buffer_offset(uint16_t *addr)
+{
+ return (uint16_t) ((uint8_t *) addr - stm_usb_sram);
+}
+#endif
+
+static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) {
+ return (epr >> STM_USB_EPR_STAT_RX) & STM_USB_EPR_STAT_RX_MASK;
+}
+
+static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) {
+ return (epr >> STM_USB_EPR_STAT_TX) & STM_USB_EPR_STAT_TX_MASK;
+}
+
+static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) {
+ return (epr >> STM_USB_EPR_CTR_RX) & 1;
+}
+
+static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) {
+ return (epr >> STM_USB_EPR_CTR_TX) & 1;
+}
+
+static inline uint32_t ao_usb_epr_setup(uint32_t epr) {
+ return (epr >> STM_USB_EPR_SETUP) & 1;
+}
+
+static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) {
+ return (epr >> STM_USB_EPR_DTOG_RX) & 1;
+}
+
+static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) {
+ return (epr >> STM_USB_EPR_DTOG_TX) & 1;
+}
+
+/*
+ * Set current device address and mark the
+ * interface as active
+ */
+void
+ao_usb_set_address(uint8_t address)
+{
+ debug("ao_usb_set_address %02x\n", address);
+ stm_usb.daddr = (1 << STM_USB_DADDR_EF) | address;
+ ao_usb_address_pending = 0;
+}
+
+/*
+ * Write these values to preserve register contents under HW changes
+ */
+
+#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \
+ (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \
+ (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \
+ (1 << STM_USB_EPR_CTR_TX) | \
+ (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \
+ (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX))
+
+#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \
+ (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \
+ (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \
+ (1 << STM_USB_EPR_CTR_TX) | \
+ (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \
+ (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX))
+
+/*
+ * These bits are purely under sw control, so preserve them in the
+ * register by re-writing what was read
+ */
+#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \
+ (1 << STM_USB_EPR_EP_KIND) | \
+ (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA))
+
+#define TX_DBG 0
+#define RX_DBG 0
+
+#if TX_DBG
+#define _tx_dbg0(msg) _dbg(__LINE__,msg,0)
+#define _tx_dbg1(msg,value) _dbg(__LINE__,msg,value)
+#else
+#define _tx_dbg0(msg)
+#define _tx_dbg1(msg,value)
+#endif
+
+#if RX_DBG
+#define _rx_dbg0(msg) _dbg(__LINE__,msg,0)
+#define _rx_dbg1(msg,value) _dbg(__LINE__,msg,value)
+#else
+#define _rx_dbg0(msg)
+#define _rx_dbg1(msg,value)
+#endif
+
+#if TX_DBG || RX_DBG
+static void _dbg(int line, char *msg, uint32_t value);
+#endif
+
+/*
+ * Set the state of the specified endpoint register to a new
+ * value. This is tricky because the bits toggle where the new
+ * value is one, and we need to write invariant values in other
+ * spots of the register. This hardware is strange...
+ */
+static void
+_ao_usb_set_stat_tx(int ep, uint32_t stat_tx)
+{
+ uint16_t epr_write, epr_old;
+
+ _tx_dbg1("set_stat_tx top", stat_tx);
+ epr_old = epr_write = stm_usb.epr[ep].r;
+ epr_write &= STM_USB_EPR_PRESERVE_MASK;
+ epr_write |= STM_USB_EPR_INVARIANT;
+ epr_write |= set_toggle(epr_old,
+ STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX,
+ stat_tx << STM_USB_EPR_STAT_TX);
+ stm_usb.epr[ep].r = epr_write;
+ _tx_dbg1("set_stat_tx bottom", epr_write);
+}
+
+static void
+ao_usb_set_stat_tx(int ep, uint32_t stat_tx)
+{
+ ao_arch_block_interrupts();
+ _ao_usb_set_stat_tx(ep, stat_tx);
+ ao_arch_release_interrupts();
+}
+
+static void
+_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) {
+ uint16_t epr_write, epr_old;
+
+ epr_write = epr_old = stm_usb.epr[ep].r;
+ epr_write &= STM_USB_EPR_PRESERVE_MASK;
+ epr_write |= STM_USB_EPR_INVARIANT;
+ epr_write |= set_toggle(epr_old,
+ STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX,
+ stat_rx << STM_USB_EPR_STAT_RX);
+ stm_usb.epr[ep].r = epr_write;
+}
+
+static void
+ao_usb_set_stat_rx(int ep, uint32_t stat_rx) {
+ ao_arch_block_interrupts();
+ _ao_usb_set_stat_rx(ep, stat_rx);
+ ao_arch_release_interrupts();
+}
+
+/*
+ * Set just endpoint 0, for use during startup
+ */
+
+static void
+ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx)
+{
+ uint16_t epr;
+
+ ao_arch_block_interrupts();
+ epr = stm_usb.epr[ep].r;
+ epr = ((0 << STM_USB_EPR_CTR_RX) |
+ (epr & (1 << STM_USB_EPR_DTOG_RX)) |
+ set_toggle(epr,
+ (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX),
+ (stat_rx << STM_USB_EPR_STAT_RX)) |
+ (type << STM_USB_EPR_EP_TYPE) |
+ (0 << STM_USB_EPR_EP_KIND) |
+ (0 << STM_USB_EPR_CTR_TX) |
+ (epr & (1 << STM_USB_EPR_DTOG_TX)) |
+ set_toggle(epr,
+ (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX),
+ (stat_tx << STM_USB_EPR_STAT_TX)) |
+ (addr << STM_USB_EPR_EA));
+ stm_usb.epr[ep].r = epr;
+ ao_arch_release_interrupts();
+ debug ("writing epr[%d] 0x%04x wrote 0x%04x\n",
+ ep, epr, stm_usb.epr[ep].r);
+}
+
+static void
+ao_usb_init_btable(void)
+{
+ ao_usb_sram_addr = 0;
+
+ ao_usb_bdt = (void *) stm_usb_sram;
+
+ ao_usb_sram_addr += 8 * STM_USB_BDT_SIZE;
+
+ /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */
+
+ ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr;
+ ao_usb_bdt[0].single.count_tx = 0;
+ ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+ ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
+
+ ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr;
+ ao_usb_bdt[0].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
+ (((AO_USB_CONTROL_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK));
+ ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+ ao_usb_sram_addr += AO_USB_CONTROL_SIZE;
+
+}
+
+static void
+ao_usb_set_ep0(void)
+{
+ int e;
+
+ ao_usb_init_btable();
+
+ /* buffer table is at the start of USB memory */
+ stm_usb.btable = 0;
+
+ ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP,
+ STM_USB_EPR_EP_TYPE_CONTROL,
+ STM_USB_EPR_STAT_RX_VALID,
+ STM_USB_EPR_STAT_TX_NAK);
+
+ /* Clear all of the other endpoints */
+ for (e = 1; e < 8; e++) {
+ ao_usb_init_ep(e, 0,
+ STM_USB_EPR_EP_TYPE_CONTROL,
+ STM_USB_EPR_STAT_RX_DISABLED,
+ STM_USB_EPR_STAT_TX_DISABLED);
+ }
+
+ ao_usb_set_address(0);
+}
+
+static void
+ao_usb_set_configuration(void)
+{
+ debug ("ao_usb_set_configuration\n");
+
+ /* Set up the INT end point */
+ ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr;
+ ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0;
+ ao_usb_sram_addr += AO_USB_INT_SIZE;
+
+ ao_usb_init_ep(AO_USB_INT_EPR,
+ AO_USB_INT_EP,
+ STM_USB_EPR_EP_TYPE_INTERRUPT,
+ STM_USB_EPR_STAT_RX_DISABLED,
+ STM_USB_EPR_STAT_TX_NAK);
+
+ /* Set up the OUT end point */
+ ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr;
+ ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) |
+ (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK));
+ ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+ ao_usb_sram_addr += AO_USB_OUT_SIZE;
+
+ ao_usb_init_ep(AO_USB_OUT_EPR,
+ AO_USB_OUT_EP,
+ STM_USB_EPR_EP_TYPE_BULK,
+ STM_USB_EPR_STAT_RX_VALID,
+ STM_USB_EPR_STAT_TX_DISABLED);
+
+ /* Set up the IN end point */
+ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr;
+ ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0;
+ ao_usb_in_tx_offset = ao_usb_sram_addr;
+ ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_in_tx_offset);
+ ao_usb_sram_addr += AO_USB_IN_SIZE;
+
+ ao_usb_init_ep(AO_USB_IN_EPR,
+ AO_USB_IN_EP,
+ STM_USB_EPR_EP_TYPE_BULK,
+ STM_USB_EPR_STAT_RX_DISABLED,
+ STM_USB_EPR_STAT_TX_NAK);
+
+ ao_usb_running = 1;
+}
+
+static uint16_t control_count;
+static uint16_t int_count;
+static uint16_t in_count;
+static uint16_t out_count;
+static uint16_t reset_count;
+
+/* The USB memory must be accessed in 16-bit units
+ */
+
+static void
+ao_usb_copy_tx(const uint8_t *src, uint16_t *base, uint16_t bytes)
+{
+ while (bytes >= 2) {
+ *base++ = src[0] | (src[1] << 8);
+ src += 2;
+ bytes -= 2;
+ }
+ if (bytes)
+ *base = *src;
+}
+
+static void
+ao_usb_copy_rx(uint8_t *dst, uint16_t *base, uint16_t bytes)
+{
+ while (bytes >= 2) {
+ uint16_t s = *base++;
+ dst[0] = s;
+ dst[1] = s >> 8;
+ dst += 2;
+ bytes -= 2;
+ }
+ if (bytes)
+ *dst = *base;
+}
+
+/* Send an IN data packet */
+static void
+ao_usb_ep0_flush(void)
+{
+ uint8_t this_len;
+
+ /* Check to see if the endpoint is still busy */
+ if (ao_usb_epr_stat_tx(stm_usb.epr[0].r) == STM_USB_EPR_STAT_TX_VALID) {
+ debug("EP0 not accepting IN data\n");
+ return;
+ }
+
+ this_len = ao_usb_ep0_in_len;
+ if (this_len > AO_USB_CONTROL_SIZE)
+ this_len = AO_USB_CONTROL_SIZE;
+
+ if (this_len < AO_USB_CONTROL_SIZE)
+ ao_usb_ep0_state = AO_USB_EP0_IDLE;
+
+ ao_usb_ep0_in_len -= this_len;
+
+ debug_data ("Flush EP0 len %d:", this_len);
+ ao_usb_copy_tx(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len);
+ debug_data ("\n");
+ ao_usb_ep0_in_data += this_len;
+
+ /* Mark the endpoint as TX valid to send the packet */
+ ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len;
+ ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, STM_USB_EPR_STAT_TX_VALID);
+ debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[AO_USB_CONTROL_EPR]);
+}
+
+/* Read data from the ep0 OUT fifo */
+static void
+ao_usb_ep0_fill(void)
+{
+ uint16_t len = ao_usb_bdt[0].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK;
+
+ if (len > ao_usb_ep0_out_len)
+ len = ao_usb_ep0_out_len;
+ ao_usb_ep0_out_len -= len;
+
+ /* Pull all of the data out of the packet */
+ debug_data ("Fill EP0 len %d:", len);
+ ao_usb_copy_rx(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, len);
+ debug_data ("\n");
+ ao_usb_ep0_out_data += len;
+
+ /* ACK the packet */
+ ao_usb_set_stat_rx(0, STM_USB_EPR_STAT_RX_VALID);
+}
+
+static void
+ao_usb_ep0_in_reset(void)
+{
+ ao_usb_ep0_in_data = ao_usb_ep0_in_buf;
+ ao_usb_ep0_in_len = 0;
+}
+
+static void
+ao_usb_ep0_in_queue_byte(uint8_t a)
+{
+ if (ao_usb_ep0_in_len < sizeof (ao_usb_ep0_in_buf))
+ ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a;
+}
+
+static void
+ao_usb_ep0_in_set(const uint8_t *data, uint8_t len)
+{
+ ao_usb_ep0_in_data = data;
+ ao_usb_ep0_in_len = len;
+}
+
+static void
+ao_usb_ep0_out_set(uint8_t *data, uint8_t len)
+{
+ ao_usb_ep0_out_data = data;
+ ao_usb_ep0_out_len = len;
+}
+
+static void
+ao_usb_ep0_in_start(uint16_t max)
+{
+ /* Don't send more than asked for */
+ if (ao_usb_ep0_in_len > max)
+ ao_usb_ep0_in_len = max;
+ ao_usb_ep0_flush();
+}
+
+static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
+
+/* Walk through the list of descriptors and find a match
+ */
+static void
+ao_usb_get_descriptor(uint16_t value)
+{
+ const uint8_t *descriptor;
+ uint8_t type = value >> 8;
+ uint8_t index = value;
+
+ descriptor = ao_usb_descriptors;
+ while (descriptor[0] != 0) {
+ if (descriptor[1] == type && index-- == 0) {
+ uint8_t len;
+ if (type == AO_USB_DESC_CONFIGURATION)
+ len = descriptor[2];
+ else
+ len = descriptor[0];
+ ao_usb_ep0_in_set(descriptor, len);
+ break;
+ }
+ descriptor += descriptor[0];
+ }
+}
+
+static void
+ao_usb_ep0_setup(void)
+{
+ /* Pull the setup packet out of the fifo */
+ ao_usb_ep0_out_set((uint8_t *) &ao_usb_setup, 8);
+ ao_usb_ep0_fill();
+ if (ao_usb_ep0_out_len != 0) {
+ debug ("invalid setup packet length\n");
+ return;
+ }
+
+ if ((ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) || ao_usb_setup.length == 0)
+ ao_usb_ep0_state = AO_USB_EP0_DATA_IN;
+ else
+ ao_usb_ep0_state = AO_USB_EP0_DATA_OUT;
+
+ ao_usb_ep0_in_reset();
+
+ switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) {
+ case AO_USB_TYPE_STANDARD:
+ debug ("Standard setup packet\n");
+ switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) {
+ case AO_USB_RECIP_DEVICE:
+ debug ("Device setup packet\n");
+ switch(ao_usb_setup.request) {
+ case AO_USB_REQ_GET_STATUS:
+ debug ("get status\n");
+ ao_usb_ep0_in_queue_byte(0);
+ ao_usb_ep0_in_queue_byte(0);
+ break;
+ case AO_USB_REQ_SET_ADDRESS:
+ debug ("set address %d\n", ao_usb_setup.value);
+ ao_usb_address = ao_usb_setup.value;
+ ao_usb_address_pending = 1;
+ break;
+ case AO_USB_REQ_GET_DESCRIPTOR:
+ debug ("get descriptor %d\n", ao_usb_setup.value);
+ ao_usb_get_descriptor(ao_usb_setup.value);
+ break;
+ case AO_USB_REQ_GET_CONFIGURATION:
+ debug ("get configuration %d\n", ao_usb_configuration);
+ ao_usb_ep0_in_queue_byte(ao_usb_configuration);
+ break;
+ case AO_USB_REQ_SET_CONFIGURATION:
+ ao_usb_configuration = ao_usb_setup.value;
+ debug ("set configuration %d\n", ao_usb_configuration);
+ ao_usb_set_configuration();
+ break;
+ }
+ break;
+ case AO_USB_RECIP_INTERFACE:
+ debug ("Interface setup packet\n");
+ switch(ao_usb_setup.request) {
+ case AO_USB_REQ_GET_STATUS:
+ ao_usb_ep0_in_queue_byte(0);
+ ao_usb_ep0_in_queue_byte(0);
+ break;
+ case AO_USB_REQ_GET_INTERFACE:
+ ao_usb_ep0_in_queue_byte(0);
+ break;
+ case AO_USB_REQ_SET_INTERFACE:
+ break;
+ }
+ break;
+ case AO_USB_RECIP_ENDPOINT:
+ debug ("Endpoint setup packet\n");
+ switch(ao_usb_setup.request) {
+ case AO_USB_REQ_GET_STATUS:
+ ao_usb_ep0_in_queue_byte(0);
+ ao_usb_ep0_in_queue_byte(0);
+ break;
+ }
+ break;
+ }
+ break;
+ case AO_USB_TYPE_CLASS:
+ debug ("Class setup packet\n");
+ switch (ao_usb_setup.request) {
+ case AO_USB_SET_LINE_CODING:
+ debug ("set line coding\n");
+ ao_usb_ep0_out_set((uint8_t *) &ao_usb_line_coding, 7);
+ break;
+ case AO_USB_GET_LINE_CODING:
+ debug ("get line coding\n");
+ ao_usb_ep0_in_set((const uint8_t *) &ao_usb_line_coding, 7);
+ break;
+ case AO_USB_SET_CONTROL_LINE_STATE:
+ break;
+ }
+ break;
+ }
+
+ /* If we're not waiting to receive data from the host,
+ * queue an IN response
+ */
+ if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN)
+ ao_usb_ep0_in_start(ao_usb_setup.length);
+}
+
+static void
+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 (receive & AO_USB_EP0_GOT_RX_DATA) {
+ debug ("\tgot rx data\n");
+ if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) {
+ ao_usb_ep0_fill();
+ if (ao_usb_ep0_out_len == 0) {
+ ao_usb_ep0_state = AO_USB_EP0_DATA_IN;
+ ao_usb_ep0_in_start(0);
+ }
+ }
+ }
+ if (receive & AO_USB_EP0_GOT_TX_ACK) {
+ debug ("\tgot tx ack\n");
+
+#if HAS_FLIGHT && AO_USB_FORCE_IDLE
+ ao_flight_force_idle = 1;
+#endif
+ /* Wait until the IN packet is received from addr 0
+ * before assigning our local address
+ */
+ if (ao_usb_address_pending)
+ ao_usb_set_address(ao_usb_address);
+ if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN)
+ ao_usb_ep0_flush();
+ }
+}
+
+void
+stm_usb_isr(void)
+{
+ uint32_t istr = stm_usb.istr;
+
+ stm_usb.istr = ~istr;
+ if (istr & (1 << STM_USB_ISTR_CTR)) {
+ uint8_t ep = istr & STM_USB_ISTR_EP_ID_MASK;
+ uint16_t epr, epr_write;
+
+ /* Preserve the SW write bits, don't mess with most HW writable bits,
+ * clear the CTR_RX and CTR_TX bits
+ */
+ epr = stm_usb.epr[ep].r;
+ epr_write = epr;
+ epr_write &= STM_USB_EPR_PRESERVE_MASK;
+ epr_write |= STM_USB_EPR_INVARIANT;
+ epr_write &= ~(1 << STM_USB_EPR_CTR_RX);
+ epr_write &= ~(1 << STM_USB_EPR_CTR_TX);
+ stm_usb.epr[ep].r = epr_write;
+
+ switch (ep) {
+ case 0:
+ ++control_count;
+ if (ao_usb_epr_ctr_rx(epr)) {
+ if (ao_usb_epr_setup(epr))
+ ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP;
+ else
+ ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA;
+ }
+ if (ao_usb_epr_ctr_tx(epr))
+ ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK;
+ ao_usb_ep0_handle(ao_usb_ep0_receive);
+ break;
+ case AO_USB_OUT_EPR:
+ ++out_count;
+ if (ao_usb_epr_ctr_rx(epr)) {
+ _rx_dbg1("RX ISR", epr);
+ ao_usb_out_avail = 1;
+ _rx_dbg0("out avail set");
+ ao_wakeup(AO_USB_OUT_SLEEP_ADDR);
+ _rx_dbg0("stdin awoken");
+ }
+ break;
+ case AO_USB_IN_EPR:
+ ++in_count;
+ _tx_dbg1("TX ISR", epr);
+ if (ao_usb_epr_ctr_tx(epr)) {
+ ao_usb_in_pending = 0;
+ ao_wakeup(&ao_usb_in_pending);
+ }
+ break;
+ case AO_USB_INT_EPR:
+ ++int_count;
+ if (ao_usb_epr_ctr_tx(epr))
+ _ao_usb_set_stat_tx(AO_USB_INT_EPR, STM_USB_EPR_STAT_TX_NAK);
+ break;
+ }
+ return;
+ }
+
+ 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);
+ }
+
+}
+
+/* Queue the current IN buffer for transmission */
+static void
+_ao_usb_in_send(void)
+{
+ _tx_dbg0("in_send start");
+ debug ("send %d\n", ao_usb_tx_count);
+ while (ao_usb_in_pending)
+ ao_sleep(&ao_usb_in_pending);
+ ao_usb_in_pending = 1;
+ if (ao_usb_tx_count != AO_USB_IN_SIZE)
+ ao_usb_in_flushed = 1;
+ ao_usb_copy_tx(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count);
+ 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 = ao_usb_tx_count;
+ ao_usb_tx_count = 0;
+ _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
+ _tx_dbg0("in_send end");
+}
+
+/* Wait for a free IN buffer. Interrupts are blocked */
+static void
+_ao_usb_in_wait(void)
+{
+ for (;;) {
+ /* Check if the current buffer is writable */
+ if (ao_usb_tx_count < AO_USB_IN_SIZE)
+ break;
+
+ _tx_dbg0("in_wait top");
+ /* Wait for an IN buffer to be ready */
+ while (ao_usb_in_pending)
+ ao_sleep(&ao_usb_in_pending);
+ _tx_dbg0("in_wait bottom");
+ }
+}
+
+void
+ao_usb_flush(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_in_flushed) {
+ _tx_dbg0("flush top");
+ _ao_usb_in_send();
+ _tx_dbg0("flush end");
+ }
+ ao_arch_release_interrupts();
+}
+
+void
+ao_usb_putchar(char c)
+{
+ if (!ao_usb_running)
+ return;
+
+ ao_arch_block_interrupts();
+ _ao_usb_in_wait();
+
+ ao_usb_in_flushed = 0;
+ ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c;
+
+ /* Send the packet when full */
+ if (ao_usb_tx_count == AO_USB_IN_SIZE) {
+ _tx_dbg0("putchar full");
+ _ao_usb_in_send();
+ _tx_dbg0("putchar flushed");
+ }
+ ao_arch_release_interrupts();
+}
+
+static void
+_ao_usb_out_recv(void)
+{
+ _rx_dbg0("out_recv top");
+ ao_usb_out_avail = 0;
+
+ ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK;
+
+ _rx_dbg1("out_recv count", ao_usb_rx_count);
+ debug ("recv %d\n", ao_usb_rx_count);
+ debug_data("Fill OUT len %d:", ao_usb_rx_count);
+ ao_usb_copy_rx(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count);
+ debug_data("\n");
+ ao_usb_rx_pos = 0;
+
+ /* ACK the packet */
+ _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID);
+}
+
+int
+_ao_usb_pollchar(void)
+{
+ uint8_t c;
+
+ if (!ao_usb_running)
+ return AO_READ_AGAIN;
+
+ for (;;) {
+ if (ao_usb_rx_pos != ao_usb_rx_count)
+ break;
+
+ _rx_dbg0("poll check");
+ /* Check to see if a packet has arrived */
+ if (!ao_usb_out_avail) {
+ _rx_dbg0("poll none");
+ return AO_READ_AGAIN;
+ }
+ _ao_usb_out_recv();
+ }
+
+ /* Pull a character out of the fifo */
+ c = ao_usb_rx_buffer[ao_usb_rx_pos++];
+ return c;
+}
+
+char
+ao_usb_getchar(void)
+{
+ int c;
+
+ ao_arch_block_interrupts();
+ while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN)
+ ao_sleep(AO_USB_OUT_SLEEP_ADDR);
+ ao_arch_release_interrupts();
+ return c;
+}
+
+#if AO_USB_DIRECTIO
+uint16_t *
+ao_usb_alloc(void)
+{
+ uint16_t *buffer;
+
+ if (!ao_usb_running)
+ return NULL;
+ buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr);
+ ao_usb_sram_addr += AO_USB_IN_SIZE;
+ return buffer;
+}
+
+void
+ao_usb_free(uint16_t *addr)
+{
+ uint16_t offset = ao_usb_packet_buffer_offset(addr);
+ if (offset < ao_usb_sram_addr)
+ ao_usb_sram_addr = offset;
+}
+
+void
+ao_usb_write(uint16_t *buffer, uint16_t len)
+{
+ ao_arch_block_interrupts();
+
+ /* Flush any pending regular */
+ if (ao_usb_tx_count)
+ _ao_usb_in_send();
+
+ while (ao_usb_in_pending)
+ ao_sleep(&ao_usb_in_pending);
+ ao_usb_in_pending = 1;
+ ao_usb_in_flushed = (len != AO_USB_IN_SIZE);
+ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer);
+ ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = len;
+ _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID);
+ ao_arch_release_interrupts();
+}
+#endif
+
+void
+ao_usb_disable(void)
+{
+ ao_arch_block_interrupts();
+ stm_usb.cntr = (1 << STM_USB_CNTR_FRES);
+ stm_usb.istr = 0;
+
+ /* Disable USB pull-up */
+ stm_usb.bcdr &= ~(1 << STM_USB_BCDR_DPPU);
+
+ /* Switch off the device */
+ stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES);
+
+ /* Disable the interface */
+ stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN);
+ ao_arch_release_interrupts();
+}
+
+void
+ao_usb_enable(void)
+{
+ int t;
+
+ /* Select HSI48 as USB clock source */
+ stm_rcc.cfgr3 &= ~(1 << STM_RCC_CFGR3_USBSW);
+
+ /* Enable USB device */
+ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USBEN);
+
+ /* Clear reset condition */
+ stm_rcc.apb1rstr &= ~(1 << STM_RCC_APB1RSTR_USBRST);
+
+ /* Disable USB pull-up */
+ stm_usb.bcdr &= ~(1 << STM_USB_BCDR_DPPU);
+
+ /* Do not touch the GPIOA configuration; USB takes priority
+ * over GPIO on pins A11 and A12, but if you select alternate
+ * input 10 (the documented correct selection), then USB is
+ * pulled low and doesn't work at all
+ */
+
+ ao_arch_block_interrupts();
+
+ /* Route interrupts */
+ stm_nvic_set_enable(STM_ISR_USB_POS);
+ stm_nvic_set_priority(STM_ISR_USB_POS, 3);
+
+ ao_usb_configuration = 0;
+
+ /* Set up buffer descriptors */
+ ao_usb_init_btable();
+
+ /* Reset the USB controller */
+ stm_usb.cntr = (1 << STM_USB_CNTR_FRES);
+
+ /* Clear the reset bit */
+ stm_usb.cntr = 0;
+
+ /* Clear any spurious interrupts */
+ stm_usb.istr = 0;
+
+ ao_usb_set_ep0();
+
+ debug ("ao_usb_enable\n");
+
+ /* Enable interrupts */
+ 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) |
+ (1 << STM_USB_CNTR_RESETM) |
+ (0 << STM_USB_CNTR_SOFM) |
+ (0 << STM_USB_CNTR_ESOFM) |
+ (0 << STM_USB_CNTR_RESUME) |
+ (0 << STM_USB_CNTR_FSUSP) |
+ (0 << STM_USB_CNTR_LP_MODE) |
+ (0 << STM_USB_CNTR_PDWN) |
+ (0 << STM_USB_CNTR_FRES));
+
+ ao_arch_release_interrupts();
+
+ for (t = 0; t < 1000; t++)
+ ao_arch_nop();
+
+ /* Enable USB pull-up */
+ stm_usb.bcdr |= (1 << STM_USB_BCDR_DPPU);
+}
+
+#if USB_ECHO
+struct ao_task ao_usb_echo_task;
+
+static void
+ao_usb_echo(void)
+{
+ char c;
+
+ for (;;) {
+ c = ao_usb_getchar();
+ ao_usb_putchar(c);
+ ao_usb_flush();
+ }
+}
+#endif
+
+#if USB_DEBUG
+static void
+ao_usb_irq(void)
+{
+ printf ("control: %d out: %d in: %d int: %d reset: %d\n",
+ control_count, out_count, in_count, int_count, reset_count);
+}
+
+__code struct ao_cmds ao_usb_cmds[] = {
+ { ao_usb_irq, "I\0Show USB interrupt counts" },
+ { 0, NULL }
+};
+#endif
+
+void
+ao_usb_init(void)
+{
+ /* Turn on syscfg */
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+ /* Set PA11/PA12 remapping bit */
+ stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP);
+
+ ao_usb_enable();
+
+ 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
+ ao_cmd_register(&ao_usb_cmds[0]);
+#endif
+#if !USB_ECHO
+#if USE_USB_STDIO
+ ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
+#endif
+#endif
+}
+
+#if TX_DBG || RX_DBG
+
+struct ao_usb_dbg {
+ int line;
+ char *msg;
+ uint32_t value;
+ uint32_t primask;
+#if TX_DBG
+ uint16_t in_count;
+ uint32_t in_epr;
+ uint32_t in_pending;
+ uint32_t tx_count;
+ uint32_t in_flushed;
+#endif
+#if RX_DBG
+ uint8_t rx_count;
+ uint8_t rx_pos;
+ uint8_t out_avail;
+ uint32_t out_epr;
+#endif
+};
+
+#define NUM_USB_DBG 128
+
+static struct ao_usb_dbg dbg[128];
+static int dbg_i;
+
+static void _dbg(int line, char *msg, uint32_t value)
+{
+ uint32_t primask;
+ dbg[dbg_i].line = line;
+ dbg[dbg_i].msg = msg;
+ dbg[dbg_i].value = value;
+ asm("mrs %0,primask" : "=&r" (primask));
+ dbg[dbg_i].primask = primask;
+#if TX_DBG
+ dbg[dbg_i].in_count = in_count;
+ dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR];
+ dbg[dbg_i].in_pending = ao_usb_in_pending;
+ dbg[dbg_i].tx_count = ao_usb_tx_count;
+ dbg[dbg_i].in_flushed = ao_usb_in_flushed;
+#endif
+#if RX_DBG
+ dbg[dbg_i].rx_count = ao_usb_rx_count;
+ dbg[dbg_i].rx_pos = ao_usb_rx_pos;
+ dbg[dbg_i].out_avail = ao_usb_out_avail;
+ dbg[dbg_i].out_epr = stm_usb.epr[AO_USB_OUT_EPR];
+#endif
+ if (++dbg_i == NUM_USB_DBG)
+ dbg_i = 0;
+}
+#endif
--- /dev/null
+stm_gpiof = 0x48001400;
+stm_gpioc = 0x48000800;
+stm_gpiob = 0x48000400;
+stm_gpioa = 0x48000000;
+
+stm_tsc = 0x40024000;
+stm_crc = 0x40023000;
+stm_flash = 0x40022000;
+stm_rcc = 0x40021000;
+stm_dma = 0x40020000;
+stm_dbgmcu = 0x40015800;
+stm_tim17 = 0x40014800;
+stm_tim16 = 0x40014400;
+stm_usart1 = 0x40013800;
+stm_spi1 = 0x40013000;
+stm_tim1 = 0x40012c00;
+stm_adc = 0x40012400;
+
+stm_exti = 0x40010400;
+stm_syscfg = 0x40010000;
+
+stm_cec = 0x40007800;
+
+stm_pwr = 0x40007000;
+stm_crs = 0x40006c00;
+
+stm_bxcan = 0x40006400;
+stm_usb_sram = 0x40006000;
+stm_usb = 0x40005c00;
+
+stm_i2c1 = 0x40005400;
+
+stm_usart2 = 0x40004400;
+
+stm_spi2 = 0x40003800; /* docs are broken here */
+
+stm_iwdg = 0x40003000;
+stm_wwdg = 0x40002c00;
+stm_rtc = 0x40002800;
+
+stm_tim14 = 0x40002000;
+
+stm_tim3 = 0x40000400;
+stm_tim2 = 0x40000000;
+
+stm_systick = 0xe000e010;
+
+stm_nvic = 0xe000e100;
+
+stm_scb = 0xe000ed00;
+
+stm_mpu = 0xe000ed90;
+
+/* calibration data in system memory */
+stm_cal = 0x1ffff7b8;
+stm_flash_size_04x = 0x1ffff7cc;
+stm_device_id = 0x1ff80050;
--- /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 _STM32F0_H_
+#define _STM32F0_H_
+
+#include <stdint.h>
+
+typedef volatile uint32_t vuint32_t;
+typedef volatile void * vvoid_t;
+typedef volatile uint16_t vuint16_t;
+typedef volatile uint8_t vuint8_t;
+
+struct stm_gpio {
+ vuint32_t moder;
+ vuint32_t otyper;
+ vuint32_t ospeedr;
+ vuint32_t pupdr;
+
+ vuint32_t idr;
+ vuint32_t odr;
+ vuint32_t bsrr;
+ vuint32_t lckr;
+
+ vuint32_t afrl;
+ vuint32_t afrh;
+ vuint32_t brr;
+};
+
+#define STM_MODER_SHIFT(pin) ((pin) << 1)
+#define STM_MODER_MASK 3
+#define STM_MODER_INPUT 0
+#define STM_MODER_OUTPUT 1
+#define STM_MODER_ALTERNATE 2
+#define STM_MODER_ANALOG 3
+
+static inline void
+stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+ gpio->moder = ((gpio->moder &
+ ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) |
+ value << STM_MODER_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_moder_get(struct stm_gpio *gpio, int pin) {
+ return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK;
+}
+
+#define STM_OTYPER_SHIFT(pin) (pin)
+#define STM_OTYPER_MASK 1
+#define STM_OTYPER_PUSH_PULL 0
+#define STM_OTYPER_OPEN_DRAIN 1
+
+static inline void
+stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+ gpio->otyper = ((gpio->otyper &
+ ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) |
+ value << STM_OTYPER_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_otyper_get(struct stm_gpio *gpio, int pin) {
+ return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK;
+}
+
+#define STM_OSPEEDR_SHIFT(pin) ((pin) << 1)
+#define STM_OSPEEDR_MASK 3
+#define STM_OSPEEDR_LOW 0 /* 2MHz */
+#define STM_OSPEEDR_MEDIUM 1 /* 10MHz */
+#define STM_OSPEEDR_HIGH 3 /* 10-50MHz */
+
+static inline void
+stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) {
+ gpio->ospeedr = ((gpio->ospeedr &
+ ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) |
+ value << STM_OSPEEDR_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_ospeedr_get(struct stm_gpio *gpio, int pin) {
+ return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK;
+}
+
+#define STM_PUPDR_SHIFT(pin) ((pin) << 1)
+#define STM_PUPDR_MASK 3
+#define STM_PUPDR_NONE 0
+#define STM_PUPDR_PULL_UP 1
+#define STM_PUPDR_PULL_DOWN 2
+#define STM_PUPDR_RESERVED 3
+
+static inline void
+stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
+ gpio->pupdr = ((gpio->pupdr &
+ ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) |
+ value << STM_PUPDR_SHIFT(pin));
+}
+
+static inline uint32_t
+stm_pupdr_get(struct stm_gpio *gpio, int pin) {
+ return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK;
+}
+
+#define STM_AFR_SHIFT(pin) ((pin) << 2)
+#define STM_AFR_MASK 0xf
+#define STM_AFR_NONE 0
+#define STM_AFR_AF0 0x0
+#define STM_AFR_AF1 0x1
+#define STM_AFR_AF2 0x2
+#define STM_AFR_AF3 0x3
+#define STM_AFR_AF4 0x4
+#define STM_AFR_AF5 0x5
+#define STM_AFR_AF6 0x6
+#define STM_AFR_AF7 0x7
+
+static inline void
+stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) {
+ /*
+ * Set alternate pin mode too
+ */
+ stm_moder_set(gpio, pin, STM_MODER_ALTERNATE);
+ if (pin < 8)
+ gpio->afrl = ((gpio->afrl &
+ ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) |
+ value << STM_AFR_SHIFT(pin));
+ else {
+ pin -= 8;
+ gpio->afrh = ((gpio->afrh &
+ ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) |
+ value << STM_AFR_SHIFT(pin));
+ }
+}
+
+static inline uint32_t
+stm_afr_get(struct stm_gpio *gpio, int pin) {
+ if (pin < 8)
+ return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK;
+ else {
+ pin -= 8;
+ return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK;
+ }
+}
+
+static inline void
+stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) {
+ /* Use the bit set/reset register to do this atomically */
+ gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin);
+}
+
+static inline uint8_t
+stm_gpio_get(struct stm_gpio *gpio, int pin) {
+ return (gpio->idr >> pin) & 1;
+}
+
+static inline uint16_t
+stm_gpio_get_all(struct stm_gpio *gpio) {
+ return gpio->idr;
+}
+
+/*
+ * We can't define these in registers.ld or our fancy
+ * ao_enable_gpio macro will expand into a huge pile of code
+ * as the compiler won't do correct constant folding and
+ * dead-code elimination
+ */
+
+extern struct stm_gpio stm_gpioa;
+extern struct stm_gpio stm_gpiob;
+extern struct stm_gpio stm_gpioc;
+extern struct stm_gpio stm_gpiof;
+
+#define stm_gpiof (*((struct stm_gpio *) 0x48001400))
+#define stm_gpioc (*((struct stm_gpio *) 0x48000800))
+#define stm_gpiob (*((struct stm_gpio *) 0x48000400))
+#define stm_gpioa (*((struct stm_gpio *) 0x48000000))
+
+/* Flash interface */
+
+struct stm_flash {
+ vuint32_t acr;
+ vuint32_t keyr;
+ vuint32_t optkeyr;
+ vuint32_t sr;
+
+ vuint32_t cr;
+ vuint32_t ar;
+ vuint32_t unused_0x18;
+ vuint32_t obr;
+
+ vuint32_t wrpr;
+};
+
+extern struct stm_flash stm_flash;
+
+#define STM_FLASH_ACR_PRFTBS (5)
+#define STM_FLASH_ACR_PRFTBE (4)
+#define STM_FLASH_ACR_LATENCY (0)
+#define STM_FLASH_ACR_LATENCY_0 0
+#define STM_FLASH_ACR_LATENCY_1 1
+
+#define STM_FLASH_PECR_OBL_LAUNCH 18
+#define STM_FLASH_PECR_ERRIE 17
+#define STM_FLASH_PECR_EOPIE 16
+#define STM_FLASH_PECR_FPRG 10
+#define STM_FLASH_PECR_ERASE 9
+#define STM_FLASH_PECR_FTDW 8
+#define STM_FLASH_PECR_DATA 4
+#define STM_FLASH_PECR_PROG 3
+#define STM_FLASH_PECR_OPTLOCK 2
+#define STM_FLASH_PECR_PRGLOCK 1
+#define STM_FLASH_PECR_PELOCK 0
+
+#define STM_FLASH_SR_EOP 5
+#define STM_FLASH_SR_WRPRTERR 4
+#define STM_FLASH_SR_PGERR 2
+#define STM_FLASH_SR_BSY 0
+
+#define STM_FLASH_CR_OBL_LAUNCH 13
+#define STM_FLASH_CR_EOPIE 12
+#define STM_FLASH_CR_ERRIE 10
+#define STM_FLASH_CR_OPTWRE 9
+#define STM_FLASH_CR_LOCK 7
+#define STM_FLASH_CR_STRT 6
+#define STM_FLASH_CR_OPTER 5
+#define STM_FLASH_CR_OPTPG 4
+#define STM_FLASH_CR_MER 2
+#define STM_FLASH_CR_PER 1
+#define STM_FLASH_CR_PG 0
+
+#define STM_FLASH_OBR_DATA1 24
+#define STM_FLASH_OBR_DATA0 16
+#define STM_FLASH_OBR_BOOT_SEL 15
+#define STM_FLASH_OBR_RAM_PARITY_CHECK 14
+#define STM_FLASH_OBR_VDDA_MONITOR 13
+#define STM_FLASH_OBR_NBOOT1 12
+#define STM_FLASH_OBR_NBOOT0 11
+#define STM_FLASH_OBR_NRST_STDBY 10
+#define STM_FLASH_OBR_NRST_STOP 9
+#define STM_FLASH_OBR_WDG_SW 8
+#define STM_FLASH_OBR_RDPRT 1
+#define STM_FLASH_OBR_RDPRT_LEVEL0 0
+#define STM_FLASH_OBR_RDPRT_LEVEL1 1
+#define STM_FLASH_OBR_RDPRT_LEVEL2 3
+#define STM_FLASH_OBR_OPTERR 0
+
+#define STM_FLASH_KEYR_KEY1 0x45670123
+#define STM_FLASH_KEYR_KEY2 0xcdef89ab
+
+struct stm_rcc {
+ vuint32_t cr;
+ vuint32_t cfgr;
+ vuint32_t cir;
+ vuint32_t apb2rstr;
+
+ vuint32_t apb1rstr;
+ vuint32_t ahbenr;
+ vuint32_t apb2enr;
+ vuint32_t apb1enr;
+
+ vuint32_t bdcr;
+ vuint32_t csr;
+ vuint32_t ahbrstr;
+ vuint32_t cfgr2;
+
+ vuint32_t cfgr3;
+ vuint32_t cr2;
+};
+
+extern struct stm_rcc stm_rcc;
+
+/* Nominal high speed internal oscillator frequency is 16MHz */
+#define STM_HSI_FREQ 16000000
+
+#define STM_RCC_CR_PLLRDY (25)
+#define STM_RCC_CR_PLLON (24)
+#define STM_RCC_CR_CSSON (19)
+#define STM_RCC_CR_HSEBYP (18)
+#define STM_RCC_CR_HSERDY (17)
+#define STM_RCC_CR_HSEON (16)
+#define STM_RCC_CR_HSICAL (8)
+#define STM_RCC_CR_HSITRIM (3)
+#define STM_RCC_CR_HSIRDY (1)
+#define STM_RCC_CR_HSION (0)
+
+#define STM_RCC_CFGR_PLL_NODIV (31)
+#define STM_RCC_CFGR_PLL_NODIV_DIV_1 1
+#define STM_RCC_CFGR_PLL_NODIV_DIV_2 0
+
+#define STM_RCC_CFGR_MCOPRE (28)
+#define STM_RCC_CFGR_MCOPRE_DIV_1 0
+#define STM_RCC_CFGR_MCOPRE_DIV_2 1
+#define STM_RCC_CFGR_MCOPRE_DIV_4 2
+#define STM_RCC_CFGR_MCOPRE_DIV_8 3
+#define STM_RCC_CFGR_MCOPRE_DIV_16 4
+#define STM_RCC_CFGR_MCOPRE_DIV_32 5
+#define STM_RCC_CFGR_MCOPRE_DIV_64 6
+#define STM_RCC_CFGR_MCOPRE_DIV_128 7
+#define STM_RCC_CFGR_MCOPRE_DIV_MASK 7
+
+#define STM_RCC_CFGR_MCO (24)
+# define STM_RCC_CFGR_MCO_DISABLE 0
+
+#define STM_RCC_CFGR_PLLMUL (18)
+#define STM_RCC_CFGR_PLLMUL_2 0
+#define STM_RCC_CFGR_PLLMUL_3 1
+#define STM_RCC_CFGR_PLLMUL_4 2
+#define STM_RCC_CFGR_PLLMUL_5 3
+#define STM_RCC_CFGR_PLLMUL_6 4
+#define STM_RCC_CFGR_PLLMUL_7 5
+#define STM_RCC_CFGR_PLLMUL_8 6
+#define STM_RCC_CFGR_PLLMUL_9 7
+#define STM_RCC_CFGR_PLLMUL_10 8
+#define STM_RCC_CFGR_PLLMUL_11 9
+#define STM_RCC_CFGR_PLLMUL_12 10
+#define STM_RCC_CFGR_PLLMUL_13 11
+#define STM_RCC_CFGR_PLLMUL_14 12
+#define STM_RCC_CFGR_PLLMUL_15 13
+#define STM_RCC_CFGR_PLLMUL_16 14
+#define STM_RCC_CFGR_PLLMUL_MASK 0xf
+
+#define STM_RCC_CFGR_PLLXTPRE (17)
+
+#define STM_RCC_CFGR_PLLSRC (15)
+# define STM_RCC_CFGR_PLLSRC_HSI_DIV_2 0
+# define STM_RCC_CFGR_PLLSRC_HSI 1
+# define STM_RCC_CFGR_PLLSRC_HSE 2
+# define STM_RCC_CFGR_PLLSRC_HSI48 3
+
+#define STM_RCC_CFGR_ADCPRE (14)
+
+#define STM_RCC_CFGR_PPRE (8)
+#define STM_RCC_CFGR_PPRE_DIV_1 0
+#define STM_RCC_CFGR_PPRE_DIV_2 4
+#define STM_RCC_CFGR_PPRE_DIV_4 5
+#define STM_RCC_CFGR_PPRE_DIV_8 6
+#define STM_RCC_CFGR_PPRE_DIV_16 7
+#define STM_RCC_CFGR_PPRE_MASK 7
+
+#define STM_RCC_CFGR_HPRE (4)
+#define STM_RCC_CFGR_HPRE_DIV_1 0
+#define STM_RCC_CFGR_HPRE_DIV_2 8
+#define STM_RCC_CFGR_HPRE_DIV_4 9
+#define STM_RCC_CFGR_HPRE_DIV_8 0xa
+#define STM_RCC_CFGR_HPRE_DIV_16 0xb
+#define STM_RCC_CFGR_HPRE_DIV_64 0xc
+#define STM_RCC_CFGR_HPRE_DIV_128 0xd
+#define STM_RCC_CFGR_HPRE_DIV_256 0xe
+#define STM_RCC_CFGR_HPRE_DIV_512 0xf
+#define STM_RCC_CFGR_HPRE_MASK 0xf
+
+#define STM_RCC_CFGR_SWS (2)
+#define STM_RCC_CFGR_SWS_HSI 0
+#define STM_RCC_CFGR_SWS_HSE 1
+#define STM_RCC_CFGR_SWS_PLL 2
+#define STM_RCC_CFGR_SWS_HSI48 3
+#define STM_RCC_CFGR_SWS_MASK 3
+
+#define STM_RCC_CFGR_SW (0)
+#define STM_RCC_CFGR_SW_HSI 0
+#define STM_RCC_CFGR_SW_HSE 1
+#define STM_RCC_CFGR_SW_PLL 2
+#define STM_RCC_CFGR_SW_HSI48 3
+#define STM_RCC_CFGR_SW_MASK 3
+
+#define STM_RCC_APB2RSTR_DBGMCURST 22
+#define STM_RCC_APB2RSTR_TIM17RST 18
+#define STM_RCC_APB2RSTR_TIM16RST 17
+#define STM_RCC_APB2RSTR_TIM15RST 16
+#define STM_RCC_APB2RSTR_USART1RST 14
+#define STM_RCC_APB2RSTR_SPI1RST 12
+#define STM_RCC_APB2RSTR_TIM1RST 11
+#define STM_RCC_APB2RSTR_ADCRST 9
+#define STM_RCC_APB2RSTR_USART8RST 7
+#define STM_RCC_APB2RSTR_USART7RST 6
+#define STM_RCC_APB2RSTR_USART6RST 5
+#define STM_RCC_APB2RSTR_SYSCFGRST 1
+
+#define STM_RCC_APB1RSTR_CECRST 30
+#define STM_RCC_APB1RSTR_DACRST 29
+#define STM_RCC_APB1RSTR_PWRRST 28
+#define STM_RCC_APB1RSTR_CRSRST 27
+#define STM_RCC_APB1RSTR_CANRST 25
+#define STM_RCC_APB1RSTR_USBRST 23
+#define STM_RCC_APB1RSTR_I2C2RST 22
+#define STM_RCC_APB1RSTR_I1C1RST 21
+#define STM_RCC_APB1RSTR_USART5RST 20
+#define STM_RCC_APB1RSTR_USART4RST 19
+#define STM_RCC_APB1RSTR_USART3RST 18
+#define STM_RCC_APB1RSTR_USART2RST 17
+#define STM_RCC_APB1RSTR_SPI2RST 14
+#define STM_RCC_APB1RSTR_WWDGRST 11
+#define STM_RCC_APB1RSTR_TIM14RST 8
+#define STM_RCC_APB1RSTR_TIM7RST 5
+#define STM_RCC_APB1RSTR_TIM6RST 4
+#define STM_RCC_APB1RSTR_TIM3RST 1
+#define STM_RCC_APB1RSTR_TIM2RST 0
+
+#define STM_RCC_AHBENR_TSCEN 24
+#define STM_RCC_AHBENR_IOPFEN 22
+#define STM_RCC_AHBENR_IOPEEN 21
+#define STM_RCC_AHBENR_IOPDEN 20
+#define STM_RCC_AHBENR_IOPCEN 19
+#define STM_RCC_AHBENR_IOPBEN 18
+#define STM_RCC_AHBENR_IOPAEN 17
+#define STM_RCC_AHBENR_CRCEN 6
+#define STM_RCC_AHBENR_FLITFEN 4
+#define STM_RCC_AHBENR_SRAMEN 2
+#define STM_RCC_AHBENR_DMA2EN 1
+#define STM_RCC_AHBENR_DMAEN 0
+
+#define STM_RCC_APB2ENR_DBGMCUEN 22
+#define STM_RCC_APB2ENR_TIM17EN 18
+#define STM_RCC_APB2ENR_TIM16EN 17
+#define STM_RCC_APB2ENR_TIM15EN 16
+#define STM_RCC_APB2ENR_USART1EN 14
+#define STM_RCC_APB2ENR_SPI1EN 12
+#define STM_RCC_APB2ENR_TIM1EN 11
+#define STM_RCC_APB2ENR_ADCEN 9
+#define STM_RCC_APB2ENR_USART8EN 7
+#define STM_RCC_APB2ENR_USART7EN 6
+#define STM_RCC_APB2ENR_USART6EN 5
+#define STM_RCC_APB2ENR_SYSCFGCOMPEN 0
+
+#define STM_RCC_APB1ENR_CECEN 30
+#define STM_RCC_APB1ENR_DACEN 29
+#define STM_RCC_APB1ENR_PWREN 28
+#define STM_RCC_APB1ENR_CRSEN 27
+#define STM_RCC_APB1ENR_CANEN 25
+#define STM_RCC_APB1ENR_USBEN 23
+#define STM_RCC_APB1ENR_I2C2EN 22
+#define STM_RCC_APB1ENR_IC21EN 21
+#define STM_RCC_APB1ENR_USART5EN 20
+#define STM_RCC_APB1ENR_USART4EN 19
+#define STM_RCC_APB1ENR_USART3EN 18
+#define STM_RCC_APB1ENR_USART2EN 17
+#define STM_RCC_APB1ENR_SPI2EN 14
+#define STM_RCC_APB1ENR_WWDGEN 11
+#define STM_RCC_APB1ENR_TIM14EN 8
+#define STM_RCC_APB1ENR_TIM7EN 5
+#define STM_RCC_APB1ENR_TIM6EN 4
+#define STM_RCC_APB1ENR_TIM3EN 1
+#define STM_RCC_APB1ENR_TIM2EN 0
+
+#define STM_RCC_CSR_LPWRRSTF (31)
+#define STM_RCC_CSR_WWDGRSTF (30)
+#define STM_RCC_CSR_IWDGRSTF (29)
+#define STM_RCC_CSR_SFTRSTF (28)
+#define STM_RCC_CSR_PORRSTF (27)
+#define STM_RCC_CSR_PINRSTF (26)
+#define STM_RCC_CSR_OBLRSTF (25)
+#define STM_RCC_CSR_RMVF (24)
+#define STM_RCC_CSR_V18PWRRSTF (23)
+#define STM_RCC_CSR_LSIRDY (1)
+#define STM_RCC_CSR_LSION (0)
+
+#define STM_RCC_CR2_HSI48CAL 24
+#define STM_RCC_CR2_HSI48RDY 17
+#define STM_RCC_CR2_HSI48ON 16
+#define STM_RCC_CR2_HSI14CAL 8
+#define STM_RCC_CR2_HSI14TRIM 3
+#define STM_RCC_CR2_HSI14DIS 2
+#define STM_RCC_CR2_HSI14RDY 1
+#define STM_RCC_CR2_HSI14ON 0
+
+#define STM_RCC_CFGR3_USART3SW 18
+#define STM_RCC_CFGR3_USART2SW 16
+#define STM_RCC_CFGR3_ADCSW 8
+#define STM_RCC_CFGR3_USBSW 7
+#define STM_RCC_CFGR3_CECSW 6
+#define STM_RCC_CFGR3_I2C1SW 4
+#define STM_RCC_CFGR3_USART1SW 0
+
+struct stm_crs {
+ vuint32_t cr;
+ vuint32_t cfgr;
+ vuint32_t isr;
+ vuint32_t icr;
+};
+
+extern struct stm_crs stm_crs;
+
+#define STM_CRS_CR_TRIM 8
+#define STM_CRS_CR_SWSYNC 7
+#define STM_CRS_CR_AUTOTRIMEN 6
+#define STM_CRS_CR_CEN 5
+#define STM_CRS_CR_ESYNCIE 3
+#define STM_CRS_CR_ERRIE 2
+#define STM_CRS_CR_SYNCWARNIE 1
+#define STM_CRS_CR_SYNCOKIE 0
+
+#define STM_CRS_CFGR_SYNCPOL 31
+#define STM_CRS_CFGR_SYNCSRC 28
+#define STM_CRS_CFGR_SYNCSRC_GPIO 0
+#define STM_CRS_CFGR_SYNCSRC_LSE 1
+#define STM_CRS_CFGR_SYNCSRC_USB 2
+#define STM_CRS_CFGR_SYNCDIV 24
+#define STM_CRS_CFGR_SYNCDIV_1 0
+#define STM_CRS_CFGR_SYNCDIV_2 1
+#define STM_CRS_CFGR_SYNCDIV_4 2
+#define STM_CRS_CFGR_SYNCDIV_8 3
+#define STM_CRS_CFGR_SYNCDIV_16 4
+#define STM_CRS_CFGR_SYNCDIV_32 5
+#define STM_CRS_CFGR_SYNCDIV_64 6
+#define STM_CRS_CFGR_SYNCDIV_128 7
+#define STM_CRS_CFGR_FELIM 16
+#define STM_CRS_CFGR_RELOAD 0
+
+#define STM_CRS_ISR_FECAP 16
+#define STM_CRS_ISR_FEDIR 15
+#define STM_CRS_ISR_TRIMOVF 10
+#define STM_CRS_ISR_SYNCMISS 9
+#define STM_CRS_ISR_SYNCERR 8
+#define STM_CRS_ISR_ESYNCF 3
+#define STM_CRS_ISR_ERRF 2
+#define STM_CRS_ISR_SYNCWARNF 1
+#define STM_CRS_ISR_SYNCOKF 0
+
+#define STM_CRS_ICR_ESYNCC 3
+#define STM_CRS_ICR_ERRC 2
+#define STM_CRS_ICR_SYNCWARNC 1
+#define STM_CRS_ICR_SYNCOKC 0
+
+struct stm_pwr {
+ vuint32_t cr;
+ vuint32_t csr;
+};
+
+extern struct stm_pwr stm_pwr;
+
+#define STM_PWR_CR_DBP (8)
+
+#define STM_PWR_CR_PLS (5)
+#define STM_PWR_CR_PLS_2_0 0
+#define STM_PWR_CR_PLS_2_1 1
+#define STM_PWR_CR_PLS_2_2 2
+#define STM_PWR_CR_PLS_2_3 3
+#define STM_PWR_CR_PLS_2_4 4
+#define STM_PWR_CR_PLS_2_5 5
+#define STM_PWR_CR_PLS_2_6 6
+#define STM_PWR_CR_PLS_EXT 7
+#define STM_PWR_CR_PLS_MASK 7
+
+#define STM_PWR_CR_PVDE (4)
+#define STM_PWR_CR_CSBF (3)
+#define STM_PWR_CR_CWUF (2)
+#define STM_PWR_CR_PDDS (1)
+#define STM_PWR_CR_LPSDSR (0)
+
+#define STM_PWR_CSR_EWUP3 (10)
+#define STM_PWR_CSR_EWUP2 (9)
+#define STM_PWR_CSR_EWUP1 (8)
+#define STM_PWR_CSR_REGLPF (5)
+#define STM_PWR_CSR_VOSF (4)
+#define STM_PWR_CSR_VREFINTRDYF (3)
+#define STM_PWR_CSR_PVDO (2)
+#define STM_PWR_CSR_SBF (1)
+#define STM_PWR_CSR_WUF (0)
+
+struct stm_crc {
+ union {
+ vuint32_t u32;
+ vuint16_t u16;
+ vuint8_t u8;
+ } dr;
+ vuint32_t idr;
+ vuint32_t cr;
+ uint32_t _0c;
+
+ vuint32_t init;
+ vuint32_t pol;
+};
+
+extern struct stm_crc stm_crc;
+
+#define stm_crc (*((struct stm_crc *) 0x40023000))
+
+#define STM_CRC_CR_REV_OUT 7
+#define STM_CRC_CR_REV_IN 5
+#define STM_CRC_CR_REV_IN_NONE 0
+#define STM_CRC_CR_REV_IN_BY_BYTE 1
+#define STM_CRC_CR_REV_IN_BY_HALF_WORD 2
+#define STM_CRC_CR_REV_IN_BY_WORD 3
+#define STM_CRC_CR_POLYSIZE 3
+#define STM_CRC_CR_POLYSIZE_32 0
+#define STM_CRC_CR_POLYSIZE_16 1
+#define STM_CRC_CR_POLYSIZE_8 2
+#define STM_CRC_CR_POLYSIZE_7 3
+#define STM_CRC_CR_RESET 0
+
+/* The SYSTICK starts at 0xe000e010 */
+
+struct stm_systick {
+ vuint32_t csr;
+ vuint32_t rvr;
+ vuint32_t cvr;
+ vuint32_t calib;
+};
+
+extern struct stm_systick stm_systick;
+
+#define STM_SYSTICK_CSR_ENABLE 0
+#define STM_SYSTICK_CSR_TICKINT 1
+#define STM_SYSTICK_CSR_CLKSOURCE 2
+#define STM_SYSTICK_CSR_CLKSOURCE_EXTERNAL 0
+#define STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 1
+#define STM_SYSTICK_CSR_COUNTFLAG 16
+
+/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */
+
+struct stm_nvic {
+ vuint32_t iser; /* 0x000 0xe000e100 Set Enable Register */
+
+ uint8_t _unused020[0x080 - 0x004];
+
+ vuint32_t icer; /* 0x080 0xe000e180 Clear Enable Register */
+
+ uint8_t _unused0a0[0x100 - 0x084];
+
+ vuint32_t ispr; /* 0x100 0xe000e200 Set Pending Register */
+
+ uint8_t _unused120[0x180 - 0x104];
+
+ vuint32_t icpr; /* 0x180 0xe000e280 Clear Pending Register */
+
+ uint8_t _unused1a0[0x300 - 0x184];
+
+ vuint32_t ipr[8]; /* 0x300 0xe000e400 Priority Register */
+};
+
+extern struct stm_nvic stm_nvic;
+
+#define IRQ_MASK(irq) (1 << (irq))
+#define IRQ_BOOL(v,irq) (((v) >> (irq)) & 1)
+
+static inline void
+stm_nvic_set_enable(int irq) {
+ stm_nvic.iser = IRQ_MASK(irq);
+}
+
+static inline void
+stm_nvic_clear_enable(int irq) {
+ stm_nvic.icer = IRQ_MASK(irq);
+}
+
+static inline int
+stm_nvic_enabled(int irq) {
+ return IRQ_BOOL(stm_nvic.iser, irq);
+}
+
+static inline void
+stm_nvic_set_pending(int irq) {
+ stm_nvic.ispr = IRQ_MASK(irq);
+}
+
+static inline void
+stm_nvic_clear_pending(int irq) {
+ stm_nvic.icpr = IRQ_MASK(irq);
+}
+
+static inline int
+stm_nvic_pending(int irq) {
+ return IRQ_BOOL(stm_nvic.ispr, irq);
+}
+
+#define IRQ_PRIO_REG(irq) ((irq) >> 2)
+#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3)
+#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq))
+
+static inline void
+stm_nvic_set_priority(int irq, uint8_t prio) {
+ int n = IRQ_PRIO_REG(irq);
+ uint32_t v;
+
+ v = stm_nvic.ipr[n];
+ v &= ~IRQ_PRIO_MASK(irq);
+ v |= (prio) << IRQ_PRIO_BIT(irq);
+ stm_nvic.ipr[n] = v;
+}
+
+static inline uint8_t
+stm_nvic_get_priority(int irq) {
+ return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0);
+}
+
+struct stm_scb {
+ vuint32_t cpuid;
+ vuint32_t icsr;
+ vuint32_t vtor;
+ vuint32_t aircr;
+
+ vuint32_t scr;
+ vuint32_t ccr;
+ vuint32_t shpr1;
+ vuint32_t shpr2;
+
+ vuint32_t shpr3;
+ vuint32_t shcrs;
+ vuint32_t cfsr;
+ vuint32_t hfsr;
+
+ uint32_t unused_30;
+ vuint32_t mmfar;
+ vuint32_t bfar;
+};
+
+extern struct stm_scb stm_scb;
+
+#define STM_SCB_AIRCR_VECTKEY 16
+#define STM_SCB_AIRCR_VECTKEY_KEY 0x05fa
+#define STM_SCB_AIRCR_PRIGROUP 8
+#define STM_SCB_AIRCR_SYSRESETREQ 2
+#define STM_SCB_AIRCR_VECTCLRACTIVE 1
+#define STM_SCB_AIRCR_VECTRESET 0
+
+#define isr(name) void stm_ ## name ## _isr(void);
+
+isr(nmi)
+isr(hardfault)
+isr(memmanage)
+isr(busfault)
+isr(usagefault)
+isr(svc)
+isr(debugmon)
+isr(pendsv)
+isr(systick)
+isr(wwdg)
+isr(pvd)
+isr(tamper_stamp)
+isr(rtc_wkup)
+isr(flash)
+isr(rcc)
+isr(exti0)
+isr(exti1)
+isr(exti2)
+isr(exti3)
+isr(exti4)
+isr(dma1_channel1)
+isr(dma1_channel2)
+isr(dma1_channel3)
+isr(dma1_channel4)
+isr(dma1_channel5)
+isr(dma1_channel6)
+isr(dma1_channel7)
+isr(adc1)
+isr(usb_hp)
+isr(usb_lp)
+isr(dac)
+isr(comp)
+isr(exti9_5)
+isr(lcd)
+isr(tim9)
+isr(tim10)
+isr(tim11)
+isr(tim2)
+isr(tim3)
+isr(tim4)
+isr(i2c1_ev)
+isr(i2c1_er)
+isr(i2c2_ev)
+isr(i2c2_er)
+isr(spi1)
+isr(spi2)
+isr(usart1)
+isr(usart2)
+isr(usart3)
+isr(exti15_10)
+isr(rtc_alarm)
+isr(usb_fs_wkup)
+isr(tim6)
+isr(tim7)
+
+#undef isr
+
+#define STM_ISR_WWDG_POS 0
+#define STM_ISR_PVD_VDDIO2_POS 1
+#define STM_ISR_RTC_POS 2
+#define STM_ISR_FLASH_POS 3
+#define STM_ISR_RCC_CRS_POS 4
+#define STM_ISR_EXTI0_1_POS 5
+#define STM_ISR_EXTI2_3_POS 6
+#define STM_ISR_EXTI4_15_POS 7
+#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_ADC_COMP_POS 12
+#define STM_ISR_TIM1_BRK_UP_TRG_COM_POS 13
+#define STM_ISR_TIM1_CC_POS 14
+#define STM_ISR_TIM2_POS 15
+#define STM_ISR_TIM3_POS 16
+#define STM_ISR_TIM6_DAC_POS 17
+#define STM_ISR_TIM7_POS 18
+#define STM_ISR_TIM14_POS 19
+#define STM_ISR_TIM15_POS 20
+#define STM_ISR_TIM16_POS 21
+#define STM_ISR_TIM17_POS 22
+#define STM_ISR_I2C1_POS 23
+#define STM_ISR_I2C2_POS 24
+#define STM_ISR_SPI1_POS 25
+#define STM_ISR_SPI2_POS 26
+#define STM_ISR_USART1_POS 27
+#define STM_ISR_USART2_POS 28
+#define STM_ISR_UASART3_4_5_6_7_8_POS 29
+#define STM_ISR_CEC_CAN_POS 30
+#define STM_ISR_USB_POS 31
+
+struct stm_syscfg {
+ vuint32_t cfgr1;
+ vuint32_t exticr[4];
+ vuint32_t cfgr2;
+};
+
+extern struct stm_syscfg stm_syscfg;
+
+#define STM_SYSCFG_CFGR1_TIM3_DMA_RMP 30
+#define STM_SYSCFG_CFGR1_TIM2_DMA_RMP 29
+#define STM_SYSCFG_CFGR1_TIM1_DMA_RMP 28
+#define STM_SYSCFG_CFGR1_I2C1_DMA_RMP 27
+#define STM_SYSCFG_CFGR1_USART3_DMA_RMP 26
+#define STM_SYSCFG_CFGR1_USART2_DMA_RMP 25
+#define STM_SYSCFG_CFGR1_SPI2_DMA_RMP 24
+#define STM_SYSCFG_CFGR1_I2C_PA10_FMP 23
+#define STM_SYSCFG_CFGR1_I2C_PA9_FMP 22
+#define STM_SYSCFG_CFGR1_I2C2_FMP 21
+#define STM_SYSCFG_CFGR1_I2C1_FMP 20
+#define STM_SYSCFG_CFGR1_I2C_PB9_FMP 19
+#define STM_SYSCFG_CFGR1_I2C_PB8_FMP 18
+#define STM_SYSCFG_CFGR1_I2C_PB7_FMP 17
+#define STM_SYSCFG_CFGR1_I2C_PB6_FMP 16
+#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP2 14
+#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP2 13
+#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP 12
+#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP 11
+#define STM_SYSCFG_CFGR1_USART1_RX_DMA_RMP 10
+#define STM_SYSCFG_CFGR1_USART1_TX_DMA_RMP 9
+#define STM_SYSCFG_CFGR1_ADC_DMA_RMP 8
+#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL 6
+#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL_TIMER16 0
+#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART1 1
+#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART4 2
+#define STM_SYSCFG_CFGR1_PA11_PA12_RMP 4
+#define STM_SYSCFG_CFGR1_MEM_MODE 0
+#define STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH 0
+#define STM_SYSCFG_CFGR1_MEM_MODE_SYSTEM_FLASH 1
+#define STM_SYSCFG_CFGR1_MEM_MODE_SRAM 3
+#define STM_SYSCFG_CFGR1_MEM_MODE_MASK 3
+
+#if 0
+static inline void
+stm_exticr_set(struct stm_gpio *gpio, int pin) {
+ uint8_t reg = pin >> 2;
+ uint8_t shift = (pin & 3) << 2;
+ uint8_t val = 0;
+
+ /* Enable SYSCFG */
+ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN);
+
+ if (gpio == &stm_gpioa)
+ val = STM_SYSCFG_EXTICR_PA;
+ else if (gpio == &stm_gpiob)
+ val = STM_SYSCFG_EXTICR_PB;
+ else if (gpio == &stm_gpioc)
+ val = STM_SYSCFG_EXTICR_PC;
+ else if (gpio == &stm_gpiof)
+ val = STM_SYSCFG_EXTICR_PF;
+
+ stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift;
+}
+#endif
+
+
+struct stm_dma_channel {
+ vuint32_t ccr;
+ vuint32_t cndtr;
+ vvoid_t cpar;
+ vvoid_t cmar;
+ vuint32_t reserved;
+};
+
+#define STM_NUM_DMA 6
+
+struct stm_dma {
+ vuint32_t isr;
+ vuint32_t ifcr;
+ struct stm_dma_channel channel[STM_NUM_DMA];
+};
+
+extern struct stm_dma stm_dma;
+
+/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh)
+ */
+
+#define STM_DMA_INDEX(channel) ((channel) - 1)
+
+#define STM_DMA_ISR(index) ((index) << 2)
+#define STM_DMA_ISR_MASK 0xf
+#define STM_DMA_ISR_TEIF 3
+#define STM_DMA_ISR_HTIF 2
+#define STM_DMA_ISR_TCIF 1
+#define STM_DMA_ISR_GIF 0
+
+#define STM_DMA_IFCR(index) ((index) << 2)
+#define STM_DMA_IFCR_MASK 0xf
+#define STM_DMA_IFCR_CTEIF 3
+#define STM_DMA_IFCR_CHTIF 2
+#define STM_DMA_IFCR_CTCIF 1
+#define STM_DMA_IFCR_CGIF 0
+
+#define STM_DMA_CCR_MEM2MEM (14)
+
+#define STM_DMA_CCR_PL (12)
+#define STM_DMA_CCR_PL_LOW (0)
+#define STM_DMA_CCR_PL_MEDIUM (1)
+#define STM_DMA_CCR_PL_HIGH (2)
+#define STM_DMA_CCR_PL_VERY_HIGH (3)
+#define STM_DMA_CCR_PL_MASK (3)
+
+#define STM_DMA_CCR_MSIZE (10)
+#define STM_DMA_CCR_MSIZE_8 (0)
+#define STM_DMA_CCR_MSIZE_16 (1)
+#define STM_DMA_CCR_MSIZE_32 (2)
+#define STM_DMA_CCR_MSIZE_MASK (3)
+
+#define STM_DMA_CCR_PSIZE (8)
+#define STM_DMA_CCR_PSIZE_8 (0)
+#define STM_DMA_CCR_PSIZE_16 (1)
+#define STM_DMA_CCR_PSIZE_32 (2)
+#define STM_DMA_CCR_PSIZE_MASK (3)
+
+#define STM_DMA_CCR_MINC (7)
+#define STM_DMA_CCR_PINC (6)
+#define STM_DMA_CCR_CIRC (5)
+#define STM_DMA_CCR_DIR (4)
+#define STM_DMA_CCR_DIR_PER_TO_MEM 0
+#define STM_DMA_CCR_DIR_MEM_TO_PER 1
+#define STM_DMA_CCR_TEIE (3)
+#define STM_DMA_CCR_HTIE (2)
+#define STM_DMA_CCR_TCIE (1)
+#define STM_DMA_CCR_EN (0)
+
+/* DMA channel assignments. When a peripheral has multiple channels
+ * (indicated with _<number>), then it can be configured to either
+ * channel using syscfg.cfgr1
+ */
+
+#define STM_DMA_CHANNEL_ADC_1 1
+#define STM_DMA_CHANNEL_ADC_2 2
+
+#define STM_DMA_CHANNEL_SPI1_RX 2
+#define STM_DMA_CHANNEL_SPI1_TX 3
+
+#define STM_DMA_CHANNEL_SPI2_RX 4
+#define STM_DMA_CHANNEL_SPI2_TX 5
+
+#define STM_DMA_CHANNEL_USART1_TX_1 2
+#define STM_DMA_CHANNEL_USART1_RX_1 3
+#define STM_DMA_CHANNEL_USART1_TX_2 4
+#define STM_DMA_CHANNEL_USART1_RX_2 5
+
+#define STM_DMA_CHANNEL_USART2_RX 4
+#define STM_DMA_CHANNEL_USART2_TX 5
+
+#define STM_DMA_CHANNEL_I2C1_TX 2
+#define STM_DMA_CHANNEL_I2C1_RX 3
+
+#define STM_DMA_CHANNEL_I2C2_TX 4
+#define STM_DMA_CHANNEL_I2C2_RX 5
+
+#define STM_DMA_CHANNEL_TIM1_CH1 2
+#define STM_DMA_CHANNEL_TIM1_CH2 3
+#define STM_DMA_CHANNEL_TIM1_CH4 4
+#define STM_DMA_CHANNEL_TIM1_TRIG 4
+#define STM_DMA_CHANNEL_TIM1_COM 4
+#define STM_DMA_CHANNEL_TIM1_CH3 5
+#define STM_DMA_CHANNEL_TIM1_UP 5
+
+#define STM_DMA_CHANNEL_TIM2_CH3 1
+#define STM_DMA_CHANNEL_TIM2_UP 2
+#define STM_DMA_CHANNEL_TIM2_CH2 3
+#define STM_DMA_CHANNEL_TIM2_CH4 4
+#define STM_DMA_CHANNEL_TIM2_CH1 5
+
+#define STM_DMA_CHANNEL_TIM3_CH3 2
+#define STM_DMA_CHANNEL_TIM3_CH4 3
+#define STM_DMA_CHANNEL_TIM3_UP 3
+#define STM_DMA_CHANNEL_TIM3_CH1 4
+#define STM_DMA_CHANNEL_TIM3_TRIG 4
+
+#define STM_DMA_CHANNEL_TIM6_UP_DAC 2
+
+#define STM_DMA_CHANNEL_TIM15_CH1 5
+#define STM_DMA_CHANNEL_TIM15_UP 5
+#define STM_DMA_CHANNEL_TIM15_TRIG 5
+#define STM_DMA_CHANNEL_TIM15_COM 5
+
+#define STM_DMA_CHANNEL_TIM16_CH1_1 3
+#define STM_DMA_CHANNEL_TIM16_UP_1 3
+#define STM_DMA_CHANNEL_TIM16_CH1_2 4
+#define STM_DMA_CHANNEL_TIM16_UP_2 4
+
+#define STM_DMA_CHANNEL_TIM17_CH1_1 1
+#define STM_DMA_CHANNEL_TIM17_UP_1 1
+#define STM_DMA_CHANNEL_TIM17_CH1_2 2
+#define STM_DMA_CHANNEL_TIM17_UP_2 2
+
+/*
+ * Only spi channel 1 and 2 can use DMA
+ */
+#define STM_NUM_SPI 2
+
+struct stm_spi {
+ vuint32_t cr1;
+ vuint32_t cr2;
+ vuint32_t sr;
+ vuint32_t dr;
+ vuint32_t crcpr;
+ vuint32_t rxcrcr;
+ vuint32_t txcrcr;
+};
+
+extern struct stm_spi stm_spi1, stm_spi2, stm_spi3;
+
+/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh)
+ */
+
+#define STM_SPI_INDEX(channel) ((channel) - 1)
+
+#define STM_SPI_CR1_BIDIMODE 15
+#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_RXONLY 10
+#define STM_SPI_CR1_SSM 9
+#define STM_SPI_CR1_SSI 8
+#define STM_SPI_CR1_LSBFIRST 7
+#define STM_SPI_CR1_SPE 6
+#define STM_SPI_CR1_BR 3
+#define STM_SPI_CR1_BR_PCLK_2 0
+#define STM_SPI_CR1_BR_PCLK_4 1
+#define STM_SPI_CR1_BR_PCLK_8 2
+#define STM_SPI_CR1_BR_PCLK_16 3
+#define STM_SPI_CR1_BR_PCLK_32 4
+#define STM_SPI_CR1_BR_PCLK_64 5
+#define STM_SPI_CR1_BR_PCLK_128 6
+#define STM_SPI_CR1_BR_PCLK_256 7
+#define STM_SPI_CR1_BR_MASK 7
+
+#define STM_SPI_CR1_MSTR 2
+#define STM_SPI_CR1_CPOL 1
+#define STM_SPI_CR1_CPHA 0
+
+#define STM_SPI_CR2_TXEIE 7
+#define STM_SPI_CR2_RXNEIE 6
+#define STM_SPI_CR2_ERRIE 5
+#define STM_SPI_CR2_SSOE 2
+#define STM_SPI_CR2_TXDMAEN 1
+#define STM_SPI_CR2_RXDMAEN 0
+
+#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_TXE 1
+#define STM_SPI_SR_RXNE 0
+
+struct stm_adc {
+ vuint32_t isr;
+ vuint32_t ier;
+ vuint32_t cr;
+ vuint32_t cfgr1;
+
+ vuint32_t cfgr2;
+ vuint32_t smpr;
+ vuint32_t r_18;
+ vuint32_t r_1c;
+
+ vuint32_t tr;
+ vuint32_t r_24;
+ vuint32_t chselr;
+ vuint32_t r_2c;
+
+ vuint32_t r_30[4];
+
+ vuint32_t dr;
+
+ uint8_t r_44[0x308 - 0x44];
+ vuint32_t ccr;
+};
+
+extern struct stm_adc stm_adc;
+
+#define STM_ADC_ISR_AWD 7
+#define STM_ADC_ISR_OVR 4
+#define STM_ADC_ISR_EOSEQ 3
+#define STM_ADC_ISR_EOC 2
+#define STM_ADC_ISR_EOSMP 1
+#define STM_ADC_ISR_ADRDY 0
+
+#define STM_ADC_IER_AWDIE 7
+#define STM_ADC_IER_OVRIE 4
+#define STM_ADC_IER_EOSEQIE 3
+#define STM_ADC_IER_EOCIE 2
+#define STM_ADC_IER_EOSMPIE 1
+#define STM_ADC_IER_ADRDYIE 0
+
+#define STM_ADC_CR_ADCAL 31
+#define STM_ADC_CR_ADSTP 4
+#define STM_ADC_CR_ADSTART 2
+#define STM_ADC_CR_ADDIS 1
+#define STM_ADC_CR_ADEN 0
+
+#define STM_ADC_CFGR1_AWDCH 26
+#define STM_ADC_CFGR1_AWDEN 23
+#define STM_ADC_CFGR1_AWDSGL 22
+#define STM_ADC_CFGR1_DISCEN 16
+#define STM_ADC_CFGR1_AUTOOFF 15
+#define STM_ADC_CFGR1_WAIT 14
+#define STM_ADC_CFGR1_CONT 13
+#define STM_ADC_CFGR1_OVRMOD 12
+#define STM_ADC_CFGR1_EXTEN 10
+#define STM_ADC_CFGR1_EXTEN_DISABLE 0
+#define STM_ADC_CFGR1_EXTEN_RISING 1
+#define STM_ADC_CFGR1_EXTEN_FALLING 2
+#define STM_ADC_CFGR1_EXTEN_BOTH 3
+#define STM_ADC_CFGR1_EXTEN_MASK 3
+
+#define STM_ADC_CFGR1_EXTSEL 6
+#define STM_ADC_CFGR1_ALIGN 5
+#define STM_ADC_CFGR1_RES 3
+#define STM_ADC_CFGR1_RES_12 0
+#define STM_ADC_CFGR1_RES_10 1
+#define STM_ADC_CFGR1_RES_8 2
+#define STM_ADC_CFGR1_RES_6 3
+#define STM_ADC_CFGR1_RES_MASK 3
+#define STM_ADC_CFGR1_SCANDIR 2
+#define STM_ADC_CFGR1_SCANDIR_UP 0
+#define STM_ADC_CFGR1_SCANDIR_DOWN 1
+#define STM_ADC_CFGR1_DMACFG 1
+#define STM_ADC_CFGR1_DMACFG_ONESHOT 0
+#define STM_ADC_CFGR1_DMACFG_CIRCULAR 1
+#define STM_ADC_CFGR1_DMAEN 0
+
+#define STM_ADC_CFGR2_CKMODE 30
+#define STM_ADC_CFGR2_CKMODE_ADCCLK 0
+#define STM_ADC_CFGR2_CKMODE_PCLK_2 1
+#define STM_ADC_CFGR2_CKMODE_PCLK_4 2
+
+#define STM_ADC_SMPR_SMP 0
+#define STM_ADC_SMPR_SMP_1_5 0
+#define STM_ADC_SMPR_SMP_7_5 1
+#define STM_ADC_SMPR_SMP_13_5 2
+#define STM_ADC_SMPR_SMP_28_5 3
+#define STM_ADC_SMPR_SMP_41_5 4
+#define STM_ADC_SMPR_SMP_55_5 5
+#define STM_ADC_SMPR_SMP_71_5 6
+#define STM_ADC_SMPR_SMP_239_5 7
+
+#define STM_ADC_TR_HT 16
+#define STM_ADC_TR_LT 0
+
+#define STM_ADC_CCR_VBATEN 24
+#define STM_ADC_CCR_TSEN 23
+#define STM_ADC_CCR_VREFEN 22
+
+struct stm_cal {
+ uint16_t ts_cal_cold; /* 30°C */
+ uint16_t vrefint_cal;
+ uint16_t unused_c0;
+ uint16_t ts_cal_hot; /* 110°C */
+};
+
+extern struct stm_cal stm_cal;
+
+#define stm_temp_cal_cold 30
+#define stm_temp_cal_hot 110
+
+struct stm_dbgmcu {
+ uint32_t idcode;
+};
+
+extern struct stm_dbgmcu stm_dbgmcu;
+
+static inline uint16_t
+stm_dev_id(void) {
+ return stm_dbgmcu.idcode & 0xfff;
+}
+
+struct stm_flash_size {
+ uint16_t f_size;
+};
+
+extern struct stm_flash_size stm_flash_size_04x;
+
+/* Returns flash size in bytes */
+extern uint32_t
+stm_flash_size(void);
+
+struct stm_device_id {
+ uint32_t u_id0;
+ uint32_t u_id1;
+ uint32_t u_id2;
+};
+
+extern struct stm_device_id stm_device_id;
+
+#define STM_NUM_I2C 2
+
+#define STM_I2C_INDEX(channel) ((channel) - 1)
+
+struct stm_i2c {
+ vuint32_t cr1;
+ vuint32_t cr2;
+ vuint32_t oar1;
+ vuint32_t oar2;
+ vuint32_t dr;
+ vuint32_t sr1;
+ vuint32_t sr2;
+ vuint32_t ccr;
+ vuint32_t trise;
+};
+
+extern struct stm_i2c stm_i2c1, stm_i2c2;
+
+#define STM_I2C_CR1_SWRST 15
+#define STM_I2C_CR1_ALERT 13
+#define STM_I2C_CR1_PEC 12
+#define STM_I2C_CR1_POS 11
+#define STM_I2C_CR1_ACK 10
+#define STM_I2C_CR1_STOP 9
+#define STM_I2C_CR1_START 8
+#define STM_I2C_CR1_NOSTRETCH 7
+#define STM_I2C_CR1_ENGC 6
+#define STM_I2C_CR1_ENPEC 5
+#define STM_I2C_CR1_ENARP 4
+#define STM_I2C_CR1_SMBTYPE 3
+#define STM_I2C_CR1_SMBUS 1
+#define STM_I2C_CR1_PE 0
+
+#define STM_I2C_CR2_LAST 12
+#define STM_I2C_CR2_DMAEN 11
+#define STM_I2C_CR2_ITBUFEN 10
+#define STM_I2C_CR2_ITEVTEN 9
+#define STM_I2C_CR2_ITERREN 8
+#define STM_I2C_CR2_FREQ 0
+#define STM_I2C_CR2_FREQ_2_MHZ 2
+#define STM_I2C_CR2_FREQ_4_MHZ 4
+#define STM_I2C_CR2_FREQ_8_MHZ 8
+#define STM_I2C_CR2_FREQ_16_MHZ 16
+#define STM_I2C_CR2_FREQ_32_MHZ 32
+#define STM_I2C_CR2_FREQ_MASK 0x3f
+
+#define STM_I2C_SR1_SMBALERT 15
+#define STM_I2C_SR1_TIMEOUT 14
+#define STM_I2C_SR1_PECERR 12
+#define STM_I2C_SR1_OVR 11
+#define STM_I2C_SR1_AF 10
+#define STM_I2C_SR1_ARLO 9
+#define STM_I2C_SR1_BERR 8
+#define STM_I2C_SR1_TXE 7
+#define STM_I2C_SR1_RXNE 6
+#define STM_I2C_SR1_STOPF 4
+#define STM_I2C_SR1_ADD10 3
+#define STM_I2C_SR1_BTF 2
+#define STM_I2C_SR1_ADDR 1
+#define STM_I2C_SR1_SB 0
+
+#define STM_I2C_SR2_PEC 8
+#define STM_I2C_SR2_PEC_MASK 0xff00
+#define STM_I2C_SR2_DUALF 7
+#define STM_I2C_SR2_SMBHOST 6
+#define STM_I2C_SR2_SMBDEFAULT 5
+#define STM_I2C_SR2_GENCALL 4
+#define STM_I2C_SR2_TRA 2
+#define STM_I2C_SR2_BUSY 1
+#define STM_I2C_SR2_MSL 0
+
+#define STM_I2C_CCR_FS 15
+#define STM_I2C_CCR_DUTY 14
+#define STM_I2C_CCR_CCR 0
+#define STM_I2C_CCR_MASK 0x7ff
+
+struct stm_tim234 {
+ vuint32_t cr1;
+ vuint32_t cr2;
+ vuint32_t smcr;
+ vuint32_t dier;
+
+ vuint32_t sr;
+ vuint32_t egr;
+ vuint32_t ccmr1;
+ vuint32_t ccmr2;
+
+ vuint32_t ccer;
+ vuint32_t cnt;
+ vuint32_t psc;
+ vuint32_t arr;
+
+ uint32_t reserved_30;
+ vuint32_t ccr1;
+ vuint32_t ccr2;
+ vuint32_t ccr3;
+
+ vuint32_t ccr4;
+ 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
+
+struct stm_usb {
+ struct {
+ vuint16_t r;
+ uint16_t _;
+ } epr[8];
+ uint8_t reserved_20[0x40 - 0x20];
+ vuint16_t cntr;
+ uint16_t reserved_42;
+ vuint16_t istr;
+ uint16_t reserved_46;
+ vuint16_t fnr;
+ uint16_t reserved_4a;
+ vuint16_t daddr;
+ uint16_t reserved_4e;
+ vuint16_t btable;
+ uint16_t reserved_52;
+ vuint16_t lpmcsr;
+ uint16_t reserved_56;
+ vuint16_t bcdr;
+ uint16_t reserved_5a;
+};
+
+extern struct stm_usb stm_usb;
+
+#define STM_USB_EPR_CTR_RX 15
+#define STM_USB_EPR_CTR_RX_WRITE_INVARIANT 1
+#define STM_USB_EPR_DTOG_RX 14
+#define STM_USB_EPR_DTOG_RX_WRITE_INVARIANT 0
+#define STM_USB_EPR_STAT_RX 12
+#define STM_USB_EPR_STAT_RX_DISABLED 0
+#define STM_USB_EPR_STAT_RX_STALL 1
+#define STM_USB_EPR_STAT_RX_NAK 2
+#define STM_USB_EPR_STAT_RX_VALID 3
+#define STM_USB_EPR_STAT_RX_MASK 3
+#define STM_USB_EPR_STAT_RX_WRITE_INVARIANT 0
+#define STM_USB_EPR_SETUP 11
+#define STM_USB_EPR_EP_TYPE 9
+#define STM_USB_EPR_EP_TYPE_BULK 0
+#define STM_USB_EPR_EP_TYPE_CONTROL 1
+#define STM_USB_EPR_EP_TYPE_ISO 2
+#define STM_USB_EPR_EP_TYPE_INTERRUPT 3
+#define STM_USB_EPR_EP_TYPE_MASK 3
+#define STM_USB_EPR_EP_KIND 8
+#define STM_USB_EPR_EP_KIND_DBL_BUF 1 /* Bulk */
+#define STM_USB_EPR_EP_KIND_STATUS_OUT 1 /* Control */
+#define STM_USB_EPR_CTR_TX 7
+#define STM_USB_CTR_TX_WRITE_INVARIANT 1
+#define STM_USB_EPR_DTOG_TX 6
+#define STM_USB_EPR_DTOG_TX_WRITE_INVARIANT 0
+#define STM_USB_EPR_STAT_TX 4
+#define STM_USB_EPR_STAT_TX_DISABLED 0
+#define STM_USB_EPR_STAT_TX_STALL 1
+#define STM_USB_EPR_STAT_TX_NAK 2
+#define STM_USB_EPR_STAT_TX_VALID 3
+#define STM_USB_EPR_STAT_TX_WRITE_INVARIANT 0
+#define STM_USB_EPR_STAT_TX_MASK 3
+#define STM_USB_EPR_EA 0
+#define STM_USB_EPR_EA_MASK 0xf
+
+#define STM_USB_CNTR_CTRM 15
+#define STM_USB_CNTR_PMAOVRM 14
+#define STM_USB_CNTR_ERRM 13
+#define STM_USB_CNTR_WKUPM 12
+#define STM_USB_CNTR_SUSPM 11
+#define STM_USB_CNTR_RESETM 10
+#define STM_USB_CNTR_SOFM 9
+#define STM_USB_CNTR_ESOFM 8
+#define STM_USB_CNTR_RESUME 4
+#define STM_USB_CNTR_FSUSP 3
+#define STM_USB_CNTR_LP_MODE 2
+#define STM_USB_CNTR_PDWN 1
+#define STM_USB_CNTR_FRES 0
+
+#define STM_USB_ISTR_CTR 15
+#define STM_USB_ISTR_PMAOVR 14
+#define STM_USB_ISTR_ERR 13
+#define STM_USB_ISTR_WKUP 12
+#define STM_USB_ISTR_SUSP 11
+#define STM_USB_ISTR_RESET 10
+#define STM_USB_ISTR_SOF 9
+#define STM_USB_ISTR_ESOF 8
+#define STM_USB_L1REQ 7
+#define STM_USB_ISTR_DIR 4
+#define STM_USB_ISTR_EP_ID 0
+#define STM_USB_ISTR_EP_ID_MASK 0xf
+
+#define STM_USB_FNR_RXDP 15
+#define STM_USB_FNR_RXDM 14
+#define STM_USB_FNR_LCK 13
+#define STM_USB_FNR_LSOF 11
+#define STM_USB_FNR_LSOF_MASK 0x3
+#define STM_USB_FNR_FN 0
+#define STM_USB_FNR_FN_MASK 0x7ff
+
+#define STM_USB_DADDR_EF 7
+#define STM_USB_DADDR_ADD 0
+#define STM_USB_DADDR_ADD_MASK 0x7f
+
+#define STM_USB_BCDR_DPPU 15
+#define STM_USB_BCDR_PS2DET 7
+#define STM_USB_BCDR_SDET 6
+#define STM_USB_BCDR_PDET 5
+#define STM_USB_BCDR_DCDET 4
+#define STM_USB_BCDR_SDEN 3
+#define STM_USB_BCDR_PDEN 2
+#define STM_USB_BCDR_DCDEN 1
+#define STM_USB_BCDR_BCDEN 0
+
+union stm_usb_bdt {
+ struct {
+ vuint16_t addr_tx;
+ vuint16_t count_tx;
+ vuint16_t addr_rx;
+ vuint16_t count_rx;
+ } single;
+ struct {
+ vuint16_t addr;
+ vuint16_t count;
+ } double_tx[2];
+ struct {
+ vuint16_t addr;
+ vuint16_t count;
+ } double_rx[2];
+};
+
+#define STM_USB_BDT_COUNT_RX_BL_SIZE 15
+#define STM_USB_BDT_COUNT_RX_NUM_BLOCK 10
+#define STM_USB_BDT_COUNT_RX_NUM_BLOCK_MASK 0x1f
+#define STM_USB_BDT_COUNT_RX_COUNT_RX 0
+#define STM_USB_BDT_COUNT_RX_COUNT_RX_MASK 0x1ff
+
+#define STM_USB_BDT_SIZE 8
+
+extern uint8_t stm_usb_sram[];
+
+struct stm_exti {
+ vuint32_t imr;
+ vuint32_t emr;
+ vuint32_t rtsr;
+ vuint32_t ftsr;
+
+ vuint32_t swier;
+ vuint32_t pr;
+};
+
+extern struct stm_exti stm_exti;
+
+#endif /* _STM32F0_H_ */
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_cc1200_CC1200.h \
+ ao_profile.h \
+ ao_task.h \
+ stm32l.h \
+ Makefile
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+# ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_data.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_serial_stm.c \
+ ao_freq.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_cc1200.c \
+ ao_adc_stm.c \
+ ao_btm.c \
+ ao_usb_stm.c \
+ ao_exti_stm.c \
+ ao_eeprom_stm.c \
+ ao_convert_volt.c \
+ ao_packet_master.c \
+ ao_packet.c \
+ ao_monitor.c \
+ $(PROFILE) \
+ $(SAMPLE_PROFILE) \
+ $(STACK_GUARD)
+
+PRODUCT=TeleBT-v3.0
+PRODUCT_DEF=-DTELEBT_V_3_0
+IDPRODUCT=0x000e
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=telebt-v3.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_telebt.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_
+
+#define HAS_TASK_QUEUE 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)
+
+/* 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_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 0
+#define SERIAL_1_PA9_PA10 1
+
+#define HAS_SERIAL_2 1
+#define USE_SERIAL_2_STDIN 1
+#define DELAY_SERIAL_2_STDIN 1
+#define USE_SERIAL_2_FLOW 1
+#define SERIAL_2_PA2_PA3 1
+#define SERIAL_2_PD5_PD6 0
+
+#define HAS_SERIAL_3 0
+#define USE_SERIAL_3_STDIN 0
+#define SERIAL_3_PB10_PB11 1
+#define SERIAL_3_PC10_PC11 0
+#define SERIAL_3_PD8_PD9 0
+
+#define AO_CONFIG_MAX_SIZE 1024
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define USE_EEPROM_CONFIG 1
+#define USE_STORAGE_CONFIG 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_BATTERY_REPORT 0
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 0
+#define HAS_APRS 0
+#define HAS_ACCEL 0
+
+#define HAS_SPI_1 1
+#define SPI_1_PA5_PA6_PA7 1 /* CC1200 */
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_SPI_2 0
+#define SPI_2_PB13_PB14_PB15 0
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define HAS_I2C_1 0
+#define I2C_1_PB8_PB9 0
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 1
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_1 (&stm_gpioc)
+#define LED_PORT_0_SHIFT 0
+#define LED_PORT_1_SHIFT 0
+#define LED_PIN_RED (4 + LED_PORT_0_SHIFT)
+#define LED_PIN_BLUE (15 + LED_PORT_1_SHIFT)
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_BLUE (1 << LED_PIN_BLUE)
+#define LED_PORT_0_MASK (AO_LED_RED)
+#define LED_PORT_1_MASK (AO_LED_BLUE)
+#define AO_BT_LED AO_LED_BLUE
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_BLUE)
+
+#define HAS_GPS 0
+#define HAS_FLIGHT 0
+#define HAS_ADC 1
+#define HAS_ADC_TEMP 0
+#define HAS_LOG 0
+
+/*
+ * ADC
+ */
+#define AO_DATA_RING 32
+#define AO_ADC_NUM_SENSE 2
+
+struct ao_adc {
+ int16_t v_batt;
+};
+
+#define AO_ADC_DUMP(p) \
+ printf("tick: %5u %5d batt: %5d\n", \
+ (p)->tick, \
+ (p)->adc.v_batt);
+
+#define AO_ADC_V_BATT 8
+#define AO_ADC_V_BATT_PORT (&stm_gpiob)
+#define AO_ADC_V_BATT_PIN 0
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOEEN))
+
+#define AO_NUM_ADC_PIN 1
+
+#define AO_ADC_PIN0_PORT AO_ADC_V_BATT_PORT
+#define AO_ADC_PIN0_PIN AO_ADC_V_BATT_PIN
+
+#define AO_NUM_ADC (AO_NUM_ADC_PIN)
+
+#define AO_ADC_SQ1 AO_ADC_V_BATT
+
+/*
+ * Voltage divider on ADC battery sampler
+ */
+#define AO_BATTERY_DIV_PLUS 51 /* 5.6k */
+#define AO_BATTERY_DIV_MINUS 100 /* 10k */
+
+/*
+ * ADC reference in decivolts
+ */
+#define AO_ADC_REFERENCE_DV 33
+
+/*
+ * BTM
+ */
+#define HAS_BTM 1
+
+#define ao_serial_btm_getchar ao_serial2_getchar
+#define ao_serial_btm_putchar ao_serial2_putchar
+#define _ao_serial_btm_pollchar _ao_serial2_pollchar
+#define _ao_serial_btm_sleep _ao_serial2_sleep
+#define ao_serial_btm_set_speed ao_serial2_set_speed
+#define ao_serial_btm_drain ao_serial2_drain
+#define ao_serial_btm_rx_fifo (ao_stm_usart2.rx_fifo)
+
+#define AO_BTM_INT_PORT (&stm_gpioa)
+#define AO_BTM_INT_PIN 15
+#define AO_BTM_RESET_PORT (&stm_gpiob)
+#define AO_BTM_RESET_PIN 3
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 5695485
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpiob)
+#define AO_CC1200_SPI_CS_PIN 10
+#define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7
+#define AO_CC1200_SPI stm_spi1
+
+#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 HAS_BOOT_RADIO 0
+
+/* Monitor bits */
+#define HAS_MONITOR 1
+#define LEGACY_MONITOR 0
+#define AO_MONITOR_LED AO_LED_RED
+
+#endif /* _AO_PINS_H_ */
--- /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.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_eeprom.h>
+#include <ao_profile.h>
+#include <ao_btm.h>
+#if HAS_SAMPLE_PROFILE
+#include <ao_sample_profile.h>
+#endif
+
+int
+main(void)
+{
+ ao_clock_init();
+
+ ao_task_init();
+ ao_serial_init();
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_RED);
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_adc_init();
+ ao_btm_init();
+ ao_cmd_init();
+
+ ao_eeprom_init();
+
+ ao_usb_init();
+ ao_radio_init();
+ ao_packet_master_init();
+ ao_monitor_init();
+
+ ao_config_init();
+
+ ao_led_off(AO_LED_RED);
+
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=telebt-v3.0
+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>
+
+/* Blue LED */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioc
+#define AO_BOOT_APPLICATION_PIN 15
+#define AO_BOOT_APPLICATION_VALUE 0
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_DOWN
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+ao_product.h
+teledongle-*.elf
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ ao_whiten.h \
+ stm32l.h \
+ ao_cc1200.h \
+ ao_cc1200_CC1200.h \
+ Makefile
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+# ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cc1200.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_usb_stm.c \
+ ao_exti_stm.c \
+ ao_send_packet.c \
+ ao_eeprom_stm.c \
+ ao_monitor.c \
+ ao_packet_master.c \
+ ao_packet.c
+
+PRODUCT=TeleDongle-v1.8
+PRODUCT_DEF=-DTELEDONGLE
+IDPRODUCT=0x000c
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=teledongle-v1.8
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_teledongle.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.
+ */
+
+/* Using TeleMetrum v1.9 board */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE 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)
+
+/* 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_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 0
+#define SERIAL_1_PA9_PA10 0
+
+#define HAS_SERIAL_2 0
+#define USE_SERIAL_2_STDIN 0
+#define SERIAL_2_PA2_PA3 0
+#define SERIAL_2_PD5_PD6 0
+
+#define HAS_SERIAL_3 0
+#define USE_SERIAL_3_STDIN 0
+#define SERIAL_3_PB10_PB11 0
+#define SERIAL_3_PC10_PC11 0
+#define SERIAL_3_PD8_PD9 0
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 1
+#define USE_STORAGE_CONFIG 0
+#define USE_EEPROM_CONFIG 1
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 0
+#define HAS_RSSI 0
+
+#define HAS_SPI_1 0
+#define SPI_1_PA5_PA6_PA7 0 /* Barometer */
+#define SPI_1_PB3_PB4_PB5 0
+#define SPI_1_PE13_PE14_PE15 0 /* Accelerometer */
+
+#define HAS_SPI_2 1
+#define SPI_2_PB13_PB14_PB15 1 /* Radio */
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define SPI_2_PORT (&stm_gpiob)
+#define SPI_2_SCK_PIN 13
+#define SPI_2_MISO_PIN 14
+#define SPI_2_MOSI_PIN 15
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 1
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOCEN
+#define LED_PORT_0 (&stm_gpioc)
+#define LED_PORT_0_MASK (0xffff)
+#define LED_PORT_0_SHIFT 0
+#define LED_PIN_RED 8
+#define LED_PIN_GREEN 9
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS 0
+#define HAS_FLIGHT 0
+#define HAS_ADC 0
+#define HAS_LOG 0
+
+/*
+ * Telemetry monitoring
+ */
+#define HAS_MONITOR 1
+#define LEGACY_MONITOR 0
+#define HAS_MONITOR_PUT 1
+#define AO_MONITOR_LED AO_LED_GREEN
+#define AO_MONITOR_BAD AO_LED_RED
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT (&stm_gpioc)
+#define AO_CC1200_SPI_CS_PIN 5
+#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+#define AO_CC1200_SPI stm_spi2
+
+#define AO_CC1200_INT_PORT (&stm_gpioe)
+#define AO_CC1200_INT_PIN 1
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE 0
+#endif
+
+#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_exti.h>
+#include <ao_packet.h>
+#include <ao_send_packet.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_RED);
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_usb_init();
+ ao_radio_init();
+ ao_monitor_init();
+ ao_packet_master_init();
+ ao_send_packet_init();
+
+ ao_config_init();
+
+ ao_led_off(AO_LED_RED);
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+ao_product.h
+teledongle-*.elf
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../lpc/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_boot.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_task.h \
+ ao_whiten.h \
+ lpc.h \
+ ao_cc1200.h \
+ ao_cc1200_CC1200.h \
+ Makefile
+
+ALTOS_SRC = \
+ ao_boot_chain.c \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cc1200.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led_lpc.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer_lpc.c \
+ ao_mutex.c \
+ ao_freq.c \
+ ao_spi_lpc.c \
+ ao_usb_lpc.c \
+ ao_exti_lpc.c \
+ ao_send_packet.c \
+ ao_monitor.c \
+ ao_packet_master.c \
+ ao_packet.c
+
+PRODUCT=TeleDongle-v3.0
+PRODUCT_DEF=-DTELEDONGLE
+IDPRODUCT=0x000c
+
+CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -Os -g
+
+PROGNAME=teledongle-v3.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_teledongle.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) > $@
+
+load: $(PROG)
+ lpc-load $(PROG)
+
+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.
+ */
+
+/* Using TeleDongle v3.0 board */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define AO_STACK_SIZE 320
+
+#define HAS_TASK_QUEUE 1
+
+#define IS_FLASH_LOADER 0
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN 12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT 48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK 24000000
+
+#define HAS_EEPROM 0
+#define USE_INTERNAL_FLASH 0
+#define USE_STORAGE_CONFIG 0
+#define USE_EEPROM_CONFIG 0
+
+#define HAS_USB 1
+#define HAS_USB_CONNECT 0
+#define HAS_USB_VBUS 0
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 20
+
+#define HAS_BEEP 0
+#define HAS_RADIO 1
+#define HAS_TELEMETRY 0
+#define HAS_RSSI 0
+
+#define HAS_SPI_0 1
+#define SPI_SCK0_P0_6 1
+
+#define PACKET_HAS_SLAVE 0
+#define PACKET_HAS_MASTER 1
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT 0
+#define LED_PIN_RED 14
+#define LED_PIN_GREEN 7
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS 0
+#define HAS_FLIGHT 0
+#define HAS_ADC 0
+#define HAS_LOG 0
+
+/*
+ * Telemetry monitoring
+ */
+#define HAS_MONITOR 1
+#define LEGACY_MONITOR 0
+#define HAS_MONITOR_PUT 1
+#define AO_MONITOR_LED AO_LED_GREEN
+#define AO_MONITOR_BAD AO_LED_RED
+
+/*
+ * Radio (cc1200)
+ */
+
+/* gets pretty close to 434.550 */
+
+#define AO_RADIO_CAL_DEFAULT 5695733
+
+#define AO_FEC_DEBUG 0
+#define AO_CC1200_SPI_CS_PORT 0
+#define AO_CC1200_SPI_CS_PIN 3
+#define AO_CC1200_SPI_BUS 0
+#define AO_CC1200_SPI 0
+
+#define AO_CC1200_INT_PORT 0
+#define AO_CC1200_INT_PIN 2
+
+#define AO_CC1200_INT_GPIO 2
+#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2
+
+/*
+ * Profiling Viterbi decoding
+ */
+
+#ifndef AO_PROFILE
+#define AO_PROFILE 0
+#endif
+
+#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_exti.h>
+#include <ao_packet.h>
+#include <ao_send_packet.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_RED);
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_usb_init();
+ ao_radio_init();
+ ao_monitor_init();
+ ao_packet_master_init();
+ ao_send_packet_init();
+
+ ao_config_init();
+
+ ao_led_off(AO_LED_RED);
+ ao_start_scheduler();
+ return 0;
+}
--- /dev/null
+#
+# AltOS flash loader build
+#
+
+TOPDIR=../..
+HARDWARE=teledongle-v3.0
+include $(TOPDIR)/lpc/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_lpc_pins.h>
+
+/* Debug port TXD (pin 6) */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO 0
+#define AO_BOOT_APPLICATION_PIN 19
+#define AO_BOOT_APPLICATION_VALUE 1
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT 0
+#define AO_USB_PULLUP_PIN 20
+
+#endif /* _AO_PINS_H_ */
ao_fec_test
ao_flight_test_mm
ao_flight_test_noisy_accel
+ao_flight_test_metrum
ao_micropeak_test
ao_aes_test
#if 1
printf("%7.2f height %8.2f accel %8.3f "
-#if TELEMEGA && 0
+#if TELEMEGA && 1
"angle %5d "
"accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d "
#endif
time,
height,
accel,
-#if TELEMEGA && 0
+#if TELEMEGA && 1
ao_sample_orient,
ao_mpu6000_accel(ao_data_static.mpu6000.accel_x),
ao_data_static.hmc5883.z = int16(bytes, 24);
#if HAS_MMA655X
ao_data_static.mma655x = int16(bytes, 26);
+ if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP)
+ ao_data_static.mma655x = ao_data_accel_invert(ao_data_static.mma655x);
#endif
ao_records_read++;
ao_insert();
} else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 &&
strcmp(words[1], "lockout:") == 0) {
ao_config.apogee_lockout = atoi(words[2]);
+ } else if (nword >= 3 && strcmp(words[0], "Pad") == 0 &&
+ strcmp(words[1], "orientation:") == 0) {
+ ao_config.pad_orientation = atoi(words[2]);
} else if (nword >= 36 && strcmp(words[0], "CALL") == 0) {
tick = atoi(words[10]);
if (!ao_flight_started) {
typedef int32_t gps_alt_t;
#define AO_TELEMETRY_LOCATION_ALTITUDE(l) (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low))
+#define AO_GPS_ORIG_ALTITUDE(l) AO_TELEMETRY_LOCATION_ALTITUDE(l)
#define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->altitude_high = (a) >> 16), \
((l)->altitude_low = (a)))
--- /dev/null
+ao_product.h
+usbtrng-*
--- /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_adc_fast.c \
+ ao_crc_stm.c \
+ ao_stdio.c \
+ ao_led.c \
+ ao_romconfig.c \
+ ao_boot_chain.c \
+ ao_cmd.c \
+ ao_usb_stm.c \
+ ao_task.c \
+ ao_product.c
+
+PRODUCT=usbtrng-v2.0
+PRODUCT_DEF=-DUSBTRNG_V_2_0
+IDPRODUCT=0x0028
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+PROGNAME=usbtrng-v2.0
+PROG=$(PROGNAME)-$(VERSION).elf
+HEX=$(PROGNAME)-$(VERSION).ihx
+
+SRC=$(ALTOS_SRC) ao_usbtrng.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) > $@
+
+$(OBJ): $(INC)
+
+distclean: clean
+
+clean:
+ rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /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 2
+#define LED_PIN_GREEN 3
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#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 0
+
+#define IS_FLASH_LOADER 0
+
+/* ADC */
+
+#define AO_ADC_PIN0_PORT (&stm_gpioa)
+#define AO_ADC_PIN0_PIN 6
+#define AO_ADC_PIN0_CH 6
+
+#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN))
+
+#define AO_NUM_ADC 1
+
+/* CRC */
+#define AO_CRC_WIDTH 32
+#define AO_CRC_INIT 0xffffffff
+
+#endif /* _AO_PINS_H_ */
--- /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>
+
+static void
+ao_trng_fetch(void)
+{
+ static uint16_t *buffer[2];
+ uint32_t kbytes = 1;
+ uint32_t count;
+ int usb_buf_id;
+ int i;
+ uint16_t *buf;
+ uint32_t *rnd;
+
+ if (!buffer[0]) {
+ buffer[0] = ao_usb_alloc();
+ buffer[1] = ao_usb_alloc();
+ if (!buffer[0])
+ return;
+ }
+
+ ao_cmd_decimal();
+ if (ao_cmd_status == ao_cmd_success)
+ kbytes = ao_cmd_lex_u32;
+ else
+ ao_cmd_status = ao_cmd_success;
+ usb_buf_id = 0;
+ count = kbytes * (1024/AO_USB_IN_SIZE);
+
+ ao_crc_reset();
+
+ ao_led_on(AO_LED_GREEN);
+ while (count--) {
+ buf = buffer[usb_buf_id];
+// printf ("before get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush();
+ rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */
+// printf ("after get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush();
+ for (i = 0; i < 32; i++)
+ *buf++ = ao_crc_in_32_out_16(*rnd++);
+ ao_adc_ack(AO_USB_IN_SIZE);
+// printf ("after ack: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush();
+ ao_led_toggle(AO_LED_GREEN|AO_LED_RED);
+ ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE);
+ ao_led_toggle(AO_LED_GREEN|AO_LED_RED);
+ usb_buf_id = 1-usb_buf_id;
+ }
+ ao_led_off(AO_LED_GREEN|AO_LED_RED);
+ flush();
+}
+
+static const struct ao_cmds usbtrng_cmds[] = {
+ { ao_trng_fetch, "f <kbytes>\0Fetch a block of numbers" },
+ { 0, NULL },
+};
+
+void main(void)
+{
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_RED);
+ ao_clock_init();
+ ao_task_init();
+ ao_timer_init();
+ ao_dma_init();
+ ao_adc_init();
+ ao_crc_init();
+
+ ao_cmd_init();
+
+ ao_usb_init();
+
+ ao_cmd_register(usbtrng_cmds);
+ ao_led_off(AO_LED_RED);
+
+ ao_start_scheduler();
+}
--- /dev/null
+ao_product.h
+usbtrng*
--- /dev/null
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=usbtrng-v2.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>
+
+/* Red LED */
+
+#define AO_BOOT_PIN 1
+#define AO_BOOT_APPLICATION_GPIO stm_gpioa
+#define AO_BOOT_APPLICATION_PIN 2
+#define AO_BOOT_APPLICATION_VALUE 0
+#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_DOWN
+
+#endif /* _AO_PINS_H_ */
*/
#define HAS_SCK1 0
#define HAS_MOSI1 0
+
+#define AO_ADC_6 1
#include <ao.h>
#define AO_TRNG_SPI_BUS 1
-#define AO_TRNG_SPI_SPEED AO_SPI_SPEED_250kHz
+
+static uint32_t spi_speed = AO_SPI_SPEED_4MHz;
+
+#define AO_TRNG_SPI_BUF 1024
+
+#if 0
+
+static uint8_t *spi_buf;
+static uint8_t *spi_head, *spi_tail;
+static uint8_t spi_wakeup;
+
+static void
+ao_trng_run(void)
+{
+ int this_time;
+ uint8_t *end;
+
+ if (!spi_buf)
+ spi_buf = ao_usb_alloc(AO_TRNG_SPI_BUF);
+ flush();
+ ao_spi_get(AO_TRNG_SPI_BUS, spi_speed);
+ spi_tail = spi_buf;
+ spi_head = spi_buf;
+ ao_spi_recv_ring_start(spi_buf, AO_TRNG_SPI_BUF, &spi_head, &spi_tail, &spi_wakeup, AO_TRNG_SPI_BUS);
+ while (!ao_usb_out_avail) {
+ ao_arch_block_interrupts();
+ while (spi_head == spi_tail) {
+ spi_wakeup = 0;
+ ao_sleep(&spi_wakeup);
+ }
+ ao_arch_release_interrupts();
+ if (spi_tail > spi_head)
+ end = spi_buf + AO_TRNG_SPI_BUF;
+ else
+ end = spi_head;
+ this_time = end - spi_tail;
+ if (this_time > 64)
+ this_time = 64;
+ ao_usb_write(spi_tail, this_time);
+ spi_tail += this_time;
+ if (spi_tail == spi_buf + AO_TRNG_SPI_BUF)
+ spi_tail = spi_buf;
+ }
+ ao_spi_put(AO_TRNG_SPI_BUS);
+ getchar();
+}
+
static void
ao_trng_test(void)
static uint8_t random[32];
uint8_t i;
- ao_spi_get(AO_TRNG_SPI_BUS, AO_TRNG_SPI_SPEED);
+ ao_spi_get(AO_TRNG_SPI_BUS, spi_speed);
ao_spi_recv(random, sizeof (random), AO_TRNG_SPI_BUS);
ao_spi_put(AO_TRNG_SPI_BUS);
for (i = 0; i < sizeof (random); i++)
printf (" %02x", random[i]);
printf ("\n");
}
+#endif
+
+#define ADC_RING_SIZE 512
+
+static uint8_t *adc_ring;
+static uint16_t adc_head, adc_tail;
+static uint16_t adc_wake;
+
+void lpc_adc_isr(void)
+{
+ uint16_t avail;
+ uint16_t this, next;
+
+ this = adc_head;
+ next = (this + 1) & (ADC_RING_SIZE - 1);
+ if (next == adc_tail) {
+ lpc_adc.inten = 0;
+ return;
+ }
+ adc_ring[this] = lpc_adc.dr[6] >> 8;
+ adc_head = next;
+
+ /* If there are enough entries, wake up any waiters
+ */
+ avail = (next - adc_tail) & (ADC_RING_SIZE - 1);
+ if (avail >= adc_wake) {
+ adc_wake = 0;
+ ao_wakeup(&adc_wake);
+ }
+}
+
+#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 450000)
+
+static void
+ao_trng_adc_init(void)
+{
+ adc_ring = ao_usb_alloc(ADC_RING_SIZE);
+
+ lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC);
+ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD);
+
+ /* Enable interrupt when AO_ADC_6 is complete */
+ lpc_adc.inten = 0;
+
+ lpc_nvic_set_enable(LPC_ISR_ADC_POS);
+ lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY);
+
+#if AO_ADC_0
+ ao_enable_analog(0, 11, 0);
+#endif
+#if AO_ADC_1
+ ao_enable_analog(0, 12, 1);
+#endif
+#if AO_ADC_2
+ ao_enable_analog(0, 13, 2);
+#endif
+#if AO_ADC_3
+ ao_enable_analog(0, 14, 3);
+#endif
+#if AO_ADC_4
+ ao_enable_analog(0, 15, 4);
+#endif
+#if AO_ADC_5
+ ao_enable_analog(0, 16, 5);
+#endif
+#if AO_ADC_6
+ ao_enable_analog(0, 22, 6);
+#endif
+#if AO_ADC_7
+ ao_enable_analog(0, 23, 7);
+#endif
+
+ lpc_adc.cr = ((1 << (LPC_ADC_CR_SEL + 6)) |
+ (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) |
+ (1 << LPC_ADC_CR_BURST) |
+ (LPC_ADC_CR_CLKS_9 << LPC_ADC_CR_CLKS));
+}
+
+static void
+ao_trng_adc_dump(void)
+{
+ int i;
+
+ while (((adc_head - adc_tail) & (ADC_RING_SIZE - 1)) < 16) {
+ lpc_adc.inten = (1 << (LPC_ADC_INTEN_ADINTEN + 6));
+ adc_wake = 16;
+ ao_sleep(&adc_wake);
+ }
+ printf("adc_head %d tail %d\n", adc_head, adc_tail);
+
+ for (i = 0; i < 16; i++) {
+ printf(" %4d", adc_ring[adc_tail]);
+ adc_tail = (adc_tail + 1) & (ADC_RING_SIZE - 1);
+ }
+ printf("\n");
+ lpc_adc.inten = 0;
+}
+
+static void
+ao_trng_run(void)
+{
+ uint16_t this_time;
+ flush();
+
+ while (!ao_usb_out_avail) {
+ ao_arch_block_interrupts();
+ while (((adc_head - adc_tail) & (ADC_RING_SIZE - 1)) < 64) {
+ lpc_adc.inten = (1 << (LPC_ADC_INTEN_ADINTEN + 6));
+ adc_wake = 64;
+ ao_sleep(&adc_wake);
+ }
+ ao_arch_release_interrupts();
+
+ this_time = ADC_RING_SIZE - adc_tail;
+ if (this_time > 64)
+ this_time = 64;
+ ao_usb_write(&adc_ring[adc_tail], this_time);
+ adc_tail = (adc_tail + this_time) & (ADC_RING_SIZE - 1);
+ }
+ lpc_adc.inten = 0;
+}
+
+static void
+ao_trng_speed(void)
+{
+ ao_cmd_decimal();
+
+ if (ao_cmd_lex_u32 == 0 || ao_cmd_status != ao_cmd_success) {
+ ao_cmd_status = ao_cmd_success;
+ printf ("Current spi speed %d\n", spi_speed);
+ } else {
+ spi_speed = ao_cmd_lex_u32;
+ }
+}
static const struct ao_cmds ao_trng_cmds[] = {
- { ao_trng_test, "R\0Dump some random numbers" },
+// { ao_trng_test, "R\0Dump some random numbers" },
+ { ao_trng_run, "s\0Send random bits until char" },
+ { ao_trng_speed, "S <speed>\0Set SPI speed (48MHz/speed)" },
+ { ao_trng_adc_dump, "a\0Dump ADC data" },
{ 0, NULL }
};
ao_task_init();
ao_timer_init();
- ao_spi_init();
+// ao_spi_init();
ao_usb_init();
+ ao_trng_adc_init();
+
ao_serial_init();
ao_led_init(LEDS_AVAILABLE);
- ao_led_on(AO_LED_GREEN);
-
ao_cmd_init();
ao_cmd_register(ao_trng_cmds);
# Firmware
FIRMWARE_TD_0_2=$(top_srcdir)/src/teledongle-v0.2/teledongle-v0.2-$(VERSION).ihx
-FIRMWARE_TD=$(FIRMWARE_TD_0_2)
+FIRMWARE_TD_3_0=$(top_srcdir)/src/teledongle-v3.0/teledongle-v3.0-$(VERSION).ihx
+FIRMWARE_TD=$(FIRMWARE_TD_0_2) $(FIRMWARE_TD_3_0)
FIRMWARE_TBT_1_0=$(top_srcdir)/src/telebt-v1.0/telebt-v1.0-$(VERSION).ihx
FIRMWARE_TBT=$(FIRMWARE_TBT_1_0)
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPS
extends AltosUIFrame
TeleGPSStatus telegps_status;
TeleGPSStatusUpdate status_update;
- javax.swing.Timer status_timer;
JTabbedPane pane;
public void show(AltosState state, AltosListenerState listener_state) {
try {
status_update.saved_state = state;
+ status_update.saved_listener_state = listener_state;
if (state == null)
state = new AltosState();
void disconnect() {
setTitle("TeleGPS");
stop_display();
- if (status_timer != null) {
- status_timer.stop();
- status_timer = null;
- status_update = null;
- }
+ telegps_status.stop();
telegps_status.disable_receive();
disable_frequency_menu();
public void set_reader(AltosFlightReader reader, AltosDevice device) {
status_update = new TeleGPSStatusUpdate(telegps_status);
- status_timer = new javax.swing.Timer(100, status_update);
- status_timer.start();
+ telegps_status.start(status_update);
setTitle(String.format("TeleGPS %s", reader.name));
thread = new TeleGPSDisplayThread(this, voice(), this, reader);
import java.io.*;
import java.util.concurrent.*;
import java.text.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPSConfig implements ActionListener {
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPSConfigUI
extends AltosUIDialog
import javax.swing.*;
import java.io.*;
import java.text.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPSDisplayThread extends Thread {
for (;;) {
try {
state = reader.read();
- if (state == null)
+ if (state == null) {
+ listener_state.running = false;
break;
+ }
reader.update(state);
show_safely();
told = tell();
import java.io.*;
import java.util.concurrent.*;
import java.util.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPSInfo extends AltosUIFlightTab {
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPSPreferences
extends AltosUIConfigure
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPSState extends AltosUIFlightTab {
import java.awt.*;
import javax.swing.*;
-import org.altusmetrum.altoslib_5.*;
-import org.altusmetrum.altosuilib_3.*;
+import org.altusmetrum.altoslib_6.*;
+import org.altusmetrum.altosuilib_6.*;
public class TeleGPSStatus extends JComponent implements AltosFlightDisplay {
GridBagLayout layout;
long last_secs = -1;
void show(AltosState state, AltosListenerState listener_state) {
- long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
-
- if (secs != last_secs) {
- value.setText(String.format("%d", secs));
- last_secs = secs;
+ if (listener_state.running) {
+ long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000;
+
+ if (secs != last_secs) {
+ value.setText(String.format("%d", secs));
+ last_secs = secs;
+ }
+ } else {
+ value.setText("done");
}
}
flight.show(state, listener_state);
rssi.show(state, listener_state);
last_packet.show(state, listener_state);
+ if (!listener_state.running)
+ stop();
}
public int height() {
return d.height;
}
+ TeleGPSStatusUpdate status_update;
+ javax.swing.Timer timer;
+
+ public void start(TeleGPSStatusUpdate status_update) {
+ this.status_update = status_update;
+ timer = new javax.swing.Timer(100, status_update);
+ timer.start();
+ }
+
+ public void stop() {
+ if (timer != null) {
+ timer.stop();
+ timer = null;
+ }
+ }
+
public TeleGPSStatus() {
layout = new GridBagLayout();
package org.altusmetrum.telegps;
import java.awt.event.*;
-import org.altusmetrum.altoslib_5.*;
+import org.altusmetrum.altoslib_6.*;
public class TeleGPSStatusUpdate implements ActionListener {
File "../icon/${WIN_APP_ICON}"
- CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$SYSDIR\javaw.exe" "-jar ${FAT_NAME}" "$INSTDIR\${WIN_APP_ICON}"
+ CreateShortCut "$SMPROGRAMS\${REG_NAME}.lnk" "$INSTDIR\${FAT_NAME}" "" "$INSTDIR\${WIN_APP_ICON}"
SectionEnd
Section "${REG_NAME} Desktop Shortcut"
File "../src/telegps-v1.0/telegps-v1.0-${VERSION}.ihx"
File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx"
+ File "../src/teledongle-v3.0/teledongle-v3.0-${VERSION}.ihx"
File "../src/telebt-v1.0/telebt-v1.0-${VERSION}.ihx"
SectionEnd
DeleteRegKey HKCR ".telem\${PROG_ID_EEPROM}"
DeleteRegValue HKCR ".telem\OpenWithProgids" "${PROG_ID_EEPROM}"
+ SearchPath $1 "javaw.exe"
+
; .eeprom elements
WriteRegStr HKCR "${PROG_ID_EEPROM}" "" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_EEPROM}" "FriendlyTypeName" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_EEPROM}\CurVer" "" "${PROG_ID_EEPROM}"
WriteRegStr HKCR "${PROG_ID_EEPROM}\DefaultIcon" "" '"$INSTDIR\${WIN_EEPROM_EXE}",-101'
- WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+ WriteRegExpandStr HKCR "${PROG_ID_EEPROM}\shell\open\command" "" '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
WriteRegStr HKCR ".eeprom" "" "${PROG_ID_EEPROM}"
WriteRegStr HKCR ".eeprom" "PerceivedType" "Altus Metrum Log File"
WriteRegStr HKCR "${PROG_ID_TELEM}" "FriendlyTypeName" "Altus Metrum Telemetry File"
WriteRegStr HKCR "${PROG_ID_TELEM}\CurVer" "" "${PROG_ID_TELEM}"
WriteRegStr HKCR "${PROG_ID_TELEM}\DefaultIcon" "" '"$INSTDIR\${WIN_TELEM_EXE}",-101'
- WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"%SYSTEMROOT%\System32\javaw.exe" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
+ WriteRegExpandStr HKCR "${PROG_ID_TELEM}\shell\open\command" "" '"$1" -Djava.library.path="$INSTDIR" -jar "$INSTDIR\${FAT_NAME}" "%1"'
WriteRegStr HKCR ".telem" "" "${PROG_ID_TELEM}"
WriteRegStr HKCR ".telem" "PerceivedType" "Altus Metrum Telemetry File"