From: Bdale Garbee Date: Tue, 25 Apr 2017 00:22:03 +0000 (-0600) Subject: Merge branch 'branch-1.7' into debian X-Git-Tag: debian/1.7-1~3 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=b91f67005709cb7f65e0a461b49b5cb0952cb391;hp=1e956f93e0c9f8ed6180490f80e8aead5538f818 Merge branch 'branch-1.7' into debian --- diff --git a/ChangeLog b/ChangeLog index 9eb8703f..69451886 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,2142 @@ -commit c0ad087008856cfc2233b977abfc3f1dcbaccdcc -Merge: 148b013 4fdf8ca +commit 9c95bed92a45741e6c1ad0ab4941f13370b77648 +Author: Keith Packard +Date: Mon Apr 24 15:47:08 2017 -0700 + + Bump to version 1.7 + + TeleMini v3.0 support + + Signed-off-by: Keith Packard + +commit 3544c33c2f386fb292de9e74982717a002f37440 +Author: Keith Packard +Date: Mon Apr 24 17:11:03 2017 -0700 + + altoslib: renamed AltosSensorTMini2, but didn't update AltosIdleFetch + + Because Java found the old installed version of this library. Thanks! + + Signed-off-by: Keith Packard + +commit 5914231bfe8220a92dde17901b952e919a40d568 +Author: Bdale Garbee +Date: Mon Apr 24 17:18:10 2017 -0600 + + update copyright year in docs + +commit 8e5b4359050701513a807131564ae54f2e6b919b +Author: Keith Packard +Date: Mon Apr 24 16:40:46 2017 -0700 + + altos/ao_pad.c: Use #if HAS_LOG instead of #ifdef HAS_LOG + + TeleFire v0.1 defines HAS_LOG to 0. + + Signed-off-by: Keith Packard + +commit c57a5c018e4bd0a0033c8759132a648977bf45f7 +Author: Keith Packard +Date: Mon Apr 24 15:59:23 2017 -0700 + + doc: Errors in the TeleMini v3.0 updates found by Bdale + + Signed-off-by: Keith Packard + +commit b6b58aa2fbae1e7782b5a0b700544efe319fe34e +Author: Keith Packard +Date: Sat Apr 22 22:04:31 2017 -0700 + + altos: Move old AO_LAUNCH defines to cc1111/ao_launch.h + + These were getting accidentally used by ao_pad.c + + Signed-off-by: Keith Packard + +commit cd291d38b92b31c3612e6de6cdf4e5988fc01c12 +Author: Bdale Garbee +Date: Sun Apr 23 00:02:47 2017 -0600 + + allow multiple tests to be logged on telefiretwo without rebooting + +commit d75351c5a07241bcbb951758796b4f639ace6b1f +Author: Bdale Garbee +Date: Sat Apr 22 23:42:23 2017 -0600 + + implement static test start and stop protocol for telefiretwo+telebt + +commit 6cfd9411026d536b5b75098b8c9ec3ceb3d945aa +Author: Bdale Garbee +Date: Sat Apr 22 23:02:53 2017 -0600 + + eliminate spurious close braces + +commit e3b30d4bd6faf68c885791fb87229558cc1157a6 +Author: Bdale Garbee +Date: Sat Apr 22 23:01:44 2017 -0600 + + add static test start and stop commands to radio protocol for telefiretwo + +commit e5e0ce18b2ae684896a6d7d0a4c10269199d95b5 +Author: Bdale Garbee +Date: Sat Apr 22 23:01:26 2017 -0600 + + enable logging support in telefiretwo + +commit e05b281e6d1a7a4fa92d52f2491f27266045df96 +Author: Bdale Garbee +Date: Sat Apr 22 17:20:41 2017 -0600 + + cobble up a command to toggle logging on/off on TeleFireTwo + +commit db12c17e9538bd82f2c2bf21357887ee7d894a1c +Author: Bdale Garbee +Date: Sat Apr 22 16:59:03 2017 -0600 + + a stab at turning on rudimentary logging for telefiretwo + +commit 6804ead7f7e54ff34b257e10e381dc52d5a61b06 +Author: Keith Packard +Date: Sat Apr 22 15:55:48 2017 -0700 + + altoslib: Add TeleFireTwo eeprom support + + Signed-off-by: Keith Packard + +commit 359e2d6eca5258f4fabc59772f1320e195a7397c +Author: Bdale Garbee +Date: Sat Apr 22 16:36:18 2017 -0600 + + fleshing out logging for telefiretwo + +commit 439a51ed503b74c1739cf150cdc91685653deed0 +Author: Bdale Garbee +Date: Sat Apr 22 15:45:52 2017 -0600 + + enable spi flash on telefiretwo + +commit ffc90fa3f932aef4dd85147817949aa9474b6d26 +Author: Bdale Garbee +Date: Sat Apr 22 11:38:08 2017 -0600 + + fix TeleFireTwo product name in ao-list output + +commit 4682323a4bf147b9a908f5f9104bf01ab2cf0533 +Author: Keith Packard +Date: Fri Apr 21 23:02:57 2017 -0700 + + altos/stmf0: Pull beeper pin low when beeper is off + + This avoids having the pin float and pick up noise from any adjacent + signals, like TeleMini's radio. + + Signed-off-by: Keith Packard + +commit eb1c2bf5244840049c0a58e0ceecfcd9f5c290dd +Author: Keith Packard +Date: Fri Apr 21 22:24:00 2017 -0700 + + doc: Finish updates for v1.7 + + Scrub all TeleMini references and make sure they're fixed for v3. No + 'emergency' mode yet. No reflashing yet. + + Add v1.7 release notes. + + Signed-off-by: Keith Packard + +commit 5849ee6c09669e6d2e6940a76bcb5cc23178fc68 +Author: Keith Packard +Date: Fri Apr 21 21:32:26 2017 -0700 + + altos/lpc: Really fix aes entry in lpc vpath + + I added another entry instead of fixing the existing one. Not ideal. + + Signed-off-by: Keith Packard + +commit c833c93e812936125cfe9532523ea36b5046e58d +Author: Keith Packard +Date: Fri Apr 21 18:16:45 2017 -0700 + + Replace turnon_telemini with v3 version. Add test-teleminiv3 + + Prepare for TeleMini v3.0 release. + + Signed-off-by: Keith Packard + +commit 8978687dc2ae90e4005a8f7d598940b7df6a4359 +Author: Keith Packard +Date: Fri Apr 21 18:08:25 2017 -0700 + + doc: Update TeleMini v3 photos to production unit + + Replace prototype photos + + Signed-off-by: Keith Packard + +commit 86a54146b58be86c58fb45386c7abcfa0bb11677 +Author: Keith Packard +Date: Fri Apr 21 17:15:05 2017 -0700 + + alots/stmf0: Fix vpath entry for AES directory + + Mis-placed ) + + Signed-off-by: Keith Packard + +commit 64ac93f5495db7a8b06f1eb4fe4eb2418125d792 +Author: Keith Packard +Date: Fri Apr 21 17:06:23 2017 -0700 + + altos/lpc,altos/stmf0: Use -n flag to work around link editor issue + + Something changed in the link editor which makes it complain about 'no + space for program headers' on LPC and STMF0 builds. Somehow, adding + the '-n' flag to the linking step fixes it. It doesn't appear to break + the build, so I guess it's ok? + + Signed-off-by: Keith Packard + +commit 77c76e429074a53c1c5230a7b5e665d1715b296f +Author: Keith Packard +Date: Fri Apr 21 17:04:28 2017 -0700 + + altos/telemini-v3.0: Remove vestiges of the pre-USB code + + Pre-USB telemini v3 designs had a separate firmware load for radio + calibration. Now that we've got enough USB to perform flash/cal/test, + we don't need that other firmware load, so we can remove the remaining + Makefile remnants of the calibration load. + + Signed-off-by: Keith Packard + +commit adb842b64b04a7d70e543bad7ae59807d549e85a +Author: Keith Packard +Date: Fri Apr 21 16:40:58 2017 -0700 + + altos/lpc: Add (void *) cast to fix alignment warning + + The -Wcast-align warning is generated when this cast is not present. + + Signed-off-by: Keith Packard + +commit 51ce352d179835ca08e4cf9326e9e77d6b972fb7 +Author: Keith Packard +Date: Fri Apr 21 09:18:48 2017 -0700 + + altos/lpc: Fix up Makefile definitions + + vpath reference to aes was busted. + WARN_CFLAGS needs -Wcast-align. + Wrap AO_CFLAGS. + + Signed-off-by: Keith Packard + +commit ec319edd2cda321d7542784b997acd0da040fa3d +Author: Keith Packard +Date: Fri Apr 21 09:17:18 2017 -0700 + + ao-test-baro: Be more lax about altitude checks + + High pressure here today and the altimeter is reading -69m. Allow down + to -100m when testing baro values. + + Signed-off-by: Keith Packard + +commit 7db49a2052ec905cdc02f626c0933ca6889d64a4 +Author: Keith Packard +Date: Wed Apr 19 23:08:56 2017 -0700 + + altos/telemini-v3.0: Add flash loader + + Now that telemini has USB, use the boot loader to make it easy to + update firmware. + + Signed-off-by: Keith Packard + +commit d1ba276c6e54564f82920f65bf4c19df85c9ea56 +Author: Keith Packard +Date: Wed Apr 19 23:08:06 2017 -0700 + + altos/telemini-v3.0: Update to production hardware + + Removed LEDs. Added USB. Flipped lots of pins around. + + This appears to make telemini work. + + Signed-off-by: Keith Packard + +commit 93983730a6628a2a85b6fc543df236b35d501ee9 +Author: Keith Packard +Date: Wed Apr 19 16:00:24 2017 -0700 + + altos/telebt-v3.0: Add LCO bits for testing + + Add the USB commands for LCO testing to TeleBT v3.0 + + Signed-off-by: Keith Packard + +commit 944d8466a31842c34304b77364d632e259238018 +Author: Keith Packard +Date: Wed Apr 19 14:19:28 2017 -0700 + + altos/telefiretwo-v0.2: Add AO_CC1200_SPI_SPEED + + Needed for products with different SPI speed options. + + Signed-off-by: Keith Packard + +commit 1e7143e5d448cd05c355f4a323ae4892b02022ac +Author: Bdale Garbee +Date: Wed Apr 19 15:08:15 2017 -0600 + + add new ADC channels for telefiretwo + +commit 6e699fa4971668bbe569d2a0e2ed9f891877d140 +Author: Bdale Garbee +Date: Tue Apr 18 16:47:43 2017 -0600 + + need top level Makefile too + +commit 9fa46346d576081f99860cad96c91bcf63233649 +Author: Bdale Garbee +Date: Tue Apr 18 16:47:05 2017 -0600 + + builds, loads, runs, not very useful yet + +commit 207403e53cc80b0649ce3c004f97d8e1dad824c8 +Author: Bdale Garbee +Date: Tue Apr 18 16:33:27 2017 -0600 + + copy telefiretwo-v0.2 to start firmware for v1.0 + +commit f69d85e2b32370ab68e2725e739417cad6d7a590 +Author: Keith Packard +Date: Thu Apr 13 21:48:46 2017 -0600 + + telegps-v2.0: Remove fec_tx code and ADC logging. + + This gets telegps-v2.0 to link. + + Signed-off-by: Keith Packard + +commit 4e561ae43a734d870470e36c41232482bd5f398f +Author: Keith Packard +Date: Thu Apr 13 21:47:14 2017 -0600 + + altos/stmf0: Split up rom load in altos.ld to make linker happy + + The linker isn't happy when the .ld file tries to add text, the .exidx + and .rodata segments in the same block. Split them up for success. + + Signed-off-by: Keith Packard + +commit a5c8b8c59f99108233d99ceceb6f85315694e4b1 +Author: Keith Packard +Date: Thu Apr 13 21:18:58 2017 -0600 + + cortexelf-v1: Fetch data at TPB rising when MWR or MRD are low + + This should get the right value at least. + + Signed-off-by: Keith Packard + +commit 3390c62b6d0761764ec5249d72bda33b984a8f90 +Author: Keith Packard +Date: Thu Apr 13 21:16:52 2017 -0600 + + altos/telegps: Inherit LDFLAGS from lpc make specification + + Somethings messed up with cortex-M0 linking, and this isn't helping as + it overrides the LDFLAGS coming from the architecture. + + Signed-off-by: Keith Packard + +commit f18793efb1fbfd17963b9146fae084f2b843d7a3 +Author: Bdale Garbee +Date: Thu Apr 13 19:36:49 2017 -0600 + + initial cut at telegps-v2.0 firmware + +commit eb0b2b4e9f56d1d6fc2b06e39c8372dfcdf3b1f5 +Author: Keith Packard +Date: Sun Apr 9 13:03:50 2017 -0700 + + cortexelf-v1: Initialize key matrix code + + This gets the hex keypad working. + + Signed-off-by: Keith Packard + +commit 6efa53bafda18313742849a6c4992f09c3e403c3 +Author: Keith Packard +Date: Sun Apr 9 12:59:07 2017 -0700 + + cortexelf-v1: Bump SPI pin speed to 40MHz to for sdcard. Fix VGA DMA. + + Tell the DMA code to leave the DMA engine enabled so the VGA output + can use it. + + Signed-off-by: Keith Packard + +commit c97b4c65d66078a4e187b782669e6b36ee92d30c +Author: Keith Packard +Date: Sun Apr 9 12:56:59 2017 -0700 + + altos: Use MP switch in cortexelf boot loader for force loader mode + + Provide a way to get to the boot loader on the cortexelf board by + turning the MP switch on. + + Signed-off-by: Keith Packard + +commit 9e80b8bd10433ecc6ebe7c295e16b62b3883987d +Author: Keith Packard +Date: Sun Apr 9 12:55:34 2017 -0700 + + altos: Escape lisp REP loop with () input + + Provide a way to get out of a lisp read-eval-print loop that can be + easily input from the keyboard. + + Signed-off-by: Keith Packard + +commit 83c1e4e8ca684f555cba252efd3882f811d8e154 +Author: Keith Packard +Date: Sun Apr 9 12:54:57 2017 -0700 + + altos: Document a few more SPI mode bits in VGA driver + + Just comment changes + + Signed-off-by: Keith Packard + +commit 24cd5dd33ccf65c1b277911c460a89ec2b52e421 +Author: Keith Packard +Date: Sun Apr 9 12:53:34 2017 -0700 + + altos: Drive row low instead of high in matrix driver + + Driving it high won't work all that well as we're looking for zero bits. + + Signed-off-by: Keith Packard + +commit a68fb412589819980759d49565a084b23eee8b8f +Author: Keith Packard +Date: Sun Apr 9 12:51:49 2017 -0700 + + altos: Place AS1107 in 'normal' mode at end of init sequence + + This makes sure the device is out of reset mode while initializing, + and then placed in normal mode to turn on the display. + + Signed-off-by: Keith Packard + +commit 04d4b17635fc9395c70aa0840971c00082f509ba +Author: Keith Packard +Date: Sun Apr 9 12:48:54 2017 -0700 + + ao-elftohex: Add conditions for skipping ELF sections + + Skip sections with size 0, or which are of type SHT_NOBITS or which + don't have the SHF_ALLOC flag set. + + This avoids crashing on sections which don't have any data to copy. + + Signed-off-by: Keith Packard + +commit 86d5119f19b5f3131d224982e011fd233b48aa22 +Author: Keith Packard +Date: Tue Apr 4 16:05:15 2017 -0700 + + cortexelf-v1: More 1802 noodling + + Add code to track the address and data displays, change how 1802 pin + tracking works + + Signed-off-by: Keith Packard + +commit 301b724d2169f4ac46d921f518455c783e1dd894 +Author: Keith Packard +Date: Tue Apr 4 16:04:25 2017 -0700 + + stm: Add more mask-based GPIO controls + + Lets cortexelf do more things with groups of pins, rather than one pin + at a time. + + Signed-off-by: Keith Packard + +commit 71e430bb39fc97e543778f7bc1f1bef554ba8b75 +Author: Keith Packard +Date: Tue Apr 4 16:03:36 2017 -0700 + + altos: Allow programs to enable SDCARD debugging if desired + + Provides for per-application control over SDCARD debugging + + Signed-off-by: Keith Packard + +commit 4eced9224f40e48d7057352b3424c18025f43f25 +Author: Keith Packard +Date: Tue Apr 4 16:02:46 2017 -0700 + + altos: Disable FAT commands unless requested + + This are debugging commands; don't provide them unless requested + + Signed-off-by: Keith Packard + +commit d4ff161e89d852c07934704ea2cbea20a48259a7 +Author: Keith Packard +Date: Tue Apr 4 16:00:56 2017 -0700 + + telegps-v0.1: Hack up for SDCARD debugging + + Disable everything not SDCARD related for debugging. + + Signed-off-by: Keith Packard + +commit 920b70fd5f6b78461c7ebae6b1e6490a0e050bc2 +Author: Keith Packard +Date: Tue Apr 4 15:59:56 2017 -0700 + + altos: Define CC115L spi speed in each product + + Different SoCs have different SPI speeds available; have each product + specify the speed to use instead of trying to use 4Mhz everywhere. + + Signed-off-by: Keith Packard + +commit 280eefc8f86e90e742c536a074d7284cce03af15 +Author: Keith Packard +Date: Mon Apr 3 11:41:51 2017 -0700 + + cortexelf-v1: Add pin definitions for 1802 connections + + Signed-off-by: Keith Packard + +commit 0197157a295d848bac65cf7f4457dd5a99af24e3 +Author: Keith Packard +Date: Mon Apr 3 11:37:21 2017 -0700 + + stm: Add a few more GPIO functions to make dealing with the 1802 easier + + ao_gpio_set_mask and ao_gpio_get_all + + Signed-off-by: Keith Packard + +commit 89c8e0299504e66fc416a778055958cff467e008 +Author: Keith Packard +Date: Mon Apr 3 11:36:52 2017 -0700 + + cortexelf-v1: Make bit flipping array constant + + Signed-off-by: Keith Packard + +commit 47004dfe8ee8c8b31085b066d3d0fd5142fd49da +Author: Keith Packard +Date: Mon Apr 3 09:36:00 2017 -0700 + + cortexelf-v1: doodling with 1802 bits + + Just some random ideas about how to manage the 1802 + + Signed-off-by: Keith Packard + +commit 5bb9cf38c84663713c178f54b684d40b6c00b11d +Author: Keith Packard +Date: Sun Apr 2 20:33:49 2017 -0700 + + cortexelf-v1: Add bit flipping array generator + + Someone hooked up the data lines between the systems backwards, so we + get to swizzle the bits in software. + + Signed-off-by: Keith Packard + +commit 8c1478b55f5dbe9711b31a34d4f5e3563f1f42d2 +Author: Keith Packard +Date: Sun Apr 2 19:32:17 2017 -0700 + + cortexelf-v1: Hook up hex keypad using matrix input driver + + Signed-off-by: Keith Packard + +commit 79215de60d3e11b4abd1ecd2fa9575a323b76754 +Author: Keith Packard +Date: Sun Apr 2 19:31:45 2017 -0700 + + altos: Allow buttons to be high when pressed rather than low + + Signed-off-by: Keith Packard + +commit 09f8710eb320f37f20dda8c635497c2b505d25e2 +Author: Keith Packard +Date: Sun Apr 2 19:30:57 2017 -0700 + + altos: add button matrix driver + + Scans the matrix once per clock tick queuing events for changed keys. + + Signed-off-by: Keith Packard + +commit 17ec1c510ccc42bbc387940b5805f452697f78d6 +Author: Keith Packard +Date: Sun Apr 2 17:39:26 2017 -0700 + + cortexelf-v1: Hook up AS1107 in test mode + + Provide a 'L' command to display values + + Signed-off-by: Keith Packard + +commit cc1b56faa88c75c9c86af89c77d7f1349573b7b0 +Author: Keith Packard +Date: Sun Apr 2 17:39:05 2017 -0700 + + altos: Add AS1107 LED display driver + + Signed-off-by: Keith Packard + +commit 1bc48b075f76bfef258f516549573429b24f284c +Author: Keith Packard +Date: Sun Apr 2 16:37:42 2017 -0700 + + cortexelf-v1: Add buttons + + Signed-off-by: Keith Packard + +commit 8284d3639cd24e2fa0faf1e35e7276ba35a24f8f +Author: Keith Packard +Date: Sun Apr 2 16:22:28 2017 -0700 + + cortexelf-v1: Add serialblather command. + + This reads from stdin and dumps it to both serial ports until you type ~ + + Signed-off-by: Keith Packard + +commit 6fb817f218a69b28973b0d059d71809717b1e2d1 +Author: Keith Packard +Date: Sun Apr 2 16:17:33 2017 -0700 + + lisp: Fix up lisp build so projects can get ao_lisp_const.h built as needed + + Signed-off-by: Keith Packard + +commit 3ce663875d69739cc2d43fcd88b22820cd9d6500 +Author: Keith Packard +Date: Sun Apr 2 15:56:17 2017 -0700 + + stm: Use common flash wait loop instead of inlining + + Signed-off-by: Keith Packard + +commit 1f5f0638f283fbb784021873c649109d4ed0257c +Author: Keith Packard +Date: Sun Apr 2 15:53:17 2017 -0700 + + cortexelf: Add lisp interpreter + + Signed-off-by: Keith Packard + +commit 54c76d48924fecc2aeabbc352c553822a87f9d19 +Author: Keith Packard +Date: Sun Apr 2 15:40:03 2017 -0700 + + cortexelf-v1: Use new memory map to access all flash and ram. Add fat. + + Signed-off-by: Keith Packard + +commit 7b031d5a86213364196b67f7e3f92865da8adbf9 +Author: Keith Packard +Date: Sun Apr 2 15:28:45 2017 -0700 + + cortexelf-v1: Hook up serial consoles for debugging + + This will make playing with serial ports easier for now. + + Signed-off-by: Keith Packard + +commit 62b0228aed5191c8d769f9f34143a13036e210a7 +Author: Keith Packard +Date: Sun Apr 2 15:18:34 2017 -0700 + + cortexelf-v1: Fix clock to drive VGA at 640/480. Add sdcard, remove others + + VGA requires the CPU to run at 24MHz. + + Signed-off-by: Keith Packard + +commit 637d522c6a15b47051103ccc3626be3206a7a2df +Author: Keith Packard +Date: Sun Apr 2 15:04:09 2017 -0700 + + cortexelf-v1: Add ps/2 and vga with graphics + + Start hooking up devices with known drivers. + + Signed-off-by: Keith Packard + +commit 9f451db9889cd578c3032356fd2aa4b5ed45878d +Author: Bdale Garbee +Date: Sun Apr 2 15:47:31 2017 -0600 + + capture pnpservo makefiles too + +commit bc150497de8539827177805c7f4430c67ca6762f +Author: Bdale Garbee +Date: Sun Apr 2 15:47:14 2017 -0600 + + makefiles too + +commit 66b06332dadd83c309bbfe02240b7a071fd57ff2 +Author: Bdale Garbee +Date: Sun Apr 2 15:41:56 2017 -0600 + + initial skeleton of CortexELF support + +commit d318b5cfc1a0312697739576d35cc1a190d88849 +Author: Bdale Garbee +Date: Sat Apr 1 12:23:24 2017 -0600 + + first rough cut at skeleton of code for pnpservo .. altos boots and runs + +commit 190cdaa5cb18e78caeeaaaaed6a9d304e939eb6b +Author: Keith Packard +Date: Sun Mar 5 22:42:37 2017 -0800 + + doc: Rename telemini doc file from telemini-v1.0.inc to telemini.inc + + This file now contains information on both TeleMini versions. + + Signed-off-by: Keith Packard + +commit 7bb4dbab45f98dd5fd85d9daf12d27b153c0ef3a +Author: Keith Packard +Date: Sun Mar 5 22:33:36 2017 -0800 + + ao-tools/ao-flash-stm: Use openocd instead of st-utils + + openocd upstream and debian package can both flash stm32l processors, + so use that in preference to st-flash. + + Signed-off-by: Keith Packard + +commit f004eaa2c26b4c61a8c3de2c0667a4e9865e704d +Author: Keith Packard +Date: Thu Mar 2 13:37:12 2017 -0800 + + ao-tools/ao-flash-lpc: Adapt to current openocd LPC support + + Openocd 0.9.0 has generalized the lpc11xx support for all lpc11xx + processors, not just the lpc11u14. This replaces the specific + lpc11u14.cfg with the general lpc11xx.cfg file. + + Unlike the build we were using, this doesn't adjust the + 'verify' command to adapt for the checksum which gets added during the + flashing process. Hence, we disable verification and trust that if the + flash loader works to load the OS, it's fine. + + Signed-off-by: Keith Packard + +commit 59aaac44e3e164b326518b324b52d115fbb76fca +Author: Keith Packard +Date: Wed Mar 1 14:01:59 2017 -0800 + + telemini outline svg had wrong version number + +commit b5a42665d7811707b6bd4a67d7d8e6532daa29e4 +Author: Keith Packard +Date: Wed Mar 1 13:53:36 2017 -0800 + + Add initial TeleMini v3 docs + + Uses pictures of the prototype. + + Signed-off-by: Keith Packard + +commit d1c2a5729da00be9d393015bbaa2d2f58e936d84 +Author: Keith Packard +Date: Mon Feb 20 17:34:43 2017 -0800 + + altos/nucleo-32: Update lisp files, add beeper support + + Signed-off-by: Keith Packard + +commit d1956000ba2e6260977aa669475d3ff725578b55 +Author: Keith Packard +Date: Mon Feb 20 17:32:09 2017 -0800 + + altos/lisp: Not quite ready to start making it look like scheme yet + + Lots more code to write before these symbols can be exposed. + + Signed-off-by: Keith Packard + +commit 9603d737e9ea58217ff2c2dd7c350c7a29fba980 +Author: Keith Packard +Date: Mon Feb 20 17:29:15 2017 -0800 + + altos/stmf0: Support timer 2/3 for the beeper + + Tested on timer 2, all four channels. + + Signed-off-by: Keith Packard + +commit 003e9479ad4364d9f7acf189b35f32ccdfd43be0 +Author: Keith Packard +Date: Mon Feb 20 16:51:09 2017 -0800 + + altos/stmf0: Support tim1 beeper channel other than 3 + + ch1 was broken and ch2 didn't have any code at all. + + Signed-off-by: Keith Packard + +commit 3c3f5e316c0c2464568db883d50881f5b898abac +Author: Keith Packard +Date: Mon Feb 20 17:33:37 2017 -0800 + + altos/telemini-v3.0: Add beeper defines needed for more general beeper code + + The beeper code now wants to know which timer, port and pin are in use. + + Signed-off-by: Keith Packard + +commit dc4bee9600be22531fd3c5bec15f712eb2e7ed2d +Author: Keith Packard +Date: Mon Feb 20 12:18:58 2017 -0800 + + altos: Add stm-vga demo project + + Uses the VGA and PS/2 drivers to provide an interactive console. + + Signed-off-by: Keith Packard + +commit 0eadc2d50417408beebd50e4a0e7e12430ed67ef +Author: Keith Packard +Date: Mon Feb 20 12:16:27 2017 -0800 + + altos/stm: Add draw and lisp to make search paths. + + Signed-off-by: Keith Packard + +commit c296acd643698d0128e2f58f91a9cfeea63f580a +Author: Keith Packard +Date: Mon Feb 20 12:21:39 2017 -0800 + + altos: Add console driver using VGA and PS/2 + + Provides an interactive text console. + + Signed-off-by: Keith Packard + +commit c1d52178ce63ebdc44c83d1bca5027942e2d778c +Author: Keith Packard +Date: Mon Feb 20 12:19:42 2017 -0800 + + altos: Add PS/2 keyboard driver + + Interrupt driven, includes standard US keymap. + + Signed-off-by: Keith Packard + +commit 6b39d3093c3b87689717bb03988d160473c53c64 +Author: Keith Packard +Date: Sun Nov 20 00:04:27 2016 -0800 + + altos: Add VGA driver for STM32L processors + + Generates vsync/hsync using timers and pixel data using the SPI port. + 320x240 video using 640x480 mode and a 24MHz "pixel" clock. + + Signed-off-by: Keith Packard + +commit 1301d576d9bface4cc625e4a4187401f93f54444 +Author: Keith Packard +Date: Mon Feb 20 12:17:42 2017 -0800 + + altos: Add bitmap drawing code + + Includes solid fills, text and lines. + + Signed-off-by: Keith Packard + +commit a487d2fcba57141f6b083d5612c76bac5ad1ac7c +Author: Keith Packard +Date: Mon Feb 20 12:15:45 2017 -0800 + + altos/stm: Add nvic priority register fields. Add more TIM234 defines. + + Signed-off-by: Keith Packard + +commit 80fd7f7bef5320ce86048d74dc4a72e1ec361120 +Author: Keith Packard +Date: Mon Feb 20 12:14:10 2017 -0800 + + altos/stm: Make i2c code handle PCLK1 of 24MHz + + Just adds the necessary defines to the code. + + Signed-off-by: Keith Packard + +commit 72ea90d28817549c4343d2fea03a4c951f849cbe +Author: Keith Packard +Date: Mon Feb 20 12:12:43 2017 -0800 + + altos/stm: Allow DMA channels to be hijacked by other code + + This lets code which needs finer control over DMA to use the channel + without interference, and leaves the DMA engine running so that it can. + + Signed-off-by: Keith Packard + +commit 5dc5e2e238f8c1a8ca35d85ec046124afa9385ad +Author: Keith Packard +Date: Tue Jan 10 14:45:25 2017 -0800 + + altos: Allow for console to be used for stdio + + Signed-off-by: Keith Packard + +commit e6fb0f13ba230ad9ce86cfa7f56491a0a3bd4b3d +Author: Keith Packard +Date: Tue Jan 10 14:43:07 2017 -0800 + + altos/avr: Avoid warning about unused args in stdio_put and stdio_get + + Signed-off-by: Keith Packard + +commit 839eadbc8e5694842eb498c6e47cfbf08ba8fbf4 +Author: Keith Packard +Date: Sun Nov 20 02:59:40 2016 -0800 + + altos/stm: Allow use basepri instead of primask for masking interrupts + + This allows for high priority interrupts (priority 0) to run, even + when other interrupts are blocked. Code executing in such interrupt + handlers must not attempt to control task execution as that will race + with the scheduler. + + Select this by defining AO_NONMASK_INTERRUPT in ao_pins.h. + non-maskable interrupt priority is AO_STM_NVIC_NONMASK_PRIORITY + + Signed-off-by: Keith Packard + +commit 088ddbb177efc8be2fc467524dc1668553080d3b +Author: Keith Packard +Date: Sun Nov 20 20:54:10 2016 -0800 + + altos/stm: Interrupt priority is in the upper bits of the priority mask + + Because the STM32L only offers 16 priority levels, the bottom four + bits of each priority mask are not used. All of the interrupt priority + settings in the system were using values < 16, making them all + effectively the same. Fix that by moving them into the upper 4 bits + and using symbolic constants everywhere. + + Signed-off-by: Keith Packard + +commit 992eee8e0b4c6c774f3355af107fb422019ff4e5 +Author: Keith Packard +Date: Sun Nov 20 20:56:01 2016 -0800 + + altos: Don't wait while idle if trying to minimize interrupt latency + + Keeping the scanout running reasonably means keeping interrupt latency + constant, and that requires leaving the CPU running. Don't wait for + interrupts when the system is running in this mode. + + Signed-off-by: Keith Packard + +commit f0c187dd6479996b83f85b6decf303ec0fc70fe5 +Author: Keith Packard +Date: Fri Jan 6 09:10:23 2017 -0800 + + ao-tools/ao-usbload: Pad image with 0xff instead of random bits + + Clear the temporary block to 0xff before copying in the target data so + that any unused bytes end up being left at 0xff instead of inheriting + whatever data was in the block before. + + Signed-off-by: Keith Packard + +commit 61f729567ff6355ab52c3e83399761103022a41a +Author: Keith Packard +Date: Sat Dec 17 20:57:38 2016 -0800 + + altos/cc1111: Remove unneeded initialization in ao_timer.c + + The timers are all stopped when the chip boots, so no need to stop + them. This saves some text space, allowing the current code to (just + barely) fit. + + Signed-off-by: Keith Packard + +commit 1029a6e4a61b20698e00e29fc0c8c3877f1e7b0f +Author: Keith Packard +Date: Sun Feb 19 17:36:04 2017 -0800 + + altoslib: Add TeleMini v3 support + + eeprom, telemetry and monitor idle. This is just like TeleMini v2, + except the ADC ranges are all difference as the voltage dividers are + different and the ADC itself has a different range. + + Signed-off-by: Keith Packard + +commit 5c272d8e50d0b23f31a6a9ebdad81fc514936222 +Author: Keith Packard +Date: Sun Feb 19 17:40:28 2017 -0800 + + altos/telemini-v3.0: Swap main and apogee sense pins. + + These were just hooked up wrong in the software. + + Signed-off-by: Keith Packard + +commit 59ac667c4ae14e0fa699fb0f398d31763a237646 +Author: Keith Packard +Date: Sun Feb 19 17:39:21 2017 -0800 + + altos: Split out TeleMini v3 log/telem labeling + + Allow the ground software to know which TeleMini version is in use, + even though they are very similar with only ADC values differing. + + Signed-off-by: Keith Packard + +commit c75736c9cd8f869c257a3024efda843cf0edf2a3 +Author: Keith Packard +Date: Sat Feb 18 22:56:49 2017 -0800 + + altos/telemini-v3.0: Finish initial turn-on + + TeleMini v3.0 is nearly working; there are some ADC issues still, and + lots of altosui work left to decode the new telemetry packet. + + Signed-off-by: Keith Packard + +commit efdeb402d04e7f04ad4bd2764f8f1ca7270b3dff +Author: Keith Packard +Date: Fri Feb 3 06:52:57 2017 +0100 + + altos/telemini-v3.0: Update to second prototype version + + Separate radio xtal means we run the processor at 48MHz. + Fix the battery monitoring voltage divider resistor values. + Disable most of the code until we've got the radio working. + + Signed-off-by: Keith Packard + +commit 97c814bc12893bee40f9dc38fabbaa69e0dc6aed +Author: Keith Packard +Date: Sat Jan 28 15:35:48 2017 -0800 + + altos: Initial TeleMini v3.0 code + + For first prototype, which attempted to use the SoC clock for the radio. + + Signed-off-by: Keith Packard + +commit b94fe9915b33283df6b86bcdc96ceada1fc71ce6 +Author: Keith Packard +Date: Sun Feb 19 17:42:05 2017 -0800 + + altos/stmf0: Add adc and beep support for TeleMini v3.0 + + Note that the ADC code is running very slowly as required by the high + impedance dividers on the TeleMini v3.0 pyro circuits. + + Signed-off-by: Keith Packard + +commit 1dc31a46f1d1adfdeab444664e581a780d995bf7 +Author: Keith Packard +Date: Sat Feb 18 22:49:34 2017 -0800 + + altos: Require SPI speed to be declared for cc1200 + + The cc1200 can't run SPI faster than 10MHz, so make sure every device + picks a SPI clock slower than that. + + Signed-off-by: Keith Packard + +commit 0bf267a6e2d401c8bd6a06d995e3d000777d622a +Author: Keith Packard +Date: Sat Feb 18 22:55:41 2017 -0800 + + altos: Allow applications to define LEDs for ao_report.c + + In case they don't have both a red and green LED. + + Signed-off-by: Keith Packard + +commit cf10239e5485a101fcd7a12b28be927af94d577a +Author: Keith Packard +Date: Sat Feb 18 22:54:35 2017 -0800 + + altos/stmf0: Allow projects to not use the USB boot loader + + Let applications define HAS_BOOT_LOADER on their own if desired. + + Signed-off-by: Keith Packard + +commit 3770a5f527cb6d519ce22fe91e0cc4078bf72661 +Author: Keith Packard +Date: Sat Feb 18 22:53:03 2017 -0800 + + altos/stmf0: Complain if the SPI configuration isn't complete + + If the pin usage values SPI_1_PA5_PA6_PA7 or SPI_1_PB3_PB4_PB5 aren't + defined, then the speed values for the pins aren't going to get set + correctly, which results in erratic SPI behaviour. + + Signed-off-by: Keith Packard + +commit f85997eb53779e637dca697d0d96da7d1235fa80 +Author: Keith Packard +Date: Fri Feb 3 06:51:11 2017 +0100 + + altos/stmf0: Allow apps to leave interrupt vectors at 0 + + TeleMini v3.0 doesn't need a boot loader, so we'll have the app run + its interrupt vector right at the bottom of the address space instead + of copying it to the bottom of ram and reconfiguring the chip to use that. + + Signed-off-by: Keith Packard + +commit f43c3ad0c643f714c523e513bdc8585c6d5a4050 +Author: Keith Packard +Date: Sat Feb 18 22:46:29 2017 -0800 + + ao-bringup: test-chaoskey needs to use the SerialNumber dmesg line + + I had a locally hacked kernel which was reporting the serial number + along with the device name. Instead of depending on that, just look + for the regular SerialNumber report which is in all kernel versions + + Signed-off-by: Keith Packard + +commit a21c7b5156e428a4f8e029fdb652c8ca1c63823b +Author: Keith Packard +Date: Fri Feb 3 06:47:32 2017 +0100 + + ao-bringup: Allow serial number on turnon_easymega cmdline + + This makes it a bit quicker to do a batch of them. + + Signed-off-by: Keith Packard + +commit 51edc29f5ba758ef8ba4fdd5f53fdabc6a31c98a +Author: Keith Packard +Date: Sat Jan 28 15:33:53 2017 -0800 + + altos: Eliminate printf format warning with long vs int + + Signed-off-by: Keith Packard + +commit d96224c2fdc535d08de23aec30d62d4ada9fb8d3 +Author: Keith Packard +Date: Sun Jan 22 15:29:13 2017 -0800 + + altos/chaoskey: use both halves of the CRC + + When pulling 16 bits from the 32-bit crc, instead of just using the + low bits, xor the two halves together. This appears to even out the + number of zero and one bits. + + Signed-off-by: Keith Packard + +commit bc076747f6cc00508aef909a3a5bd3edf8c9bd66 +Author: Keith Packard +Date: Sat Feb 18 12:14:59 2017 -0800 + + altos/lisp: Start adding scheme symbols + + Migrating to something more like scheme + + Signed-off-by: Keith Packard + +commit 9c85c9d60334edc2af65a47124873e94e0ff1e9c +Author: Keith Packard +Date: Tue Jan 10 14:47:03 2017 -0800 + + altos/lisp: Add casts to keep the latest GCC from whinging + + Something about alignment issues. + + Signed-off-by: Keith Packard + +commit 399ba0a62422f71ff9669ba03b6a058bb2981c27 +Author: Keith Packard +Date: Tue Jan 10 14:45:59 2017 -0800 + + altos/lisp: Tell compiler that the two lisp memory pools are aligned + + Otherwise, it will generate unaligned accesses to things fetched from + them. Sigh. + + Signed-off-by: Keith Packard + +commit 30d6b241447cb922b9316e86817f6e31eb973eed +Author: Keith Packard +Date: Sun Nov 20 01:41:59 2016 -0800 + + altos/lisp: Clean up hanoi.lisp demo a bit + + No serious changes. + + Signed-off-by: Keith Packard + +commit 329f76d5e2732ab1c1b10223842d7816275c7e8b +Author: Keith Packard +Date: Fri Nov 18 23:37:44 2016 -0800 + + altos/lisp: Move stack recursion check after null check + + Don't crash when printing null stack this way. + + Signed-off-by: Keith Packard + +commit 1999b2c915bd5b7df70cffa7777e411d3032d2d5 +Author: Keith Packard +Date: Fri Nov 18 22:57:22 2016 -0800 + + altos/lisp: Include memory stats for test program + + Signed-off-by: Keith Packard + +commit 129e07ccc9b8a33491a905a91ca6c5b0509aba9c +Author: Keith Packard +Date: Fri Nov 18 22:53:36 2016 -0800 + + altos/lisp: Cleanup some DBG defines + + Get rid of the remaining duplicate defines. + + Signed-off-by: Keith Packard + +commit 2c80fea1936ff956df127b43e65139afec3929a0 +Author: Keith Packard +Date: Fri Nov 18 22:52:53 2016 -0800 + + altos/lisp: Share binary search for memory chunk between mark and move + + Save some text space. + + Signed-off-by: Keith Packard + +commit 1b1bc92e6781c563e3d3b117b9cda2dddccc44de +Author: Keith Packard +Date: Fri Nov 18 22:52:10 2016 -0800 + + altos/lisp: Add builtin 'collect' + + Collect memory, return amount free. + + Signed-off-by: Keith Packard + +commit c3a4d7721f0f5d082336b8cc9c9d765ad2f7d17e +Author: Keith Packard +Date: Fri Nov 18 22:41:46 2016 -0800 + + altos/lisp: Sort frames by atom + + Fortunately, the collector always retains the relative order between + addresses, so we can sort based on the atom address itself. This + reduces the time spent looking for names in larger (e.g. global) + frames. + + Signed-off-by: Keith Packard + +commit 8f833f31f625526a5f1e9a1bd561733b5bb2bcaa +Author: Keith Packard +Date: Fri Nov 18 21:17:54 2016 -0800 + + altos/lisp: Build new ao_lisp_stack.c into test and lambdakey + + Helpful to include the new source file. + + Signed-off-by: Keith Packard + +commit 35424031747b41b1125e715a975f1679b89fc27a +Author: Keith Packard +Date: Fri Nov 18 21:16:11 2016 -0800 + + altos/lisp: bounds check in move_map plus binary search + + This makes move_map faster by skipping all addresses which aren't + changing. + + Also changed the interface from address to offset to avoid computing + the offset multiple times. + + Signed-off-by: Keith Packard + +commit 85db6d68a273859482e036b60fec7e2b84e9c262 +Author: Keith Packard +Date: Fri Nov 18 21:15:33 2016 -0800 + + altos/lisp: Empty lambda body is not an error + + It's not very exciting, but it's still legal + + Signed-off-by: Keith Packard + +commit ecef616599d5ec4fd5d42e67d0dc779a0630079b +Author: Keith Packard +Date: Fri Nov 18 21:14:47 2016 -0800 + + altos/lisp: Use poly stashes for stacks + + Saves some memory. + + Signed-off-by: Keith Packard + +commit 4c812b8c903bd7e689572f8800ecc092af9cfe18 +Author: Keith Packard +Date: Fri Nov 18 21:12:50 2016 -0800 + + altos/lisp: Make DBG settings global + + This avoids having different values in different files, which wasn't useful. + + Signed-off-by: Keith Packard + +commit e600fc409c577eec02af612a36431c477a9c875e +Author: Keith Packard +Date: Fri Nov 18 19:04:05 2016 -0800 + + altos/lisp: Add continuations + + This provides call/cc and makes 'stacks' visible to the application. + + Signed-off-by: Keith Packard + +commit 2cc8ca2b781be0a6e7ce14405eb4611bc00a3a3e +Author: Keith Packard +Date: Thu Nov 17 18:45:31 2016 -0800 + + altos/lisp: Take advantage of implicit progns in hanoi demo + + Remove extra progn wrappers now that cond, lambda and while all + support implicit ones. + + Signed-off-by: Keith Packard + +commit 11c79167cdd56015bbd1645db2d4394dcb4f0fbb +Author: Keith Packard +Date: Thu Nov 17 16:52:30 2016 -0800 + + altos/lisp: have 'while' return the last body value + + Instead of always returning 'nil', let while return the last body + value. + + Signed-off-by: Keith Packard + +commit 9126ae10b3c5acf0055caa31b1f08215675af784 +Author: Keith Packard +Date: Thu Nov 17 16:51:34 2016 -0800 + + altos/lisp: Take advantage of implicit progn in ROM code + + Signed-off-by: Keith Packard + +commit eaa528e4e62ba1d9765888760d387303487b2e01 +Author: Keith Packard +Date: Thu Nov 17 16:08:15 2016 -0800 + + altos/lisp: Make lambda, cond and while all have implicit progns + + This lets all of these execute more than one sexpr, returning the + value of the last. + + Signed-off-by: Keith Packard + +commit ffaf73407bcdf6bc4120c90212de4a2f52cf7991 +Author: Keith Packard +Date: Thu Nov 17 16:07:42 2016 -0800 + + altos/lisp: Compile ao_lisp_make_const -no-pie + + Makes debugging easier + + Signed-off-by: Keith Packard + +commit 51bdee662fdfad1937c576daadd2e5eacac17905 +Author: Keith Packard +Date: Thu Nov 17 16:06:55 2016 -0800 + + altos/lisp: Fix uninitialized values in ao_lisp_make_const + + Signed-off-by: Keith Packard + +commit 84732aebd10c293101727ba567bfc733dc30efca +Author: Keith Packard +Date: Thu Nov 17 16:06:05 2016 -0800 + + altos/lisp: Dump globals on error + + Useful for debugging + + Signed-off-by: Keith Packard + +commit 05ac336ea954c0f5eefabdefb0c8c5747be3fd32 +Author: Keith Packard +Date: Thu Nov 17 16:05:29 2016 -0800 + + altos/lisp: Fix error atom name in ao_lisp_length + + Cut&paste error. + + Signed-off-by: Keith Packard + +commit 2ce7ab37df07b3c1ea1ca9befc06477e3b6cdeac +Author: Keith Packard +Date: Thu Nov 17 16:04:38 2016 -0800 + + altos/lisp: Remove some stale frame debugging checks + + No-one sets frame->_num to 0xff to hit these + + Signed-off-by: Keith Packard + +commit d37945f1404043e6bd287ce7ad7a57bc3289609b +Author: Keith Packard +Date: Wed Nov 16 14:59:08 2016 -0800 + + altos/lisp: Clean up hanoi.lisp comments. + + Signed-off-by: Keith Packard + +commit bcf5eb5825b1217d74f117b02d09b4ce4b007beb +Author: Keith Packard +Date: Wed Nov 16 14:12:59 2016 -0800 + + altos/lisp: Eliminate compiler warning about array bounds at -O3 + + Using ao_lisp_pool - 4 caused the compiler to whinge about computing + an address outside the bounds of the array. Sigh. Restructure the code + to do the adjustment-by-4 in the integer computations instead of the + pointer ones. + + Signed-off-by: Keith Packard + +commit a5ef084659205700aab33e81d20fb89833c03249 +Author: Keith Packard +Date: Wed Nov 16 14:00:38 2016 -0800 + + altos/lisp: binary search for chunk in collect + + Speeds up collect a bit + + Signed-off-by: Keith Packard + +commit 9f19cb10cd12f86b12d0599bab5c2ee351d814ae +Author: Keith Packard +Date: Wed Nov 16 13:59:54 2016 -0800 + + altos/test: Disable position independent executables + + This makes debugging programs so much harder + +commit a7fcf80e22e70516d0b2da314fb17ced20a3f775 +Author: Keith Packard +Date: Wed Nov 16 13:47:49 2016 -0800 + + altos/lisp: Allow empty defun bodies + + This allows for (defun foo()) + + Signed-off-by: Keith Packard + +commit daa06c8dedc6dc1cf21936ee2769d9d25f0567bd +Author: Keith Packard +Date: Wed Nov 16 13:19:20 2016 -0800 + + altos/lisp: Optimize chunk searching in collect + + Note range of existing chunks to exclude objects outside. + Only look at chunks which have been set to reduce loop cost. + + Signed-off-by: Keith Packard + +commit c8f9db184cc929ebde845730a6d4b7864e423a84 +Author: Keith Packard +Date: Wed Nov 16 12:34:14 2016 -0800 + + altos/lisp: Add incremental collection + + Realizing that long-lived objects will eventually float to the bottom + of the heap, I added a simple hack to the collector that 'remembers' + the top of the heap the last time a full collect was run and then runs + incremental collects looking to shift only objects above that + boundary. That doesn't perfectly capture the bounds of transient + objects, but does manage to reduce the amount of time spent not moving + persistent objects each time through the collector. + + Signed-off-by: Keith Packard + +commit 8406ddf8f0bd5453d6213973daed35991f80972a +Author: Keith Packard +Date: Tue Nov 15 20:37:59 2016 -0800 + + altos/lisp: Make hanoi example output a bit prettier + + Make the towers symmetrical instead of lopsided. Much nicer looking. + + Signed-off-by: Keith Packard + +commit 472ecec64213e6c37b588d69ca2e8efd5e9abe36 +Author: Keith Packard +Date: Tue Nov 15 20:25:03 2016 -0800 + + altos/lisp: remove nth from hanoi.lisp + + It's now in ROM. + + Signed-off-by: Keith Packard + +commit 5161f6d78647591cc7ab8774a04edbc68a09f689 +Author: Keith Packard +Date: Tue Nov 15 20:24:33 2016 -0800 + + altos/lambdakey: Strip out unused code + + Make space for more lisp bits! + + Signed-off-by: Keith Packard + +commit ac0f7768659e288338bf452b4248ae3572ea2f7d +Author: Keith Packard +Date: Tue Nov 15 20:22:54 2016 -0800 + + altos/lisp: Take advantage of multi-arg macros. Add more ROM funcs + + Added nth, or and and. + + Signed-off-by: Keith Packard + +commit 1a00bf4ac12a6505d4b23d94e99b4b46bf679020 +Author: Keith Packard +Date: Tue Nov 15 20:21:47 2016 -0800 + + altos/lisp: Allow macro/nlambda/lexpr to have multiple args + + Entries from the params are bound to the formals with whatever + remaining formals there are bound to the last argument as a list. + This makes writing functions a bit easier. + + Signed-off-by: Keith Packard + +commit 5c1fa73f159de9d9839e8619494c26931521d2d4 +Author: Keith Packard +Date: Tue Nov 15 20:20:14 2016 -0800 + + altos/lisp: Do better checking for un-evaluated macros in ROM + + Need to look at immediate lambdas as well, and also deal with + recursive functions by checking for recursion at each atom + dereference. + + Signed-off-by: Keith Packard + +commit 881161fe1c5fb0e2b1220c30572eb2c45bedbafe +Author: Keith Packard +Date: Tue Nov 15 20:18:59 2016 -0800 + + altos/lisp: re-use small frames + + This saves a pile more use of the allocator by noting when frames have + not been referenced from another frame and freeing them when they go + out of scope. Frames with references are left to the allocator to deal + with. + + Signed-off-by: Keith Packard + +commit 994adc7a47cbf3cbf6041eca7430273f8018de08 +Author: Keith Packard +Date: Tue Nov 15 10:32:36 2016 -0800 + + altos/lisp: remove duplicate 'length' lambda from hanoi example + + This function is now a builtin. + + Signed-off-by: Keith Packard + +commit 41175ff82bc0e35c99c60b49aa62944a12917157 +Author: Keith Packard +Date: Tue Nov 15 10:18:12 2016 -0800 + + altos/lisp: Get lambdakey and nucleo-32 building again + + Remove exti from the build list to make things fit. + + Signed-off-by: Keith Packard + +commit 974717eb9dad105c9897ee24f953d98d57eaec77 +Author: Keith Packard +Date: Tue Nov 15 09:55:22 2016 -0800 + + altos/lisp: Evaluate macros once, then smash them into place + + This assumes that macros are all pure functions, which should be true + for syntactic macros. + + Signed-off-by: Keith Packard + +commit b3b5bd2c14cfcde6c551a87ee6da08a53f1e4bc6 +Author: Keith Packard +Date: Mon Nov 14 23:04:05 2016 -0800 + + altos/lisp: Add license to hanoi demo + + Signed-off-by: Keith Packard + +commit 13a4d451b903d08e52005bcf531efa8de351bf2b +Author: Keith Packard +Date: Mon Nov 14 21:27:41 2016 -0800 + + altos/lisp: Improve hanoi demo + + Repaint in place, without first clearing. This makes the updates a lot + clealyer looking. + + Signed-off-by: Keith Packard + +commit 74ff0c6fd6c41cdaa054dcdb3d05c7d333bc24ff +Author: Keith Packard +Date: Mon Nov 14 21:27:03 2016 -0800 + + altos/lisp: Show number of collect calls in ao_lisp_test + + This helps tune the allocator + + Signed-off-by: Keith Packard + +commit 5557f6b87a9b8bc9716de8191f2062a772a6ae6c +Author: Keith Packard +Date: Mon Nov 14 21:25:38 2016 -0800 + + altos/lisp: Cache freed cons and stack items + + Track freed cons cells and stack items from the eval process where + possible so that they can be re-used without needing to collect. + + This dramatically reduces the number of collect calls. + + Signed-off-by: Keith Packard + +commit ce549b2c11e6b2571590021e1c0503d8a6e7a702 +Author: Keith Packard +Date: Mon Nov 14 19:55:36 2016 -0800 + + altos/lisp: Simplify GC a bit by only marking the head of each object + + We don't need to mark the whole object now as we're getting + information about where objects are by walking the tree each time + around the loop; ao_lisp_busy is only useful for terminating the walk + now. + + Signed-off-by: Keith Packard + +commit ddb4b8d90478ae324aa207a7541352c1ac9451ee +Author: Keith Packard +Date: Mon Nov 14 18:45:12 2016 -0800 + + altos/lisp: Change GC to do moves in batches of 32 + + This should make it quite a bit faster than doing one at a time. + + Signed-off-by: Keith Packard + +commit affcf6ffc08313151541993ee543bfe390165e81 +Author: Keith Packard +Date: Fri Nov 11 23:38:03 2016 -0800 + + altos/stmf0: Add a comment about the requirements for using ao_flash_stm + + Need HSI clock and the flashing functions loaded in ram. + + Signed-off-by: Keith Packard + +commit 30db58ade19ec69272a8c39c2f13d7919ca491a9 +Author: Keith Packard +Date: Fri Nov 11 23:36:22 2016 -0800 + + altos/lambdakey: Get save/restore working + + Need the HSI clock running for the flash hardware to work. + + Signed-off-by: Keith Packard + +commit 33aeffc123af1f9063969acf585f1caac885ced4 +Author: Keith Packard +Date: Fri Nov 11 23:34:54 2016 -0800 + + altos/lisp: Append a CRC to the saved image to validate on restore + + The CRC is actually of the ROM bits, so we can tell if the restored + image relates to the currently running code. + + Signed-off-by: Keith Packard + +commit 8f2d60b4c029bffaa559bd1f31f5b15230dfa674 +Author: Keith Packard +Date: Fri Nov 11 21:18:50 2016 -0800 + + altos/lisp: Add save/restore to ao_lisp_test + + Allow testing of the save/restore code under Linux. + + Signed-off-by: Keith Packard + +commit dba374516ed396633659dec571b6a44b03da8ad1 +Author: Keith Packard +Date: Fri Nov 11 21:16:09 2016 -0800 + + altos/lisp: Add save/restore infrastructure. Needs OS support to work. + + This sticks a few globals past the end of the heap and then asks the + OS to save the heap. On restore, the heap is re-populated by the OS + and then various global variables reset. + + Signed-off-by: Keith Packard + +commit 29c890b4599b3bbdbd09a5915ea68a63f4e0a9ac +Author: Keith Packard +Date: Fri Nov 11 21:11:13 2016 -0800 + + altos/lisp: Make sure memmove only happens once per object. Other GC fixes + + The memmove may be overlapping, so make sure it happens only once by + just checking whether move_size has been set, rather than looking at + ao_lisp_moving; that doesn't get set when moving a noted cons as that + still needs to be walked at a later time. + + Fix up the various looping move functions to all use the same + pattern. Atom was busted. + + Signed-off-by: Keith Packard + +commit d46ca67f93e9ecbc4d8c051c3fbdead85490b690 +Author: Keith Packard +Date: Fri Nov 11 21:07:09 2016 -0800 + + altos/lisp: Make ao_lisp_ref and ao_lisp_poly non-inline + + These functions are pretty large and end up consuming quite a bit of + space if inlined everywhere they are used. + + Signed-off-by: Keith Packard + +commit 00827a0ffe30938c26be216369fd2d8f8946d2c4 +Author: Keith Packard +Date: Fri Nov 11 00:28:57 2016 -0800 + + altos/lisp: Share mark function for mark and move + + These two operations both wanted to walk the referenced objects; + sharing is caring. + + Signed-off-by: Keith Packard + +commit 7f7e2431f5d1f7c1782ed6e774ccfc70fb4c87cf +Author: Keith Packard +Date: Fri Nov 11 00:28:31 2016 -0800 + + altos/lisp: add length, pack, unpack and flush + + lots more builtins + + Signed-off-by: Keith Packard + +commit f5a36c15f894803f8804bbc3daf105eed53d5ff6 +Author: Keith Packard +Date: Thu Nov 10 23:31:10 2016 -0800 + + altos/lisp: Add towers of hanoi example + + Uses vt100 escape sequences to animate the display even. + + Signed-off-by: Keith Packard + +commit 7da6bfc195fad97e3afc576c609897c131fd4d8c +Author: Keith Packard +Date: Thu Nov 10 23:29:21 2016 -0800 + + altos/lisp: Deal with memory compation in the middle of operations + + Handle memory compaction in places where we've got pointers into the + heap across an allocation operation. Either re-compute the values from + managed global references or add new roots across the allocation. + + Signed-off-by: Keith Packard + +commit 137898e3431d887e75b09d8c1ce57297a1558e43 +Author: Keith Packard +Date: Thu Nov 10 23:28:26 2016 -0800 + + altos/lisp: Improve lisp test program UI + + Add a prompt for stdin, read from other files on command line before + stdin. + + Signed-off-by: Keith Packard + +commit 92cdc0cf0e80c1ff3f31cce20fc2b9bda86e3638 +Author: Keith Packard +Date: Thu Nov 10 23:25:56 2016 -0800 + + altos/lisp: Make read() return eof atom on end of file + + Also make it an exception to hit eof in the middle of an sexpr. + + Signed-off-by: Keith Packard + +commit fb710f7f4f24f74ac3d45fcc423803384d986bb2 +Author: Keith Packard +Date: Thu Nov 10 23:24:11 2016 -0800 + + altos/lisp: use regular read-eval-print loop for make const + + No need to open code this sequence of operations. + + Signed-off-by: Keith Packard + +commit c7d7cdc2318a97534c4c1f9c6fd2b51644be729d +Author: Keith Packard +Date: Thu Nov 10 11:30:55 2016 -0800 + + altos/lisp: add progn, while, read and eval + + Progn as a builtin will help with tail-recursion. + while provides for loops until tail-recursion works :-) + read and eval are kinda useful. + + Signed-off-by: Keith Packard + +commit 417161dbb36323b5a6572859dedad02ca92fc65c +Author: Keith Packard +Date: Wed Nov 9 16:22:43 2016 -0800 + + altos/lisp: Clean up OS integration bits, add defun + + Provide an abstraction for the OS interface so that it + can build more cleanly on Linux and AltOS. Add defun macro. + + Signed-off-by: Keith Packard + +commit 0ee44c8e4bf5dabe6a97bf76b366c8b767c387f8 +Author: Keith Packard +Date: Wed Nov 9 11:13:58 2016 -0800 + + altos/lisp: macros appear to work now + + Needed an extra stack frame to stash the pre-macro state. This + simplified macro processing quite a bit; a macro now just evaluates + the function and then sends that result to be evaluated again. + + Signed-off-by: Keith Packard + +commit 794718abc62f4610495fe2bd535a2b67bc46573c +Author: Keith Packard +Date: Wed Nov 9 09:14:50 2016 -0800 + + altos/lisp: working on lexical scoping + + Not working yet + + Signed-off-by: Keith Packard + +commit cb4cdb115ad83ae0d75eb58e68f561d20279f027 +Author: Keith Packard +Date: Sun Nov 6 21:47:31 2016 -0800 + + altos/lambdakey-v1.0: Tweak memory allocations + + With non-recursive GC, more memory is available for the heap + + Signed-off-by: Keith Packard + +commit 6e5c1308ce33a864095eae02e7db18b0e043ab6e +Author: Keith Packard +Date: Sun Nov 6 10:53:46 2016 -0800 + + altos/lisp: convert GC to non-recursive + + Use a boolean array to note cons cells which would otherwise recurse, + then loop until that array is empty. + + Signed-off-by: Keith Packard + +commit d8cf97fe22acefab40d7bb321138e46d4483fef7 +Author: Keith Packard +Date: Sat Nov 5 17:53:15 2016 -0700 + + altos/lisp: more GC issues. add patom + + Use global ao_lisp_stack instead of local stack so that gc + moves of that item work. + + Signed-off-by: Keith Packard + +commit 286d07d83bd7ff361e5a904c151a75e5a9c8b071 +Author: Keith Packard +Date: Sat Nov 5 15:12:05 2016 -0700 + + altos/lisp: make sure stack->formals_last gets moved during GC + + Failing this leads to broken formals chains + + Signed-off-by: Keith Packard + +commit 3366efb139653939f053c1fe4aba352ba3b66c94 +Author: Keith Packard +Date: Sat Nov 5 14:51:58 2016 -0700 + + altos/lisp: Change GC move API + + Pass reference to move API so it can change the values in-place, then + let it return '1' when the underlying object has already been moved to + shorten GC times. + + Signed-off-by: Keith Packard + +commit 6fc1ee0f7adc6fcb3e850bcbaabc1db705314234 +Author: Keith Packard +Date: Fri Nov 4 16:51:12 2016 -0700 + + altos/lisp: get builtin macros working again + + Signed-off-by: Keith Packard + +commit c9456362c8bad8cd9be717f591f2d0841f88eb50 +Author: Keith Packard +Date: Fri Nov 4 16:31:34 2016 -0700 + + altos/lisp: Start rewriting eval as state machine + + Ad-hoc code was incomprehensible and I couldn't make 'cond' work, so + I'm starting over. + + Signed-off-by: Keith Packard + +commit c48bda3625fc507134da7b4af87a634e8eb3715b +Author: Keith Packard +Date: Thu Nov 3 21:51:26 2016 -0700 + + altos: Add lambdakey + + Signed-off-by: Keith Packard + +commit 77db0e8162cd01c2b42737b3d71b38cea942484f +Author: Keith Packard +Date: Thu Nov 3 21:49:50 2016 -0700 + + altos: Add lambda support to lisp + + Signed-off-by: Keith Packard + +commit 11cb03b1d336ee90c422be27588f57be573a9546 +Author: Keith Packard +Date: Wed Nov 2 22:56:01 2016 -0700 + + altos/lisp: Separate out values from atoms + + This enables changing values of atoms declared as constants, should + enable lets, and with some work, even lexical scoping. + + this required changing the constant computation to run + ao_lisp_collect() before dumping the block of constant data, and that + uncovered some minor memory manager bugs. + + Signed-off-by: Keith Packard + +commit 9e1a787f8828fb7b750ad3310c89a89536ea5286 +Author: Keith Packard +Date: Wed Nov 2 14:18:54 2016 -0700 + + altos/lisp: add set/setq and ' in reader + + Along with other small fixes + + Signed-off-by: Keith Packard + +commit 8362393a621ea78a96e7f65f602f4bfc7bbd1158 +Author: Keith Packard +Date: Wed Nov 2 14:18:31 2016 -0700 + + altos/stmf0: Add lisp to include directories + + Signed-off-by: Keith Packard + +commit caba623cb013b73e1f0ca369edf98e0376bec41a +Author: Keith Packard +Date: Wed Nov 2 14:14:23 2016 -0700 + + altos/kernel: Make ao_cmd_readline public. Return char from ao_cmd_lex. + + With these two changes, the readline function can be used by other + code. + + Signed-off-by: Keith Packard + +commit d2408e72d1e0d3459918601712b09860ab17e200 +Author: Keith Packard +Date: Tue Nov 1 21:14:45 2016 -0700 + + altos/lisp: Change lisp objects to use ao_poly everywhere. Add const + + This makes all lisp objects use 16-bit ints for references so we can + hold more stuff in small amounts of memory. Also adds a separate + constant pool of lisp objects for builtins, initial atoms and constant + lisp code. + + Now builds (and runs!) on the nucleo-32 boards. + + Signed-off-by: Keith Packard + +commit e2f4d25cd6f6f3787d4ee99264732d5b2ce23d4c +Author: Keith Packard +Date: Mon Oct 31 18:53:09 2016 -0700 + + altos: Add lisp reader + +commit 56d46ceaa1413415f25e47e81036426132f99924 +Author: Keith Packard +Date: Mon Oct 31 16:43:44 2016 -0700 + + Add first lisp bits + + Signed-off-by: Keith Packard + +commit 2cfcc622c94d87cdbee099f457b7d63cb2fcbc71 +Author: Bdale Garbee +Date: Wed Jan 25 12:21:29 2017 -0700 + + use elf, not ihx + +commit 4ae8eeb426ef60105ec8e53e289739e5a8ae5dae +Author: Bdale Garbee +Date: Wed Jan 25 12:00:20 2017 -0700 + + stop using /usr/share for binaries in remaining turnon scripts + +commit f2c7bb5879ba22df05fd1e39f01ea692313306fd +Author: Richard Hughes +Date: Tue Jan 10 17:15:24 2017 +0000 + + altos/chaoskey: Add a metainfo for the ChaosKey + + This provides the information necessary to reflash chaoskey using + standard Linux device firmware tooling. + +commit 89ecc32b90565ace078c4a84d4406a4d1f86821a +Author: Keith Packard +Date: Sat Dec 17 20:58:36 2016 -0800 + + altos/arm: Align data so that gcc 5.4 doesn't do byte-accesses. Add -Wcast-align + + Gcc 5.4.1 tracks alignment of data through assignments, so that a + uint32_t pointer which comes from byte-aligned uint8_t data: + + extern uint8_t foo[]; + + uint32_t *q = (void *) foo; + + Fetches and stores through this pointer are done bytewise. This is + slow (meh), but if q references a device register, things to bad very + quickly. + + This patch works around this bug in the compiler by adding + __attribute__((aligned(4))) tags to some variables, or changing them + from uint8_t to uint32_t. Places doing this will now be caught as I've + added -Wcast-align to the compiler flags. That required adding (void + *) casts, after the relevant code was checked to make sure the + compiler could tell that the addresses were aligned. + + Signed-off-by: Keith Packard + +commit f650211f9e99e1d3d0ae13ae559dd1c082f71545 +Author: Keith Packard +Date: Mon Dec 12 16:44:47 2016 -0800 + + altos/stm: Make ao_usb_set_address static. Saves a bunch of text space + + I'm sure this makes the function end up in-lined, which saves enough + text space to fit the flash loader in ROM again. + + Signed-off-by: Keith Packard + +commit d46698a01ed4903d36635b34867bfc4bb8fbafc6 +Author: Keith Packard +Date: Thu Nov 17 22:17:20 2016 -0800 + + ao-bringup: Improve EasyMini turnon and test scripts + + Wait less time before trying the test script. + Have the test script wait for the device to appear. And then use + colors to help make the results clear. + + Signed-off-by: Keith Packard + +commit 5e24d637a8af09bf64beb7fcf7be4c13eee76a43 +Author: Keith Packard +Date: Sun Oct 9 19:42:42 2016 -0700 + + altos/test: Fix tests + + A couple of fixups for ao_flight_test to dump pyro info only when + running in debug mode, and to change the aprs testing + + Signed-off-by: Keith Packard + +commit e3d8ad6de7d2dfabe45a285b27f465ba68844f05 +Author: Keith Packard +Date: Sun Oct 30 19:08:14 2016 -0700 + + altos/nucleo-32: Add basic support for STM32F042 Nucleo-32 board + + This hooks up the LED, USB and the USART. + + Signed-off-by: Keith Packard + +commit 148f6e0a107d9e88509958700351794f2f971312 +Author: Keith Packard +Date: Sun Oct 30 19:06:20 2016 -0700 + + altos/stmf0: Add USART support + + The STM32F0 usart can be operated much like the STM32L usart, but the + registers are all moved around. + + Signed-off-by: Keith Packard + +commit 26f2727eac0cca8930dde9d757bc094f73801859 Author: Bdale Garbee -Date: Mon Sep 5 20:59:11 2016 -0600 +Date: Sun Oct 2 17:19:14 2016 -0600 + + augment TeleDongle turn on script to support serial number on command line + +commit 66d4b5ea4031193e3c79ebdabeb381aae46fe93b +Author: Keith Packard +Date: Thu Sep 22 03:23:34 2016 +0300 + + Update pdclib to version using arm-specific 'ar' program + + Signed-off-by: Keith Packard + +commit 2c1ab416728c942ddf176f881f025840ada6bf93 +Author: Keith Packard +Date: Mon Sep 5 22:25:07 2016 -0600 - Merge branch 'master' into branch-1.6 + Fix release note html to remove xml bits + + Signed-off-by: Keith Packard commit 4fdf8ca9ca1cd5a84b03bd7a03c5806af64b413d Author: Keith Packard @@ -485,13 +2618,6 @@ Date: Tue Jul 5 18:03:49 2016 +0200 Signed-off-by: Keith Packard -commit 148b013dd29c26920ddfb53449ed4d8cc5a4b5ee -Merge: ea1ff22 cd97128 -Author: Bdale Garbee -Date: Tue Jul 5 10:23:18 2016 +0200 - - Merge branch 'master' into branch-1.6 - commit cd97128e30c47edfcc71f7d872cbdad14867934c Author: Bdale Garbee Date: Tue Jul 5 10:21:29 2016 +0200 @@ -504,19 +2630,6 @@ Date: Tue Jul 5 00:48:07 2016 +0200 updates made during 1.6.5 release process -commit ea1ff225f1f450ee3fc377807d1bb7b982bf792d -Author: Bdale Garbee -Date: Mon Jul 4 23:47:56 2016 +0200 - - updating ChangeLog for 1.6.5 release - -commit 2e26d1ab42163988dc26b06b016c3b05efe17659 -Merge: 639e461 65ed2f5 -Author: Bdale Garbee -Date: Mon Jul 4 23:47:24 2016 +0200 - - Merge branch 'master' into branch-1.6 - commit 65ed2f588ca596fe9aa559bebd590a2a11b9859b Author: Keith Packard Date: Sun Jul 3 12:00:10 2016 +0200 @@ -842,19 +2955,6 @@ Date: Fri Jun 17 10:18:20 2016 -0700 Signed-off-by: Keith Packard -commit 639e461ded29a48c155afea12171cbfc191ccfd7 -Author: Bdale Garbee -Date: Fri Jun 17 10:01:17 2016 -0600 - - releasing 1.6.4 - -commit 31cf047113ec72a78f4b500223a2c6be23bc86fd -Merge: 2f0c977 afe74c0 -Author: Bdale Garbee -Date: Fri Jun 17 10:00:10 2016 -0600 - - Merge branch 'master' into branch-1.6 - commit afe74c067a31ce420d0d4cdac2069c1d258a5114 Author: Keith Packard Date: Fri Jun 17 08:58:06 2016 -0700 @@ -1495,7 +3595,7 @@ Date: Mon May 9 17:56:28 2016 -0700 Signed-off-by: Keith Packard commit f078235803a80403014b3e54039fd2d0e0704367 -Merge: 04759dd c457c82 +Merge: 04759ddd c457c827 Author: Bdale Garbee Date: Mon May 9 15:52:38 2016 -0600 @@ -1527,19 +3627,6 @@ Date: Mon May 9 11:33:48 2016 -0700 Signed-off-by: Keith Packard -commit 2f0c977c747824d0798550ac64eceb1d66c50efd -Author: Bdale Garbee -Date: Fri May 6 18:12:20 2016 -0600 - - releasing 1.6.3 - -commit 15ae97fbdb4e75a74ea2e716194661d19dec46ff -Merge: ac7be4a 1216c0c -Author: Bdale Garbee -Date: Fri May 6 18:11:01 2016 -0600 - - Merge branch 'master' into branch-1.6 - commit 1216c0ccece4ca1492967a341c5d01e9e5068ed8 Author: Keith Packard Date: Fri May 6 17:10:14 2016 -0700 @@ -1548,15 +3635,8 @@ Date: Fri May 6 17:10:14 2016 -0700 Signed-off-by: Keith Packard -commit ac7be4a40df88ee3a0992e041635e4ac4cf5ac48 -Merge: b53c78e ce4c8a8 -Author: Bdale Garbee -Date: Fri May 6 17:59:39 2016 -0600 - - Merge branch 'master' into branch-1.6 - commit ce4c8a8ad57515e851207b0a82f3af791bb30d3e -Merge: aa9630c 320e312 +Merge: aa9630c3 320e312d Author: Bdale Garbee Date: Fri May 6 17:49:30 2016 -0600 @@ -2798,51 +4878,18 @@ Date: Sun Jan 10 21:39:38 2016 -0800 Signed-off-by: Keith Packard -commit b53c78e75879d647935a30acb88fdd69467617a7 -Merge: a2ea621 64adfbb -Author: Bdale Garbee -Date: Sun Jan 10 19:15:16 2016 -0700 - - Merge branch 'master' into branch-1.6 - commit 64adfbbb80c90dfe244179d81beaef8a84ed8bd6 Author: Bdale Garbee Date: Thu Jul 16 14:47:10 2015 -0600 process updates from 1.6.1 release -commit a2ea621eac3263348aff50885c79296f8ece26ed -Author: Bdale Garbee -Date: Sun Jan 10 19:08:12 2016 -0700 - - update Changelog from git log - -commit 1681776abc0873bcbbbc5b2b17e15d54a1031f51 -Merge: 8830926 aebdcaf -Author: Bdale Garbee -Date: Sun Jan 10 19:07:49 2016 -0700 - - Merge branch 'master' into branch-1.6 - commit aebdcaf37eafbc13cce695fe65a455e49c6108c3 Author: Bdale Garbee Date: Sun Jan 10 19:06:19 2016 -0700 one more time, with feeling .. this time, I've updated pdclib -commit 88309264656220bae6ee941211f7aa1b1dc19944 -Author: Bdale Garbee -Date: Sun Jan 10 19:06:19 2016 -0700 - - one more time, with feeling .. this time, I've updated pdclib - -commit 70e9064ca962dfd345f8a342afa130f969606553 -Merge: 489d22f 73ce3f7 -Author: Bdale Garbee -Date: Sun Jan 10 19:04:49 2016 -0700 - - Merge branch 'master' into branch-1.6 - commit 73ce3f73526edfabccd3b98e6e67de6d82a84b63 Author: Bdale Garbee Date: Sun Jan 10 18:58:31 2016 -0700 @@ -2850,7 +4897,7 @@ Date: Sun Jan 10 18:58:31 2016 -0700 submodule madness commit cbec66452ecd01bbd5aebf6f98443d5e0540f5d2 -Merge: 4043e07 81b8f4d +Merge: 4043e070 81b8f4da Author: Bdale Garbee Date: Sun Jan 10 18:29:07 2016 -0700 @@ -2903,7 +4950,7 @@ Date: Sun Jan 10 17:45:45 2016 -0700 modify release procedure to reflect Keith setting version in confgure.ac commit 2f35e0ba52f538ea1061bfff5bbd772b8a241386 -Merge: 86ccbac 3fdaf74 +Merge: 86ccbac1 3fdaf745 Author: Bdale Garbee Date: Sun Jan 10 17:44:03 2016 -0700 @@ -3475,7 +5522,7 @@ Date: Sat Sep 12 19:20:49 2015 -0700 Signed-off-by: Keith Packard commit 7064bc685aebeef07711e525dea4d5fbe33d235b -Merge: ea1d241 dda3f45 +Merge: ea1d2415 dda3f459 Author: Bdale Garbee Date: Tue Sep 29 00:46:42 2015 -0600 @@ -3585,13 +5632,6 @@ Date: Thu Aug 20 10:50:30 2015 -0700 Signed-off-by: Keith Packard -commit 489d22f448d9927533e90da4d16c5a332a234a8d -Merge: 570daac eaab49a -Author: Bdale Garbee -Date: Sun Aug 16 17:53:40 2015 +0200 - - Merge branch 'master' into branch-1.6 - commit eaab49ab1859ebe236a201f93b5352e67aa7ed2b Author: Bdale Garbee Date: Sun Aug 16 17:43:32 2015 +0200 @@ -3616,21 +5656,8 @@ Date: Tue Jul 28 01:34:25 2015 -0600 move turnon_teledongle to new cal-freq code -commit 570daace9caf7647a09c53d5c75593cc4c98b93b -Author: Bdale Garbee -Date: Thu Jul 16 13:36:13 2015 -0600 - - changelog for 1.6.1 release - -commit 6e9bb9178356620bd47d9f2e31abf42b7f1a8f11 -Merge: e2cefd8 87c8bb3 -Author: Bdale Garbee -Date: Thu Jul 16 13:31:42 2015 -0600 - - Merge branch 'master' into branch-1.6 - commit 87c8bb3956897830da1f7aaca2990a9571767b73 -Merge: 643c2fb d6445b3 +Merge: 643c2fb0 d6445b37 Author: Bdale Garbee Date: Thu Jul 16 07:54:35 2015 -0600 @@ -3647,7 +5674,7 @@ Date: Wed Jul 15 18:31:05 2015 -0700 Signed-off-by: Keith Packard commit 643c2fb03833d658320f476ef731bbb06fe3cc31 -Merge: e41786f 271f56a +Merge: e41786fb 271f56a4 Author: Bdale Garbee Date: Wed Jul 15 16:43:50 2015 -0600 @@ -4008,19 +6035,19 @@ Date: Tue Jun 23 21:39:09 2015 -0700 Pad - Reports igniter and GPS status changes + Reports igniter and GPS status changes Flight - Report flight state changes and max height after apogee - Report current speed, height and bearing/elevation/range once - every 10 seconds while the rocket is in motion. + Report flight state changes and max height after apogee + Report current speed, height and bearing/elevation/range once + every 10 seconds while the rocket is in motion. Recovery - Report distance and bearing when the location of either the - tracker or the receiver changes by more than 10m, but not more - than once every 10 seconds. + Report distance and bearing when the location of either the + tracker or the receiver changes by more than 10m, but not more + than once every 10 seconds. Signed-off-by: Keith Packard @@ -4367,7 +6394,7 @@ Date: Tue Jun 16 23:38:07 2015 -0700 Signed-off-by: Keith Packard commit c46c2c5767c6e909fa58587e6c864a4fbaa9fa20 -Merge: 39f4361 6cb7d76 +Merge: 39f43616 6cb7d76c Author: Robert Garbee Date: Sat Jun 13 17:40:59 2015 -0600 @@ -5321,7 +7348,7 @@ Date: Sat Feb 28 15:07:16 2015 -0800 Signed-off-by: Keith Packard commit 4af4e36cda96d053458eeb040e35886890917385 -Merge: 91b1a80 106b16b +Merge: 91b1a806 106b16b4 Author: Bdale Garbee Date: Sun Feb 22 14:55:40 2015 -0700 @@ -5525,12 +7552,6 @@ Date: Mon Feb 9 08:35:24 2015 -0600 Minor typo in man page -commit e2cefd8593d269ce603aaf33f4a53a5c2dcb3350 -Author: Bdale Garbee -Date: Sat Feb 7 22:36:22 2015 -0700 - - update ChangeLog for release - commit 26f61380ce6b4df80fa0b5a8a242cef79d5ae339 Author: Bdale Garbee Date: Sat Feb 7 22:23:38 2015 -0700 @@ -5914,7 +7935,7 @@ Date: Fri Jan 16 22:09:26 2015 +1300 Signed-off-by: Keith Packard Conflicts: - src/lpc/ao_usb_lpc.c + src/lpc/ao_usb_lpc.c commit 0671b3c8c24c9f33be77a10315c4669f33c516d7 Author: Keith Packard @@ -6379,7 +8400,7 @@ Date: Sat Dec 6 15:08:29 2014 -0800 Signed-off-by: Keith Packard commit 7339d2379713b5b7e4c4fe6bad89ed93f9d39e82 -Merge: d1f9121 b6462ca +Merge: d1f91215 b6462ca3 Author: Bdale Garbee Date: Sat Dec 6 15:39:53 2014 -0700 @@ -6907,11 +8928,11 @@ Date: Sat Oct 4 00:11:13 2014 -0700 This change also renames all of the imu values to make them easier to understand: - accel gyro axis + accel gyro axis - along roll length of the board - across pitch across the board - through yaw through the board. + along roll length of the board + across pitch across the board + through yaw through the board. Signed-off-by: Keith Packard @@ -7227,7 +9248,7 @@ Date: Wed Sep 10 00:26:10 2014 -0600 another build dep commit 615b69b19557a9683eeb0475b30a053a35ca51ac -Merge: a72b768 0365493 +Merge: a72b7683 03654934 Author: Bdale Garbee Date: Wed Sep 10 01:30:37 2014 -0600 @@ -7337,7 +9358,7 @@ Date: Sat Sep 6 22:56:25 2014 -0700 Signed-off-by: Keith Packard commit f0d2d34f84980ab45ecedae17546f4d71e020c5e -Merge: 8c212cd 6c812f1 +Merge: 8c212cd5 6c812f10 Author: Bdale Garbee Date: Sat Sep 6 23:42:47 2014 -0600 @@ -7404,14 +9425,14 @@ Date: Sat Sep 6 20:39:37 2014 -0700 Signed-off-by: Keith Packard commit 8c212cd5bfa03f71a31d84bd0051314e77d88461 -Merge: e9714e3 dd26ec2 +Merge: e9714e34 dd26ec2e Author: Bdale Garbee Date: Sat Sep 6 13:41:36 2014 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos Conflicts: - ao-bringup/turnon_telemega + ao-bringup/turnon_telemega commit e9714e34091abe657aa1b30aeda9466331aa39c1 Author: Bdale Garbee @@ -7851,7 +9872,7 @@ Date: Thu Aug 14 18:16:14 2014 -0600 change easymega from v0.1 to v1.0, tweak to build on master, add to Makefile commit 4828be0ca5252ac9cd6061209385dcd6c4c57965 -Merge: 17e894d 165b7dc +Merge: 17e894d1 165b7dcf Author: Bdale Garbee Date: Thu Aug 14 17:08:36 2014 -0600 @@ -8534,7 +10555,7 @@ Date: Tue Jun 24 21:22:26 2014 -0600 need the api key in Bdale's root too commit bd440afc2a6e37b74fffcf1b977e149485095316 -Merge: 5d4f912 a0ccab8 +Merge: 5d4f912b a0ccab8e Author: Bdale Garbee Date: Tue Jun 24 21:17:53 2014 -0600 @@ -8916,7 +10937,7 @@ Date: Sun Jun 15 17:40:27 2014 -0600 tweaks commit a6c61fb993d3fd15183f8755d9058f05c606c9c0 -Merge: 0634119 4384899 +Merge: 0634119d 43848991 Author: Keith Packard Date: Sun Jun 15 16:31:01 2014 -0700 @@ -11154,7 +13175,7 @@ Date: Tue May 13 17:30:47 2014 -0700 Signed-off-by: Keith Packard commit 8124af8c27b2b9e446aa3a4f1da83d4db7c1ea87 -Merge: 6dd7eae 3bcf4bd +Merge: 6dd7eae5 3bcf4bdd Author: Keith Packard Date: Mon May 12 23:21:55 2014 -0700 @@ -11894,7 +13915,7 @@ Date: Sun Feb 23 17:42:08 2014 -0800 Signed-off-by: Keith Packard commit 104b8bfc9b37fda175f2cb2a1e33601fbf6f48f6 -Merge: 403b95e 1edf7ef +Merge: 403b95ee 1edf7ef8 Author: Bdale Garbee Date: Thu Feb 20 13:23:52 2014 -0700 @@ -12035,7 +14056,7 @@ Date: Sun Feb 16 14:57:38 2014 -0800 Signed-off-by: Keith Packard commit 95f5a6ef52947088993d395874cf6aa502fd2503 -Merge: 135b6d4 de2a619 +Merge: 135b6d40 de2a6199 Author: Bdale Garbee Date: Sun Feb 16 15:53:35 2014 -0700 @@ -12547,7 +14568,7 @@ Date: Tue Jan 21 21:34:58 2014 -0800 Signed-off-by: Keith Packard commit 13cf4000bd53ac4af66231d56e24c9eb11178a5f -Merge: 7a8551f 99fedbf +Merge: 7a8551fe 99fedbf0 Author: Keith Packard Date: Tue Jan 21 20:59:06 2014 -0800 @@ -13049,7 +15070,7 @@ Date: Thu Dec 19 03:22:21 2013 -0700 updated notes from 1.3 release commit 27528961457865acc3a38b822268df6d7cb86cfd -Merge: 4006eff a31629d +Merge: 4006effc a31629df Author: Bdale Garbee Date: Thu Dec 19 02:00:10 2013 -0700 @@ -13152,7 +15173,7 @@ Date: Wed Dec 18 21:02:15 2013 -0800 Signed-off-by: Keith Packard commit 39cb8c2896317b7538353be979ac99baffc14489 -Merge: 2a6016c ee42796 +Merge: 2a6016cf ee427961 Author: Bdale Garbee Date: Wed Dec 18 21:53:52 2013 -0700 @@ -13204,7 +15225,7 @@ Date: Wed Dec 18 18:30:54 2013 -0700 update release docs to include option for submodules commit d9982c257463f23be940eea66bd4dc3aadff0043 -Merge: 1b97ed2 b63fc05 +Merge: 1b97ed2b b63fc054 Author: Bdale Garbee Date: Wed Dec 18 18:25:35 2013 -0700 @@ -13331,7 +15352,7 @@ Date: Wed Dec 18 11:25:05 2013 -0800 Signed-off-by: Keith Packard commit 6df58bb0115a8da13d35ab38861f6231bea7f2a7 -Merge: 4383baf 02195f2 +Merge: 4383bafc 02195f29 Author: Bdale Garbee Date: Wed Dec 18 12:19:31 2013 -0700 @@ -13538,14 +15559,14 @@ Date: Tue Dec 17 14:53:59 2013 -0700 further documentation tweaks commit 90c88bab305c43eb62f964fd3ff350b8b0b5320d -Merge: d5d6d10 dffbdd9 +Merge: d5d6d10c dffbdd93 Author: Bdale Garbee Date: Tue Dec 17 14:09:30 2013 -0700 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos Conflicts: - doc/altusmetrum.xsl + doc/altusmetrum.xsl commit d5d6d10ceb724081c7cf89a3885d7e6c3da14604 Author: Bdale Garbee @@ -14831,7 +16852,7 @@ Date: Tue Oct 8 09:39:29 2013 -0700 Signed-off-by: Keith Packard commit 488a527267decece48e6682e0e0c7fc29cbed329 -Merge: 6a1e398 f6661cc +Merge: 6a1e398e f6661cc0 Author: Keith Packard Date: Tue Oct 8 09:26:41 2013 -0700 @@ -14840,7 +16861,7 @@ Date: Tue Oct 8 09:26:41 2013 -0700 Signed-off-by: Keith Packard Conflicts: - configure.ac + configure.ac commit 6a1e398e590121458176758858bb4210f3eb5a55 Author: Keith Packard @@ -15223,7 +17244,7 @@ Date: Thu Sep 5 03:11:42 2013 +1200 Signed-off-by: Mike Beattie Conflicts: - altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java + altosdroid/src/org/altusmetrum/AltosDroid/AltosVoice.java commit ee14ad16c242e8bd7a9d33ebf569211d1490b8e1 Author: Mike Beattie @@ -15234,9 +17255,9 @@ Date: Tue Sep 3 15:10:23 2013 +1200 Signed-off-by: Mike Beattie Conflicts: - altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java - altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java - altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java + altosdroid/src/org/altusmetrum/AltosDroid/TabAscent.java + altosdroid/src/org/altusmetrum/AltosDroid/TabDescent.java + altosdroid/src/org/altusmetrum/AltosDroid/TabPad.java commit 5b976a6651f4eb05d30afc08b9e1f27c7e52ae00 Author: Keith Packard @@ -15397,7 +17418,7 @@ Date: Sat Aug 31 23:10:56 2013 -0500 Signed-off-by: Keith Packard commit 7ec1b97d278c7aec3199fb7270f0dcf9484c879f -Merge: 017ed54 4188153 +Merge: 017ed54f 41881535 Author: Keith Packard Date: Sat Aug 31 08:22:09 2013 -0500 @@ -15466,7 +17487,7 @@ Date: Tue Aug 27 21:28:07 2013 -0600 Signed-off-by: Keith Packard commit dcc51bb18985c24fa35bce0dd42ea3d847b960bf -Merge: 7c82acc a73b025 +Merge: 7c82acc1 a73b0251 Author: Keith Packard Date: Wed Aug 28 22:52:58 2013 -0600 @@ -15475,8 +17496,8 @@ Date: Wed Aug 28 22:52:58 2013 -0600 Signed-off-by: Keith Packard Conflicts: - src/core/ao_telemetry.c - src/core/ao_telemetry.h + src/core/ao_telemetry.c + src/core/ao_telemetry.h Added both Mini and Metrum telemetry defines @@ -15853,7 +17874,7 @@ Date: Sun Aug 25 22:22:55 2013 -0700 Signed-off-by: Keith Packard commit 203951f6e049ec7e95489849a2bfaa01aa19c0c9 -Merge: 4babe73 b363a62 +Merge: 4babe731 b363a628 Author: Keith Packard Date: Sun Aug 25 22:00:27 2013 -0700 @@ -16009,7 +18030,7 @@ Date: Sat Aug 17 17:35:08 2013 +0200 Signed-off-by: Keith Packard commit f0e126251360f050b7121f167771c057bda8747e -Merge: d95a2c5 4fe47ad +Merge: d95a2c5d 4fe47adc Author: Keith Packard Date: Sat Aug 17 17:33:31 2013 +0200 @@ -16026,7 +18047,7 @@ Date: Sat Aug 17 17:30:52 2013 +0200 Signed-off-by: Keith Packard commit 4ff54bb96f6c00c0c2c7dd32f81403bac331621a -Merge: fa0859a 01f8df0 +Merge: fa0859a5 01f8df08 Author: Keith Packard Date: Sat Aug 17 16:03:26 2013 +0200 @@ -16044,7 +18065,7 @@ Date: Sat Aug 17 16:01:44 2013 +0200 Signed-off-by: Keith Packard commit 01f8df088759ee7e6bc3900a013e0ea4fafaf984 -Merge: e2ebe60 15063cb +Merge: e2ebe60a 15063cbb Author: Bdale Garbee Date: Tue Jul 30 00:15:06 2013 -0600 @@ -16514,7 +18535,7 @@ Date: Tue May 21 11:30:44 2013 -0700 Signed-off-by: Keith Packard commit fd5567882b732f8947b44b217552077c82a3d28e -Merge: fd55c1f 57b4d82 +Merge: fd55c1fe 57b4d82d Author: Keith Packard Date: Tue May 21 11:16:54 2013 -0700 @@ -16558,7 +18579,7 @@ Date: Sun May 19 23:07:54 2013 -0700 Signed-off-by: Keith Packard commit 27e9b93f3d35890a49575b2ead1983ce3c2fc213 -Merge: a4df257 d9cbef8 +Merge: a4df2575 d9cbef8c Author: Keith Packard Date: Sun May 19 20:40:42 2013 -0700 @@ -17392,7 +19413,7 @@ Date: Fri May 10 19:21:18 2013 -0700 Signed-off-by: Keith Packard commit 106d212ff5920c39d95751ef6249dc141970412c -Merge: ecb1285 09d5d6f +Merge: ecb12857 09d5d6f5 Author: Keith Packard Date: Thu May 9 21:06:52 2013 -0700 @@ -18247,7 +20268,7 @@ Date: Thu May 2 23:14:02 2013 -0700 Signed-off-by: Keith Packard commit 7cce6c205e4595894e033ab8f0acc8064bf9f561 -Merge: 75f8229 5591509 +Merge: 75f8229d 55915098 Author: Bdale Garbee Date: Mon Apr 29 17:24:43 2013 -0600 @@ -18292,7 +20313,7 @@ Date: Sat Apr 27 00:36:11 2013 -0700 Signed-off-by: Keith Packard commit cef4e3ee95037050ae859fb2fdc0a57373764bd8 -Merge: fefc021 f3ee7de +Merge: fefc0210 f3ee7deb Author: Keith Packard Date: Thu Apr 25 22:22:50 2013 -0700 @@ -18465,7 +20486,7 @@ Date: Sun Apr 21 14:52:56 2013 +1200 Signed-off-by: Mike Beattie commit 49caac78786014d443d9c05f47b5eb3070ec9bd3 -Merge: 5b7bbf1 cbf38c5 +Merge: 5b7bbf18 cbf38c55 Author: Mike Beattie Date: Sun Apr 21 14:51:07 2013 +1200 @@ -18542,7 +20563,7 @@ Date: Sat Apr 20 12:22:38 2013 -0600 improve text in telebt turn-on script commit ff332e640b27c6be37dabef58ebac350ac2347b2 -Merge: b300060 87d6ed2 +Merge: b3000609 87d6ed24 Author: Keith Packard Date: Wed Apr 17 10:41:05 2013 -0700 @@ -18595,7 +20616,7 @@ Date: Tue Apr 16 14:22:23 2013 -0700 Signed-off-by: Keith Packard commit d5a557004c00d1ae25da04dc63c78b816562a236 -Merge: 6592a5b 5b04176 +Merge: 6592a5be 5b041769 Author: Keith Packard Date: Mon Apr 15 23:26:33 2013 -0700 @@ -18610,7 +20631,7 @@ Date: Mon Apr 15 23:25:55 2013 -0700 Signed-off-by: Keith Packard commit 6592a5be127a9c95d3b2e7d5aa6ffba71c6748b9 -Merge: c6f85cb eba3aa9 +Merge: c6f85cb1 eba3aa94 Author: Keith Packard Date: Mon Apr 15 23:19:44 2013 -0700 @@ -18630,7 +20651,7 @@ Date: Mon Apr 15 23:14:22 2013 -0700 Signed-off-by: Keith Packard commit c6f85cb149dff8732104521cb62b355e8a0d7148 -Merge: 3cd8ff1 58dd4b8 +Merge: 3cd8ff18 58dd4b88 Author: Keith Packard Date: Sun Apr 14 20:02:10 2013 -0700 @@ -18681,7 +20702,7 @@ Date: Sat Apr 13 11:39:14 2013 -0700 Signed-off-by: Keith Packard commit 2f7015afcca7c6042365d2124d3a5b7219e8e588 -Merge: 5077f3a 778daf0 +Merge: 5077f3ad 778daf0c Author: Keith Packard Date: Sat Apr 13 10:51:04 2013 -0700 @@ -18884,7 +20905,7 @@ Date: Mon Apr 8 17:42:18 2013 -0700 Signed-off-by: Keith Packard commit 6ba0df9b440b69bf5bc5f4e435b431adf303fee2 -Merge: 1d3ab47 28adf55 +Merge: 1d3ab47d 28adf554 Author: Bdale Garbee Date: Mon Apr 8 18:02:37 2013 -0600 @@ -19577,7 +21598,7 @@ Date: Mon Mar 11 18:16:55 2013 -0700 Signed-off-by: Keith Packard commit 90ee11542b111befa0e96e27292dc548e5c37396 -Merge: 97efce5 d7973de +Merge: 97efce5f d7973de3 Author: Keith Packard Date: Sun Mar 10 11:43:06 2013 -0700 @@ -19622,7 +21643,7 @@ Date: Sun Mar 10 20:40:13 2013 +1300 Signed-off-by: Mike Beattie commit 8adadf6bd2ba623642675e4beafac4ac98b1916d -Merge: d029aca 0c0c6d6 +Merge: d029acad 0c0c6d60 Author: Mike Beattie Date: Sun Mar 10 20:24:56 2013 +1300 @@ -19653,7 +21674,7 @@ Date: Sun Mar 10 20:22:09 2013 +1300 Signed-off-by: Mike Beattie commit d029acad6a992be9b7b4498e70605f8a1e1a4ef6 -Merge: eba7b2e 72c5b14 +Merge: eba7b2ef 72c5b142 Author: Mike Beattie Date: Sun Mar 10 19:07:01 2013 +1300 @@ -19698,7 +21719,7 @@ Date: Fri Mar 8 19:41:32 2013 +1300 Signed-off-by: Mike Beattie commit 84d35e4cbd7ea2f681c43496b9b9db84f9dd923f -Merge: 760b1f0 e0d9128 +Merge: 760b1f02 e0d9128b Author: Keith Packard Date: Thu Mar 7 13:00:44 2013 -0800 @@ -19848,7 +21869,7 @@ Date: Thu Mar 7 18:54:45 2013 +1300 Signed-off-by: Mike Beattie commit 760b1f02c178c600226f39b5e66d8cbadbf4a29b -Merge: afd2674 cbad587 +Merge: afd26742 cbad587b Author: Keith Packard Date: Wed Mar 6 21:53:22 2013 -0800 @@ -19972,7 +21993,7 @@ Date: Sun Feb 24 01:20:16 2013 -0800 Signed-off-by: Keith Packard commit 2120d362cefceba69e75996b6391d9558978c01d -Merge: 5246acb a04c4f7 +Merge: 5246acb7 a04c4f7b Author: Keith Packard Date: Sun Feb 24 00:20:54 2013 -0800 @@ -20155,7 +22176,7 @@ Date: Sun Feb 10 11:58:36 2013 -0800 Signed-off-by: Keith Packard commit bf88c5f829ea5d32043431945e862a9f6c96740a -Merge: 3227029 d05a779 +Merge: 32270296 d05a7799 Author: Keith Packard Date: Sun Feb 10 01:21:52 2013 -0800 @@ -20493,7 +22514,7 @@ Date: Wed Jan 16 22:05:32 2013 -0800 Signed-off-by: Keith Packard commit a04c4f7b07e97d568f8f6f56dd363329817fb52c -Merge: 0c2fa96 bd84dfd +Merge: 0c2fa961 bd84dfd8 Author: Keith Packard Date: Wed Jan 16 15:22:46 2013 -0800 @@ -20545,8 +22566,8 @@ Date: Wed Jan 16 15:01:12 2013 -0800 The correct matrix is seen in this paper: On Reduced-Order Kalman Filters For GPS Position Filtering - J. Shima - 6/2/2001 + J. Shima + 6/2/2001 This references an older paper which is supposed to describe the derivation of the matrix: @@ -20561,14 +22582,14 @@ Date: Wed Jan 16 15:01:12 2013 -0800 Signed-off-by: Keith Packard commit 0c2fa9614ffe22901ba0fd089e1e02c362f9fbe0 -Merge: 456120d f2b59cf +Merge: 456120d2 f2b59cf3 Author: Keith Packard Date: Wed Jan 16 10:40:28 2013 -0800 Merge remote-tracking branch 'origin/telescience-v0.2' into telescience-v0.2 commit 456120d201d72c89576a0c8d69b2fcba44169507 -Merge: f24c421 994ff76 +Merge: f24c4219 994ff76a Author: Keith Packard Date: Wed Jan 16 10:39:40 2013 -0800 @@ -20660,7 +22681,7 @@ Date: Sat Jan 12 20:11:38 2013 -0800 Signed-off-by: Keith Packard commit 670034eef48d63cdaec8d271fa93da984ffe2ea9 -Merge: 8c5ebaf d374d6b +Merge: 8c5ebaf8 d374d6be Author: Bdale Garbee Date: Sat Jan 12 10:57:22 2013 -0700 @@ -20765,7 +22786,7 @@ Date: Thu Jan 10 21:26:20 2013 -0800 Signed-off-by: Keith Packard commit 1ed6b13e87c1cc2d6618b6ba3a293ea6e3b5752e -Merge: acff2f4 d409417 +Merge: acff2f46 d409417f Author: Keith Packard Date: Thu Jan 10 21:48:12 2013 -0800 @@ -20810,7 +22831,7 @@ Date: Wed Jan 9 15:23:46 2013 -0800 Signed-off-by: Keith Packard commit 8c5ebaf88b459b09924753a8077393a7b0639133 -Merge: 59f355f d7d259c +Merge: 59f355f5 d7d259c7 Author: Bdale Garbee Date: Tue Jan 8 22:12:17 2013 -0700 @@ -21147,7 +23168,7 @@ Date: Tue Jan 1 15:30:11 2013 -0800 Signed-off-by: Keith Packard commit 65b512c890a3ccf487655b79305ab1cfcf49259c -Merge: 434e946 d7d259c +Merge: 434e946a d7d259c7 Author: Keith Packard Date: Mon Dec 31 14:24:59 2012 -0800 @@ -21217,14 +23238,14 @@ Date: Fri Dec 28 23:05:31 2012 -0700 Signed-off-by: Keith Packard commit f7a56152808c7838c1886884bb77de2705ab076c -Merge: daf8776 b70ca5e +Merge: daf8776f b70ca5ea Author: Keith Packard Date: Fri Dec 28 21:50:13 2012 -0800 Merge remote-tracking branch 'origin/master' into micropeak-logging commit 59f355f5288b42b2e47743d06e41e55819a55f64 -Merge: 099d2b0 b70ca5e +Merge: 099d2b0e b70ca5ea Author: Bdale Garbee Date: Fri Dec 28 22:30:26 2012 -0700 @@ -21286,7 +23307,7 @@ Date: Tue Dec 25 14:23:29 2012 -0800 Signed-off-by: Keith Packard commit 868ef0c9c4b208c02a87180b0eede329369bdc77 -Merge: 669cde8 57487e7 +Merge: 669cde8a 57487e78 Author: Keith Packard Date: Tue Dec 25 14:20:42 2012 -0800 @@ -21380,7 +23401,7 @@ Date: Sun Dec 16 16:08:33 2012 -0800 Signed-off-by: Keith Packard commit dfff41c2bec16fe4c7b198a4720eb40d8e740ac4 -Merge: 22a58b0 00bc1a0 +Merge: 22a58b0f 00bc1a09 Author: Keith Packard Date: Sun Dec 16 16:06:41 2012 -0800 @@ -21468,7 +23489,7 @@ Date: Sat Dec 15 14:47:22 2012 -0800 Signed-off-by: Keith Packard commit 6fa1ec0dbf2a4eda8d061c67b3779b83b88f29f0 -Merge: f140931 73422bf +Merge: f1409311 73422bf7 Author: Keith Packard Date: Fri Dec 14 19:29:50 2012 -0800 @@ -21522,7 +23543,7 @@ Date: Wed Dec 12 22:53:36 2012 -0800 Signed-off-by: Keith Packard commit 688a9458bb03a81e71554c14295d1baacbbbd530 -Merge: 816c6b5 c8866fb +Merge: 816c6b5d c8866fba Author: Keith Packard Date: Wed Dec 12 22:36:59 2012 -0800 @@ -21537,7 +23558,7 @@ Date: Wed Dec 12 22:35:05 2012 -0800 Signed-off-by: Keith Packard commit 816c6b5d087694a9db9c34cc5ec7671a1487d9b9 -Merge: a4a8418 a4678cd +Merge: a4a84182 a4678cd8 Author: Keith Packard Date: Wed Dec 12 11:10:14 2012 -0800 @@ -21577,7 +23598,7 @@ Date: Tue Dec 11 23:43:30 2012 -0800 Signed-off-by: Keith Packard commit a4a841828924ee37f5201d4ff0aec38459f2d802 -Merge: b26e837 d309fcf +Merge: b26e837a d309fcff Author: Keith Packard Date: Tue Dec 11 14:42:43 2012 -0800 @@ -21595,7 +23616,7 @@ Date: Tue Dec 11 14:41:53 2012 -0800 Signed-off-by: Keith Packard commit b26e837a6f18641aae9372aab22168849ff10812 -Merge: 1489c7f c233ef6 +Merge: 1489c7f7 c233ef67 Author: Keith Packard Date: Sun Dec 9 18:33:31 2012 -0800 @@ -21662,7 +23683,7 @@ Date: Fri Dec 7 17:35:15 2012 -0800 Signed-off-by: Keith Packard commit bd05421991b596fe9cf73ee25c9046b0fb4e32f7 -Merge: 1f79706 1489c7f +Merge: 1f797066 1489c7f7 Author: Keith Packard Date: Fri Dec 7 17:34:10 2012 -0800 @@ -21714,7 +23735,7 @@ Date: Fri Dec 7 10:15:25 2012 -0800 Signed-off-by: Keith Packard commit 748e42ebf1dfb1efd5dec6ddd93f5c7aeedeb01d -Merge: 75912f8 c10f9a4 +Merge: 75912f8a c10f9a43 Author: Keith Packard Date: Fri Dec 7 10:14:11 2012 -0800 @@ -21969,7 +23990,7 @@ Date: Wed Dec 5 09:59:16 2012 -0800 reporting. We're going to appropriate the code for use in Mega Metrum to (optionally) broadcast APRS packets. - http://ad7zj.net/kd7lmo/aprsbeacon_code.html + http://ad7zj.net/kd7lmo/aprsbeacon_code.html Signed-off-by: Keith Packard ( @@ -22166,7 +24187,7 @@ Date: Thu Nov 29 20:36:51 2012 -0800 Signed-off-by: Keith Packard commit ceea0e75ac42acac4a20bf88f34bb93fd2768f4c -Merge: 7738ddc 285fccf +Merge: 7738ddc5 285fccfa Author: Bdale Garbee Date: Tue Nov 20 12:37:38 2012 -0700 @@ -22442,7 +24463,7 @@ Date: Mon Oct 29 11:43:02 2012 -0700 Signed-off-by: Keith Packard commit a46c9398a5f02ff4b52b7a4309a51498560cadb5 -Merge: e57ab2a 56023cf +Merge: e57ab2a7 56023cf5 Author: Keith Packard Date: Fri Oct 26 14:08:32 2012 -0700 @@ -22537,7 +24558,7 @@ Date: Thu Oct 25 00:12:57 2012 -0700 Signed-off-by: Keith Packard commit 282f0451dd141db3304ab73e4020a849e59721eb -Merge: 0680d62 78e1de4 +Merge: 0680d62d 78e1de48 Author: Keith Packard Date: Thu Oct 25 00:09:01 2012 -0700 @@ -22665,7 +24686,7 @@ Date: Wed Oct 24 20:52:09 2012 +1300 Signed-off-by: Mike Beattie commit 055f3232decc07e064d596469b81cf9869411c2d -Merge: 8ca58e2 9e60fa2 +Merge: 8ca58e20 9e60fa21 Author: Bdale Garbee Date: Tue Oct 23 09:38:36 2012 -0600 @@ -22693,7 +24714,7 @@ Date: Tue Oct 23 19:22:52 2012 +1300 Signed-off-by: Mike Beattie commit 9e60fa214ad2c48fbe8f7e5c437681aa35d249fa -Merge: 27c3157 4b41561 +Merge: 27c31572 4b41561a Author: Keith Packard Date: Mon Oct 22 22:39:31 2012 -0700 @@ -22925,7 +24946,7 @@ Date: Sun Oct 21 13:01:03 2012 -0700 Signed-off-by: Keith Packard commit 7f664da148ae15d46d179d8ecede6fc0bc710ffb -Merge: 3aba5eb 23b0c2f +Merge: 3aba5eb5 23b0c2fe Author: Keith Packard Date: Thu Oct 18 16:49:28 2012 -0700 @@ -22963,7 +24984,7 @@ Date: Thu Oct 18 15:34:41 2012 -0700 Signed-off-by: Keith Packard commit 5a55501660ebab3b858a48483c5df1cfb4e858e4 -Merge: 0361235 440365b +Merge: 0361235c 440365bd Author: Keith Packard Date: Thu Oct 18 15:18:52 2012 -0700 @@ -23530,7 +25551,7 @@ Date: Sat Oct 6 17:05:59 2012 -0700 Signed-off-by: Keith Packard commit 82fdc42d61340e6b76580ff12a9e1bea59eb8079 -Merge: 6b8881a 2cac8c5 +Merge: 6b8881a7 2cac8c57 Author: Keith Packard Date: Wed Oct 3 10:44:28 2012 -0700 @@ -23589,21 +25610,21 @@ Date: Thu Sep 20 11:33:24 2012 +0200 Signed-off-by: Keith Packard commit 2f2734bb418f5c3a89fa3f1bf1b98ce4cfe432e1 -Merge: e69a433 3fe5c2f +Merge: e69a433f 3fe5c2f9 Author: Keith Packard Date: Thu Sep 20 11:30:19 2012 +0200 Merge remote-tracking branch 'mjb/altosdroid' commit e69a433fd93b9f6bd2297d8045eb075fee29e73b -Merge: 19243ec 6e0d672 +Merge: 19243ecc 6e0d672b Author: Keith Packard Date: Thu Sep 20 11:30:11 2012 +0200 Merge remote-tracking branch 'mjb/prefs_interface' commit 19243ecc9b5bbdcc069ae24acf1ca807322c84d8 -Merge: 90c1b6d 0ef8b71 +Merge: 90c1b6db 0ef8b714 Author: Keith Packard Date: Thu Sep 20 11:29:55 2012 +0200 @@ -23691,7 +25712,7 @@ Date: Mon Sep 17 01:29:33 2012 +1200 Signed-off-by: Mike Beattie commit 52d3cad4f744140e1aa06fdfc0d49a0cf8734fd4 -Merge: 31f5a02 6e0d672 +Merge: 31f5a026 6e0d672b Author: Mike Beattie Date: Sun Sep 16 22:27:04 2012 +1200 @@ -23946,7 +25967,7 @@ Date: Thu Sep 13 15:12:33 2012 -0700 Signed-off-by: Keith Packard commit 320d90c376dccfe1599505e3b485df8d46e34bb3 -Merge: 9a7d643 2e6c6a6 +Merge: 9a7d6431 2e6c6a6c Author: Bdale Garbee Date: Thu Sep 13 15:36:37 2012 -0600 @@ -23963,7 +25984,7 @@ Date: Thu Sep 13 00:35:27 2012 -0700 Signed-off-by: Keith Packard commit 9a7d6431777ce3377b788ddac6cb9fadd53c039c -Merge: 2439f53 9728b20 +Merge: 2439f53e 9728b20a Author: Bdale Garbee Date: Thu Sep 13 00:58:30 2012 -0600 @@ -24020,7 +26041,7 @@ Date: Wed Sep 12 19:50:07 2012 -0600 update Releasing for non-native versioning and builds on debian branch commit fe009534ce6846b6db96cac8f6c2d53ba8010d91 -Merge: 69d42b2 8ee29fe +Merge: 69d42b26 8ee29fe4 Author: Bdale Garbee Date: Wed Sep 12 19:49:51 2012 -0600 @@ -24108,7 +26129,7 @@ Date: Tue Sep 11 23:36:26 2012 -0700 Signed-off-by: Keith Packard commit 69d42b26223b45df4167aa3baafba100ad71baab -Merge: 3e9078c 3fa5fbd +Merge: 3e9078cb 3fa5fbdf Author: Bdale Garbee Date: Wed Sep 12 00:26:21 2012 -0600 @@ -24145,7 +26166,7 @@ Date: Tue Sep 11 22:17:22 2012 -0600 releasing 1.1 commit 4563624638884b7b2f16cd4d396c00690e045999 -Merge: 11fbcf5 e5a55db +Merge: 11fbcf5e e5a55dbf Author: Tom Marble Date: Tue Sep 11 22:50:18 2012 -0500 @@ -24203,7 +26224,7 @@ Date: Tue Sep 11 12:44:24 2012 -0500 Add appropriate Java build deps as given from autoconf commit 8e506274a35eccacd2d4523faa08d279a201753f -Merge: 0bc3ed5 1fc97dd +Merge: 0bc3ed53 1fc97dd9 Author: Tom Marble Date: Tue Sep 11 11:39:22 2012 -0500 @@ -24216,7 +26237,7 @@ Date: Tue Sep 11 11:37:14 2012 -0500 Use explicit build deps for altosui (avoids * wildcarding) commit 1fc97dd9875a7639533a34438c4c7c999412eb3a -Merge: 8397d2b 4420d4a +Merge: 8397d2b0 4420d4a9 Author: Bdale Garbee Date: Tue Sep 11 10:35:04 2012 -0600 @@ -24382,7 +26403,7 @@ Date: Sun Sep 9 13:09:27 2012 -0700 Signed-off-by: Keith Packard commit e2b458a448106ba1ab207f0ea6824b56927d8547 -Merge: 9682e9e 3fe9322 +Merge: 9682e9e6 3fe93220 Author: Keith Packard Date: Sun Sep 9 13:03:47 2012 -0700 @@ -24562,7 +26583,7 @@ Date: Sat Sep 1 00:14:27 2012 -0500 This reverts commit ada6f2dfc045e77cb9499f20cdec1b4a54ef0db1. commit ec9e1186dce079a2f2b7be8050216ddb1bc1af66 -Merge: 503eabd 6d31f8d +Merge: 503eabd0 6d31f8d1 Author: Keith Packard Date: Fri Aug 31 22:24:16 2012 -0500 @@ -24669,7 +26690,7 @@ Date: Thu Aug 30 16:28:53 2012 -0500 Signed-off-by: Keith Packard commit b635cb26ba54c8f5c6a958e0ab0bc4d34d33b635 -Merge: 354c1fe a8ecf3a +Merge: 354c1fed a8ecf3aa Author: Keith Packard Date: Thu Aug 30 16:24:38 2012 -0500 @@ -24773,7 +26794,7 @@ Date: Thu Aug 30 13:13:20 2012 +1200 Signed-off-by: Mike Beattie commit 583458772746317b98fced907ec780edff465888 -Merge: aea10c1 17b6ffb +Merge: aea10c10 17b6ffb6 Author: Keith Packard Date: Wed Aug 29 11:29:24 2012 -0700 @@ -24994,14 +27015,14 @@ Date: Mon Aug 27 22:45:20 2012 -0700 Signed-off-by: Keith Packard commit 5ed88fb72c3e3ecf3333c700d838667db71cfbdc -Merge: adbe64c 621d093 +Merge: adbe64c5 621d0930 Author: Bdale Garbee Date: Tue Aug 28 23:39:53 2012 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos Conflicts: - debian/control + debian/control commit adbe64c5a9402b7c5075a444a12629131b663877 Author: Bdale Garbee @@ -25967,21 +27988,21 @@ Date: Wed Aug 8 07:07:49 2012 +1200 Signed-off-by: Mike Beattie commit 9456332fc16269270a2e9b7ef0b54523800cfe27 -Merge: bd02349 4d4ad34 +Merge: bd023491 4d4ad34a Author: Mike Beattie Date: Wed Aug 8 06:49:15 2012 +1200 Merge branch 'master' of git://git.gag.com/fw/altos commit 4d4ad34aec0c75c66162b992f1e52947e4685730 -Merge: c7f2285 8e4ebd1 +Merge: c7f22850 8e4ebd1f Author: Keith Packard Date: Tue Aug 7 11:48:20 2012 -0700 Merge remote-tracking branch 'mjb/master' commit bd02349111ae0f39b320e6a10a330051ddc39fdf -Merge: 8e4ebd1 c7f2285 +Merge: 8e4ebd1f c7f22850 Author: Mike Beattie Date: Wed Aug 8 06:46:56 2012 +1200 @@ -26168,7 +28189,7 @@ Date: Thu Aug 2 21:20:23 2012 +1200 Signed-off-by: Mike Beattie commit 7481d06bebc2dc1473f451971d8b744c9da4e726 -Merge: 599e28b c56dead +Merge: 599e28b2 c56dead7 Author: Mike Beattie Date: Thu Aug 2 21:18:15 2012 +1200 @@ -26325,7 +28346,7 @@ Date: Wed Jul 18 18:41:00 2012 -0600 telescience: correctly calculating rate values with higher resolution commit e2b472bbb2418fc13be42dbc7c52beb88479c46d -Merge: 75d6aa6 b242f27 +Merge: 75d6aa6f b242f275 Author: Robert Garbee Date: Wed Jul 18 14:25:27 2012 -0600 @@ -28631,7 +30652,7 @@ Date: Mon May 7 23:14:14 2012 -0700 Signed-off-by: Keith Packard commit 6a973f788563ccc66b01cc7557a004dabef18d09 -Merge: d387f24 da2c920 +Merge: d387f246 da2c920b Author: Bdale Garbee Date: Wed May 16 09:13:53 2012 -0600 @@ -30956,34 +32977,34 @@ Date: Fri Oct 7 09:53:09 2011 -0600 Conflicts: - src/Makefile.proto - src/cc1111/ao_adc.c - src/cc1111/ao_packet_master.c - src/core/ao.h + src/Makefile.proto + src/cc1111/ao_adc.c + src/cc1111/ao_packet_master.c + src/core/ao.h Fix up the new makefiles commit 128bbfa150f88c09f7adde2434b7bf0b5a9ed556 -Merge: f6f54d7 246864b +Merge: f6f54d70 246864b0 Author: Keith Packard Date: Fri Oct 7 08:41:56 2011 -0600 Merge remote-tracking branch 'origin/simple-quiet' into multiarch Conflicts: - configure.ac + configure.ac fix version number commit f6f54d70b768dca1715ddddea64a4df00d82b09e -Merge: 1c344b7 0d10e25 +Merge: 1c344b76 0d10e257 Author: Keith Packard Date: Fri Oct 7 08:40:14 2011 -0600 Merge remote-tracking branch 'uniarch/master' into multiarch Conflicts: - src/core/ao_cmd.c + src/core/ao_cmd.c Use ao_arch_reboot after waiting for a second @@ -31017,14 +33038,14 @@ Date: Mon Sep 26 11:50:28 2011 -0700 Signed-off-by: Keith Packard commit 1c344b760776cd5d8c0297d8db9bf02687381b4e -Merge: 4ed53ef fc4173f +Merge: 4ed53ef8 fc4173ff Author: Keith Packard Date: Fri Oct 7 08:34:59 2011 -0600 Merge remote-tracking branch 'origin/master' into multiarch Conflicts: - configure.ac + configure.ac Fix version number and location of ao.h header @@ -31035,7 +33056,7 @@ Date: Tue Sep 27 00:59:08 2011 -0600 add run-time dependency on libjfreechart-java commit 989aae5b18856e3420ea5b7a26ddd8dccae9d6d3 -Merge: 0552fbe e44f1ff +Merge: 0552fbed e44f1ffb Author: Bdale Garbee Date: Sat Sep 24 15:34:59 2011 -0600 @@ -31601,7 +33622,7 @@ Date: Fri Aug 26 09:41:46 2011 -0600 get ready for a 1.0.1 release commit 674231773256bacd7acb4b5718c47412e47b813f -Merge: 08e3d54 3bfe8df +Merge: 08e3d54b 3bfe8df4 Author: Bdale Garbee Date: Fri Aug 26 09:37:01 2011 -0600 @@ -31663,11 +33684,11 @@ Date: Thu Aug 25 20:43:44 2011 -0700 Split out sources into separate directories: - core: architecture and product independent bits - cc1111: cc1111-specific code - drivers: architecture independent drivers - product: product-specific sources and Makefile fragments - util: scripts for building stuff + core: architecture and product independent bits + cc1111: cc1111-specific code + drivers: architecture independent drivers + product: product-specific sources and Makefile fragments + util: scripts for building stuff This should have no effect on the built products, but testing is encouraged @@ -31761,14 +33782,14 @@ Date: Thu Aug 25 01:11:47 2011 -0600 prepare to release commit 73abe19acf709c00f5352ec12e8cd6edae1d1963 -Merge: 1bd781d 5158493 +Merge: 1bd781da 5158493c Author: Bdale Garbee Date: Thu Aug 25 00:34:49 2011 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos Conflicts: - doc/altusmetrum.xsl + doc/altusmetrum.xsl commit 1bd781da934c738e0c9294197c7eb622b0710a9a Author: Bdale Garbee @@ -31788,7 +33809,7 @@ Date: Wed Aug 24 23:21:02 2011 -0700 Signed-off-by: Keith Packard commit e268798dc260311f5f0167909481b41c9d27fc1c -Merge: 458f816 242344d +Merge: 458f816a 242344d3 Author: Keith Packard Date: Wed Aug 24 23:06:44 2011 -0700 @@ -31805,14 +33826,14 @@ Date: Wed Aug 24 23:06:01 2011 -0700 Signed-off-by: Keith Packard commit 242344d3e32e7c7cd9270d708555923fa888e4d8 -Merge: 5c1cf74 94a1b22 +Merge: 5c1cf749 94a1b220 Author: Bdale Garbee Date: Wed Aug 24 23:51:38 2011 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos Conflicts: - doc/altusmetrum.xsl + doc/altusmetrum.xsl commit 5c1cf7492b82e63a9db9d0238ecbcd2b59486893 Author: Bdale Garbee @@ -31829,7 +33850,7 @@ Date: Wed Aug 24 22:29:56 2011 -0700 Signed-off-by: Keith Packard commit edfb553bb4fa5b0c7c6c658505b2a99d05fb13bf -Merge: c74ab82 ec96f11 +Merge: c74ab82a ec96f116 Author: Bdale Garbee Date: Wed Aug 24 23:23:56 2011 -0600 @@ -31863,7 +33884,7 @@ Date: Wed Aug 24 22:18:29 2011 -0700 Signed-off-by: Keith Packard commit 50769fbbeaaf61111d363411e0ef0b2868681cf4 -Merge: 425fa99 d92c173 +Merge: 425fa995 d92c1736 Author: Bdale Garbee Date: Wed Aug 24 23:15:20 2011 -0600 @@ -31893,7 +33914,7 @@ Date: Wed Aug 24 23:03:23 2011 -0600 more tweaks commit 09981cd024297fd4ef093c7468de2b9d5f3c2691 -Merge: a476e76 03c8b27 +Merge: a476e766 03c8b270 Author: Bdale Garbee Date: Wed Aug 24 22:42:39 2011 -0600 @@ -31960,7 +33981,7 @@ Date: Wed Aug 24 21:39:21 2011 -0600 doc tweaks through chap 3 commit 3d88e0493ab446d7c7011786390d30618a72d045 -Merge: 02d6545 5a9972d +Merge: 02d65453 5a9972d4 Author: Bdale Garbee Date: Wed Aug 24 21:26:26 2011 -0600 @@ -32035,7 +34056,7 @@ Date: Wed Aug 24 01:41:53 2011 -0600 another test round commit 4d94e8f9f807a0bbeab0cdead011e74eeca1d1b6 -Merge: 4b5369d 3b0a9a1 +Merge: 4b5369dc 3b0a9a1c Author: Bdale Garbee Date: Wed Aug 24 01:38:58 2011 -0600 @@ -32287,7 +34308,7 @@ Date: Sun Aug 21 22:12:04 2011 -0700 Signed-off-by: Keith Packard commit a08826292ebd802a1ff2effccac3b96fd061c47d -Merge: 3366cfe 55be3db +Merge: 3366cfe6 55be3db2 Author: Bdale Garbee Date: Mon Aug 22 16:08:55 2011 -0600 @@ -32805,7 +34826,7 @@ Date: Wed Aug 10 15:00:44 2011 -0700 The official URL is now: - http://www.altusmetrum.org/AltOS/launch-sites.txt + http://www.altusmetrum.org/AltOS/launch-sites.txt Signed-off-by: Keith Packard @@ -33361,7 +35382,7 @@ Date: Sun Jul 17 11:25:47 2011 -0700 Signed-off-by: Keith Packard commit f7cd8317bf78ece334e1ceb0263b875ca43bbbd2 -Merge: 51796e2 a482d90 +Merge: 51796e2f a482d904 Author: Keith Packard Date: Sun Jul 17 08:17:44 2011 -0700 @@ -33419,7 +35440,7 @@ Date: Sat Jul 16 22:34:44 2011 -0700 Signed-off-by: Keith Packard commit abb8510b97ce9cbbff0275cc31f74780fe1ce138 -Merge: 0929ee3 00e6981 +Merge: 0929ee32 00e6981c Author: Keith Packard Date: Sat Jul 16 21:06:37 2011 -0700 @@ -34285,7 +36306,7 @@ Date: Tue Apr 19 15:29:39 2011 -0700 Signed-off-by: Keith Packard commit 44fb71ca3e5bccd5f601fc5a2d5da7292050b1d6 -Merge: 2ebdb88 c269e26 +Merge: 2ebdb888 c269e263 Author: Keith Packard Date: Tue Apr 19 14:06:39 2011 -0700 @@ -34494,7 +36515,7 @@ Date: Thu Apr 7 22:00:38 2011 -0700 Signed-off-by: Keith Packard commit f28efe271f9670473249574f6bcf6e160fe58c7b -Merge: 8db5c52 835ab3a +Merge: 8db5c52f 835ab3a8 Author: Keith Packard Date: Fri Apr 1 19:35:22 2011 -0700 @@ -35286,7 +37307,7 @@ Date: Fri Mar 18 20:26:12 2011 -0700 Signed-off-by: Keith Packard commit 5db94e1e230bade966a997aa83165405a9ec9d83 -Merge: 1a8f45e cbb968f +Merge: 1a8f45e7 cbb968f5 Author: Bdale Garbee Date: Fri Mar 18 21:12:39 2011 -0600 @@ -35793,7 +37814,7 @@ Date: Tue Jan 18 17:27:11 2011 -0700 update changelogs for Debian build commit da42f406e88ccc821cd45d5a94d5afec65ec50e9 -Merge: ea4cdfb cf550f9 +Merge: ea4cdfb8 cf550f9b Author: Bdale Garbee Date: Mon Jan 17 09:50:17 2011 -0700 @@ -36790,14 +38811,14 @@ Date: Wed Nov 24 21:39:18 2010 -0800 Signed-off-by: Keith Packard commit 51c7741040d95c5deece939dae5e4136cc04afc4 -Merge: d1dbe3b 4e47c44 +Merge: d1dbe3b6 4e47c44d Author: Keith Packard Date: Wed Nov 24 21:00:52 2010 -0800 Merge branch 'buttonbox' Conflicts: - doc/telemetrum-doc.xsl + doc/telemetrum-doc.xsl Pull the buttbox version of the docs in as it had been updated. @@ -36822,7 +38843,7 @@ Date: Wed Nov 24 20:53:36 2010 -0700 fix missing section close in Site Map content commit db2b19b8f0d452d682d53c7ed0ff6e359b46efa0 -Merge: b372f3c 915f881 +Merge: b372f3c0 915f881d Author: Keith Packard Date: Wed Nov 24 18:57:35 2010 -0800 @@ -36843,7 +38864,7 @@ Date: Thu Nov 25 09:52:30 2010 +1000 doc: Document altosui "Site Map" tab commit f01096c4b42f9a4720ed0414826c2a283a992545 -Merge: 357826a 3fbefb3 +Merge: 357826aa 3fbefb3e Author: Anthony Towns Date: Thu Nov 25 09:10:50 2010 +1000 @@ -36864,7 +38885,7 @@ Date: Thu Nov 25 09:07:34 2010 +1000 docs: Document altosui "Graph Data" button commit 7811e6dfa6caf10251da7df7c24b98cdc3787892 -Merge: 71b1949 7a50837 +Merge: 71b1949e 7a50837e Author: Anthony Towns Date: Thu Nov 25 08:47:36 2010 +1000 @@ -36966,7 +38987,7 @@ Date: Tue Nov 23 18:56:46 2010 -0800 Signed-off-by: Keith Packard commit 71b1949e50f4533bcf44537da65b19bc67863c8e -Merge: a79225c f1892b1 +Merge: a79225c2 f1892b13 Author: Anthony Towns Date: Wed Nov 24 12:14:11 2010 +1000 @@ -36980,7 +39001,7 @@ Date: Tue Nov 23 18:58:11 2010 -0700 while before I tackle that, if ever. commit a79225c215f17fa5218ddd9db4fc3f5c563a9f74 -Merge: 84cd5d4 853b711 +Merge: 84cd5d42 853b7112 Author: Anthony Towns Date: Wed Nov 24 11:55:14 2010 +1000 @@ -37005,7 +39026,7 @@ Date: Wed Nov 24 02:11:36 2010 +1000 altosui: don't switch away from user selected tab commit ae55a107f12546dc65f04618c7abc17beb920d73 -Merge: d1005f6 737f2fd +Merge: d1005f68 737f2fdd Author: Anthony Towns Date: Wed Nov 24 01:53:46 2010 +1000 @@ -37026,14 +39047,14 @@ Date: Mon Nov 22 21:07:10 2010 -0700 add a rudimentary --help for command line use commit d1005f68376d695039c314b8d7a68bbf9acbca4f -Merge: 9a83e0d 22c0978 +Merge: 9a83e0dc 22c09781 Author: Anthony Towns Date: Tue Nov 23 10:14:55 2010 +1000 Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox commit 22c09781af1df4b38562b577e9926c23e4a397f2 -Merge: b27327a a79606a +Merge: b27327a0 a79606a6 Author: Keith Packard Date: Mon Nov 22 16:02:22 2010 -0800 @@ -37063,7 +39084,7 @@ Date: Mon Nov 22 15:53:27 2010 -0800 Signed-off-by: Keith Packard commit 9a83e0dc79f7a7467c7814d58daa2a2b89e50972 -Merge: 902735f a79606a +Merge: 902735ff a79606a6 Author: Anthony Towns Date: Tue Nov 23 08:07:04 2010 +1000 @@ -37104,7 +39125,7 @@ Date: Sun Nov 21 17:39:50 2010 +1000 AltosSiteMap: ensure buffer around active tile commit ec47bc93a487614714a752cb30ec9fe3d8f72929 -Merge: 0393830 e7954c8 +Merge: 0393830f e7954c82 Author: Anthony Towns Date: Sun Nov 21 16:08:37 2010 +1000 @@ -37162,14 +39183,14 @@ Date: Sun Nov 21 13:07:11 2010 +1000 AltosSiteMap: extend map if rocket goes far away commit 835b903727a2eabda8d9659cc46e53301f92897c -Merge: 440a0f3 8789135 +Merge: 440a0f3f 87891355 Author: Anthony Towns Date: Sun Nov 21 11:15:02 2010 +1000 Merge branch 'sitemap' into buttonbox Conflicts: - ao-tools/altosui/AltosSiteMap.java + ao-tools/altosui/AltosSiteMap.java commit 878913551a1e4e3c8f2b39fa4aeb234880735a1c Author: Anthony Towns @@ -37188,24 +39209,24 @@ Date: Sat Nov 20 16:55:12 2010 -0800 Signed-off-by: Keith Packard commit 2a7dc3ba36bac81640a9498e0d0caf1470b57c19 -Merge: e5b1ada ece2c86 +Merge: e5b1adae ece2c86e Author: Anthony Towns Date: Sun Nov 21 10:45:15 2010 +1000 Merge branch 'buttonbox' into sitemap Conflicts: - ao-tools/altosui/AltosFlightUI.java + ao-tools/altosui/AltosFlightUI.java commit 8df185cd95cfecbed8272dd1275d077c5b45535b -Merge: ece2c86 1e71264 +Merge: ece2c86e 1e712647 Author: Keith Packard Date: Sat Nov 20 16:35:48 2010 -0800 Merge remote branch 'aj/sitemap' into buttonbox Conflicts: - ao-tools/altosui/AltosFlightUI.java + ao-tools/altosui/AltosFlightUI.java Signed-off-by: Keith Packard @@ -37237,7 +39258,7 @@ Date: Sun Nov 21 08:58:44 2010 +1000 altosui: reindent commit a59a204e188e40ec8848a0dc63d6de710cee3039 -Merge: 8263630 37f0201 +Merge: 82636305 37f0201d Author: Anthony Towns Date: Sun Nov 21 08:56:13 2010 +1000 @@ -37315,14 +39336,14 @@ Date: Sat Nov 20 21:06:37 2010 +1000 AltosSiteMap: add autoscroll and grabndrag scroll commit 74cab8503b51ba6fb05a4d12a031c749e870b0ef -Merge: 0ecf033 9a99cab +Merge: 0ecf0331 9a99cabc Author: Anthony Towns Date: Sat Nov 20 18:20:45 2010 +1000 Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox commit 0ecf033110084f1a8be98282d7029dc14f70dab5 -Merge: 081fbd5 71c41ea +Merge: 081fbd57 71c41ead Author: Anthony Towns Date: Sat Nov 20 18:14:30 2010 +1000 @@ -37353,14 +39374,14 @@ Date: Sat Nov 20 00:09:03 2010 -0800 Signed-off-by: Keith Packard commit 081fbd5715f9d3d81d98e149fb95d40447c07a79 -Merge: 90b9bc4 7920ed5 +Merge: 90b9bc44 7920ed5c Author: Anthony Towns Date: Sat Nov 20 17:40:49 2010 +1000 Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox Conflicts: - ao-tools/altosui/AltosFlightUI.java + ao-tools/altosui/AltosFlightUI.java commit 7920ed5c34b088f45ce4213b061ddd1ffe22cee8 Author: Keith Packard @@ -37504,14 +39525,14 @@ Date: Fri Nov 19 12:09:46 2010 +1000 altosui: tile site maps commit 939be6793238a275b7682ecc376fed14379cf044 -Merge: e68fe94 1a4b6e9 +Merge: e68fe945 1a4b6e96 Author: Anthony Towns Date: Thu Nov 18 05:54:06 2010 +1000 Merge branch 'buttonbox' of git://git.gag.com/fw/altos into buttonbox Conflicts: - ao-tools/altosui/AltosFlightUI.java + ao-tools/altosui/AltosFlightUI.java commit 1a4b6e96f823035b113f01d1bdfd61afc1f33e25 Author: Keith Packard @@ -37654,7 +39675,7 @@ Date: Sun Nov 14 00:57:45 2010 +1000 AltosTelemetryReader: actually open serial port commit 9c32b93ef5fb43558fb0179ea1b047e35b7ed6e8 -Merge: 991541f a6f30fa +Merge: 991541f5 a6f30fae Author: Anthony Towns Date: Sun Nov 14 00:29:11 2010 +1000 @@ -37671,7 +39692,7 @@ Date: Fri Nov 12 17:02:22 2010 -0800 Signed-off-by: Keith Packard commit 1bdc6166f3bc5ce3f8e55acb1484923781412e21 -Merge: f111871 5c6a533 +Merge: f1118717 5c6a5335 Author: Bdale Garbee Date: Fri Nov 12 17:32:43 2010 -0700 @@ -37721,7 +39742,7 @@ Date: Fri Nov 12 02:07:41 2010 +1000 add site map tab, at least for QRS launches commit 5394548fa5c7bdbfcc01e8aa19e93e1cf6345e2a -Merge: 891e629 75f7698 +Merge: 891e629f 75f7698b Author: Keith Packard Date: Wed Nov 10 22:11:21 2010 -0800 @@ -37937,7 +39958,7 @@ Date: Tue Sep 28 17:56:49 2010 -0700 Signed-off-by: Keith Packard commit 5a119fd92532d53e552efe1f7c61e87181fcace0 -Merge: 28da340 82744c3 +Merge: 28da3406 82744c34 Author: Keith Packard Date: Mon Sep 27 22:28:07 2010 -0700 @@ -37966,7 +39987,7 @@ Date: Tue Sep 28 14:45:01 2010 +1000 Hax0r graphing to support telem/eeprom files commit e2b9f47a205348d38756c70e928a2a9183de6884 -Merge: 7ef3ad0 8032031 +Merge: 7ef3ad0c 80320319 Author: Anthony Towns Date: Tue Sep 28 12:55:47 2010 +1000 @@ -38014,7 +40035,7 @@ Date: Mon Sep 27 17:11:48 2010 -0700 Signed-off-by: Keith Packard commit 7ef3ad0c9354c0484c25badc69334b59c7f355e2 -Merge: eb74866 e66919a +Merge: eb74866e e66919aa Author: Anthony Towns Date: Fri Sep 24 10:28:06 2010 +1000 @@ -38053,7 +40074,7 @@ Date: Mon Aug 30 14:00:04 2010 -0700 Signed-off-by: Keith Packard commit eb74866e919e8c661153847871f5a79e66d37296 -Merge: af404b4 1260589 +Merge: af404b42 12605899 Author: Anthony Towns Date: Mon Sep 20 22:05:26 2010 +1000 @@ -38096,7 +40117,7 @@ Date: Wed Sep 15 06:51:05 2010 +1000 Add graphing. commit 3d64f5a6511529ca53699190f4d54de1ba62a9bd -Merge: ec6da08 b9623f8 +Merge: ec6da082 b9623f8e Author: Anthony Towns Date: Sat Sep 11 15:15:14 2010 +1000 @@ -38131,7 +40152,7 @@ Date: Fri Sep 10 10:42:35 2010 -0600 make the column headers comma separated, too, so they align with the data commit ec6da0824474e46de842845d7b53fe1a1dde33ed -Merge: 7c2e411 1031067 +Merge: 7c2e4114 10310672 Author: Anthony Towns Date: Fri Sep 10 16:11:34 2010 +1000 @@ -38194,7 +40215,7 @@ Date: Thu Sep 9 23:51:23 2010 -0600 rewind packaging changelog commit 7c2e4114a3a43f919a7a6c967d3f16e5d630f90f -Merge: ddc83b4 af200f5 +Merge: ddc83b4c af200f5b Author: Anthony Towns Date: Fri Sep 10 15:50:01 2010 +1000 @@ -38299,7 +40320,7 @@ Date: Thu Sep 9 20:06:09 2010 -0600 update changelogs for Debian build commit 0ea75761416bff299233991e961ba25b6c7dcf89 -Merge: 35d70c9 8ee3464 +Merge: 35d70c92 8ee3464d Author: Bdale Garbee Date: Thu Sep 9 20:05:27 2010 -0600 @@ -38412,7 +40433,7 @@ Date: Thu Sep 9 15:43:47 2010 -0600 update changelogs for Debian build commit ddc83b4c401be965a9947782becf20cc8c54e6a2 -Merge: afea6c2 3d49d5f +Merge: afea6c26 3d49d5f6 Author: Anthony Towns Date: Sun Sep 5 20:49:34 2010 +1000 @@ -39224,14 +41245,14 @@ Date: Fri Aug 27 12:41:26 2010 -0600 update changelogs for Debian build commit cf65c6b8056c4af7c26b52ec6f9fbd3400cef638 -Merge: 5f2f6a8 ae5eff7 +Merge: 5f2f6a8f ae5eff7b Author: Bdale Garbee Date: Fri Aug 27 12:38:25 2010 -0600 Merge branch 'bdale' Conflicts: - debian/control + debian/control commit ae5eff7bc0b63047737223423009707bedcb00f5 Author: Bdale Garbee @@ -39273,7 +41294,7 @@ Date: Fri Aug 27 12:04:13 2010 -0600 fix up the wrapper's path to the jar file commit 5f2f6a8f9ba56be867888758848bc7f152ccbd47 -Merge: 63bd34c 9d1b27f +Merge: 63bd34cd 9d1b27fa Author: Keith Packard Date: Fri Aug 27 11:00:31 2010 -0700 @@ -39312,7 +41333,7 @@ Date: Fri Aug 27 11:17:54 2010 -0600 add a dummy install target commit c443f43f8dee6e0fcbcecf9d09e948fd928b7af4 -Merge: 2950431 2923cf5 +Merge: 29504311 2923cf50 Author: Bdale Garbee Date: Fri Aug 27 03:08:53 2010 -0600 @@ -39537,7 +41558,7 @@ Date: Mon Aug 23 23:15:05 2010 -0700 Signed-off-by: Keith Packard commit afea6c264c5ebf12f1d629bd4bc724da86d11b7a -Merge: 0e17853 9d1b27f +Merge: 0e17853c 9d1b27fa Author: Anthony Towns Date: Tue Aug 24 00:02:31 2010 -0600 @@ -39555,7 +41576,7 @@ Date: Mon Aug 23 23:01:36 2010 -0700 Signed-off-by: Keith Packard commit 295043112ccde35092945c286596f9045ee6fa05 -Merge: 2007288 ef8376c +Merge: 2007288d ef8376c4 Author: Bdale Garbee Date: Mon Aug 23 23:11:22 2010 -0600 @@ -39957,7 +41978,7 @@ Date: Thu Jul 29 13:30:36 2010 -0600 update changelogs for Debian build commit 7877496d47ce6d25210c0e1c6500666dbfc0876c -Merge: c71061a 4cf39b1 +Merge: c71061a3 4cf39b13 Author: Keith Packard Date: Thu Jul 29 12:07:49 2010 -0700 @@ -40176,7 +42197,7 @@ Date: Wed Jul 28 15:41:34 2010 -0700 Signed-off-by: Keith Packard commit 8a6040e143ecc7830cc1c0114de85f3b72c067eb -Merge: 024d077 554a97e +Merge: 024d0773 554a97ef Author: Keith Packard Date: Wed Jul 28 13:29:51 2010 -0700 @@ -40220,7 +42241,7 @@ Date: Wed Jul 28 12:24:53 2010 -0700 Signed-off-by: Keith Packard commit 172a2817dde6718724f2b5fad5a7761801446fa0 -Merge: f2a006f 81bf204 +Merge: f2a006fd 81bf2042 Author: Keith Packard Date: Wed Jul 28 11:20:22 2010 -0700 @@ -40245,21 +42266,21 @@ Date: Wed Jul 28 09:31:09 2010 -0700 Here's what happens with the ao_gps_tracking_report and ao_log threads: - ao_gps_tracking_report ao_log + ao_gps_tracking_report ao_log Writes a bunch of records *blocks* in the eeprom flush - sets ao_log_data 'log' to global 'log' - computes checksum for 'log' block - *blocks* on ao_log_mutex + sets ao_log_data 'log' to global 'log' + computes checksum for 'log' block + *blocks* on ao_log_mutex Wakes up sets ao_log_data 'log' to 'gps_log' writes remaining records 'gps_log' is left with svid = 0 *blocks* on ao_gps_tracking_data - writes data, reading from - the current ao_log_data 'log' - pointer which points at 'gps_log' + writes data, reading from + the current ao_log_data 'log' + pointer which points at 'gps_log' Making ao_log_data re-entrant fixes this by ensuring that the 'ao_log' thread has its own copy of the ao_log_data 'log' parameter. @@ -40463,7 +42484,7 @@ Date: Tue Jul 20 22:08:56 2010 -0600 update changelogs for Debian build commit e747954b6a9e71705f619684df8a118a909b1039 -Merge: bd40a5b 695879d +Merge: bd40a5b4 695879db Author: Bdale Garbee Date: Tue Jul 20 22:07:22 2010 -0600 @@ -40534,14 +42555,14 @@ Date: Mon Jun 21 11:44:32 2010 -0700 ao-postflight: was walking off state.data array commit 11d155d558d0b121b66f089adee0a47d71f65a78 -Merge: 544003a 24393ea +Merge: 544003a8 24393eab Author: Keith Packard Date: Wed Jun 16 21:54:06 2010 -0700 Merge remote branch 'mjb/master' commit 544003a8da0248fd6f3c62ded86af74ab7cdadf6 -Merge: 267923e 93c1e29 +Merge: 267923e5 93c1e29b Author: Keith Packard Date: Wed Jun 16 21:52:23 2010 -0700 @@ -40615,7 +42636,7 @@ Date: Tue May 18 00:24:03 2010 -0600 merge the altusmetrum-themes package commit 0c6cf621dfd8339b8bc3915750a3147235f1331b -Merge: 32e430b 563a9dc +Merge: 32e430b8 563a9dcd Author: Bdale Garbee Date: Mon May 17 23:59:43 2010 -0600 @@ -40640,7 +42661,7 @@ Date: Mon May 17 21:30:57 2010 -0700 Signed-off-by: Keith Packard commit 69092ffd23ac1928d5c84413fd00c2423f313fc2 -Merge: 3c2211a cc002c0 +Merge: 3c2211ad cc002c0a Author: Bdale Garbee Date: Mon May 17 20:10:46 2010 -0600 @@ -40742,7 +42763,7 @@ Date: Thu May 6 12:48:00 2010 -0600 update changelogs for Debian build commit 314d27a73c903fef2968dabac3d5313573713460 -Merge: fa77db2 823fc0a +Merge: fa77db2f 823fc0ac Author: Bdale Garbee Date: Thu May 6 12:47:30 2010 -0600 @@ -40850,7 +42871,7 @@ Date: Tue Apr 27 00:18:43 2010 -0600 update changelogs for Debian build commit 99094f02bf4849ba1f6b9842ded6c39d894320f7 -Merge: 641e76c 75d8ffd +Merge: 641e76c5 75d8ffd4 Author: Bdale Garbee Date: Tue Apr 27 00:17:37 2010 -0600 @@ -40892,7 +42913,7 @@ Date: Thu Apr 22 14:53:44 2010 -0700 Signed-off-by: Keith Packard commit f4383394b5d2b275b21e3ce8040d8cb9e48bb375 -Merge: 5f93cf8 c879b17 +Merge: 5f93cf8c c879b178 Author: Bdale Garbee Date: Sun Apr 18 08:36:07 2010 -0600 @@ -40997,7 +43018,7 @@ Date: Thu Apr 8 17:28:17 2010 -0700 Signed-off-by: Keith Packard commit baaaac499cfbc1286ae55374cfdc796d32983b92 -Merge: a4356b9 dec9971 +Merge: a4356b9b dec9971d Author: Keith Packard Date: Thu Apr 8 13:31:23 2010 -0700 @@ -41010,7 +43031,7 @@ Date: Thu Apr 8 13:30:16 2010 -0700 Use 16-bit flite voice (which appears to have changed symbols recently) commit 447c121fc1ceb878e45718ad1364a5349965a59a -Merge: 10330d2 53ca3f9 +Merge: 10330d23 53ca3f98 Author: Keith Packard Date: Thu Apr 8 11:46:56 2010 -0700 @@ -41284,14 +43305,14 @@ Date: Tue Mar 30 23:18:37 2010 -0600 update changelogs for Debian build commit b41e617080fe825f7810ee5eee52ea37f7618ec6 -Merge: 28e40cc df7bda1 +Merge: 28e40ccf df7bda1f Author: Bdale Garbee Date: Tue Mar 30 23:15:32 2010 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos Conflicts: - ChangeLog + ChangeLog commit 28e40ccfcd80ab8764d4aa235257cea4d193a0c1 Author: Bdale Garbee @@ -41312,7 +43333,7 @@ Date: Mon Mar 15 12:04:18 2010 -0600 move gbp.conf into debian/ commit df7bda1f32b0049c3878c325ea0b55999f3980e3 -Merge: 23da4f3 a7042fe +Merge: 23da4f3b a7042fe7 Author: Keith Packard Date: Fri Mar 12 10:38:26 2010 -0800 @@ -41374,7 +43395,7 @@ Date: Sat Feb 27 17:36:13 2010 -0700 update changelogs for Debian build commit a1478f65538fdaac7b58ffbd958a035b74956099 -Merge: 901fce5 bbf8c9f +Merge: 901fce5f bbf8c9f1 Author: Keith Packard Date: Sat Feb 27 15:19:33 2010 -0800 @@ -42335,7 +44356,7 @@ Date: Mon Nov 2 16:54:06 2009 -0700 update changelogs for Debian build commit 7db9d86178ecfd58cc1c17ac9fcbdcfd2f13aaec -Merge: b219801 f9de200 +Merge: b219801f f9de2000 Author: Keith Packard Date: Mon Nov 2 15:47:40 2009 -0800 @@ -42384,7 +44405,7 @@ Date: Mon Nov 2 15:56:42 2009 -0700 de-version the libreadline-dev build dependency commit 0b483233118673cbc2cda1be6acd379df82bc95a -Merge: ca5d323 550482d +Merge: ca5d323a 550482d9 Author: Keith Packard Date: Sun Nov 1 20:59:02 2009 -0800 @@ -42573,14 +44594,14 @@ Date: Mon Oct 12 15:57:19 2009 -0600 update changelogs for Debian build commit c57bd7fd2f80e50b0b4c87fccb024ab07c93773d -Merge: adf8764 2b76572 +Merge: adf8764b 2b765728 Author: Bdale Garbee Date: Mon Oct 12 15:57:08 2009 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos commit 69b6f6bb465163cf767bb68e0e4a716d8ad2b39c -Merge: bc77da6 2b76572 +Merge: bc77da68 2b765728 Author: Keith Packard Date: Sat Oct 10 17:16:21 2009 -0700 @@ -42598,7 +44619,7 @@ Date: Sat Oct 10 17:15:38 2009 -0700 Signed-off-by: Keith Packard commit bc77da68c9cb7d4cca483eadbbb7e9ccf71c0060 -Merge: 46cccf6 8f7ea3d +Merge: 46cccf62 8f7ea3de Author: Keith Packard Date: Sat Oct 10 15:09:48 2009 -0700 @@ -42627,14 +44648,14 @@ Date: Sat Oct 10 15:11:23 2009 -0600 update changelogs for Debian build commit 541da6f3bbf81be93dfe3c01f7c8cfd757b28a2b -Merge: dfc73cb 5f26ad6 +Merge: dfc73cba 5f26ad66 Author: Bdale Garbee Date: Sat Oct 10 15:05:50 2009 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos commit 46cccf62fb40514b5930fcb2ffdaf2735415c764 -Merge: fb8f3fe 5f26ad6 +Merge: fb8f3fee 5f26ad66 Author: Keith Packard Date: Sat Oct 10 14:00:03 2009 -0700 @@ -42655,7 +44676,7 @@ Date: Sat Oct 10 13:58:16 2009 -0700 Signed-off-by: Keith Packard commit fb8f3fee6a1bab1e46d782e84405845cee2dadb4 -Merge: 22856cf b8fc397 +Merge: 22856cf8 b8fc3975 Author: Keith Packard Date: Sat Oct 10 13:41:00 2009 -0700 @@ -42675,7 +44696,7 @@ Date: Sat Oct 10 13:39:01 2009 -0700 Signed-off-by: Keith Packard commit 22856cf8bb0f5e1f37c9b774132d9ef6934526ed -Merge: 2f76034 e29961f +Merge: 2f760349 e29961fd Author: Keith Packard Date: Sat Oct 10 11:44:20 2009 -0700 @@ -42744,7 +44765,7 @@ Date: Mon Sep 21 11:00:32 2009 -0700 update changelogs for Debian build commit 327c64305a59f48ababf19875874a550af6b9cef -Merge: c8a81a4 74f0fb4 +Merge: c8a81a41 74f0fb4d Author: Bdale Garbee Date: Mon Sep 21 11:00:22 2009 -0700 @@ -42775,7 +44796,7 @@ Date: Sun Sep 20 09:21:00 2009 -0600 update changelogs for Debian build commit df42ccaaf468cdc5d93cbd1c001f58df58419722 -Merge: 0b24e40 078e9cd +Merge: 0b24e403 078e9cdb Author: Bdale Garbee Date: Sun Sep 20 09:19:28 2009 -0600 @@ -42871,7 +44892,7 @@ Date: Sun Sep 6 17:46:39 2009 -0600 update changelogs for Debian build commit 37e6c9a492a1d51373bf9333fb3172e0c377720f -Merge: d256f82 2e6686b +Merge: d256f820 2e6686b1 Author: Bdale Garbee Date: Sun Sep 6 17:46:10 2009 -0600 @@ -42884,7 +44905,7 @@ Date: Sun Sep 6 16:45:47 2009 -0700 Use plplotd instead of plplotd-gnome2 commit d256f8204e9fce53ae4309562bb4c0cde1fae43e -Merge: 0fc344d 32d3536 +Merge: 0fc344df 32d35367 Author: Bdale Garbee Date: Sun Sep 6 17:34:08 2009 -0600 @@ -42907,7 +44928,7 @@ Date: Sun Sep 6 14:15:57 2009 -0600 update changelogs for Debian build commit 4b0de757874c0ecaf38e3dfd3beefc398150e3d5 -Merge: 773c4ff d0eac98 +Merge: 773c4ffb d0eac989 Author: Bdale Garbee Date: Sun Sep 6 14:15:53 2009 -0600 @@ -42940,7 +44961,7 @@ Date: Sun Sep 6 14:05:55 2009 -0600 update changelogs for Debian build commit 45ede4a4b203ef9da5bf05c49cb9c5a2e6382ec5 -Merge: 45e2938 e35e485 +Merge: 45e29381 e35e485f Author: Bdale Garbee Date: Sun Sep 6 14:05:51 2009 -0600 @@ -42963,7 +44984,7 @@ Date: Sun Sep 6 14:02:14 2009 -0600 update changelogs for Debian build commit d42ebf0661ecf15455e5051de1e16ae66f8dd857 -Merge: 384dbe9 7a19aac +Merge: 384dbe9f 7a19aac5 Author: Bdale Garbee Date: Sun Sep 6 14:02:09 2009 -0600 @@ -42988,7 +45009,7 @@ Date: Sun Sep 6 10:40:06 2009 -0600 update changelogs for Debian build commit 35c54b3a278fa9bc2bc7f4b5ee04866697c93ba0 -Merge: 4f8eff7 6d018ab +Merge: 4f8eff74 6d018ab9 Author: Bdale Garbee Date: Sun Sep 6 10:39:23 2009 -0600 @@ -43138,7 +45159,7 @@ Date: Wed Sep 2 23:18:15 2009 -0600 update changelogs for Debian build commit cb4a73f3b65ba72f645fd37ab8712829c9537bf8 -Merge: 9ddd869 e2e449d +Merge: 9ddd8696 e2e449d5 Author: Bdale Garbee Date: Wed Sep 2 23:17:37 2009 -0600 @@ -43214,7 +45235,7 @@ Date: Mon Aug 31 16:26:00 2009 -0600 update changelogs for Debian build commit b34474c1f3083e73b7184d519f54d4c8031836fd -Merge: 8df1697 0d65bff +Merge: 8df16979 0d65bff4 Author: Bdale Garbee Date: Mon Aug 31 16:25:32 2009 -0600 @@ -43282,7 +45303,7 @@ Date: Wed Aug 19 00:52:57 2009 -0600 update changelogs for Debian build commit 4486d9156e19e4280b42bcd422d81d04f2d04a92 -Merge: dd09f0b 33edd62 +Merge: dd09f0bc 33edd629 Author: Bdale Garbee Date: Wed Aug 19 00:49:24 2009 -0600 @@ -43324,7 +45345,7 @@ Date: Tue Aug 18 21:49:39 2009 -0600 add support for building Debian package commit d996aa9b32fb0eb385bd3d158256c29788a42fe3 -Merge: b3b2d3c 7d4ceb7 +Merge: b3b2d3c4 7d4ceb75 Author: Bdale Garbee Date: Tue Aug 18 18:56:09 2009 -0600 @@ -43341,7 +45362,7 @@ Date: Tue Aug 18 17:55:22 2009 -0700 Signed-off-by: Keith Packard commit b3b2d3c475a135084b5628c730fc6fca1ba0817b -Merge: 4685fc5 da12b89 +Merge: 4685fc54 da12b89f Author: Bdale Garbee Date: Tue Aug 18 18:36:03 2009 -0600 @@ -43360,18 +45381,18 @@ Date: Tue Aug 18 17:29:29 2009 -0700 Fix ao-bitbang examples to not have . in the first column commit 4685fc541466afbeefc151bcb64cd054739c048b -Merge: 1c2a0b6 c29275b +Merge: 1c2a0b66 c29275b7 Author: Bdale Garbee Date: Tue Aug 18 18:09:38 2009 -0600 Merge branch 'master' of ssh://git.gag.com/scm/git/fw/altos Conflicts: - ao-tools/ao-bitbang/Makefile.am - ao-tools/ao-eeprom/Makefile.am - ao-tools/ao-load/Makefile.am - ao-tools/ao-load/ao-load.c - ao-tools/ao-rawload/Makefile.am + ao-tools/ao-bitbang/Makefile.am + ao-tools/ao-eeprom/Makefile.am + ao-tools/ao-load/Makefile.am + ao-tools/ao-load/ao-load.c + ao-tools/ao-rawload/Makefile.am commit c29275b72438637d46d7a50742882d2736eb176a Author: Keith Packard @@ -43860,7 +45881,7 @@ Date: Thu Jun 4 11:20:10 2009 -0700 Signed-off-by: Keith Packard commit 17d2432a8b9c15963cd3b821f025ad33972ef477 -Merge: 210dbaa 8a9a3f0 +Merge: 210dbaa2 8a9a3f02 Author: Keith Packard Date: Thu Jun 4 11:13:15 2009 -0700 diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index 288f43ce..8617a12c 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -219,7 +219,23 @@ public class AltosConvert { return AltosLib.MISSING; } - static double tele_mini_voltage(int sensor) { + static double tele_mini_3_adc(int raw) { + return raw / 4095.0; + } + + static public double tele_mini_3_battery_voltage(int v_batt) { + if (v_batt != AltosLib.MISSING) + return 3.3 * tele_mini_3_adc(v_batt) * (5.6 + 10.0) / 10.0; + return AltosLib.MISSING; + } + + static double tele_mini_3_pyro_voltage(int raw) { + if (raw != AltosLib.MISSING) + return 3.3 * tele_mini_3_adc(raw) * (100.0 + 27.0) / 27.0; + return AltosLib.MISSING; + } + + static double tele_mini_2_voltage(int sensor) { double supply = 3.3; return sensor / 32767.0 * supply * 127/27; @@ -350,6 +366,10 @@ public class AltosConvert { return (c - 32) * 5/9; } + public static double psi_to_pa(double psi) { + return psi * 6894.76; + } + public static boolean imperial_units = false; public static AltosDistance distance = new AltosDistance(); diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java index c9598254..32d9f8ea 100644 --- a/altoslib/AltosEepromChunk.java +++ b/altoslib/AltosEepromChunk.java @@ -82,13 +82,17 @@ public class AltosEepromChunk { case AltosLib.AO_LOG_FORMAT_TELEMETRUM: eeprom = new AltosEepromMetrum2(this, offset); break; - case AltosLib.AO_LOG_FORMAT_TELEMINI: + case AltosLib.AO_LOG_FORMAT_TELEMINI2: + case AltosLib.AO_LOG_FORMAT_TELEMINI3: case AltosLib.AO_LOG_FORMAT_EASYMINI: eeprom = new AltosEepromMini(this, offset); break; case AltosLib.AO_LOG_FORMAT_TELEGPS: eeprom = new AltosEepromGPS(this, offset); break; + case AltosLib.AO_LOG_FORMAT_TELEFIRETWO: + eeprom = new AltosEepromFireTwo(this, offset); + break; default: throw new ParseException("unknown eeprom format " + log_format, 0); } diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 957c826a..5544ec37 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -101,13 +101,17 @@ public class AltosEepromFile extends AltosStateIterable { case AltosLib.AO_LOG_FORMAT_TELEMETRUM: body = new AltosEepromIterable(AltosEepromMetrum2.read(input)); break; - case AltosLib.AO_LOG_FORMAT_TELEMINI: + case AltosLib.AO_LOG_FORMAT_TELEMINI2: + case AltosLib.AO_LOG_FORMAT_TELEMINI3: case AltosLib.AO_LOG_FORMAT_EASYMINI: body = new AltosEepromIterable(AltosEepromMini.read(input)); break; case AltosLib.AO_LOG_FORMAT_TELEGPS: body = new AltosEepromIterable(AltosEepromGPS.read(input)); break; + case AltosLib.AO_LOG_FORMAT_TELEFIRETWO: + body = new AltosEepromIterable(AltosEepromFireTwo.read(input)); + break; default: body = new AltosEepromIterable(new LinkedList()); break; diff --git a/altoslib/AltosEepromFireTwo.java b/altoslib/AltosEepromFireTwo.java new file mode 100644 index 00000000..dd510280 --- /dev/null +++ b/altoslib/AltosEepromFireTwo.java @@ -0,0 +1,118 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.io.*; +import java.util.*; +import java.text.*; + +public class AltosEepromFireTwo extends AltosEeprom { + public static final int record_length = 32; + + public int record_length() { return record_length; } + + /* AO_LOG_FLIGHT elements */ + public int flight() { return data16(0); } + public int idle_pres() { return data16(2); } + public int idle_thrust() { return data16(4); } + + /* AO_LOG_STATE elements */ + public int state() { return data16(0); } + public int reason() { return data16(2); } + + /* AO_LOG_SENSOR elements */ + public int pres() { return data16(0); } + public int thrust() { return data16(2); } + public int temp(int i) { return data16(4+i*2); } + + public AltosEepromFireTwo (AltosEepromChunk chunk, int start) throws ParseException { + parse_chunk(chunk, start); + } + + private static final double r_above = 5600.0; + private static final double r_below = 10000.0; + private static final double v_adc = 3.3; + + private static double + firetwo_adc(int raw) { + return raw / 4095.0; + } + + private static double + adc_to_pa(int adc) { + + /* raw adc to processor voltage, then back through the + * voltage divider to the sensor voltage + */ + + double v = firetwo_adc(adc) * v_adc * (r_above + r_below) / r_below; + + /* Bound to ranges provided in sensor */ + if (v < 0.5) v = 0.5; + if (v > 4.5) v = 4.5; + + double psi = (v - 0.5) / 4.0 * 1600.0; + return AltosConvert.psi_to_pa(psi); + } + + public void update_state(AltosState state) { + super.update_state(state); + + switch (cmd) { + case AltosLib.AO_LOG_FLIGHT: + state.set_flight(flight()); + state.set_ground_pressure(adc_to_pa(idle_pres())); + break; + case AltosLib.AO_LOG_STATE: + state.set_state(state()); + break; + case AltosLib.AO_LOG_SENSOR: + state.set_pressure(adc_to_pa(pres())); + break; + } + } + + public AltosEepromFireTwo (String line) { + parse_string(line); + } + + static public LinkedList read(FileInputStream input) { + LinkedList firetwos = new LinkedList(); + + for (;;) { + try { + String line = AltosLib.gets(input); + if (line == null) + break; + try { + AltosEepromFireTwo firetwo = new AltosEepromFireTwo(line); + + if (firetwo.cmd != AltosLib.AO_LOG_INVALID) + firetwos.add(firetwo); + } catch (Exception e) { + System.out.printf ("exception\n"); + } + } catch (IOException ie) { + break; + } + } + + return firetwos; + } +} diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java index dc51e591..04155071 100644 --- a/altoslib/AltosEepromMini.java +++ b/altoslib/AltosEepromMini.java @@ -42,11 +42,24 @@ public class AltosEepromMini extends AltosEeprom { public int sense_m() { return data16(8); } public int v_batt() { return data16(10); } - double voltage(AltosState state, int sensor) { + private double battery_voltage(AltosState state, int sensor) { if (state.log_format == AltosLib.AO_LOG_FORMAT_EASYMINI) return AltosConvert.easy_mini_voltage(sensor, state.serial); - else - return AltosConvert.tele_mini_voltage(sensor); + if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) + return AltosConvert.tele_mini_2_voltage(sensor); + if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) + return AltosConvert.tele_mini_3_battery_voltage(sensor); + return -1; + } + + private double pyro_voltage(AltosState state, int sensor) { + if (state.log_format == AltosLib.AO_LOG_FORMAT_EASYMINI) + return AltosConvert.easy_mini_voltage(sensor, state.serial); + if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI2) + return AltosConvert.tele_mini_2_voltage(sensor); + if (state.log_format == AltosLib.AO_LOG_FORMAT_TELEMINI3) + return AltosConvert.tele_mini_3_pyro_voltage(sensor); + return -1; } public void update_state(AltosState state) { @@ -62,9 +75,9 @@ public class AltosEepromMini extends AltosEeprom { break; case AltosLib.AO_LOG_SENSOR: state.set_ms5607(pres(), temp()); - state.set_apogee_voltage(voltage(state, sense_a())); - state.set_main_voltage(voltage(state, sense_m())); - state.set_battery_voltage(voltage(state, v_batt())); + state.set_apogee_voltage(pyro_voltage(state, sense_a())); + state.set_main_voltage(pyro_voltage(state, sense_m())); + state.set_battery_voltage(battery_voltage(state, v_batt())); break; } } diff --git a/altoslib/AltosIdleFetch.java b/altoslib/AltosIdleFetch.java index 8871e9cc..73717e17 100644 --- a/altoslib/AltosIdleFetch.java +++ b/altoslib/AltosIdleFetch.java @@ -38,8 +38,9 @@ class AltosIdler { static final int idle_sensor_metrum = 11; 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_tmini2 = 14; static final int idle_sensor_tgps = 15; + static final int idle_sensor_tmini3 = 16; public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException, TimeoutException, AltosUnknownProduct { for (int idler : idlers) { @@ -72,12 +73,15 @@ class AltosIdler { case idle_sensor_emini: AltosSensorEMini.update_state(state, link, config_data); break; - case idle_sensor_tmini: - AltosSensorTMini.update_state(state, link, config_data); + case idle_sensor_tmini2: + AltosSensorTMini2.update_state(state, link, config_data); break; case idle_sensor_tgps: AltosSensorTGPS.update_state(state, link, config_data); break; + case idle_sensor_tmini3: + AltosSensorTMini3.update_state(state, link, config_data); + break; } if (idle != null) idle.update_state(state); @@ -108,7 +112,11 @@ public class AltosIdleFetch implements AltosStateUpdate { new AltosIdler("TeleMini-v2", AltosIdler.idle_ms5607, - AltosIdler.idle_sensor_tmini), + AltosIdler.idle_sensor_tmini2), + + new AltosIdler("TeleMini-v3", + AltosIdler.idle_ms5607, + AltosIdler.idle_sensor_tmini3), new AltosIdler("TeleMetrum-v1", AltosIdler.idle_gps, diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index cfa1fa27..a3f164d4 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -332,9 +332,12 @@ public class AltosLib { 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_TELEMINI2 = 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_DETHERM = 11; + public static final int AO_LOG_FORMAT_TELEMINI3 = 12; + public static final int AO_LOG_FORMAT_TELEFIRETWO = 13; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { diff --git a/altoslib/AltosSensorTMini.java b/altoslib/AltosSensorTMini.java deleted file mode 100644 index 073144d4..00000000 --- a/altoslib/AltosSensorTMini.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * 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. - */ - -package org.altusmetrum.altoslib_11; - -import java.util.concurrent.TimeoutException; - -public class AltosSensorTMini { - public int tick; - public int apogee; - public int main; - public int batt; - - static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { - try { - AltosSensorTMini sensor_tmini = new AltosSensorTMini(link); - - if (sensor_tmini == null) - return; - state.set_battery_voltage(AltosConvert.tele_mini_voltage(sensor_tmini.batt)); - state.set_apogee_voltage(AltosConvert.tele_mini_voltage(sensor_tmini.apogee)); - state.set_main_voltage(AltosConvert.tele_mini_voltage(sensor_tmini.main)); - - } catch (TimeoutException te) { - } - } - - public AltosSensorTMini(AltosLink link) throws InterruptedException, TimeoutException { - String[] items = link.adc(); - for (int i = 0; i < items.length;) { - if (items[i].equals("tick:")) { - tick = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("apogee:")) { - apogee = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("main:")) { - main = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - if (items[i].equals("batt:")) { - batt = Integer.parseInt(items[i+1]); - i += 2; - continue; - } - i++; - } - } -} - diff --git a/altoslib/AltosSensorTMini2.java b/altoslib/AltosSensorTMini2.java new file mode 100644 index 00000000..7e00abd0 --- /dev/null +++ b/altoslib/AltosSensorTMini2.java @@ -0,0 +1,70 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.util.concurrent.TimeoutException; + +public class AltosSensorTMini2 { + public int tick; + public int apogee; + public int main; + public int batt; + + static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + try { + AltosSensorTMini2 sensor_tmini = new AltosSensorTMini2(link); + + if (sensor_tmini == null) + return; + state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.batt)); + state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.apogee)); + state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sensor_tmini.main)); + + } catch (TimeoutException te) { + } + } + + public AltosSensorTMini2(AltosLink link) throws InterruptedException, TimeoutException { + String[] items = link.adc(); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("apogee:")) { + apogee = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("main:")) { + main = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + } +} + diff --git a/altoslib/AltosSensorTMini3.java b/altoslib/AltosSensorTMini3.java new file mode 100644 index 00000000..19d514d7 --- /dev/null +++ b/altoslib/AltosSensorTMini3.java @@ -0,0 +1,70 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + +import java.util.concurrent.TimeoutException; + +public class AltosSensorTMini3 { + public int tick; + public int apogee; + public int main; + public int batt; + + static public void update_state(AltosState state, AltosLink link, AltosConfigData config_data) throws InterruptedException { + try { + AltosSensorTMini3 sensor_tmini = new AltosSensorTMini3(link); + + if (sensor_tmini == null) + return; + state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(sensor_tmini.batt)); + state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.apogee)); + state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sensor_tmini.main)); + + } catch (TimeoutException te) { + } + } + + public AltosSensorTMini3(AltosLink link) throws InterruptedException, TimeoutException { + String[] items = link.adc(); + for (int i = 0; i < items.length;) { + if (items[i].equals("tick:")) { + tick = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("apogee:")) { + apogee = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("main:")) { + main = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + if (items[i].equals("batt:")) { + batt = Integer.parseInt(items[i+1]); + i += 2; + continue; + } + i++; + } + } +} + diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index 0caefcd6..f830bf35 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -67,7 +67,8 @@ public abstract class AltosTelemetry implements AltosStateUpdate { final static int packet_type_mega_data = 0x09; final static int packet_type_metrum_sensor = 0x0a; final static int packet_type_metrum_data = 0x0b; - final static int packet_type_mini = 0x10; + final static int packet_type_mini2 = 0x10; + final static int packet_type_mini3 = 0x11; static AltosTelemetry parse_hex(String hex) throws ParseException, AltosCRCException { AltosTelemetry telem = null; diff --git a/altoslib/AltosTelemetryMini.java b/altoslib/AltosTelemetryMini.java deleted file mode 100644 index 74adb052..00000000 --- a/altoslib/AltosTelemetryMini.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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. - */ - -package org.altusmetrum.altoslib_11; - - -public class AltosTelemetryMini extends AltosTelemetryStandard { - int state; - - int v_batt; - int sense_a; - int sense_m; - - int pres; - int temp; - - int acceleration; - int speed; - int height; - - int ground_pres; - - public AltosTelemetryMini(int[] bytes) { - super(bytes); - - state = int8(5); - - v_batt = int16(6); - sense_a = int16(8); - sense_m = int16(10); - - pres = int32(12); - temp = int16(16); - - acceleration = int16(18); - speed = int16(20); - height = int16(22); - - ground_pres = int32(24); - } - - public void update_state(AltosState state) { - super.update_state(state); - - state.set_state(this.state); - - state.set_battery_voltage(AltosConvert.tele_mini_voltage(v_batt)); - state.set_apogee_voltage(AltosConvert.tele_mini_voltage(sense_a)); - state.set_main_voltage(AltosConvert.tele_mini_voltage(sense_m)); - - state.set_ground_pressure(ground_pres); - - state.set_pressure(pres); - state.set_temperature(temp/100.0); - - state.set_kalman(height, speed/16.0, acceleration/16.0); - } -} diff --git a/altoslib/AltosTelemetryMini2.java b/altoslib/AltosTelemetryMini2.java new file mode 100644 index 00000000..50ec504d --- /dev/null +++ b/altoslib/AltosTelemetryMini2.java @@ -0,0 +1,73 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + + +public class AltosTelemetryMini2 extends AltosTelemetryStandard { + int state; + + int v_batt; + int sense_a; + int sense_m; + + int pres; + int temp; + + int acceleration; + int speed; + int height; + + int ground_pres; + + public AltosTelemetryMini2(int[] bytes) { + super(bytes); + + state = int8(5); + + v_batt = int16(6); + sense_a = int16(8); + sense_m = int16(10); + + pres = int32(12); + temp = int16(16); + + acceleration = int16(18); + speed = int16(20); + height = int16(22); + + ground_pres = int32(24); + } + + public void update_state(AltosState state) { + super.update_state(state); + + state.set_state(this.state); + + state.set_battery_voltage(AltosConvert.tele_mini_2_voltage(v_batt)); + state.set_apogee_voltage(AltosConvert.tele_mini_2_voltage(sense_a)); + state.set_main_voltage(AltosConvert.tele_mini_2_voltage(sense_m)); + + state.set_ground_pressure(ground_pres); + + state.set_pressure(pres); + state.set_temperature(temp/100.0); + + state.set_kalman(height, speed/16.0, acceleration/16.0); + } +} diff --git a/altoslib/AltosTelemetryMini3.java b/altoslib/AltosTelemetryMini3.java new file mode 100644 index 00000000..21f8c485 --- /dev/null +++ b/altoslib/AltosTelemetryMini3.java @@ -0,0 +1,76 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +package org.altusmetrum.altoslib_11; + + +public class AltosTelemetryMini3 extends AltosTelemetryStandard { + + int state; + + int v_batt; + int sense_a; + int sense_m; + + int pres; + int temp; + + int acceleration; + int speed; + int height_16; + + int ground_pres; + + public AltosTelemetryMini3(int[] bytes) { + super(bytes); + + state = int8(5); + + v_batt = int16(6); + sense_a = int16(8); + sense_m = int16(10); + + pres = int32(12); + temp = int16(16); + + acceleration = int16(18); + speed = int16(20); + height_16 = int16(22); + + ground_pres = int32(24); + } + + public void update_state(AltosState state) { + super.update_state(state); + + state.set_state(this.state); + + state.set_battery_voltage(AltosConvert.tele_mini_3_battery_voltage(v_batt)); + + state.set_apogee_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_a)); + state.set_main_voltage(AltosConvert.tele_mini_3_pyro_voltage(sense_m)); + + state.set_pressure(pres); + state.set_temperature(temp/100.0); + + state.set_kalman(extend_height(state, height_16), + speed/16.0, acceleration/16.0); + + state.set_ground_pressure(ground_pres); + } +} diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java index 4f0d7130..35d315c7 100644 --- a/altoslib/AltosTelemetryStandard.java +++ b/altoslib/AltosTelemetryStandard.java @@ -84,8 +84,11 @@ public abstract class AltosTelemetryStandard extends AltosTelemetry { case packet_type_metrum_data: telem = new AltosTelemetryMetrumData(bytes); break; - case packet_type_mini: - telem = new AltosTelemetryMini(bytes); + case packet_type_mini2: + telem = new AltosTelemetryMini2(bytes); + break; + case packet_type_mini3: + telem = new AltosTelemetryMini3(bytes); break; default: telem = new AltosTelemetryRaw(bytes); diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 2a9eb9c9..26159421 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -49,6 +49,7 @@ altoslib_JAVA = \ AltosEepromMini.java \ AltosEepromGPS.java \ AltosEepromMonitor.java \ + AltosEepromFireTwo.java \ AltosFile.java \ AltosFlash.java \ AltosFlashListener.java \ @@ -88,7 +89,8 @@ altoslib_JAVA = \ AltosSensorMM.java \ AltosSensorEMini.java \ AltosSensorTM.java \ - AltosSensorTMini.java \ + AltosSensorTMini2.java \ + AltosSensorTMini3.java \ AltosSensorMega.java \ AltosSensorMetrum.java \ AltosSensorTGPS.java \ @@ -105,7 +107,8 @@ altoslib_JAVA = \ AltosTelemetryMap.java \ AltosTelemetryMegaSensor.java \ AltosTelemetryMegaData.java \ - AltosTelemetryMini.java \ + AltosTelemetryMini2.java \ + AltosTelemetryMini3.java \ AltosTelemetryMetrumSensor.java \ AltosTelemetryMetrumData.java \ AltosTelemetryReader.java \ diff --git a/ao-bringup/test-chaoskey b/ao-bringup/test-chaoskey index b4c8164f..f64b1f84 100755 --- a/ao-bringup/test-chaoskey +++ b/ao-bringup/test-chaoskey @@ -12,7 +12,9 @@ case "$#" in serial="--serial $1" ;; 0) - snum=`dmesg | grep 'on chaoskey' | tail -1 | sed 's/.*chaoskey \([0-9a-f][0-9a-f]*\) on chaoskey.*/\1/'` + snum=`sudo dmesg | awk '/usb.*Product:/ { ck = index($0, "ChaosKey"); } + /usb.*SerialNumber:/ { if (ck) print $5; }' | tail -1` + case "$snum" in "") serial="" diff --git a/ao-bringup/test-easymini b/ao-bringup/test-easymini index e11244d2..e9948da9 100755 --- a/ao-bringup/test-easymini +++ b/ao-bringup/test-easymini @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash VERSION=1.0 PRODUCT=EasyMini @@ -8,48 +8,55 @@ 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 -e "\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"" +found=0 +while [ $found -eq 0 ]; do + (ao-list; echo END END END END) | while read product serial dev; do + case "$product" in + "$PRODUCT-v$VERSION") - FLASHSIZE=1048576 + found=1 + echo -e '\e[34m'Testing $product $serial $dev'\e[39m' + echo "" + + ./test-igniters "$dev" drogue main + echo "" - echo "Testing flash" - ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE" + echo "Testing baro sensor" + ../ao-tools/ao-test-baro/ao-test-baro --tty="$dev" - case $? in - 0) - ;; - *) - echo "failed" + if [ $? -ne 0 ]; then + echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m' exit 1 - esac - echo"" + fi + echo"" + + FLASHSIZE=1048576 - echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship - ret=0 - ;; - esac + echo "Testing flash" + ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE" + + if [ $? -ne 0 ]; then + echo -e '\e[31m'"$PRODUCT-$VERSION serial $serial failed"'\e[39m' + exit 1 + fi + + echo "" + + echo -e '\e[32m'"$PRODUCT-v$VERSION" serial "$serial" is ready to ship'\e[39m' + exit 0 + ;; + END) + exit 2 + ;; + esac + done + result=$? + if [ $result -ne 2 ]; then + exit $result + fi + echo 'No device, sleeping...' + sleep 1 done diff --git a/ao-bringup/test-telemini b/ao-bringup/test-telemini new file mode 100755 index 00000000..7df36a28 --- /dev/null +++ b/ao-bringup/test-telemini @@ -0,0 +1,56 @@ +#!/bin/sh + +VERSION=3.0 +PRODUCT=TeleMini +BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'` + +echo "$PRODUCT-v$VERSION Test Program" +echo "Copyright 2017 by Keith Packard. Released under GPL v2 or later" +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=524288 + + echo "Testing flash" + ../ao-tools/ao-test-flash/ao-test-flash --tty="$dev" "$FLASHSIZE" + + case $? in + 0) + ;; + *) + echo "failed" + exit 1 + esac + echo"" + + echo "$PRODUCT-v$VERSION" serial "$serial" is ready to ship + echo "\007" + ret=0 + ;; + esac +done diff --git a/ao-bringup/turnon_easymega b/ao-bringup/turnon_easymega index 1e75e72f..b14ed2ab 100755 --- a/ao-bringup/turnon_easymega +++ b/ao-bringup/turnon_easymega @@ -1,5 +1,7 @@ #!/bin/sh +PRODUCT=EasyMega + if [ -x ../ao-tools/ao-flash/ao-flash-stm ]; then STMLOAD=../ao-tools/ao-flash/ao-flash-stm else @@ -17,16 +19,29 @@ fi VERSION=1.0 REPO=~/altusmetrumllc/Binaries -echo "EasyMega v$VERSION Turn-On and Calibration Program" +echo "$PRODUCT v$VERSION Turn-On and Calibration Program" echo "Copyright 2014 by Bdale Garbee. Released under GPL v2" echo echo "Expectations:" -echo "\tEasyMega v$VERSION" +echo "\t$PRODUCT v$VERSION" echo "\t\twith USB cable attached" echo "\t\twith ST-Link-V2 cabled to debug header" echo -echo -n "EasyMega-$VERSION serial number: " -read SERIAL + +case $# in + 1) + SERIAL="$1" + echo "$PRODUCT-$VERSION serial number: $SERIAL" + ;; + 0) + echo -n "$PRODUCT-$VERSION serial number: " + read SERIAL + ;; + *) + echo "Usage: $0 " 1>&2 + exit 1; + ;; +esac echo $STMLOAD @@ -38,14 +53,14 @@ $USBLOAD --serial=$SERIAL $REPO/easymega-v$VERSION*.elf || exit 1 sleep 2 -dev=`../ao-tools/ao-list/ao-list | awk '/EasyMega-v'"$VERSION"'/ { print $3; exit(0); }'` +dev=`../ao-tools/ao-list/ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'` case "$dev" in /dev/tty*) - echo "EasyMega found on $dev" + echo "$PRODUCT found on $dev" ;; *) - echo 'No EasyMega-v'"$VERSION"' found' + echo 'No '"$PRODUCT"'-v'"$VERSION"' found' exit 1 ;; esac diff --git a/ao-bringup/turnon_easymini b/ao-bringup/turnon_easymini index 0b915c5e..4580790a 100755 --- a/ao-bringup/turnon_easymini +++ b/ao-bringup/turnon_easymini @@ -65,7 +65,7 @@ echo $USBLOAD $ALTOS_FILE $USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1 -sleep 2 +sleep 1 ./test-easymini diff --git a/ao-bringup/turnon_teledongle b/ao-bringup/turnon_teledongle index d17e2b96..0cdbde7a 100755 --- a/ao-bringup/turnon_teledongle +++ b/ao-bringup/turnon_teledongle @@ -28,8 +28,21 @@ 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 + +case $# in + 1) + SERIAL="$1" + echo "$PRODUCT-$VERSION serial number: $SERIAL" + ;; + 0) + echo -n "$PRODUCT-$VERSION serial number: " + read SERIAL + ;; + *) + echo "Usage: $0 " 1>&2 + exit 1; + ;; +esac BINARIES=$HOME/altusmetrumllc/Binaries diff --git a/ao-bringup/turnon_teledongle_v0.2 b/ao-bringup/turnon_teledongle_v0.2 index 058e72ce..20c8798a 100755 --- a/ao-bringup/turnon_teledongle_v0.2 +++ b/ao-bringup/turnon_teledongle_v0.2 @@ -51,7 +51,7 @@ read FREQ CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD -D $programmer --cal $CAL_VALUE /usr/share/altos/teledongle-v0.2*.ihx $SERIAL +$AOLOAD -D $programmer --cal $CAL_VALUE ~/altusmetrumllc/Binaries/teledongle-v0.2*.ihx $SERIAL echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE echo $SERIAL","$CAL_VALUE >> cal_values diff --git a/ao-bringup/turnon_telegps b/ao-bringup/turnon_telegps index ba97d503..b6da2898 100755 --- a/ao-bringup/turnon_telegps +++ b/ao-bringup/turnon_telegps @@ -1,10 +1,12 @@ #!/bin/sh -if [ -x /usr/bin/ao-flash-lpc ]; then - FLASH_LPC=/usr/bin/ao-flash-lpc +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 + echo "Can't find ao-flash-lpc! Aborting." + exit 1 fi if [ -x /usr/bin/ao-usbload ]; then @@ -14,8 +16,8 @@ else exit 1 fi -VERSION=1.0 PRODUCT=TeleGPS +VERSION=1.0 BASE=`echo $PRODUCT | tr 'A-Z' 'a-z'` echo $FILE diff --git a/ao-bringup/turnon_telemetrum b/ao-bringup/turnon_telemetrum index 5c62c49d..d40be953 100755 --- a/ao-bringup/turnon_telemetrum +++ b/ao-bringup/turnon_telemetrum @@ -48,7 +48,7 @@ $FLASH_STM ~/altusmetrumllc/Binaries/loaders/telemetrum-v$VERSION-*.elf || exit sleep 2 -$USBLOAD --serial=$SERIAL /usr/share/altos/telemetrum-v$VERSION*.ihx || exit 1 +$USBLOAD --serial=$SERIAL ~/altusmetrumllc/Binaries/telemetrum-v$VERSION-*.elf || exit 1 sleep 5 diff --git a/ao-bringup/turnon_telemetrum_v1.1 b/ao-bringup/turnon_telemetrum_v1.1 new file mode 100755 index 00000000..830d7ed9 --- /dev/null +++ b/ao-bringup/turnon_telemetrum_v1.1 @@ -0,0 +1,49 @@ +#!/bin/sh + +if [ -x ../ao-tools/ao-load/ao-load ]; then + AOLOAD=../ao-tools/ao-load/ao-load +elif [ -x /usr/bin/ao-load ]; then + AOLOAD=/usr/bin/ao-load +else + echo "Can't find ao-load! Aborting." + exit 1 +fi + +if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then + RAWLOAD=../ao-tools/ao-rawload/ao-rawload +elif [ -x /usr/bin/ao-rawload ]; then + RAWLOAD=/usr/bin/ao-rawload +else + echo "Can't find ao-rawload! Aborting." + exit 1 +fi + +echo "TeleMetrum v1.1 Turn-On and Calibration Program" +echo "Copyright 2010 by Bdale Garbee. Released under GPL v2" +echo +echo "Expectations:" +echo "\tTeleMetrum v1.1 powered from USB" +echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" +echo "\t\twith coax from UHF to frequency counter" +echo +echo -n "TeleMetrum serial number: " +read SERIAL + +echo $RAWLOAD + +$RAWLOAD --device 100 -r ao_led_blink.ihx +echo "the red LED should be blinking" +sleep 5 + +$RAWLOAD --device 100 -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 --device 100 --cal $CAL_VALUE \ + ~/altusmetrumllc/Binaries/telemetrum-v1.1*.ihx $SERIAL + +echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE +echo "Unplug and replug USB, cu to the board, confirm freq and record power" diff --git a/ao-bringup/turnon_telemini b/ao-bringup/turnon_telemini index 6aef7f51..1958de2a 100755 --- a/ao-bringup/turnon_telemini +++ b/ao-bringup/turnon_telemini @@ -1,59 +1,76 @@ #!/bin/sh -if [ -x ../ao-tools/ao-load/ao-load ]; then - AOLOAD=../ao-tools/ao-load/ao-load -elif [ -x /usr/bin/ao-load ]; then - AOLOAD=/usr/bin/ao-load +if [ -x /usr/bin/dfu-util ]; then + DFU_UTIL=/usr/bin/dfu-util else - echo "Can't find ao-load! Aborting." - exit 1 + echo "Can't find dfu-util! Aborting." + exit 1 fi -if [ -x ../ao-tools/ao-rawload/ao-rawload ]; then - RAWLOAD=../ao-tools/ao-rawload/ao-rawload -elif [ -x /usr/bin/ao-rawload ]; then - RAWLOAD=/usr/bin/ao-rawload +if [ -x /usr/bin/ao-usbload ]; then + USBLOAD=/usr/bin/ao-usbload else - echo "Can't find ao-rawload! Aborting." + echo "Can't find ao-usbload! Aborting." exit 1 fi -VERSION=1.0 +VERSION=3.0 +PRODUCT=TeleMini -echo "TeleMini v$VERSION Turn-On and Calibration Program" -echo "Copyright 2011 by Bdale Garbee. Released under GPL v2" +echo "$PRODUCT v$VERSION Turn-On and Calibration Program" +echo "Copyright 2017 by Keith Packard. Released under GPL v2 or later" echo echo "Expectations:" -echo "\tTeleMini v$VERSION powered from LiPo" -echo "\t\twith TeleDongle (on /dev/ttyACM0) cabled to debug header" -echo "\t\twith frequency counter able to sample RF output" +echo "\t$PRODUCT v$VERSION powered from USB" echo -echo -n "TeleMini serial number: " -read SERIAL +echo -n "$PRODUCT-$VERSION serial number: " + +case $# in + 1) + SERIAL="$1" + echo "$PRODUCT-$VERSION serial number: $SERIAL" + ;; + 0) + echo -n "$PRODUCT-$VERSION serial number: " + read SERIAL + ;; + *) + echo "Usage: $0 " 1>&2 + exit 1; + ;; +esac -echo $RAWLOAD +FLASH_FILE=~/altusmetrumllc/Binaries/loaders/telemini-v$VERSION-altos-flash-*.bin +ALTOS_FILE=~/altusmetrumllc/Binaries/telemini-v$VERSION-*.elf +#FLASH_FILE=../src/telemini-v3.0/flash-loader/telemini-v$VERSION-altos-flash-*.bin +#ALTOS_FILE=../src/telemini-v3.0/telemini-v$VERSION-*.elf -case $USER in - bdale) - programmer=100 +$DFU_UTIL -a 0 -s 0x08000000:leave -D $FLASH_FILE || exit 1 + +sleep 2 + +$USBLOAD --serial=$SERIAL $ALTOS_FILE || exit 1 + +sleep 3 + +dev=`ao-list | awk '/'"$PRODUCT"'-v'"$VERSION"'/ { print $3; exit(0); }'` + +case "$dev" in +/dev/tty*) + echo "$PRODUCT found on $dev" ;; - keithp) - programmer=186 +*) + echo 'No '"$PRODUCT"'-v'"$VERSION"' found' + exit 1 ;; esac -$RAWLOAD -D $programmer -r ao_led_blink.ihx -echo "LEDs should be blinking" -sleep 5 +echo 'E 0' > $dev -$RAWLOAD -D $programmer -r ao_radio_xmit.ihx -echo -n "Generating RF carrier. Please enter measured frequency: " -read FREQ +SERIAL=$SERIAL ./cal-freq $dev -CAL_VALUE=`nickle -e "floor(434.55 / $FREQ * 1186611 + 0.5)"` +echo 'E 1' > $dev -echo "Programming flash with cal value " $CAL_VALUE -$AOLOAD -D $programmer --cal $CAL_VALUE ~/altusmetrumllc/Binaries/telemini-v$VERSION-*.ihx $SERIAL +./test-telemini -echo "Serial number "$SERIAL" programmed with RF cal value "$CAL_VALUE -echo "Unplug and replug USB, cu to the board, confirm freq and record power" +exit $? diff --git a/ao-tools/ao-flash/ao-flash-stm b/ao-tools/ao-flash/ao-flash-stm index 9eebf5d2..a20428f2 100755 --- a/ao-tools/ao-flash/ao-flash-stm +++ b/ao-tools/ao-flash/ao-flash-stm @@ -5,29 +5,12 @@ case "$#" in exit 1 ;; esac - -ST_FLASH=st-flash - -if which $ST_FLASH > /dev/null; then - : -else - echo "$0: $ST_FLASH not found. Check to see if the stlink package is installed" - exit 1 -fi - -file=$1 - -bin=/tmp/flash$$.bin -trap "rm $bin" 0 1 15 - -base=`arm-none-eabi-nm $file | awk '/interrupt_vector/ { print $1 }'` -case x"$base" in -x) - echo "$file: No interrupt vector address found" - exit 1 - ;; -esac - -arm-none-eabi-objcopy -O binary $file $bin - -$ST_FLASH --reset write $bin $base +cmds=/tmp/flash$$ +trap "rm $cmds" 0 1 15 +file="$1" +echo "program $file reset" > $cmds +openocd \ + -f interface/stlink-v2.cfg \ + -f target/stm32l1.cfg \ + -f $cmds \ + -c shutdown diff --git a/ao-tools/ao-test-baro/ao-test-baro.c b/ao-tools/ao-test-baro/ao-test-baro.c index d2b81e4f..36c805c2 100644 --- a/ao-tools/ao-test-baro/ao-test-baro.c +++ b/ao-tools/ao-test-baro/ao-test-baro.c @@ -164,7 +164,7 @@ do_baro(struct cc_usb *usb) { double temperature = strtod(temp[2], NULL) / 100.0; double altitude = strtod(alt[1], NULL); - if (altitude < -50 || 3000 < altitude) { + if (altitude < -100 || 3000 < altitude) { printf ("weird altitude %f\n", altitude); free_baro(b); return 0; diff --git a/ao-tools/lib/ao-selfload.c b/ao-tools/lib/ao-selfload.c index 0a23dfda..754cd784 100644 --- a/ao-tools/lib/ao-selfload.c +++ b/ao-tools/lib/ao-selfload.c @@ -110,6 +110,7 @@ ao_self_write(struct cc_usb *cc, struct ao_hex_image *image) start = image->address; if (stop > image->address + image->length) stop = image->address + image->length; + memset(block, 0xff, 0x100); memcpy(block + start - address, image->data + start - image->address, stop - start); ao_self_block_write(cc, address, block); ao_self_block_read(cc, address, check); diff --git a/configure.ac b/configure.ac index 0fc946f2..3e6658e9 100644 --- a/configure.ac +++ b/configure.ac @@ -18,12 +18,15 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.6.8) -ANDROID_VERSION=13 +AC_INIT([altos], 1.7) +ANDROID_VERSION=14 AC_CONFIG_SRCDIR([src/kernel/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE +RELEASE_DATE=2017-04-24 +AC_SUBST(RELEASE_DATE) + VERSION_DASH=`echo $VERSION | sed 's/\./-/g'` AC_SUBST(VERSION_DASH) AC_SUBST(ANDROID_VERSION) @@ -515,6 +518,7 @@ AM_CONDITIONAL([INSTALL_SHARED_MIME_INFO], [test x$INSTALL_SHARED_MIME_INFO = xy AC_OUTPUT([ Makefile src/Makedefs +src/chaoskey-v1.0/org.altusmetrum.ChaosKey.metainfo.xml altoslib/Makefile altoslib/AltosVersion.java icon/Makefile diff --git a/doc/Makefile b/doc/Makefile index e6fb95ab..0d01279f 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -3,6 +3,7 @@ # RELNOTES_INC=\ + release-notes-1.7.inc \ release-notes-1.6.8.inc \ release-notes-1.6.5.inc \ release-notes-1.6.4.inc \ @@ -86,8 +87,11 @@ IMAGES=\ telemetrum.svg \ telemetrum-v1.1-thside.jpg \ telemetrum-v2.0-th.jpg \ - telemini.svg \ + telemini-v1.svg \ telemini-v1-top.jpg \ + telemini-v3.svg \ + telemini-v3.0-top.jpg \ + telemini-v3.0-bottom.jpg \ altusmetrum-oneline.svg \ telegps-oneline.svg \ micropeak-oneline.svg @@ -107,7 +111,7 @@ INC_FILES=\ getting-started.inc \ usage.inc \ telemetrum.inc \ - telemini-v1.0.inc \ + telemini.inc \ easymini-device.inc \ telemega.inc \ easymega.inc \ @@ -162,7 +166,8 @@ OUTLINE_TXT_FILES=\ easymini-outline.txt \ telemega-outline.txt \ telemetrum-outline.txt \ - telemini-outline.txt + telemini-v1-outline.txt \ + telemini-v3-outline.txt OUTLINE_RAW_FILES=$(OUTLINE_TXT_FILES:.txt=.raw) @@ -172,7 +177,8 @@ SVG=\ easymini.svg \ telemega.svg \ telemetrum.svg \ - telemini.svg \ + telemini-v1.svg \ + telemini-v3.svg \ easymega.svg RELNOTES_PDF=$(RELNOTES_INC:.inc=.pdf) @@ -237,6 +243,7 @@ DOC=$(HTML) $(HTML_REVHISTORY) $(PDF) $(IMAGES) $(STYLESHEET) .raw.pdf: a2x --verbose -a docinfo -f pdf --xsltproc-opts "--stringparam toc.section.depth 2" --xsl-file $(FOP_STYLE) --fop --fop-opts="-c $(FOP_XCONF)" $*.raw a2x --verbose -a docinfo -f xhtml --xsltproc-opts "--stringparam toc.section.depth 2" --xsl-file $(HTML_STYLE) --stylesheet=$(STYLESHEET) $*.raw + case $* in release-notes*) ./fix-html $*.html ;; esac .pdf.html: @touch $@ @@ -260,6 +267,10 @@ micropeak.pdf micropeak.html: micropeak-docinfo.xml $(MICROPEAK_RAW_FILES) $(IMA easymini.pdf easymini.html: easymini-docinfo.xml $(EASYMINI_RAW_FILES) $(IMAGES) +telemini-v1-outline.pdf: telemini-v1-outline.txt telemini-v1.svg + +telemini-v3-outline.pdf: telemini-v3-outline.txt telemini-v3.svg + install: all publish: $(DOC) $(FONTS) diff --git a/doc/altosdroid.inc b/doc/altosdroid.inc index faaa13f9..dce81c3b 100644 --- a/doc/altosdroid.inc +++ b/doc/altosdroid.inc @@ -224,7 +224,7 @@ flights, there may not be any space left. TeleMetrum and TeleMega can store multiple flights, depending on the configured maximum flight log size. TeleGPS logs - data continuously. TeleMini stores only a single + data continuously. TeleMini v1.0 stores only a single flight, so it will need to be downloaded and erased after each flight to capture data. This only affects on-board flight logging; the altimeter will still diff --git a/doc/altosui.inc b/doc/altosui.inc index 76a24d91..88e7a035 100644 --- a/doc/altosui.inc +++ b/doc/altosui.inc @@ -592,8 +592,8 @@ This reprograms Altus Metrum devices with new firmware. ifdef::telemetrum,telemini[] - TeleMetrum v1.x, TeleDongle v0.2, TeleMini - and TeleBT are all reprogrammed by using another + TeleMetrum v1.x, TeleDongle v0.2, TeleMini v1.0 + and TeleBT v1.0 are all reprogrammed by using another similar unit as a programming dongle (pair programming). endif::telemetrum,telemini[] diff --git a/doc/altusmetrum-docinfo.xml b/doc/altusmetrum-docinfo.xml index e1f4eb62..2475b5f1 100644 --- a/doc/altusmetrum-docinfo.xml +++ b/doc/altusmetrum-docinfo.xml @@ -18,7 +18,7 @@ Towns - 2016 + 2017 Bdale Garbee and Keith Packard @@ -46,6 +46,13 @@ + + 1.7 + 21 Apr 2017 + + Add support for TeleMini v3.0 in firmware, AltosUI and AltosDroid + + 1.6.8 4 Sep 2016 diff --git a/doc/altusmetrum.txt b/doc/altusmetrum.txt index 15fc28fc..48211eb8 100644 --- a/doc/altusmetrum.txt +++ b/doc/altusmetrum.txt @@ -22,7 +22,7 @@ include::telemetrum.raw[] - include::telemini-v1.0.raw[] + include::telemini.raw[] include::easymini-device.raw[] diff --git a/doc/fix-html b/doc/fix-html new file mode 100755 index 00000000..d8751e4d --- /dev/null +++ b/doc/fix-html @@ -0,0 +1,4 @@ +#!/bin/sh +sed -i \ +-e 's/<[?]xml [^>]*>//' \ +-e 's/]*>//' "$@" diff --git a/doc/flight-data-recording.inc b/doc/flight-data-recording.inc index 32e44840..39228908 100644 --- a/doc/flight-data-recording.inc +++ b/doc/flight-data-recording.inc @@ -25,6 +25,7 @@ endif::telemetrum[] ifdef::telemini[] |TeleMini v1.0 |2 |5kB |4 + |TeleMini v3.0 |16 |512kB |5 endif::telemini[] ifdef::easymini[] |EasyMini |16 |1MB |10 @@ -44,7 +45,7 @@ Configuration data is also stored in the flash memory on ifdef::telemetrum[TeleMetrum v1.x,] - ifdef::telemini[TeleMini and] + ifdef::telemini[TeleMini v3.0 and] ifdef::easymini[EasyMini.] This consumes 64kB of flash space. This configuration space is not available diff --git a/doc/installation.inc b/doc/installation.inc index d390551e..273b435b 100644 --- a/doc/installation.inc +++ b/doc/installation.inc @@ -6,7 +6,6 @@ apogee and main ejection charges. All Altus Metrum products are designed for use with single-cell batteries with 3.7 volts nominal. - ifdef::telemini[TeleMini v2.0 and] EasyMini may also be used with other batteries as long as they supply between 4 and 12 volts. diff --git a/doc/intro.inc b/doc/intro.inc index 28daa41a..6b0cd318 100644 --- a/doc/intro.inc +++ b/doc/intro.inc @@ -17,9 +17,9 @@ Our second device was TeleMini, a dual deploy altimeter with radio telemetry and radio direction finding. The first version of this device was only 13mm by 38mm (½ inch by 1½ inches) and - could fit easily in an 18mm air-frame. The latest version, v2.0, - includes a beeper, USB data download and extended on-board - flight logging, along with an improved barometric sensor. + could fit easily in an 18mm air-frame. The latest version, v3.0, + includes a beeper, higher power radio, extended on-board + flight logging and an improved barometric sensor. TeleMega is our most sophisticated device, including six pyro channels (four of which are fully programmable), integrated GPS, diff --git a/doc/release-notes-1.7.inc b/doc/release-notes-1.7.inc new file mode 100644 index 00000000..f2da71f3 --- /dev/null +++ b/doc/release-notes-1.7.inc @@ -0,0 +1,25 @@ += Release Notes for Version 1.7 +:toc!: +:doctype: article + + Version 1.7 includes support for our new TeleMini v3.0 + flight computer and bug fixes in in the flight software for all our boards + and ground station interfaces. + + == AltOS + + AltOS New Features + + * Add support for TeleMini v3.0 boards. + + AltOS Fixes + + * Fix interrupt priorities on STM32L processors. Run timer + interrupt at lowest priority so that device interrupts get + serviced first. + + == AltosUI and TeleGPS Applications + + AltosUI New Features + + * Add support for TeleMini v3.0 hardware diff --git a/doc/release-notes.inc b/doc/release-notes.inc index 7cd075f6..86ce95d3 100644 --- a/doc/release-notes.inc +++ b/doc/release-notes.inc @@ -1,6 +1,10 @@ [appendix] == Release Notes + :leveloffset: 2 + include::release-notes-1.7.raw[] + + <<<< :leveloffset: 2 include::release-notes-1.6.8.raw[] diff --git a/doc/specs.inc b/doc/specs.inc index c335b081..f09d6fc9 100644 --- a/doc/specs.inc +++ b/doc/specs.inc @@ -57,6 +57,14 @@ |10mW |3.7V + |TeleMini v3.0 + |MS5607 30km (100k') + |- + |- + |- + |512kB + |40mW + |3.7V endif::telemini[] ifdef::easymini[] diff --git a/doc/system-operation.inc b/doc/system-operation.inc index e68b2acb..17dfdf89 100644 --- a/doc/system-operation.inc +++ b/doc/system-operation.inc @@ -25,8 +25,9 @@ is selected if the board is connected via USB to a computer, otherwise the board enters “flight” mode. ifdef::telemini[] - TeleMini v1.0 - selects “idle” mode if it receives a command packet within the + TeleMini + selects “idle” mode if it receives a command packet + within the first five seconds of operation. endif::telemini[] @@ -60,7 +61,7 @@ mode for requests sent via TeleDongle. Commands can be issued in idle mode over either USB or the radio link equivalently. - ifdef::telemini[TeleMini v1.0 only has the radio link.] + ifdef::telemini[TeleMini only has the radio link.] endif::radio[] Idle mode is useful for configuring the altimeter, for extracting data from the on-board storage chip after @@ -97,11 +98,13 @@ endif::telemetrum,telemega,easymega[] ifdef::telemini[] - TeleMini v1.0 is configured solely via the radio link. Of course, that + TeleMini is configured solely via the radio link. Of course, that means you need to know the TeleMini radio configuration values or you won't be able to communicate with it. For situations - when you don't have the radio configuration values, TeleMini v1.0 - offers an 'emergency recovery' mode. In this mode, TeleMini is + when you don't have the radio configuration values, + TeleMini v1.0 + offers an 'emergency recovery' mode. In this mode, + TeleMini v1.0 is configured as follows: @@ -154,7 +157,7 @@ Any operation which can be performed with a flight computer can either be done with the device directly connected to the computer via the USB cable, or through the radio - link. TeleMini v1.0 doesn't provide a USB connector and so it is + link. TeleMini doesn't provide a USB connector and so it is always communicated with over radio. Select the appropriate TeleDongle device when the list of devices is presented and AltosUI will interact with an altimeter over the radio link. diff --git a/doc/telemetry.txt b/doc/telemetry.txt index 36d2edba..d7399b6a 100644 --- a/doc/telemetry.txt +++ b/doc/telemetry.txt @@ -44,18 +44,18 @@ which device has transmitted the packet, when it was transmitted and what the rest of the packet contains. - === TeleMetrum v1.x, TeleMini and TeleNano Sensor Data + === TeleMetrum v1.x, TeleMini v1.0 and TeleNano Sensor Data .Sensor Packet Type [options="border",cols="1,3"] |==== |Type |Description |0x01 |TeleMetrum v1.x Sensor Data - |0x02 |TeleMini Sensor Data + |0x02 |TeleMini v1.0 Sensor Data |0x03 |TeleNano Sensor Data |==== - TeleMetrum v1.x, TeleMini and TeleNano share this same + TeleMetrum v1.x, TeleMini v1.0 and TeleNano share this same packet format for sensor data. Each uses a distinct packet type so that the receiver knows which data values are valid and which are undefined. @@ -213,6 +213,41 @@ |32 |==== + === TeleMini v3.0 Sensor Data + + .Sensor Packet Type + [options="border",cols="1,3"] + |==== + |Type |Description + |0x11 |TeleMini v3.0 Sensor Data + |==== + + TeleMini v3.0 uses this + packet format for sensor data. + + Sensor Data packets are transmitted once per second on + the ground, 10 times per second during ascent and once + per second during descent and landing + + .Sensor Packet Contents + [options="border",cols="2,3,3,9"] + |==== + |Offset |Data Type |Name |Description + |5 |uint8_t |state |Flight state + |6 |int16_t |v_batt |battery voltage + |8 |int16_t |sense_a |apogee continuity sense + |10 |int16_t |sense_m |main continuity sense + |12 |int32_t |pres |pressure sensor (Pa * 10) + |16 |int16_t |temp |temperature sensor (°C * 100) + |18 |int16_t |acceleration |m/s² * 16 + |20 |int16_t |speed |m/s * 16 + |22 |int16_t |height |m + |24 |int16_t |ground_pres |Average barometer reading on ground + |28 |pad[4] |pad bytes | + |32 + |==== + + === Configuration Data .Configuration Packet Type diff --git a/doc/telemini-outline.txt b/doc/telemini-outline.txt deleted file mode 100644 index 1992adf0..00000000 --- a/doc/telemini-outline.txt +++ /dev/null @@ -1,9 +0,0 @@ -= TeleMini Outline and Hole Pattern -:doctype: article - - This image, when printed, provides a precise template for the - mounting holes in TeleMini. TeleMini has overall dimensions of - 0.500 x 1.500 inches, and the mounting holes are sized for use - with 2-56 or M2 screws. - - image::telemini.svg[align="center"] diff --git a/doc/telemini-v1-outline.txt b/doc/telemini-v1-outline.txt new file mode 100644 index 00000000..bce3f651 --- /dev/null +++ b/doc/telemini-v1-outline.txt @@ -0,0 +1,10 @@ += TeleMini v1 Outline and Hole Pattern +:doctype: article + + This image, when printed, provides a precise template for the + mounting holes in TeleMini. TeleMini v1 has overall dimensions of + 0.500 x 1.500 inches, and the mounting holes are sized for use + with 2-56 or M2 screws. The holes are located 0.100 inches + from the edge of the board in both directions. + + image::telemini-v1.svg[align="center"] diff --git a/doc/telemini-v1.0.inc b/doc/telemini-v1.0.inc deleted file mode 100644 index e0d674f6..00000000 --- a/doc/telemini-v1.0.inc +++ /dev/null @@ -1,93 +0,0 @@ -== TeleMini v1.0 - - .TeleMini v1.0 Board - image::telemini-v1-top.jpg[width="5.5in"] - - TeleMini v1.0 is ½ inches by 1½ inches. It was - designed to fit inside an 18mm air-frame tube, but using it in - a tube that small in diameter may require some creativity in - mounting and wiring to succeed! Since there is no - accelerometer, TeleMini can be mounted in any convenient - orientation. The default ¼ wave UHF wire antenna attached to - the center of one end of the board is about 7 inches long. Two - wires for the power switch are connected to holes in the - middle of the board. Screw terminals for the e-matches for - apogee and main ejection charges depart from the other end of - the board, meaning an ideal “simple” avionics bay for TeleMini - should have at least 9 inches of interior length. - - === TeleMini v1.0 Screw Terminals - - TeleMini v1.0 has four screw terminals on the end of the - board opposite the telemetry antenna. Two are for the apogee - and two are for main igniter circuits. There are also wires - soldered to the board for the power switch. Using the - picture above and starting from the top for the terminals - and from the left for the power switch wires, the - connections are as follows: - - .TeleMini v1.0 Screw Terminals - [options="header",grid="all",cols="2,3,10"] - |==== - |Terminal #|Terminal Name|Description - - |1 - |Apogee - - |Apogee pyro channel connection to pyro circuit - - |2 - |Apogee + - |Apogee pyro channel common connection to battery + - - |3 - |Main - - |Main pyro channel connection to pyro circuit - - |4 - |Main + - |Main pyro channel common connection to battery + - - |Left - |Switch Output - |Switch connection to flight computer - - |Right - |Switch Input - |Switch connection to positive battery terminal - |==== - - === Using a Separate Pyro Battery with TeleMini v1.0 - - As described above, using an external pyro battery involves - connecting the negative battery terminal to the flight - computer ground, connecting the positive battery terminal to - one of the igniter leads and connecting the other igniter - lead to the per-channel pyro circuit connection. Because - there is no solid ground connection to use on TeleMini, this - is not recommended. - - The only available ground connection on TeleMini v1.0 are - the two mounting holes next to the telemetry - antenna. Somehow connect a small piece of wire to one of - those holes and hook it to the negative pyro battery terminal. - - Connecting the positive battery terminal to the pyro - charges must be done separate from TeleMini v1.0, by soldering - them together or using some other connector. - - The other lead from each pyro charge is then inserted into - the appropriate per-pyro channel screw terminal (terminal 3 for the - Main charge, terminal 1 for the Apogee charge). - - === Using an Active Switch with TeleMini v1.0 - - As explained above, an external active switch requires three - connections, one to the positive battery terminal, one to - the flight computer positive input and one to ground. Again, - because TeleMini doesn't have any good ground connection, - this is not recommended. - - The positive battery terminal is available on the Right - power switch wire, the positive flight computer input is on - the left power switch wire. Hook a lead to either of the - mounting holes for a ground connection. diff --git a/doc/telemini-v1.svg b/doc/telemini-v1.svg new file mode 100644 index 00000000..b2e21e3d --- /dev/null +++ b/doc/telemini-v1.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + TeleMini + + UP + + + \ No newline at end of file diff --git a/doc/telemini-v3-outline.txt b/doc/telemini-v3-outline.txt new file mode 100644 index 00000000..bb26ed6e --- /dev/null +++ b/doc/telemini-v3-outline.txt @@ -0,0 +1,10 @@ += TeleMini v3 Outline and Hole Pattern +:doctype: article + + This image, when printed, provides a precise template for the + mounting holes in TeleMini v3. TeleMini v3 has overall dimensions of + 0.500 x 1.670 inches, and the mounting holes are sized for use + with 2-56 or M2 screws. The holes are located 0.085 inches + from the edge of the board in both directions. + + image::telemini-v3.svg[align="center"] diff --git a/doc/telemini-v3.0-bottom.jpg b/doc/telemini-v3.0-bottom.jpg new file mode 100644 index 00000000..e4e4744b Binary files /dev/null and b/doc/telemini-v3.0-bottom.jpg differ diff --git a/doc/telemini-v3.0-top.jpg b/doc/telemini-v3.0-top.jpg new file mode 100644 index 00000000..1539902d Binary files /dev/null and b/doc/telemini-v3.0-top.jpg differ diff --git a/doc/telemini-v3.svg b/doc/telemini-v3.svg new file mode 100644 index 00000000..8835a2b2 --- /dev/null +++ b/doc/telemini-v3.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + TeleMini v3 + + UP + + + diff --git a/doc/telemini.inc b/doc/telemini.inc new file mode 100644 index 00000000..b40582a2 --- /dev/null +++ b/doc/telemini.inc @@ -0,0 +1,106 @@ +== TeleMini + + .TeleMini v3 Board + image::telemini-v3.0-top.jpg[width="5.5in"] + image::telemini-v3.0-bottom.jpg[width="5.5in"] + + TeleMini v3 is 0.5 inches by 1.67 inches. It was + designed to fit inside an 18mm air-frame tube, but using it in + a tube that small in diameter may require some creativity in + mounting and wiring to succeed! Since there is no + accelerometer, TeleMini can be mounted in any convenient + orientation. The default ¼ wave UHF wire antenna attached to + the center of one end of the board is about 7 inches long. Screw + terminals for the power switch are located in the + middle of the board. Screw terminals for the e-matches for + apogee and main ejection charges depart from the other end of + the board, meaning an ideal “simple” avionics bay for TeleMini + should have at least 9 inches of interior length. + + === TeleMini v3 Screw Terminals + + TeleMini v3 has four screw terminals on the end of the + board opposite the telemetry antenna. Two are for the apogee + and two are for main igniter circuits. Another two + screw terminals are located in the middle of the board + for the power switch. Using the + picture above and starting from the top for the pyro terminals + and from the left for the power switch terminals, the + connections are as follows: + + .TeleMini v3 Screw Terminals + [options="header",grid="all",cols="2,3,10"] + |==== + |Terminal #|Terminal Name|Description + + |1 + |Apogee - + |Apogee pyro channel connection to pyro circuit + + |2 + |Apogee + + |Apogee pyro channel common connection to battery + + + |3 + |Main - + |Main pyro channel connection to pyro circuit + + |4 + |Main + + |Main pyro channel common connection to battery + + + |Left + |Switch Output + |Switch connection to flight computer + + |Right + |Switch Input + |Switch connection to positive battery terminal + |==== + + === Using a Separate Pyro Battery with TeleMini v3 + + As described above, using an external pyro battery involves + connecting the negative battery terminal to the flight + computer ground, connecting the positive battery terminal to + one of the igniter leads and connecting the other igniter + lead to the per-channel pyro circuit connection. Because + there is no solid ground connection to use on TeleMini, this + is not recommended. + + The only available ground connection on TeleMini v3 are + the two mounting holes next to the telemetry + antenna. Somehow connect a small piece of wire to one of + those holes and hook it to the negative pyro battery terminal. + + Connecting the positive battery terminal to the pyro + charges must be done separate from TeleMini v3, by soldering + them together or using some other connector. + + The other lead from each pyro charge is then inserted into + the appropriate per-pyro channel screw terminal (terminal 3 for the + Main charge, terminal 1 for the Apogee charge). + + === Using an Active Switch with TeleMini v3 + + As explained above, an external active switch requires three + connections, one to the positive battery terminal, one to + the flight computer positive input and one to ground. Again, + because TeleMini doesn't have any good ground connection, + this is not recommended. + + The positive battery terminal is available on the Right + power switch wire, the positive flight computer input is on + the left power switch wire. Hook a lead to either of the + mounting holes for a ground connection. + + === TeleMini v1 + + TeleMini v1 is the earlier version of this product. It + has a lower-power radio, less storage, no beeper and + soldered-in wires instead of screw terminals for the + power switch. + + .TeleMini v1 Board + image::telemini-v1-top.jpg[width="5.5in"] + diff --git a/doc/telemini.svg b/doc/telemini.svg deleted file mode 100644 index b2e21e3d..00000000 --- a/doc/telemini.svg +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - TeleMini - - UP - - - \ No newline at end of file diff --git a/doc/updating-firmware.inc b/doc/updating-firmware.inc index 11ea1283..91aa58f2 100644 --- a/doc/updating-firmware.inc +++ b/doc/updating-firmware.inc @@ -11,7 +11,7 @@ programmed directly over their USB connectors (self programming). ifdef::telemega[] - TeleMetrum v1, TeleMini and TeleDongle v0.2 are + TeleMetrum v1, TeleMini v1.0 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. @@ -228,10 +228,10 @@ If something goes wrong, give it another try. - ==== Updating TeleMini Firmware + ==== Updating TeleMini v1.0 Firmware You'll need a special 'programming cable' to - reprogram the TeleMini. You can make your own + reprogram the TeleMini v1.0. You can make your own using an 8-pin MicroMaTch connector on one end and a set of four pins on the other. @@ -242,19 +242,19 @@ . Plug the 8-pin end of the programming cable to the matching connector on the TeleDongle v0.2 or TeleBT v1.0, and the 4-pins into the - holes in the TeleMini circuit board. Note + holes in the TeleMini v1.0 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 that pin 1 on the - TeleMini board is marked with a square pad + TeleMini v1.0 board is marked with a square pad while the other pins have round pads. - . Attach a battery to the TeleMini board. + . Attach a battery to the TeleMini v1.0 board. . Plug the TeleDongle v0.2 or TeleBT v1.0 into your computer's USB port, and power up the - TeleMini + TeleMini v1.0 . Run AltosUI, and select 'Flash Image' from the File menu. @@ -264,7 +264,7 @@ programming device. . Select the image you want put on the - TeleMini, which should have a name in the + TeleMini v1.0, which should have a name in the form telemini-v1.0-1.0.0.ihx. It should be visible in the default directory, if not you may have to poke around your system to find @@ -276,10 +276,10 @@ you'll need to change them. . Hit the 'OK' button and the software should - proceed to flash the TeleMini with new + proceed to flash the TeleMini v1.0 with new firmware, showing a progress bar. - . Confirm that the TeleMini board seems to + . Confirm that the TeleMini v1.0 board seems to have updated OK, which you can do by configuring it over the radio link through the TeleDongle, or letting it come up in @@ -290,7 +290,7 @@ ==== Updating TeleDongle v0.2 Firmware Updating TeleDongle v0.2 firmware is just like - updating TeleMetrum v1.x or TeleMini firmware, but you + updating TeleMetrum v1.x or TeleMini v1.0 firmware, but you use either a TeleMetrum v1.x, TeleDongle v0.2 or TeleBT v1.0 as the programmer. diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c index cca2a971..fde3c421 100644 --- a/src/avr/ao_avr_stdio.c +++ b/src/avr/ao_avr_stdio.c @@ -21,6 +21,7 @@ int stdio_put(char c, FILE *stream) { + (void) stream; putchar(c); return 0; } @@ -28,6 +29,7 @@ stdio_put(char c, FILE *stream) int stdio_get(FILE *stream) { + (void) stream; return (int) getchar() & 0xff; } diff --git a/src/cc1111/ao_launch.c b/src/cc1111/ao_launch.c index 4f0a0c14..76d6d13b 100644 --- a/src/cc1111/ao_launch.c +++ b/src/cc1111/ao_launch.c @@ -17,6 +17,7 @@ */ #include +#include #include __xdata uint16_t ao_launch_ignite; diff --git a/src/cc1111/ao_launch.h b/src/cc1111/ao_launch.h new file mode 100644 index 00000000..966b5cea --- /dev/null +++ b/src/cc1111/ao_launch.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#ifndef _AO_LAUNCH_H_ +#define _AO_LAUNCH_H_ +/* ao_launch.c */ + +struct ao_launch_command { + uint16_t tick; + uint16_t serial; + uint8_t cmd; + uint8_t channel; + uint16_t unused; +}; + +#define AO_LAUNCH_QUERY 1 + +struct ao_launch_query { + uint16_t tick; + uint16_t serial; + uint8_t channel; + uint8_t valid; + uint8_t arm_status; + uint8_t igniter_status; +}; + +#define AO_LAUNCH_ARM 2 +#define AO_LAUNCH_FIRE 3 + +void +ao_launch_init(void); + +#endif /* _AO_LAUNCH_H_ */ diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index 0acef562..a3d454da 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -62,7 +62,7 @@ ao_timer_init(void) /* NOTE: This uses a timer only present on cc1111 architecture. */ /* disable timer 1 */ - T1CTL = 0; +/* T1CTL = 0; */ /* set the sample rate */ T1CC0H = T1_SAMPLE_TIME >> 8; diff --git a/src/chaoskey-v1.0/.gitignore b/src/chaoskey-v1.0/.gitignore index b0adba26..9fd59154 100644 --- a/src/chaoskey-v1.0/.gitignore +++ b/src/chaoskey-v1.0/.gitignore @@ -1,2 +1,3 @@ ao_product.h chaoskey-* +*.cab diff --git a/src/chaoskey-v1.0/Makefile b/src/chaoskey-v1.0/Makefile index d9944a12..f2c168ba 100644 --- a/src/chaoskey-v1.0/Makefile +++ b/src/chaoskey-v1.0/Makefile @@ -14,6 +14,7 @@ INC = \ ao_task.h \ ao_adc_fast.h \ ao_power.h \ + ao_crc.h \ stm32f0.h # @@ -38,6 +39,8 @@ ALTOS_SRC = \ ao_gpio.c \ ao_product.c +VENDOR=AltusMetrum +PROJECT_NAME=ChaosKey PRODUCT=ChaosKey-hw-1.0-sw-$(VERSION) PRODUCT_DEF=-DCHAOSKEY_V_1_0 IDVENDOR=0x1d50 @@ -48,6 +51,7 @@ CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os PROGNAME=chaoskey-v1.0 PROG=$(PROGNAME)-$(VERSION).elf HEX=$(PROGNAME)-$(VERSION).ihx +METAINFO=org.altusmetrum.ChaosKey.metainfo.xml SRC=$(ALTOS_SRC) ao_chaoskey.c OBJ=$(SRC:.c=.o) @@ -62,11 +66,20 @@ ao_product.h: ao-make-product.5c ../Version $(OBJ): $(INC) +%.cab: $(PROG) $(HEX) $(METAINFO) + gcab --create --nopath $@ $(PROG) $(HEX) $(METAINFO) + +cab: $(VENDOR)-$(PROJECT_NAME)-$(VERSION).cab + +check: $(METAINFO) + appstream-util validate-relax $(METAINFO) + distclean: clean clean: rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h + rm -f *.cab install: diff --git a/src/chaoskey-v1.0/chaoskey-connector.svg b/src/chaoskey-v1.0/chaoskey-connector.svg new file mode 100644 index 00000000..671a46bd --- /dev/null +++ b/src/chaoskey-v1.0/chaoskey-connector.svg @@ -0,0 +1,274 @@ + + + + + + + + image/svg+xml + + Gnome Symbolic Icon Theme + + + + + + + Gnome Symbolic Icon Theme + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/chaoskey-v1.0/org.altusmetrum.ChaosKey.metainfo.xml.in b/src/chaoskey-v1.0/org.altusmetrum.ChaosKey.metainfo.xml.in new file mode 100644 index 00000000..6e391878 --- /dev/null +++ b/src/chaoskey-v1.0/org.altusmetrum.ChaosKey.metainfo.xml.in @@ -0,0 +1,46 @@ + + + + org.altusmetrum.ChaosKey.firmware + ChaosKey + Firmware for the Altus Metrum ChaosKey + +

+ Updating the firmware on your ChaosKey device improves performance and adds + new features. +

+
+ + + b62500d7-c981-595b-a798-eb6cf4d4942b + + https://chaoskey.org/ + CC-BY-4.0 + GPL-2.0 + AltusMetrum + + + + +

+ FIXME before release. +

+
+
+ + + +

+ Change the ADC clock speed to eliminate sampling problems which + cleans up the chaoskey raw data. +

+
+
+
+ + + https://chaoskey.org/chaoskey-connector.svg + Remove the plastic cover, then connect pins 1 and 5 whilst inserting into a USB socket. + + +
diff --git a/src/cortexelf-v1/Makefile b/src/cortexelf-v1/Makefile new file mode 100644 index 00000000..8cc6ce31 --- /dev/null +++ b/src/cortexelf-v1/Makefile @@ -0,0 +1,137 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs +LDFLAGS=-L../stm -Wl,-Tcortexelf.ld + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_pins.h \ + ao_kalman.h \ + ao_product.h \ + ao_profile.h \ + ao_task.h \ + math.h \ + ao_mpu.h \ + stm32l.h \ + math.h \ + ao_vga.h \ + ao_draw.h \ + ao_draw_int.h \ + ao_font.h \ + ao_ps2.h \ + ao_lisp.h \ + ao_lisp_const.h \ + ao_lisp_os.h \ + ao_flip_bits.h \ + Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_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_task.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_serial_stm.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_i2c_stm.c \ + ao_as1107.c \ + ao_matrix.c \ + ao_vga.c \ + ao_blt.c \ + ao_copy.c \ + ao_rect.c \ + ao_text.c \ + ao_line.c \ + ao_ps2.c \ + ao_console.c \ + ao_sdcard.c \ + ao_bufio.c \ + ao_fat.c \ + ao_flash_stm.c \ + ao_button.c \ + ao_event.c \ + ao_1802.c \ + ao_hex.c \ + ao_lisp_lex.c \ + ao_lisp_mem.c \ + ao_lisp_cons.c \ + ao_lisp_eval.c \ + ao_lisp_string.c \ + ao_lisp_atom.c \ + ao_lisp_int.c \ + ao_lisp_poly.c \ + ao_lisp_builtin.c \ + ao_lisp_read.c \ + ao_lisp_rep.c \ + ao_lisp_frame.c \ + ao_lisp_error.c \ + ao_lisp_lambda.c \ + ao_lisp_save.c \ + ao_lisp_stack.c \ + ao_lisp_os_save.c \ + $(PROFILE) \ + $(SAMPLE_PROFILE) \ + $(STACK_GUARD) + +PRODUCT=CortexELF-v1 +PRODUCT_DEF=-DCORTEXELF +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=cortexelf-v1 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_cortexelf.c +OBJ=$(SRC:.c=.o) + +all:: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) cortexelf.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +../altitude-pa.h: make-altitude-pa + nickle $< > $@ + +$(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 ao_flip_bits.h + +ao_flip_bits.h: ao_flip_bits.5c + nickle ao_flip_bits.5c > $@ + +include ../lisp/Makefile-lisp + +install: + +uninstall: diff --git a/src/cortexelf-v1/ao_1802.c b/src/cortexelf-v1/ao_1802.c new file mode 100644 index 00000000..9fb36595 --- /dev/null +++ b/src/cortexelf-v1/ao_1802.c @@ -0,0 +1,328 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#include +#include +#include +#include + +/* Decoded address driven by TPA/TPB signals */ +uint16_t ADDRESS; + +/* Decoded data, driven by TPB signal */ +uint8_t DATA; + +/* Mux control */ +#define _MUX_1802 0 +#define _MUX_STM 1 + +uint8_t MUX_CONTROL; + +/* Signals muxed between 1802 and STM */ +uint8_t +MRD(void) { + return ao_gpio_get(MRD_PORT, MRD_BIT, MRD_PIN); +} + +void +MRD_set(uint8_t value) { + ao_gpio_set(MRD_PORT, MRD_BIT, MRD_PIN, value); +} + +uint8_t +MWR(void) { + return ao_gpio_get(MWR_PORT, MWR_BIT, MWR_PIN); +} + +void +MWR_set(uint8_t value) { + ao_gpio_set(MWR_PORT, MWR_BIT, MWR_PIN, value); +} + +static void +TPA_rising(void) +{ + ADDRESS = (ADDRESS & 0x00ff) | ((uint16_t) MA() << 8); + ao_wakeup(&ADDRESS); +} + +uint8_t +TPA(void) { + return ao_gpio_get(TPA_PORT, TPA_BIT, TPA_PIN); +} + +void +TPA_set(uint8_t tpa) { + ao_gpio_set(TPA_PORT, TPA_BIT, TPA_PIN, tpa); + if (tpa) + TPA_rising(); +} + +static void +TPB_rising(void) +{ + ADDRESS = (ADDRESS & 0xff00) | MA(); + if (MWR() == 0 || MRD() == 0) + DATA = BUS(); + ao_wakeup(&ADDRESS); +} + +static void +TPB_falling(void) +{ +} + +uint8_t +TPB(void) { + return ao_gpio_get(TPB_PORT, TPB_BIT, TPB_PIN); +} + +void +TPB_set(uint8_t tpb) { + ao_gpio_set(TPB_PORT, TPB_BIT, TPB_PIN, tpb); + if (tpb) + TPB_rising(); + else + TPB_falling(); +} + +uint8_t +MA(void) { + return (ao_gpio_get_all(MA_PORT) >> MA_SHIFT) & MA_MASK; +} + +void +MA_set(uint8_t ma) { + ao_gpio_set_mask(MA_PORT, ((uint16_t) ma) << MA_SHIFT, MA_MASK << MA_SHIFT); +} + +/* Tri-state data bus */ + +uint8_t +BUS(void) { + return ao_flip_bits_8[(ao_gpio_get_all(BUS_PORT) >> BUS_SHIFT) & BUS_MASK]; +} + +void +BUS_set(uint8_t bus) { + ao_gpio_set_mask(BUS_PORT, ao_flip_bits_8[bus] << BUS_SHIFT, BUS_MASK << BUS_SHIFT); +} + +void +BUS_stm(void) +{ + ao_set_output_mask(BUS_PORT, BUS_MASK << BUS_SHIFT); +} + +void +BUS_1802(void) +{ + ao_set_input_mask(BUS_PORT, BUS_MASK << BUS_SHIFT); +} + +/* Pins controlled by 1802 */ +uint8_t +SC(void) { + return ao_flip_bits_2[(ao_gpio_get_all(SC_PORT) >> SC_SHIFT) & SC_MASK]; +} + +uint8_t +Q(void) { + return ao_gpio_get(Q_PORT, Q_BIT, Q_PIN); +} + +uint8_t +N(void) { + return (ao_gpio_get_all(N_PORT) >> N_SHIFT) & N_MASK; +} + +/* Pins controlled by STM */ +uint8_t +EF(void) { + return (ao_gpio_get_all(EF_PORT) >> EF_SHIFT) & EF_MASK; +} + +void +EF_set(uint8_t ef) { + ao_gpio_set_mask(EF_PORT, ef << EF_SHIFT, EF_MASK << EF_SHIFT); +} + +uint8_t +DMA_IN(void) { + return ao_gpio_get(DMA_IN_PORT, DMA_IN_BIT, DMA_IN_PIN); +} + +void +DMA_IN_set(uint8_t dma_in) { + ao_gpio_set(DMA_IN_PORT, DMA_IN_BIT, DMA_IN_PIN, dma_in); +} + +uint8_t +DMA_OUT(void) { + return ao_gpio_get(DMA_OUT_PORT, DMA_OUT_BIT, DMA_OUT_PIN); +} + +void +DMA_OUT_set(uint8_t dma_out) { + ao_gpio_set(DMA_OUT_PORT, DMA_OUT_BIT, DMA_OUT_PIN, dma_out); +} + +uint8_t +INT(void) { + return ao_gpio_get(INT_PORT, INT_BIT, INT_PIN); +} + +void +INT_set(uint8_t dma_out) { + ao_gpio_set(INT_PORT, INT_BIT, INT_PIN, dma_out); +} + +uint8_t +CLEAR(void) { + return ao_gpio_get(CLEAR_PORT, CLEAR_BIT, CLEAR_PIN); +} + +void +CLEAR_set(uint8_t dma_out) { + ao_gpio_set(CLEAR_PORT, CLEAR_BIT, CLEAR_PIN, dma_out); +} + +uint8_t +WAIT(void) { + return ao_gpio_get(WAIT_PORT, WAIT_BIT, WAIT_PIN); +} + +void +WAIT_set(uint8_t dma_out) { + ao_gpio_set(WAIT_PORT, WAIT_BIT, WAIT_PIN, dma_out); +} + +void +tpb_isr(void) { + /* Latch low address and data on rising edge of TPB */ + if (TPB()) + TPB_rising(); + else + TPB_falling(); +} + +void +tpa_isr(void) { + /* Latch high address on rising edge of TPA */ + if (TPA()) + TPA_rising(); +} + +#define ao_1802_in(port, bit, mode) do { \ + ao_gpio_set_mode(port, bit, mode); \ + ao_set_input(port, bit); \ + } while (0) + +#define ao_1802_in_isr(port, bit, mode) do { \ + ao_gpio_set_mode(port, bit, mode); \ + ao_set_input(port, bit); \ + ao_exti_enable(port, bit); \ + } while (0) + +#define ao_1802_out_isr(port, bit) do { \ + ao_exti_disable(port, bit); \ + ao_set_output(port, bit); \ + } while (0) + +void +MUX_1802(void) +{ + if (MUX_CONTROL != _MUX_1802) { + /* Set pins to input, but pulled to idle value */ + ao_1802_in(MRD_PORT, MRD_BIT, AO_EXTI_MODE_PULL_UP); + ao_1802_in(MWR_PORT, MWR_BIT, AO_EXTI_MODE_PULL_UP); + ao_1802_in_isr(TPB_PORT, TPB_BIT, AO_EXTI_MODE_PULL_DOWN); + ao_1802_in_isr(TPA_PORT, TPA_BIT, AO_EXTI_MODE_PULL_DOWN); + ao_set_input_mask(MA_PORT, MA_MASK << MA_SHIFT); + + ao_gpio_set(MUX_PORT, MUX_BIT, MUX_PIN, 0); + + /* Now change the pins to eliminate the pull up/down */ + ao_gpio_set_mode(MRD_PORT, MRD_BIT, 0); + ao_gpio_set_mode(MWR_PORT, MWR_BIT, 0); + ao_gpio_set_mode(TPB_PORT, TPB_BIT, 0); + ao_gpio_set_mode(TPA_PORT, TPA_BIT, 0); + + MUX_CONTROL = _MUX_1802; + } +} + +void +MUX_stm(void) +{ + if (MUX_CONTROL != _MUX_STM) { + /* Set the pins back to pull to the idle value */ + ao_gpio_set_mode(MRD_PORT, MRD_BIT, AO_EXTI_MODE_PULL_UP); + ao_gpio_set_mode(MWR_PORT, MWR_BIT, AO_EXTI_MODE_PULL_UP); + ao_gpio_set_mode(TPB_PORT, TPB_BIT, AO_EXTI_MODE_PULL_DOWN); + ao_gpio_set_mode(TPA_PORT, TPA_BIT, AO_EXTI_MODE_PULL_DOWN); + + ao_gpio_set(MUX_PORT, MUX_BIT, MUX_PIN, 1); + + /* Now set the pins as output, driven to the idle value */ + ao_set_output(MRD_PORT, MRD_BIT, MRD_PIN, 1); + ao_set_output(MWR_PORT, MWR_BIT, MWR_PIN, 1); + ao_set_output(TPB_PORT, TPB_BIT, TPB_PIN, 0); + ao_set_output(TPA_PORT, TPA_BIT, TPA_PIN, 0); + ao_set_output_mask(MA_PORT, MA_MASK << MA_SHIFT); + MUX_CONTROL = _MUX_STM; + } +} + +void +ao_1802_init(void) +{ + /* Multiplexed signals*/ + + /* active low signals */ + ao_enable_input(MRD_PORT, MRD_BIT, AO_EXTI_MODE_PULL_UP); + ao_enable_input(MWR_PORT, MWR_BIT, AO_EXTI_MODE_PULL_UP); + + /* active high signals with interrupts */ + ao_exti_setup(TPA_PORT, TPA_BIT, + AO_EXTI_MODE_PULL_DOWN | AO_EXTI_MODE_RISING | AO_EXTI_MODE_FALLING, + tpa_isr); + ao_exti_setup(TPB_PORT, TPB_BIT, + AO_EXTI_MODE_PULL_DOWN | AO_EXTI_MODE_RISING | AO_EXTI_MODE_FALLING, + tpb_isr); + + /* multiplexed address bus */ + ao_enable_input_mask(MA_PORT, MA_MASK << MA_SHIFT, 0); + + /* Data bus */ + + ao_enable_input_mask(BUS_PORT, BUS_MASK << BUS_SHIFT, 0); + + /* Pins controlled by 1802 */ + ao_enable_input_mask(SC_PORT, SC_MASK << SC_SHIFT, 0); + ao_enable_input(Q_PORT, Q_BIT, 0); + ao_enable_input_mask(N_PORT, N_MASK << N_SHIFT, 0); + + /* Pins controlled by STM */ + ao_enable_output_mask(EF_PORT, 0, EF_MASK << EF_SHIFT); + ao_enable_output(DMA_IN_PORT, DMA_IN_BIT, DMA_IN_PIN, 1); + ao_enable_output(DMA_OUT_PORT, DMA_OUT_BIT, DMA_OUT_PIN, 1); + ao_enable_output(INT_PORT, INT_BIT, INT_PIN, 1); + ao_enable_output(CLEAR_PORT, CLEAR_BIT, CLEAR_PIN, 1); + ao_enable_output(WAIT_PORT, WAIT_BIT, WAIT_PIN, 1); + + /* Force configuration to STM so that MUX_1802 will do something */ + MUX_CONTROL = _MUX_STM; + MUX_1802(); +} diff --git a/src/cortexelf-v1/ao_1802.h b/src/cortexelf-v1/ao_1802.h new file mode 100644 index 00000000..5ea89fee --- /dev/null +++ b/src/cortexelf-v1/ao_1802.h @@ -0,0 +1,129 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#ifndef _AO_1802_H_ +#define _AO_1802_H_ + +/* Decoded address driven by TPA/TPB signals */ +extern uint16_t ADDRESS; + +/* Decoded data, driven by TPB signal */ +extern uint8_t DATA; + +uint8_t +MRD(void); + +void +MRD_set(uint8_t value); + +uint8_t +MWR(void); + +void +MWR_set(uint8_t value); + +uint8_t +TPA(void); + +void +TPA_set(uint8_t tpa); + +uint8_t +TPB(void); + +void +TPB_set(uint8_t tpb); + +uint8_t +MA(void); + +void +MA_set(uint8_t ma); + +/* Tri-state data bus */ + +uint8_t +BUS(void); + +void +BUS_set(uint8_t bus); + +void +BUS_stm(void); + +void +BUS_1802(void); + +/* Pins controlled by 1802 */ +uint8_t +SC(void); + +uint8_t +Q(void); + +uint8_t +N(void); + +/* Pins controlled by STM */ +uint8_t +EF(void); + +void +EF_set(uint8_t ef); + +uint8_t +DMA_IN(void); + +void +DMA_IN_set(uint8_t dma_in); + +uint8_t +DMA_OUT(void); + +void +DMA_OUT_set(uint8_t dma_out); + +uint8_t +INT(void); + +void +INT_set(uint8_t dma_out); + +uint8_t +CLEAR(void); + +void +CLEAR_set(uint8_t dma_out); + +uint8_t +WAIT(void); + +void +WAIT_set(uint8_t dma_out); + +#define SC_FETCH 0 +#define SC_EXECUTE 1 +#define SC_DMA 2 +#define SC_INTERRUPT 3 + +void +MUX_1802(void); + +void +MUX_stm(void); + +void +ao_1802_init(void); + +#endif /* _AO_1802_H_ */ diff --git a/src/cortexelf-v1/ao_cortexelf.c b/src/cortexelf-v1/ao_cortexelf.c new file mode 100644 index 00000000..61a9d219 --- /dev/null +++ b/src/cortexelf-v1/ao_cortexelf.c @@ -0,0 +1,291 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +#include +#include +#include +#if HAS_STACK_GUARD +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ao_task ball_task; + +#define BALL_WIDTH 5 +#define BALL_HEIGHT 5 + +static int ball_x; +static int ball_y; +static int ball_dx, ball_dy; + +uint8_t ball_enable; + +void +ao_ball(void) +{ + ball_dx = 1; + ball_dy = 1; + ball_x = 0; + ball_y = 0; + for (;;) { + while (!ball_enable) + ao_sleep(&ball_enable); + for (;;) { + ao_line(&ao_vga_bitmap, + -100, -100, ball_x*2, ball_y*2, + 1, AO_XOR); + ao_text(&ao_vga_bitmap, + ball_x, ball_y - 10, + "Hello, Bdale!", + 1, AO_XOR); + ao_rect(&ao_vga_bitmap, + ball_x, ball_y, + BALL_WIDTH, + BALL_HEIGHT, + 1, + AO_XOR); + ao_delay(AO_MS_TO_TICKS(10)); + ao_rect(&ao_vga_bitmap, + ball_x, ball_y, + BALL_WIDTH, + BALL_HEIGHT, + 1, + AO_XOR); + ao_text(&ao_vga_bitmap, + ball_x, ball_y - 10, + "Hello, Bdale!", + 1, AO_XOR); + ao_line(&ao_vga_bitmap, + -100, -100, ball_x*2, ball_y*2, + 1, AO_XOR); + if (!ball_enable) + break; + ball_x += ball_dx; + ball_y += ball_dy; + if (ball_x + BALL_WIDTH > AO_VGA_WIDTH) { + ball_x = AO_VGA_WIDTH - BALL_WIDTH; + ball_dx = -ball_dx; + } + if (ball_x < 0) { + ball_x = -ball_x; + ball_dx = -ball_dx; + } + if (ball_y + BALL_HEIGHT > AO_VGA_HEIGHT) { + ball_y = AO_VGA_HEIGHT - BALL_HEIGHT; + ball_dy = -ball_dy; + } + if (ball_y < 0) { + ball_y = -ball_y; + ball_dy = -ball_dy; + } + } + } +} + +static void +ao_fb_init(void) +{ + ao_rect(&ao_vga_bitmap, + 0, 0, AO_VGA_WIDTH, AO_VGA_HEIGHT, + 1, AO_COPY); + + ao_rect(&ao_vga_bitmap, + 10, 10, 10, 10, + 0, AO_COPY); + + ao_rect(&ao_vga_bitmap, + AO_VGA_WIDTH - 20, 10, 10, 10, + 0, AO_COPY); + + ao_rect(&ao_vga_bitmap, + 10, AO_VGA_HEIGHT - 20, 10, 10, + 0, AO_COPY); + + ao_rect(&ao_vga_bitmap, + AO_VGA_WIDTH - 20, AO_VGA_HEIGHT - 20, 10, 10, + 0, AO_COPY); + + ao_text(&ao_vga_bitmap, + 20, 100, + "Hello, Bdale!", + 0, AO_COPY); + + ao_text(&ao_vga_bitmap, + 1, ao_font.ascent, + "UL", + 0, AO_COPY); + + ao_text(&ao_vga_bitmap, + 1, AO_VGA_HEIGHT - ao_font.descent, + "BL", + 0, AO_COPY); +} + +static void +ao_video_toggle(void) +{ + ao_cmd_decimal(); + if (ao_cmd_lex_i) + ao_fb_init(); + ao_vga_enable(ao_cmd_lex_i); +} + +static void +ao_ball_toggle(void) +{ + ao_cmd_decimal(); + ball_enable = ao_cmd_lex_i; + ao_wakeup(&ball_enable); +} + +static void +ao_ps2_read_keys(void) +{ + char c; + + for (;;) { + c = ao_ps2_getchar(); + printf("%02x %c\n", c, ' ' <= c && c < 0x7f ? c : '.'); + flush(); + if (c == ' ') + break; + } +} + +static void +ao_console_send(void) +{ + char c; + + while ((c = getchar()) != '~') { + ao_console_putchar(c); + flush(); + } +} + +static void lisp_cmd() { + ao_lisp_read_eval_print(); +} + +static void +ao_serial_blather(void) +{ + char c; + + while ((c = getchar()) != '~') { + ao_serial1_putchar(c); + ao_serial2_putchar(c); + } +} + +static void +led_cmd(void) +{ + uint8_t start; + uint8_t value; + ao_cmd_decimal(); + + start = ao_cmd_lex_i; + ao_cmd_hex(); + value = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + ao_as1107_write_8(start, value); +} + +__code struct ao_cmds ao_demo_cmds[] = { + { ao_video_toggle, "V\0Toggle video" }, + { ao_ball_toggle, "B\0Toggle ball" }, + { ao_ps2_read_keys, "K\0Read keys from keyboard" }, + { ao_console_send, "C\0Send data to console, end with ~" }, + { ao_serial_blather, "S\0Blather on serial ports briefly" }, + { lisp_cmd, "l\0Run lisp interpreter" }, + { led_cmd, "L start value\0Show value (byte) at digit start" }, + { 0, NULL } +}; + +static struct ao_task event_task; + +static void +ao_event_loop(void) +{ + for (;;) { + struct ao_event ev; + + ao_event_get(&ev); + printf("type %d uint %d tick %d value %d\n", + ev.type, ev.unit, ev.tick, ev.value); + flush(); + } +} + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_serial_init(); + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_sdcard_init(); + ao_fat_init(); + + ao_ps2_init(); + ao_vga_init(); + ao_console_init(); + + ao_cmd_init(); + + ao_usb_init(); + + ao_button_init(); + + ao_as1107_init(); + ao_matrix_init(); + ao_1802_init(); + + ao_hex_init(); + + ao_config_init(); + + ao_add_task(&ball_task, ao_ball, "ball"); + ao_add_task(&event_task, ao_event_loop, "events"); + ao_cmd_register(&ao_demo_cmds[0]); + + ao_start_scheduler(); + return 0; +} diff --git a/src/cortexelf-v1/ao_flip_bits.5c b/src/cortexelf-v1/ao_flip_bits.5c new file mode 100644 index 00000000..cd5507cc --- /dev/null +++ b/src/cortexelf-v1/ao_flip_bits.5c @@ -0,0 +1,24 @@ +#!/usr/bin/nickle + +int flip_bits(int a, int n) +{ + int result = 0; + for (int pos = 0; pos < n; pos++) + if ((a & (1 << pos)) != 0) + result |= (1 << (n - 1 - pos)); + return result; +} + +void print_flip_bits(string name, int n) { + printf ("static const uint8_t %s_%d[%d] = {\n", name, n, 1 << n); + + for (int i = 0; i < 1 << n; i++) { + printf (" 0x%02x,", flip_bits(i, n)); + if ((i & 0xf) == 0xf) + printf("\n"); + } + printf("};\n"); +} + +print_flip_bits("ao_flip_bits", 8); +print_flip_bits("ao_flip_bits", 2); diff --git a/src/cortexelf-v1/ao_hex.c b/src/cortexelf-v1/ao_hex.c new file mode 100644 index 00000000..1507407b --- /dev/null +++ b/src/cortexelf-v1/ao_hex.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#include +#include "ao_hex.h" +#include "ao_as1107.h" +#include "ao_1802.h" + +static struct ao_task ao_hex_task; + +static void +ao_hex(void) +{ + for (;;) { + ao_as1107_write_16(0, ADDRESS); + ao_as1107_write_8(6, DATA); + ao_sleep(&ADDRESS); + } +} + +void +ao_hex_init(void) +{ + ao_add_task(&ao_hex_task, ao_hex, "hex"); +} diff --git a/src/cortexelf-v1/ao_hex.h b/src/cortexelf-v1/ao_hex.h new file mode 100644 index 00000000..674c1eee --- /dev/null +++ b/src/cortexelf-v1/ao_hex.h @@ -0,0 +1,21 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#ifndef _AO_HEX_H_ +#define _AO_HEX_H_ + +void +ao_hex_init(void); + +#endif /* _AO_HEX_H_ */ diff --git a/src/cortexelf-v1/ao_lisp_os.h b/src/cortexelf-v1/ao_lisp_os.h new file mode 100644 index 00000000..d0c1f7b7 --- /dev/null +++ b/src/cortexelf-v1/ao_lisp_os.h @@ -0,0 +1,65 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_LISP_OS_H_ +#define _AO_LISP_OS_H_ + +#include "ao.h" + +#define AO_LISP_POOL_TOTAL 16384 +#define AO_LISP_SAVE 1 + +static inline int +ao_lisp_getc() { + static uint8_t at_eol; + int c; + + if (at_eol) { + ao_cmd_readline(); + at_eol = 0; + } + c = ao_cmd_lex(); + if (c == '\n') + at_eol = 1; + return c; +} + +static inline void +ao_lisp_os_flush(void) +{ + flush(); +} + +static inline void +ao_lisp_abort(void) +{ + ao_panic(1); +} + +static inline void +ao_lisp_os_led(int led) +{ + (void) led; +} + +static inline void +ao_lisp_os_delay(int delay) +{ + ao_delay(AO_MS_TO_TICKS(delay)); +} + +#endif diff --git a/src/cortexelf-v1/ao_lisp_os_save.c b/src/cortexelf-v1/ao_lisp_os_save.c new file mode 100644 index 00000000..7c853990 --- /dev/null +++ b/src/cortexelf-v1/ao_lisp_os_save.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include +#include +#include + +extern uint8_t __flash__[]; + +/* saved variables to rebuild the heap + + ao_lisp_atoms + ao_lisp_frame_global + */ + +int +ao_lisp_os_save(void) +{ + int i; + + for (i = 0; i < AO_LISP_POOL_TOTAL; i += 256) { + uint32_t *dst = (uint32_t *) (void *) &__flash__[i]; + uint32_t *src = (uint32_t *) (void *) &ao_lisp_pool[i]; + + ao_flash_page(dst, src); + } + return 1; +} + +int +ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset) +{ + memcpy(save, &__flash__[offset], sizeof (struct ao_lisp_os_save)); + return 1; +} + +int +ao_lisp_os_restore(void) +{ + memcpy(ao_lisp_pool, __flash__, AO_LISP_POOL_TOTAL); + return 1; +} diff --git a/src/cortexelf-v1/ao_pins.h b/src/cortexelf-v1/ao_pins.h new file mode 100644 index 00000000..258ffe31 --- /dev/null +++ b/src/cortexelf-v1/ao_pins.h @@ -0,0 +1,265 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +#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 = 24MHz */ +#define AO_PLLDIV 4 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_4) + +/* HCLK = 24MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at HCLK/1 */ +#define AO_APB1_PRESCALER 1 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE1_DIV_1 + +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER 1 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1 + +/* Allow for non-maskable interrupts at priority 0 */ +#define AO_NONMASK_INTERRUPT 1 + +/* PS/2 keyboard connection */ +#define AO_PS2_CLOCK_PORT (&stm_gpiod) +#define AO_PS2_CLOCK_BIT 9 +#define AO_PS2_DATA_PORT (&stm_gpiod) +#define AO_PS2_DATA_BIT 8 + +#define HAS_SERIAL_1 1 +#define USE_SERIAL_1_STDIN 1 +#define SERIAL_1_PB6_PB7 1 +#define SERIAL_1_PA9_PA10 0 + +#define HAS_SERIAL_2 1 +#define USE_SERIAL_2_STDIN 1 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 1 + +#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 0 +#define USE_INTERNAL_FLASH 0 +#define USE_EEPROM_CONFIG 0 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_BATTERY_REPORT 0 +#define HAS_RADIO 0 +#define HAS_TELEMETRY 0 +#define HAS_APRS 0 +#define HAS_COMPANION 0 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 0 +#define SPI_2_PD1_PD3_PD4 1 /* LED displays, microSD */ +#define SPI_2_OSPEEDR STM_OSPEEDR_40MHz + +#define SPI_2_PORT (&stm_gpiod) +//#define SPI_2_SCK_PIN 1 +//#define SPI_2_MISO_PIN 3 +//#define SPI_2_MOSI_PIN 4 + +#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 0 + +#define LOW_LEVEL_DEBUG 0 + +#define HAS_GPS 0 +#define HAS_FLIGHT 0 +#define HAS_ADC 0 +#define HAS_ADC_TEMP 0 +#define HAS_LOG 0 + +#define NUM_CMDS 16 + +/* SD card */ +#define AO_SDCARD_SPI_BUS AO_SPI_2_PD1_PD3_PD4 +#define AO_SDCARD_SPI_CS_PORT (&stm_gpiod) +#define AO_SDCARD_SPI_CS_PIN 2 +#define AO_SDCARD_SPI_PORT (&stm_gpiod) +#define AO_SDCARD_SPI_SCK_PIN 1 +#define AO_SDCARD_SPI_MISO_PIN 3 +#define AO_SDCARD_SPI_MOSI_PIN 4 + +/* VGA */ +#define STM_DMA1_3_STOLEN 1 +/* Buttons */ + +#define AO_EVENT 1 + +#define AO_BUTTON_COUNT 4 +#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_DOWN +#define AO_BUTTON_INVERTED 0 + +/* INPUT */ +#define AO_BUTTON_0_PORT (&stm_gpioc) +#define AO_BUTTON_0 8 + +/* MP */ +#define AO_BUTTON_1_PORT (&stm_gpioc) +#define AO_BUTTON_1 9 + +/* RUN */ +#define AO_BUTTON_2_PORT (&stm_gpioc) +#define AO_BUTTON_2 10 + +/* LOAD */ +#define AO_BUTTON_3_PORT (&stm_gpioc) +#define AO_BUTTON_3 11 + +/* AS1107 */ +#define AO_AS1107_NUM_DIGITS 8 + +/* Set the hex digits up for decode, leave the extra leds alone */ + +#define AO_AS1107_DECODE ((1 << 7) | \ + (1 << 6) | \ + (1 << 4) | \ + (1 << 3) | \ + (1 << 1) | \ + (1 << 0)) + +#define AO_AS1107_SPI_INDEX AO_SPI_2_PD1_PD3_PD4 +#define AO_AS1107_SPI_SPEED AO_SPI_SPEED_8MHz +#define AO_AS1107_CS_PORT (&stm_gpiod) +#define AO_AS1107_CS_PIN 0 + +/* Hex keypad */ + +#define AO_MATRIX_ROWS 4 +#define AO_MATRIX_COLS 4 + +#define AO_MATRIX_KEYCODES { \ + { 0x0, 0x1, 0x2, 0x3 }, \ + { 0x4, 0x5, 0x6, 0x7 }, \ + { 0x8, 0x9, 0xa, 0xb }, \ + { 0xc, 0xd, 0xe, 0xf } \ + } + +#include + +#define AO_TIMER_HOOK ao_matrix_poll() + +#define AO_MATRIX_ROW_0_PORT (&stm_gpioc) +#define AO_MATRIX_ROW_0_PIN 4 + +#define AO_MATRIX_ROW_1_PORT (&stm_gpioc) +#define AO_MATRIX_ROW_1_PIN 1 + +#define AO_MATRIX_ROW_2_PORT (&stm_gpioc) +#define AO_MATRIX_ROW_2_PIN 7 + +#define AO_MATRIX_ROW_3_PORT (&stm_gpioc) +#define AO_MATRIX_ROW_3_PIN 0 + +#define AO_MATRIX_COL_0_PORT (&stm_gpioc) +#define AO_MATRIX_COL_0_PIN 2 + +#define AO_MATRIX_COL_1_PORT (&stm_gpioc) +#define AO_MATRIX_COL_1_PIN 3 + +#define AO_MATRIX_COL_2_PORT (&stm_gpioc) +#define AO_MATRIX_COL_2_PIN 5 + +#define AO_MATRIX_COL_3_PORT (&stm_gpioc) +#define AO_MATRIX_COL_3_PIN 6 + +/* 1802 connections */ +#define MRD_PORT (&stm_gpiob) +#define MRD_BIT 15 + +#define MWR_PORT (&stm_gpioa) +#define MWR_BIT 3 + +#define TPB_PORT (&stm_gpioa) +#define TPB_BIT 7 + +#define TPA_PORT (&stm_gpioa) +#define TPA_BIT 6 + +#define MA_PORT (&stm_gpioe) +#define MA_SHIFT 0 +#define MA_MASK 0xff + +#define BUS_PORT (&stm_gpioe) +#define BUS_SHIFT 8 +#define BUS_MASK 0xff + +#define SC_PORT (&stm_gpiob) +#define SC_SHIFT 13 +#define SC_MASK 3 + +#define Q_PORT (&stm_gpiob) +#define Q_BIT 12 + +#define N_PORT (&stm_gpiod) +#define N_SHIFT 13 +#define N_MASK 7 + +#define EF_PORT (&stm_gpiob) +#define EF_SHIFT 8 +#define EF_MASK 0xf + +#define DMA_IN_PORT (&stm_gpioa) +#define DMA_IN_BIT 0 + +#define DMA_OUT_PORT (&stm_gpioa) +#define DMA_OUT_BIT 9 + +#define INT_PORT (&stm_gpioa) +#define INT_BIT 2 + +#define CLEAR_PORT (&stm_gpioa) +#define CLEAR_BIT 10 + +#define WAIT_PORT (&stm_gpioa) +#define WAIT_BIT 4 + +#define MUX_PORT (&stm_gpiob) +#define MUX_BIT 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/cortexelf-v1/cortexelf.ld b/src/cortexelf-v1/cortexelf.ld new file mode 100644 index 00000000..6ad2a679 --- /dev/null +++ b/src/cortexelf-v1/cortexelf.ld @@ -0,0 +1,101 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08001000, LENGTH = 492K + flash (r) : ORIGIN = 0x0807c000, LENGTH = 16K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 81408 + stack (!w) : ORIGIN = 0x20013e00, LENGTH = 512 +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text ORIGIN(rom) : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + + /* 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 */ + *(.rodata*) /* Constants */ + + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > 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)); + + __flash__ = ORIGIN(flash); +} + +ENTRY(start); + + diff --git a/src/cortexelf-v1/flash-loader/Makefile b/src/cortexelf-v1/flash-loader/Makefile new file mode 100644 index 00000000..19cf84e4 --- /dev/null +++ b/src/cortexelf-v1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=cortexelf-v1 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/cortexelf-v1/flash-loader/ao_pins.h b/src/cortexelf-v1/flash-loader/ao_pins.h new file mode 100644 index 00000000..5d63dc2c --- /dev/null +++ b/src/cortexelf-v1/flash-loader/ao_pins.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +/* MP switch, gpioc 9 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioc +#define AO_BOOT_APPLICATION_PIN 9 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/draw/5x7.bdf b/src/draw/5x7.bdf new file mode 100644 index 00000000..b511f289 --- /dev/null +++ b/src/draw/5x7.bdf @@ -0,0 +1,3190 @@ +STARTFONT 2.1 +COMMENT Copyright 1991 Massachusetts Institute of Technology +COMMENT +COMMENT Permission to use, copy, modify, and distribute this software +COMMENT and its documentation for any purpose and without fee is +COMMENT hereby granted, provided that the above copyright notice +COMMENT appear in all copies and that both that copyright notice and +COMMENT this permission notice appear in supporting documentation, +COMMENT and that the name of M.I.T. not be used in advertising or +COMMENT publicity pertaining to distribution of the software without +COMMENT specific, written prior permission. M.I.T. makes no +COMMENT representations about the suitability of this software for +COMMENT any purpose. It is provided "as is" without express or +COMMENT implied warranty. +COMMENT +COMMENT M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +COMMENT INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +COMMENT FITNESS, IN NO EVENT SHALL M.I.T. BE LIABLE FOR ANY SPECIAL, +COMMENT INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER +COMMENT RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +COMMENT ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +COMMENT ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE +COMMENT OF THIS SOFTWARE. +COMMENT +COMMENT Author: Stephen Gildea, MIT X Consortium, June 1991 +COMMENT +FONT -Misc-Fixed-Medium-R-Normal--7-70-75-75-C-50-ISO8859-1 +SIZE 7 75 75 +FONTBOUNDINGBOX 5 7 0 -1 +STARTPROPERTIES 21 +FONTNAME_REGISTRY "" +FOUNDRY "Misc" +FAMILY_NAME "Fixed" +WEIGHT_NAME "Medium" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 7 +POINT_SIZE 70 +RESOLUTION_X 75 +RESOLUTION_Y 75 +SPACING "C" +AVERAGE_WIDTH 50 +CHARSET_REGISTRY "ISO8859" +CHARSET_ENCODING "1" +FONT_ASCENT 6 +FONT_DESCENT 1 +UNDERLINE_POSITION 0 +DESTINATION 1 +DEFAULT_CHAR 0 +COPYRIGHT "Copyright 1991 Massachusetts Institute of Technology" +ENDPROPERTIES +CHARS 224 +STARTCHAR C000 +ENCODING 0 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +f0 +f0 +f0 +f0 +f0 +00 +ENDCHAR +STARTCHAR C001 +ENCODING 1 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +20 +70 +f8 +70 +20 +00 +ENDCHAR +STARTCHAR C002 +ENCODING 2 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +a0 +50 +a0 +50 +a0 +00 +ENDCHAR +STARTCHAR C003 +ENCODING 3 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +e0 +a0 +a0 +70 +20 +20 +ENDCHAR +STARTCHAR C004 +ENCODING 4 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +c0 +80 +c0 +b0 +20 +30 +20 +ENDCHAR +STARTCHAR C005 +ENCODING 5 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +c0 +80 +c0 +60 +50 +60 +50 +ENDCHAR +STARTCHAR C006 +ENCODING 6 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +80 +c0 +30 +20 +30 +20 +ENDCHAR +STARTCHAR C007 +ENCODING 7 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +50 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C010 +ENCODING 8 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +70 +20 +00 +70 +00 +00 +ENDCHAR +STARTCHAR C011 +ENCODING 9 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +d0 +b0 +90 +20 +20 +30 +ENDCHAR +STARTCHAR C012 +ENCODING 10 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +a0 +a0 +40 +70 +20 +20 +ENDCHAR +STARTCHAR C013 +ENCODING 11 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +20 +e0 +00 +00 +00 +ENDCHAR +STARTCHAR C014 +ENCODING 12 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +e0 +20 +20 +20 +ENDCHAR +STARTCHAR C015 +ENCODING 13 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +38 +20 +20 +20 +ENDCHAR +STARTCHAR C016 +ENCODING 14 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +20 +38 +00 +00 +00 +ENDCHAR +STARTCHAR C017 +ENCODING 15 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +20 +f8 +20 +20 +20 +ENDCHAR +STARTCHAR C020 +ENCODING 16 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +f8 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C021 +ENCODING 17 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 6 7 0 -1 +BITMAP +00 +00 +f8 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C022 +ENCODING 18 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +f8 +00 +00 +00 +ENDCHAR +STARTCHAR C023 +ENCODING 19 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +f8 +00 +00 +ENDCHAR +STARTCHAR C024 +ENCODING 20 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +00 +f8 +00 +ENDCHAR +STARTCHAR C025 +ENCODING 21 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +20 +38 +20 +20 +20 +ENDCHAR +STARTCHAR C026 +ENCODING 22 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +20 +e0 +20 +20 +20 +ENDCHAR +STARTCHAR C027 +ENCODING 23 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 6 7 0 -1 +BITMAP +20 +20 +20 +f8 +00 +00 +00 +ENDCHAR +STARTCHAR C030 +ENCODING 24 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +f8 +20 +20 +20 +ENDCHAR +STARTCHAR C031 +ENCODING 25 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +20 +20 +20 +20 +20 +ENDCHAR +STARTCHAR C032 +ENCODING 26 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +10 +20 +40 +20 +10 +70 +00 +ENDCHAR +STARTCHAR C033 +ENCODING 27 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +20 +10 +20 +40 +70 +00 +ENDCHAR +STARTCHAR C034 +ENCODING 28 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +70 +50 +50 +50 +00 +ENDCHAR +STARTCHAR C035 +ENCODING 29 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +10 +70 +20 +70 +40 +00 +ENDCHAR +STARTCHAR C036 +ENCODING 30 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +30 +40 +e0 +40 +b0 +00 +ENDCHAR +STARTCHAR C037 +ENCODING 31 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +20 +00 +00 +00 +ENDCHAR +STARTCHAR C040 +ENCODING 32 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR ! +ENCODING 33 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +20 +20 +00 +20 +00 +ENDCHAR +STARTCHAR " +ENCODING 34 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +50 +50 +00 +00 +00 +00 +ENDCHAR +STARTCHAR # +ENCODING 35 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +50 +f8 +50 +f8 +50 +00 +ENDCHAR +STARTCHAR $ +ENCODING 36 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +70 +a0 +70 +28 +70 +00 +ENDCHAR +STARTCHAR % +ENCODING 37 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +90 +20 +40 +90 +10 +00 +ENDCHAR +STARTCHAR & +ENCODING 38 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +40 +a0 +40 +a0 +50 +00 +ENDCHAR +STARTCHAR ' +ENCODING 39 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +40 +80 +00 +00 +00 +00 +ENDCHAR +STARTCHAR ( +ENCODING 40 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +40 +40 +40 +20 +00 +ENDCHAR +STARTCHAR ) +ENCODING 41 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +20 +20 +20 +20 +40 +00 +ENDCHAR +STARTCHAR * +ENCODING 42 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +a0 +40 +e0 +40 +a0 +00 +ENDCHAR +STARTCHAR + +ENCODING 43 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +20 +20 +f8 +20 +20 +00 +ENDCHAR +STARTCHAR , +ENCODING 44 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +60 +40 +80 +ENDCHAR +STARTCHAR - +ENCODING 45 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +f0 +00 +00 +00 +ENDCHAR +STARTCHAR . +ENCODING 46 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +60 +60 +00 +ENDCHAR +STARTCHAR / +ENCODING 47 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +10 +20 +40 +80 +00 +00 +ENDCHAR +STARTCHAR 0 +ENCODING 48 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +a0 +a0 +a0 +a0 +40 +00 +ENDCHAR +STARTCHAR 1 +ENCODING 49 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +c0 +40 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR 2 +ENCODING 50 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +10 +20 +40 +f0 +00 +ENDCHAR +STARTCHAR 3 +ENCODING 51 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +10 +60 +10 +90 +60 +00 +ENDCHAR +STARTCHAR 4 +ENCODING 52 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +60 +a0 +f0 +20 +20 +00 +ENDCHAR +STARTCHAR 5 +ENCODING 53 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +80 +e0 +10 +90 +60 +00 +ENDCHAR +STARTCHAR 6 +ENCODING 54 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +80 +e0 +90 +90 +60 +00 +ENDCHAR +STARTCHAR 7 +ENCODING 55 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +10 +20 +20 +40 +40 +00 +ENDCHAR +STARTCHAR 8 +ENCODING 56 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR 9 +ENCODING 57 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +70 +10 +60 +00 +ENDCHAR +STARTCHAR : +ENCODING 58 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +60 +60 +00 +60 +60 +00 +ENDCHAR +STARTCHAR ; +ENCODING 59 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +60 +60 +00 +60 +40 +80 +ENDCHAR +STARTCHAR < +ENCODING 60 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +20 +40 +80 +40 +20 +00 +ENDCHAR +STARTCHAR = +ENCODING 61 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +f0 +00 +f0 +00 +00 +ENDCHAR +STARTCHAR > +ENCODING 62 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +80 +40 +20 +40 +80 +00 +ENDCHAR +STARTCHAR ? +ENCODING 63 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +a0 +20 +40 +00 +40 +00 +ENDCHAR +STARTCHAR @ +ENCODING 64 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +b0 +b0 +80 +60 +00 +ENDCHAR +STARTCHAR A +ENCODING 65 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR B +ENCODING 66 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +90 +e0 +90 +90 +e0 +00 +ENDCHAR +STARTCHAR C +ENCODING 67 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +80 +80 +90 +60 +00 +ENDCHAR +STARTCHAR D +ENCODING 68 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +90 +90 +90 +90 +e0 +00 +ENDCHAR +STARTCHAR E +ENCODING 69 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +80 +e0 +80 +80 +f0 +00 +ENDCHAR +STARTCHAR F +ENCODING 70 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +80 +e0 +80 +80 +80 +00 +ENDCHAR +STARTCHAR G +ENCODING 71 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +80 +b0 +90 +70 +00 +ENDCHAR +STARTCHAR H +ENCODING 72 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +f0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR I +ENCODING 73 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +40 +40 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR J +ENCODING 74 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +10 +10 +10 +10 +90 +60 +00 +ENDCHAR +STARTCHAR K +ENCODING 75 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +a0 +c0 +c0 +a0 +90 +00 +ENDCHAR +STARTCHAR L +ENCODING 76 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +80 +80 +80 +80 +f0 +00 +ENDCHAR +STARTCHAR M +ENCODING 77 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +f0 +f0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR N +ENCODING 78 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +d0 +d0 +b0 +b0 +90 +00 +ENDCHAR +STARTCHAR O +ENCODING 79 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR P +ENCODING 80 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +90 +90 +e0 +80 +80 +00 +ENDCHAR +STARTCHAR Q +ENCODING 81 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +90 +d0 +60 +10 +ENDCHAR +STARTCHAR R +ENCODING 82 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +90 +90 +e0 +a0 +90 +00 +ENDCHAR +STARTCHAR S +ENCODING 83 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +40 +20 +90 +60 +00 +ENDCHAR +STARTCHAR T +ENCODING 84 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +40 +40 +40 +40 +40 +00 +ENDCHAR +STARTCHAR U +ENCODING 85 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR V +ENCODING 86 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +90 +90 +60 +60 +00 +ENDCHAR +STARTCHAR W +ENCODING 87 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +90 +f0 +f0 +90 +00 +ENDCHAR +STARTCHAR X +ENCODING 88 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +60 +60 +90 +90 +00 +ENDCHAR +STARTCHAR Y +ENCODING 89 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +a0 +a0 +40 +40 +40 +00 +ENDCHAR +STARTCHAR Z +ENCODING 90 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +10 +20 +40 +80 +f0 +00 +ENDCHAR +STARTCHAR [ +ENCODING 91 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +80 +80 +80 +80 +e0 +00 +ENDCHAR +STARTCHAR \ +ENCODING 92 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +80 +40 +20 +10 +00 +00 +ENDCHAR +STARTCHAR ] +ENCODING 93 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +20 +20 +20 +20 +e0 +00 +ENDCHAR +STARTCHAR ^ +ENCODING 94 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +a0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR _ +ENCODING 95 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +00 +f0 +00 +ENDCHAR +STARTCHAR ` +ENCODING 96 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +c0 +40 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR a +ENCODING 97 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +70 +90 +b0 +50 +00 +ENDCHAR +STARTCHAR b +ENCODING 98 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +80 +e0 +90 +90 +e0 +00 +ENDCHAR +STARTCHAR c +ENCODING 99 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +60 +80 +80 +60 +00 +ENDCHAR +STARTCHAR d +ENCODING 100 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +10 +10 +70 +90 +90 +70 +00 +ENDCHAR +STARTCHAR e +ENCODING 101 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +60 +b0 +c0 +60 +00 +ENDCHAR +STARTCHAR f +ENCODING 102 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +50 +40 +e0 +40 +40 +00 +ENDCHAR +STARTCHAR g +ENCODING 103 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +70 +90 +60 +80 +70 +ENDCHAR +STARTCHAR h +ENCODING 104 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +80 +e0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR i +ENCODING 105 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +00 +c0 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR j +ENCODING 106 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +00 +20 +20 +20 +a0 +40 +ENDCHAR +STARTCHAR k +ENCODING 107 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +80 +a0 +c0 +a0 +90 +00 +ENDCHAR +STARTCHAR l +ENCODING 108 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +c0 +40 +40 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR m +ENCODING 109 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +a0 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR n +ENCODING 110 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +e0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR o +ENCODING 111 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR p +ENCODING 112 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +e0 +90 +90 +e0 +80 +ENDCHAR +STARTCHAR q +ENCODING 113 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +70 +90 +90 +70 +10 +ENDCHAR +STARTCHAR r +ENCODING 114 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +e0 +90 +80 +80 +00 +ENDCHAR +STARTCHAR s +ENCODING 115 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 6 7 0 -1 +BITMAP +00 +00 +70 +c0 +30 +e0 +00 +ENDCHAR +STARTCHAR t +ENCODING 116 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +40 +e0 +40 +40 +30 +00 +ENDCHAR +STARTCHAR u +ENCODING 117 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR v +ENCODING 118 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +a0 +a0 +a0 +40 +00 +ENDCHAR +STARTCHAR w +ENCODING 119 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +90 +90 +f0 +f0 +00 +ENDCHAR +STARTCHAR x +ENCODING 120 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +90 +60 +60 +90 +00 +ENDCHAR +STARTCHAR y +ENCODING 121 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +90 +90 +50 +20 +40 +ENDCHAR +STARTCHAR z +ENCODING 122 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +f0 +20 +40 +f0 +00 +ENDCHAR +STARTCHAR { +ENCODING 123 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +c0 +40 +40 +20 +00 +ENDCHAR +STARTCHAR | +ENCODING 124 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +40 +40 +40 +40 +40 +00 +ENDCHAR +STARTCHAR } +ENCODING 125 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 6 7 0 -1 +BITMAP +80 +40 +60 +40 +40 +80 +00 +ENDCHAR +STARTCHAR ~ +ENCODING 126 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +a0 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR Blank +ENCODING 127 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C160 +ENCODING 160 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C161 +ENCODING 161 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +00 +20 +20 +20 +20 +00 +ENDCHAR +STARTCHAR C162 +ENCODING 162 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +20 +70 +a0 +a0 +70 +20 +ENDCHAR +STARTCHAR C163 +ENCODING 163 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +30 +40 +e0 +40 +b0 +00 +ENDCHAR +STARTCHAR C164 +ENCODING 164 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +88 +70 +50 +70 +88 +00 +ENDCHAR +STARTCHAR C165 +ENCODING 165 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +a0 +40 +e0 +40 +40 +00 +ENDCHAR +STARTCHAR C166 +ENCODING 166 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +20 +20 +00 +20 +20 +00 +ENDCHAR +STARTCHAR C167 +ENCODING 167 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +30 +40 +60 +50 +30 +10 +60 +ENDCHAR +STARTCHAR C168 +ENCODING 168 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C169 +ENCODING 169 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +70 +88 +a8 +c8 +a8 +88 +70 +ENDCHAR +STARTCHAR C170 +ENCODING 170 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +a0 +60 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C171 +ENCODING 171 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +48 +90 +48 +00 +00 +ENDCHAR +STARTCHAR C172 +ENCODING 172 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +f0 +10 +00 +00 +00 +ENDCHAR +STARTCHAR C173 +ENCODING 173 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +f0 +00 +00 +00 +ENDCHAR +STARTCHAR C174 +ENCODING 174 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +70 +88 +e8 +c8 +c8 +88 +70 +ENDCHAR +STARTCHAR C175 +ENCODING 175 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +00 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C176 +ENCODING 176 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +50 +20 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C177 +ENCODING 177 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +20 +f8 +20 +20 +f8 +00 +ENDCHAR +STARTCHAR C178 +ENCODING 178 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +20 +40 +60 +00 +00 +00 +ENDCHAR +STARTCHAR C179 +ENCODING 179 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +60 +20 +60 +00 +00 +00 +ENDCHAR +STARTCHAR C180 +ENCODING 180 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +00 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C181 +ENCODING 181 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +90 +90 +90 +e0 +80 +ENDCHAR +STARTCHAR C182 +ENCODING 182 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +70 +d0 +d0 +50 +50 +50 +00 +ENDCHAR +STARTCHAR C183 +ENCODING 183 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +60 +60 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C184 +ENCODING 184 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +00 +00 +00 +20 +40 +ENDCHAR +STARTCHAR C185 +ENCODING 185 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +60 +20 +70 +00 +00 +00 +ENDCHAR +STARTCHAR C186 +ENCODING 186 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +a0 +40 +00 +00 +00 +00 +ENDCHAR +STARTCHAR C187 +ENCODING 187 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +90 +48 +90 +00 +00 +ENDCHAR +STARTCHAR C188 +ENCODING 188 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +80 +80 +90 +30 +70 +10 +ENDCHAR +STARTCHAR C189 +ENCODING 189 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +80 +80 +b0 +10 +20 +30 +ENDCHAR +STARTCHAR C190 +ENCODING 190 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +c0 +c0 +40 +d0 +30 +70 +10 +ENDCHAR +STARTCHAR C191 +ENCODING 191 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +00 +40 +80 +a0 +40 +00 +ENDCHAR +STARTCHAR Agrave +ENCODING 192 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR C193 +ENCODING 193 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR C194 +ENCODING 194 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR C195 +ENCODING 195 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR C196 +ENCODING 196 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR C197 +ENCODING 197 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +f0 +90 +90 +00 +ENDCHAR +STARTCHAR C198 +ENCODING 198 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +70 +a0 +b0 +e0 +a0 +b0 +00 +ENDCHAR +STARTCHAR C199 +ENCODING 199 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +80 +80 +90 +60 +40 +ENDCHAR +STARTCHAR Egrave +ENCODING 200 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +80 +e0 +80 +80 +f0 +00 +ENDCHAR +STARTCHAR C201 +ENCODING 201 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +80 +e0 +80 +80 +f0 +00 +ENDCHAR +STARTCHAR C202 +ENCODING 202 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +80 +e0 +80 +80 +f0 +00 +ENDCHAR +STARTCHAR C203 +ENCODING 203 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +f0 +80 +e0 +80 +80 +f0 +00 +ENDCHAR +STARTCHAR C204 +ENCODING 204 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +40 +40 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C205 +ENCODING 205 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +40 +40 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C206 +ENCODING 206 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +40 +40 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C207 +ENCODING 207 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +40 +40 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C208 +ENCODING 208 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +e0 +50 +d0 +50 +50 +e0 +00 +ENDCHAR +STARTCHAR C209 +ENCODING 209 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +b0 +90 +d0 +b0 +b0 +90 +00 +ENDCHAR +STARTCHAR Ograve +ENCODING 210 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C211 +ENCODING 211 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C212 +ENCODING 212 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C213 +ENCODING 213 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C214 +ENCODING 214 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C215 +ENCODING 215 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +90 +60 +60 +90 +00 +ENDCHAR +STARTCHAR C216 +ENCODING 216 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +70 +b0 +b0 +d0 +d0 +e0 +00 +ENDCHAR +STARTCHAR Ugrave +ENCODING 217 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C218 +ENCODING 218 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C219 +ENCODING 219 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C220 +ENCODING 220 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +90 +90 +90 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C221 +ENCODING 221 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +a0 +a0 +40 +40 +40 +00 +ENDCHAR +STARTCHAR C222 +ENCODING 222 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +e0 +90 +e0 +80 +80 +00 +ENDCHAR +STARTCHAR C223 +ENCODING 223 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +90 +e0 +90 +d0 +a0 +80 +ENDCHAR +STARTCHAR a-grave +ENCODING 224 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +20 +70 +90 +b0 +50 +00 +ENDCHAR +STARTCHAR C225 +ENCODING 225 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +70 +90 +b0 +50 +00 +ENDCHAR +STARTCHAR C226 +ENCODING 226 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +50 +70 +90 +b0 +50 +00 +ENDCHAR +STARTCHAR C227 +ENCODING 227 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +a0 +70 +90 +b0 +50 +00 +ENDCHAR +STARTCHAR C228 +ENCODING 228 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +00 +70 +90 +b0 +50 +00 +ENDCHAR +STARTCHAR C229 +ENCODING 229 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +60 +70 +90 +b0 +50 +00 +ENDCHAR +STARTCHAR C230 +ENCODING 230 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +70 +b0 +a0 +70 +00 +ENDCHAR +STARTCHAR C231 +ENCODING 231 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +60 +80 +80 +60 +40 +ENDCHAR +STARTCHAR e-grave +ENCODING 232 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +20 +60 +b0 +c0 +60 +00 +ENDCHAR +STARTCHAR C233 +ENCODING 233 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +60 +b0 +c0 +60 +00 +ENDCHAR +STARTCHAR C234 +ENCODING 234 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +a0 +60 +b0 +c0 +60 +00 +ENDCHAR +STARTCHAR C235 +ENCODING 235 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +00 +60 +b0 +c0 +60 +00 +ENDCHAR +STARTCHAR C236 +ENCODING 236 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +80 +40 +c0 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C237 +ENCODING 237 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +80 +c0 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C238 +ENCODING 238 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +a0 +c0 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C239 +ENCODING 239 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +00 +c0 +40 +40 +e0 +00 +ENDCHAR +STARTCHAR C240 +ENCODING 240 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +30 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C241 +ENCODING 241 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +a0 +e0 +90 +90 +90 +00 +ENDCHAR +STARTCHAR C242 +ENCODING 242 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +20 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C243 +ENCODING 243 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C244 +ENCODING 244 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C245 +ENCODING 245 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +a0 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C246 +ENCODING 246 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +a0 +00 +60 +90 +90 +60 +00 +ENDCHAR +STARTCHAR C247 +ENCODING 247 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +60 +00 +f0 +00 +60 +00 +ENDCHAR +STARTCHAR C248 +ENCODING 248 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +00 +70 +b0 +d0 +e0 +00 +ENDCHAR +STARTCHAR C249 +ENCODING 249 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +40 +20 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR C250 +ENCODING 250 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR C251 +ENCODING 251 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +60 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR C252 +ENCODING 252 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +00 +90 +90 +90 +70 +00 +ENDCHAR +STARTCHAR C253 +ENCODING 253 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +20 +40 +90 +90 +50 +20 +40 +ENDCHAR +STARTCHAR C254 +ENCODING 254 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +00 +80 +e0 +90 +90 +e0 +80 +ENDCHAR +STARTCHAR C255 +ENCODING 255 +SWIDTH 686 0 +DWIDTH 5 0 +BBX 5 7 0 -1 +BITMAP +50 +00 +90 +90 +50 +20 +40 +ENDCHAR +ENDFONT diff --git a/src/draw/Makefile b/src/draw/Makefile new file mode 100644 index 00000000..0a542a1f --- /dev/null +++ b/src/draw/Makefile @@ -0,0 +1,4 @@ +BDF=5x7.bdf + +ao_font.h: font-convert $(BDF) + nickle font-convert $(BDF) > $@ diff --git a/src/draw/ao_blt.c b/src/draw/ao_blt.c new file mode 100644 index 00000000..e3f45221 --- /dev/null +++ b/src/draw/ao_blt.c @@ -0,0 +1,294 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_draw.h" +#include "ao_draw_int.h" + +#define O 0 +#define I AO_ALLONES + +struct ao_merge_rop { + uint32_t ca1, cx1, ca2, cx2; +}; + +const struct ao_merge_rop ao_merge_rop[16] = { + {O, O, O, O}, /* clear 0x0 0 */ + {I, O, O, O}, /* and 0x1 src AND dst */ + {I, O, I, O}, /* andReverse 0x2 src AND NOT dst */ + {O, O, I, O}, /* copy 0x3 src */ + {I, I, O, O}, /* andInverted 0x4 NOT src AND dst */ + {O, I, O, O}, /* noop 0x5 dst */ + {O, I, I, O}, /* xor 0x6 src XOR dst */ + {I, I, I, O}, /* or 0x7 src OR dst */ + {I, I, I, I}, /* nor 0x8 NOT src AND NOT dst */ + {O, I, I, I}, /* equiv 0x9 NOT src XOR dst */ + {O, I, O, I}, /* invert 0xa NOT dst */ + {I, I, O, I}, /* orReverse 0xb src OR NOT dst */ + {O, O, I, I}, /* copyInverted 0xc NOT src */ + {I, O, I, I}, /* orInverted 0xd NOT src OR dst */ + {I, O, O, I}, /* nand 0xe NOT src OR NOT dst */ + {O, O, O, I}, /* set 0xf 1 */ +}; + +#define ao_do_merge_rop(src, dst) \ + (((dst) & (((src) & _ca1) ^ _cx1)) ^ (((src) & _ca2) ^ _cx2)) + +#define ao_do_dst_invarient_merge_rop(src) (((src) & _ca2) ^ _cx2) + +#define ao_do_mask_merge_rop(src, dst, mask) \ + (((dst) & ((((src) & _ca1) ^ _cx1) | ~(mask))) ^ ((((src) & _ca2) ^ _cx2) & (mask))) + +#define ao_dst_invarient_merge_rop() (_ca1 == 0 && _cx1 == 0) + +void +ao_blt(uint32_t *src_line, + int16_t src_stride, + int16_t src_x, + uint32_t *dst_line, + int16_t dst_stride, + int16_t dst_x, + int16_t width, + int16_t height, + uint8_t rop, + uint8_t reverse, + uint8_t upsidedown) +{ + uint32_t *src, *dst; + uint32_t _ca1, _cx1, _ca2, _cx2; + uint8_t dst_invarient; + uint32_t startmask, endmask; + int16_t nmiddle, n; + uint32_t bits1, bits; + int16_t left_shift, right_shift; + + _ca1 = ao_merge_rop[rop].ca1; + _cx1 = ao_merge_rop[rop].cx1; + _ca2 = ao_merge_rop[rop].ca2; + _cx2 = ao_merge_rop[rop].cx2; + dst_invarient = ao_dst_invarient_merge_rop(); + + if (upsidedown) { + src_line += (height - 1) * src_stride; + dst_line += (height - 1) * dst_stride; + src_stride = -src_stride; + dst_stride = -dst_stride; + } + + ao_mask_bits(dst_x, width, startmask, nmiddle, endmask); + if (reverse) { + src_line += ((src_x + width - 1) >> AO_SHIFT) + 1; + dst_line += ((dst_x + width - 1) >> AO_SHIFT) + 1; + src_x = (src_x + width - 1) & AO_MASK; + dst_x = (dst_x + width - 1) & AO_MASK; + } else { + src_line += src_x >> AO_SHIFT; + dst_line += dst_x >> AO_SHIFT; + src_x &= AO_MASK; + dst_x &= AO_MASK; + } + if (src_x == dst_x) { + while (height--) { + src = src_line; + src_line += src_stride; + dst = dst_line; + dst_line += dst_stride; + if (reverse) { + if (endmask) { + bits = *--src; + --dst; + *dst = ao_do_mask_merge_rop(bits, *dst, endmask); + } + n = nmiddle; + if (dst_invarient) { + while (n--) + *--dst = ao_do_dst_invarient_merge_rop(*--src); + } + else { + while (n--) { + bits = *--src; + --dst; + *dst = ao_do_merge_rop(bits, *dst); + } + } + if (startmask) { + bits = *--src; + --dst; + *dst = ao_do_mask_merge_rop(bits, *dst, startmask); + } + } + else { + if (startmask) { + bits = *src++; + *dst = ao_do_mask_merge_rop(bits, *dst, startmask); + dst++; + } + n = nmiddle; + if (dst_invarient) { + while (n--) + *dst++ = ao_do_dst_invarient_merge_rop(*src++); + } + else { + while (n--) { + bits = *src++; + *dst = ao_do_merge_rop(bits, *dst); + dst++; + } + } + if (endmask) { + bits = *src; + *dst = ao_do_mask_merge_rop(bits, *dst, endmask); + } + } + } + } else { + if (src_x > dst_x) { + left_shift = src_x - dst_x; + right_shift = AO_UNIT - left_shift; + } else { + right_shift = dst_x - src_x; + left_shift = AO_UNIT - right_shift; + } + while (height--) { + src = src_line; + src_line += src_stride; + dst = dst_line; + dst_line += dst_stride; + + bits1 = 0; + if (reverse) { + if (src_x < dst_x) + bits1 = *--src; + if (endmask) { + bits = ao_right(bits1, right_shift); + if (ao_right(endmask, left_shift)) { + bits1 = *--src; + bits |= ao_left(bits1, left_shift); + } + --dst; + *dst = ao_do_mask_merge_rop(bits, *dst, endmask); + } + n = nmiddle; + if (dst_invarient) { + while (n--) { + bits = ao_right(bits1, right_shift); + bits1 = *--src; + bits |= ao_left(bits1, left_shift); + --dst; + *dst = ao_do_dst_invarient_merge_rop(bits); + } + } else { + while (n--) { + bits = ao_right(bits1, right_shift); + bits1 = *--src; + bits |= ao_left(bits1, left_shift); + --dst; + *dst = ao_do_merge_rop(bits, *dst); + } + } + if (startmask) { + bits = ao_right(bits1, right_shift); + if (ao_right(startmask, left_shift)) { + bits1 = *--src; + bits |= ao_left(bits1, left_shift); + } + --dst; + *dst = ao_do_mask_merge_rop(bits, *dst, startmask); + } + } + else { + if (src_x > dst_x) + bits1 = *src++; + if (startmask) { + bits = ao_left(bits1, left_shift); + if (ao_left(startmask, right_shift)) { + bits1 = *src++; + bits |= ao_right(bits1, right_shift); + } + *dst = ao_do_mask_merge_rop(bits, *dst, startmask); + dst++; + } + n = nmiddle; + if (dst_invarient) { + while (n--) { + bits = ao_left(bits1, left_shift); + bits1 = *src++; + bits |= ao_right(bits1, right_shift); + *dst = ao_do_dst_invarient_merge_rop(bits); + dst++; + } + } + else { + while (n--) { + bits = ao_left(bits1, left_shift); + bits1 = *src++; + bits |= ao_right(bits1, right_shift); + *dst = ao_do_merge_rop(bits, *dst); + dst++; + } + } + if (endmask) { + bits = ao_left(bits1, left_shift); + if (ao_left(endmask, right_shift)) { + bits1 = *src; + bits |= ao_right(bits1, right_shift); + } + *dst = ao_do_mask_merge_rop(bits, *dst, endmask); + } + } + } + } +} + +void +ao_solid(uint32_t and, + uint32_t xor, + uint32_t *dst, + int16_t dst_stride, + int16_t dst_x, + int16_t width, + int16_t height) +{ + uint32_t startmask, endmask; + int16_t nmiddle; + int16_t n; + + dst += dst_x >> AO_SHIFT; + dst_x &= AO_MASK; + + ao_mask_bits(dst_x, width, startmask, nmiddle, endmask); + + if (startmask) + dst_stride--; + + dst_stride -= nmiddle; + while (height--) { + if (startmask) { + *dst = ao_do_mask_rrop(*dst, and, xor, startmask); + dst++; + } + n = nmiddle; + if (!and) + while (n--) + *dst++ = xor; + else + while (n--) { + *dst = ao_do_rrop(*dst, and, xor); + dst++; + } + if (endmask) + *dst = ao_do_mask_rrop(*dst, and, xor, endmask); + dst += dst_stride; + } +} diff --git a/src/draw/ao_copy.c b/src/draw/ao_copy.c new file mode 100644 index 00000000..47067bb8 --- /dev/null +++ b/src/draw/ao_copy.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_draw.h" +#include "ao_draw_int.h" + +#define bound(val,max,other) do { \ + if (val < 0) { \ + other -= val; \ + val = 0; \ + } \ + if (val > max) { \ + other -= (val - max); \ + val = max; \ + } \ + } while (0) + +#define bound2(a, max_a, b, max_b) do { \ + bound(a, max_a, b); \ + bound(b, max_b, a); \ + } while (0) + +void +ao_copy(const struct ao_bitmap *dst, + int16_t dst_x, + int16_t dst_y, + int16_t width, + int16_t height, + const struct ao_bitmap *src, + int16_t src_x, + int16_t src_y, + uint8_t rop) +{ + int16_t dst_x2 = dst_x + width, dst_y2 = dst_y + height; + int16_t src_x2 = src_x + width, src_y2 = src_y + height; + uint8_t reverse = 0; + uint8_t upsidedown = 0; + + bound2(dst_x, dst->width, src_x, src->width); + bound2(dst_x2, dst->width, src_x2, src->width); + bound2(dst_y, dst->height, src_y, src->height); + bound2(dst_y2, dst->height, src_y2, src->height); + + if (dst == src) { + reverse = (dst_x > src_x); + upsidedown = (dst_y > src_y); + } + + if (dst_x < dst_x2 && dst_y < dst_y2) { + ao_blt(src->base + src_y * src->stride, + src->stride, + src_x, + dst->base + dst_y * dst->stride, + dst->stride, + dst_x, + dst_x2 - dst_x, + dst_y2 - dst_y, + rop, + reverse, + upsidedown); + } +} + diff --git a/src/draw/ao_draw.h b/src/draw/ao_draw.h new file mode 100644 index 00000000..92150fc1 --- /dev/null +++ b/src/draw/ao_draw.h @@ -0,0 +1,119 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_DRAW_H_ +#define _AO_DRAW_H_ + +struct ao_bitmap { + uint32_t *base; + int16_t stride; /* in units */ + int16_t width; /* in pixels */ + int16_t height; /* in pixels */ +}; + +struct ao_pattern { + uint8_t pattern[8]; +}; + +void +ao_copy(const struct ao_bitmap *dst, + int16_t dst_x, + int16_t dst_y, + int16_t width, + int16_t height, + const struct ao_bitmap *src, + int16_t src_x, + int16_t src_y, + uint8_t rop); + +void +ao_rect(const struct ao_bitmap *dst, + int16_t x, + int16_t y, + int16_t width, + int16_t height, + uint32_t fill, + uint8_t rop); + +void +ao_pattern(const struct ao_bitmap *dst, + int16_t x, + int16_t y, + int16_t width, + int16_t height, + const struct ao_pattern *pattern, + int16_t pat_x, + int16_t pat_y, + uint8_t rop); + +void +ao_line(const struct ao_bitmap *dst, + int16_t x1, + int16_t y1, + int16_t x2, + int16_t y2, + uint32_t fill, + uint8_t rop); + +void +ao_text(const struct ao_bitmap *dst, + int16_t x, + int16_t y, + char *string, + uint32_t fill, + uint8_t rop); + +struct ao_font { + int width; + int height; + int ascent; + int descent; +}; + +extern const struct ao_font ao_font; + +#define AO_SHIFT 5 +#define AO_UNIT (1 << AO_SHIFT) +#define AO_MASK (AO_UNIT - 1) +#define AO_ALLONES ((uint32_t) -1) + +/* + * dst + * 0 1 + * + * 0 a b + * src + * 1 c d + * + * ROP = abcd + */ + +#define AO_CLEAR 0x0 /* 0 */ +#define AO_AND 0x1 /* src AND dst */ +#define AO_AND_REVERSE 0x2 /* src AND NOT dst */ +#define AO_COPY 0x3 /* src */ +#define AO_AND_INVERTED 0x4 /* NOT src AND dst */ +#define AO_NOOP 0x5 /* dst */ +#define AO_XOR 0x6 /* src XOR dst */ +#define AO_OR 0x7 /* src OR dst */ +#define AO_NOR 0x8 /* NOT src AND NOT dst */ +#define AO_EQUIV 0x9 /* NOT src XOR dst */ +#define AO_INVERT 0xa /* NOT dst */ +#define AO_OR_REVERSE 0xb /* src OR NOT dst */ +#define AO_COPY_INVERTED 0xc /* NOT src */ +#define AO_OR_INVERTED 0xd /* NOT src OR dst */ +#define AO_NAND 0xe /* NOT src OR NOT dst */ +#define AO_SET 0xf /* 1 */ + +#endif /* _AO_DRAW_H_ */ diff --git a/src/draw/ao_draw_int.h b/src/draw/ao_draw_int.h new file mode 100644 index 00000000..433aa409 --- /dev/null +++ b/src/draw/ao_draw_int.h @@ -0,0 +1,136 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_DRAW_INT_H_ +#define _AO_DRAW_INT_H_ + +static inline uint32_t +ao_expand(uint32_t bits) +{ + return ~((bits & 1)-1); +} + +static inline uint32_t +ao_xor(uint8_t rop, uint32_t fg) +{ + fg = ao_expand(fg); + + return (fg & ao_expand(rop >> 1)) | + (~fg & ao_expand(rop >> 3)); +} + +static inline uint32_t +ao_and(uint8_t rop, uint32_t fg) +{ + fg = ao_expand(fg); + + return (fg & ao_expand(rop ^ (rop >> 1))) | + (~fg & ao_expand((rop>>2) ^ (rop>>3))); +} + +static inline uint32_t +ao_left(uint32_t bits, int16_t shift) { + return bits >> shift; +} + +static inline uint32_t +ao_right(uint32_t bits, int16_t shift) { + return bits << shift; +} + +static inline uint32_t +ao_right_mask(int16_t x) { + if ((AO_UNIT - x) & AO_MASK) + return ao_left(AO_ALLONES,(AO_UNIT - x) & AO_MASK); + else + return 0; +} + +static inline uint32_t +ao_left_mask(int16_t x) { + if (x & AO_MASK) + return ao_right(AO_ALLONES, x & AO_MASK); + else + return 0; +} + +static inline uint32_t +ao_bits_mask(int16_t x, int16_t w) { + return ao_right(AO_ALLONES, x & AO_MASK) & + ao_left(AO_ALLONES,(AO_UNIT - (x + w)) & AO_MASK); +} + +#define ao_mask_bits(x,w,l,n,r) { \ + n = (w); \ + r = ao_right_mask((x)+n); \ + l = ao_left_mask(x); \ + if (l) { \ + n -= AO_UNIT - ((x) & AO_MASK); \ + if (n < 0) { \ + n = 0; \ + l &= r; \ + r = 0; \ + } \ + } \ + n >>= AO_SHIFT; \ +} + +#define ao_clip(val,min,max) do { \ + if (val < min) { \ + val = min; \ + } else if (val > max) { \ + val = max; \ + } \ + } while (0) + +static inline uint32_t +ao_do_mask_rrop(uint32_t dst, uint32_t and, uint32_t xor, uint32_t mask) { + return (dst & (and | ~mask)) ^ (xor & mask); +} + +static inline uint32_t +ao_do_rrop(uint32_t dst, uint32_t and, uint32_t xor) { + return (dst & and) ^ xor; +} + +void +ao_blt(uint32_t *src_line, + int16_t src_stride, + int16_t src_x, + uint32_t *dst_line, + int16_t dst_stride, + int16_t dst_x, + int16_t width, + int16_t height, + uint8_t rop, + uint8_t reverse, + uint8_t upsidedown); + +void +ao_solid(uint32_t and, + uint32_t xor, + uint32_t *dst, + int16_t dst_stride, + int16_t dst_x, + int16_t width, + int16_t height); + +int16_t +ao_glyph(const struct ao_bitmap *dst, + int16_t x, + int16_t y, + uint8_t c, + uint8_t rop); + +#endif /* _AO_DRAW_INT_H_ */ diff --git a/src/draw/ao_font.h b/src/draw/ao_font.h new file mode 100644 index 00000000..5e31dd11 --- /dev/null +++ b/src/draw/ao_font.h @@ -0,0 +1,139 @@ +static const uint8_t glyph_bytes[1568] = { + 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x00, 0x00, 0x04, 0x0e, 0x1f, 0x0e, 0x04, 0x00, 0x0a, 0x05, + 0x0a, 0x05, 0x0a, 0x05, 0x00, 0x05, 0x07, 0x05, 0x05, 0x0e, 0x04, 0x04, 0x03, 0x01, 0x03, 0x0d, + 0x04, 0x0c, 0x04, 0x03, 0x01, 0x03, 0x06, 0x0a, 0x06, 0x0a, 0x01, 0x01, 0x03, 0x0c, 0x04, 0x0c, + 0x04, 0x04, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x0e, 0x04, 0x00, 0x0e, 0x00, 0x00, 0x09, + 0x0b, 0x0d, 0x09, 0x04, 0x04, 0x0c, 0x05, 0x05, 0x05, 0x02, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x1c, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0x00, 0x04, 0x04, 0x04, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x02, 0x04, 0x08, 0x0e, 0x00, 0x02, 0x04, 0x08, + 0x04, 0x02, 0x0e, 0x00, 0x00, 0x00, 0x0e, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x08, 0x0e, 0x04, 0x0e, + 0x02, 0x00, 0x00, 0x0c, 0x02, 0x07, 0x02, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x04, 0x00, 0x0a, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x00, 0x00, 0x0e, 0x05, 0x0e, + 0x14, 0x0e, 0x00, 0x01, 0x09, 0x04, 0x02, 0x09, 0x08, 0x00, 0x00, 0x02, 0x05, 0x02, 0x05, 0x0a, + 0x00, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x02, 0x02, 0x02, 0x04, 0x00, 0x02, + 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, 0x00, 0x05, 0x02, 0x07, 0x02, 0x05, 0x00, 0x00, 0x04, 0x04, + 0x1f, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x02, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, + 0x02, 0x05, 0x05, 0x05, 0x05, 0x02, 0x00, 0x02, 0x03, 0x02, 0x02, 0x02, 0x07, 0x00, 0x06, 0x09, + 0x08, 0x04, 0x02, 0x0f, 0x00, 0x0f, 0x08, 0x06, 0x08, 0x09, 0x06, 0x00, 0x04, 0x06, 0x05, 0x0f, + 0x04, 0x04, 0x00, 0x0f, 0x01, 0x07, 0x08, 0x09, 0x06, 0x00, 0x06, 0x01, 0x07, 0x09, 0x09, 0x06, + 0x00, 0x0f, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x06, 0x09, 0x06, 0x09, 0x09, 0x06, 0x00, 0x06, + 0x09, 0x09, 0x0e, 0x08, 0x06, 0x00, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x00, 0x06, 0x06, + 0x00, 0x06, 0x02, 0x01, 0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0x01, 0x02, 0x04, 0x02, 0x01, 0x00, 0x02, 0x05, 0x04, 0x02, 0x00, 0x02, 0x00, + 0x06, 0x09, 0x0d, 0x0d, 0x01, 0x06, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x07, 0x09, + 0x07, 0x09, 0x09, 0x07, 0x00, 0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x00, 0x07, 0x09, 0x09, 0x09, + 0x09, 0x07, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x01, + 0x00, 0x06, 0x09, 0x01, 0x0d, 0x09, 0x0e, 0x00, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x09, 0x00, 0x07, + 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x08, 0x08, 0x08, 0x08, 0x09, 0x06, 0x00, 0x09, 0x05, 0x03, + 0x03, 0x05, 0x09, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0f, 0x00, 0x09, 0x0f, 0x0f, 0x09, 0x09, + 0x09, 0x00, 0x09, 0x0b, 0x0b, 0x0d, 0x0d, 0x09, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, + 0x07, 0x09, 0x09, 0x07, 0x01, 0x01, 0x00, 0x06, 0x09, 0x09, 0x09, 0x0b, 0x06, 0x08, 0x07, 0x09, + 0x09, 0x07, 0x05, 0x09, 0x00, 0x06, 0x09, 0x02, 0x04, 0x09, 0x06, 0x00, 0x07, 0x02, 0x02, 0x02, + 0x02, 0x02, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x06, 0x06, + 0x00, 0x09, 0x09, 0x09, 0x0f, 0x0f, 0x09, 0x00, 0x09, 0x09, 0x06, 0x06, 0x09, 0x09, 0x00, 0x05, + 0x05, 0x05, 0x02, 0x02, 0x02, 0x00, 0x0f, 0x08, 0x04, 0x02, 0x01, 0x0f, 0x00, 0x07, 0x01, 0x01, + 0x01, 0x01, 0x07, 0x00, 0x00, 0x01, 0x02, 0x04, 0x08, 0x00, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, + 0x07, 0x00, 0x02, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x03, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x01, 0x01, + 0x07, 0x09, 0x09, 0x07, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x06, 0x00, 0x08, 0x08, 0x0e, 0x09, + 0x09, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x04, 0x0a, 0x02, 0x07, 0x02, 0x02, + 0x00, 0x00, 0x00, 0x0e, 0x09, 0x06, 0x01, 0x0e, 0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x00, 0x02, + 0x00, 0x03, 0x02, 0x02, 0x07, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x05, 0x02, 0x01, 0x01, 0x05, + 0x03, 0x05, 0x09, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x00, 0x00, 0x05, 0x0f, 0x09, + 0x09, 0x00, 0x00, 0x00, 0x07, 0x09, 0x09, 0x09, 0x00, 0x00, 0x00, 0x06, 0x09, 0x09, 0x06, 0x00, + 0x00, 0x00, 0x07, 0x09, 0x09, 0x07, 0x01, 0x00, 0x00, 0x0e, 0x09, 0x09, 0x0e, 0x08, 0x00, 0x00, + 0x07, 0x09, 0x01, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x03, 0x0c, 0x07, 0x00, 0x02, 0x02, 0x07, 0x02, + 0x02, 0x0c, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x00, 0x00, 0x05, 0x05, 0x05, 0x02, + 0x00, 0x00, 0x00, 0x09, 0x09, 0x0f, 0x0f, 0x00, 0x00, 0x00, 0x09, 0x06, 0x06, 0x09, 0x00, 0x00, + 0x00, 0x09, 0x09, 0x0a, 0x04, 0x02, 0x00, 0x00, 0x0f, 0x04, 0x02, 0x0f, 0x00, 0x04, 0x02, 0x03, + 0x02, 0x02, 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x06, 0x02, 0x02, + 0x01, 0x00, 0x0a, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x04, + 0x0e, 0x05, 0x05, 0x0e, 0x04, 0x00, 0x0c, 0x02, 0x07, 0x02, 0x0d, 0x00, 0x00, 0x11, 0x0e, 0x0a, + 0x0e, 0x11, 0x00, 0x05, 0x05, 0x02, 0x07, 0x02, 0x02, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, 0x04, + 0x00, 0x0c, 0x02, 0x06, 0x0a, 0x0c, 0x08, 0x06, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, + 0x11, 0x15, 0x13, 0x15, 0x11, 0x0e, 0x06, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, + 0x09, 0x12, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, + 0x00, 0x00, 0x0e, 0x11, 0x17, 0x13, 0x13, 0x11, 0x0e, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x0a, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x1f, 0x00, 0x06, 0x04, + 0x02, 0x06, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x06, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x07, 0x01, 0x0e, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, + 0x00, 0x00, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x02, 0x04, + 0x06, 0x04, 0x0e, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, + 0x12, 0x09, 0x00, 0x00, 0x01, 0x01, 0x01, 0x09, 0x0c, 0x0e, 0x08, 0x01, 0x01, 0x01, 0x0d, 0x08, + 0x04, 0x0c, 0x03, 0x03, 0x02, 0x0b, 0x0c, 0x0e, 0x08, 0x02, 0x00, 0x02, 0x01, 0x05, 0x02, 0x00, + 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, + 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, + 0x09, 0x09, 0x00, 0x06, 0x09, 0x09, 0x0f, 0x09, 0x09, 0x00, 0x0e, 0x05, 0x0d, 0x07, 0x05, 0x0d, + 0x00, 0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x02, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, + 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f, 0x00, 0x0f, 0x01, 0x07, + 0x01, 0x01, 0x0f, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, + 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x07, 0x00, + 0x07, 0x0a, 0x0b, 0x0a, 0x0a, 0x07, 0x00, 0x0d, 0x09, 0x0b, 0x0d, 0x0d, 0x09, 0x00, 0x06, 0x09, + 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, + 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06, + 0x00, 0x00, 0x00, 0x09, 0x06, 0x06, 0x09, 0x00, 0x0e, 0x0d, 0x0d, 0x0b, 0x0b, 0x07, 0x00, 0x09, + 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, + 0x09, 0x09, 0x06, 0x00, 0x09, 0x09, 0x09, 0x09, 0x09, 0x06, 0x00, 0x05, 0x05, 0x05, 0x02, 0x02, + 0x02, 0x00, 0x01, 0x07, 0x09, 0x07, 0x01, 0x01, 0x00, 0x06, 0x09, 0x07, 0x09, 0x0b, 0x05, 0x01, + 0x02, 0x04, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x04, 0x02, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x04, 0x0a, + 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x0a, 0x05, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x0a, 0x00, 0x0e, 0x09, + 0x0d, 0x0a, 0x00, 0x06, 0x06, 0x0e, 0x09, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x05, 0x0e, + 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x06, 0x02, 0x02, 0x04, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x04, + 0x02, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x02, 0x05, 0x06, 0x0d, 0x03, 0x06, 0x00, 0x05, 0x00, 0x06, + 0x0d, 0x03, 0x06, 0x00, 0x01, 0x02, 0x03, 0x02, 0x02, 0x07, 0x00, 0x02, 0x01, 0x03, 0x02, 0x02, + 0x07, 0x00, 0x02, 0x05, 0x03, 0x02, 0x02, 0x07, 0x00, 0x05, 0x00, 0x03, 0x02, 0x02, 0x07, 0x00, + 0x02, 0x0c, 0x06, 0x09, 0x09, 0x06, 0x00, 0x0a, 0x05, 0x07, 0x09, 0x09, 0x09, 0x00, 0x02, 0x04, + 0x06, 0x09, 0x09, 0x06, 0x00, 0x04, 0x02, 0x06, 0x09, 0x09, 0x06, 0x00, 0x06, 0x00, 0x06, 0x09, + 0x09, 0x06, 0x00, 0x0a, 0x05, 0x06, 0x09, 0x09, 0x06, 0x00, 0x05, 0x00, 0x06, 0x09, 0x09, 0x06, + 0x00, 0x00, 0x06, 0x00, 0x0f, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0e, 0x0d, 0x0b, 0x07, 0x00, 0x02, + 0x04, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x04, 0x02, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x06, 0x00, 0x09, + 0x09, 0x09, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x09, 0x09, 0x0e, 0x00, 0x04, 0x02, 0x09, 0x09, 0x0a, + 0x04, 0x02, 0x00, 0x01, 0x07, 0x09, 0x09, 0x07, 0x01, 0x0a, 0x00, 0x09, 0x09, 0x0a, 0x04, 0x02, +}; + +static const uint16_t glyph_pos[256] = { + 0, 7, 14, 21, 28, 35, 42, 49, + 56, 63, 70, 77, 84, 91, 98, 105, + 112, 119, 126, 133, 140, 147, 154, 161, + 168, 175, 182, 189, 196, 203, 210, 217, + 224, 231, 238, 245, 252, 259, 266, 273, + 280, 287, 294, 301, 308, 315, 322, 329, + 336, 343, 350, 357, 364, 371, 378, 385, + 392, 399, 406, 413, 420, 427, 434, 441, + 448, 455, 462, 469, 476, 483, 490, 497, + 504, 511, 518, 525, 532, 539, 546, 553, + 560, 567, 574, 581, 588, 595, 602, 609, + 616, 623, 630, 637, 644, 651, 658, 665, + 672, 679, 686, 693, 700, 707, 714, 721, + 728, 735, 742, 749, 756, 763, 770, 777, + 784, 791, 798, 805, 812, 819, 826, 833, + 840, 847, 854, 861, 868, 875, 882, 889, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 896, 903, 910, 917, 924, 931, 938, 945, + 952, 959, 966, 973, 980, 987, 994, 1001, + 1008, 1015, 1022, 1029, 1036, 1043, 1050, 1057, + 1064, 1071, 1078, 1085, 1092, 1099, 1106, 1113, + 1120, 1127, 1134, 1141, 1148, 1155, 1162, 1169, + 1176, 1183, 1190, 1197, 1204, 1211, 1218, 1225, + 1232, 1239, 1246, 1253, 1260, 1267, 1274, 1281, + 1288, 1295, 1302, 1309, 1316, 1323, 1330, 1337, + 1344, 1351, 1358, 1365, 1372, 1379, 1386, 1393, + 1400, 1407, 1414, 1421, 1428, 1435, 1442, 1449, + 1456, 1463, 1470, 1477, 1484, 1491, 1498, 1505, + 1512, 1519, 1526, 1533, 1540, 1547, 1554, 1561, +}; + +#define GLYPH_WIDTH 5 +#define GLYPH_HEIGHT 7 +#define GLYPH_ASCENT 6 diff --git a/src/draw/ao_line.c b/src/draw/ao_line.c new file mode 100644 index 00000000..ed1fc21c --- /dev/null +++ b/src/draw/ao_line.c @@ -0,0 +1,314 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_draw.h" +#include "ao_draw_int.h" + +#define ao_mask(x,w) (ao_right(AO_ALLONES,(x) & AO_MASK) & \ + ao_left(AO_ALLONES,(FB_UNIT - ((x)+(w))) & AO_MASK)) + + +/* out of clip region codes */ +#define OUT_LEFT 0x08 +#define OUT_RIGHT 0x04 +#define OUT_ABOVE 0x02 +#define OUT_BELOW 0x01 + +/* major axis for bresenham's line */ +#define X_AXIS 0 +#define Y_AXIS 1 + +/* + * Line clipping. Clip to the box, bringing the coordinates forward while + * preserving the actual slope and error + * + * + * X major line, clip X: + * + * adjust_x = -x; + * + * e += adjust_x * e1; + * + * adjust_y = (e + -e3-1) / -e3; + * + * e -= adjust_y / -e3; + * + * X major line, clip Y: + * + * adjust_y = -y; + + * + * e -= adjust_y / -e3; + * + * adjust_x = e / e1; + */ + + + + +static void +ao_bres(const struct ao_bitmap *dst_bitmap, + int16_t signdx, + int16_t signdy, + int16_t axis, + int16_t x1, + int16_t y1, + int16_t e, + int16_t e1, + int16_t e3, + int16_t len, + uint32_t and, + uint32_t xor) +{ + int16_t stride = dst_bitmap->stride; + uint32_t *dst = dst_bitmap->base; + uint32_t mask0, mask; + + mask0 = 1; + if (signdx < 0) + mask0 = ao_right(1, AO_UNIT - 1); + + if (signdy < 0) + stride = -stride; + + dst = dst + y1 * stride + (x1 >> AO_SHIFT); + mask = ao_right(1, x1 & AO_MASK); + + while (len--) { + /* clip each point */ + + *dst = ao_do_mask_rrop(*dst, and, xor, mask); + + if (axis == X_AXIS) { + if (signdx < 0) + mask = ao_left(mask, 1); + else + mask = ao_right(mask, 1); + if (!mask) { + dst += signdx; + mask = mask0; + } + e += e1; + if (e >= 0) { + dst += stride; + e += e3; + } + } else { + dst += stride; + e += e1; + if (e >= 0) { + if (signdx < 0) + mask = ao_left(mask, 1); + else + mask = ao_right(mask, 1); + if (!mask) { + dst += signdx; + mask = mask0; + } + e += e3; + } + } + } +} + +struct ao_cc { + int16_t major; + int16_t minor; + int16_t sign_major; + int16_t sign_minor; + int16_t e; + int16_t e1; + int16_t e3; + int8_t first; +}; + +/* line clipping box */ +struct ao_cbox { + int16_t maj1, min1; + int16_t maj2, min2; +}; + +/* -b <= a, so we need to make a bigger */ +static int16_t +div_ceil(int32_t a, int16_t b) { + return (a + b + b - 1) / b - 1; +} + +static int16_t +div_floor_plus_one(int32_t a, int16_t b) { + return (a + b) / b; +} + +static int8_t +ao_clip_line(struct ao_cc *c, struct ao_cbox *b) +{ + int32_t adjust_major = 0, adjust_minor = 0; + + /* Clip major axis */ + if (c->major < b->maj1) { + if (c->sign_major <= 0) + return FALSE; + adjust_major = b->maj1 - c->major; + } else if (c->major >= b->maj2) { + if (c->sign_major >= 0) + return FALSE; + adjust_major = c->major - (b->maj2-1); + } + + /* Clip minor axis */ + if (c->minor < b->min1) { + if (c->sign_minor <= 0) + return FALSE; + adjust_minor = b->min1 - c->minor; + } else if (c->minor >= b->min2) { + if (c->sign_minor >= 0) + return FALSE; + adjust_minor = c->minor - (b->min2-1); + } + + /* If unclipped, we're done */ + if (adjust_major == 0 && adjust_minor == 0) + return TRUE; + + /* See how much minor adjustment would happen during + * a major clip. This is a bit tricky because line drawing + * isn't symmetrical when the line passes exactly between + * two pixels, we have to pick which one gets drawn + */ + int32_t adj_min; + + if (!c->first) + adj_min = div_ceil(c->e + adjust_major * c->e1, -c->e3); + else + adj_min = div_floor_plus_one(c->e + adjust_major * c->e1, -c->e3); + + if (adj_min < adjust_minor) { + if (c->first) + adjust_major = div_ceil(c->e - adjust_minor * c->e3, c->e1); + else + adjust_major = div_floor_plus_one(c->e - adjust_minor * c->e3, c->e1); + } else { + adjust_minor = adj_min; + } + + c->e += adjust_major * c->e1 + adjust_minor * c->e3; + + c->major += c->sign_major * adjust_major; + c->minor += c->sign_minor * adjust_minor; + + return TRUE; +} + +void +ao_line(const struct ao_bitmap *dst, + int16_t x1, + int16_t y1, + int16_t x2, + int16_t y2, + uint32_t fill, + uint8_t rop) +{ + int16_t adx, ady; + int16_t e, e1, e2, e3; + int16_t signdx = 1, signdy = 1; + int16_t axis; + int16_t len; + struct ao_cc clip_1, clip_2; + struct ao_cbox cbox; + + if ((adx = x2 - x1) < 0) { + adx = -adx; + signdx = -1; + } + if ((ady = y2 - y1) < 0) { + ady = -ady; + signdy = -1; + } + + if (adx > ady) { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + + clip_1.major = x1; + clip_1.minor = y1; + clip_2.major = x2; + clip_2.minor = y2; + clip_1.sign_major = signdx; + clip_1.sign_minor = signdy; + + cbox.maj1 = 0; + cbox.maj2 = dst->width; + cbox.min1 = 0; + cbox.min2 = dst->height; + } else { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + + clip_1.major = y1; + clip_1.minor = x1; + clip_2.major = y2; + clip_2.minor = x2; + clip_1.sign_major = signdy; + clip_1.sign_minor = signdx; + + cbox.maj1 = 0; + cbox.maj2 = dst->height; + cbox.min1 = 0; + cbox.min2 = dst->width; + } + + e3 = e2 - e1; + e = e - e1; + + clip_1.first = TRUE; + clip_2.first = FALSE; + clip_2.e = clip_1.e = e; + clip_2.e1 = clip_1.e1 = e1; + clip_2.e3 = clip_1.e3 = e3; + clip_2.sign_major = -clip_1.sign_major; + clip_2.sign_minor = -clip_1.sign_minor; + + if (!ao_clip_line(&clip_1, &cbox)) + return; + + if (!ao_clip_line(&clip_2, &cbox)) + return; + + len = clip_1.sign_major * (clip_2.major - clip_1.major) + clip_2.first; + + if (len <= 0) + return; + + if (adx > ady) { + x1 = clip_1.major; + y1 = clip_1.minor; + } else { + x1 = clip_1.minor; + y1 = clip_1.major; + } + ao_bres(dst, + signdx, + signdy, + axis, + x1, + y1, + clip_1.e, e1, e3, len, + ao_and(rop, fill), + ao_xor(rop, fill)); +} diff --git a/src/draw/ao_pattern.c b/src/draw/ao_pattern.c new file mode 100644 index 00000000..0d1dc765 --- /dev/null +++ b/src/draw/ao_pattern.c @@ -0,0 +1,80 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_draw.h" +#include "ao_draw_int.h" + +static inline uint32_t +ao_pattern_expand(uint8_t v, uint8_t rot) +{ + uint32_t r; + + if (rot) + v = ao_left(v, 8-rot) | ao_right(v, rot); + r = v; + return (r << 24) | (r << 16) | (r << 8) | (r); +} + +static inline int +min(int a, int b) { + return a < b ? a : b; +} + +void +ao_pattern(const struct ao_bitmap *dst, + int16_t x, + int16_t y, + int16_t width, + int16_t height, + const struct ao_pattern *pattern, + int16_t pat_x, + int16_t pat_y, + uint8_t rop) +{ + uint32_t pat[8]; + + int16_t x2 = x + width; + int16_t y2 = y + height; + + ao_clip(x, 0, dst->width); + ao_clip(x2, 0, dst->width); + ao_clip(y, 0, dst->height); + ao_clip(y2, 0, dst->height); + + if (x < x2 && y < y2) { + int xrot = (x - pat_x) & 7; + int yrot = (y - pat_y) & 7; + int i; + int16_t dst_x, dst_y; + + for (i = 0; i < 8; i++) + pat[(i + yrot) & 7] = ao_pattern_expand(pattern->pattern[i], xrot); + for (dst_y = y; dst_y < y2; dst_y += 8) { + int h = min(y2 - dst_y, 8); + for (dst_x = x; dst_x < x2; dst_x += 8) { + int w = min(x2 - dst_x, 8); + + ao_blt(pat, 1, 0, + dst->base + dst_y * dst->stride, + dst->stride, + dst_x, + w, h, + rop, + 0, 0); + } + } + } +} + diff --git a/src/draw/ao_rect.c b/src/draw/ao_rect.c new file mode 100644 index 00000000..71fa4aea --- /dev/null +++ b/src/draw/ao_rect.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_draw.h" +#include "ao_draw_int.h" + +void +ao_rect(const struct ao_bitmap *dst, + int16_t x, + int16_t y, + int16_t width, + int16_t height, + uint32_t fill, + uint8_t rop) +{ + int16_t x2 = x + width; + int16_t y2 = y + height; + + ao_clip(x, 0, dst->width); + ao_clip(x2, 0, dst->width); + ao_clip(y, 0, dst->height); + ao_clip(y2, 0, dst->height); + + if (x < x2 && y < y2) { + ao_solid(ao_and(rop, fill), + ao_xor(rop, fill), + dst->base + y * dst->stride, + dst->stride, + x, + x2 - x, + y2 - y); + } +} + diff --git a/src/draw/ao_text.c b/src/draw/ao_text.c new file mode 100644 index 00000000..7ce2a623 --- /dev/null +++ b/src/draw/ao_text.c @@ -0,0 +1,65 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_draw.h" +#include "ao_draw_int.h" +#include "ao_font.h" + +const struct ao_font ao_font = { + .width = GLYPH_WIDTH, + .height = GLYPH_HEIGHT, + .ascent = GLYPH_ASCENT, + .descent = GLYPH_HEIGHT - GLYPH_ASCENT, +}; + +void +ao_text(const struct ao_bitmap *dst, + int16_t x, + int16_t y, + char *string, + uint32_t fill, + uint8_t rop) +{ + uint32_t src[GLYPH_HEIGHT]; + char c; + int h; + + struct ao_bitmap src_bitmap = { + .base = src, + .stride = 1, + .width = GLYPH_WIDTH, + .height = GLYPH_HEIGHT + }; + + y -= GLYPH_ASCENT; + + rop = (rop & 3) | 0x4; + + if ((fill&1) == 0) + rop ^= 3; + + while ((c = *string++)) { + const uint8_t *bytes = &glyph_bytes[glyph_pos[(uint8_t) c]]; + + for (h = 0; h < GLYPH_HEIGHT; h++) + src[h] = bytes[h]; + + ao_copy(dst, + x, y, GLYPH_WIDTH, GLYPH_HEIGHT, + &src_bitmap, + 0, 0, rop); + x += GLYPH_WIDTH; + } +} diff --git a/src/draw/font-convert b/src/draw/font-convert new file mode 100755 index 00000000..1985e418 --- /dev/null +++ b/src/draw/font-convert @@ -0,0 +1,150 @@ +#!/usr/bin/nickle + +typedef struct { + int[] bytes; + int width; + int height; + int encoding; + int location; +} glyph_t; + +typedef struct { + glyph_t[...] glyphs; + int default_char; + int ascent; +} font_t; + +glyph_t +read_glyph(file f) +{ + glyph_t glyph = { .encoding = -1, .bytes = (int[...]){}, .width = 0 }; + + while (!File::end(f)) { + string l = fgets(f); + + string[*] tokens = String::split(l, " "); + if (dim(tokens) == 0) + continue; + + switch (tokens[0]) { + case "ENCODING": + glyph.encoding = atoi(tokens[1]); + break; + case "DWIDTH": + glyph.width = atoi(tokens[1]); + break; + case "BBX": + glyph.height = atoi(tokens[2]); + break; + case "ENDCHAR": + return glyph; + case "BITMAP": + while (!File::end(f)) { + string l = fgets(f); + if (l == "ENDCHAR") + return glyph; + glyph.bytes[dim(glyph.bytes)] = atoi(l, 16); + } + break; + } + } + return glyph; +} + +font_t read_font(file f) { + font_t font = { .glyphs = {}, .default_char = -1 }; + bool in_head = true; + + while (in_head && !File::end(f)) { + string l = File::fgets(f); + + string[*] tokens = String::split(l, " "); + switch (tokens[0]) { + case "DEFAULT_CHAR": + font.default_char = atoi(tokens[1]); + break; + case "FONT_ASCENT": + font.ascent = atoi(tokens[1]); + break; + case "CHARS": + in_head = false; + break; + } + } + while (!File::end(f)) { + glyph_t glyph = read_glyph(f); + if (glyph.encoding == -1) + break; + font.glyphs[dim(font.glyphs)] = glyph; + } + return font; +} + +int +flip_byte(int x) +{ + int dest = 0; + + for (int i = 0; i < 8; i++) + dest |= ((x >> (7 - i)) & 1) << i; + return dest; +} + +void print_font(font_t font) { + int width = font.glyphs[0].width; + int height = font.glyphs[0].height; + int[256] pos = { -1 ... }; + int[...] bytes; + + if (false) { + for (int i = 1; i < dim(font.glyphs); i++) { + if (font.glyphs[i].width != width || + font.glyphs[i].height != height) + { + File::fprintf(stderr, "font not constant size, glyph %d is %dx%d\n", + font.glyphs[i].encoding, font.glyphs[i].width, font.glyphs[i].height); + exit(1); + } + } + } + + if (font.default_char == -1) + font.default_char = font.glyphs[0].encoding; + + /* build byte array */ + for (int i = 0; i < dim(font.glyphs); i++) { + pos[font.glyphs[i].encoding] = dim(bytes); + for (int b = 0; b < dim(font.glyphs[i].bytes); b++) + bytes[dim(bytes)] = font.glyphs[i].bytes[b]; + } + + /* Fill in default glyph */ + for (int i = 0; i < dim(pos); i++) + if (pos[i] == -1) + pos[i] = pos[font.default_char]; + + printf("static const uint8_t glyph_bytes[%d] = {", dim(bytes)); + for (int b = 0; b < dim(bytes); b++) { + if ((b & 15) == 0) + printf("\n\t"); + printf("0x%02x, ", flip_byte(bytes[b])); + } + printf("\n};\n\n"); + + printf("static const uint16_t glyph_pos[%d] = {", dim(pos)); + for (int i = 0; i < dim(pos); i++) { + if ((i & 7) == 0) + printf("\n\t"); + printf("%4d, ", pos[i]); + } + printf("\n};\n\n"); + + printf("#define GLYPH_WIDTH %d\n", width); + printf("#define GLYPH_HEIGHT %d\n", height); + printf("#define GLYPH_ASCENT %d\n", font.ascent); +} + +twixt (file f = File::open(argv[1], "r"); File::close(f)) { + font_t font = read_font(f); + print_font(font); +} diff --git a/src/draw/line.5c b/src/draw/line.5c new file mode 100644 index 00000000..747768b0 --- /dev/null +++ b/src/draw/line.5c @@ -0,0 +1,389 @@ +#!/usr/bin/nickle + +autoimport Cairo; +autoload PRNG; + +int +sign(int x) +{ + return x == 0 ? 0 : x < 0 ? -1 : 1; +} + +int X_AXIS = 0; +int Y_AXIS = 1; + +typedef struct { + int major; + int minor; + int sign_major; + int sign_minor; + int e; + int e1; + int e3; + bool first; +} clip_context; + +typedef struct { + int maj1, min1, maj2, min2; +} clip_box; + +typedef struct { + int x1, y1, x2, y2; +} box; + +typedef struct { + int x, y; +} point; + +typedef struct { + int x1, y1, x2, y2; + box b; + point[] clipped; + point[] run; +} test; + +box bounds = { .x1 = 10, .x2 = 30, .y1 = 10, .y2 = 30 }; + +int +div_ceil(a, b) { + a += b; + assert(a >= 0 && b > 0, "bad divide args %d %d\n", a, b); + return (a + b - 1) // b - 1; +} + +int +div_floor_plus_one(a, b) { + a += b; + assert(a >= 0 && b > 0, "bad divide args %d %d\n", a, b); + return a // b; +} + +bool +clip(*clip_context c, *clip_box b) +{ + int adjust_major = 0, adjust_minor = 0; + + /* Clip major axis */ + if (c->major < b->maj1) { + if (c->sign_major <= 0) + return false; + adjust_major = b->maj1 - c->major; + } else if (c->major >= b->maj2) { + if (c->sign_major >= 0) + return false; + adjust_major = c->major - (b->maj2-1); + } + + /* Clip minor axis */ + if (c->minor < b->min1) { + if (c->sign_minor <= 0) + return false; + adjust_minor = b->min1 - c->minor; + } else if (c->minor >= b->min2) { + if (c->sign_minor >= 0) + return false; + adjust_minor = c->minor - (b->min2-1); + } + + /* If unclipped, we're done */ + if (adjust_major == 0 && adjust_minor == 0) + return true; + + /* See how much minor adjustment would happen during + * a major clip. This is a bit tricky because line drawing + * isn't symmetrical when the line passes exactly between + * two pixels, we have to pick which one gets drawn + */ + int adj_min; + + if (!c->first) + adj_min = div_ceil(c->e + adjust_major * c->e1, -c->e3); + else + adj_min = div_floor_plus_one(c->e + adjust_major * c->e1, -c->e3); + + /* Compare that to the minor clip and pick + * the larger amount. + */ + printf ("\tinitial major %d minor %d error %d e1 %d e3 %d\n", c->major, c->minor, c->e, c->e1, c->e3); + + if (adj_min < adjust_minor) { + printf("\tminor clip dominates %d < %d. adjust major %d -> ", + adj_min, adjust_minor, adjust_major); + if (c->first) + adjust_major = div_ceil(c->e - adjust_minor * c->e3, c->e1); + else + adjust_major = div_floor_plus_one(c->e - adjust_minor * c->e3, c->e1); + printf("%d\n", adjust_major); + } else { + printf("\tminor clip dominates %d > %d. adjust minor %d -> ", + adj_min, adjust_minor, adjust_minor); + adjust_minor = adj_min; + printf("%d\n", adjust_minor); + } + + c->e += adjust_major * c->e1 + adjust_minor * c->e3; + + c->major += c->sign_major * adjust_major; + c->minor += c->sign_minor * adjust_minor; + + printf ("\tadjust major %d adjust minor %d e %d e1 %d e3 %e\n", + adjust_major, adjust_minor, c->e, c->e1, c->e3); + + if (c->e >= 0) + printf ("error positive e %d e1 %d e3 %d\n", + c->e, c->e1, c->e3); + if (c->e < c->e3) + printf ("error magnitude too large e %d e1 %d e3 %d\n", c->e, c->e1, c->e3); + + return true; +} + +test +line(int x1, int y1, int x2, int y2, *box b) { + + int dx = x2 - x1; + int dy = y2 - y1; + int signdx = sign(dx); + int signdy = sign(dy); + int adx = abs(dx); + int ady = abs(dy); + int axis; + int e, e1, e2, e3; + int len; + clip_context clip_1, clip_2; + clip_box c; + bool clipped = false; + test t = { + .x1 = x1, + .y1 = y1, + .x2 = x2, + .y2 = y2, + .b = *b, + .clipped = (point[...]) {}, + .run = (point[...]) {} + }; + + if (adx >= ady) { + axis = X_AXIS; + e1 = ady << 1; + e2 = e1 - (adx << 1); + e = e1 - adx; + len = adx; + + clip_1.major = x1; + clip_1.minor = y1; + clip_2.major = x2; + clip_2.minor = y2; + clip_1.sign_major = signdx; + clip_1.sign_minor = signdy; + + c.maj1 = b->x1; + c.maj2 = b->x2; + c.min1 = b->y1; + c.min2 = b->y2; + } else { + axis = Y_AXIS; + e1 = adx << 1; + e2 = e1 - (ady << 1); + e = e1 - ady; + len = ady; + + clip_1.major = y1; + clip_1.minor = x1; + clip_2.major = y2; + clip_2.minor = x2; + clip_1.sign_major = signdy; + clip_1.sign_minor = signdx; + c.maj1 = b->y1; + c.maj2 = b->y2; + c.min1 = b->x1; + c.min2 = b->x2; + } + + e3 = e2 - e1; + e = e - e1; + + clip_1.first = true; + clip_2.first = false; + clip_2.e = clip_1.e = e; + clip_2.e1 = clip_1.e1 = e1; + clip_2.e3 = clip_1.e3 = e3; + clip_2.sign_major = -clip_1.sign_major; + clip_2.sign_minor = -clip_1.sign_minor; + + printf ("clip start:\n"); + if (!clip(&clip_1, &c)) + clipped = true; + + printf("clip end:\n"); + if (!clip(&clip_2, &c)) + clipped = true; + + int clip_len; + int clip_x, clip_y; + int clip_e; + int x_major, x_minor; + int y_major, y_minor; + + clip_len = clip_1.sign_major * (clip_2.major - clip_1.major); + if (clip_len < 0) + clipped = true; + + int x, y; + + if (axis == X_AXIS) { + x = clip_1.major; + y = clip_1.minor; + x_major = clip_1.sign_major; + x_minor = 0; + y_major = 0; + y_minor = clip_1.sign_minor; + } else { + x = clip_1.minor; + y = clip_1.major; + x_major = 0; + x_minor = clip_1.sign_minor; + y_major = clip_1.sign_major; + y_minor = 0; + } + + clip_e = clip_1.e; + + if (clipped) + clip_len = -1; + + while (clip_len-- >= 0) { + t.clipped[dim(t.clipped)] = (point) { .x = x, .y = y }; + x += x_major; + y += y_major; + clip_e += e1; + if (clip_e >= 0) { + x += x_minor; + y += y_minor; + clip_e += e3; + } + } + + x = x1; + y = y1; + + while (len-- >= 0) { + if (bounds.x1 <= x && x < bounds.x2 && + bounds.y1 <= y && y < bounds.y2) { + t.run[dim(t.run)] = (point) { .x = x, .y = y }; + } + x += x_major; + y += y_major; + e += e1; + if (e >= 0) { + x += x_minor; + y += y_minor; + e += e3; + } + } + return t; +} + +void read_events (Cairo::cairo_t cr) +{ + file event = Cairo::open_event(cr); + + while (!File::end(event)) { + string event_line = File::fgets(event); + if (String::index(event_line, "delete") >= 0) + exit(0); + } +} + +#for (int y = 0; y < 20; y++) + +void +show(cairo_t cr, test t) +{ + rectangle(cr, 0, 0, 40, 40); + set_source_rgba(cr, 1, 1, 1, 1); + fill(cr); + + set_source_rgba(cr, 0, 1, 0, .2); + set_line_width(cr, 0.1); + for (int x = 0; x < 40; x++) { + move_to(cr, 0, x); + line_to(cr, 40, x); + move_to(cr, x, 0); + line_to(cr, x, 40); + } + stroke(cr); + + rectangle(cr, t.b.x1, t.b.y1, t.b.x2 - t.b.x1, t.b.y2 - t.b.y1); + set_line_width(cr, 0.1); + set_source_rgba(cr, 0, 0, 0, 1); + stroke(cr); + + move_to(cr, t.x1+.5, t.y1+.5); + line_to(cr, t.x2+.5, t.y2+.5); + move_to(cr, t.x2, t.y2); + line_to(cr, t.x2+1, t.y2+1); + move_to(cr, t.x2+1, t.y2); + line_to(cr, t.x2, t.y2+1); + stroke(cr); + + void pixels(point[] pt) { + for (int i = 0; i < dim(pt); i++) { + rectangle(cr, pt[i].x, pt[i].y, 1, 1); + } + fill(cr); + } + + set_source_rgba(cr, 1, 0, 0, .5); + pixels(t.clipped); + + set_source_rgba(cr, 0, 0, 1, .5); + pixels(t.run); +} + +bool +compare(test t) +{ + if (dim(t.clipped) != dim(t.run)) + return false; + + for (int i = 0; i < dim(t.clipped); i++) + if (t.clipped[i] != t.run[i]) + return false; + return true; +} + +void +doit(int i) +{ + int n; + *box b = &bounds; + + cairo_t cr = new(800, 800); + + scale(cr, 20, 20); + + for (;;) { + PRNG::srandom(i); + int x1 = PRNG::randint(40); + int x2 = PRNG::randint(40); + int y1 = PRNG::randint(40); + int y2 = PRNG::randint(40); + + test t = line (x1, y1, x2, y2, &bounds); + show(cr, t); + if (!compare(t)) { + printf("line %d -- %d x %d - %d x %d\n", i, x1, y1, x2, y2); + gets(); + } + i++; + } + + read_events(cr); +} + +int i = 0; +if (dim(argv) > 1) + i = atoi(argv[1]); + +doit(i); diff --git a/src/drivers/ao_as1107.c b/src/drivers/ao_as1107.c new file mode 100644 index 00000000..e0172d95 --- /dev/null +++ b/src/drivers/ao_as1107.c @@ -0,0 +1,105 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#include +#include + +static uint8_t as1107_configured; +static uint8_t as1107_mutex; + +static void +ao_as1107_start(void) { + ao_spi_get_bit(AO_AS1107_CS_PORT, AO_AS1107_CS_PIN, AO_AS1107_CS, AO_AS1107_SPI_INDEX, AO_AS1107_SPI_SPEED); +} + +static void +ao_as1107_stop(void) { + ao_spi_put_bit(AO_AS1107_CS_PORT, AO_AS1107_CS_PIN, AO_AS1107_CS, AO_AS1107_SPI_INDEX); +} + +static void +_ao_as1107_cmd(uint8_t addr, uint8_t value) +{ + uint8_t packet[2] = { addr, value }; + + ao_as1107_start(); + ao_spi_send(packet, 2, AO_AS1107_SPI_INDEX); + ao_as1107_stop(); +} + +static void +_ao_as1107_setup(void) +{ + if (!as1107_configured) { + as1107_configured = 1; + _ao_as1107_cmd(AO_AS1107_SHUTDOWN, AO_AS1107_SHUTDOWN_SHUTDOWN_RESET); + _ao_as1107_cmd(AO_AS1107_SHUTDOWN, AO_AS1107_SHUTDOWN_SHUTDOWN_NOP); + _ao_as1107_cmd(AO_AS1107_DECODE_MODE, AO_AS1107_DECODE); + _ao_as1107_cmd(AO_AS1107_SCAN_LIMIT, AO_AS1107_NUM_DIGITS - 1); + _ao_as1107_cmd(AO_AS1107_INTENSITY, 0x0f); + _ao_as1107_cmd(AO_AS1107_FEATURE, + (0 << AO_AS1107_FEATURE_CLK_EN) | + (0 << AO_AS1107_FEATURE_REG_RES) | + (1 << AO_AS1107_FEATURE_DECODE_SEL) | + (1 << AO_AS1107_FEATURE_SPI_EN) | + (0 << AO_AS1107_FEATURE_BLINK_EN) | + (0 << AO_AS1107_FEATURE_BLINK_FREQ) | + (0 << AO_AS1107_FEATURE_SYNC) | + (0 << AO_AS1107_FEATURE_BLINK_START)); + _ao_as1107_cmd(AO_AS1107_SHUTDOWN, AO_AS1107_SHUTDOWN_NORMAL_NOP); + } +} + +void +ao_as1107_write(uint8_t start, uint8_t count, uint8_t *values) +{ + uint8_t i; + ao_mutex_get(&as1107_mutex); + _ao_as1107_setup(); + for (i = 0; i < count; i++) + { + _ao_as1107_cmd(AO_AS1107_DIGIT(start + i), + values[i]); + } + ao_mutex_put(&as1107_mutex); +} + +void +ao_as1107_write_8(uint8_t start, uint8_t value) +{ + uint8_t values[2]; + + values[0] = (value >> 4); + values[1] = value & 0xf; + ao_as1107_write(start, 2, values); +} + +void +ao_as1107_write_16(uint8_t start, uint16_t value) +{ + uint8_t values[4]; + + values[0] = (value >> 12); + values[1] = (value >> 8) & 0xf; + values[2] = (value >> 4) & 0xf; + values[3] = (value) & 0xf; + ao_as1107_write(start, 4, values); +} + +void +ao_as1107_init(void) +{ + as1107_configured = 0; + ao_spi_init_cs(AO_AS1107_CS_PORT, (1 << AO_AS1107_CS_PIN)); +} diff --git a/src/drivers/ao_as1107.h b/src/drivers/ao_as1107.h new file mode 100644 index 00000000..a22b17db --- /dev/null +++ b/src/drivers/ao_as1107.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#ifndef _AO_AS1107_H_ +#define _AO_AS1107_H_ + +#define AO_AS1107_NO_OP 0x00 +#define AO_AS1107_DIGIT(n) (0x01 + (n)) +#define AO_AS1107_DECODE_MODE 0x09 +#define AO_AS1107_INTENSITY 0x0a +#define AO_AS1107_SCAN_LIMIT 0x0b +#define AO_AS1107_SHUTDOWN 0x0c +#define AO_AS1107_SHUTDOWN_SHUTDOWN_RESET 0x00 +#define AO_AS1107_SHUTDOWN_SHUTDOWN_NOP 0x80 +#define AO_AS1107_SHUTDOWN_NORMAL_RESET 0x01 +#define AO_AS1107_SHUTDOWN_NORMAL_NOP 0x81 + +#define AO_AS1107_FEATURE 0x0e +#define AO_AS1107_FEATURE_CLK_EN 0 /* external clock enable */ +#define AO_AS1107_FEATURE_REG_RES 1 +#define AO_AS1107_FEATURE_DECODE_SEL 2 /* select HEX decode */ +#define AO_AS1107_FEATURE_SPI_EN 3 +#define AO_AS1107_FEATURE_BLINK_EN 4 +#define AO_AS1107_FEATURE_BLINK_FREQ 5 +#define AO_AS1107_FEATURE_SYNC 6 +#define AO_AS1107_FEATURE_BLINK_START 7 +#define AO_AS1107_DISPLAY_TEST 0x0f + +void ao_as1107_init(void); + +void +ao_as1107_write(uint8_t start, uint8_t count, uint8_t *values); + +void +ao_as1107_write_8(uint8_t start, uint8_t value); + +void +ao_as1107_write_16(uint8_t start, uint16_t value); + +#ifndef AO_AS1107_DECODE +#error "must define AO_AS1107_DECODE" +#endif + +#ifndef AO_AS1107_NUM_DIGITS +#error "must define AO_AS1107_NUM_DIGITS" +#endif + +#endif /* _AO_AS1107_H_ */ diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index 725ac45a..07e92c67 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -39,8 +39,16 @@ static struct ao_button_state ao_button_state[AO_BUTTON_COUNT]; #define bit(q) AO_BUTTON_ ## q #define pin(q) AO_BUTTON_ ## q ## _PIN +#ifndef AO_BUTTON_INVERTED +#define AO_BUTTON_INVERTED 1 +#endif + +#if AO_BUTTON_INVERTED /* pins are inverted */ #define ao_button_value(b) !ao_gpio_get(port(b), bit(b), pin(b)) +#else +#define ao_button_value(b) ao_gpio_get(port(b), bit(b), pin(b)) +#endif static uint8_t _ao_button_get(uint8_t b) diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index a67071d2..c1c21e0d 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -39,7 +39,7 @@ static uint8_t ao_radio_abort; /* radio operation should 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_6MHz) +#define ao_radio_select() ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_CC115L_SPI_SPEED) #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) diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 2bc99734..de282000 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -51,7 +51,11 @@ extern const uint32_t ao_radio_cal; #define FOSC 40000000 #endif -#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) +#ifndef AO_CC1200_SPI_SPEED +#error AO_CC1200_SPI_SPEED undefined +#endif + +#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_CC1200_SPI_SPEED) #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) @@ -1323,7 +1327,7 @@ static void ao_radio_packet(void) { void ao_radio_test_recv(void) { - uint8_t bytes[34]; + static uint8_t bytes[34]; uint8_t b; if (ao_radio_recv(bytes, 34, 0)) { diff --git a/src/drivers/ao_console.c b/src/drivers/ao_console.c new file mode 100644 index 00000000..cbde38c9 --- /dev/null +++ b/src/drivers/ao_console.c @@ -0,0 +1,151 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_console.h" +#include "ao_ps2.h" +#include "ao_vga.h" + +static uint8_t console_row, console_col; + +#define ao_console_bitmap ao_vga_bitmap + +static uint8_t console_rows, console_cols; + +static void +ao_console_scroll(void) +{ + ao_copy(&ao_console_bitmap, + 0, 0, + ao_console_bitmap.width, + ao_console_bitmap.height - ao_font.height, + &ao_console_bitmap, + 0, ao_font.height, + AO_COPY); + ao_rect(&ao_console_bitmap, + 0, + (console_rows - 1) * ao_font.height, + ao_console_bitmap.width, + ao_font.height, + 1, + AO_COPY); +} + +static void +ao_console_cursor(void) +{ + ao_rect(&ao_console_bitmap, + console_col * ao_font.width, + console_row * ao_font.height, + ao_font.width, + ao_font.height, + 1, + AO_XOR); +} + +static void +ao_console_clear(void) +{ + ao_rect(&ao_console_bitmap, + 0, 0, + ao_console_bitmap.width, + ao_console_bitmap.height, + 1, + AO_COPY); +} + +static void +ao_console_space(void) +{ + ao_rect(&ao_console_bitmap, + console_col * ao_font.width, + console_row * ao_font.height, + ao_font.width, + ao_font.height, + 1, + AO_COPY); +} + +static void +ao_console_newline(void) +{ + if (++console_row == console_rows) { + ao_console_scroll(); + console_row--; + } +} + +void +ao_console_putchar(char c) +{ + if (' ' <= c && c < 0x7f) { + char text[2]; + ao_console_space(); + text[0] = c; + text[1] = '\0'; + ao_text(&ao_console_bitmap, + console_col * ao_font.width, + console_row * ao_font.height + ao_font.ascent, + text, + 0, + AO_COPY); + if (++console_col == console_cols) { + console_col = 0; + ao_console_newline(); + } + } else { + ao_console_cursor(); + switch (c) { + case '\r': + console_col = 0; + break; + case '\t': + console_col += 8 - (console_col & 7); + if (console_col >= console_cols) { + console_col = 0; + ao_console_newline(); + } + break; + case '\n': + ao_console_newline(); + break; + case '\f': + console_col = console_row = 0; + ao_console_clear(); + break; + case '\177': + case '\010': + if (console_col) + console_col--; + break; + } + } + ao_console_cursor(); +} + +void +ao_console_init(void) +{ + console_cols = ao_console_bitmap.width / ao_font.width; + console_rows = ao_console_bitmap.height / ao_font.height; +#if CONSOLE_STDIN + ao_ps2_stdin = 1; + ao_add_stdio(_ao_ps2_pollchar, + ao_console_putchar, + NULL); +#endif + ao_console_clear(); + ao_console_cursor(); + ao_vga_enable(1); +} diff --git a/src/drivers/ao_console.h b/src/drivers/ao_console.h new file mode 100644 index 00000000..33d3658a --- /dev/null +++ b/src/drivers/ao_console.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_CONSOLE_H_ +#define _AO_CONSOLE_H_ + +void +ao_console_putchar(char c); + +void +ao_console_init(void); + +#endif /* _AO_CONSOLE_H_ */ diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h index d1c69d81..d1df6eac 100644 --- a/src/drivers/ao_event.h +++ b/src/drivers/ao_event.h @@ -22,6 +22,7 @@ #define AO_EVENT_NONE 0 #define AO_EVENT_QUADRATURE 1 #define AO_EVENT_BUTTON 2 +#define AO_EVENT_KEY 3 struct ao_event { uint8_t type; diff --git a/src/drivers/ao_fat.c b/src/drivers/ao_fat.c index fb8eecff..43e7df23 100644 --- a/src/drivers/ao_fat.c +++ b/src/drivers/ao_fat.c @@ -1615,7 +1615,7 @@ ao_fat_hexdump_cmd(void) ao_cmd_status = ao_cmd_syntax_error; return; } - + fd = ao_fat_open(name, AO_FAT_OPEN_READ); if (fd < 0) { printf ("Open failed: %d\n", fd); @@ -1649,5 +1649,7 @@ void ao_fat_init(void) { ao_bufio_init(); +#if FAT_COMMANDS ao_cmd_register(&ao_fat_cmds[0]); +#endif } diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 00f10ecc..e1806ca3 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -661,7 +661,7 @@ ao_lco_monitor(void) ao_lco_armed, ao_lco_firing); if (ao_lco_armed && ao_lco_firing) { - ao_lco_ignite(); + ao_lco_ignite(AO_PAD_FIRE); } else { ao_lco_update(); if (ao_lco_armed) { diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c index dcc0c6d0..8de21fb6 100644 --- a/src/drivers/ao_lco_cmd.c +++ b/src/drivers/ao_lco_cmd.c @@ -61,9 +61,9 @@ lco_arm(void) } static void -lco_ignite(void) +lco_ignite(uint8_t cmd) { - ao_lco_ignite(); + ao_lco_ignite(cmd); } static void @@ -145,7 +145,40 @@ lco_fire_cmd(void) __reentrant secs = 100; for (i = 0; i < secs; i++) { printf("fire %d\n", i); flush(); - lco_ignite(); + lco_ignite(AO_PAD_FIRE); + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +static void +lco_static_cmd(void) __reentrant +{ + uint8_t secs; + uint8_t i; + int8_t r; + + lco_args(); + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + r = lco_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + lco_arm(); + } + + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + lco_ignite(AO_PAD_STATIC); ao_delay(AO_MS_TO_TICKS(100)); } } @@ -171,12 +204,22 @@ lco_ignite_cmd(void) __reentrant uint8_t i; lco_args(); for (i = 0; i < 4; i++) - lco_ignite(); + lco_ignite(AO_PAD_FIRE); +} + + +static void +lco_endstatic_cmd(void) __reentrant +{ + lco_ignite(AO_PAD_ENDSTATIC); } static __code struct ao_cmds ao_lco_cmds[] = { { lco_report_cmd, "l \0Get remote status" }, { lco_fire_cmd, "F \0Fire remote igniters" }, + { lco_fire_cmd, "F \0Fire remote igniters" }, + { lco_static_cmd, "S \0Initiate static test" }, + { lco_endstatic_cmd, "D\0End static test (and download someday)" }, { lco_arm_cmd, "a \0Arm remote igniter" }, { lco_ignite_cmd, "i \0Pulse remote igniter" }, { 0, NULL }, diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c index 862cb1be..92b344ed 100644 --- a/src/drivers/ao_lco_func.c +++ b/src/drivers/ao_lco_func.c @@ -47,7 +47,7 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset) ao_mutex_get(&ao_lco_mutex); command.tick = ao_time(); command.box = box; - command.cmd = AO_LAUNCH_QUERY; + command.cmd = AO_PAD_QUERY; command.channels = 0; ao_radio_cmac_send(&command, sizeof (command)); sent_time = ao_time(); @@ -64,19 +64,19 @@ ao_lco_arm(uint16_t box, uint8_t channels, uint16_t tick_offset) ao_mutex_get(&ao_lco_mutex); command.tick = ao_time() - tick_offset; command.box = box; - command.cmd = AO_LAUNCH_ARM; + command.cmd = AO_PAD_ARM; command.channels = channels; ao_radio_cmac_send(&command, sizeof (command)); ao_mutex_put(&ao_lco_mutex); } void -ao_lco_ignite(void) +ao_lco_ignite(uint8_t cmd) { ao_mutex_get(&ao_lco_mutex); command.tick = 0; command.box = 0; - command.cmd = AO_LAUNCH_FIRE; + command.cmd = cmd; command.channels = 0; ao_radio_cmac_send(&command, sizeof (command)); ao_mutex_put(&ao_lco_mutex); diff --git a/src/drivers/ao_lco_func.h b/src/drivers/ao_lco_func.h index 6b06f928..9d4a27ba 100644 --- a/src/drivers/ao_lco_func.h +++ b/src/drivers/ao_lco_func.h @@ -28,6 +28,6 @@ void ao_lco_arm(uint16_t box, uint8_t channels, uint16_t tick_offset); void -ao_lco_ignite(void); +ao_lco_ignite(uint8_t cmd); #endif /* _AO_LCO_FUNC_H_ */ diff --git a/src/drivers/ao_lco_two.c b/src/drivers/ao_lco_two.c index 1cb0546c..e2f86745 100644 --- a/src/drivers/ao_lco_two.c +++ b/src/drivers/ao_lco_two.c @@ -287,7 +287,7 @@ ao_lco_monitor(void) ao_lco_armed, ao_lco_firing); if (ao_lco_armed && ao_lco_firing) { - ao_lco_ignite(); + ao_lco_ignite(AO_PAD_FIRE); } else { ao_lco_get_channels(); if (ao_lco_armed) { diff --git a/src/drivers/ao_matrix.c b/src/drivers/ao_matrix.c new file mode 100644 index 00000000..fa2d0c57 --- /dev/null +++ b/src/drivers/ao_matrix.c @@ -0,0 +1,201 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#include +#include +#include +#include + +#define row_port(q) AO_MATRIX_ROW_ ## q ## _PORT +#define row_bit(q) AO_MATRIX_ROW_ ## q ## _PIN +#define row_pin(q) AO_MATRIX_ROW_ ## q ## _PIN + +#define col_port(q) AO_MATRIX_COL_ ## q ## _PORT +#define col_bit(q) AO_MATRIX_COL_ ## q ## _PIN +#define col_pin(q) AO_MATRIX_COL_ ## q ## _PIN + +static void +_ao_matrix_drive_row(uint8_t row, uint8_t val) +{ + switch (row) { +#define drive(n) case n: ao_gpio_set(row_port(n), row_bit(n), row_pin(n), val); break + drive(0); +#if AO_MATRIX_ROWS > 1 + drive(1); +#endif +#if AO_MATRIX_ROWS > 2 + drive(2); +#endif +#if AO_MATRIX_ROWS > 3 + drive(3); +#endif +#if AO_MATRIX_ROWS > 4 + drive(4); +#endif +#if AO_MATRIX_ROWS > 5 + drive(5); +#endif +#if AO_MATRIX_ROWS > 6 + drive(6); +#endif +#if AO_MATRIX_ROWS > 7 + drive(7); +#endif + } +} + +static uint8_t +_ao_matrix_read_cols(void) +{ + uint8_t v = 0; +#define read(n) (v |= ao_gpio_get(col_port(n), col_bit(n), col_pin(n)) << n) + + read(0); +#if AO_MATRIX_ROWS > 1 + read(1); +#endif +#if AO_MATRIX_ROWS > 2 + read(2); +#endif +#if AO_MATRIX_ROWS > 3 + read(3); +#endif +#if AO_MATRIX_ROWS > 4 + read(4); +#endif +#if AO_MATRIX_ROWS > 5 + read(5); +#endif +#if AO_MATRIX_ROWS > 6 + read(6); +#endif +#if AO_MATRIX_ROWS > 7 + read(7); +#endif + return v; +} + +static uint8_t +_ao_matrix_read(uint8_t row) { + uint8_t state; + _ao_matrix_drive_row(row, 0); + state = _ao_matrix_read_cols(); + _ao_matrix_drive_row(row, 1); + return state; +} + +#define AO_MATRIX_DEBOUNCE_INTERVAL AO_MS_TO_TICKS(50) + +static uint8_t ao_matrix_keymap[AO_MATRIX_ROWS][AO_MATRIX_COLS] = AO_MATRIX_KEYCODES; + +static uint8_t ao_matrix_state[AO_MATRIX_ROWS]; +static AO_TICK_TYPE ao_matrix_tick[AO_MATRIX_ROWS]; + +static void +_ao_matrix_poll_one(uint8_t row) { + uint8_t state = _ao_matrix_read(row); + + if (state != ao_matrix_state[row]) { + AO_TICK_TYPE now = ao_time(); + + if ((now - ao_matrix_tick[row]) >= AO_MATRIX_DEBOUNCE_INTERVAL) { + uint8_t col; + uint8_t changes = state ^ ao_matrix_state[row]; + + for (col = 0; col < AO_MATRIX_COLS; col++) { + if (changes & (1 << col)) { + ao_event_put_isr(AO_EVENT_KEY, + ao_matrix_keymap[row][col], + ((state >> col) & 1) == 0); + } + } + ao_matrix_state[row] = state; + } + ao_matrix_tick[row] = now; + } +} + +void +ao_matrix_poll(void) +{ + uint8_t row; + + for (row = 0; row < AO_MATRIX_ROWS; row++) + _ao_matrix_poll_one(row); +} + +#define init_row(b) do { \ + ao_enable_output(row_port(b), row_bit(b), row_pin(v), 1); \ + ao_gpio_set_output_mode(row_port(b), row_bit(b), row_pin(b), AO_OUTPUT_OPEN_DRAIN); \ + } while (0) + +#define init_col(b) do { \ + ao_enable_input(col_port(b), col_bit(b), AO_EXTI_MODE_PULL_UP); \ + } while(0) + +void +ao_matrix_init(void) +{ + uint8_t row; + + init_row(0); +#if AO_MATRIX_ROWS > 1 + init_row(1); +#endif +#if AO_MATRIX_ROWS > 2 + init_row(2); +#endif +#if AO_MATRIX_ROWS > 3 + init_row(3); +#endif +#if AO_MATRIX_ROWS > 4 + init_row(4); +#endif +#if AO_MATRIX_ROWS > 5 + init_row(5); +#endif +#if AO_MATRIX_ROWS > 6 + init_row(6); +#endif +#if AO_MATRIX_ROWS > 7 + init_row(7); +#endif + + init_col(0); +#if AO_MATRIX_COLS > 1 + init_col(1); +#endif +#if AO_MATRIX_COLS > 2 + init_col(2); +#endif +#if AO_MATRIX_COLS > 3 + init_col(3); +#endif +#if AO_MATRIX_COLS > 4 + init_col(4); +#endif +#if AO_MATRIX_COLS > 5 + init_col(5); +#endif +#if AO_MATRIX_COLS > 6 + init_col(6); +#endif +#if AO_MATRIX_COLS > 7 + init_col(7); +#endif + for (row = 0; row < AO_MATRIX_ROWS; row++) { + ao_matrix_state[row] = _ao_matrix_read(row); + ao_matrix_tick[row] = ao_time(); + } +} diff --git a/src/drivers/ao_matrix.h b/src/drivers/ao_matrix.h new file mode 100644 index 00000000..ab5a1c51 --- /dev/null +++ b/src/drivers/ao_matrix.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +#ifndef _AO_MATRIX_H_ +#define _AO_MATRIX_H_ + +void +ao_matrix_poll(void); + +void +ao_matrix_init(void); + +#endif /* _AO_MATRIX_H_ */ diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index ffa833fe..16b4ae60 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -316,7 +316,7 @@ ao_pad(void) command.tick, command.box, ao_pad_box, command.cmd, command.channels); switch (command.cmd) { - case AO_LAUNCH_ARM: + case AO_PAD_ARM: if (command.box != ao_pad_box) { PRINTD ("box number mismatch\n"); break; @@ -338,7 +338,7 @@ ao_pad(void) ao_pad_arm_time = ao_time(); break; - case AO_LAUNCH_QUERY: + case AO_PAD_QUERY: if (command.box != ao_pad_box) { PRINTD ("box number mismatch\n"); break; @@ -357,7 +357,7 @@ ao_pad(void) query.igniter_status[3]); ao_radio_cmac_send(&query, sizeof (query)); break; - case AO_LAUNCH_FIRE: + case AO_PAD_FIRE: if (!ao_pad_armed) { PRINTD ("not armed\n"); break; @@ -372,6 +372,29 @@ ao_pad(void) ao_pad_arm_time = ao_time(); ao_wakeup(&ao_pad_ignite); break; + case AO_PAD_STATIC: + if (!ao_pad_armed) { + PRINTD ("not armed\n"); + break; + } +#if HAS_LOG + if (!ao_log_running) ao_log_start(); +#endif + if ((uint16_t) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late pad arm_time %d time %d\n", + ao_pad_arm_time, ao_time()); + break; + } + PRINTD ("ignite\n"); + ao_pad_ignite = ao_pad_armed; + ao_pad_arm_time = ao_time(); + ao_wakeup(&ao_pad_ignite); + break; + case AO_PAD_ENDSTATIC: +#if HAS_LOG + ao_log_stop(); +#endif + break; } } } diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index 648d3005..e4115222 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -54,6 +54,11 @@ struct ao_pad_query { */ #define AO_PAD_FIRE 3 +/* Fire current armed pads for 200ms, no report, logging test stand sensors + */ +#define AO_PAD_STATIC 4 +#define AO_PAD_ENDSTATIC 5 + #define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(200) #define AO_PAD_ARM_STATUS_DISARMED 0 diff --git a/src/drivers/ao_ps2.c b/src/drivers/ao_ps2.c new file mode 100644 index 00000000..29eecea8 --- /dev/null +++ b/src/drivers/ao_ps2.c @@ -0,0 +1,419 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_ps2.h" +#include "ao_exti.h" + +static struct ao_fifo ao_ps2_rx_fifo; + +static uint16_t ao_ps2_tx; +static uint8_t ao_ps2_tx_count; + +static AO_TICK_TYPE ao_ps2_tick; +static uint16_t ao_ps2_value; +static uint8_t ao_ps2_count; + +uint8_t ao_ps2_stdin; + +uint8_t ao_ps2_scancode_set; + +#define AO_PS2_CLOCK_MODE(pull) ((pull) | AO_EXTI_MODE_FALLING | AO_EXTI_PRIORITY_MED) + +static void +ao_ps2_isr(void); + +static uint8_t +_ao_ps2_parity(uint8_t value) +{ + uint8_t parity = 1; + uint8_t b; + + for (b = 0; b < 8; b++) { + parity ^= (value & 1); + value >>= 1; + } + return parity; +} + +static int +_ao_ps2_poll(void) +{ + uint8_t u; + if (ao_fifo_empty(ao_ps2_rx_fifo)) { + return AO_READ_AGAIN; + } + ao_fifo_remove(ao_ps2_rx_fifo, u); + + return (int) u; +} + +uint8_t +ao_ps2_get(void) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_ps2_poll()) == AO_READ_AGAIN) + ao_sleep(&ao_ps2_rx_fifo); + ao_arch_release_interrupts(); + return (uint8_t) c; +} + + +int +ao_ps2_poll(void) +{ + int c; + ao_arch_block_interrupts(); + c = _ao_ps2_poll(); + ao_arch_release_interrupts(); + return (uint8_t) c; +} + +void +ao_ps2_put(uint8_t c) +{ + ao_arch_block_interrupts(); + ao_ps2_tx = ((uint16_t) c) | (_ao_ps2_parity(c) << 8) | (3 << 9); + ao_ps2_tx_count = 11; + ao_exti_disable(AO_PS2_CLOCK_PORT, AO_PS2_CLOCK_BIT); + ao_arch_release_interrupts(); + + /* pull the clock pin down */ + ao_enable_output(AO_PS2_CLOCK_PORT, AO_PS2_CLOCK_BIT, AO_PS2_CLOCK_PIN, 0); + ao_delay(0); + + /* pull the data pin down for the start bit */ + ao_enable_output(AO_PS2_DATA_PORT, AO_PS2_DATA_BIT, AO_PS2_DATA_PIN, 0); + ao_delay(0); + + /* switch back to input mode for the interrupt to work */ + ao_exti_setup(AO_PS2_CLOCK_PORT, AO_PS2_CLOCK_BIT, + AO_PS2_CLOCK_MODE(AO_EXTI_MODE_PULL_UP), + ao_ps2_isr); + ao_exti_enable(AO_PS2_CLOCK_PORT, AO_PS2_CLOCK_BIT); + + /* wait for the bits to drain */ + while (ao_ps2_tx_count) + ao_sleep(&ao_ps2_tx_count); + +} + +static uint8_t ao_ps2_down[128 / 8]; + +static void +ao_ps2_set_down(uint8_t code, uint8_t value) +{ + uint8_t shift = (code & 0x07); + uint8_t byte = code >> 3; + + ao_ps2_down[byte] = (ao_ps2_down[byte] & ~(1 << shift)) | (value << shift); +} + +uint8_t +ao_ps2_is_down(uint8_t code) +{ + uint8_t shift = (code & 0x07); + uint8_t byte = code >> 3; + + return (ao_ps2_down[byte] >> shift) & 1; +} + +static void +_ao_ps2_set_leds(void) +{ + uint8_t led = 0; + if (ao_ps2_is_down(AO_PS2_CAPS_LOCK)) + led |= AO_PS2_SET_LEDS_CAPS; + if (ao_ps2_is_down(AO_PS2_NUM_LOCK)) + led |= AO_PS2_SET_LEDS_NUM; + if (ao_ps2_is_down(AO_PS2_SCROLL_LOCK)) + led |= AO_PS2_SET_LEDS_SCROLL; + ao_arch_release_interrupts(); + ao_ps2_put(AO_PS2_SET_LEDS); + while (ao_ps2_get() != 0xfa); + ao_ps2_put(led); + ao_arch_block_interrupts(); +} + +static uint8_t +ao_ps2_is_lock(uint8_t code) { + switch (code) { + case AO_PS2_CAPS_LOCK: + case AO_PS2_NUM_LOCK: + case AO_PS2_SCROLL_LOCK: + return 1; + } + return 0; +} + +static void +_ao_ps2_set_scancode_set(uint8_t set) +{ + ao_ps2_scancode_set = set; + ao_arch_release_interrupts(); + ao_ps2_put(AO_PS2_SET_SCAN_CODE_SET); + while (ao_ps2_get() != 0xfa); + ao_ps2_put(set); + ao_ps2_put(AO_PS2_SET_KEY_TYPEMATIC_MAKE_BREAK); + while (ao_ps2_get() != 0xfa); + ao_arch_block_interrupts(); +} + +static int +_ao_ps2_poll_key(void) +{ + int c; + uint8_t set_led = 0; + static uint8_t saw_break; + + c = _ao_ps2_poll(); + if (c < 0) { + if (ao_ps2_scancode_set != 3) { + _ao_ps2_set_scancode_set(3); + } + return c; + } + + if (c == AO_PS2_BREAK) { + saw_break = 1; + return AO_READ_AGAIN; + } + if (c & 0x80) + return AO_READ_AGAIN; + + if (ao_ps2_is_lock(c)) { + if (saw_break) { + saw_break = 0; + return AO_READ_AGAIN; + } + if (ao_ps2_is_down(c)) + saw_break = 1; + set_led = 1; + } + if (saw_break) { + saw_break = 0; + ao_ps2_set_down(c, 0); + c |= 0x80; + } else + ao_ps2_set_down(c, 1); + if (set_led) + _ao_ps2_set_leds(); + + if (ao_ps2_scancode_set != 3) + _ao_ps2_set_scancode_set(3); + + return c; +} + +int +ao_ps2_poll_key(void) +{ + int c; + ao_arch_block_interrupts(); + c = _ao_ps2_poll_key(); + ao_arch_release_interrupts(); + return c; +} + +uint8_t +ao_ps2_get_key(void) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_ps2_poll_key()) == AO_READ_AGAIN) + ao_sleep(&ao_ps2_rx_fifo); + ao_arch_release_interrupts(); + return (uint8_t) c; +} + +static const uint8_t ao_ps2_asciimap[128][2] = { + [AO_PS2_A] = { 'a', 'A' }, + [AO_PS2_B] = { 'b', 'B' }, + [AO_PS2_C] = { 'c', 'C' }, + [AO_PS2_D] = { 'd', 'D' }, + [AO_PS2_E] = { 'e', 'E' }, + [AO_PS2_F] = { 'f', 'F' }, + [AO_PS2_G] = { 'g', 'G' }, + [AO_PS2_H] = { 'h', 'H' }, + [AO_PS2_I] = { 'i', 'I' }, + [AO_PS2_J] = { 'j', 'J' }, + [AO_PS2_K] = { 'k', 'K' }, + [AO_PS2_L] = { 'l', 'L' }, + [AO_PS2_M] = { 'm', 'M' }, + [AO_PS2_N] = { 'n', 'N' }, + [AO_PS2_O] = { 'o', 'O' }, + [AO_PS2_P] = { 'p', 'P' }, + [AO_PS2_Q] = { 'q', 'Q' }, + [AO_PS2_R] = { 'r', 'R' }, + [AO_PS2_S] = { 's', 'S' }, + [AO_PS2_T] = { 't', 'T' }, + [AO_PS2_U] = { 'u', 'U' }, + [AO_PS2_V] = { 'v', 'V' }, + [AO_PS2_W] = { 'w', 'W' }, + [AO_PS2_X] = { 'x', 'X' }, + [AO_PS2_Y] = { 'y', 'Y' }, + [AO_PS2_Z] = { 'z', 'Z' }, + + [AO_PS2_0] = { '0', ')' }, + [AO_PS2_1] = { '1', '!' }, + [AO_PS2_2] = { '2', '@' }, + [AO_PS2_3] = { '3', '#' }, + [AO_PS2_4] = { '4', '$' }, + [AO_PS2_5] = { '5', '%' }, + [AO_PS2_6] = { '6', '^' }, + [AO_PS2_7] = { '7', '&' }, + [AO_PS2_8] = { '8', '*' }, + [AO_PS2_9] = { '9', '(' }, + + [AO_PS2_GRAVE] = { '`', '~' }, + [AO_PS2_HYPHEN] = { '-', '_' }, + [AO_PS2_EQUAL] = { '=', '+' }, + [AO_PS2_BACKSLASH] = { '\\', '|' }, + [AO_PS2_BACKSPACE] = { '\010', '\010' }, + [AO_PS2_SPACE] = { ' ', ' ' }, + [AO_PS2_TAB] = { '\t', '\t' }, + + [AO_PS2_ENTER] = { '\r', '\r' }, + [AO_PS2_ESC] = { '\033', '\033' }, + + [AO_PS2_OPEN_SQ] = { '[', '{' }, + [AO_PS2_DELETE] = { '\177', '\177' }, + + [AO_PS2_KP_TIMES] = { '*', '*' }, + [AO_PS2_KP_PLUS] = { '+', '+' }, + [AO_PS2_KP_ENTER] = { '\r', '\r' }, + [AO_PS2_KP_DECIMAL] = { '.', '.' }, + [AO_PS2_KP_0] = { '0', '0' }, + [AO_PS2_KP_1] = { '1', '1' }, + [AO_PS2_KP_2] = { '2', '2' }, + [AO_PS2_KP_3] = { '3', '3' }, + [AO_PS2_KP_4] = { '4', '4' }, + [AO_PS2_KP_5] = { '5', '5' }, + [AO_PS2_KP_6] = { '6', '6' }, + [AO_PS2_KP_7] = { '7', '7' }, + [AO_PS2_KP_8] = { '8', '8' }, + [AO_PS2_KP_9] = { '9', '9' }, + [AO_PS2_CLOSE_SQ] = { ']', '}' }, + [AO_PS2_SEMICOLON] = { ';', ':' }, + [AO_PS2_ACUTE] = { '\'', '"' }, + [AO_PS2_COMMA] = { ',', '<' }, + [AO_PS2_PERIOD] = { '.', '>' }, + [AO_PS2_SLASH] = { '/', '?' }, +}; + +int +ao_ps2_ascii(uint8_t key) +{ + uint8_t col; + char a; + + /* Skip key releases */ + if (key & 0x80) + return AO_READ_AGAIN; + + col = 0; + if (ao_ps2_is_down(AO_PS2_L_SHIFT) || ao_ps2_is_down(AO_PS2_R_SHIFT)) + col = 1; + + /* caps lock */ + a = ao_ps2_asciimap[key][0]; + if (!a) + return AO_READ_AGAIN; + + if ('a' <= a && a <= 'z') + if (ao_ps2_is_down(AO_PS2_CAPS_LOCK)) + col ^= 1; + a = ao_ps2_asciimap[key][col]; + if ('@' <= a && a <= 0x7f && (ao_ps2_is_down(AO_PS2_L_CTRL) || ao_ps2_is_down(AO_PS2_R_CTRL))) + a &= 0x1f; + return a; +} + +int +_ao_ps2_pollchar(void) +{ + int key; + + key = _ao_ps2_poll_key(); + if (key < 0) + return key; + return ao_ps2_ascii(key); +} + +char +ao_ps2_getchar(void) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_ps2_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_ps2_rx_fifo); + ao_arch_release_interrupts(); + return (char) c; +} + +static void +ao_ps2_isr(void) +{ + uint8_t bit; + + if (ao_ps2_tx_count) { + ao_gpio_set(AO_PS2_DATA_PORT, AO_PS2_DATA_BIT, AO_PS2_DATA_PIN, ao_ps2_tx&1); + ao_ps2_tx >>= 1; + ao_ps2_tx_count--; + if (!ao_ps2_tx_count) { + ao_enable_input(AO_PS2_DATA_PORT, AO_PS2_DATA_BIT, AO_EXTI_MODE_PULL_UP); + ao_wakeup(&ao_ps2_tx_count); + } + return; + } + /* reset if its been a while */ + if ((ao_tick_count - ao_ps2_tick) > AO_MS_TO_TICKS(100)) + ao_ps2_count = 0; + ao_ps2_tick = ao_tick_count; + + bit = ao_gpio_get(AO_PS2_DATA_PORT, AO_PS2_DATA_BIT, AO_PS2_DATA_PIN); + if (ao_ps2_count == 0) { + /* check for start bit, ignore if not zero */ + if (bit) + return; + ao_ps2_value = 0; + } else if (ao_ps2_count < 9) { + ao_ps2_value |= (bit << (ao_ps2_count - 1)); + } else if (ao_ps2_count == 10) { + ao_fifo_insert(ao_ps2_rx_fifo, ao_ps2_value); + ao_wakeup(&ao_ps2_rx_fifo); + if (ao_ps2_stdin) + ao_wakeup(&ao_stdin_ready); + ao_ps2_count = 0; + return; + } + ao_ps2_count++; +} + +void +ao_ps2_init(void) +{ + ao_enable_input(AO_PS2_DATA_PORT, AO_PS2_DATA_BIT, + AO_EXTI_MODE_PULL_UP); + + ao_enable_port(AO_PS2_CLOCK_PORT); + + ao_exti_setup(AO_PS2_CLOCK_PORT, AO_PS2_CLOCK_BIT, + AO_PS2_CLOCK_MODE(AO_EXTI_MODE_PULL_UP), + ao_ps2_isr); + ao_exti_enable(AO_PS2_CLOCK_PORT, AO_PS2_CLOCK_BIT); + + ao_ps2_scancode_set = 2; +} diff --git a/src/drivers/ao_ps2.h b/src/drivers/ao_ps2.h new file mode 100644 index 00000000..f1f05ee5 --- /dev/null +++ b/src/drivers/ao_ps2.h @@ -0,0 +1,220 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_PS2_H_ +#define _AO_PS2_H_ + +extern uint8_t ao_ps2_stdin; + +int +ao_ps2_poll(void); + +uint8_t +ao_ps2_get(void); + +void +ao_ps2_put(uint8_t b); + +uint8_t +ao_ps2_is_down(uint8_t code); + +int +ao_ps2_poll_key(void); + +uint8_t +ao_ps2_get_key(void); + +int +ao_ps2_ascii(uint8_t key); + +int +_ao_ps2_pollchar(void); + +char +ao_ps2_getchar(void); + +void +ao_ps2_init(void); + +/* From http://computer-engineering.org/ps2keyboard/ */ + +/* Device responds with ACK and then resets */ +#define AO_PS2_RESET 0xff + +/* Device retransmits last byte */ +#define AO_PS2_RESEND 0xfe + +/* Setting key report only works in mode 3 */ + +/* Disable break and typematic for specified mode 3 keys. Terminate with invalid key */ +#define AO_PS2_SET_KEY_MAKE 0xfd + +/* Disable typematic for keys */ +#define AO_PS2_SET_KEY_MAKE_BREAK 0xfc + +/* Disable break code for keys */ +#define AO_PS2_SET_KEY_TYPEMATIC 0xfb + +/* Enable make, break and typematic */ +#define AO_PS2_SET_KEY_TYPEMATIC_MAKE_BREAK 0xfa + +/* Disable break and typematic for all */ +#define AO_PS2_SET_ALL_MAKE 0xf9 + +/* Disable typematic for all */ +#define AO_PS2_SET_ALL_MAKE_BREAK 0xf8 + +/* Disable break for all */ +#define AO_PS2_SET_ALL_TYPEMATIC 0xf7 + +/* Set keyboard to default (repeat, report and scan code set 2) */ +#define AO_PS2_SET_DEFAULT 0xf6 + +/* Disable and reset to default */ +#define AO_PS2_DISABLE 0xf5 + +/* Enable */ +#define AO_PS2_ENABLE 0xf4 + +/* Set repeat rate. Bytes 5-6 are the start delay, bits 0-4 are the rate */ +#define AO_PS2_SET_REPEAT_RATE 0xf3 + +/* Read keyboard id. Returns two bytes */ +#define AO_PS2_GETID 0xf2 + +/* Set scan code (1, 2, or 3) */ +#define AO_PS2_SET_SCAN_CODE_SET 0xf0 + +/* Echo. Keyboard replies with Echo */ +#define AO_PS2_ECHO 0xee + +/* Set LEDs */ +#define AO_PS2_SET_LEDS 0xed +# define AO_PS2_SET_LEDS_SCROLL 0x01 +# define AO_PS2_SET_LEDS_NUM 0x02 +# define AO_PS2_SET_LEDS_CAPS 0x04 + +#define AO_PS2_BREAK 0xf0 +#define AO_PS2_ACK 0xfa +#define AO_PS2_ERROR 0xfc +#define AO_PS2_NAK 0xfe + +/* Scan code set 3 */ + +#define AO_PS2_A 0x1c +#define AO_PS2_B 0x32 +#define AO_PS2_C 0x21 +#define AO_PS2_D 0x23 +#define AO_PS2_E 0x24 +#define AO_PS2_F 0x2b +#define AO_PS2_G 0x34 +#define AO_PS2_H 0x33 +#define AO_PS2_I 0x43 +#define AO_PS2_J 0x3b +#define AO_PS2_K 0x42 +#define AO_PS2_L 0x4b +#define AO_PS2_M 0x3a +#define AO_PS2_N 0x31 +#define AO_PS2_O 0x44 +#define AO_PS2_P 0x4d +#define AO_PS2_Q 0x15 +#define AO_PS2_R 0x2d +#define AO_PS2_S 0x1b +#define AO_PS2_T 0x2c +#define AO_PS2_U 0x3c +#define AO_PS2_V 0x2a +#define AO_PS2_W 0x1d +#define AO_PS2_X 0x22 +#define AO_PS2_Y 0x35 +#define AO_PS2_Z 0x1a +#define AO_PS2_0 0x45 +#define AO_PS2_1 0x16 +#define AO_PS2_2 0x1e +#define AO_PS2_3 0x26 +#define AO_PS2_4 0x25 +#define AO_PS2_5 0x2e +#define AO_PS2_6 0x36 +#define AO_PS2_7 0x3d +#define AO_PS2_8 0x3e +#define AO_PS2_9 0x46 +#define AO_PS2_GRAVE 0x0e +#define AO_PS2_HYPHEN 0x4e +#define AO_PS2_EQUAL 0x55 +#define AO_PS2_BACKSLASH 0x5c +#define AO_PS2_BACKSPACE 0x66 +#define AO_PS2_SPACE 0x29 +#define AO_PS2_TAB 0x0d +#define AO_PS2_CAPS_LOCK 0x14 +#define AO_PS2_L_SHIFT 0x12 +#define AO_PS2_L_CTRL 0x11 +#define AO_PS2_L_WIN 0x8b +#define AO_PS2_L_ALT 0x19 +#define AO_PS2_R_SHIFT 0x59 +#define AO_PS2_R_CTRL 0x58 +#define AO_PS2_R_WIN 0x8c +#define AO_PS2_R_ALT 0x39 +#define AO_PS2_APPS 0x8d +#define AO_PS2_ENTER 0x5a +#define AO_PS2_ESC 0x08 +#define AO_PS2_F1 0x07 +#define AO_PS2_F2 0x0f +#define AO_PS2_F3 0x17 +#define AO_PS2_F4 0x1f +#define AO_PS2_F5 0x27 +#define AO_PS2_F6 0x2f +#define AO_PS2_F7 0x37 +#define AO_PS2_F8 0x3f +#define AO_PS2_F9 0x47 +#define AO_PS2_F10 0x4f +#define AO_PS2_F11 0x56 +#define AO_PS2_F12 0x5e +#define AO_PS2_PRNT_SCRN 0x57 +#define AO_PS2_SCROLL_LOCK 0x5f +#define AO_PS2_PAUSE 0x62 +#define AO_PS2_OPEN_SQ 0x54 +#define AO_PS2_INSERT 0x67 +#define AO_PS2_HOME 0x6e +#define AO_PS2_PG_UP 0x6f +#define AO_PS2_DELETE 0x64 +#define AO_PS2_END 0x65 +#define AO_PS2_PG_DN 0x6d +#define AO_PS2_UP 0x63 +#define AO_PS2_LEFT 0x61 +#define AO_PS2_DOWN 0x60 +#define AO_PS2_RIGHT 0x6a +#define AO_PS2_NUM_LOCK 0x76 +#define AO_PS2_KP_TIMES 0x7e +#define AO_PS2_KP_PLUS 0x7c +#define AO_PS2_KP_ENTER 0x79 +#define AO_PS2_KP_DECIMAL 0x71 +#define AO_PS2_KP_0 0x70 +#define AO_PS2_KP_1 0x69 +#define AO_PS2_KP_2 0x72 +#define AO_PS2_KP_3 0x7a +#define AO_PS2_KP_4 0x6b +#define AO_PS2_KP_5 0x73 +#define AO_PS2_KP_6 0x74 +#define AO_PS2_KP_7 0x6c +#define AO_PS2_KP_8 0x75 +#define AO_PS2_KP_9 0x7d +#define AO_PS2_CLOSE_SQ 0x5b +#define AO_PS2_SEMICOLON 0x4c +#define AO_PS2_ACUTE 0x52 +#define AO_PS2_COMMA 0x41 +#define AO_PS2_PERIOD 0x49 +#define AO_PS2_SLASH 0x4a + +#define AO_PS2_RELEASE_FLAG 0x80 + +#endif /* _AO_PS2_H_ */ diff --git a/src/drivers/ao_sdcard.c b/src/drivers/ao_sdcard.c index 4b17c5e3..45454000 100644 --- a/src/drivers/ao_sdcard.c +++ b/src/drivers/ao_sdcard.c @@ -38,13 +38,19 @@ extern uint8_t ao_radio_mutex; #define ao_sdcard_deselect() ao_gpio_set(AO_SDCARD_SPI_CS_PORT,AO_SDCARD_SPI_CS_PIN,AO_SDCARD_SPI_CS,1) /* Include SD card commands */ +#ifndef SDCARD_DEBUG #define SDCARD_DEBUG 0 +#endif /* Spew SD tracing */ +#ifndef SDCARD_TRACE #define SDCARD_TRACE 0 +#endif /* Emit error and warning messages */ +#ifndef SDCARD_WARN #define SDCARD_WARN 0 +#endif static uint8_t initialized; static uint8_t present; diff --git a/src/drivers/ao_vga.c b/src/drivers/ao_vga.c new file mode 100644 index 00000000..909e3109 --- /dev/null +++ b/src/drivers/ao_vga.c @@ -0,0 +1,366 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include "ao_vga.h" + +/* VGA output from the SPI port + * + * Connections: + * + * STM VGA + * GND 4,6,7,8,9,10 + * HSYNC PA5 13 + * VSYNC PB5 14 + * RGB PB4 1,2,3 + * + * pixel clock PA8 -> PB3 + * pixel enable PA1 -> PA15 + */ + +/* GRF formula for 640x480 yields a pixel clock very close to 24MHz. Pad by + * three scanlines to hit exactly that value + */ + +#define HACTIVE (640) +#define HSYNC_START (656) +#define HSYNC_END (720) +#define HTOTAL (800) + +#define VACTIVE 480 +#define VSYNC_START 481 +#define VSYNC_END 484 +#define VTOTAL 500 + +/* + * The horizontal counter is set so that the end of hsync is reached + * at the maximum counter value. That means that the hblank interval + * is offset by HSYNC_END. + */ + +#define HSYNC (HSYNC_END - HSYNC_START) +#define HBLANK_END (HTOTAL - HSYNC_END) +#define HBLANK_START (HBLANK_END + HACTIVE) + +/* + * The vertical counter is set so that the end of vsync is reached at + * the maximum counter value. That means that the vblank interval is + * offset by VSYNC_END. We send a blank line at the start of the + * frame, so each of these is off by one + */ +#define VSYNC (VSYNC_END - VSYNC_START) +#define VBLANK_END (VTOTAL - VSYNC_END) +#define VBLANK_START (VBLANK_END + VACTIVE) + +#define WIDTH_BYTES (AO_VGA_WIDTH >> 3) +#define SCANOUT ((WIDTH_BYTES+2) >> 1) + +uint32_t ao_vga_fb[AO_VGA_STRIDE * AO_VGA_HEIGHT]; + +const struct ao_bitmap ao_vga_bitmap = { + .base = ao_vga_fb, + .stride = AO_VGA_STRIDE, + .width = AO_VGA_WIDTH, + .height = AO_VGA_HEIGHT +}; + +static uint32_t *scanline; + +#define DMA_INDEX STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX) + +#define DMA_CCR(en) ((0 << STM_DMA_CCR_MEM2MEM) | \ + (STM_DMA_CCR_PL_VERY_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_MEM_TO_PER << STM_DMA_CCR_DIR) | \ + (0 << STM_DMA_CCR_TCIE) | \ + (en << STM_DMA_CCR_EN)) + + +void stm_tim2_isr(void) +{ + int16_t line = stm_tim3.cnt; + + if (VBLANK_END <= line && line < VBLANK_START) { + /* Disable */ + stm_dma.channel[DMA_INDEX].ccr = DMA_CCR(0); + /* Reset DMA engine for the next scanline */ + stm_dma.channel[DMA_INDEX].cmar = scanline; + stm_dma.channel[DMA_INDEX].cndtr = SCANOUT; + + /* reset SPI */ + (void) stm_spi1.dr; + (void) stm_spi1.sr; + + /* Enable */ + stm_dma.channel[DMA_INDEX].ccr = DMA_CCR(1); + if (((line - VBLANK_END) & 1)) + scanline += AO_VGA_STRIDE; + } else { + scanline = ao_vga_fb; + } + stm_tim2.sr = 0; +} + + +void +ao_vga_init(void) +{ + uint32_t cfgr; + + /* Initialize spi1 using MISO PB4 for output */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_ospeedr_set(&stm_gpiob, 4, STM_OSPEEDR_40MHz); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 15, STM_AFR_AF5); + + /* turn on SPI */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + + stm_spi1.cr1 = ((1 << STM_SPI_CR1_BIDIMODE) | /* Two wire mode */ + (1 << STM_SPI_CR1_BIDIOE) | + (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ + (0 << STM_SPI_CR1_CRCNEXT) | + (1 << STM_SPI_CR1_DFF) | + (0 << STM_SPI_CR1_RXONLY) | /* transmit, not receive */ + (0 << STM_SPI_CR1_SSM) | /* Software SS handling */ + (1 << STM_SPI_CR1_SSI) | /* ... */ + (1 << STM_SPI_CR1_LSBFIRST) | /* Little endian */ + (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ + (0 << STM_SPI_CR1_BR) | /* baud rate to pclk/2 */ + (0 << STM_SPI_CR1_MSTR) | /* slave */ + (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ + (0 << STM_SPI_CR1_CPHA)); + stm_spi1.cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (0 << STM_SPI_CR2_RXDMAEN)); + + (void) stm_spi1.dr; + (void) stm_spi1.sr; + + /* Grab the DMA channel for SPI1 MOSI */ + stm_dma.channel[DMA_INDEX].cpar = &stm_spi1.dr; + stm_dma.channel[DMA_INDEX].cmar = ao_vga_fb; + + /* + * Hsync Configuration + */ + /* Turn on timer 2 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM2EN); + + /* tim2 runs at full speed */ + stm_tim2.psc = 0; + + /* Disable channels while modifying */ + stm_tim2.ccer = 0; + + /* Channel 1 hsync PWM values */ + stm_tim2.ccr1 = HSYNC; + + /* Channel 2 trigger scanout */ + /* wait for the time to start scanout */ + stm_tim2.ccr2 = HBLANK_END; + + stm_tim2.ccr3 = 32; + + /* Configure channel 1 to output on the pin and + * channel 2 to to set the trigger for the vsync timer + */ + stm_tim2.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) | + (STM_TIM234_CCMR1_OC2M_PWM_MODE_1 << STM_TIM234_CCMR1_OC2M) | + (1 << STM_TIM234_CCMR1_OC2PE) | + (0 << STM_TIM234_CCMR1_OC2FE) | + (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) | + + (0 << STM_TIM234_CCMR1_OC1CE) | + (STM_TIM234_CCMR1_OC1M_PWM_MODE_1 << STM_TIM234_CCMR1_OC1M) | + (1 << STM_TIM234_CCMR1_OC1PE) | + (0 << STM_TIM234_CCMR1_OC1FE) | + (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S)); + + stm_tim2.ccmr2 = ((0 << STM_TIM234_CCMR2_OC4CE) | + (0 << STM_TIM234_CCMR2_OC4M) | + (0 << STM_TIM234_CCMR2_OC4PE) | + (0 << STM_TIM234_CCMR2_OC4FE) | + (0 << STM_TIM234_CCMR2_CC4S) | + + (0 << STM_TIM234_CCMR2_OC3CE) | + (STM_TIM234_CCMR2_OC3M_PWM_MODE_1 << STM_TIM234_CCMR2_OC3M) | + (1 << STM_TIM234_CCMR2_OC3PE) | + (0 << STM_TIM234_CCMR2_OC3FE) | + (0 << STM_TIM234_CCMR2_CC3S)); + + /* One scanline */ + stm_tim2.arr = HTOTAL; + + stm_tim2.cnt = 0; + + /* Update the register contents */ + stm_tim2.egr |= (1 << STM_TIM234_EGR_UG); + + /* Enable the timer */ + + /* Enable the output */ + stm_tim2.ccer = ((0 << STM_TIM234_CCER_CC2NP) | + (STM_TIM234_CCER_CC2P_ACTIVE_HIGH << STM_TIM234_CCER_CC2P) | + (1 << STM_TIM234_CCER_CC2E) | + (0 << STM_TIM234_CCER_CC1NP) | + (STM_TIM234_CCER_CC1P_ACTIVE_LOW << STM_TIM234_CCER_CC1P) | + (1 << STM_TIM234_CCER_CC1E)); + + stm_tim2.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_UPDATE << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + + /* hsync is not a slave timer */ + stm_tim2.smcr = 0; + + /* Send an interrupt on channel 3 */ + stm_tim2.dier = ((1 << STM_TIM234_DIER_CC3IE)); + + stm_tim2.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (1 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (1 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (0 << STM_TIM234_CR1_CEN)); + + /* Hsync is on PA5 which is Timer 2 CH1 output */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + stm_ospeedr_set(&stm_gpioa, 5, STM_OSPEEDR_40MHz); + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF1); + + /* pixel transmit enable is on PA1 */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + stm_ospeedr_set(&stm_gpioa, 1, STM_OSPEEDR_40MHz); + stm_afr_set(&stm_gpioa, 1, STM_AFR_AF1); + + /* + * Vsync configuration + */ + + /* Turn on timer 3, slaved to timer 1 using ITR1 (table 61) */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM3EN); + + /* No prescale */ + stm_tim3.psc = 0; + + /* Channel 1 or 2 vsync PWM values */ + stm_tim3.ccr1 = VSYNC; + stm_tim3.ccr2 = VSYNC; + + stm_tim3.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) | + (STM_TIM234_CCMR1_OC2M_PWM_MODE_1 << STM_TIM234_CCMR1_OC2M) | + (1 << STM_TIM234_CCMR1_OC2PE) | + (0 << STM_TIM234_CCMR1_OC2FE) | + (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) | + + (0 << STM_TIM234_CCMR1_OC1CE) | + (STM_TIM234_CCMR1_OC1M_PWM_MODE_1 << STM_TIM234_CCMR1_OC1M) | + (1 << STM_TIM234_CCMR1_OC1PE) | + (0 << STM_TIM234_CCMR1_OC1FE) | + (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S)); + + stm_tim3.arr = VTOTAL; + stm_tim3.cnt = 0; + + /* Update the register contents */ + stm_tim3.egr |= (1 << STM_TIM234_EGR_UG); + + /* Enable the timer */ + + /* Enable the output */ + stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC1NP) | + (STM_TIM234_CCER_CC2P_ACTIVE_LOW << STM_TIM234_CCER_CC2P) | + (1 << STM_TIM234_CCER_CC2E) | + (STM_TIM234_CCER_CC1P_ACTIVE_LOW << STM_TIM234_CCER_CC1P) | + (1 << STM_TIM234_CCER_CC1E)); + + stm_tim3.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_UPDATE << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + + stm_tim3.smcr = 0; + stm_tim3.smcr = ((0 << STM_TIM234_SMCR_ETP) | + (0 << STM_TIM234_SMCR_ECE) | + (STM_TIM234_SMCR_ETPS_OFF << STM_TIM234_SMCR_ETPS) | + (STM_TIM234_SMCR_ETF_NONE << STM_TIM234_SMCR_ETF) | + (0 << STM_TIM234_SMCR_MSM) | + (STM_TIM234_SMCR_TS_ITR1 << STM_TIM234_SMCR_TS) | + (0 << STM_TIM234_SMCR_OCCS) | + (STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK << STM_TIM234_SMCR_SMS)); + + stm_tim3.dier = 0; + + stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (1 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (1 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + + /* Vsync is on PB5 which is is Timer 3 CH2 output */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_ospeedr_set(&stm_gpiob, 5, STM_OSPEEDR_40MHz); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF2); + + /* Use MCO for the pixel clock, that appears on PA8 */ + cfgr = stm_rcc.cfgr & ~((STM_RCC_CFGR_MCOPRE_MASK << STM_RCC_CFGR_MCOPRE) | + (STM_RCC_CFGR_MCOSEL_MASK << STM_RCC_CFGR_MCOSEL)); + + cfgr |= ((STM_RCC_CFGR_MCOPRE_DIV_2 << STM_RCC_CFGR_MCOPRE) | + (STM_RCC_CFGR_MCOSEL_SYSCLK << STM_RCC_CFGR_MCOSEL)); + + stm_rcc.cfgr = cfgr; + + stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_40MHz); + stm_afr_set(&stm_gpioa, 8, STM_AFR_AF0); + + /* Enable the scanline interrupt */ + stm_nvic_set_priority(STM_ISR_TIM2_POS, AO_STM_NVIC_NONMASK_PRIORITY); + stm_nvic_set_enable(STM_ISR_TIM2_POS); +} + +uint8_t enabled; + +void +ao_vga_enable(int enable) +{ + if (enable) { + if (!enabled) { + ++ao_task_minimize_latency; + enabled = 1; + } + stm_tim2.cr1 |= (1 << STM_TIM234_CR1_CEN); + } else { + if (enabled) { + --ao_task_minimize_latency; + enabled = 0; + } + stm_tim2.cr1 &= ~(1 << STM_TIM234_CR1_CEN); + } +} diff --git a/src/drivers/ao_vga.h b/src/drivers/ao_vga.h new file mode 100644 index 00000000..7d9d6b39 --- /dev/null +++ b/src/drivers/ao_vga.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_VGA_H_ +#define _AO_VGA_H_ + +#include "ao_draw.h" + +void +ao_vga_init(void); + +void +ao_vga_enable(int active); + +/* Active frame buffer */ +#define AO_VGA_WIDTH 320 +#define AO_VGA_HEIGHT 240 + +/* Pad on the right so that there are zeros on the output after the line */ +#define AO_VGA_HPAD 32 + +#define AO_VGA_STRIDE ((AO_VGA_WIDTH + AO_VGA_HPAD) >> AO_SHIFT) + +extern uint32_t ao_vga_fb[AO_VGA_STRIDE * AO_VGA_HEIGHT]; + +extern const struct ao_bitmap ao_vga_bitmap; + +#endif /* _AO_VGA_H_ */ diff --git a/src/kernel/ao.h b/src/kernel/ao.h index fb41d7a9..e56fbb2e 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -170,6 +170,9 @@ void ao_put_string(__code char *s); void +ao_cmd_readline(void); + +char ao_cmd_lex(void); void @@ -853,33 +856,6 @@ struct ao_fifo { #include #endif -/* ao_launch.c */ - -struct ao_launch_command { - uint16_t tick; - uint16_t serial; - uint8_t cmd; - uint8_t channel; - uint16_t unused; -}; - -#define AO_LAUNCH_QUERY 1 - -struct ao_launch_query { - uint16_t tick; - uint16_t serial; - uint8_t channel; - uint8_t valid; - uint8_t arm_status; - uint8_t igniter_status; -}; - -#define AO_LAUNCH_ARM 2 -#define AO_LAUNCH_FIRE 3 - -void -ao_launch_init(void); - /* * ao_log_single.c */ diff --git a/src/kernel/ao_cmd.c b/src/kernel/ao_cmd.c index 10716afd..881f3500 100644 --- a/src/kernel/ao_cmd.c +++ b/src/kernel/ao_cmd.c @@ -24,13 +24,15 @@ __pdata uint32_t ao_cmd_lex_u32; __pdata char ao_cmd_lex_c; __pdata enum ao_cmd_status ao_cmd_status; +#ifndef AO_CMD_LEN #if AO_PYRO_NUM -#define CMD_LEN 128 +#define AO_CMD_LEN 128 #else -#define CMD_LEN 48 +#define AO_CMD_LEN 48 +#endif #endif -static __xdata char cmd_line[CMD_LEN]; +static __xdata char cmd_line[AO_CMD_LEN]; static __pdata uint8_t cmd_len; static __pdata uint8_t cmd_i; @@ -48,8 +50,8 @@ backspace(void) ao_put_string ("\010 \010"); } -static void -readline(void) +void +ao_cmd_readline(void) { char c; if (ao_echo()) @@ -88,7 +90,7 @@ readline(void) break; } - if (cmd_len >= CMD_LEN - 2) + if (cmd_len >= AO_CMD_LEN - 2) continue; cmd_line[cmd_len++] = c; if (ao_echo()) @@ -99,12 +101,13 @@ readline(void) cmd_i = 0; } -void +char ao_cmd_lex(void) { ao_cmd_lex_c = '\n'; if (cmd_i < cmd_len) ao_cmd_lex_c = cmd_line[cmd_i++]; + return ao_cmd_lex_c; } static void @@ -307,7 +310,7 @@ version(void) #endif #endif #if defined(AO_BOOT_APPLICATION_BASE) && defined(AO_BOOT_APPLICATION_BOUND) - , (uint32_t) AO_BOOT_APPLICATION_BOUND - (uint32_t) AO_BOOT_APPLICATION_BASE + , (unsigned) ((uint32_t) AO_BOOT_APPLICATION_BOUND - (uint32_t) AO_BOOT_APPLICATION_BASE) #endif ); printf("software-version %s\n", ao_version); @@ -376,7 +379,7 @@ ao_cmd(void) void (*__xdata func)(void); for (;;) { - readline(); + ao_cmd_readline(); ao_cmd_lex(); ao_cmd_white(); c = ao_cmd_lex_c; diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index 13eb05bf..a2f2c6ca 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -47,10 +47,12 @@ extern __pdata enum ao_flight_state ao_log_state; #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_TELEMINI2 8 /* 16-byte MS5607 baro only, 3.3V supply, cc1111 SoC */ #define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */ #define AO_LOG_FORMAT_TELEMEGA 10 /* 32 byte typed telemega records with 32 bit gyro cal */ #define AO_LOG_FORMAT_DETHERM 11 /* 16-byte MS5607 baro only, no ADC */ +#define AO_LOG_FORMAT_TELEMINI3 12 /* 16-byte MS5607 baro only, 3.3V supply, stm32f042 SoC */ +#define AO_LOG_FORMAT_TELEFIRETWO 13 /* 32-byte test stand data */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -299,6 +301,32 @@ struct ao_log_mega { ((l)->u.gps.altitude_high = (a) >> 16), \ (l)->u.gps.altitude_low = (a)) +struct ao_log_firetwo { + char type; /* 0 */ + uint8_t csum; /* 1 */ + uint16_t tick; /* 2 */ + union { /* 4 */ + /* AO_LOG_FLIGHT */ + struct { + uint16_t flight; /* 4 */ + uint16_t idle_pressure; /* 6 */ + uint16_t idle_thrust; /* 8 */ + } flight; /* 16 */ + /* AO_LOG_STATE */ + struct { + uint16_t state; /* 4 */ + uint16_t reason; /* 6 */ + } state; /* 8 */ + /* AO_LOG_SENSOR */ + struct { + uint16_t pressure; /* 4 */ + uint16_t thrust; /* 6 */ + uint16_t thermistor[4]; /* 8 */ + } sensor; /* 24 */ + uint8_t align[28]; /* 4 */ + } u; /* 32 */ +}; + struct ao_log_metrum { char type; /* 0 */ uint8_t csum; /* 1 */ diff --git a/src/kernel/ao_log_firetwo.c b/src/kernel/ao_log_firetwo.c new file mode 100644 index 00000000..4b42abe4 --- /dev/null +++ b/src/kernel/ao_log_firetwo.c @@ -0,0 +1,149 @@ +/* + * Copyright © 2017 Bdale Garbee + * + * 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. + */ + +#include "ao.h" +#include +#include +#include + +static __xdata struct ao_log_firetwo log; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEFIRETWO; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_firetwo); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_firetwo(__xdata struct ao_log_firetwo *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_firetwo)); + ao_log_current_pos += sizeof (struct ao_log_firetwo); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +#if HAS_ADC +static __data uint8_t ao_log_data_pos; + +/* a hack to make sure that ao_log_metrums fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_firetwo))] ; +#endif + +void +ao_log(void) +{ + uint16_t ao_idle_pressure = 0; // write code to capture pre-test values someday + uint16_t ao_idle_thrust = 0; + uint16_t ao_flight_state = ao_flight_startup; + + ao_storage_setup(); + + do { + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + + log.type = AO_LOG_FLIGHT; + log.tick = ao_time(); + log.u.flight.idle_pressure = ao_idle_pressure; + log.u.flight.idle_thrust = ao_idle_thrust; + log.u.flight.flight = ao_flight_number; + ao_log_firetwo(&log); + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_data_pos = ao_data_ring_next(ao_data_head); + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_data_pos != ao_data_head) { + log.tick = ao_data_ring[ao_log_data_pos].tick; + log.type = AO_LOG_SENSOR; + log.u.sensor.pressure = ao_data_ring[ao_log_data_pos].adc.pressure; + log.u.sensor.thrust = ao_data_ring[ao_log_data_pos].adc.thrust; + // for (i = 0; i < 4; i++) { + // log.u.sensor.thermistor[i] = ao_data_ring[ao_log_data_pos].sensor.thermistor[i]; + // } + ao_log_firetwo(&log); + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_time(); + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_firetwo(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } + + ao_log_flush(); + + if (!ao_log_running) break; + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + } + } while (ao_log_running); +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_firetwo))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/kernel/ao_pyro.c b/src/kernel/ao_pyro.c index 813e866a..a0881f9e 100644 --- a/src/kernel/ao_pyro.c +++ b/src/kernel/ao_pyro.c @@ -75,7 +75,8 @@ uint16_t ao_pyro_fired; #endif #if PYRO_DBG -#define DBG(...) do { printf("\t%d: ", (int) (pyro - ao_config.pyro)); printf(__VA_ARGS__); } while (0) +int pyro_dbg; +#define DBG(...) do { if (pyro_dbg) printf("\t%d: ", (int) (pyro - ao_config.pyro)); printf(__VA_ARGS__); } while (0) #else #define DBG(...) #endif diff --git a/src/kernel/ao_report.c b/src/kernel/ao_report.c index 6592d616..af48b390 100644 --- a/src/kernel/ao_report.c +++ b/src/kernel/ao_report.c @@ -45,9 +45,16 @@ static const uint8_t flight_reports[] = { #define mid(time) ao_beep_for(AO_BEEP_MID, time) #define high(time) ao_beep_for(AO_BEEP_HIGH, time) #else -#define low(time) ao_led_for(AO_LED_GREEN, time) -#define mid(time) ao_led_for(AO_LED_RED, time) -#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) +#ifndef AO_LED_LOW +#define AO_LED_LOW AO_LED_GREEN +#endif +#ifndef AO_LED_MID +#define AO_LED_MID AO_LED_RED +#endif + +#define low(time) ao_led_for(AO_LED_LOW, time) +#define mid(time) ao_led_for(AO_LED_MID, time) +#define high(time) ao_led_for(AO_LED_MID|AO_LED_LOW, time) #endif #define pause(time) ao_delay(time) diff --git a/src/kernel/ao_stdio.c b/src/kernel/ao_stdio.c index b79d465a..f0ee0a14 100644 --- a/src/kernel/ao_stdio.c +++ b/src/kernel/ao_stdio.c @@ -55,6 +55,9 @@ #ifndef PACKET_HAS_SLAVE #define PACKET_HAS_SLAVE 0 #endif +#ifndef CONSOLE_STDIN +#define CONSOLE_STDIN 0 +#endif #define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \ USE_SERIAL_1_STDIN + \ @@ -67,7 +70,7 @@ USE_SERIAL_8_STDIN + \ USE_SERIAL_9_STDIN) -#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) +#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN + CONSOLE_STDIN) __xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; diff --git a/src/kernel/ao_task.c b/src/kernel/ao_task.c index e8a092aa..de23ea02 100644 --- a/src/kernel/ao_task.c +++ b/src/kernel/ao_task.c @@ -373,7 +373,11 @@ ao_yield(void) ao_arch_naked_define if (!ao_list_is_empty(&run_queue)) break; /* Wait for interrupts when there's nothing ready */ - ao_arch_wait_interrupt(); + if (ao_task_minimize_latency) { + ao_arch_release_interrupts(); + ao_arch_block_interrupts(); + } else + ao_arch_wait_interrupt(); } ao_cur_task = ao_list_first_entry(&run_queue, struct ao_task, queue); #else diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 15085bf4..fa817824 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -270,7 +270,7 @@ ao_send_mini(void) __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; telemetry.generic.tick = packet->tick; - telemetry.generic.type = AO_TELEMETRY_MINI; + telemetry.generic.type = AO_SEND_MINI; telemetry.mini.state = ao_flight_state; diff --git a/src/kernel/ao_telemetry.h b/src/kernel/ao_telemetry.h index c0f5e3c5..45aaeb07 100644 --- a/src/kernel/ao_telemetry.h +++ b/src/kernel/ao_telemetry.h @@ -270,7 +270,8 @@ struct ao_telemetry_metrum_data { /* 32 */ }; -#define AO_TELEMETRY_MINI 0x10 +#define AO_TELEMETRY_MINI2 0x10 /* CC1111 based */ +#define AO_TELEMETRY_MINI3 0x11 /* STMF042 based */ struct ao_telemetry_mini { uint16_t serial; /* 0 */ diff --git a/src/lambdakey-v1.0/.gitignore b/src/lambdakey-v1.0/.gitignore new file mode 100644 index 00000000..6462d930 --- /dev/null +++ b/src/lambdakey-v1.0/.gitignore @@ -0,0 +1,2 @@ +lambdakey-* +ao_product.h diff --git a/src/lambdakey-v1.0/Makefile b/src/lambdakey-v1.0/Makefile new file mode 100644 index 00000000..2609bea3 --- /dev/null +++ b/src/lambdakey-v1.0/Makefile @@ -0,0 +1,92 @@ +# +# AltOS build +# +# + +include ../stmf0/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_lisp.h \ + ao_lisp_const.h \ + ao_lisp_os.h \ + stm32f0.h \ + Makefile + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_dma_stm.c \ + ao_stdio.c \ + ao_mutex.c \ + ao_panic.c \ + ao_timer.c \ + ao_usb_stm.c \ + ao_flash_stm.c \ + ao_lisp_lex.c \ + ao_lisp_mem.c \ + ao_lisp_cons.c \ + ao_lisp_eval.c \ + ao_lisp_string.c \ + ao_lisp_atom.c \ + ao_lisp_int.c \ + ao_lisp_poly.c \ + ao_lisp_builtin.c \ + ao_lisp_read.c \ + ao_lisp_rep.c \ + ao_lisp_frame.c \ + ao_lisp_error.c \ + ao_lisp_lambda.c \ + ao_lisp_save.c \ + ao_lisp_stack.c \ + ao_lisp_os_save.c + +PRODUCT=LambdaKey-v1.0 +PRODUCT_DEF=-DLAMBDAKEY +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) -I. $(STMF0_CFLAGS) -Os -g + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tlambda.ld + +PROGNAME=lambdakey-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_lambdakey.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) lambda.ld 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) + stm-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/lambdakey-v1.0/ao_lambdakey.c b/src/lambdakey-v1.0/ao_lambdakey.c new file mode 100644 index 00000000..8bd344cf --- /dev/null +++ b/src/lambdakey-v1.0/ao_lambdakey.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include +#include + +static void lisp_cmd() { + ao_lisp_read_eval_print(); +} + +static const struct ao_cmds blink_cmds[] = { + { lisp_cmd, "l\0Run lisp interpreter" }, + { 0, 0 } +}; + + +void main(void) +{ + ao_led_init(LEDS_AVAILABLE); + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_dma_init(); + ao_usb_init(); + ao_cmd_init(); + ao_cmd_register(blink_cmds); + ao_start_scheduler(); +} + + diff --git a/src/lambdakey-v1.0/ao_lisp_os.h b/src/lambdakey-v1.0/ao_lisp_os.h new file mode 100644 index 00000000..1993ac44 --- /dev/null +++ b/src/lambdakey-v1.0/ao_lisp_os.h @@ -0,0 +1,62 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_LISP_OS_H_ +#define _AO_LISP_OS_H_ + +#include "ao.h" + +static inline int +ao_lisp_getc() { + static uint8_t at_eol; + int c; + + if (at_eol) { + ao_cmd_readline(); + at_eol = 0; + } + c = ao_cmd_lex(); + if (c == '\n') + at_eol = 1; + return c; +} + +static inline void +ao_lisp_os_flush(void) +{ + flush(); +} + +static inline void +ao_lisp_abort(void) +{ + ao_panic(1); +} + +static inline void +ao_lisp_os_led(int led) +{ + ao_led_set(led); +} + +static inline void +ao_lisp_os_delay(int delay) +{ + ao_delay(AO_MS_TO_TICKS(delay)); +} + +#endif diff --git a/src/lambdakey-v1.0/ao_lisp_os_save.c b/src/lambdakey-v1.0/ao_lisp_os_save.c new file mode 100644 index 00000000..44138398 --- /dev/null +++ b/src/lambdakey-v1.0/ao_lisp_os_save.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include +#include +#include + +extern uint8_t __flash__[]; + +/* saved variables to rebuild the heap + + ao_lisp_atoms + ao_lisp_frame_global + */ + +int +ao_lisp_os_save(void) +{ + int i; + + for (i = 0; i < AO_LISP_POOL_TOTAL; i += 256) { + uint32_t *dst = (uint32_t *) &__flash__[i]; + uint32_t *src = (uint32_t *) &ao_lisp_pool[i]; + + ao_flash_page(dst, src); + } + return 1; +} + +int +ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset) +{ + memcpy(save, &__flash__[offset], sizeof (struct ao_lisp_os_save)); + return 1; +} + +int +ao_lisp_os_restore(void) +{ + memcpy(ao_lisp_pool, __flash__, AO_LISP_POOL_TOTAL); + return 1; +} diff --git a/src/lambdakey-v1.0/ao_pins.h b/src/lambdakey-v1.0/ao_pins.h new file mode 100644 index 00000000..2ba79c01 --- /dev/null +++ b/src/lambdakey-v1.0/ao_pins.h @@ -0,0 +1,57 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN +#define LED_PORT (&stm_gpiob) +#define LED_PIN_RED 4 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_PANIC AO_LED_RED +#define AO_CMD_LEN 128 +#define AO_LISP_POOL_TOTAL 3072 +#define AO_LISP_SAVE 1 +#define AO_STACK_SIZE 1024 + +/* need HSI active to write to flash */ +#define AO_NEED_HSI 1 + +#define LEDS_AVAILABLE (AO_LED_RED) + +#define AO_POWER_MANAGEMENT 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 0 +#define AO_PA11_PA12_RMP 1 +#define HAS_BEEP 0 + +#define IS_FLASH_LOADER 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/lambdakey-v1.0/flash-loader/.gitignore b/src/lambdakey-v1.0/flash-loader/.gitignore new file mode 100644 index 00000000..86ebb7f2 --- /dev/null +++ b/src/lambdakey-v1.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +lambdakey* diff --git a/src/lambdakey-v1.0/flash-loader/Makefile b/src/lambdakey-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..dbded719 --- /dev/null +++ b/src/lambdakey-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=lambdakey-v1.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/lambdakey-v1.0/flash-loader/ao_pins.h b/src/lambdakey-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..4b788f67 --- /dev/null +++ b/src/lambdakey-v1.0/flash-loader/ao_pins.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 15 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/lambdakey-v1.0/lambda.ld b/src/lambdakey-v1.0/lambda.ld new file mode 100644 index 00000000..5de65eb5 --- /dev/null +++ b/src/lambdakey-v1.0/lambda.ld @@ -0,0 +1,117 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08001000, LENGTH = 25K + flash (r): ORIGIN = 0x08007400, LENGTH = 3k + 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 + + /* 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 */ + . = 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)); + + __flash__ = ORIGIN(flash); +} + +ENTRY(start); diff --git a/src/lisp/.gitignore b/src/lisp/.gitignore new file mode 100644 index 00000000..76a555ea --- /dev/null +++ b/src/lisp/.gitignore @@ -0,0 +1,2 @@ +ao_lisp_make_const +ao_lisp_const.h diff --git a/src/lisp/Makefile b/src/lisp/Makefile new file mode 100644 index 00000000..25796ec5 --- /dev/null +++ b/src/lisp/Makefile @@ -0,0 +1,22 @@ +all: ao_lisp_const.h + +clean: + rm -f ao_lisp_const.h $(OBJS) ao_lisp_make_const + +ao_lisp_const.h: ao_lisp_const.lisp ao_lisp_make_const + ./ao_lisp_make_const -o $@ ao_lisp_const.lisp + +include Makefile-inc +SRCS=$(LISP_SRCS) + +HDRS=$(LISP_HDRS) + +OBJS=$(SRCS:.c=.o) + +CFLAGS=-DAO_LISP_MAKE_CONST -O0 -g -I. -Wall -Wextra -no-pie + + +ao_lisp_make_const: $(OBJS) + $(CC) $(CFLAGS) -o $@ $(OBJS) + +$(OBJS): $(HDRS) diff --git a/src/lisp/Makefile-inc b/src/lisp/Makefile-inc new file mode 100644 index 00000000..126deeb0 --- /dev/null +++ b/src/lisp/Makefile-inc @@ -0,0 +1,22 @@ +LISP_SRCS=\ + ao_lisp_make_const.c\ + ao_lisp_mem.c \ + ao_lisp_cons.c \ + ao_lisp_string.c \ + ao_lisp_atom.c \ + ao_lisp_int.c \ + ao_lisp_poly.c \ + ao_lisp_builtin.c \ + ao_lisp_read.c \ + ao_lisp_frame.c \ + ao_lisp_lambda.c \ + ao_lisp_eval.c \ + ao_lisp_rep.c \ + ao_lisp_save.c \ + ao_lisp_stack.c \ + ao_lisp_error.c + +LISP_HDRS=\ + ao_lisp.h \ + ao_lisp_os.h \ + ao_lisp_read.h diff --git a/src/lisp/Makefile-lisp b/src/lisp/Makefile-lisp new file mode 100644 index 00000000..998c7673 --- /dev/null +++ b/src/lisp/Makefile-lisp @@ -0,0 +1,4 @@ +include ../lisp/Makefile-inc + +ao_lisp_const.h: $(LISP_SRCS) $(LISP_HDRS) + +cd ../lisp && make $@ diff --git a/src/lisp/ao_lisp.h b/src/lisp/ao_lisp.h new file mode 100644 index 00000000..980514cc --- /dev/null +++ b/src/lisp/ao_lisp.h @@ -0,0 +1,793 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_LISP_H_ +#define _AO_LISP_H_ + +#define DBG_MEM 0 +#define DBG_EVAL 0 + +#include +#include +#include + +typedef uint16_t ao_poly; +typedef int16_t ao_signed_poly; + +#ifdef AO_LISP_SAVE + +struct ao_lisp_os_save { + ao_poly atoms; + ao_poly globals; + uint16_t const_checksum; + uint16_t const_checksum_inv; +}; + +#define AO_LISP_POOL_EXTRA (sizeof(struct ao_lisp_os_save)) +#define AO_LISP_POOL ((int) (AO_LISP_POOL_TOTAL - AO_LISP_POOL_EXTRA)) + +int +ao_lisp_os_save(void); + +int +ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset); + +int +ao_lisp_os_restore(void); + +#endif + +#ifdef AO_LISP_MAKE_CONST +#define AO_LISP_POOL_CONST 16384 +extern uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4))); +#define ao_lisp_pool ao_lisp_const +#define AO_LISP_POOL AO_LISP_POOL_CONST + +#define _atom(n) ao_lisp_atom_poly(ao_lisp_atom_intern(n)) + +#define _ao_lisp_atom_quote _atom("quote") +#define _ao_lisp_atom_set _atom("set") +#define _ao_lisp_atom_setq _atom("setq") +#define _ao_lisp_atom_t _atom("t") +#define _ao_lisp_atom_car _atom("car") +#define _ao_lisp_atom_cdr _atom("cdr") +#define _ao_lisp_atom_cons _atom("cons") +#define _ao_lisp_atom_last _atom("last") +#define _ao_lisp_atom_length _atom("length") +#define _ao_lisp_atom_cond _atom("cond") +#define _ao_lisp_atom_lambda _atom("lambda") +#define _ao_lisp_atom_led _atom("led") +#define _ao_lisp_atom_delay _atom("delay") +#define _ao_lisp_atom_pack _atom("pack") +#define _ao_lisp_atom_unpack _atom("unpack") +#define _ao_lisp_atom_flush _atom("flush") +#define _ao_lisp_atom_eval _atom("eval") +#define _ao_lisp_atom_read _atom("read") +#define _ao_lisp_atom_eof _atom("eof") +#define _ao_lisp_atom_save _atom("save") +#define _ao_lisp_atom_restore _atom("restore") +#define _ao_lisp_atom_call2fcc _atom("call/cc") +#define _ao_lisp_atom_collect _atom("collect") +#define _ao_lisp_atom_symbolp _atom("symbol?") +#define _ao_lisp_atom_builtin _atom("builtin?") +#define _ao_lisp_atom_symbolp _atom("symbol?") +#define _ao_lisp_atom_symbolp _atom("symbol?") +#else +#include "ao_lisp_const.h" +#ifndef AO_LISP_POOL +#define AO_LISP_POOL 3072 +#endif +extern uint8_t ao_lisp_pool[AO_LISP_POOL + AO_LISP_POOL_EXTRA] __attribute__((aligned(4))); +#endif + +/* Primitive types */ +#define AO_LISP_CONS 0 +#define AO_LISP_INT 1 +#define AO_LISP_STRING 2 +#define AO_LISP_OTHER 3 + +#define AO_LISP_TYPE_MASK 0x0003 +#define AO_LISP_TYPE_SHIFT 2 +#define AO_LISP_REF_MASK 0x7ffc +#define AO_LISP_CONST 0x8000 + +/* These have a type value at the start of the struct */ +#define AO_LISP_ATOM 4 +#define AO_LISP_BUILTIN 5 +#define AO_LISP_FRAME 6 +#define AO_LISP_LAMBDA 7 +#define AO_LISP_STACK 8 +#define AO_LISP_NUM_TYPE 9 + +/* Leave two bits for types to use as they please */ +#define AO_LISP_OTHER_TYPE_MASK 0x3f + +#define AO_LISP_NIL 0 + +extern uint16_t ao_lisp_top; + +#define AO_LISP_OOM 0x01 +#define AO_LISP_DIVIDE_BY_ZERO 0x02 +#define AO_LISP_INVALID 0x04 +#define AO_LISP_UNDEFINED 0x08 +#define AO_LISP_EOF 0x10 + +extern uint8_t ao_lisp_exception; + +static inline int +ao_lisp_is_const(ao_poly poly) { + return poly & AO_LISP_CONST; +} + +#define AO_LISP_IS_CONST(a) (ao_lisp_const <= ((uint8_t *) (a)) && ((uint8_t *) (a)) < ao_lisp_const + AO_LISP_POOL_CONST) +#define AO_LISP_IS_POOL(a) (ao_lisp_pool <= ((uint8_t *) (a)) && ((uint8_t *) (a)) < ao_lisp_pool + AO_LISP_POOL) +#define AO_LISP_IS_INT(p) (ao_lisp_base_type(p) == AO_LISP_INT); + +void * +ao_lisp_ref(ao_poly poly); + +ao_poly +ao_lisp_poly(const void *addr, ao_poly type); + +struct ao_lisp_type { + int (*size)(void *addr); + void (*mark)(void *addr); + void (*move)(void *addr); + char name[]; +}; + +struct ao_lisp_cons { + ao_poly car; + ao_poly cdr; +}; + +struct ao_lisp_atom { + uint8_t type; + uint8_t pad[1]; + ao_poly next; + char name[]; +}; + +struct ao_lisp_val { + ao_poly atom; + ao_poly val; +}; + +struct ao_lisp_frame { + uint8_t type; + uint8_t num; + ao_poly prev; + struct ao_lisp_val vals[]; +}; + +/* Set on type when the frame escapes the lambda */ +#define AO_LISP_FRAME_MARK 0x80 +#define AO_LISP_FRAME_PRINT 0x40 + +static inline int ao_lisp_frame_marked(struct ao_lisp_frame *f) { + return f->type & AO_LISP_FRAME_MARK; +} + +static inline struct ao_lisp_frame * +ao_lisp_poly_frame(ao_poly poly) { + return ao_lisp_ref(poly); +} + +static inline ao_poly +ao_lisp_frame_poly(struct ao_lisp_frame *frame) { + return ao_lisp_poly(frame, AO_LISP_OTHER); +} + +enum eval_state { + eval_sexpr, /* Evaluate an sexpr */ + eval_val, /* Value computed */ + eval_formal, /* Formal computed */ + eval_exec, /* Start a lambda evaluation */ + eval_cond, /* Start next cond clause */ + eval_cond_test, /* Check cond condition */ + eval_progn, /* Start next progn entry */ + eval_while, /* Start while condition */ + eval_while_test, /* Check while condition */ + eval_macro, /* Finished with macro generation */ +}; + +struct ao_lisp_stack { + uint8_t type; /* AO_LISP_STACK */ + uint8_t state; /* enum eval_state */ + ao_poly prev; /* previous stack frame */ + ao_poly sexprs; /* expressions to evaluate */ + ao_poly values; /* values computed */ + ao_poly values_tail; /* end of the values list for easy appending */ + ao_poly frame; /* current lookup frame */ + ao_poly list; /* most recent function call */ +}; + +#define AO_LISP_STACK_MARK 0x80 /* set on type when a reference has been taken */ +#define AO_LISP_STACK_PRINT 0x40 /* stack is being printed */ + +static inline int ao_lisp_stack_marked(struct ao_lisp_stack *s) { + return s->type & AO_LISP_STACK_MARK; +} + +static inline void ao_lisp_stack_mark(struct ao_lisp_stack *s) { + s->type |= AO_LISP_STACK_MARK; +} + +static inline struct ao_lisp_stack * +ao_lisp_poly_stack(ao_poly p) +{ + return ao_lisp_ref(p); +} + +static inline ao_poly +ao_lisp_stack_poly(struct ao_lisp_stack *stack) +{ + return ao_lisp_poly(stack, AO_LISP_OTHER); +} + +extern ao_poly ao_lisp_v; + +#define AO_LISP_FUNC_LAMBDA 0 +#define AO_LISP_FUNC_NLAMBDA 1 +#define AO_LISP_FUNC_MACRO 2 +#define AO_LISP_FUNC_LEXPR 3 + +#define AO_LISP_FUNC_FREE_ARGS 0x80 +#define AO_LISP_FUNC_MASK 0x7f + +#define AO_LISP_FUNC_F_LAMBDA (AO_LISP_FUNC_FREE_ARGS | AO_LISP_FUNC_LAMBDA) +#define AO_LISP_FUNC_F_NLAMBDA (AO_LISP_FUNC_FREE_ARGS | AO_LISP_FUNC_NLAMBDA) +#define AO_LISP_FUNC_F_MACRO (AO_LISP_FUNC_FREE_ARGS | AO_LISP_FUNC_MACRO) +#define AO_LISP_FUNC_F_LEXPR (AO_LISP_FUNC_FREE_ARGS | AO_LISP_FUNC_LEXPR) + +struct ao_lisp_builtin { + uint8_t type; + uint8_t args; + uint16_t func; +}; + +enum ao_lisp_builtin_id { + builtin_eval, + builtin_read, + builtin_lambda, + builtin_lexpr, + builtin_nlambda, + builtin_macro, + builtin_car, + builtin_cdr, + builtin_cons, + builtin_last, + builtin_length, + builtin_quote, + builtin_set, + builtin_setq, + builtin_cond, + builtin_progn, + builtin_while, + builtin_print, + builtin_patom, + builtin_plus, + builtin_minus, + builtin_times, + builtin_divide, + builtin_mod, + builtin_equal, + builtin_less, + builtin_greater, + builtin_less_equal, + builtin_greater_equal, + builtin_pack, + builtin_unpack, + builtin_flush, + builtin_delay, + builtin_led, + builtin_save, + builtin_restore, + builtin_call_cc, + builtin_collect, + _builtin_last +}; + +typedef ao_poly (*ao_lisp_func_t)(struct ao_lisp_cons *cons); + +extern const ao_lisp_func_t ao_lisp_builtins[]; + +static inline ao_lisp_func_t +ao_lisp_func(struct ao_lisp_builtin *b) +{ + return ao_lisp_builtins[b->func]; +} + +struct ao_lisp_lambda { + uint8_t type; + uint8_t args; + ao_poly code; + ao_poly frame; +}; + +static inline struct ao_lisp_lambda * +ao_lisp_poly_lambda(ao_poly poly) +{ + return ao_lisp_ref(poly); +} + +static inline ao_poly +ao_lisp_lambda_poly(struct ao_lisp_lambda *lambda) +{ + return ao_lisp_poly(lambda, AO_LISP_OTHER); +} + +static inline void * +ao_lisp_poly_other(ao_poly poly) { + return ao_lisp_ref(poly); +} + +static inline uint8_t +ao_lisp_other_type(void *other) { +#if DBG_MEM + if ((*((uint8_t *) other) & AO_LISP_OTHER_TYPE_MASK) >= AO_LISP_NUM_TYPE) + ao_lisp_abort(); +#endif + return *((uint8_t *) other) & AO_LISP_OTHER_TYPE_MASK; +} + +static inline ao_poly +ao_lisp_other_poly(const void *other) +{ + return ao_lisp_poly(other, AO_LISP_OTHER); +} + +static inline int +ao_lisp_size_round(int size) +{ + return (size + 3) & ~3; +} + +static inline int +ao_lisp_size(const struct ao_lisp_type *type, void *addr) +{ + return ao_lisp_size_round(type->size(addr)); +} + +#define AO_LISP_OTHER_POLY(other) ((ao_poly)(other) + AO_LISP_OTHER) + +static inline int ao_lisp_poly_base_type(ao_poly poly) { + return poly & AO_LISP_TYPE_MASK; +} + +static inline int ao_lisp_poly_type(ao_poly poly) { + int type = poly & AO_LISP_TYPE_MASK; + if (type == AO_LISP_OTHER) + return ao_lisp_other_type(ao_lisp_poly_other(poly)); + return type; +} + +static inline struct ao_lisp_cons * +ao_lisp_poly_cons(ao_poly poly) +{ + return ao_lisp_ref(poly); +} + +static inline ao_poly +ao_lisp_cons_poly(struct ao_lisp_cons *cons) +{ + return ao_lisp_poly(cons, AO_LISP_CONS); +} + +static inline int +ao_lisp_poly_int(ao_poly poly) +{ + return (int) ((ao_signed_poly) poly >> AO_LISP_TYPE_SHIFT); +} + +static inline ao_poly +ao_lisp_int_poly(int i) +{ + return ((ao_poly) i << 2) | AO_LISP_INT; +} + +static inline char * +ao_lisp_poly_string(ao_poly poly) +{ + return ao_lisp_ref(poly); +} + +static inline ao_poly +ao_lisp_string_poly(char *s) +{ + return ao_lisp_poly(s, AO_LISP_STRING); +} + +static inline struct ao_lisp_atom * +ao_lisp_poly_atom(ao_poly poly) +{ + return ao_lisp_ref(poly); +} + +static inline ao_poly +ao_lisp_atom_poly(struct ao_lisp_atom *a) +{ + return ao_lisp_poly(a, AO_LISP_OTHER); +} + +static inline struct ao_lisp_builtin * +ao_lisp_poly_builtin(ao_poly poly) +{ + return ao_lisp_ref(poly); +} + +static inline ao_poly +ao_lisp_builtin_poly(struct ao_lisp_builtin *b) +{ + return ao_lisp_poly(b, AO_LISP_OTHER); +} + +/* memory functions */ + +extern int ao_lisp_collects[2]; +extern int ao_lisp_freed[2]; +extern int ao_lisp_loops[2]; + +/* returns 1 if the object was already marked */ +int +ao_lisp_mark(const struct ao_lisp_type *type, void *addr); + +/* returns 1 if the object was already marked */ +int +ao_lisp_mark_memory(const struct ao_lisp_type *type, void *addr); + +void * +ao_lisp_move_map(void *addr); + +/* returns 1 if the object was already moved */ +int +ao_lisp_move(const struct ao_lisp_type *type, void **ref); + +/* returns 1 if the object was already moved */ +int +ao_lisp_move_memory(const struct ao_lisp_type *type, void **ref); + +void * +ao_lisp_alloc(int size); + +#define AO_LISP_COLLECT_FULL 1 +#define AO_LISP_COLLECT_INCREMENTAL 0 + +int +ao_lisp_collect(uint8_t style); + +void +ao_lisp_cons_stash(int id, struct ao_lisp_cons *cons); + +struct ao_lisp_cons * +ao_lisp_cons_fetch(int id); + +void +ao_lisp_poly_stash(int id, ao_poly poly); + +ao_poly +ao_lisp_poly_fetch(int id); + +void +ao_lisp_string_stash(int id, char *string); + +char * +ao_lisp_string_fetch(int id); + +static inline void +ao_lisp_stack_stash(int id, struct ao_lisp_stack *stack) { + ao_lisp_poly_stash(id, ao_lisp_stack_poly(stack)); +} + +static inline struct ao_lisp_stack * +ao_lisp_stack_fetch(int id) { + return ao_lisp_poly_stack(ao_lisp_poly_fetch(id)); +} + +/* cons */ +extern const struct ao_lisp_type ao_lisp_cons_type; + +struct ao_lisp_cons * +ao_lisp_cons_cons(ao_poly car, struct ao_lisp_cons *cdr); + +extern struct ao_lisp_cons *ao_lisp_cons_free_list; + +void +ao_lisp_cons_free(struct ao_lisp_cons *cons); + +void +ao_lisp_cons_print(ao_poly); + +void +ao_lisp_cons_patom(ao_poly); + +int +ao_lisp_cons_length(struct ao_lisp_cons *cons); + +/* string */ +extern const struct ao_lisp_type ao_lisp_string_type; + +char * +ao_lisp_string_copy(char *a); + +char * +ao_lisp_string_cat(char *a, char *b); + +ao_poly +ao_lisp_string_pack(struct ao_lisp_cons *cons); + +ao_poly +ao_lisp_string_unpack(char *a); + +void +ao_lisp_string_print(ao_poly s); + +void +ao_lisp_string_patom(ao_poly s); + +/* atom */ +extern const struct ao_lisp_type ao_lisp_atom_type; + +extern struct ao_lisp_atom *ao_lisp_atoms; +extern struct ao_lisp_frame *ao_lisp_frame_global; +extern struct ao_lisp_frame *ao_lisp_frame_current; + +void +ao_lisp_atom_print(ao_poly a); + +struct ao_lisp_atom * +ao_lisp_atom_intern(char *name); + +ao_poly * +ao_lisp_atom_ref(struct ao_lisp_frame *frame, ao_poly atom); + +ao_poly +ao_lisp_atom_get(ao_poly atom); + +ao_poly +ao_lisp_atom_set(ao_poly atom, ao_poly val); + +/* int */ +void +ao_lisp_int_print(ao_poly i); + +/* prim */ +void +ao_lisp_poly_print(ao_poly p); + +void +ao_lisp_poly_patom(ao_poly p); + +int +ao_lisp_poly_mark(ao_poly p, uint8_t note_cons); + +/* returns 1 if the object has already been moved */ +int +ao_lisp_poly_move(ao_poly *p, uint8_t note_cons); + +/* eval */ + +void +ao_lisp_eval_clear_globals(void); + +int +ao_lisp_eval_restart(void); + +ao_poly +ao_lisp_eval(ao_poly p); + +ao_poly +ao_lisp_set_cond(struct ao_lisp_cons *cons); + +/* builtin */ +void +ao_lisp_builtin_print(ao_poly b); + +extern const struct ao_lisp_type ao_lisp_builtin_type; + +/* Check argument count */ +ao_poly +ao_lisp_check_argc(ao_poly name, struct ao_lisp_cons *cons, int min, int max); + +/* Check argument type */ +ao_poly +ao_lisp_check_argt(ao_poly name, struct ao_lisp_cons *cons, int argc, int type, int nil_ok); + +/* Fetch an arg (nil if off the end) */ +ao_poly +ao_lisp_arg(struct ao_lisp_cons *cons, int argc); + +char * +ao_lisp_args_name(uint8_t args); + +/* read */ +extern struct ao_lisp_cons *ao_lisp_read_cons; +extern struct ao_lisp_cons *ao_lisp_read_cons_tail; +extern struct ao_lisp_cons *ao_lisp_read_stack; + +ao_poly +ao_lisp_read(void); + +/* rep */ +ao_poly +ao_lisp_read_eval_print(void); + +/* frame */ +extern const struct ao_lisp_type ao_lisp_frame_type; + +#define AO_LISP_FRAME_FREE 6 + +extern struct ao_lisp_frame *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE]; + +ao_poly +ao_lisp_frame_mark(struct ao_lisp_frame *frame); + +ao_poly * +ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom); + +struct ao_lisp_frame * +ao_lisp_frame_new(int num); + +void +ao_lisp_frame_free(struct ao_lisp_frame *frame); + +void +ao_lisp_frame_bind(struct ao_lisp_frame *frame, int num, ao_poly atom, ao_poly val); + +int +ao_lisp_frame_add(struct ao_lisp_frame **frame, ao_poly atom, ao_poly val); + +void +ao_lisp_frame_print(ao_poly p); + +/* lambda */ +extern const struct ao_lisp_type ao_lisp_lambda_type; + +extern const char *ao_lisp_state_names[]; + +struct ao_lisp_lambda * +ao_lisp_lambda_new(ao_poly cons); + +void +ao_lisp_lambda_print(ao_poly lambda); + +ao_poly +ao_lisp_lambda(struct ao_lisp_cons *cons); + +ao_poly +ao_lisp_lexpr(struct ao_lisp_cons *cons); + +ao_poly +ao_lisp_nlambda(struct ao_lisp_cons *cons); + +ao_poly +ao_lisp_macro(struct ao_lisp_cons *cons); + +ao_poly +ao_lisp_lambda_eval(void); + +/* save */ + +ao_poly +ao_lisp_save(struct ao_lisp_cons *cons); + +ao_poly +ao_lisp_restore(struct ao_lisp_cons *cons); + +/* stack */ + +extern const struct ao_lisp_type ao_lisp_stack_type; +extern struct ao_lisp_stack *ao_lisp_stack; +extern struct ao_lisp_stack *ao_lisp_stack_free_list; + +void +ao_lisp_stack_reset(struct ao_lisp_stack *stack); + +int +ao_lisp_stack_push(void); + +void +ao_lisp_stack_pop(void); + +void +ao_lisp_stack_clear(void); + +void +ao_lisp_stack_print(ao_poly stack); + +ao_poly +ao_lisp_stack_eval(void); + +ao_poly +ao_lisp_call_cc(struct ao_lisp_cons *cons); + +/* error */ + +void +ao_lisp_error_poly(char *name, ao_poly poly, ao_poly last); + +void +ao_lisp_error_frame(int indent, char *name, struct ao_lisp_frame *frame); + +ao_poly +ao_lisp_error(int error, char *format, ...); + +/* debugging macros */ + +#if DBG_EVAL +#define DBG_CODE 1 +int ao_lisp_stack_depth; +#define DBG_DO(a) a +#define DBG_INDENT() do { int _s; for(_s = 0; _s < ao_lisp_stack_depth; _s++) printf(" "); } while(0) +#define DBG_IN() (++ao_lisp_stack_depth) +#define DBG_OUT() (--ao_lisp_stack_depth) +#define DBG_RESET() (ao_lisp_stack_depth = 0) +#define DBG(...) printf(__VA_ARGS__) +#define DBGI(...) do { DBG("%4d: ", __LINE__); DBG_INDENT(); DBG(__VA_ARGS__); } while (0) +#define DBG_CONS(a) ao_lisp_cons_print(ao_lisp_cons_poly(a)) +#define DBG_POLY(a) ao_lisp_poly_print(a) +#define OFFSET(a) ((a) ? (int) ((uint8_t *) a - ao_lisp_pool) : -1) +#define DBG_STACK() ao_lisp_stack_print(ao_lisp_stack_poly(ao_lisp_stack)) +static inline void +ao_lisp_frames_dump(void) +{ + struct ao_lisp_stack *s; + DBGI(".. current frame: "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + for (s = ao_lisp_stack; s; s = ao_lisp_poly_stack(s->prev)) { + DBGI(".. stack frame: "); DBG_POLY(s->frame); DBG("\n"); + } +} +#define DBG_FRAMES() ao_lisp_frames_dump() +#else +#define DBG_DO(a) +#define DBG_INDENT() +#define DBG_IN() +#define DBG_OUT() +#define DBG(...) +#define DBGI(...) +#define DBG_CONS(a) +#define DBG_POLY(a) +#define DBG_RESET() +#define DBG_STACK() +#define DBG_FRAMES() +#endif + +#define DBG_MEM_START 1 + +#if DBG_MEM + +#include +extern int dbg_move_depth; +#define MDBG_DUMP 1 +#define MDBG_OFFSET(a) ((int) ((uint8_t *) (a) - ao_lisp_pool)) + +extern int dbg_mem; + +#define MDBG_DO(a) a +#define MDBG_MOVE(...) do { if (dbg_mem) { int d; for (d = 0; d < dbg_move_depth; d++) printf (" "); printf(__VA_ARGS__); } } while (0) +#define MDBG_MORE(...) do { if (dbg_mem) printf(__VA_ARGS__); } while (0) +#define MDBG_MOVE_IN() (dbg_move_depth++) +#define MDBG_MOVE_OUT() (assert(--dbg_move_depth >= 0)) + +#else + +#define MDBG_DO(a) +#define MDBG_MOVE(...) +#define MDBG_MORE(...) +#define MDBG_MOVE_IN() +#define MDBG_MOVE_OUT() + +#endif + +#endif /* _AO_LISP_H_ */ diff --git a/src/lisp/ao_lisp_atom.c b/src/lisp/ao_lisp_atom.c new file mode 100644 index 00000000..8c9e8ed1 --- /dev/null +++ b/src/lisp/ao_lisp_atom.c @@ -0,0 +1,165 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_lisp.h" + +static int name_size(char *name) +{ + return sizeof(struct ao_lisp_atom) + strlen(name) + 1; +} + +static int atom_size(void *addr) +{ + struct ao_lisp_atom *atom = addr; + if (!atom) + return 0; + return name_size(atom->name); +} + +static void atom_mark(void *addr) +{ + struct ao_lisp_atom *atom = addr; + + for (;;) { + atom = ao_lisp_poly_atom(atom->next); + if (!atom) + break; + if (ao_lisp_mark_memory(&ao_lisp_atom_type, atom)) + break; + } +} + +static void atom_move(void *addr) +{ + struct ao_lisp_atom *atom = addr; + int ret; + + for (;;) { + struct ao_lisp_atom *next = ao_lisp_poly_atom(atom->next); + + if (!next) + break; + ret = ao_lisp_move_memory(&ao_lisp_atom_type, (void **) &next); + if (next != ao_lisp_poly_atom(atom->next)) + atom->next = ao_lisp_atom_poly(next); + if (ret) + break; + atom = next; + } +} + +const struct ao_lisp_type ao_lisp_atom_type = { + .mark = atom_mark, + .size = atom_size, + .move = atom_move, + .name = "atom" +}; + +struct ao_lisp_atom *ao_lisp_atoms; + +struct ao_lisp_atom * +ao_lisp_atom_intern(char *name) +{ + struct ao_lisp_atom *atom; + + for (atom = ao_lisp_atoms; atom; atom = ao_lisp_poly_atom(atom->next)) { + if (!strcmp(atom->name, name)) + return atom; + } +#ifdef ao_builtin_atoms + for (atom = ao_lisp_poly_atom(ao_builtin_atoms); atom; atom = ao_lisp_poly_atom(atom->next)) { + if (!strcmp(atom->name, name)) + return atom; + } +#endif + ao_lisp_string_stash(0, name); + atom = ao_lisp_alloc(name_size(name)); + name = ao_lisp_string_fetch(0); + if (atom) { + atom->type = AO_LISP_ATOM; + atom->next = ao_lisp_atom_poly(ao_lisp_atoms); + ao_lisp_atoms = atom; + strcpy(atom->name, name); + } + return atom; +} + +struct ao_lisp_frame *ao_lisp_frame_global; +struct ao_lisp_frame *ao_lisp_frame_current; + +static void +ao_lisp_atom_init(void) +{ + if (!ao_lisp_frame_global) + ao_lisp_frame_global = ao_lisp_frame_new(0); +} + +ao_poly * +ao_lisp_atom_ref(struct ao_lisp_frame *frame, ao_poly atom) +{ + ao_poly *ref; + ao_lisp_atom_init(); + while (frame) { + ref = ao_lisp_frame_ref(frame, atom); + if (ref) + return ref; + frame = ao_lisp_poly_frame(frame->prev); + } + if (ao_lisp_frame_global) { + ref = ao_lisp_frame_ref(ao_lisp_frame_global, atom); + if (ref) + return ref; + } + return NULL; +} + +ao_poly +ao_lisp_atom_get(ao_poly atom) +{ + ao_poly *ref = ao_lisp_atom_ref(ao_lisp_frame_current, atom); + + if (!ref && ao_lisp_frame_global) + ref = ao_lisp_frame_ref(ao_lisp_frame_global, atom); +#ifdef ao_builtin_frame + if (!ref) + ref = ao_lisp_frame_ref(ao_lisp_poly_frame(ao_builtin_frame), atom); +#endif + if (ref) + return *ref; + return ao_lisp_error(AO_LISP_UNDEFINED, "undefined atom %s", ao_lisp_poly_atom(atom)->name); +} + +ao_poly +ao_lisp_atom_set(ao_poly atom, ao_poly val) +{ + ao_poly *ref = ao_lisp_atom_ref(ao_lisp_frame_current, atom); + + if (!ref && ao_lisp_frame_global) + ref = ao_lisp_frame_ref(ao_lisp_frame_global, atom); + if (ref) + *ref = val; + else + ao_lisp_frame_add(&ao_lisp_frame_global, atom, val); + return val; +} + +void +ao_lisp_atom_print(ao_poly a) +{ + struct ao_lisp_atom *atom = ao_lisp_poly_atom(a); + printf("%s", atom->name); +} diff --git a/src/lisp/ao_lisp_builtin.c b/src/lisp/ao_lisp_builtin.c new file mode 100644 index 00000000..902f60e2 --- /dev/null +++ b/src/lisp/ao_lisp_builtin.c @@ -0,0 +1,619 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + +static int +builtin_size(void *addr) +{ + (void) addr; + return sizeof (struct ao_lisp_builtin); +} + +static void +builtin_mark(void *addr) +{ + (void) addr; +} + +static void +builtin_move(void *addr) +{ + (void) addr; +} + +const struct ao_lisp_type ao_lisp_builtin_type = { + .size = builtin_size, + .mark = builtin_mark, + .move = builtin_move +}; + +#ifdef AO_LISP_MAKE_CONST +char *ao_lisp_builtin_name(enum ao_lisp_builtin_id b) { + (void) b; + return "???"; +} +char *ao_lisp_args_name(uint8_t args) { + (void) args; + return "???"; +} +#else +static const ao_poly builtin_names[] = { + [builtin_eval] = _ao_lisp_atom_eval, + [builtin_read] = _ao_lisp_atom_read, + [builtin_lambda] = _ao_lisp_atom_lambda, + [builtin_lexpr] = _ao_lisp_atom_lexpr, + [builtin_nlambda] = _ao_lisp_atom_nlambda, + [builtin_macro] = _ao_lisp_atom_macro, + [builtin_car] = _ao_lisp_atom_car, + [builtin_cdr] = _ao_lisp_atom_cdr, + [builtin_cons] = _ao_lisp_atom_cons, + [builtin_last] = _ao_lisp_atom_last, + [builtin_length] = _ao_lisp_atom_length, + [builtin_quote] = _ao_lisp_atom_quote, + [builtin_set] = _ao_lisp_atom_set, + [builtin_setq] = _ao_lisp_atom_setq, + [builtin_cond] = _ao_lisp_atom_cond, + [builtin_progn] = _ao_lisp_atom_progn, + [builtin_while] = _ao_lisp_atom_while, + [builtin_print] = _ao_lisp_atom_print, + [builtin_patom] = _ao_lisp_atom_patom, + [builtin_plus] = _ao_lisp_atom_2b, + [builtin_minus] = _ao_lisp_atom_2d, + [builtin_times] = _ao_lisp_atom_2a, + [builtin_divide] = _ao_lisp_atom_2f, + [builtin_mod] = _ao_lisp_atom_25, + [builtin_equal] = _ao_lisp_atom_3d, + [builtin_less] = _ao_lisp_atom_3c, + [builtin_greater] = _ao_lisp_atom_3e, + [builtin_less_equal] = _ao_lisp_atom_3c3d, + [builtin_greater_equal] = _ao_lisp_atom_3e3d, + [builtin_pack] = _ao_lisp_atom_pack, + [builtin_unpack] = _ao_lisp_atom_unpack, + [builtin_flush] = _ao_lisp_atom_flush, + [builtin_delay] = _ao_lisp_atom_delay, + [builtin_led] = _ao_lisp_atom_led, + [builtin_save] = _ao_lisp_atom_save, + [builtin_restore] = _ao_lisp_atom_restore, + [builtin_call_cc] = _ao_lisp_atom_call2fcc, + [builtin_collect] = _ao_lisp_atom_collect, +#if 0 + [builtin_symbolp] = _ao_lisp_atom_symbolp, + [builtin_listp] = _ao_lisp_atom_listp, + [builtin_stringp] = _ao_lisp_atom_stringp, + [builtin_numberp] = _ao_lisp_atom_numberp, +#endif +}; + +static char * +ao_lisp_builtin_name(enum ao_lisp_builtin_id b) { + if (b < _builtin_last) + return ao_lisp_poly_atom(builtin_names[b])->name; + return "???"; +} + +static const ao_poly ao_lisp_args_atoms[] = { + [AO_LISP_FUNC_LAMBDA] = _ao_lisp_atom_lambda, + [AO_LISP_FUNC_LEXPR] = _ao_lisp_atom_lexpr, + [AO_LISP_FUNC_NLAMBDA] = _ao_lisp_atom_nlambda, + [AO_LISP_FUNC_MACRO] = _ao_lisp_atom_macro, +}; + +char * +ao_lisp_args_name(uint8_t args) +{ + args &= AO_LISP_FUNC_MASK; + if (args < sizeof ao_lisp_args_atoms / sizeof ao_lisp_args_atoms[0]) + return ao_lisp_poly_atom(ao_lisp_args_atoms[args])->name; + return "(unknown)"; +} +#endif + +void +ao_lisp_builtin_print(ao_poly b) +{ + struct ao_lisp_builtin *builtin = ao_lisp_poly_builtin(b); + printf("%s", ao_lisp_builtin_name(builtin->func)); +} + +ao_poly +ao_lisp_check_argc(ao_poly name, struct ao_lisp_cons *cons, int min, int max) +{ + int argc = 0; + + while (cons && argc <= max) { + argc++; + cons = ao_lisp_poly_cons(cons->cdr); + } + if (argc < min || argc > max) + return ao_lisp_error(AO_LISP_INVALID, "%s: invalid arg count", ao_lisp_poly_atom(name)->name); + return _ao_lisp_atom_t; +} + +ao_poly +ao_lisp_arg(struct ao_lisp_cons *cons, int argc) +{ + if (!cons) + return AO_LISP_NIL; + while (argc--) { + if (!cons) + return AO_LISP_NIL; + cons = ao_lisp_poly_cons(cons->cdr); + } + return cons->car; +} + +ao_poly +ao_lisp_check_argt(ao_poly name, struct ao_lisp_cons *cons, int argc, int type, int nil_ok) +{ + ao_poly car = ao_lisp_arg(cons, argc); + + if ((!car && !nil_ok) || ao_lisp_poly_type(car) != type) + return ao_lisp_error(AO_LISP_INVALID, "%s: invalid type for arg %d", ao_lisp_poly_atom(name)->name, argc); + return _ao_lisp_atom_t; +} + +ao_poly +ao_lisp_car(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_car, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_car, cons, 0, AO_LISP_CONS, 0)) + return AO_LISP_NIL; + return ao_lisp_poly_cons(cons->car)->car; +} + +ao_poly +ao_lisp_cdr(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_cdr, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_cdr, cons, 0, AO_LISP_CONS, 0)) + return AO_LISP_NIL; + return ao_lisp_poly_cons(cons->car)->cdr; +} + +ao_poly +ao_lisp_cons(struct ao_lisp_cons *cons) +{ + ao_poly car, cdr; + if(!ao_lisp_check_argc(_ao_lisp_atom_cons, cons, 2, 2)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_cons, cons, 1, AO_LISP_CONS, 1)) + return AO_LISP_NIL; + car = ao_lisp_arg(cons, 0); + cdr = ao_lisp_arg(cons, 1); + return ao_lisp_cons_poly(ao_lisp_cons_cons(car, ao_lisp_poly_cons(cdr))); +} + +ao_poly +ao_lisp_last(struct ao_lisp_cons *cons) +{ + ao_poly l; + if (!ao_lisp_check_argc(_ao_lisp_atom_last, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_last, cons, 0, AO_LISP_CONS, 1)) + return AO_LISP_NIL; + l = ao_lisp_arg(cons, 0); + while (l) { + struct ao_lisp_cons *list = ao_lisp_poly_cons(l); + if (!list->cdr) + return list->car; + l = list->cdr; + } + return AO_LISP_NIL; +} + +ao_poly +ao_lisp_length(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_length, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_length, cons, 0, AO_LISP_CONS, 1)) + return AO_LISP_NIL; + return ao_lisp_int_poly(ao_lisp_cons_length(ao_lisp_poly_cons(ao_lisp_arg(cons, 0)))); +} + +ao_poly +ao_lisp_quote(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_quote, cons, 1, 1)) + return AO_LISP_NIL; + return ao_lisp_arg(cons, 0); +} + +ao_poly +ao_lisp_set(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_set, cons, 2, 2)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_set, cons, 0, AO_LISP_ATOM, 0)) + return AO_LISP_NIL; + + return ao_lisp_atom_set(ao_lisp_arg(cons, 0), ao_lisp_arg(cons, 1)); +} + +ao_poly +ao_lisp_setq(struct ao_lisp_cons *cons) +{ + struct ao_lisp_cons *expand = 0; + if (!ao_lisp_check_argc(_ao_lisp_atom_setq, cons, 2, 2)) + return AO_LISP_NIL; + expand = ao_lisp_cons_cons(_ao_lisp_atom_set, + ao_lisp_cons_cons(ao_lisp_cons_poly(ao_lisp_cons_cons(_ao_lisp_atom_quote, + ao_lisp_cons_cons(cons->car, NULL))), + ao_lisp_poly_cons(cons->cdr))); + return ao_lisp_cons_poly(expand); +} + +ao_poly +ao_lisp_cond(struct ao_lisp_cons *cons) +{ + ao_lisp_set_cond(cons); + return AO_LISP_NIL; +} + +ao_poly +ao_lisp_progn(struct ao_lisp_cons *cons) +{ + ao_lisp_stack->state = eval_progn; + ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons); + return AO_LISP_NIL; +} + +ao_poly +ao_lisp_while(struct ao_lisp_cons *cons) +{ + ao_lisp_stack->state = eval_while; + ao_lisp_stack->sexprs = ao_lisp_cons_poly(cons); + return AO_LISP_NIL; +} + +ao_poly +ao_lisp_print(struct ao_lisp_cons *cons) +{ + ao_poly val = AO_LISP_NIL; + while (cons) { + val = cons->car; + ao_lisp_poly_print(val); + cons = ao_lisp_poly_cons(cons->cdr); + if (cons) + printf(" "); + } + printf("\n"); + return val; +} + +ao_poly +ao_lisp_patom(struct ao_lisp_cons *cons) +{ + ao_poly val = AO_LISP_NIL; + while (cons) { + val = cons->car; + ao_lisp_poly_patom(val); + cons = ao_lisp_poly_cons(cons->cdr); + } + return val; +} + +ao_poly +ao_lisp_math(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op) +{ + ao_poly ret = AO_LISP_NIL; + + while (cons) { + ao_poly car = cons->car; + uint8_t rt = ao_lisp_poly_type(ret); + uint8_t ct = ao_lisp_poly_type(car); + + cons = ao_lisp_poly_cons(cons->cdr); + + if (rt == AO_LISP_NIL) + ret = car; + + else if (rt == AO_LISP_INT && ct == AO_LISP_INT) { + int r = ao_lisp_poly_int(ret); + int c = ao_lisp_poly_int(car); + + switch(op) { + case builtin_plus: + r += c; + break; + case builtin_minus: + r -= c; + break; + case builtin_times: + r *= c; + break; + case builtin_divide: + if (c == 0) + return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "divide by zero"); + r /= c; + break; + case builtin_mod: + if (c == 0) + return ao_lisp_error(AO_LISP_DIVIDE_BY_ZERO, "mod by zero"); + r %= c; + break; + default: + break; + } + ret = ao_lisp_int_poly(r); + } + + else if (rt == AO_LISP_STRING && ct == AO_LISP_STRING && op == builtin_plus) + ret = ao_lisp_string_poly(ao_lisp_string_cat(ao_lisp_poly_string(ret), + ao_lisp_poly_string(car))); + else + return ao_lisp_error(AO_LISP_INVALID, "invalid args"); + } + return ret; +} + +ao_poly +ao_lisp_plus(struct ao_lisp_cons *cons) +{ + return ao_lisp_math(cons, builtin_plus); +} + +ao_poly +ao_lisp_minus(struct ao_lisp_cons *cons) +{ + return ao_lisp_math(cons, builtin_minus); +} + +ao_poly +ao_lisp_times(struct ao_lisp_cons *cons) +{ + return ao_lisp_math(cons, builtin_times); +} + +ao_poly +ao_lisp_divide(struct ao_lisp_cons *cons) +{ + return ao_lisp_math(cons, builtin_divide); +} + +ao_poly +ao_lisp_mod(struct ao_lisp_cons *cons) +{ + return ao_lisp_math(cons, builtin_mod); +} + +ao_poly +ao_lisp_compare(struct ao_lisp_cons *cons, enum ao_lisp_builtin_id op) +{ + ao_poly left; + + if (!cons) + return _ao_lisp_atom_t; + + left = cons->car; + cons = ao_lisp_poly_cons(cons->cdr); + while (cons) { + ao_poly right = cons->car; + + if (op == builtin_equal) { + if (left != right) + return AO_LISP_NIL; + } else { + uint8_t lt = ao_lisp_poly_type(left); + uint8_t rt = ao_lisp_poly_type(right); + if (lt == AO_LISP_INT && rt == AO_LISP_INT) { + int l = ao_lisp_poly_int(left); + int r = ao_lisp_poly_int(right); + + switch (op) { + case builtin_less: + if (!(l < r)) + return AO_LISP_NIL; + break; + case builtin_greater: + if (!(l > r)) + return AO_LISP_NIL; + break; + case builtin_less_equal: + if (!(l <= r)) + return AO_LISP_NIL; + break; + case builtin_greater_equal: + if (!(l >= r)) + return AO_LISP_NIL; + break; + default: + break; + } + } else if (lt == AO_LISP_STRING && rt == AO_LISP_STRING) { + int c = strcmp(ao_lisp_poly_string(left), + ao_lisp_poly_string(right)); + switch (op) { + case builtin_less: + if (!(c < 0)) + return AO_LISP_NIL; + break; + case builtin_greater: + if (!(c > 0)) + return AO_LISP_NIL; + break; + case builtin_less_equal: + if (!(c <= 0)) + return AO_LISP_NIL; + break; + case builtin_greater_equal: + if (!(c >= 0)) + return AO_LISP_NIL; + break; + default: + break; + } + } + } + left = right; + cons = ao_lisp_poly_cons(cons->cdr); + } + return _ao_lisp_atom_t; +} + +ao_poly +ao_lisp_equal(struct ao_lisp_cons *cons) +{ + return ao_lisp_compare(cons, builtin_equal); +} + +ao_poly +ao_lisp_less(struct ao_lisp_cons *cons) +{ + return ao_lisp_compare(cons, builtin_less); +} + +ao_poly +ao_lisp_greater(struct ao_lisp_cons *cons) +{ + return ao_lisp_compare(cons, builtin_greater); +} + +ao_poly +ao_lisp_less_equal(struct ao_lisp_cons *cons) +{ + return ao_lisp_compare(cons, builtin_less_equal); +} + +ao_poly +ao_lisp_greater_equal(struct ao_lisp_cons *cons) +{ + return ao_lisp_compare(cons, builtin_greater_equal); +} + +ao_poly +ao_lisp_pack(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_pack, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_pack, cons, 0, AO_LISP_CONS, 1)) + return AO_LISP_NIL; + return ao_lisp_string_pack(ao_lisp_poly_cons(ao_lisp_arg(cons, 0))); +} + +ao_poly +ao_lisp_unpack(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_unpack, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_unpack, cons, 0, AO_LISP_STRING, 0)) + return AO_LISP_NIL; + return ao_lisp_string_unpack(ao_lisp_poly_string(ao_lisp_arg(cons, 0))); +} + +ao_poly +ao_lisp_flush(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_flush, cons, 0, 0)) + return AO_LISP_NIL; + ao_lisp_os_flush(); + return _ao_lisp_atom_t; +} + +ao_poly +ao_lisp_led(struct ao_lisp_cons *cons) +{ + ao_poly led; + if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0)) + return AO_LISP_NIL; + led = ao_lisp_arg(cons, 0); + ao_lisp_os_led(ao_lisp_poly_int(led)); + return led; +} + +ao_poly +ao_lisp_delay(struct ao_lisp_cons *cons) +{ + ao_poly delay; + if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_led, cons, 0, AO_LISP_INT, 0)) + return AO_LISP_NIL; + delay = ao_lisp_arg(cons, 0); + ao_lisp_os_delay(ao_lisp_poly_int(delay)); + return delay; +} + +ao_poly +ao_lisp_do_eval(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_eval, cons, 1, 1)) + return AO_LISP_NIL; + ao_lisp_stack->state = eval_sexpr; + return cons->car; +} + +ao_poly +ao_lisp_do_read(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_read, cons, 0, 0)) + return AO_LISP_NIL; + return ao_lisp_read(); +} + +ao_poly +ao_lisp_do_collect(struct ao_lisp_cons *cons) +{ + int free; + (void) cons; + free = ao_lisp_collect(AO_LISP_COLLECT_FULL); + return ao_lisp_int_poly(free); +} + +const ao_lisp_func_t ao_lisp_builtins[] = { + [builtin_eval] = ao_lisp_do_eval, + [builtin_read] = ao_lisp_do_read, + [builtin_lambda] = ao_lisp_lambda, + [builtin_lexpr] = ao_lisp_lexpr, + [builtin_nlambda] = ao_lisp_nlambda, + [builtin_macro] = ao_lisp_macro, + [builtin_car] = ao_lisp_car, + [builtin_cdr] = ao_lisp_cdr, + [builtin_cons] = ao_lisp_cons, + [builtin_last] = ao_lisp_last, + [builtin_length] = ao_lisp_length, + [builtin_quote] = ao_lisp_quote, + [builtin_set] = ao_lisp_set, + [builtin_setq] = ao_lisp_setq, + [builtin_cond] = ao_lisp_cond, + [builtin_progn] = ao_lisp_progn, + [builtin_while] = ao_lisp_while, + [builtin_print] = ao_lisp_print, + [builtin_patom] = ao_lisp_patom, + [builtin_plus] = ao_lisp_plus, + [builtin_minus] = ao_lisp_minus, + [builtin_times] = ao_lisp_times, + [builtin_divide] = ao_lisp_divide, + [builtin_mod] = ao_lisp_mod, + [builtin_equal] = ao_lisp_equal, + [builtin_less] = ao_lisp_less, + [builtin_greater] = ao_lisp_greater, + [builtin_less_equal] = ao_lisp_less_equal, + [builtin_greater_equal] = ao_lisp_greater_equal, + [builtin_pack] = ao_lisp_pack, + [builtin_unpack] = ao_lisp_unpack, + [builtin_flush] = ao_lisp_flush, + [builtin_led] = ao_lisp_led, + [builtin_delay] = ao_lisp_delay, + [builtin_save] = ao_lisp_save, + [builtin_restore] = ao_lisp_restore, + [builtin_call_cc] = ao_lisp_call_cc, + [builtin_collect] = ao_lisp_do_collect, +}; + diff --git a/src/lisp/ao_lisp_cons.c b/src/lisp/ao_lisp_cons.c new file mode 100644 index 00000000..d2b60c9a --- /dev/null +++ b/src/lisp/ao_lisp_cons.c @@ -0,0 +1,143 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + +static void cons_mark(void *addr) +{ + struct ao_lisp_cons *cons = addr; + + for (;;) { + ao_lisp_poly_mark(cons->car, 1); + cons = ao_lisp_poly_cons(cons->cdr); + if (!cons) + break; + if (ao_lisp_mark_memory(&ao_lisp_cons_type, cons)) + break; + } +} + +static int cons_size(void *addr) +{ + (void) addr; + return sizeof (struct ao_lisp_cons); +} + +static void cons_move(void *addr) +{ + struct ao_lisp_cons *cons = addr; + + if (!cons) + return; + + for (;;) { + struct ao_lisp_cons *cdr; + int ret; + + MDBG_MOVE("cons_move start %d (%d, %d)\n", + MDBG_OFFSET(cons), MDBG_OFFSET(ao_lisp_ref(cons->car)), MDBG_OFFSET(ao_lisp_ref(cons->cdr))); + (void) ao_lisp_poly_move(&cons->car, 1); + cdr = ao_lisp_poly_cons(cons->cdr); + if (!cdr) + break; + ret = ao_lisp_move_memory(&ao_lisp_cons_type, (void **) &cdr); + if (cdr != ao_lisp_poly_cons(cons->cdr)) + cons->cdr = ao_lisp_cons_poly(cdr); + MDBG_MOVE("cons_move end %d (%d, %d)\n", + MDBG_OFFSET(cons), MDBG_OFFSET(ao_lisp_ref(cons->car)), MDBG_OFFSET(ao_lisp_ref(cons->cdr))); + if (ret) + break; + cons = cdr; + } +} + +const struct ao_lisp_type ao_lisp_cons_type = { + .mark = cons_mark, + .size = cons_size, + .move = cons_move, + .name = "cons", +}; + +struct ao_lisp_cons *ao_lisp_cons_free_list; + +struct ao_lisp_cons * +ao_lisp_cons_cons(ao_poly car, struct ao_lisp_cons *cdr) +{ + struct ao_lisp_cons *cons; + + if (ao_lisp_cons_free_list) { + cons = ao_lisp_cons_free_list; + ao_lisp_cons_free_list = ao_lisp_poly_cons(cons->cdr); + } else { + ao_lisp_poly_stash(0, car); + ao_lisp_cons_stash(0, cdr); + cons = ao_lisp_alloc(sizeof (struct ao_lisp_cons)); + car = ao_lisp_poly_fetch(0); + cdr = ao_lisp_cons_fetch(0); + if (!cons) + return NULL; + } + cons->car = car; + cons->cdr = ao_lisp_cons_poly(cdr); + return cons; +} + +void +ao_lisp_cons_free(struct ao_lisp_cons *cons) +{ + while (cons) { + ao_poly cdr = cons->cdr; + cons->cdr = ao_lisp_cons_poly(ao_lisp_cons_free_list); + ao_lisp_cons_free_list = cons; + cons = ao_lisp_poly_cons(cdr); + } +} + +void +ao_lisp_cons_print(ao_poly c) +{ + struct ao_lisp_cons *cons = ao_lisp_poly_cons(c); + int first = 1; + printf("("); + while (cons) { + if (!first) + printf(" "); + ao_lisp_poly_print(cons->car); + cons = ao_lisp_poly_cons(cons->cdr); + first = 0; + } + printf(")"); +} + +void +ao_lisp_cons_patom(ao_poly c) +{ + struct ao_lisp_cons *cons = ao_lisp_poly_cons(c); + + while (cons) { + ao_lisp_poly_patom(cons->car); + cons = ao_lisp_poly_cons(cons->cdr); + } +} + +int +ao_lisp_cons_length(struct ao_lisp_cons *cons) +{ + int len = 0; + while (cons) { + len++; + cons = ao_lisp_poly_cons(cons->cdr); + } + return len; +} diff --git a/src/lisp/ao_lisp_const.lisp b/src/lisp/ao_lisp_const.lisp new file mode 100644 index 00000000..3c8fd21b --- /dev/null +++ b/src/lisp/ao_lisp_const.lisp @@ -0,0 +1,184 @@ +; +; Copyright © 2016 Keith Packard +; +; 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. +; +; Lisp code placed in ROM + + ; return a list containing all of the arguments + +(set (quote list) (lexpr (l) l)) + + ; + ; Define a variable without returning the value + ; Useful when defining functions to avoid + ; having lots of output generated + ; + +(setq def (macro (name val rest) + (list + 'progn + (list + 'set + (list 'quote name) + val) + (list 'quote name) + ) + ) + ) + + ; + ; A slightly more convenient form + ; for defining lambdas. + ; + ; (defun () s-exprs) + ; + +(def defun (macro (name args exprs) + (list + def + name + (cons 'lambda (cons args exprs)) + ) + ) + ) + + ; basic list accessors + + +(defun cadr (l) (car (cdr l))) + +(defun caddr (l) (car (cdr (cdr l)))) + +(defun nth (list n) + (cond ((= n 0) (car list)) + ((nth (cdr list) (1- n))) + ) + ) + + ; simple math operators + +(defun 1+ (x) (+ x 1)) +(defun 1- (x) (- x 1)) + + ; define a set of local + ; variables and then evaluate + ; a list of sexprs + ; + ; (let (var-defines) sexprs) + ; + ; where var-defines are either + ; + ; (name value) + ; + ; or + ; + ; (name) + ; + ; e.g. + ; + ; (let ((x 1) (y)) (setq y (+ x 1)) y) + +(def let (macro (vars exprs) + ((lambda (make-names make-exprs make-nils) + + ; + ; make the list of names in the let + ; + + (setq make-names (lambda (vars) + (cond (vars + (cons (car (car vars)) + (make-names (cdr vars)))) + ) + ) + ) + + ; the set of expressions is + ; the list of set expressions + ; pre-pended to the + ; expressions to evaluate + + (setq make-exprs (lambda (vars exprs) + (cond (vars (cons + (list set + (list quote + (car (car vars)) + ) + (cadr (car vars)) + ) + (make-exprs (cdr vars) exprs) + ) + ) + (exprs) + ) + ) + ) + + ; the parameters to the lambda is a list + ; of nils of the right length + + (setq make-nils (lambda (vars) + (cond (vars (cons nil (make-nils (cdr vars)))) + ) + ) + ) + ; prepend the set operations + ; to the expressions + + (setq exprs (make-exprs vars exprs)) + + ; build the lambda. + + (cons (cons 'lambda (cons (make-names vars) exprs)) + (make-nils vars) + ) + ) + () + () + () + ) + ) + ) + + ; boolean operators + +(def or (lexpr (l) + (let ((ret nil)) + (while l + (cond ((setq ret (car l)) + (setq l nil)) + ((setq l (cdr l))))) + ret + ) + ) + ) + + ; execute to resolve macros + +(or nil t) + +(def and (lexpr (l) + (let ((ret t)) + (while l + (cond ((setq ret (car l)) + (setq l (cdr l))) + ((setq ret (setq l nil))) + ) + ) + ret + ) + ) + ) + + ; execute to resolve macros + +(and t nil) diff --git a/src/lisp/ao_lisp_error.c b/src/lisp/ao_lisp_error.c new file mode 100644 index 00000000..54a9be10 --- /dev/null +++ b/src/lisp/ao_lisp_error.c @@ -0,0 +1,102 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" +#include + +void +ao_lisp_error_poly(char *name, ao_poly poly, ao_poly last) +{ + int first = 1; + printf("\t\t%s(", name); + if (ao_lisp_poly_type(poly) == AO_LISP_CONS) { + if (poly) { + while (poly) { + struct ao_lisp_cons *cons = ao_lisp_poly_cons(poly); + if (!first) + printf("\t\t "); + else + first = 0; + ao_lisp_poly_print(cons->car); + printf("\n"); + if (poly == last) + break; + poly = cons->cdr; + } + printf("\t\t )\n"); + } else + printf(")\n"); + } else { + ao_lisp_poly_print(poly); + printf("\n"); + } +} + +static void tabs(int indent) +{ + while (indent--) + printf("\t"); +} + +void +ao_lisp_error_frame(int indent, char *name, struct ao_lisp_frame *frame) +{ + int f; + + tabs(indent); + printf ("%s{", name); + if (frame) { + if (frame->type & AO_LISP_FRAME_PRINT) + printf("recurse..."); + else { + frame->type |= AO_LISP_FRAME_PRINT; + for (f = 0; f < frame->num; f++) { + if (f != 0) { + tabs(indent); + printf(" "); + } + ao_lisp_poly_print(frame->vals[f].atom); + printf(" = "); + ao_lisp_poly_print(frame->vals[f].val); + printf("\n"); + } + if (frame->prev) + ao_lisp_error_frame(indent + 1, "prev: ", ao_lisp_poly_frame(frame->prev)); + frame->type &= ~AO_LISP_FRAME_PRINT; + } + tabs(indent); + printf(" }\n"); + } else + printf ("}\n"); +} + + +ao_poly +ao_lisp_error(int error, char *format, ...) +{ + va_list args; + + ao_lisp_exception |= error; + va_start(args, format); + vprintf(format, args); + va_end(args); + printf("\n"); + printf("Value: "); ao_lisp_poly_print(ao_lisp_v); printf("\n"); + printf("Stack:\n"); + ao_lisp_stack_print(ao_lisp_stack_poly(ao_lisp_stack)); + printf("Globals:\n\t"); + ao_lisp_frame_print(ao_lisp_frame_poly(ao_lisp_frame_global)); + printf("\n"); + return AO_LISP_NIL; +} diff --git a/src/lisp/ao_lisp_eval.c b/src/lisp/ao_lisp_eval.c new file mode 100644 index 00000000..3be7c9c4 --- /dev/null +++ b/src/lisp/ao_lisp_eval.c @@ -0,0 +1,531 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" +#include + +struct ao_lisp_stack *ao_lisp_stack; +ao_poly ao_lisp_v; + +ao_poly +ao_lisp_set_cond(struct ao_lisp_cons *c) +{ + ao_lisp_stack->state = eval_cond; + ao_lisp_stack->sexprs = ao_lisp_cons_poly(c); + return AO_LISP_NIL; +} + +static int +func_type(ao_poly func) +{ + if (func == AO_LISP_NIL) + return ao_lisp_error(AO_LISP_INVALID, "func is nil"); + switch (ao_lisp_poly_type(func)) { + case AO_LISP_BUILTIN: + return ao_lisp_poly_builtin(func)->args & AO_LISP_FUNC_MASK; + case AO_LISP_LAMBDA: + return ao_lisp_poly_lambda(func)->args; + case AO_LISP_STACK: + return AO_LISP_FUNC_LAMBDA; + default: + ao_lisp_error(AO_LISP_INVALID, "not a func"); + return -1; + } +} + +/* + * Flattened eval to avoid stack issues + */ + +/* + * Evaluate an s-expression + * + * For a list, evaluate all of the elements and + * then execute the resulting function call. + * + * Each element of the list is evaluated in + * a clean stack context. + * + * The current stack state is set to 'formal' so that + * when the evaluation is complete, the value + * will get appended to the values list. + * + * For other types, compute the value directly. + */ + +static int +ao_lisp_eval_sexpr(void) +{ + DBGI("sexpr: "); DBG_POLY(ao_lisp_v); DBG("\n"); + switch (ao_lisp_poly_type(ao_lisp_v)) { + case AO_LISP_CONS: + if (ao_lisp_v == AO_LISP_NIL) { + if (!ao_lisp_stack->values) { + /* + * empty list evaluates to empty list + */ + ao_lisp_v = AO_LISP_NIL; + ao_lisp_stack->state = eval_val; + } else { + /* + * done with arguments, go execute it + */ + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->values)->car; + ao_lisp_stack->state = eval_exec; + } + } else { + if (!ao_lisp_stack->values) + ao_lisp_stack->list = ao_lisp_v; + /* + * Evaluate another argument and then switch + * to 'formal' to add the value to the values + * list + */ + ao_lisp_stack->sexprs = ao_lisp_v; + ao_lisp_stack->state = eval_formal; + if (!ao_lisp_stack_push()) + return 0; + /* + * push will reset the state to 'sexpr', which + * will evaluate the expression + */ + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car; + } + break; + case AO_LISP_ATOM: + DBGI("..frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + ao_lisp_v = ao_lisp_atom_get(ao_lisp_v); + /* fall through */ + case AO_LISP_INT: + case AO_LISP_STRING: + case AO_LISP_BUILTIN: + case AO_LISP_LAMBDA: + ao_lisp_stack->state = eval_val; + break; + } + DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG("\n"); + return 1; +} + +/* + * A value has been computed. + * + * If the value was computed from a macro, + * then we want to reset the current context + * to evaluate the macro result again. + * + * If not a macro, then pop the stack. + * If the stack is empty, we're done. + * Otherwise, the stack will contain + * the next state. + */ + +static int +ao_lisp_eval_val(void) +{ + DBGI("val: "); DBG_POLY(ao_lisp_v); DBG("\n"); + /* + * Value computed, pop the stack + * to figure out what to do with the value + */ + ao_lisp_stack_pop(); + DBGI("..state %d\n", ao_lisp_stack ? ao_lisp_stack->state : -1); + return 1; +} + +/* + * A formal has been computed. + * + * If this is the first formal, then check to see if we've got a + * lamda/lexpr or macro/nlambda. + * + * For lambda/lexpr, go compute another formal. This will terminate + * when the sexpr state sees nil. + * + * For macro/nlambda, we're done, so move the sexprs into the values + * and go execute it. + * + * Macros have an additional step of saving a stack frame holding the + * macro value execution context, which then gets the result of the + * macro to run + */ + +static int +ao_lisp_eval_formal(void) +{ + ao_poly formal; + struct ao_lisp_stack *prev; + + DBGI("formal: "); DBG_POLY(ao_lisp_v); DBG("\n"); + + /* Check what kind of function we've got */ + if (!ao_lisp_stack->values) { + switch (func_type(ao_lisp_v)) { + case AO_LISP_FUNC_LAMBDA: + case AO_LISP_FUNC_LEXPR: + DBGI(".. lambda or lexpr\n"); + break; + case AO_LISP_FUNC_MACRO: + /* Evaluate the result once more */ + ao_lisp_stack->state = eval_macro; + if (!ao_lisp_stack_push()) + return 0; + + /* After the function returns, take that + * value and re-evaluate it + */ + prev = ao_lisp_poly_stack(ao_lisp_stack->prev); + ao_lisp_stack->sexprs = prev->sexprs; + + DBGI(".. start macro\n"); + DBGI(".. sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + DBGI(".. values "); DBG_POLY(ao_lisp_stack->values); DBG("\n"); + DBG_FRAMES(); + + /* fall through ... */ + case AO_LISP_FUNC_NLAMBDA: + DBGI(".. nlambda or macro\n"); + + /* use the raw sexprs as values */ + ao_lisp_stack->values = ao_lisp_stack->sexprs; + ao_lisp_stack->values_tail = AO_LISP_NIL; + ao_lisp_stack->state = eval_exec; + + /* ready to execute now */ + return 1; + case -1: + return 0; + } + } + + /* Append formal to list of values */ + formal = ao_lisp_cons_poly(ao_lisp_cons_cons(ao_lisp_v, NULL)); + if (!formal) + return 0; + + if (ao_lisp_stack->values_tail) + ao_lisp_poly_cons(ao_lisp_stack->values_tail)->cdr = formal; + else + ao_lisp_stack->values = formal; + ao_lisp_stack->values_tail = formal; + + DBGI(".. values "); DBG_POLY(ao_lisp_stack->values); DBG("\n"); + + /* + * Step to the next argument, if this is last, then + * 'sexpr' will end up switching to 'exec' + */ + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr; + + ao_lisp_stack->state = eval_sexpr; + + DBGI(".. "); DBG_POLY(ao_lisp_v); DBG("\n"); + return 1; +} + +/* + * Start executing a function call + * + * Most builtins are easy, just call the function. + * 'cond' is magic; it sticks the list of clauses + * in 'sexprs' and switches to 'cond' state. That + * bit of magic is done in ao_lisp_set_cond. + * + * Lambdas build a new frame to hold the locals and + * then re-use the current stack context to evaluate + * the s-expression from the lambda. + */ + +static int +ao_lisp_eval_exec(void) +{ + ao_poly v; + struct ao_lisp_builtin *builtin; + + DBGI("exec: "); DBG_POLY(ao_lisp_v); DBG(" values "); DBG_POLY(ao_lisp_stack->values); DBG ("\n"); + ao_lisp_stack->sexprs = AO_LISP_NIL; + switch (ao_lisp_poly_type(ao_lisp_v)) { + case AO_LISP_BUILTIN: + ao_lisp_stack->state = eval_val; + builtin = ao_lisp_poly_builtin(ao_lisp_v); + v = ao_lisp_func(builtin) ( + ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->values)->cdr)); + DBG_DO(if (!ao_lisp_exception && ao_lisp_poly_builtin(ao_lisp_v)->func == builtin_set) { + struct ao_lisp_cons *cons = ao_lisp_poly_cons(ao_lisp_stack->values); + ao_poly atom = ao_lisp_arg(cons, 1); + ao_poly val = ao_lisp_arg(cons, 2); + DBGI("set "); DBG_POLY(atom); DBG(" = "); DBG_POLY(val); DBG("\n"); + }); + builtin = ao_lisp_poly_builtin(ao_lisp_v); + if (builtin->args & AO_LISP_FUNC_FREE_ARGS && !ao_lisp_stack_marked(ao_lisp_stack)) + ao_lisp_cons_free(ao_lisp_poly_cons(ao_lisp_stack->values)); + + ao_lisp_v = v; + ao_lisp_stack->values = AO_LISP_NIL; + ao_lisp_stack->values_tail = AO_LISP_NIL; + DBGI(".. result "); DBG_POLY(ao_lisp_v); DBG ("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + break; + case AO_LISP_LAMBDA: + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + ao_lisp_stack->state = eval_progn; + v = ao_lisp_lambda_eval(); + ao_lisp_stack->sexprs = v; + ao_lisp_stack->values = AO_LISP_NIL; + ao_lisp_stack->values_tail = AO_LISP_NIL; + DBGI(".. sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + break; + case AO_LISP_STACK: + DBGI(".. stack "); DBG_POLY(ao_lisp_v); DBG("\n"); + ao_lisp_v = ao_lisp_stack_eval(); + DBGI(".. value "); DBG_POLY(ao_lisp_v); DBG("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + break; + } + return 1; +} + +/* + * Start evaluating the next cond clause + * + * If the list of clauses is empty, then + * the result of the cond is nil. + * + * Otherwise, set the current stack state to 'cond_test' and create a + * new stack context to evaluate the test s-expression. Once that's + * complete, we'll land in 'cond_test' to finish the clause. + */ +static int +ao_lisp_eval_cond(void) +{ + DBGI("cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n"); + if (!ao_lisp_stack->sexprs) { + ao_lisp_v = AO_LISP_NIL; + ao_lisp_stack->state = eval_val; + } else { + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car; + if (!ao_lisp_v || ao_lisp_poly_type(ao_lisp_v) != AO_LISP_CONS) { + ao_lisp_error(AO_LISP_INVALID, "invalid cond clause"); + return 0; + } + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_v)->car; + ao_lisp_stack->state = eval_cond_test; + if (!ao_lisp_stack_push()) + return 0; + } + return 1; +} + +/* + * Finish a cond clause. + * + * Check the value from the test expression, if + * non-nil, then set up to evaluate the value expression. + * + * Otherwise, step to the next clause and go back to the 'cond' + * state + */ +static int +ao_lisp_eval_cond_test(void) +{ + DBGI("cond_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n"); + if (ao_lisp_v) { + struct ao_lisp_cons *car = ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car); + ao_poly c = car->cdr; + + if (c) { + ao_lisp_stack->state = eval_progn; + ao_lisp_stack->sexprs = c; + } else + ao_lisp_stack->state = eval_val; + } else { + ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr; + DBGI("next cond: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + ao_lisp_stack->state = eval_cond; + } + return 1; +} + +/* + * Evaluate a list of sexprs, returning the value from the last one. + * + * ao_lisp_progn records the list in stack->sexprs, so we just need to + * walk that list. Set ao_lisp_v to the car of the list and jump to + * eval_sexpr. When that's done, it will land in eval_val. For all but + * the last, leave a stack frame with eval_progn set so that we come + * back here. For the last, don't add a stack frame so that we can + * just continue on. + */ +static int +ao_lisp_eval_progn(void) +{ + DBGI("progn: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n"); + + if (!ao_lisp_stack->sexprs) { + ao_lisp_v = AO_LISP_NIL; + ao_lisp_stack->state = eval_val; + } else { + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car; + ao_lisp_stack->sexprs = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr; + + /* If there are more sexprs to do, then come back here, otherwise + * return the value of the last one by just landing in eval_sexpr + */ + if (ao_lisp_stack->sexprs) { + ao_lisp_stack->state = eval_progn; + if (!ao_lisp_stack_push()) + return 0; + } + ao_lisp_stack->state = eval_sexpr; + } + return 1; +} + +/* + * Conditionally execute a list of sexprs while the first is true + */ +static int +ao_lisp_eval_while(void) +{ + DBGI("while: "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n"); + + ao_lisp_stack->values = ao_lisp_v; + if (!ao_lisp_stack->sexprs) { + ao_lisp_v = AO_LISP_NIL; + ao_lisp_stack->state = eval_val; + } else { + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->car; + ao_lisp_stack->state = eval_while_test; + if (!ao_lisp_stack_push()) + return 0; + } + return 1; +} + +/* + * Check the while condition, terminate the loop if nil. Otherwise keep going + */ +static int +ao_lisp_eval_while_test(void) +{ + DBGI("while_test: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + DBGI(".. frame "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n"); + DBGI(".. saved frame "); DBG_POLY(ao_lisp_stack->frame); DBG("\n"); + + if (ao_lisp_v) { + ao_lisp_stack->values = ao_lisp_v; + ao_lisp_v = ao_lisp_poly_cons(ao_lisp_stack->sexprs)->cdr; + ao_lisp_stack->state = eval_while; + if (!ao_lisp_stack_push()) + return 0; + ao_lisp_stack->state = eval_progn; + ao_lisp_stack->sexprs = ao_lisp_v; + } + else + { + ao_lisp_stack->state = eval_val; + ao_lisp_v = ao_lisp_stack->values; + } + return 1; +} + +/* + * Replace the original sexpr with the macro expansion, then + * execute that + */ +static int +ao_lisp_eval_macro(void) +{ + DBGI("macro: "); DBG_POLY(ao_lisp_v); DBG(" sexprs "); DBG_POLY(ao_lisp_stack->sexprs); DBG("\n"); + + if (ao_lisp_v == AO_LISP_NIL) + ao_lisp_abort(); + if (ao_lisp_poly_type(ao_lisp_v) == AO_LISP_CONS) { + *ao_lisp_poly_cons(ao_lisp_stack->sexprs) = *ao_lisp_poly_cons(ao_lisp_v); + ao_lisp_v = ao_lisp_stack->sexprs; + DBGI("sexprs rewritten to: "); DBG_POLY(ao_lisp_v); DBG("\n"); + } + ao_lisp_stack->sexprs = AO_LISP_NIL; + ao_lisp_stack->state = eval_sexpr; + return 1; +} + +static int (*const evals[])(void) = { + [eval_sexpr] = ao_lisp_eval_sexpr, + [eval_val] = ao_lisp_eval_val, + [eval_formal] = ao_lisp_eval_formal, + [eval_exec] = ao_lisp_eval_exec, + [eval_cond] = ao_lisp_eval_cond, + [eval_cond_test] = ao_lisp_eval_cond_test, + [eval_progn] = ao_lisp_eval_progn, + [eval_while] = ao_lisp_eval_while, + [eval_while_test] = ao_lisp_eval_while_test, + [eval_macro] = ao_lisp_eval_macro, +}; + +const char *ao_lisp_state_names[] = { + "sexpr", + "val", + "formal", + "exec", + "cond", + "cond_test", + "progn", +}; + +/* + * Called at restore time to reset all execution state + */ + +void +ao_lisp_eval_clear_globals(void) +{ + ao_lisp_stack = NULL; + ao_lisp_frame_current = NULL; + ao_lisp_v = AO_LISP_NIL; +} + +int +ao_lisp_eval_restart(void) +{ + return ao_lisp_stack_push(); +} + +ao_poly +ao_lisp_eval(ao_poly _v) +{ + ao_lisp_v = _v; + + if (!ao_lisp_stack_push()) + return AO_LISP_NIL; + + while (ao_lisp_stack) { + if (!(*evals[ao_lisp_stack->state])() || ao_lisp_exception) { + ao_lisp_stack_clear(); + return AO_LISP_NIL; + } + } + DBG_DO(if (ao_lisp_frame_current) {DBGI("frame left as "); DBG_POLY(ao_lisp_frame_poly(ao_lisp_frame_current)); DBG("\n");}); + ao_lisp_frame_current = NULL; + return ao_lisp_v; +} diff --git a/src/lisp/ao_lisp_frame.c b/src/lisp/ao_lisp_frame.c new file mode 100644 index 00000000..05f6d253 --- /dev/null +++ b/src/lisp/ao_lisp_frame.c @@ -0,0 +1,293 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + +static inline int +frame_num_size(int num) +{ + return sizeof (struct ao_lisp_frame) + num * sizeof (struct ao_lisp_val); +} + +static int +frame_size(void *addr) +{ + struct ao_lisp_frame *frame = addr; + return frame_num_size(frame->num); +} + +static void +frame_mark(void *addr) +{ + struct ao_lisp_frame *frame = addr; + int f; + + for (;;) { + MDBG_MOVE("frame mark %d\n", MDBG_OFFSET(frame)); + if (!AO_LISP_IS_POOL(frame)) + break; + for (f = 0; f < frame->num; f++) { + struct ao_lisp_val *v = &frame->vals[f]; + + ao_lisp_poly_mark(v->val, 0); + MDBG_MOVE("frame mark atom %s %d val %d at %d\n", + ao_lisp_poly_atom(v->atom)->name, + MDBG_OFFSET(ao_lisp_ref(v->atom)), + MDBG_OFFSET(ao_lisp_ref(v->val)), f); + } + frame = ao_lisp_poly_frame(frame->prev); + MDBG_MOVE("frame next %d\n", MDBG_OFFSET(frame)); + if (!frame) + break; + if (ao_lisp_mark_memory(&ao_lisp_frame_type, frame)) + break; + } +} + +static void +frame_move(void *addr) +{ + struct ao_lisp_frame *frame = addr; + int f; + + for (;;) { + struct ao_lisp_frame *prev; + int ret; + + MDBG_MOVE("frame move %d\n", MDBG_OFFSET(frame)); + if (!AO_LISP_IS_POOL(frame)) + break; + for (f = 0; f < frame->num; f++) { + struct ao_lisp_val *v = &frame->vals[f]; + + ao_lisp_poly_move(&v->atom, 0); + ao_lisp_poly_move(&v->val, 0); + MDBG_MOVE("frame move atom %s %d val %d at %d\n", + ao_lisp_poly_atom(v->atom)->name, + MDBG_OFFSET(ao_lisp_ref(v->atom)), + MDBG_OFFSET(ao_lisp_ref(v->val)), f); + } + prev = ao_lisp_poly_frame(frame->prev); + if (!prev) + break; + ret = ao_lisp_move_memory(&ao_lisp_frame_type, (void **) &prev); + if (prev != ao_lisp_poly_frame(frame->prev)) { + MDBG_MOVE("frame prev moved from %d to %d\n", + MDBG_OFFSET(ao_lisp_poly_frame(frame->prev)), + MDBG_OFFSET(prev)); + frame->prev = ao_lisp_frame_poly(prev); + } + if (ret) + break; + frame = prev; + } +} + +const struct ao_lisp_type ao_lisp_frame_type = { + .mark = frame_mark, + .size = frame_size, + .move = frame_move, + .name = "frame", +}; + +void +ao_lisp_frame_print(ao_poly p) +{ + struct ao_lisp_frame *frame = ao_lisp_poly_frame(p); + int f; + + printf ("{"); + if (frame) { + if (frame->type & AO_LISP_FRAME_PRINT) + printf("recurse..."); + else { + frame->type |= AO_LISP_FRAME_PRINT; + for (f = 0; f < frame->num; f++) { + if (f != 0) + printf(", "); + ao_lisp_poly_print(frame->vals[f].atom); + printf(" = "); + ao_lisp_poly_print(frame->vals[f].val); + } + if (frame->prev) + ao_lisp_poly_print(frame->prev); + frame->type &= ~AO_LISP_FRAME_PRINT; + } + } + printf("}"); +} + +static int +ao_lisp_frame_find(struct ao_lisp_frame *frame, int top, ao_poly atom) +{ + int l = 0; + int r = top - 1; + while (l <= r) { + int m = (l + r) >> 1; + if (frame->vals[m].atom < atom) + l = m + 1; + else + r = m - 1; + } + return l; +} + +ao_poly * +ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom) +{ + int l = ao_lisp_frame_find(frame, frame->num, atom); + + if (l >= frame->num) + return NULL; + + if (frame->vals[l].atom != atom) + return NULL; + return &frame->vals[l].val; +} + +int +ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val) +{ + while (frame) { + if (!AO_LISP_IS_CONST(frame)) { + ao_poly *ref = ao_lisp_frame_ref(frame, atom); + if (ref) { + *ref = val; + return 1; + } + } + frame = ao_lisp_poly_frame(frame->prev); + } + return 0; +} + +ao_poly +ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom) +{ + while (frame) { + ao_poly *ref = ao_lisp_frame_ref(frame, atom); + if (ref) + return *ref; + frame = ao_lisp_poly_frame(frame->prev); + } + return AO_LISP_NIL; +} + +struct ao_lisp_frame *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE]; + +struct ao_lisp_frame * +ao_lisp_frame_new(int num) +{ + struct ao_lisp_frame *frame; + + if (num < AO_LISP_FRAME_FREE && (frame = ao_lisp_frame_free_list[num])) + ao_lisp_frame_free_list[num] = ao_lisp_poly_frame(frame->prev); + else { + frame = ao_lisp_alloc(frame_num_size(num)); + if (!frame) + return NULL; + } + frame->type = AO_LISP_FRAME; + frame->num = num; + frame->prev = AO_LISP_NIL; + memset(frame->vals, '\0', num * sizeof (struct ao_lisp_val)); + return frame; +} + +ao_poly +ao_lisp_frame_mark(struct ao_lisp_frame *frame) +{ + if (!frame) + return AO_LISP_NIL; + frame->type |= AO_LISP_FRAME_MARK; + return ao_lisp_frame_poly(frame); +} + +void +ao_lisp_frame_free(struct ao_lisp_frame *frame) +{ + if (!ao_lisp_frame_marked(frame)) { + int num = frame->num; + if (num < AO_LISP_FRAME_FREE) { + frame->prev = ao_lisp_frame_poly(ao_lisp_frame_free_list[num]); + ao_lisp_frame_free_list[num] = frame; + } + } +} + +static struct ao_lisp_frame * +ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num) +{ + struct ao_lisp_frame *frame = *frame_ref; + struct ao_lisp_frame *new; + int copy; + + if (new_num == frame->num) + return frame; + new = ao_lisp_frame_new(new_num); + if (!new) + return NULL; + /* + * Re-fetch the frame as it may have moved + * during the allocation + */ + frame = *frame_ref; + copy = new_num; + if (copy > frame->num) + copy = frame->num; + memcpy(new->vals, frame->vals, copy * sizeof (struct ao_lisp_val)); + new->prev = frame->prev; + ao_lisp_frame_free(frame); + return new; +} + +void +ao_lisp_frame_bind(struct ao_lisp_frame *frame, int num, ao_poly atom, ao_poly val) +{ + int l = ao_lisp_frame_find(frame, num, atom); + + memmove(&frame->vals[l+1], + &frame->vals[l], + (num - l) * sizeof (struct ao_lisp_val)); + frame->vals[l].atom = atom; + frame->vals[l].val = val; +} + +int +ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val) +{ + struct ao_lisp_frame *frame = *frame_ref; + ao_poly *ref = frame ? ao_lisp_frame_ref(frame, atom) : NULL; + + if (!ref) { + int f; + ao_lisp_poly_stash(0, atom); + ao_lisp_poly_stash(1, val); + if (frame) { + f = frame->num; + frame = ao_lisp_frame_realloc(frame_ref, f + 1); + } else { + f = 0; + frame = ao_lisp_frame_new(1); + } + if (!frame) + return 0; + *frame_ref = frame; + atom = ao_lisp_poly_fetch(0); + val = ao_lisp_poly_fetch(1); + ao_lisp_frame_bind(frame, frame->num - 1, atom, val); + } else + *ref = val; + return 1; +} diff --git a/src/lisp/ao_lisp_int.c b/src/lisp/ao_lisp_int.c new file mode 100644 index 00000000..77f65e95 --- /dev/null +++ b/src/lisp/ao_lisp_int.c @@ -0,0 +1,22 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + +void +ao_lisp_int_print(ao_poly p) +{ + int i = ao_lisp_poly_int(p); + printf("%d", i); +} diff --git a/src/lisp/ao_lisp_lambda.c b/src/lisp/ao_lisp_lambda.c new file mode 100644 index 00000000..526863c5 --- /dev/null +++ b/src/lisp/ao_lisp_lambda.c @@ -0,0 +1,196 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_lisp.h" + +int +lambda_size(void *addr) +{ + (void) addr; + return sizeof (struct ao_lisp_lambda); +} + +void +lambda_mark(void *addr) +{ + struct ao_lisp_lambda *lambda = addr; + + ao_lisp_poly_mark(lambda->code, 0); + ao_lisp_poly_mark(lambda->frame, 0); +} + +void +lambda_move(void *addr) +{ + struct ao_lisp_lambda *lambda = addr; + + ao_lisp_poly_move(&lambda->code, 0); + ao_lisp_poly_move(&lambda->frame, 0); +} + +const struct ao_lisp_type ao_lisp_lambda_type = { + .size = lambda_size, + .mark = lambda_mark, + .move = lambda_move, + .name = "lambda", +}; + +void +ao_lisp_lambda_print(ao_poly poly) +{ + struct ao_lisp_lambda *lambda = ao_lisp_poly_lambda(poly); + struct ao_lisp_cons *cons = ao_lisp_poly_cons(lambda->code); + + printf("("); + printf("%s", ao_lisp_args_name(lambda->args)); + while (cons) { + printf(" "); + ao_lisp_poly_print(cons->car); + cons = ao_lisp_poly_cons(cons->cdr); + } + printf(")"); +} + +ao_poly +ao_lisp_lambda_alloc(struct ao_lisp_cons *code, int args) +{ + ao_lisp_cons_stash(0, code); + struct ao_lisp_lambda *lambda = ao_lisp_alloc(sizeof (struct ao_lisp_lambda)); + code = ao_lisp_cons_fetch(0); + struct ao_lisp_cons *arg; + int f; + + if (!lambda) + return AO_LISP_NIL; + + if (!ao_lisp_check_argt(_ao_lisp_atom_lambda, code, 0, AO_LISP_CONS, 1)) + return AO_LISP_NIL; + f = 0; + arg = ao_lisp_poly_cons(ao_lisp_arg(code, 0)); + while (arg) { + if (ao_lisp_poly_type(arg->car) != AO_LISP_ATOM) + return ao_lisp_error(AO_LISP_INVALID, "formal %d is not an atom", f); + arg = ao_lisp_poly_cons(arg->cdr); + f++; + } + + lambda->type = AO_LISP_LAMBDA; + lambda->args = args; + lambda->code = ao_lisp_cons_poly(code); + lambda->frame = ao_lisp_frame_mark(ao_lisp_frame_current); + DBGI("build frame: "); DBG_POLY(lambda->frame); DBG("\n"); + DBG_STACK(); + return ao_lisp_lambda_poly(lambda); +} + +ao_poly +ao_lisp_lambda(struct ao_lisp_cons *cons) +{ + return ao_lisp_lambda_alloc(cons, AO_LISP_FUNC_LAMBDA); +} + +ao_poly +ao_lisp_lexpr(struct ao_lisp_cons *cons) +{ + return ao_lisp_lambda_alloc(cons, AO_LISP_FUNC_LEXPR); +} + +ao_poly +ao_lisp_nlambda(struct ao_lisp_cons *cons) +{ + return ao_lisp_lambda_alloc(cons, AO_LISP_FUNC_NLAMBDA); +} + +ao_poly +ao_lisp_macro(struct ao_lisp_cons *cons) +{ + return ao_lisp_lambda_alloc(cons, AO_LISP_FUNC_MACRO); +} + +ao_poly +ao_lisp_lambda_eval(void) +{ + struct ao_lisp_lambda *lambda = ao_lisp_poly_lambda(ao_lisp_v); + struct ao_lisp_cons *cons = ao_lisp_poly_cons(ao_lisp_stack->values); + struct ao_lisp_cons *code = ao_lisp_poly_cons(lambda->code); + struct ao_lisp_cons *args = ao_lisp_poly_cons(ao_lisp_arg(code, 0)); + struct ao_lisp_frame *next_frame; + int args_wanted; + int args_provided; + int f; + struct ao_lisp_cons *vals; + + DBGI("lambda "); DBG_POLY(ao_lisp_lambda_poly(lambda)); DBG("\n"); + + args_wanted = ao_lisp_cons_length(args); + + /* Create a frame to hold the variables + */ + args_provided = ao_lisp_cons_length(cons) - 1; + if (lambda->args == AO_LISP_FUNC_LAMBDA) { + if (args_wanted != args_provided) + return ao_lisp_error(AO_LISP_INVALID, "need %d args, got %d", args_wanted, args_provided); + } else { + if (args_provided < args_wanted - 1) + return ao_lisp_error(AO_LISP_INVALID, "need at least %d args, got %d", args_wanted, args_provided); + } + + next_frame = ao_lisp_frame_new(args_wanted); + + /* Re-fetch all of the values in case something moved */ + lambda = ao_lisp_poly_lambda(ao_lisp_v); + cons = ao_lisp_poly_cons(ao_lisp_stack->values); + code = ao_lisp_poly_cons(lambda->code); + args = ao_lisp_poly_cons(ao_lisp_arg(code, 0)); + vals = ao_lisp_poly_cons(cons->cdr); + + next_frame->prev = lambda->frame; + ao_lisp_frame_current = next_frame; + ao_lisp_stack->frame = ao_lisp_frame_poly(ao_lisp_frame_current); + + switch (lambda->args) { + case AO_LISP_FUNC_LAMBDA: + for (f = 0; f < args_wanted; f++) { + DBGI("bind "); DBG_POLY(args->car); DBG(" = "); DBG_POLY(vals->car); DBG("\n"); + ao_lisp_frame_bind(next_frame, f, args->car, vals->car); + args = ao_lisp_poly_cons(args->cdr); + vals = ao_lisp_poly_cons(vals->cdr); + } + if (!ao_lisp_stack_marked(ao_lisp_stack)) + ao_lisp_cons_free(cons); + cons = NULL; + break; + case AO_LISP_FUNC_LEXPR: + case AO_LISP_FUNC_NLAMBDA: + case AO_LISP_FUNC_MACRO: + for (f = 0; f < args_wanted - 1; f++) { + DBGI("bind "); DBG_POLY(args->car); DBG(" = "); DBG_POLY(vals->car); DBG("\n"); + ao_lisp_frame_bind(next_frame, f, args->car, vals->car); + args = ao_lisp_poly_cons(args->cdr); + vals = ao_lisp_poly_cons(vals->cdr); + } + DBGI("bind "); DBG_POLY(args->car); DBG(" = "); DBG_POLY(ao_lisp_cons_poly(vals)); DBG("\n"); + ao_lisp_frame_bind(next_frame, f, args->car, ao_lisp_cons_poly(vals)); + break; + default: + break; + } + DBGI("eval frame: "); DBG_POLY(ao_lisp_frame_poly(next_frame)); DBG("\n"); + DBG_STACK(); + DBGI("eval code: "); DBG_POLY(code->cdr); DBG("\n"); + return code->cdr; +} diff --git a/src/lisp/ao_lisp_lex.c b/src/lisp/ao_lisp_lex.c new file mode 100644 index 00000000..fe7c47f4 --- /dev/null +++ b/src/lisp/ao_lisp_lex.c @@ -0,0 +1,16 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + diff --git a/src/lisp/ao_lisp_make_const.c b/src/lisp/ao_lisp_make_const.c new file mode 100644 index 00000000..49f989e6 --- /dev/null +++ b/src/lisp/ao_lisp_make_const.c @@ -0,0 +1,423 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" +#include +#include +#include +#include + +static struct ao_lisp_builtin * +ao_lisp_make_builtin(enum ao_lisp_builtin_id func, int args) { + struct ao_lisp_builtin *b = ao_lisp_alloc(sizeof (struct ao_lisp_builtin)); + + b->type = AO_LISP_BUILTIN; + b->func = func; + b->args = args; + return b; +} + +struct builtin_func { + char *name; + int args; + int func; +}; + +struct builtin_func funcs[] = { + { .name = "eval", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_eval }, + { .name = "read", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_read }, + { .name = "lambda", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_lambda }, + { .name = "lexpr", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_lexpr }, + { .name = "nlambda", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_nlambda }, + { .name = "macro", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_macro }, + { .name = "car", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_car }, + { .name = "cdr", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_cdr }, + { .name = "cons", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_cons }, + { .name = "last", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_last }, + { .name = "length", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_length }, + { .name = "quote", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_quote }, + { .name = "set", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_set }, + { .name = "setq", .args = AO_LISP_FUNC_MACRO, .func = builtin_setq }, + { .name = "cond", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_cond }, + { .name = "progn", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_progn }, + { .name = "while", .args = AO_LISP_FUNC_NLAMBDA, .func = builtin_while }, + { .name = "print", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_print }, + { .name = "patom", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_patom }, + { .name = "+", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_plus }, + { .name = "-", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_minus }, + { .name = "*", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_times }, + { .name = "/", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_divide }, + { .name = "%", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_mod }, + { .name = "=", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_equal }, + { .name = "<", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_less }, + { .name = ">", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_greater }, + { .name = "<=", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_less_equal }, + { .name = ">=", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_greater_equal }, + { .name = "pack", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_pack }, + { .name = "unpack", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_unpack }, + { .name = "flush", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_flush }, + { .name = "delay", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_delay }, + { .name = "led", .args = AO_LISP_FUNC_F_LEXPR, .func = builtin_led }, + { .name = "save", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_save }, + { .name = "restore", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_restore }, + { .name = "call/cc", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_call_cc }, + { .name = "collect", .args = AO_LISP_FUNC_F_LAMBDA, .func = builtin_collect }, +}; + +#define N_FUNC (sizeof funcs / sizeof funcs[0]) + +struct ao_lisp_frame *globals; + +static int +is_atom(int offset) +{ + struct ao_lisp_atom *a; + + for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) + if (((uint8_t *) a->name - ao_lisp_const) == offset) + return strlen(a->name); + return 0; +} + +#define AO_FEC_CRC_INIT 0xffff + +static inline uint16_t +ao_fec_crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} + +uint16_t +ao_fec_crc(const uint8_t *bytes, uint8_t len) +{ + uint16_t crc = AO_FEC_CRC_INIT; + + while (len--) + crc = ao_fec_crc_byte(*bytes++, crc); + return crc; +} + +struct ao_lisp_macro_stack { + struct ao_lisp_macro_stack *next; + ao_poly p; +}; + +struct ao_lisp_macro_stack *macro_stack; + +int +ao_lisp_macro_push(ao_poly p) +{ + struct ao_lisp_macro_stack *m = macro_stack; + + while (m) { + if (m->p == p) + return 1; + m = m->next; + } + m = malloc (sizeof (struct ao_lisp_macro_stack)); + m->p = p; + m->next = macro_stack; + macro_stack = m; + return 0; +} + +void +ao_lisp_macro_pop(void) +{ + struct ao_lisp_macro_stack *m = macro_stack; + + macro_stack = m->next; + free(m); +} + +#define DBG_MACRO 0 +#if DBG_MACRO +int macro_scan_depth; + +void indent(void) +{ + int i; + for (i = 0; i < macro_scan_depth; i++) + printf(" "); +} +#define MACRO_DEBUG(a) a +#else +#define MACRO_DEBUG(a) +#endif + +ao_poly +ao_has_macro(ao_poly p); + +ao_poly +ao_macro_test_get(ao_poly atom) +{ + ao_poly *ref = ao_lisp_atom_ref(ao_lisp_frame_global, atom); + if (ref) + return *ref; + return AO_LISP_NIL; +} + +ao_poly +ao_is_macro(ao_poly p) +{ + struct ao_lisp_builtin *builtin; + struct ao_lisp_lambda *lambda; + ao_poly ret; + + MACRO_DEBUG(indent(); printf ("is macro "); ao_lisp_poly_print(p); printf("\n"); ++macro_scan_depth); + switch (ao_lisp_poly_type(p)) { + case AO_LISP_ATOM: + if (ao_lisp_macro_push(p)) + ret = AO_LISP_NIL; + else { + if (ao_is_macro(ao_macro_test_get(p))) + ret = p; + else + ret = AO_LISP_NIL; + ao_lisp_macro_pop(); + } + break; + case AO_LISP_CONS: + ret = ao_has_macro(p); + break; + case AO_LISP_BUILTIN: + builtin = ao_lisp_poly_builtin(p); + if ((builtin->args & AO_LISP_FUNC_MASK) == AO_LISP_FUNC_MACRO) + ret = p; + else + ret = 0; + break; + + case AO_LISP_LAMBDA: + lambda = ao_lisp_poly_lambda(p); + if (lambda->args == AO_LISP_FUNC_MACRO) + ret = p; + else + ret = ao_has_macro(lambda->code); + break; + default: + ret = AO_LISP_NIL; + break; + } + MACRO_DEBUG(--macro_scan_depth; indent(); printf ("... "); ao_lisp_poly_print(ret); printf("\n")); + return ret; +} + +ao_poly +ao_has_macro(ao_poly p) +{ + struct ao_lisp_cons *cons; + struct ao_lisp_lambda *lambda; + ao_poly m; + + if (p == AO_LISP_NIL) + return AO_LISP_NIL; + + MACRO_DEBUG(indent(); printf("has macro "); ao_lisp_poly_print(p); printf("\n"); ++macro_scan_depth); + switch (ao_lisp_poly_type(p)) { + case AO_LISP_LAMBDA: + lambda = ao_lisp_poly_lambda(p); + p = ao_has_macro(lambda->code); + break; + case AO_LISP_CONS: + cons = ao_lisp_poly_cons(p); + if ((p = ao_is_macro(cons->car))) + break; + + cons = ao_lisp_poly_cons(cons->cdr); + p = AO_LISP_NIL; + while (cons) { + m = ao_has_macro(cons->car); + if (m) { + p = m; + break; + } + cons = ao_lisp_poly_cons(cons->cdr); + } + break; + + default: + p = AO_LISP_NIL; + break; + } + MACRO_DEBUG(--macro_scan_depth; indent(); printf("... "); ao_lisp_poly_print(p); printf("\n")); + return p; +} + +int +ao_lisp_read_eval_abort(void) +{ + ao_poly in, out = AO_LISP_NIL; + for(;;) { + in = ao_lisp_read(); + if (in == _ao_lisp_atom_eof) + break; + out = ao_lisp_eval(in); + if (ao_lisp_exception) + return 0; + ao_lisp_poly_print(out); + putchar ('\n'); + } + return 1; +} + +static FILE *in; +static FILE *out; + +int +ao_lisp_getc(void) +{ + return getc(in); +} + +static const struct option options[] = { + { .name = "out", .has_arg = 1, .val = 'o' }, + { 0, 0, 0, 0 } +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--out=] [input]\n", program); + exit(1); +} + +int +main(int argc, char **argv) +{ + int f, o; + ao_poly val; + struct ao_lisp_atom *a; + struct ao_lisp_builtin *b; + int in_atom = 0; + char *out_name = NULL; + int c; + + in = stdin; + out = stdout; + + while ((c = getopt_long(argc, argv, "o:", options, NULL)) != -1) { + switch (c) { + case 'o': + out_name = optarg; + break; + default: + usage(argv[0]); + break; + } + } + + for (f = 0; f < (int) N_FUNC; f++) { + b = ao_lisp_make_builtin(funcs[f].func, funcs[f].args); + a = ao_lisp_atom_intern(funcs[f].name); + ao_lisp_atom_set(ao_lisp_atom_poly(a), + ao_lisp_builtin_poly(b)); + } + + /* boolean constants */ + ao_lisp_atom_set(ao_lisp_atom_poly(ao_lisp_atom_intern("nil")), + AO_LISP_NIL); + a = ao_lisp_atom_intern("t"); + ao_lisp_atom_set(ao_lisp_atom_poly(a), + ao_lisp_atom_poly(a)); + + /* end of file value */ + a = ao_lisp_atom_intern("eof"); + ao_lisp_atom_set(ao_lisp_atom_poly(a), + ao_lisp_atom_poly(a)); + + if (argv[optind]){ + in = fopen(argv[optind], "r"); + if (!in) { + perror(argv[optind]); + exit(1); + } + } + if (!ao_lisp_read_eval_abort()) { + fprintf(stderr, "eval failed\n"); + exit(1); + } + + /* Reduce to referenced values */ + ao_lisp_collect(AO_LISP_COLLECT_FULL); + + for (f = 0; f < ao_lisp_frame_global->num; f++) { + val = ao_has_macro(ao_lisp_frame_global->vals[f].val); + if (val != AO_LISP_NIL) { + printf("error: function %s contains unresolved macro: ", + ao_lisp_poly_atom(ao_lisp_frame_global->vals[f].atom)->name); + ao_lisp_poly_print(val); + printf("\n"); + exit(1); + } + } + + if (out_name) { + out = fopen(out_name, "w"); + if (!out) { + perror(out_name); + exit(1); + } + } + + fprintf(out, "/* Generated file, do not edit */\n\n"); + + fprintf(out, "#define AO_LISP_POOL_CONST %d\n", ao_lisp_top); + fprintf(out, "extern const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4)));\n"); + fprintf(out, "#define ao_builtin_atoms 0x%04x\n", ao_lisp_atom_poly(ao_lisp_atoms)); + fprintf(out, "#define ao_builtin_frame 0x%04x\n", ao_lisp_frame_poly(ao_lisp_frame_global)); + fprintf(out, "#define ao_lisp_const_checksum ((uint16_t) 0x%04x)\n", ao_fec_crc(ao_lisp_const, ao_lisp_top)); + + + for (a = ao_lisp_atoms; a; a = ao_lisp_poly_atom(a->next)) { + char *n = a->name, c; + fprintf(out, "#define _ao_lisp_atom_"); + while ((c = *n++)) { + if (isalnum(c)) + fprintf(out, "%c", c); + else + fprintf(out, "%02x", c); + } + fprintf(out, " 0x%04x\n", ao_lisp_atom_poly(a)); + } + fprintf(out, "#ifdef AO_LISP_CONST_BITS\n"); + fprintf(out, "const uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute((aligned(4))) = {"); + for (o = 0; o < ao_lisp_top; o++) { + uint8_t c; + if ((o & 0xf) == 0) + fprintf(out, "\n\t"); + else + fprintf(out, " "); + c = ao_lisp_const[o]; + if (!in_atom) + in_atom = is_atom(o); + if (in_atom) { + fprintf(out, " '%c',", c); + in_atom--; + } else { + fprintf(out, "0x%02x,", c); + } + } + fprintf(out, "\n};\n"); + fprintf(out, "#endif /* AO_LISP_CONST_BITS */\n"); + exit(0); +} diff --git a/src/lisp/ao_lisp_mem.c b/src/lisp/ao_lisp_mem.c new file mode 100644 index 00000000..d067ea07 --- /dev/null +++ b/src/lisp/ao_lisp_mem.c @@ -0,0 +1,880 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#define AO_LISP_CONST_BITS + +#include "ao_lisp.h" +#include + +#ifdef AO_LISP_MAKE_CONST + +/* + * When building the constant table, it is the + * pool for allocations. + */ + +#include +uint8_t ao_lisp_const[AO_LISP_POOL_CONST] __attribute__((aligned(4))); +#define ao_lisp_pool ao_lisp_const +#undef AO_LISP_POOL +#define AO_LISP_POOL AO_LISP_POOL_CONST + +#else + +uint8_t ao_lisp_pool[AO_LISP_POOL + AO_LISP_POOL_EXTRA] __attribute__((aligned(4))); + +#endif + +#ifndef DBG_MEM_STATS +#define DBG_MEM_STATS DBG_MEM +#endif + +#if DBG_MEM +int dbg_move_depth; +int dbg_mem = DBG_MEM_START; +int dbg_validate = 0; + +struct ao_lisp_record { + struct ao_lisp_record *next; + const struct ao_lisp_type *type; + void *addr; + int size; +}; + +static struct ao_lisp_record *record_head, **record_tail; + +static void +ao_lisp_record_free(struct ao_lisp_record *record) +{ + while (record) { + struct ao_lisp_record *next = record->next; + free(record); + record = next; + } +} + +static void +ao_lisp_record_reset(void) +{ + ao_lisp_record_free(record_head); + record_head = NULL; + record_tail = &record_head; +} + +static void +ao_lisp_record(const struct ao_lisp_type *type, + void *addr, + int size) +{ + struct ao_lisp_record *r = malloc(sizeof (struct ao_lisp_record)); + + r->next = NULL; + r->type = type; + r->addr = addr; + r->size = size; + *record_tail = r; + record_tail = &r->next; +} + +static struct ao_lisp_record * +ao_lisp_record_save(void) +{ + struct ao_lisp_record *r = record_head; + + record_head = NULL; + record_tail = &record_head; + return r; +} + +static void +ao_lisp_record_compare(char *where, + struct ao_lisp_record *a, + struct ao_lisp_record *b) +{ + while (a && b) { + if (a->type != b->type || a->size != b->size) { + printf("%s record difers %d %s %d -> %d %s %d\n", + where, + MDBG_OFFSET(a->addr), + a->type->name, + a->size, + MDBG_OFFSET(b->addr), + b->type->name, + b->size); + ao_lisp_abort(); + } + a = a->next; + b = b->next; + } + if (a) { + printf("%s record differs %d %s %d -> NULL\n", + where, + MDBG_OFFSET(a->addr), + a->type->name, + a->size); + ao_lisp_abort(); + } + if (b) { + printf("%s record differs NULL -> %d %s %d\n", + where, + MDBG_OFFSET(b->addr), + b->type->name, + b->size); + ao_lisp_abort(); + } +} + +#else +#define ao_lisp_record_reset() +#endif + +uint8_t ao_lisp_exception; + +struct ao_lisp_root { + const struct ao_lisp_type *type; + void **addr; +}; + +static struct ao_lisp_cons *save_cons[2]; +static char *save_string[2]; +static ao_poly save_poly[3]; + +static const struct ao_lisp_root ao_lisp_root[] = { + { + .type = &ao_lisp_cons_type, + .addr = (void **) &save_cons[0], + }, + { + .type = &ao_lisp_cons_type, + .addr = (void **) &save_cons[1], + }, + { + .type = &ao_lisp_string_type, + .addr = (void **) &save_string[0], + }, + { + .type = &ao_lisp_string_type, + .addr = (void **) &save_string[1], + }, + { + .type = NULL, + .addr = (void **) (void *) &save_poly[0] + }, + { + .type = NULL, + .addr = (void **) (void *) &save_poly[1] + }, + { + .type = NULL, + .addr = (void **) (void *) &save_poly[2] + }, + { + .type = &ao_lisp_atom_type, + .addr = (void **) &ao_lisp_atoms + }, + { + .type = &ao_lisp_frame_type, + .addr = (void **) &ao_lisp_frame_global, + }, + { + .type = &ao_lisp_frame_type, + .addr = (void **) &ao_lisp_frame_current, + }, + { + .type = &ao_lisp_stack_type, + .addr = (void **) &ao_lisp_stack, + }, + { + .type = NULL, + .addr = (void **) (void *) &ao_lisp_v, + }, + { + .type = &ao_lisp_cons_type, + .addr = (void **) &ao_lisp_read_cons, + }, + { + .type = &ao_lisp_cons_type, + .addr = (void **) &ao_lisp_read_cons_tail, + }, + { + .type = &ao_lisp_cons_type, + .addr = (void **) &ao_lisp_read_stack, + }, +}; + +#define AO_LISP_ROOT (sizeof (ao_lisp_root) / sizeof (ao_lisp_root[0])) + +static const void ** const ao_lisp_cache[] = { + (const void **) &ao_lisp_cons_free_list, + (const void **) &ao_lisp_stack_free_list, + (const void **) &ao_lisp_frame_free_list[0], + (const void **) &ao_lisp_frame_free_list[1], + (const void **) &ao_lisp_frame_free_list[2], + (const void **) &ao_lisp_frame_free_list[3], + (const void **) &ao_lisp_frame_free_list[4], + (const void **) &ao_lisp_frame_free_list[5], +}; + +#if AO_LISP_FRAME_FREE != 6 +#error Unexpected AO_LISP_FRAME_FREE value +#endif + +#define AO_LISP_CACHE (sizeof (ao_lisp_cache) / sizeof (ao_lisp_cache[0])) + +#define AO_LISP_BUSY_SIZE ((AO_LISP_POOL + 31) / 32) + +static uint8_t ao_lisp_busy[AO_LISP_BUSY_SIZE]; +static uint8_t ao_lisp_cons_note[AO_LISP_BUSY_SIZE]; +static uint8_t ao_lisp_cons_last[AO_LISP_BUSY_SIZE]; +static uint8_t ao_lisp_cons_noted; + +uint16_t ao_lisp_top; + +struct ao_lisp_chunk { + uint16_t old_offset; + union { + uint16_t size; + uint16_t new_offset; + }; +}; + +#define AO_LISP_NCHUNK 64 + +static struct ao_lisp_chunk ao_lisp_chunk[AO_LISP_NCHUNK]; + +/* Offset of an address within the pool. */ +static inline uint16_t pool_offset(void *addr) { +#if DBG_MEM + if (!AO_LISP_IS_POOL(addr)) + ao_lisp_abort(); +#endif + return ((uint8_t *) addr) - ao_lisp_pool; +} + +static inline void mark(uint8_t *tag, int offset) { + int byte = offset >> 5; + int bit = (offset >> 2) & 7; + tag[byte] |= (1 << bit); +} + +static inline void clear(uint8_t *tag, int offset) { + int byte = offset >> 5; + int bit = (offset >> 2) & 7; + tag[byte] &= ~(1 << bit); +} + +static inline int busy(uint8_t *tag, int offset) { + int byte = offset >> 5; + int bit = (offset >> 2) & 7; + return (tag[byte] >> bit) & 1; +} + +static inline int min(int a, int b) { return a < b ? a : b; } +static inline int max(int a, int b) { return a > b ? a : b; } + +static inline int limit(int offset) { + return min(AO_LISP_POOL, max(offset, 0)); +} + +static void +note_cons(uint16_t offset) +{ + MDBG_MOVE("note cons %d\n", offset); + ao_lisp_cons_noted = 1; + mark(ao_lisp_cons_note, offset); +} + +static uint16_t chunk_low, chunk_high; +static uint16_t chunk_first, chunk_last; + +static int +find_chunk(uint16_t offset) +{ + int l, r; + /* Binary search for the location */ + l = chunk_first; + r = chunk_last - 1; + while (l <= r) { + int m = (l + r) >> 1; + if (ao_lisp_chunk[m].old_offset < offset) + l = m + 1; + else + r = m - 1; + } + return l; +} + +static void +note_chunk(uint16_t offset, uint16_t size) +{ + int l; + + if (offset < chunk_low || chunk_high <= offset) + return; + + l = find_chunk(offset); + + /* + * The correct location is always in 'l', with r = l-1 being + * the entry before the right one + */ + +#if DBG_MEM + /* Off the right side */ + if (l >= AO_LISP_NCHUNK) + ao_lisp_abort(); + + /* Off the left side */ + if (l == 0 && chunk_last && offset > ao_lisp_chunk[0].old_offset) + ao_lisp_abort(); +#endif + + /* Shuffle existing entries right */ + int end = min(AO_LISP_NCHUNK, chunk_last + 1); + + memmove(&ao_lisp_chunk[l+1], + &ao_lisp_chunk[l], + (end - (l+1)) * sizeof (struct ao_lisp_chunk)); + + /* Add new entry */ + ao_lisp_chunk[l].old_offset = offset; + ao_lisp_chunk[l].size = size; + + /* Increment the number of elements up to the size of the array */ + if (chunk_last < AO_LISP_NCHUNK) + chunk_last++; + + /* Set the top address if the array is full */ + if (chunk_last == AO_LISP_NCHUNK) + chunk_high = ao_lisp_chunk[AO_LISP_NCHUNK-1].old_offset + + ao_lisp_chunk[AO_LISP_NCHUNK-1].size; +} + +static void +reset_chunks(void) +{ + chunk_high = ao_lisp_top; + chunk_last = 0; + chunk_first = 0; +} + +/* + * Walk all referenced objects calling functions on each one + */ + +static void +walk(int (*visit_addr)(const struct ao_lisp_type *type, void **addr), + int (*visit_poly)(ao_poly *p, uint8_t do_note_cons)) +{ + int i; + + ao_lisp_record_reset(); + memset(ao_lisp_busy, '\0', sizeof (ao_lisp_busy)); + memset(ao_lisp_cons_note, '\0', sizeof (ao_lisp_cons_note)); + ao_lisp_cons_noted = 0; + for (i = 0; i < (int) AO_LISP_ROOT; i++) { + if (ao_lisp_root[i].type) { + void **a = ao_lisp_root[i].addr, *v; + if (a && (v = *a)) { + MDBG_MOVE("root ptr %d\n", MDBG_OFFSET(v)); + visit_addr(ao_lisp_root[i].type, a); + } + } else { + ao_poly *a = (ao_poly *) ao_lisp_root[i].addr, p; + if (a && (p = *a)) { + MDBG_MOVE("root poly %d\n", MDBG_OFFSET(ao_lisp_ref(p))); + visit_poly(a, 0); + } + } + } + while (ao_lisp_cons_noted) { + memcpy(ao_lisp_cons_last, ao_lisp_cons_note, sizeof (ao_lisp_cons_note)); + memset(ao_lisp_cons_note, '\0', sizeof (ao_lisp_cons_note)); + ao_lisp_cons_noted = 0; + for (i = 0; i < AO_LISP_POOL; i += 4) { + if (busy(ao_lisp_cons_last, i)) { + void *v = ao_lisp_pool + i; + MDBG_MOVE("root cons %d\n", MDBG_OFFSET(v)); + visit_addr(&ao_lisp_cons_type, &v); + } + } + } +} + +#if MDBG_DUMP +static void +dump_busy(void) +{ + int i; + MDBG_MOVE("busy:"); + for (i = 0; i < ao_lisp_top; i += 4) { + if ((i & 0xff) == 0) { + MDBG_MORE("\n"); + MDBG_MOVE("%s", ""); + } + else if ((i & 0x1f) == 0) + MDBG_MORE(" "); + if (busy(ao_lisp_busy, i)) + MDBG_MORE("*"); + else + MDBG_MORE("-"); + } + MDBG_MORE ("\n"); +} +#define DUMP_BUSY() dump_busy() +#else +#define DUMP_BUSY() +#endif + +static const struct ao_lisp_type const *ao_lisp_types[AO_LISP_NUM_TYPE] = { + [AO_LISP_CONS] = &ao_lisp_cons_type, + [AO_LISP_INT] = NULL, + [AO_LISP_STRING] = &ao_lisp_string_type, + [AO_LISP_OTHER] = (void *) 0x1, + [AO_LISP_ATOM] = &ao_lisp_atom_type, + [AO_LISP_BUILTIN] = &ao_lisp_builtin_type, + [AO_LISP_FRAME] = &ao_lisp_frame_type, + [AO_LISP_LAMBDA] = &ao_lisp_lambda_type, + [AO_LISP_STACK] = &ao_lisp_stack_type, +}; + +static int +ao_lisp_mark_ref(const struct ao_lisp_type *type, void **ref) +{ + return ao_lisp_mark(type, *ref); +} + +static int +ao_lisp_poly_mark_ref(ao_poly *p, uint8_t do_note_cons) +{ + return ao_lisp_poly_mark(*p, do_note_cons); +} + +#if DBG_MEM_STATS +int ao_lisp_collects[2]; +int ao_lisp_freed[2]; +int ao_lisp_loops[2]; +#endif + +int ao_lisp_last_top; + +int +ao_lisp_collect(uint8_t style) +{ + int i; + int top; +#if DBG_MEM_STATS + int loops = 0; +#endif +#if DBG_MEM + struct ao_lisp_record *mark_record = NULL, *move_record = NULL; + + MDBG_MOVE("collect %d\n", ao_lisp_collects[style]); +#endif + + /* The first time through, we're doing a full collect */ + if (ao_lisp_last_top == 0) + style = AO_LISP_COLLECT_FULL; + + /* Clear references to all caches */ + for (i = 0; i < (int) AO_LISP_CACHE; i++) + *ao_lisp_cache[i] = NULL; + if (style == AO_LISP_COLLECT_FULL) { + chunk_low = top = 0; + } else { + chunk_low = top = ao_lisp_last_top; + } + for (;;) { +#if DBG_MEM_STATS + loops++; +#endif + MDBG_MOVE("move chunks from %d to %d\n", chunk_low, top); + /* Find the sizes of the first chunk of objects to move */ + reset_chunks(); + walk(ao_lisp_mark_ref, ao_lisp_poly_mark_ref); +#if DBG_MEM + + ao_lisp_record_free(mark_record); + mark_record = ao_lisp_record_save(); + if (mark_record && move_record) + ao_lisp_record_compare("mark", move_record, mark_record); +#endif + + DUMP_BUSY(); + + /* Find the first moving object */ + for (i = 0; i < chunk_last; i++) { + uint16_t size = ao_lisp_chunk[i].size; + +#if DBG_MEM + if (!size) + ao_lisp_abort(); +#endif + + if (ao_lisp_chunk[i].old_offset > top) + break; + + MDBG_MOVE("chunk %d %d not moving\n", + ao_lisp_chunk[i].old_offset, + ao_lisp_chunk[i].size); +#if DBG_MEM + if (ao_lisp_chunk[i].old_offset != top) + ao_lisp_abort(); +#endif + top += size; + } + + /* + * Limit amount of chunk array used in mapping moves + * to the active region + */ + chunk_first = i; + chunk_low = ao_lisp_chunk[i].old_offset; + + /* Copy all of the objects */ + for (; i < chunk_last; i++) { + uint16_t size = ao_lisp_chunk[i].size; + +#if DBG_MEM + if (!size) + ao_lisp_abort(); +#endif + + MDBG_MOVE("chunk %d %d -> %d\n", + ao_lisp_chunk[i].old_offset, + size, + top); + ao_lisp_chunk[i].new_offset = top; + + memmove(&ao_lisp_pool[top], + &ao_lisp_pool[ao_lisp_chunk[i].old_offset], + size); + + top += size; + } + + if (chunk_first < chunk_last) { + /* Relocate all references to the objects */ + walk(ao_lisp_move, ao_lisp_poly_move); + +#if DBG_MEM + ao_lisp_record_free(move_record); + move_record = ao_lisp_record_save(); + if (mark_record && move_record) + ao_lisp_record_compare("move", mark_record, move_record); +#endif + } + + /* If we ran into the end of the heap, then + * there's no need to keep walking + */ + if (chunk_last != AO_LISP_NCHUNK) + break; + + /* Next loop starts right above this loop */ + chunk_low = chunk_high; + } + +#if DBG_MEM_STATS + /* Collect stats */ + ++ao_lisp_collects[style]; + ao_lisp_freed[style] += ao_lisp_top - top; + ao_lisp_loops[style] += loops; +#endif + + ao_lisp_top = top; + if (style == AO_LISP_COLLECT_FULL) + ao_lisp_last_top = top; + + MDBG_DO(memset(ao_lisp_chunk, '\0', sizeof (ao_lisp_chunk)); + walk(ao_lisp_mark_ref, ao_lisp_poly_mark_ref)); + + return AO_LISP_POOL - ao_lisp_top; +} + +/* + * Mark interfaces for objects + */ + +/* + * Note a reference to memory and collect information about a few + * object sizes at a time + */ + +int +ao_lisp_mark_memory(const struct ao_lisp_type *type, void *addr) +{ + int offset; + if (!AO_LISP_IS_POOL(addr)) + return 1; + + offset = pool_offset(addr); + MDBG_MOVE("mark memory %d\n", MDBG_OFFSET(addr)); + if (busy(ao_lisp_busy, offset)) { + MDBG_MOVE("already marked\n"); + return 1; + } + mark(ao_lisp_busy, offset); + note_chunk(offset, ao_lisp_size(type, addr)); + return 0; +} + +/* + * Mark an object and all that it refereces + */ +int +ao_lisp_mark(const struct ao_lisp_type *type, void *addr) +{ + int ret; + MDBG_MOVE("mark %d\n", MDBG_OFFSET(addr)); + MDBG_MOVE_IN(); + ret = ao_lisp_mark_memory(type, addr); + if (!ret) { + MDBG_MOVE("mark recurse\n"); + type->mark(addr); + } + MDBG_MOVE_OUT(); + return ret; +} + +/* + * Mark an object, unless it is a cons cell and + * do_note_cons is set. In that case, just + * set a bit in the cons note array; those + * will be marked in a separate pass to avoid + * deep recursion in the collector + */ +int +ao_lisp_poly_mark(ao_poly p, uint8_t do_note_cons) +{ + uint8_t type; + void *addr; + + type = ao_lisp_poly_base_type(p); + + if (type == AO_LISP_INT) + return 1; + + addr = ao_lisp_ref(p); + if (!AO_LISP_IS_POOL(addr)) + return 1; + + if (type == AO_LISP_CONS && do_note_cons) { + note_cons(pool_offset(addr)); + return 1; + } else { + if (type == AO_LISP_OTHER) + type = ao_lisp_other_type(addr); + + const struct ao_lisp_type *lisp_type = ao_lisp_types[type]; +#if DBG_MEM + if (!lisp_type) + ao_lisp_abort(); +#endif + + return ao_lisp_mark(lisp_type, addr); + } +} + +/* + * Find the current location of an object + * based on the original location. For unmoved + * objects, this is simple. For moved objects, + * go search for it + */ + +static uint16_t +move_map(uint16_t offset) +{ + int l; + + if (offset < chunk_low || chunk_high <= offset) + return offset; + + l = find_chunk(offset); + +#if DBG_MEM + if (ao_lisp_chunk[l].old_offset != offset) + ao_lisp_abort(); +#endif + return ao_lisp_chunk[l].new_offset; +} + +int +ao_lisp_move_memory(const struct ao_lisp_type *type, void **ref) +{ + void *addr = *ref; + uint16_t offset, orig_offset; + + if (!AO_LISP_IS_POOL(addr)) + return 1; + + (void) type; + + MDBG_MOVE("move memory %d\n", MDBG_OFFSET(addr)); + orig_offset = pool_offset(addr); + offset = move_map(orig_offset); + if (offset != orig_offset) { + MDBG_MOVE("update ref %d %d -> %d\n", + AO_LISP_IS_POOL(ref) ? MDBG_OFFSET(ref) : -1, + orig_offset, offset); + *ref = ao_lisp_pool + offset; + } + if (busy(ao_lisp_busy, offset)) { + MDBG_MOVE("already moved\n"); + return 1; + } + mark(ao_lisp_busy, offset); + MDBG_DO(ao_lisp_record(type, addr, ao_lisp_size(type, addr))); + return 0; +} + +int +ao_lisp_move(const struct ao_lisp_type *type, void **ref) +{ + int ret; + MDBG_MOVE("move object %d\n", MDBG_OFFSET(*ref)); + MDBG_MOVE_IN(); + ret = ao_lisp_move_memory(type, ref); + if (!ret) { + MDBG_MOVE("move recurse\n"); + type->move(*ref); + } + MDBG_MOVE_OUT(); + return ret; +} + +int +ao_lisp_poly_move(ao_poly *ref, uint8_t do_note_cons) +{ + uint8_t type; + ao_poly p = *ref; + int ret; + void *addr; + uint16_t offset, orig_offset; + uint8_t base_type; + + base_type = type = ao_lisp_poly_base_type(p); + + if (type == AO_LISP_INT) + return 1; + + addr = ao_lisp_ref(p); + if (!AO_LISP_IS_POOL(addr)) + return 1; + + orig_offset = pool_offset(addr); + offset = move_map(orig_offset); + + if (type == AO_LISP_CONS && do_note_cons) { + note_cons(orig_offset); + ret = 1; + } else { + if (type == AO_LISP_OTHER) + type = ao_lisp_other_type(ao_lisp_pool + offset); + + const struct ao_lisp_type *lisp_type = ao_lisp_types[type]; +#if DBG_MEM + if (!lisp_type) + ao_lisp_abort(); +#endif + + ret = ao_lisp_move(lisp_type, &addr); + } + + /* Re-write the poly value */ + if (offset != orig_offset) { + ao_poly np = ao_lisp_poly(ao_lisp_pool + offset, base_type); + MDBG_MOVE("poly %d moved %d -> %d\n", + type, orig_offset, offset); + *ref = np; + } + return ret; +} + +#if DBG_MEM +void +ao_lisp_validate(void) +{ + chunk_low = 0; + memset(ao_lisp_chunk, '\0', sizeof (ao_lisp_chunk)); + walk(ao_lisp_mark_ref, ao_lisp_poly_mark_ref); +} + +int dbg_allocs; + +#endif + +void * +ao_lisp_alloc(int size) +{ + void *addr; + + MDBG_DO(++dbg_allocs); + MDBG_DO(if (dbg_validate) ao_lisp_validate()); + size = ao_lisp_size_round(size); + if (AO_LISP_POOL - ao_lisp_top < size && + ao_lisp_collect(AO_LISP_COLLECT_INCREMENTAL) < size && + ao_lisp_collect(AO_LISP_COLLECT_FULL) < size) + { + ao_lisp_error(AO_LISP_OOM, "out of memory"); + return NULL; + } + addr = ao_lisp_pool + ao_lisp_top; + ao_lisp_top += size; + return addr; +} + +void +ao_lisp_cons_stash(int id, struct ao_lisp_cons *cons) +{ + save_cons[id] = cons; +} + +struct ao_lisp_cons * +ao_lisp_cons_fetch(int id) +{ + struct ao_lisp_cons *cons = save_cons[id]; + save_cons[id] = NULL; + return cons; +} + +void +ao_lisp_poly_stash(int id, ao_poly poly) +{ + save_poly[id] = poly; +} + +ao_poly +ao_lisp_poly_fetch(int id) +{ + ao_poly poly = save_poly[id]; + save_poly[id] = AO_LISP_NIL; + return poly; +} + +void +ao_lisp_string_stash(int id, char *string) +{ + save_string[id] = string; +} + +char * +ao_lisp_string_fetch(int id) +{ + char *string = save_string[id]; + save_string[id] = NULL; + return string; +} + diff --git a/src/lisp/ao_lisp_os.h b/src/lisp/ao_lisp_os.h new file mode 100644 index 00000000..5fa3686b --- /dev/null +++ b/src/lisp/ao_lisp_os.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_LISP_OS_H_ +#define _AO_LISP_OS_H_ + +#include +#include +#include + +extern int ao_lisp_getc(void); + +static inline void +ao_lisp_os_flush(void) { + fflush(stdout); +} + +static inline void +ao_lisp_abort(void) +{ + abort(); +} + +static inline void +ao_lisp_os_led(int led) +{ + printf("leds set to 0x%x\n", led); +} + +static inline void +ao_lisp_os_delay(int delay) +{ + struct timespec ts = { + .tv_sec = delay / 1000, + .tv_nsec = (delay % 1000) * 1000000, + }; + nanosleep(&ts, NULL); +} +#endif diff --git a/src/lisp/ao_lisp_poly.c b/src/lisp/ao_lisp_poly.c new file mode 100644 index 00000000..fb3b06fe --- /dev/null +++ b/src/lisp/ao_lisp_poly.c @@ -0,0 +1,102 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + +struct ao_lisp_funcs { + void (*print)(ao_poly); + void (*patom)(ao_poly); +}; + +static const struct ao_lisp_funcs ao_lisp_funcs[AO_LISP_NUM_TYPE] = { + [AO_LISP_CONS] = { + .print = ao_lisp_cons_print, + .patom = ao_lisp_cons_patom, + }, + [AO_LISP_STRING] = { + .print = ao_lisp_string_print, + .patom = ao_lisp_string_patom, + }, + [AO_LISP_INT] = { + .print = ao_lisp_int_print, + .patom = ao_lisp_int_print, + }, + [AO_LISP_ATOM] = { + .print = ao_lisp_atom_print, + .patom = ao_lisp_atom_print, + }, + [AO_LISP_BUILTIN] = { + .print = ao_lisp_builtin_print, + .patom = ao_lisp_builtin_print, + }, + [AO_LISP_FRAME] = { + .print = ao_lisp_frame_print, + .patom = ao_lisp_frame_print, + }, + [AO_LISP_LAMBDA] = { + .print = ao_lisp_lambda_print, + .patom = ao_lisp_lambda_print, + }, + [AO_LISP_STACK] = { + .print = ao_lisp_stack_print, + .patom = ao_lisp_stack_print, + }, +}; + +static const struct ao_lisp_funcs * +funcs(ao_poly p) +{ + uint8_t type = ao_lisp_poly_type(p); + + if (type < AO_LISP_NUM_TYPE) + return &ao_lisp_funcs[type]; + return NULL; +} + +void +ao_lisp_poly_print(ao_poly p) +{ + const struct ao_lisp_funcs *f = funcs(p); + + if (f && f->print) + f->print(p); +} + +void +ao_lisp_poly_patom(ao_poly p) +{ + const struct ao_lisp_funcs *f = funcs(p); + + if (f && f->patom) + f->patom(p); +} + +void * +ao_lisp_ref(ao_poly poly) { + if (poly == AO_LISP_NIL) + return NULL; + if (poly & AO_LISP_CONST) + return (void *) (ao_lisp_const + (poly & AO_LISP_REF_MASK) - 4); + return (void *) (ao_lisp_pool + (poly & AO_LISP_REF_MASK) - 4); +} + +ao_poly +ao_lisp_poly(const void *addr, ao_poly type) { + const uint8_t *a = addr; + if (a == NULL) + return AO_LISP_NIL; + if (AO_LISP_IS_CONST(a)) + return AO_LISP_CONST | (a - ao_lisp_const + 4) | type; + return (a - ao_lisp_pool + 4) | type; +} diff --git a/src/lisp/ao_lisp_read.c b/src/lisp/ao_lisp_read.c new file mode 100644 index 00000000..84ef2a61 --- /dev/null +++ b/src/lisp/ao_lisp_read.c @@ -0,0 +1,498 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" +#include "ao_lisp_read.h" + +static const uint16_t lex_classes[128] = { + IGNORE, /* ^@ */ + IGNORE, /* ^A */ + IGNORE, /* ^B */ + IGNORE, /* ^C */ + IGNORE, /* ^D */ + IGNORE, /* ^E */ + IGNORE, /* ^F */ + IGNORE, /* ^G */ + IGNORE, /* ^H */ + WHITE, /* ^I */ + WHITE, /* ^J */ + WHITE, /* ^K */ + WHITE, /* ^L */ + WHITE, /* ^M */ + IGNORE, /* ^N */ + IGNORE, /* ^O */ + IGNORE, /* ^P */ + IGNORE, /* ^Q */ + IGNORE, /* ^R */ + IGNORE, /* ^S */ + IGNORE, /* ^T */ + IGNORE, /* ^U */ + IGNORE, /* ^V */ + IGNORE, /* ^W */ + IGNORE, /* ^X */ + IGNORE, /* ^Y */ + IGNORE, /* ^Z */ + IGNORE, /* ^[ */ + IGNORE, /* ^\ */ + IGNORE, /* ^] */ + IGNORE, /* ^^ */ + IGNORE, /* ^_ */ + PRINTABLE|WHITE, /* */ + PRINTABLE, /* ! */ + PRINTABLE|STRINGC, /* " */ + PRINTABLE|COMMENT, /* # */ + PRINTABLE, /* $ */ + PRINTABLE, /* % */ + PRINTABLE, /* & */ + PRINTABLE|QUOTEC, /* ' */ + PRINTABLE|BRA, /* ( */ + PRINTABLE|KET, /* ) */ + PRINTABLE, /* * */ + PRINTABLE|SIGN, /* + */ + PRINTABLE, /* , */ + PRINTABLE|SIGN, /* - */ + PRINTABLE, /* . */ + PRINTABLE, /* / */ + PRINTABLE|DIGIT, /* 0 */ + PRINTABLE|DIGIT, /* 1 */ + PRINTABLE|DIGIT, /* 2 */ + PRINTABLE|DIGIT, /* 3 */ + PRINTABLE|DIGIT, /* 4 */ + PRINTABLE|DIGIT, /* 5 */ + PRINTABLE|DIGIT, /* 6 */ + PRINTABLE|DIGIT, /* 7 */ + PRINTABLE|DIGIT, /* 8 */ + PRINTABLE|DIGIT, /* 9 */ + PRINTABLE, /* : */ + PRINTABLE|COMMENT, /* ; */ + PRINTABLE, /* < */ + PRINTABLE, /* = */ + PRINTABLE, /* > */ + PRINTABLE, /* ? */ + PRINTABLE, /* @ */ + PRINTABLE, /* A */ + PRINTABLE, /* B */ + PRINTABLE, /* C */ + PRINTABLE, /* D */ + PRINTABLE, /* E */ + PRINTABLE, /* F */ + PRINTABLE, /* G */ + PRINTABLE, /* H */ + PRINTABLE, /* I */ + PRINTABLE, /* J */ + PRINTABLE, /* K */ + PRINTABLE, /* L */ + PRINTABLE, /* M */ + PRINTABLE, /* N */ + PRINTABLE, /* O */ + PRINTABLE, /* P */ + PRINTABLE, /* Q */ + PRINTABLE, /* R */ + PRINTABLE, /* S */ + PRINTABLE, /* T */ + PRINTABLE, /* U */ + PRINTABLE, /* V */ + PRINTABLE, /* W */ + PRINTABLE, /* X */ + PRINTABLE, /* Y */ + PRINTABLE, /* Z */ + PRINTABLE, /* [ */ + PRINTABLE|BACKSLASH, /* \ */ + PRINTABLE, /* ] */ + PRINTABLE, /* ^ */ + PRINTABLE, /* _ */ + PRINTABLE, /* ` */ + PRINTABLE, /* a */ + PRINTABLE, /* b */ + PRINTABLE, /* c */ + PRINTABLE, /* d */ + PRINTABLE, /* e */ + PRINTABLE, /* f */ + PRINTABLE, /* g */ + PRINTABLE, /* h */ + PRINTABLE, /* i */ + PRINTABLE, /* j */ + PRINTABLE, /* k */ + PRINTABLE, /* l */ + PRINTABLE, /* m */ + PRINTABLE, /* n */ + PRINTABLE, /* o */ + PRINTABLE, /* p */ + PRINTABLE, /* q */ + PRINTABLE, /* r */ + PRINTABLE, /* s */ + PRINTABLE, /* t */ + PRINTABLE, /* u */ + PRINTABLE, /* v */ + PRINTABLE, /* w */ + PRINTABLE, /* x */ + PRINTABLE, /* y */ + PRINTABLE, /* z */ + PRINTABLE, /* { */ + PRINTABLE|VBAR, /* | */ + PRINTABLE, /* } */ + PRINTABLE|TWIDDLE, /* ~ */ + IGNORE, /* ^? */ +}; + +static int lex_unget_c; + +static inline int +lex_get() +{ + int c; + if (lex_unget_c) { + c = lex_unget_c; + lex_unget_c = 0; + } else { + c = ao_lisp_getc(); + } + return c; +} + +static inline void +lex_unget(int c) +{ + if (c != EOF) + lex_unget_c = c; +} + +static int +lex_quoted (void) +{ + int c; + int v; + int count; + + c = lex_get(); + if (c == EOF) + return EOF; + c &= 0x7f; + switch (c) { + case 'n': + return '\n'; + case 'f': + return '\f'; + case 'b': + return '\b'; + case 'r': + return '\r'; + case 'v': + return '\v'; + case 't': + return '\t'; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + v = c - '0'; + count = 1; + while (count <= 3) { + c = lex_get(); + if (c == EOF) + return EOF; + c &= 0x7f; + if (c < '0' || '7' < c) { + lex_unget(c); + break; + } + v = (v << 3) + c - '0'; + ++count; + } + return v; + default: + return c; + } +} + +static uint16_t lex_class; + +static int +lexc(void) +{ + int c; + do { + c = lex_get(); + if (c == EOF) { + lex_class = ENDOFFILE; + c = 0; + } else { + c &= 0x7f; + lex_class = lex_classes[c]; + if (lex_class & BACKSLASH) { + c = lex_quoted(); + if (c == EOF) + lex_class = ENDOFFILE; + else + lex_class = PRINTABLE; + } + } + } while (lex_class & IGNORE); + return c; +} + +#define AO_LISP_TOKEN_MAX 32 + +static char token_string[AO_LISP_TOKEN_MAX]; +static int token_int; +static int token_len; + +static inline void add_token(int c) { + if (c && token_len < AO_LISP_TOKEN_MAX - 1) + token_string[token_len++] = c; +} + +static inline void end_token(void) { + token_string[token_len] = '\0'; +} + +static int +lex(void) +{ + int c; + + token_len = 0; + for (;;) { + c = lexc(); + if (lex_class & ENDOFFILE) + return END; + + if (lex_class & WHITE) + continue; + + if (lex_class & COMMENT) { + while ((c = lexc()) != '\n') { + if (lex_class & ENDOFFILE) + return END; + } + continue; + } + + if (lex_class & (BRA|KET|QUOTEC)) { + add_token(c); + end_token(); + switch (c) { + case '(': + return OPEN; + case ')': + return CLOSE; + case '\'': + return QUOTE; + } + } + if (lex_class & TWIDDLE) { + token_int = lexc(); + return NUM; + } + if (lex_class & STRINGC) { + for (;;) { + c = lexc(); + if (lex_class & (STRINGC|ENDOFFILE)) { + end_token(); + return STRING; + } + add_token(c); + } + } + if (lex_class & PRINTABLE) { + int isnum; + int hasdigit; + int isneg; + + isnum = 1; + hasdigit = 0; + token_int = 0; + isneg = 0; + for (;;) { + if (!(lex_class & NUMBER)) { + isnum = 0; + } else { + if (token_len != 0 && + (lex_class & SIGN)) + { + isnum = 0; + } + if (c == '-') + isneg = 1; + if (lex_class & DIGIT) { + hasdigit = 1; + if (isnum) + token_int = token_int * 10 + c - '0'; + } + } + add_token (c); + c = lexc (); + if (lex_class & (NOTNAME)) { +// if (lex_class & ENDOFFILE) +// clearerr (f); + lex_unget(c); + end_token (); + if (isnum && hasdigit) { + if (isneg) + token_int = -token_int; + return NUM; + } + return NAME; + } + } + + } + } +} + +static int parse_token; + +struct ao_lisp_cons *ao_lisp_read_cons; +struct ao_lisp_cons *ao_lisp_read_cons_tail; +struct ao_lisp_cons *ao_lisp_read_stack; + +static int +push_read_stack(int cons, int in_quote) +{ + DBGI("push read stack %p %d\n", ao_lisp_read_cons, in_quote); + DBG_IN(); + if (cons) { + ao_lisp_read_stack = ao_lisp_cons_cons(ao_lisp_cons_poly(ao_lisp_read_cons), + ao_lisp_cons_cons(ao_lisp_int_poly(in_quote), + ao_lisp_read_stack)); + if (!ao_lisp_read_stack) + return 0; + } + ao_lisp_read_cons = NULL; + ao_lisp_read_cons_tail = NULL; + return 1; +} + +static int +pop_read_stack(int cons) +{ + int in_quote = 0; + if (cons) { + ao_lisp_read_cons = ao_lisp_poly_cons(ao_lisp_read_stack->car); + ao_lisp_read_stack = ao_lisp_poly_cons(ao_lisp_read_stack->cdr); + in_quote = ao_lisp_poly_int(ao_lisp_read_stack->car); + ao_lisp_read_stack = ao_lisp_poly_cons(ao_lisp_read_stack->cdr); + for (ao_lisp_read_cons_tail = ao_lisp_read_cons; + ao_lisp_read_cons_tail && ao_lisp_read_cons_tail->cdr; + ao_lisp_read_cons_tail = ao_lisp_poly_cons(ao_lisp_read_cons_tail->cdr)) + ; + } else { + ao_lisp_read_cons = 0; + ao_lisp_read_cons_tail = 0; + ao_lisp_read_stack = 0; + } + DBG_OUT(); + DBGI("pop read stack %p %d\n", ao_lisp_read_cons, in_quote); + return in_quote; +} + +ao_poly +ao_lisp_read(void) +{ + struct ao_lisp_atom *atom; + char *string; + int cons; + int in_quote; + ao_poly v; + + parse_token = lex(); + DBGI("token %d (%s)\n", parse_token, token_string); + + cons = 0; + in_quote = 0; + ao_lisp_read_cons = ao_lisp_read_cons_tail = ao_lisp_read_stack = 0; + for (;;) { + while (parse_token == OPEN) { + if (!push_read_stack(cons, in_quote)) + return AO_LISP_NIL; + cons++; + in_quote = 0; + parse_token = lex(); + DBGI("token %d (%s)\n", parse_token, token_string); + } + + switch (parse_token) { + case END: + default: + if (cons) + ao_lisp_error(AO_LISP_EOF, "unexpected end of file"); + return _ao_lisp_atom_eof; + break; + case NAME: + atom = ao_lisp_atom_intern(token_string); + if (atom) + v = ao_lisp_atom_poly(atom); + else + v = AO_LISP_NIL; + break; + case NUM: + v = ao_lisp_int_poly(token_int); + break; + case STRING: + string = ao_lisp_string_copy(token_string); + if (string) + v = ao_lisp_string_poly(string); + else + v = AO_LISP_NIL; + break; + case QUOTE: + if (!push_read_stack(cons, in_quote)) + return AO_LISP_NIL; + cons++; + in_quote = 1; + v = _ao_lisp_atom_quote; + break; + case CLOSE: + if (!cons) { + v = AO_LISP_NIL; + break; + } + v = ao_lisp_cons_poly(ao_lisp_read_cons); + --cons; + in_quote = pop_read_stack(cons); + break; + } + + /* loop over QUOTE ends */ + for (;;) { + if (!cons) + return v; + + struct ao_lisp_cons *read = ao_lisp_cons_cons(v, NULL); + if (!read) + return AO_LISP_NIL; + + if (ao_lisp_read_cons_tail) + ao_lisp_read_cons_tail->cdr = ao_lisp_cons_poly(read); + else + ao_lisp_read_cons = read; + ao_lisp_read_cons_tail = read; + + if (!in_quote || !ao_lisp_read_cons->cdr) + break; + + v = ao_lisp_cons_poly(ao_lisp_read_cons); + --cons; + in_quote = pop_read_stack(cons); + } + + parse_token = lex(); + DBGI("token %d (%s)\n", parse_token, token_string); + } + return v; +} diff --git a/src/lisp/ao_lisp_read.h b/src/lisp/ao_lisp_read.h new file mode 100644 index 00000000..1c994d56 --- /dev/null +++ b/src/lisp/ao_lisp_read.h @@ -0,0 +1,49 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_LISP_READ_H_ +#define _AO_LISP_READ_H_ + +# define END 0 +# define NAME 1 +# define OPEN 2 +# define CLOSE 3 +# define QUOTE 4 +# define STRING 5 +# define NUM 6 + +/* + * character classes + */ + +# define PRINTABLE 0x00000001 /* \t \n ' ' - '~' */ +# define QUOTED 0x00000002 /* \ anything */ +# define BRA 0x00000004 /* ( [ { */ +# define KET 0x00000008 /* ) ] } */ +# define WHITE 0x00000010 /* ' ' \t \n */ +# define DIGIT 0x00000020 /* [0-9] */ +# define SIGN 0x00000040 /* +- */ +# define ENDOFFILE 0x00000080 /* end of file */ +# define COMMENT 0x00000100 /* ; # */ +# define IGNORE 0x00000200 /* \0 - ' ' */ +# define QUOTEC 0x00000400 /* ' */ +# define BACKSLASH 0x00000800 /* \ */ +# define VBAR 0x00001000 /* | */ +# define TWIDDLE 0x00002000 /* ~ */ +# define STRINGC 0x00004000 /* " */ + +# define NOTNAME (STRINGC|TWIDDLE|VBAR|QUOTEC|COMMENT|ENDOFFILE|WHITE|KET|BRA) +# define NUMBER (DIGIT|SIGN) + +#endif /* _AO_LISP_READ_H_ */ diff --git a/src/lisp/ao_lisp_rep.c b/src/lisp/ao_lisp_rep.c new file mode 100644 index 00000000..3be95d44 --- /dev/null +++ b/src/lisp/ao_lisp_rep.c @@ -0,0 +1,34 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + +ao_poly +ao_lisp_read_eval_print(void) +{ + ao_poly in, out = AO_LISP_NIL; + for(;;) { + in = ao_lisp_read(); + if (in == _ao_lisp_atom_eof || in == AO_LISP_NIL) + break; + out = ao_lisp_eval(in); + if (ao_lisp_exception) { + ao_lisp_exception = 0; + } else { + ao_lisp_poly_print(out); + putchar ('\n'); + } + } + return out; +} diff --git a/src/lisp/ao_lisp_save.c b/src/lisp/ao_lisp_save.c new file mode 100644 index 00000000..4f850fb9 --- /dev/null +++ b/src/lisp/ao_lisp_save.c @@ -0,0 +1,76 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include + +ao_poly +ao_lisp_save(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_save, cons, 0, 0)) + return AO_LISP_NIL; + +#ifdef AO_LISP_SAVE + struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) (void *) &ao_lisp_pool[AO_LISP_POOL]; + + ao_lisp_collect(AO_LISP_COLLECT_FULL); + os->atoms = ao_lisp_atom_poly(ao_lisp_atoms); + os->globals = ao_lisp_frame_poly(ao_lisp_frame_global); + os->const_checksum = ao_lisp_const_checksum; + os->const_checksum_inv = (uint16_t) ~ao_lisp_const_checksum; + + if (ao_lisp_os_save()) + return _ao_lisp_atom_t; +#endif + return AO_LISP_NIL; +} + +ao_poly +ao_lisp_restore(struct ao_lisp_cons *cons) +{ + if (!ao_lisp_check_argc(_ao_lisp_atom_save, cons, 0, 0)) + return AO_LISP_NIL; + +#ifdef AO_LISP_SAVE + struct ao_lisp_os_save save; + struct ao_lisp_os_save *os = (struct ao_lisp_os_save *) (void *) &ao_lisp_pool[AO_LISP_POOL]; + + if (!ao_lisp_os_restore_save(&save, AO_LISP_POOL)) + return ao_lisp_error(AO_LISP_INVALID, "header restore failed"); + + if (save.const_checksum != ao_lisp_const_checksum || + save.const_checksum_inv != (uint16_t) ~ao_lisp_const_checksum) + { + return ao_lisp_error(AO_LISP_INVALID, "image is corrupted or stale"); + } + + if (ao_lisp_os_restore()) { + + ao_lisp_atoms = ao_lisp_poly_atom(os->atoms); + ao_lisp_frame_global = ao_lisp_poly_frame(os->globals); + + /* Clear the eval global variabls */ + ao_lisp_eval_clear_globals(); + + /* Reset the allocator */ + ao_lisp_top = AO_LISP_POOL; + ao_lisp_collect(AO_LISP_COLLECT_FULL); + + /* Re-create the evaluator stack */ + if (!ao_lisp_eval_restart()) + return AO_LISP_NIL; + return _ao_lisp_atom_t; + } +#endif + return AO_LISP_NIL; +} diff --git a/src/lisp/ao_lisp_stack.c b/src/lisp/ao_lisp_stack.c new file mode 100644 index 00000000..53adf432 --- /dev/null +++ b/src/lisp/ao_lisp_stack.c @@ -0,0 +1,278 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" + +const struct ao_lisp_type ao_lisp_stack_type; + +static int +stack_size(void *addr) +{ + (void) addr; + return sizeof (struct ao_lisp_stack); +} + +static void +stack_mark(void *addr) +{ + struct ao_lisp_stack *stack = addr; + for (;;) { + ao_lisp_poly_mark(stack->sexprs, 0); + ao_lisp_poly_mark(stack->values, 0); + /* no need to mark values_tail */ + ao_lisp_poly_mark(stack->frame, 0); + ao_lisp_poly_mark(stack->list, 0); + stack = ao_lisp_poly_stack(stack->prev); + if (ao_lisp_mark_memory(&ao_lisp_stack_type, stack)) + break; + } +} + +static void +stack_move(void *addr) +{ + struct ao_lisp_stack *stack = addr; + + while (stack) { + struct ao_lisp_stack *prev; + int ret; + (void) ao_lisp_poly_move(&stack->sexprs, 0); + (void) ao_lisp_poly_move(&stack->values, 0); + (void) ao_lisp_poly_move(&stack->values_tail, 0); + (void) ao_lisp_poly_move(&stack->frame, 0); + (void) ao_lisp_poly_move(&stack->list, 0); + prev = ao_lisp_poly_stack(stack->prev); + if (!prev) + break; + ret = ao_lisp_move_memory(&ao_lisp_stack_type, (void **) &prev); + if (prev != ao_lisp_poly_stack(stack->prev)) + stack->prev = ao_lisp_stack_poly(prev); + if (ret) + break; + stack = prev; + } +} + +const struct ao_lisp_type ao_lisp_stack_type = { + .size = stack_size, + .mark = stack_mark, + .move = stack_move, + .name = "stack" +}; + +struct ao_lisp_stack *ao_lisp_stack_free_list; + +void +ao_lisp_stack_reset(struct ao_lisp_stack *stack) +{ + stack->state = eval_sexpr; + stack->sexprs = AO_LISP_NIL; + stack->values = AO_LISP_NIL; + stack->values_tail = AO_LISP_NIL; +} + +static struct ao_lisp_stack * +ao_lisp_stack_new(void) +{ + struct ao_lisp_stack *stack; + + if (ao_lisp_stack_free_list) { + stack = ao_lisp_stack_free_list; + ao_lisp_stack_free_list = ao_lisp_poly_stack(stack->prev); + } else { + stack = ao_lisp_alloc(sizeof (struct ao_lisp_stack)); + if (!stack) + return 0; + stack->type = AO_LISP_STACK; + } + ao_lisp_stack_reset(stack); + return stack; +} + +int +ao_lisp_stack_push(void) +{ + struct ao_lisp_stack *stack = ao_lisp_stack_new(); + + if (!stack) + return 0; + + stack->prev = ao_lisp_stack_poly(ao_lisp_stack); + stack->frame = ao_lisp_frame_poly(ao_lisp_frame_current); + stack->list = AO_LISP_NIL; + + ao_lisp_stack = stack; + + DBGI("stack push\n"); + DBG_FRAMES(); + DBG_IN(); + return 1; +} + +void +ao_lisp_stack_pop(void) +{ + ao_poly prev; + struct ao_lisp_frame *prev_frame; + + if (!ao_lisp_stack) + return; + prev = ao_lisp_stack->prev; + if (!ao_lisp_stack_marked(ao_lisp_stack)) { + ao_lisp_stack->prev = ao_lisp_stack_poly(ao_lisp_stack_free_list); + ao_lisp_stack_free_list = ao_lisp_stack; + } + + ao_lisp_stack = ao_lisp_poly_stack(prev); + prev_frame = ao_lisp_frame_current; + if (ao_lisp_stack) + ao_lisp_frame_current = ao_lisp_poly_frame(ao_lisp_stack->frame); + else + ao_lisp_frame_current = NULL; + if (ao_lisp_frame_current != prev_frame) + ao_lisp_frame_free(prev_frame); + DBG_OUT(); + DBGI("stack pop\n"); + DBG_FRAMES(); +} + +void +ao_lisp_stack_clear(void) +{ + ao_lisp_stack = NULL; + ao_lisp_frame_current = NULL; + ao_lisp_v = AO_LISP_NIL; +} + +void +ao_lisp_stack_print(ao_poly poly) +{ + struct ao_lisp_stack *s = ao_lisp_poly_stack(poly); + + while (s) { + if (s->type & AO_LISP_STACK_PRINT) { + printf("[recurse...]"); + return; + } + s->type |= AO_LISP_STACK_PRINT; + printf("\t[\n"); + printf("\t\texpr: "); ao_lisp_poly_print(s->list); printf("\n"); + printf("\t\tstate: %s\n", ao_lisp_state_names[s->state]); + ao_lisp_error_poly ("values: ", s->values, s->values_tail); + ao_lisp_error_poly ("sexprs: ", s->sexprs, AO_LISP_NIL); + ao_lisp_error_frame(2, "frame: ", ao_lisp_poly_frame(s->frame)); + printf("\t]\n"); + s->type &= ~AO_LISP_STACK_PRINT; + s = ao_lisp_poly_stack(s->prev); + } +} + +/* + * Copy a stack, being careful to keep everybody referenced + */ +static struct ao_lisp_stack * +ao_lisp_stack_copy(struct ao_lisp_stack *old) +{ + struct ao_lisp_stack *new = NULL; + struct ao_lisp_stack *n, *prev = NULL; + + while (old) { + ao_lisp_stack_stash(0, old); + ao_lisp_stack_stash(1, new); + ao_lisp_stack_stash(2, prev); + n = ao_lisp_stack_new(); + prev = ao_lisp_stack_fetch(2); + new = ao_lisp_stack_fetch(1); + old = ao_lisp_stack_fetch(0); + if (!n) + return NULL; + + ao_lisp_stack_mark(old); + ao_lisp_frame_mark(ao_lisp_poly_frame(old->frame)); + *n = *old; + + if (prev) + prev->prev = ao_lisp_stack_poly(n); + else + new = n; + prev = n; + + old = ao_lisp_poly_stack(old->prev); + } + return new; +} + +/* + * Evaluate a continuation invocation + */ +ao_poly +ao_lisp_stack_eval(void) +{ + struct ao_lisp_stack *new = ao_lisp_stack_copy(ao_lisp_poly_stack(ao_lisp_v)); + if (!new) + return AO_LISP_NIL; + + struct ao_lisp_cons *cons = ao_lisp_poly_cons(ao_lisp_stack->values); + + if (!cons || !cons->cdr) + return ao_lisp_error(AO_LISP_INVALID, "continuation requires a value"); + + new->state = eval_val; + + ao_lisp_stack = new; + ao_lisp_frame_current = ao_lisp_poly_frame(ao_lisp_stack->frame); + + return ao_lisp_poly_cons(cons->cdr)->car; +} + +/* + * Call with current continuation. This calls a lambda, passing + * it a single argument which is the current continuation + */ +ao_poly +ao_lisp_call_cc(struct ao_lisp_cons *cons) +{ + struct ao_lisp_stack *new; + ao_poly v; + + /* Make sure the single parameter is a lambda */ + if (!ao_lisp_check_argc(_ao_lisp_atom_call2fcc, cons, 1, 1)) + return AO_LISP_NIL; + if (!ao_lisp_check_argt(_ao_lisp_atom_call2fcc, cons, 0, AO_LISP_LAMBDA, 0)) + return AO_LISP_NIL; + + /* go get the lambda */ + ao_lisp_v = ao_lisp_arg(cons, 0); + + /* Note that the whole call chain now has + * a reference to it which may escape + */ + new = ao_lisp_stack_copy(ao_lisp_stack); + if (!new) + return AO_LISP_NIL; + + /* re-fetch cons after the allocation */ + cons = ao_lisp_poly_cons(ao_lisp_poly_cons(ao_lisp_stack->values)->cdr); + + /* Reset the arg list to the current stack, + * and call the lambda + */ + + cons->car = ao_lisp_stack_poly(new); + cons->cdr = AO_LISP_NIL; + v = ao_lisp_lambda_eval(); + ao_lisp_stack->sexprs = v; + ao_lisp_stack->state = eval_progn; + return AO_LISP_NIL; +} diff --git a/src/lisp/ao_lisp_string.c b/src/lisp/ao_lisp_string.c new file mode 100644 index 00000000..cd7b27a9 --- /dev/null +++ b/src/lisp/ao_lisp_string.c @@ -0,0 +1,158 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_lisp.h" + +static void string_mark(void *addr) +{ + (void) addr; +} + +static int string_size(void *addr) +{ + if (!addr) + return 0; + return strlen(addr) + 1; +} + +static void string_move(void *addr) +{ + (void) addr; +} + +const struct ao_lisp_type ao_lisp_string_type = { + .mark = string_mark, + .size = string_size, + .move = string_move, + .name = "string", +}; + +char * +ao_lisp_string_copy(char *a) +{ + int alen = strlen(a); + + ao_lisp_string_stash(0, a); + char *r = ao_lisp_alloc(alen + 1); + a = ao_lisp_string_fetch(0); + if (!r) + return NULL; + strcpy(r, a); + return r; +} + +char * +ao_lisp_string_cat(char *a, char *b) +{ + int alen = strlen(a); + int blen = strlen(b); + + ao_lisp_string_stash(0, a); + ao_lisp_string_stash(1, b); + char *r = ao_lisp_alloc(alen + blen + 1); + a = ao_lisp_string_fetch(0); + b = ao_lisp_string_fetch(1); + if (!r) + return NULL; + strcpy(r, a); + strcpy(r+alen, b); + return r; +} + +ao_poly +ao_lisp_string_pack(struct ao_lisp_cons *cons) +{ + int len = ao_lisp_cons_length(cons); + ao_lisp_cons_stash(0, cons); + char *r = ao_lisp_alloc(len + 1); + cons = ao_lisp_cons_fetch(0); + char *s = r; + + while (cons) { + if (ao_lisp_poly_type(cons->car) != AO_LISP_INT) + return ao_lisp_error(AO_LISP_INVALID, "non-int passed to pack"); + *s++ = ao_lisp_poly_int(cons->car); + cons = ao_lisp_poly_cons(cons->cdr); + } + *s++ = 0; + return ao_lisp_string_poly(r); +} + +ao_poly +ao_lisp_string_unpack(char *a) +{ + struct ao_lisp_cons *cons = NULL, *tail = NULL; + int c; + int i; + + for (i = 0; (c = a[i]); i++) { + ao_lisp_cons_stash(0, cons); + ao_lisp_cons_stash(1, tail); + ao_lisp_string_stash(0, a); + struct ao_lisp_cons *n = ao_lisp_cons_cons(ao_lisp_int_poly(c), NULL); + a = ao_lisp_string_fetch(0); + cons = ao_lisp_cons_fetch(0); + tail = ao_lisp_cons_fetch(1); + + if (!n) { + cons = NULL; + break; + } + if (tail) + tail->cdr = ao_lisp_cons_poly(n); + else + cons = n; + tail = n; + } + return ao_lisp_cons_poly(cons); +} + +void +ao_lisp_string_print(ao_poly p) +{ + char *s = ao_lisp_poly_string(p); + char c; + + putchar('"'); + while ((c = *s++)) { + switch (c) { + case '\n': + printf ("\\n"); + break; + case '\r': + printf ("\\r"); + break; + case '\t': + printf ("\\t"); + break; + default: + putchar(c); + break; + } + } + putchar('"'); +} + +void +ao_lisp_string_patom(ao_poly p) +{ + char *s = ao_lisp_poly_string(p); + char c; + + while ((c = *s++)) + putchar(c); +} diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs index bccea5bc..c4521620 100644 --- a/src/lpc/Makefile-lpc.defs +++ b/src/lpc/Makefile-lpc.defs @@ -4,7 +4,7 @@ endif include $(TOPDIR)/Makedefs -vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR):$(TOPDIR)/math +vpath % $(TOPDIR)/lpc:$(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 @@ -26,9 +26,12 @@ endif ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex CC=$(ARM_CC) -WARN_FLAGS=-Wall -Wextra -Werror +WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align + +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers \ + -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math -I$(TOPDIR) \ + $(PDCLIB_INCLUDES) -AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math -I$(TOPDIR) $(PDCLIB_INCLUDES) LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\ -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS) diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 5fc0f680..15106dea 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -109,7 +109,7 @@ ao_arch_memory_barrier() { 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 *sp = (uint32_t *) (void *) (task->stack + AO_STACK_SIZE); uint32_t a = (uint32_t) start; int i; diff --git a/src/nucleao-32/.gitignore b/src/nucleao-32/.gitignore new file mode 100644 index 00000000..cb8f78e5 --- /dev/null +++ b/src/nucleao-32/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +nucleo-32* diff --git a/src/nucleao-32/Makefile b/src/nucleao-32/Makefile new file mode 100644 index 00000000..69049982 --- /dev/null +++ b/src/nucleao-32/Makefile @@ -0,0 +1,93 @@ +# +# AltOS build +# +# + +include ../stmf0/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_lisp.h \ + ao_lisp_const.h \ + stm32f0.h \ + Makefile + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_beep_stm.c \ + ao_dma_stm.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_usb_stm.c \ + ao_serial_stm.c \ + ao_flash_stm.c \ + ao_lisp_atom.c \ + ao_lisp_builtin.c \ + ao_lisp_cons.c \ + ao_lisp_error.c \ + ao_lisp_eval.c \ + ao_lisp_frame.c \ + ao_lisp_int.c \ + ao_lisp_lambda.c \ + ao_lisp_lex.c \ + ao_lisp_mem.c \ + ao_lisp_poly.c \ + ao_lisp_read.c \ + ao_lisp_rep.c \ + ao_lisp_save.c \ + ao_lisp_stack.c \ + ao_lisp_string.c \ + ao_lisp_os_save.c + +PRODUCT=Nucleo-32 +PRODUCT_DEF=-DNUCLEO +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -Os -g + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tload.ld + +PROGNAME=nucleo-32 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_nucleo.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) + stm-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/nucleao-32/ao_nucleo.c b/src/nucleao-32/ao_nucleo.c new file mode 100644 index 00000000..6b4cbaae --- /dev/null +++ b/src/nucleao-32/ao_nucleo.c @@ -0,0 +1,48 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include +#include +#include + +static void lisp_cmd() { + ao_lisp_read_eval_print(); +} + +static void beep() { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +} + +static const struct ao_cmds blink_cmds[] = { + { lisp_cmd, "l\0Run lisp interpreter" }, + { beep, "b\0Beep" }, + { 0, 0 } +}; + +void main(void) +{ + ao_led_init(LEDS_AVAILABLE); + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_dma_init(); + ao_usb_init(); + ao_serial_init(); + ao_beep_init(); + ao_cmd_init(); + ao_cmd_register(blink_cmds); + ao_start_scheduler(); +} + + diff --git a/src/nucleao-32/ao_pins.h b/src/nucleao-32/ao_pins.h new file mode 100644 index 00000000..cee4616f --- /dev/null +++ b/src/nucleao-32/ao_pins.h @@ -0,0 +1,65 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN +#define LED_PORT (&stm_gpiob) +#define LED_PIN_GREEN 3 +#define AO_LED_GREEN (1 << LED_PIN_GREEN) +#define AO_LED_PANIC AO_LED_GREEN +#define AO_CMD_LEN 128 +#define AO_LISP_POOL_TOTAL 3072 +#define AO_LISP_SAVE 1 +#define AO_STACK_SIZE 1024 + +#define LEDS_AVAILABLE (AO_LED_GREEN) + +#define AO_POWER_MANAGEMENT 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 0 +#define AO_PA11_PA12_RMP 0 +#define HAS_BEEP 1 + +#define BEEPER_TIMER 2 +#define BEEPER_CHANNEL 4 +#define BEEPER_PORT (&stm_gpioa) +#define BEEPER_PIN 3 + +#define IS_FLASH_LOADER 0 + +#define HAS_SERIAL_2 1 +#define SERIAL_2_PA2_PA15 1 +#define USE_SERIAL_2_FLOW 0 +#define USE_SERIAL_2_STDIN 1 +#define DELAY_SERIAL_2_STDIN 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/nucleao-32/flash-loader/.gitignore b/src/nucleao-32/flash-loader/.gitignore new file mode 100644 index 00000000..cb8f78e5 --- /dev/null +++ b/src/nucleao-32/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +nucleo-32* diff --git a/src/nucleao-32/flash-loader/Makefile b/src/nucleao-32/flash-loader/Makefile new file mode 100644 index 00000000..2392e998 --- /dev/null +++ b/src/nucleao-32/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=nucleo-32 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/nucleao-32/flash-loader/ao_pins.h b/src/nucleao-32/flash-loader/ao_pins.h new file mode 100644 index 00000000..8bdbdb1a --- /dev/null +++ b/src/nucleao-32/flash-loader/ao_pins.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Pin D3, which is PB0 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiob +#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/pnpservo-v1/Makefile b/src/pnpservo-v1/Makefile new file mode 100644 index 00000000..8606b1ae --- /dev/null +++ b/src/pnpservo-v1/Makefile @@ -0,0 +1,72 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + stm32f0.h \ + Makefile + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_dma_stm.c \ + ao_stdio.c \ + ao_mutex.c \ + ao_panic.c \ + ao_timer.c \ + ao_usb_stm.c \ + ao_flash_stm.c + +PRODUCT=PNPservo-v1 +PRODUCT_DEF=-DPNPSERVO +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) -I. $(STMF0_CFLAGS) -Os -g + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Tlambda.ld + +PROGNAME=pnpservo-v1 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_pnpservo.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) lambda.ld 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) + stm-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/pnpservo-v1/ao_pins.h b/src/pnpservo-v1/ao_pins.h new file mode 100644 index 00000000..38f3d8e5 --- /dev/null +++ b/src/pnpservo-v1/ao_pins.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#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 9 +#define LED_PIN_GREEN 10 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) +#define AO_LED_PANIC AO_LED_RED +#define AO_CMD_LEN 128 +#define AO_LISP_POOL_TOTAL 3072 +#define AO_LISP_SAVE 1 +#define AO_STACK_SIZE 1024 + +/* need HSI active to write to flash */ +#define AO_NEED_HSI 1 + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define AO_POWER_MANAGEMENT 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 0 +#define AO_PA11_PA12_RMP 1 +#define HAS_BEEP 0 + +#define IS_FLASH_LOADER 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/pnpservo-v1/ao_pnpservo.c b/src/pnpservo-v1/ao_pnpservo.c new file mode 100644 index 00000000..d4c2d495 --- /dev/null +++ b/src/pnpservo-v1/ao_pnpservo.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include + +static const struct ao_cmds blink_cmds[] = { +// { lisp_cmd, "l\0Run lisp interpreter" }, + { 0, 0 } +}; + + +void main(void) +{ + ao_led_init(LEDS_AVAILABLE); + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_dma_init(); + ao_usb_init(); + ao_cmd_init(); + ao_cmd_register(blink_cmds); + ao_start_scheduler(); +} + + diff --git a/src/pnpservo-v1/flash-loader/.gitignore b/src/pnpservo-v1/flash-loader/.gitignore new file mode 100644 index 00000000..86ebb7f2 --- /dev/null +++ b/src/pnpservo-v1/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +lambdakey* diff --git a/src/pnpservo-v1/flash-loader/Makefile b/src/pnpservo-v1/flash-loader/Makefile new file mode 100644 index 00000000..3283380c --- /dev/null +++ b/src/pnpservo-v1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=pnpservo-v1 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/pnpservo-v1/flash-loader/ao_pins.h b/src/pnpservo-v1/flash-loader/ao_pins.h new file mode 100644 index 00000000..4b788f67 --- /dev/null +++ b/src/pnpservo-v1/flash-loader/ao_pins.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 15 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/pnpservo-v1/lambda.ld b/src/pnpservo-v1/lambda.ld new file mode 100644 index 00000000..5de65eb5 --- /dev/null +++ b/src/pnpservo-v1/lambda.ld @@ -0,0 +1,117 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08001000, LENGTH = 25K + flash (r): ORIGIN = 0x08007400, LENGTH = 3k + 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 + + /* 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 */ + . = 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)); + + __flash__ = ORIGIN(flash); +} + +ENTRY(start); diff --git a/src/stm-vga/Makefile b/src/stm-vga/Makefile new file mode 100644 index 00000000..46a77272 --- /dev/null +++ b/src/stm-vga/Makefile @@ -0,0 +1,83 @@ +# +# 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_vga.h \ + ao_draw.h \ + ao_draw_int.h \ + ao_font.h \ + ao_ps2.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_boot_chain.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_lcd_stm.c \ + ao_lcd_font.c \ + ao_vga.c \ + ao_blt.c \ + ao_copy.c \ + ao_rect.c \ + ao_text.c \ + ao_line.c \ + ao_mutex.c \ + ao_dma_stm.c \ + ao_adc_stm.c \ + ao_data.c \ + ao_i2c_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_ps2.c \ + ao_console.c + +PRODUCT=StmVga-v0.0 +IDPRODUCT=0x000a + +CFLAGS = $(STM_CFLAGS) -g -Os + +PROG=stm-vga-$(VERSION) +ELF=$(PROG).elf +IHX=$(PROG).ihx + +SRC=$(ALTOS_SRC) ao_demo.c +OBJ=$(SRC:.c=.o) + +all: $(ELF) $(IHX) + +$(ELF): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(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 *.elf *.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/stm-vga/ao_demo.c b/src/stm-vga/ao_demo.c new file mode 100644 index 00000000..1b443b1f --- /dev/null +++ b/src/stm-vga/ao_demo.c @@ -0,0 +1,233 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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. + */ + +#include "ao.h" +#include +#include +#include +#include +#include +#include +#include +#include + +struct ao_task ball_task; +struct ao_task ps2_task; + +#define BALL_WIDTH 5 +#define BALL_HEIGHT 5 + +static int ball_x; +static int ball_y; +static int ball_dx, ball_dy; + +uint8_t ball_enable; + +void +ao_ball(void) +{ + ball_dx = 1; + ball_dy = 1; + ball_x = 0; + ball_y = 0; + for (;;) { + while (!ball_enable) + ao_sleep(&ball_enable); + for (;;) { + ao_line(&ao_vga_bitmap, + -100, -100, ball_x*2, ball_y*2, + 1, AO_XOR); + ao_text(&ao_vga_bitmap, + ball_x, ball_y - 10, + "Hello, Bdale!", + 1, AO_XOR); + ao_rect(&ao_vga_bitmap, + ball_x, ball_y, + BALL_WIDTH, + BALL_HEIGHT, + 1, + AO_XOR); + ao_delay(AO_MS_TO_TICKS(10)); + ao_rect(&ao_vga_bitmap, + ball_x, ball_y, + BALL_WIDTH, + BALL_HEIGHT, + 1, + AO_XOR); + ao_text(&ao_vga_bitmap, + ball_x, ball_y - 10, + "Hello, Bdale!", + 1, AO_XOR); + ao_line(&ao_vga_bitmap, + -100, -100, ball_x*2, ball_y*2, + 1, AO_XOR); + if (!ball_enable) + break; + ball_x += ball_dx; + ball_y += ball_dy; + if (ball_x + BALL_WIDTH > AO_VGA_WIDTH) { + ball_x = AO_VGA_WIDTH - BALL_WIDTH; + ball_dx = -ball_dx; + } + if (ball_x < 0) { + ball_x = -ball_x; + ball_dx = -ball_dx; + } + if (ball_y + BALL_HEIGHT > AO_VGA_HEIGHT) { + ball_y = AO_VGA_HEIGHT - BALL_HEIGHT; + ball_dy = -ball_dy; + } + if (ball_y < 0) { + ball_y = -ball_y; + ball_dy = -ball_dy; + } + } + } +} + +void +ao_ps2(void) +{ + uint8_t leds = 0; + for (;;) { + uint8_t b = ao_ps2_get(); + printf ("%02x\n", b); + flush(); + if (b == 0x14) { + leds ^= 4; + ao_ps2_put(0xed); + if (ao_ps2_get() == 0xfa) + ao_ps2_put(leds); + } + } +} + +static void +ao_fb_init(void) +{ + ao_rect(&ao_vga_bitmap, + 0, 0, AO_VGA_WIDTH, AO_VGA_HEIGHT, + 1, AO_COPY); + + ao_rect(&ao_vga_bitmap, + 10, 10, 10, 10, + 0, AO_COPY); + + ao_rect(&ao_vga_bitmap, + AO_VGA_WIDTH - 20, 10, 10, 10, + 0, AO_COPY); + + ao_rect(&ao_vga_bitmap, + 10, AO_VGA_HEIGHT - 20, 10, 10, + 0, AO_COPY); + + ao_rect(&ao_vga_bitmap, + AO_VGA_WIDTH - 20, AO_VGA_HEIGHT - 20, 10, 10, + 0, AO_COPY); + + ao_text(&ao_vga_bitmap, + 20, 100, + "Hello, Bdale!", + 0, AO_COPY); + + ao_text(&ao_vga_bitmap, + 1, ao_font.ascent, + "UL", + 0, AO_COPY); + + ao_text(&ao_vga_bitmap, + 1, AO_VGA_HEIGHT - ao_font.descent, + "BL", + 0, AO_COPY); +} + +static void +ao_video_toggle(void) +{ + ao_cmd_decimal(); + if (ao_cmd_lex_i) + ao_fb_init(); + ao_vga_enable(ao_cmd_lex_i); +} + +static void +ao_ball_toggle(void) +{ + ao_cmd_decimal(); + ball_enable = ao_cmd_lex_i; + ao_wakeup(&ball_enable); +} + +static void +ao_ps2_read_keys(void) +{ + char c; + + for (;;) { + c = ao_ps2_getchar(); + printf("%02x %c\n", c, ' ' <= c && c < 0x7f ? c : '.'); + flush(); + if (c == ' ') + break; + } +} + +static void +ao_console_send(void) +{ + char c; + + while ((c = getchar()) != '~') { + ao_console_putchar(c); + flush(); + } +} + +__code struct ao_cmds ao_demo_cmds[] = { + { ao_video_toggle, "V\0Toggle video" }, + { ao_ball_toggle, "B\0Toggle ball" }, + { ao_ps2_read_keys, "K\0Read keys from keyboard" }, + { ao_console_send, "C\0Send data to console, end with ~" }, + { 0, NULL } +}; + +int +main(void) +{ + ao_clock_init(); + + ao_task_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_led_off(AO_LED_BLUE); + ao_timer_init(); + ao_dma_init(); + ao_cmd_init(); + ao_vga_init(); + ao_usb_init(); + ao_exti_init(); + ao_ps2_init(); + ao_console_init(); + + ao_add_task(&ball_task, ao_ball, "ball"); + ao_cmd_register(&ao_demo_cmds[0]); + + ao_start_scheduler(); + return 0; +} diff --git a/src/stm-vga/ao_lisp_os.h b/src/stm-vga/ao_lisp_os.h new file mode 100644 index 00000000..1993ac44 --- /dev/null +++ b/src/stm-vga/ao_lisp_os.h @@ -0,0 +1,62 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_LISP_OS_H_ +#define _AO_LISP_OS_H_ + +#include "ao.h" + +static inline int +ao_lisp_getc() { + static uint8_t at_eol; + int c; + + if (at_eol) { + ao_cmd_readline(); + at_eol = 0; + } + c = ao_cmd_lex(); + if (c == '\n') + at_eol = 1; + return c; +} + +static inline void +ao_lisp_os_flush(void) +{ + flush(); +} + +static inline void +ao_lisp_abort(void) +{ + ao_panic(1); +} + +static inline void +ao_lisp_os_led(int led) +{ + ao_led_set(led); +} + +static inline void +ao_lisp_os_delay(int delay) +{ + ao_delay(AO_MS_TO_TICKS(delay)); +} + +#endif diff --git a/src/stm-vga/ao_lisp_os_save.c b/src/stm-vga/ao_lisp_os_save.c new file mode 100644 index 00000000..7c853990 --- /dev/null +++ b/src/stm-vga/ao_lisp_os_save.c @@ -0,0 +1,53 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include +#include +#include + +extern uint8_t __flash__[]; + +/* saved variables to rebuild the heap + + ao_lisp_atoms + ao_lisp_frame_global + */ + +int +ao_lisp_os_save(void) +{ + int i; + + for (i = 0; i < AO_LISP_POOL_TOTAL; i += 256) { + uint32_t *dst = (uint32_t *) (void *) &__flash__[i]; + uint32_t *src = (uint32_t *) (void *) &ao_lisp_pool[i]; + + ao_flash_page(dst, src); + } + return 1; +} + +int +ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset) +{ + memcpy(save, &__flash__[offset], sizeof (struct ao_lisp_os_save)); + return 1; +} + +int +ao_lisp_os_restore(void) +{ + memcpy(ao_lisp_pool, __flash__, AO_LISP_POOL_TOTAL); + return 1; +} diff --git a/src/stm-vga/ao_pins.h b/src/stm-vga/ao_pins.h new file mode 100644 index 00000000..8503c4fd --- /dev/null +++ b/src/stm-vga/ao_pins.h @@ -0,0 +1,219 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* Bridge SB17 on the board and use the MCO from the other chip */ +#define AO_HSE 8000000 +#define AO_HSE_BYPASS 1 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 24MHz */ +#define AO_PLLDIV 4 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_4) + +/* HCLK = 24MHZ (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at HCLK/1 */ +#define AO_APB1_PRESCALER 1 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_1 + +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER 1 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1 + +/* Allow for non-maskable interrupts at priority 0 */ +#define AO_NONMASK_INTERRUPT 1 + +#define HAS_SERIAL_1 0 +#define USE_SERIAL_1_STDIN 0 +#define SERIAL_1_PB6_PB7 1 +#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 1 + +#define HAS_SERIAL_3 0 +#define USE_SERIAL_3_STDIN 1 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 0 +#define SERIAL_3_PD8_PD9 1 + +#define HAS_SPI_1 0 +#define SPI_1_PB3_PB4_PB5 1 +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_SPI_2 0 + +#define HAS_USB 1 +#define HAS_BEEP 0 +#define PACKET_HAS_SLAVE 0 +#define HAS_TASK_QUEUE 1 + +#define CONSOLE_STDIN 1 + +#define AO_STACK_SIZE 1024 + +#define STM_DMA1_3_STOLEN 1 + +#define AO_BOOT_CHAIN 1 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN +#define LED_PORT (&stm_gpiob) +#define LED_PIN_GREEN 7 +#define LED_PIN_BLUE 6 +#define AO_LED_GREEN (1 << LED_PIN_GREEN) +#define AO_LED_BLUE (1 << LED_PIN_BLUE) +#define AO_LED_PANIC AO_LED_BLUE + +#define LEDS_AVAILABLE (AO_LED_BLUE | AO_LED_GREEN) + +#define AO_LCD_STM_SEG_ENABLED_0 ( \ + (1 << 0) | /* PA1 */ \ + (1 << 1) | /* PA2 */ \ + (1 << 2) | /* PA3 */ \ + (0 << 3) | /* PA6 */ \ + (0 << 4) | /* PA7 */ \ + (0 << 5) | /* PB0 */ \ + (0 << 6) | /* PB1 */ \ + (1 << 7) | /* PB3 */ \ + (1 << 8) | /* PB4 */ \ + (1 << 9) | /* PB5 */ \ + (1 << 10) | /* PB10 */ \ + (1 << 11) | /* PB11 */ \ + (1 << 12) | /* PB12 */ \ + (1 << 13) | /* PB13 */ \ + (1 << 14) | /* PB14 */ \ + (1 << 15) | /* PB15 */ \ + (1 << 16) | /* PB8 */ \ + (1 << 17) | /* PA15 */ \ + (1 << 18) | /* PC0 */ \ + (1 << 19) | /* PC1 */ \ + (1 << 20) | /* PC2 */ \ + (1 << 21) | /* PC3 */ \ + (0 << 22) | /* PC4 */ \ + (0 << 23) | /* PC5 */ \ + (1 << 24) | /* PC6 */ \ + (1 << 25) | /* PC7 */ \ + (1 << 26) | /* PC8 */ \ + (1 << 27) | /* PC9 */ \ + (1 << 28) | /* PC10 or PD8 */ \ + (1 << 29) | /* PC11 or PD9 */ \ + (0 << 30) | /* PC12 or PD10 */ \ + (0 << 31)) /* PD2 or PD11 */ + +#define AO_LCD_STM_SEG_ENABLED_1 ( \ + (0 << 0) | /* PD12 */ \ + (0 << 1) | /* PD13 */ \ + (0 << 2) | /* PD14 */ \ + (0 << 3) | /* PD15 */ \ + (0 << 4) | /* PE0 */ \ + (0 << 5) | /* PE1 */ \ + (0 << 6) | /* PE2 */ \ + (0 << 7)) /* PE3 */ + +#define AO_LCD_STM_COM_ENABLED ( \ + (1 << 0) | /* PA8 */ \ + (1 << 1) | /* PA9 */ \ + (1 << 2) | /* PA10 */ \ + (1 << 3) | /* PB9 */ \ + (0 << 4) | /* PC10 */ \ + (0 << 5) | /* PC11 */ \ + (0 << 6)) /* PC12 */ + +#define AO_LCD_28_ON_C 1 + +#define AO_LCD_DUTY STM_LCD_CR_DUTY_STATIC + +#define HAS_ADC 1 + +#define AO_ADC_RING 32 + +struct ao_adc { + uint16_t tick; + int16_t idd; + int16_t temp; + int16_t vref; +}; + +#define AO_ADC_IDD 4 +#define AO_ADC_PIN0_PORT (&stm_gpioa) +#define AO_ADC_PIN0_PIN 4 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN)) +#define AO_ADC_TEMP 16 +#define AO_ADC_VREF 17 + +#define HAS_ADC_TEMP 1 + +#define AO_DATA_RING 32 +#define AO_NUM_ADC 3 + +#define AO_ADC_SQ1 AO_ADC_IDD +#define AO_ADC_SQ2 AO_ADC_TEMP +#define AO_ADC_SQ3 AO_ADC_VREF + +#define HAS_I2C_1 1 +#define I2C_1_PB6_PB7 0 +#define I2C_1_PB8_PB9 1 + +#define HAS_I2C_2 0 +#define I2C_2_PB10_PB11 0 + +#define AO_EVENT 1 + +#define AO_QUADRATURE_COUNT 2 +#define AO_QUADRATURE_MODE AO_EXTI_MODE_PULL_UP + +#define AO_QUADRATURE_0_PORT &stm_gpioc +#define AO_QUADRATURE_0_A 1 +#define AO_QUADRATURE_0_B 0 + +#define AO_QUADRATURE_1_PORT &stm_gpioc +#define AO_QUADRATURE_1_A 3 +#define AO_QUADRATURE_1_B 2 + +#define AO_BUTTON_COUNT 2 +#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_0_PORT &stm_gpioc +#define AO_BUTTON_0 6 + +#define AO_BUTTON_1_PORT &stm_gpioc +#define AO_BUTTON_1 7 + +#define AO_TICK_TYPE uint32_t +#define AO_TICK_SIGNED int32_t + +#define AO_PS2_CLOCK_PORT (&stm_gpioc) +#define AO_PS2_CLOCK_BIT 0 + +#define AO_PS2_DATA_PORT (&stm_gpioc) +#define AO_PS2_DATA_BIT 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 0ba86f5a..66ed4be8 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -1,4 +1,4 @@ -vpath % ../stm:../product:../drivers:../kernel:../util:../kalman:../aes:../math:.. +vpath % ../stm:../product:../drivers:../kernel:../util:../kalman:../aes:../math:../draw:../lisp:.. vpath make-altitude ../util vpath make-kalman ../util vpath kalman.5c ../kalman @@ -26,7 +26,7 @@ LIBS=$(PDCLIB_LIBS_M3) -lgcc WARN_FLAGS=-Wall -Wextra -Werror -AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../math -I.. $(PDCLIB_INCLUDES) +AO_CFLAGS=-I. -I../stm -I../kernel -I../drivers -I../math -I../draw -I../lisp -I.. $(PDCLIB_INCLUDES) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -Wcast-align \ -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS) diff --git a/src/stm/altos-512.ld b/src/stm/altos-512.ld new file mode 100644 index 00000000..78c41685 --- /dev/null +++ b/src/stm/altos-512.ld @@ -0,0 +1,98 @@ +/* + * Copyright © 2017 Keith Packard + * + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08001000, LENGTH = 508K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 81408 + stack (!w) : ORIGIN = 0x20013e00, LENGTH = 512 +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text ORIGIN(rom) : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + + /* 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 */ + *(.rodata*) /* Constants */ + + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > 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); + + diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 0cc29376..5f033b66 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -85,10 +85,6 @@ 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") - - /* * For now, we're running at a weird frequency */ @@ -122,10 +118,21 @@ extern const uint32_t ao_radio_cal; #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 +/* The stm32l implements only 4 bits of the priority fields */ + +#if AO_NONMASK_INTERRUPT +#define AO_STM_NVIC_NONMASK_PRIORITY 0x00 + +/* Set the basepri register to this value to mask all + * non-maskable priorities + */ +#define AO_STM_NVIC_BASEPRI_MASK 0x10 +#endif + +#define AO_STM_NVIC_HIGH_PRIORITY 0x40 +#define AO_STM_NVIC_MED_PRIORITY 0x80 +#define AO_STM_NVIC_LOW_PRIORITY 0xC0 +#define AO_STM_NVIC_CLOCK_PRIORITY 0xf0 void ao_lcd_stm_init(void); diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index a9d0fa34..522059bc 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -202,8 +202,11 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s #define ao_gpio_set_bits(port, bits) stm_gpio_set_bits(port, bits) +#define ao_gpio_set_mask(port, bits, mask) stm_gpio_set_mask(port, bits, mask) + #define ao_gpio_clr_bits(port, bits) stm_gpio_clr_bits(port, bits); +#define ao_gpio_get_all(port) stm_gpio_get_all(port) #define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ @@ -211,6 +214,18 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) +#define ao_enable_output_mask(port,bits,mask) do { \ + ao_enable_port(port); \ + ao_gpio_set_mask(port, bits, mask); \ + ao_set_output_mask(port, mask); \ + } while (0) + +#define AO_OUTPUT_PUSH_PULL STM_OTYPER_PUSH_PULL +#define AO_OUTPUT_OPEN_DRAIN STM_OTYPER_OPEN_DRAIN + +#define ao_gpio_set_output_mode(port,bit,pin,mode) \ + stm_otyper_set(port, pin, mode) + #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); \ @@ -219,36 +234,73 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s else \ stm_pupdr_set(port, bit, STM_PUPDR_NONE); \ } while (0) - + +#define ao_gpio_set_mode_mask(port,mask,mode) do { \ + if (mode == AO_EXTI_MODE_PULL_UP) \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_UP); \ + else if (mode == AO_EXTI_MODE_PULL_DOWN) \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_PULL_DOWN); \ + else \ + stm_pupdr_set_mask(port, mask, STM_PUPDR_NONE); \ + } while (0) + +#define ao_set_input(port, bit) do { \ + stm_moder_set(port, bit, STM_MODER_INPUT); \ + } while (0) + +#define ao_set_output(port, bit, pin, v) do { \ + ao_gpio_set(port, bit, pin, v); \ + stm_moder_set(port, bit, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_set_output_mask(port, mask) do { \ + stm_moder_set_mask(port, mask, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_set_input_mask(port, mask) do { \ + stm_moder_set_mask(port, mask, STM_MODER_INPUT); \ + } while (0) + #define ao_enable_input(port,bit,mode) do { \ ao_enable_port(port); \ - stm_moder_set(port, bit, STM_MODER_INPUT); \ + ao_set_input(port, bit); \ ao_gpio_set_mode(port, bit, mode); \ } while (0) -#define ao_enable_cs(port,bit) do { \ +#define ao_enable_input_mask(port,mask,mode) do { \ + ao_enable_port(port); \ + ao_gpio_set_mode_mask(port, mask, mode); \ + ao_set_input_mask(port, mask); \ + } 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_enable_cs(port,bit) do { \ + ao_enable_port(port); \ + _ao_enable_cs(port, bit); \ + } 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);\ + 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 @@ -345,17 +397,43 @@ extern struct ao_stm_usart ao_stm_usart3; typedef uint32_t ao_arch_irq_t; +static inline void +ao_arch_block_interrupts(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (AO_STM_NVIC_BASEPRI_MASK)); +#else + asm("cpsid i"); +#endif +} + +static inline void +ao_arch_release_interrupts(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (0x0)); +#else + asm("cpsie i"); +#endif +} + static inline uint32_t ao_arch_irqsave(void) { - uint32_t primask; - asm("mrs %0,primask" : "=&r" (primask)); + uint32_t val; +#ifdef AO_NONMASK_INTERRUPTS + asm("mrs %0,basepri" : "=r" (val)); +#else + asm("mrs %0,primask" : "=r" (val)); +#endif ao_arch_block_interrupts(); - return primask; + return val; } static inline void -ao_arch_irqrestore(uint32_t primask) { - asm("msr primask,%0" : : "r" (primask)); +ao_arch_irqrestore(uint32_t basepri) { +#ifdef AO_NONMASK_INTERRUPTS + asm("msr basepri,%0" : : "r" (basepri)); +#else + asm("msr primask,%0" : : "r" (basepri)); +#endif } static inline void @@ -365,10 +443,17 @@ ao_arch_memory_barrier() { static inline void ao_arch_irq_check(void) { +#ifdef AO_NONMASK_INTERRUPTS + uint32_t basepri; + asm("mrs %0,basepri" : "=r" (basepri)); + if (basepri == 0) + ao_panic(AO_PANIC_IRQ); +#else uint32_t primask; - asm("mrs %0,primask" : "=&r" (primask)); + asm("mrs %0,primask" : "=r" (primask)); if ((primask & 1) == 0) ao_panic(AO_PANIC_IRQ); +#endif } #if HAS_TASK @@ -390,7 +475,7 @@ ao_arch_init_stack(struct ao_task *task, void *start) /* APSR */ ARM_PUSH32(sp, 0); - /* PRIMASK with interrupts enabled */ + /* BASEPRI with interrupts enabled */ ARM_PUSH32(sp, 0); task->sp = sp; @@ -404,8 +489,13 @@ static inline void ao_arch_save_regs(void) { asm("mrs r0,apsr"); asm("push {r0}"); +#ifdef AO_NONMASK_INTERRUPTS + /* Save BASEPRI */ + asm("mrs r0,basepri"); +#else /* Save PRIMASK */ asm("mrs r0,primask"); +#endif asm("push {r0}"); } @@ -419,9 +509,15 @@ static inline void ao_arch_restore_stack(void) { /* Switch stacks */ asm("mov sp, %0" : : "r" (ao_cur_task->sp) ); +#ifdef AO_NONMASK_INTERRUPTS + /* Restore BASEPRI */ + asm("pop {r0}"); + asm("msr basepri,r0"); +#else /* Restore PRIMASK */ asm("pop {r0}"); asm("msr primask,r0"); +#endif /* Restore APSR */ asm("pop {r0}"); @@ -463,7 +559,7 @@ static inline void ao_arch_start_scheduler(void) { asm("mrs %0,msp" : "=&r" (sp)); asm("msr psp,%0" : : "r" (sp)); - asm("mrs %0,control" : "=&r" (control)); + asm("mrs %0,control" : "=r" (control)); control |= (1 << 1); asm("msr control,%0" : : "r" (control)); asm("isb"); @@ -474,12 +570,24 @@ static inline void ao_arch_start_scheduler(void) { #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) +static inline void +ao_arch_wait_interrupt(void) { +#ifdef AO_NONMASK_INTERRUPTS + asm( + "dsb\n" /* Serialize data */ + "isb\n" /* Serialize instructions */ + "cpsid i\n" /* Block all interrupts */ + "msr basepri,%0\n" /* Allow all interrupts through basepri */ + "wfi\n" /* Wait for an interrupt */ + "cpsie i\n" /* Allow all interrupts */ + "msr basepri,%1\n" /* Block interrupts through basepri */ + : : "r" (0), "r" (AO_STM_NVIC_BASEPRI_MASK)); +#else + asm("\twfi\n"); + ao_arch_release_interrupts(); + ao_arch_block_interrupts(); +#endif +} #define ao_arch_critical(b) do { \ uint32_t __mask = ao_arch_irqsave(); \ diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 6d779660..962b3acc 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -29,7 +29,6 @@ uint8_t ao_dma_done[NUM_DMA]; static struct ao_dma_config ao_dma_config[NUM_DMA]; static uint8_t ao_dma_allocated[NUM_DMA]; static uint8_t ao_dma_mutex[NUM_DMA]; -static uint8_t ao_dma_active; static void ao_dma_isr(uint8_t index) { @@ -49,12 +48,24 @@ ao_dma_isr(uint8_t index) { void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } void stm_dma1_channel2_isr(void) { ao_dma_isr(STM_DMA_INDEX(2)); } +#ifdef STM_DMA1_3_STOLEN +#define LEAVE_DMA_ON +#else void stm_dma1_channel3_isr(void) { ao_dma_isr(STM_DMA_INDEX(3)); } +#endif void stm_dma1_channel4_isr(void) { ao_dma_isr(STM_DMA_INDEX(4)); } +#ifdef STM_DMA1_5_STOLEN +#define LEAVE_DMA_ON +#else void stm_dma1_channel5_isr(void) { ao_dma_isr(STM_DMA_INDEX(5)); } +#endif void stm_dma1_channel6_isr(void) { ao_dma_isr(STM_DMA_INDEX(6)); } void stm_dma1_channel7_isr(void) { ao_dma_isr(STM_DMA_INDEX(7)); } +#ifndef LEAVE_DMA_ON +static uint8_t ao_dma_active; +#endif + void ao_dma_set_transfer(uint8_t index, volatile void *peripheral, @@ -68,10 +79,12 @@ ao_dma_set_transfer(uint8_t index, ao_dma_mutex[index] = 0xff; } else ao_mutex_get(&ao_dma_mutex[index]); +#ifndef LEAVE_DMA_ON ao_arch_critical( if (ao_dma_active++ == 0) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); ); +#endif stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); stm_dma.channel[index].cndtr = count; stm_dma.channel[index].cpar = peripheral; @@ -96,10 +109,12 @@ void ao_dma_done_transfer(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); +#ifndef LEAVE_DMA_ON ao_arch_critical( if (--ao_dma_active == 0) stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); ); +#endif if (ao_dma_allocated[index]) ao_dma_mutex[index] = 0; else @@ -120,10 +135,12 @@ ao_dma_dump_cmd(void) { int i; +#ifndef LEAVE_DMA_ON ao_arch_critical( if (ao_dma_active++ == 0) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); ); +#endif printf ("isr %08x ifcr%08x\n", stm_dma.isr, stm_dma.ifcr); for (i = 0; i < NUM_DMA; i++) printf("%d: done %d allocated %d mutex %2d ccr %04x cndtr %04x cpar %08x cmar %08x isr %08x\n", @@ -136,10 +153,12 @@ ao_dma_dump_cmd(void) stm_dma.channel[i].cpar, stm_dma.channel[i].cmar, ao_dma_config[i].isr); +#ifndef LEAVE_DMA_ON ao_arch_critical( if (--ao_dma_active == 0) stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); ); +#endif } static const struct ao_cmds ao_dma_cmds[] = { @@ -153,9 +172,27 @@ ao_dma_init(void) { int index; +#ifdef LEAVE_DMA_ON + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); +#endif for (index = 0; index < STM_NUM_DMA; index++) { +#if STM_DMA1_5_STOLEN + if (index == STM_DMA_INDEX(5)) { + ao_dma_allocated[index] = 1; + ao_dma_mutex[index] = 0xff; + continue; + } +#endif +#if STM_DMA1_3_STOLEN + if (index == STM_DMA_INDEX(3)) { + ao_dma_allocated[index] = 1; + ao_dma_mutex[index] = 0xff; + continue; + } +#endif stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); - stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); + stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, + AO_STM_NVIC_MED_PRIORITY); ao_dma_allocated[index] = 0; ao_dma_mutex[index] = 0; } diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 3e0b3e5c..2491b609 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -123,7 +123,7 @@ ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) { (void) gpio; uint32_t mask = 1 << pin; - + if (mode & AO_EXTI_MODE_RISING) stm_exti.rtsr |= mask; else diff --git a/src/stm/ao_flash_stm.c b/src/stm/ao_flash_stm.c index c1648421..38618bbe 100644 --- a/src/stm/ao_flash_stm.c +++ b/src/stm/ao_flash_stm.c @@ -74,11 +74,10 @@ static void __attribute__ ((section(".ramtext"),noinline)) _ao_flash_erase_page(uint32_t *page) { stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE) | (1 << STM_FLASH_PECR_PROG); - + *page = 0x00000000; - while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) - ; + ao_flash_wait_bsy(); } void @@ -101,9 +100,8 @@ _ao_flash_half_page(uint32_t *dst, uint32_t *src) stm_flash.pecr |= (1 << STM_FLASH_PECR_FPRG); stm_flash.pecr |= (1 << STM_FLASH_PECR_PROG); - - while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) - ; + + ao_flash_wait_bsy(); for (i = 0; i < 32; i++) { *dst++ = *src++; diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 29a8f173..59cad495 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -75,6 +75,9 @@ uint8_t ao_i2c_mutex[STM_NUM_I2C]; #if AO_PCLK1 == 16000000 # define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_16_MHZ #endif +#if AO_PCLK1 == 24000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_24_MHZ +#endif #if AO_PCLK1 == 32000000 # define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_32_MHZ #endif diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index db0be992..c625471e 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -444,7 +444,7 @@ ao_serial_init(void) ao_usart_init(&ao_stm_usart1); stm_nvic_set_enable(STM_ISR_USART1_POS); - stm_nvic_set_priority(STM_ISR_USART1_POS, 4); + stm_nvic_set_priority(STM_ISR_USART1_POS, AO_STM_NVIC_MED_PRIORITY); #if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN ao_add_stdio(_ao_serial1_pollchar, ao_serial1_putchar, @@ -500,7 +500,7 @@ ao_serial_init(void) #endif stm_nvic_set_enable(STM_ISR_USART2_POS); - stm_nvic_set_priority(STM_ISR_USART2_POS, 4); + stm_nvic_set_priority(STM_ISR_USART2_POS, AO_STM_NVIC_MED_PRIORITY); #if USE_SERIAL_2_STDIN && !DELAY_SERIAL_2_STDIN ao_add_stdio(_ao_serial2_pollchar, ao_serial2_putchar, @@ -544,7 +544,7 @@ ao_serial_init(void) ao_usart_init(&ao_stm_usart3); stm_nvic_set_enable(STM_ISR_USART3_POS); - stm_nvic_set_priority(STM_ISR_USART3_POS, 4); + stm_nvic_set_priority(STM_ISR_USART3_POS, AO_STM_NVIC_MED_PRIORITY); #if USE_SERIAL_3_STDIN && !DELAY_SERIAL_3_STDIN ao_add_stdio(_ao_serial3_pollchar, ao_serial3_putchar, diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index f86a5116..1576a6c9 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -90,6 +90,7 @@ ao_timer_init(void) stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) | (1 << STM_SYSTICK_CSR_TICKINT) | (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE)); + stm_nvic.shpr15_12 |= AO_STM_NVIC_CLOCK_PRIORITY << 24; } #endif diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 9d72844e..33e0617c 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -1015,7 +1015,7 @@ ao_usb_enable(void) ao_arch_block_interrupts(); /* Route interrupts */ - stm_nvic_set_priority(STM_ISR_USB_LP_POS, 3); + stm_nvic_set_priority(STM_ISR_USB_LP_POS, AO_STM_NVIC_LOW_PRIORITY); stm_nvic_set_enable(STM_ISR_USB_LP_POS); ao_usb_configuration = 0; @@ -1109,7 +1109,7 @@ struct ao_usb_dbg { int line; char *msg; uint32_t value; - uint32_t primask; + uint32_t prival; #if TX_DBG uint16_t in_count; uint32_t in_epr; @@ -1125,19 +1125,23 @@ struct ao_usb_dbg { #endif }; -#define NUM_USB_DBG 128 +#define NUM_USB_DBG 16 -static struct ao_usb_dbg dbg[128]; +static struct ao_usb_dbg dbg[NUM_USB_DBG]; static int dbg_i; static void _dbg(int line, char *msg, uint32_t value) { - uint32_t primask; + uint32_t prival; 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 AO_NONMASK_INTERRUPT + asm("mrs %0,basepri" : "=&r" (prival)); +#else + asm("mrs %0,primask" : "=&r" (prival)); +#endif + dbg[dbg_i].prival = prival; #if TX_DBG dbg[dbg_i].in_count = in_count; dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR]; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index be1e1d65..201f4f36 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -52,7 +52,32 @@ stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) { ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) | value << STM_MODER_SHIFT(pin)); } - + +static inline uint32_t +stm_spread_mask(uint16_t mask) { + uint32_t m = mask; + + /* 0000000000000000mmmmmmmmmmmmmmmm */ + m = (m & 0xff) | ((m & 0xff00) << 8); + /* 00000000mmmmmmmm00000000mmmmmmmm */ + m = (m & 0x000f000f) | ((m & 0x00f000f0) << 4); + /* 0000mmmm0000mmmm0000mmmm0000mmmm */ + m = (m & 0x03030303) | ((m & 0x0c0c0c0c) << 2); + /* 00mm00mm00mm00mm00mm00mm00mm00mm */ + m = (m & 0x11111111) | ((m & 0x22222222) << 2); + /* 0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m0m */ + return m; +} + +static inline void +stm_moder_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->moder = ((gpio->moder & ~mask32) | value32); +} + static inline uint32_t stm_moder_get(struct stm_gpio *gpio, int pin) { return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK; @@ -69,7 +94,7 @@ stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) { ~(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; @@ -83,12 +108,21 @@ stm_otyper_get(struct stm_gpio *gpio, int pin) { #define STM_OSPEEDR_40MHz 3 static inline void -stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { +stm_ospeedr_set(struct stm_gpio *gpio, int pin, uint32_t value) { gpio->ospeedr = ((gpio->ospeedr & ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) | value << STM_OSPEEDR_SHIFT(pin)); } - + +static inline void +stm_ospeedr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->ospeedr = ((gpio->ospeedr & ~mask32) | value32); +} + static inline uint32_t stm_ospeedr_get(struct stm_gpio *gpio, int pin) { return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK; @@ -107,7 +141,16 @@ stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) { ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | value << STM_PUPDR_SHIFT(pin)); } - + +static inline void +stm_pupdr_set_mask(struct stm_gpio *gpio, uint16_t mask, uint32_t value) { + uint32_t bits32 = stm_spread_mask(mask); + uint32_t mask32 = 3 * bits32; + uint32_t value32 = (value & 3) * bits32; + + gpio->pupdr = (gpio->pupdr & ~mask32) | value32; +} + static inline uint32_t stm_pupdr_get(struct stm_gpio *gpio, int pin) { return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; @@ -167,6 +210,12 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); } +static inline void +stm_gpio_set_mask(struct stm_gpio *gpio, uint16_t bits, uint16_t mask) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = ((uint32_t) (~bits & mask) << 16) | ((uint32_t) (bits & mask)); +} + static inline void stm_gpio_set_bits(struct stm_gpio *gpio, uint16_t bits) { gpio->bsrr = bits; @@ -518,7 +567,7 @@ extern struct stm_rcc stm_rcc; #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_MASK 7 +#define STM_RCC_CFGR_MCOPRE_MASK 7 #define STM_RCC_CFGR_MCOSEL (24) #define STM_RCC_CFGR_MCOSEL_DISABLE 0 @@ -897,7 +946,11 @@ struct stm_nvic { vuint32_t sc; /* 0xc10 0xe000ed10 System Control Register */ vuint32_t cc; /* 0xc14 0xe000ed14 Configuration Control Register */ - uint8_t _unusedc18[0xe00 - 0xc18]; + vuint32_t shpr7_4; /* 0xc18 0xe000ed18 System Hander Priority Registers */ + vuint32_t shpr11_8; /* 0xc1c */ + vuint32_t shpr15_12; /* 0xc20 */ + + uint8_t _unusedc18[0xe00 - 0xc24]; vuint32_t stir; /* 0xe00 */ }; @@ -1594,6 +1647,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2; #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_24_MHZ 24 #define STM_I2C_CR2_FREQ_32_MHZ 32 #define STM_I2C_CR2_FREQ_MASK 0x3f @@ -1740,6 +1794,12 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7 #define STM_TIM234_SMCR_SMS_MASK 7 +#define STM_TIM234_DIER_CC4IE 4 +#define STM_TIM234_DIER_CC3IE 3 +#define STM_TIM234_DIER_CC2IE 2 +#define STM_TIM234_DIER_CC1IE 1 +#define STM_TIM234_DIER_UIE 0 + #define STM_TIM234_SR_CC4OF 12 #define STM_TIM234_SR_CC3OF 11 #define STM_TIM234_SR_CC2OF 10 @@ -1840,15 +1900,23 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_CCER_CC4NP 15 #define STM_TIM234_CCER_CC4P 13 +#define STM_TIM234_CCER_CC4P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC4P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC4E 12 #define STM_TIM234_CCER_CC3NP 11 #define STM_TIM234_CCER_CC3P 9 +#define STM_TIM234_CCER_CC3P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC3P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC3E 8 #define STM_TIM234_CCER_CC2NP 7 #define STM_TIM234_CCER_CC2P 5 +#define STM_TIM234_CCER_CC2P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC2P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC2E 4 #define STM_TIM234_CCER_CC1NP 3 #define STM_TIM234_CCER_CC1P 1 +#define STM_TIM234_CCER_CC1P_ACTIVE_HIGH 0 +#define STM_TIM234_CCER_CC1P_ACTIVE_LOW 1 #define STM_TIM234_CCER_CC1E 0 struct stm_usb { diff --git a/src/stmf0/Makefile-stmf0.defs b/src/stmf0/Makefile-stmf0.defs index f3296b69..f2c53499 100644 --- a/src/stmf0/Makefile-stmf0.defs +++ b/src/stmf0/Makefile-stmf0.defs @@ -4,7 +4,7 @@ endif include $(TOPDIR)/Makedefs -vpath % $(TOPDIR)/stmf0:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR):$(TOPDIR)/math +vpath % $(TOPDIR)/stmf0:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR)/aes:$(TOPDIR):$(TOPDIR)/math:$(TOPDIR)/lisp vpath make-altitude $(TOPDIR)/util vpath make-kalman $(TOPDIR)/util vpath kalman.5c $(TOPDIR)/kalman @@ -27,7 +27,10 @@ CC=$(ARM_CC) WARN_FLAGS=-Wall -Wextra -Werror -Wcast-align -AO_CFLAGS=-I. -I$(TOPDIR)/stmf0 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math $(PDCLIB_INCLUDES) +AO_CFLAGS=-I. -I$(TOPDIR)/stmf0 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers \ + -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math -I$(TOPDIR)/lisp \ + $(PDCLIB_INCLUDES) + STMF0_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\ -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS) diff --git a/src/stmf0/altos-raw.ld b/src/stmf0/altos-raw.ld new file mode 100644 index 00000000..eb285e07 --- /dev/null +++ b/src/stmf0/altos-raw.ld @@ -0,0 +1,85 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K + 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 : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + } > rom + + .text ORIGIN(rom) + 0x100 : { + + /* 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__ = .; + + /* 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); + + diff --git a/src/stmf0/altos.ld b/src/stmf0/altos.ld index 8f8933c6..74fdf3ea 100644 --- a/src/stmf0/altos.ld +++ b/src/stmf0/altos.ld @@ -55,10 +55,16 @@ SECTIONS { ao_product.o(.romconfig*) *(.text*) /* Executable code */ + } > rom + + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) - *(.rodata*) /* Constants */ + } > rom + .rodata : { + *(.rodata*) /* Constants */ } > rom + __text_end__ = .; /* Boot data which must live at the start of ram so that diff --git a/src/stmf0/ao_adc_stm.c b/src/stmf0/ao_adc_stm.c new file mode 100644 index 00000000..2b23dc50 --- /dev/null +++ b/src/stmf0/ao_adc_stm.c @@ -0,0 +1,340 @@ +/* + * Copyright © 2015 Keith Packard + * + * 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 +#include + +#define AO_ADC_DEBUG 0 + +static uint8_t ao_adc_ready; + +/* + * Callback from DMA ISR + * + * Mark time in ring, shut down DMA engine + */ +static void ao_adc_done(int index) +{ + (void) index; + /* Clear ISR bits */ + stm_adc.isr = ((1 << STM_ADC_ISR_AWD) | + (1 << STM_ADC_ISR_OVR) | + (1 << STM_ADC_ISR_EOSEQ) | + (1 << STM_ADC_ISR_EOC)); + + AO_DATA_PRESENT(AO_DATA_ADC); + ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); + if (ao_data_present == AO_DATA_ALL) { +#if HAS_MS5607 + ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; +#endif +#if HAS_MMA655X + ao_data_ring[ao_data_head].mma655x = ao_mma655x_current; +#endif +#if HAS_HMC5883 + ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; +#endif +#if HAS_MPU6000 + ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; +#endif + ao_data_ring[ao_data_head].tick = ao_tick_count; + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); + } + ao_adc_ready = 1; +} + +/* + * Start the ADC sequence using the DMA engine + */ +void +ao_adc_poll(void) +{ + if (!ao_adc_ready) + return; + ao_adc_ready = 0; + stm_adc.isr = 0; + ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), + &stm_adc.dr, + (void *) (&ao_data_ring[ao_data_head].adc), + AO_NUM_ADC, + (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) | + (1 << STM_DMA_CCR_TCIE)); + ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_done); + ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); + + stm_adc.cr |= (1 << STM_ADC_CR_ADSTART); +} + +static void +ao_adc_dump(void) +{ + struct ao_data packet; + + ao_data_get(&packet); + AO_ADC_DUMP(&packet); +} + +#if AO_ADC_DEBUG +static void +ao_adc_one(void) +{ + int ch; + uint16_t value; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ch = ao_cmd_lex_i; + if (ch < 0 || AO_NUM_ADC <= ch) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + + ao_timer_set_adc_interval(0); + ao_delay(1); + + printf("At top, data %u isr %04x cr %04x\n", stm_adc.dr, stm_adc.isr, stm_adc.cr); + + if (stm_adc.cr & (1 << STM_ADC_CR_ADEN)) { + printf("Disabling\n"); flush(); + stm_adc.cr |= (1 << STM_ADC_CR_ADDIS); + while (stm_adc.cr & (1 << STM_ADC_CR_ADDIS)) + ; + printf("Disabled\n"); flush(); + } + + /* Turn off everything */ + stm_adc.cr &= ~((1 << STM_ADC_CR_ADCAL) | + (1 << STM_ADC_CR_ADSTP) | + (1 << STM_ADC_CR_ADSTART) | + (1 << STM_ADC_CR_ADEN)); + + printf("After disable, ADC status %04x\n", stm_adc.cr); + + /* Configure */ + stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) | /* analog watchdog channel 0 */ + (0 << STM_ADC_CFGR1_AWDEN) | /* Disable analog watchdog */ + (0 << STM_ADC_CFGR1_AWDSGL) | /* analog watchdog on all channels */ + (0 << STM_ADC_CFGR1_DISCEN) | /* Not discontinuous mode. All channels converted with one trigger */ + (0 << STM_ADC_CFGR1_AUTOOFF) | /* Leave ADC running */ + (1 << STM_ADC_CFGR1_WAIT) | /* Wait for data to be read before next conversion */ + (0 << STM_ADC_CFGR1_CONT) | /* only one set of conversions per trigger */ + (1 << STM_ADC_CFGR1_OVRMOD) | /* overwrite on overrun */ + (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) | /* SW trigger */ + (0 << STM_ADC_CFGR1_ALIGN) | /* Align to LSB */ + (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) | /* 12 bit resolution */ + (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) | /* scan 0 .. n */ + (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) | /* one set of conversions then stop */ + (0 << STM_ADC_CFGR1_DMAEN)); /* disable DMA */ + + stm_adc.chselr = (1 << ch); + + /* Longest sample time */ + stm_adc.smpr = STM_ADC_SMPR_SMP_41_5 << STM_ADC_SMPR_SMP; + + printf("Before enable, ADC status %04x\n", stm_adc.cr); flush(); + /* Enable */ + stm_adc.cr |= (1 << STM_ADC_CR_ADEN); + while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0) + ; + + /* Start */ + stm_adc.cr |= (1 << STM_ADC_CR_ADSTART); + + /* Wait for conversion complete */ + while (!(stm_adc.isr & (1 << STM_ADC_ISR_EOC))) + ; + + value = stm_adc.dr; + printf ("value %u, cr is %04x isr is %04x\n", + value, stm_adc.cr, stm_adc.isr); + + + /* Clear ISR bits */ + stm_adc.isr = ((1 << STM_ADC_ISR_AWD) | + (1 << STM_ADC_ISR_OVR) | + (1 << STM_ADC_ISR_EOSEQ) | + (1 << STM_ADC_ISR_EOC)); +} +#endif + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, +#if AO_ADC_DEBUG + { ao_adc_one, "A ch\0Display one ADC channel" }, +#endif + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ + uint32_t chselr; + + /* 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); + stm_pupdr_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_PUPDR_NONE); +#endif +#ifdef AO_ADC_PIN1_PORT + stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); + stm_pupdr_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_PUPDR_NONE); +#endif +#ifdef AO_ADC_PIN2_PORT + stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); + stm_pupdr_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_PUPDR_NONE); +#endif +#ifdef AO_ADC_PIN3_PORT + stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); + stm_pupdr_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_PUPDR_NONE); +#endif +#ifdef AO_ADC_PIN4_PORT + stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); + stm_pupdr_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_PUPDR_NONE); +#endif +#ifdef AO_ADC_PIN5_PORT + stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); + stm_pupdr_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_PUPDR_NONE); +#endif +#ifdef AO_ADC_PIN6_PORT + stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); + stm_pupdr_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_PUPDR_NONE); +#endif +#ifdef AO_ADC_PIN7_PORT + stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); + stm_pupdr_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_PUPDR_NONE); +#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 + + /* Wait for ADC to be idle */ + while (stm_adc.cr & ((1 << STM_ADC_CR_ADCAL) | + (1 << STM_ADC_CR_ADDIS))) + ; + + /* Disable */ + if (stm_adc.cr & (1 << STM_ADC_CR_ADEN)) { + stm_adc.cr |= (1 << STM_ADC_CR_ADDIS); + while (stm_adc.cr & (1 << STM_ADC_CR_ADDIS)) + ; + } + + /* Turn off everything */ + stm_adc.cr &= ~((1 << STM_ADC_CR_ADCAL) | + (1 << STM_ADC_CR_ADSTP) | + (1 << STM_ADC_CR_ADSTART) | + (1 << STM_ADC_CR_ADEN)); + + /* Configure */ + stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) | /* analog watchdog channel 0 */ + (0 << STM_ADC_CFGR1_AWDEN) | /* Disable analog watchdog */ + (0 << STM_ADC_CFGR1_AWDSGL) | /* analog watchdog on all channels */ + (0 << STM_ADC_CFGR1_DISCEN) | /* Not discontinuous mode. All channels converted with one trigger */ + (0 << STM_ADC_CFGR1_AUTOOFF) | /* Leave ADC running */ + (1 << STM_ADC_CFGR1_WAIT) | /* Wait for data to be read before next conversion */ + (0 << STM_ADC_CFGR1_CONT) | /* only one set of conversions per trigger */ + (1 << STM_ADC_CFGR1_OVRMOD) | /* overwrite on overrun */ + (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) | /* SW trigger */ + (0 << STM_ADC_CFGR1_ALIGN) | /* Align to LSB */ + (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) | /* 12 bit resolution */ + (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) | /* scan 0 .. n */ + (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) | /* one set of conversions then stop */ + (1 << STM_ADC_CFGR1_DMAEN)); /* enable DMA */ + + /* 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_71_5 << STM_ADC_SMPR_SMP; + + stm_adc.chselr = chselr; + + stm_adc.ccr = ((0 << STM_ADC_CCR_VBATEN) | + (0 << STM_ADC_CCR_TSEN) | + (0 << STM_ADC_CCR_VREFEN)); + + /* Calibrate */ + stm_adc.cr |= (1 << STM_ADC_CR_ADCAL); + while ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) != 0) + ; + + /* Enable */ + stm_adc.cr |= (1 << STM_ADC_CR_ADEN); + while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 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_cmd_register(&ao_adc_cmds[0]); + + ao_adc_ready = 1; +} diff --git a/src/stmf0/ao_arch.h b/src/stmf0/ao_arch.h index a36482b6..c5f451f5 100644 --- a/src/stmf0/ao_arch.h +++ b/src/stmf0/ao_arch.h @@ -144,10 +144,15 @@ ao_adc_init(); /* ADC maximum reported value */ #define AO_ADC_MAX 4095 +#ifndef HAS_BOOT_LOADER +#define HAS_BOOT_LOADER 1 +#endif + +#if HAS_BOOT_LOADER #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 #endif /* _AO_ARCH_H_ */ diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 0cb0e43d..c38ce41a 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -314,7 +314,18 @@ struct ao_stm_usart { struct ao_fifo rx_fifo; struct ao_fifo tx_fifo; struct stm_usart *reg; - uint8_t tx_started; + uint8_t tx_running; + uint8_t draining; +#if HAS_SERIAL_SW_FLOW + /* RTS - 0 if we have FIFO space, 1 if not + * CTS - 0 if we can send, 0 if not + */ + struct stm_gpio *gpio_rts; + struct stm_gpio *gpio_cts; + uint8_t pin_rts; + uint8_t pin_cts; + uint8_t rts; +#endif }; #if HAS_SERIAL_1 diff --git a/src/stmf0/ao_beep_stm.c b/src/stmf0/ao_beep_stm.c new file mode 100644 index 00000000..610f4a31 --- /dev/null +++ b/src/stmf0/ao_beep_stm.c @@ -0,0 +1,389 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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" + +#ifndef BEEPER_CHANNEL +#error BEEPER_CHANNEL undefined +#endif + +#ifndef BEEPER_TIMER +#define BEEPER_TIMER 1 +#endif + +#if BEEPER_TIMER == 1 +#define timer stm_tim1 +#define STM_RCC_TIMER STM_RCC_APB2ENR_TIM1EN +#define stm_rcc_enr stm_rcc.apb2enr +#endif + +#if BEEPER_TIMER == 2 +#define timer stm_tim2 +#define STM_RCC_TIMER STM_RCC_APB1ENR_TIM2EN +#define stm_rcc_enr stm_rcc.apb1enr +#endif + +#if BEEPER_TIMER == 3 +#define timer stm_tim3 +#define STM_RCC_TIMER STM_RCC_APB1ENR_TIM3EN +#define stm_rcc_enr stm_rcc.apb1enr +#endif + +#ifndef timer +#error BEEPER_TIMER invalid +#endif + +static inline void +disable(void) +{ + timer.cr1 = 0; +#if BEEPER_TIMER == 1 + timer.bdtr = 0; +#endif + stm_rcc_enr &= ~(1 << STM_RCC_TIMER); + + /* Disconnect the timer from the pin */ + stm_afr_set(BEEPER_PORT, BEEPER_PIN, STM_AFR_NONE); +} + +void +ao_beep(uint8_t beep) +{ + if (beep == 0) { + disable(); + } else { + stm_rcc_enr |= (1 << STM_RCC_TIMER); + +#if BEEPER_TIMER == 1 + /* Master output enable */ + stm_tim1.bdtr = (1 << STM_TIM1_BDTR_MOE); + + stm_tim1.cr2 = ((0 << STM_TIM1_CR2_TI1S) | + (STM_TIM1_CR2_MMS_RESET << STM_TIM1_CR2_MMS) | + (0 << STM_TIM1_CR2_CCDS)); + + /* Set prescaler to match cc1111 clocks + */ + stm_tim1.psc = AO_TIM_CLK / 750000; + + /* 1. Select the counter clock (internal, external, prescaler). + * + * Setting SMCR to zero means use the internal clock + */ + + stm_tim1.smcr = 0; + + /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */ + stm_tim1.arr = beep; + stm_tim1.ccr1 = beep; + + /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a + * DMA request is to be generated. + */ + /* don't want this */ + + /* 4. Select the output mode. For example, you must write + * OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output + * pin when CNT matches CCRx, CCRx preload is not used, OCx + * is enabled and active high. + */ + +#if BEEPER_CHANNEL == 1 + stm_tim1.ccmr1 = ((0 << STM_TIM1_CCMR1_OC2CE) | + (STM_TIM1_CCMR_OCM_FROZEN << STM_TIM1_CCMR1_OC2M) | + (0 << STM_TIM1_CCMR1_OC2PE) | + (0 << STM_TIM1_CCMR1_OC2FE) | + (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC2S) | + + (0 << STM_TIM1_CCMR1_OC1CE) | + (STM_TIM1_CCMR_OCM_TOGGLE << STM_TIM1_CCMR1_OC1M) | + (0 << STM_TIM1_CCMR1_OC1PE) | + (0 << STM_TIM1_CCMR1_OC1FE) | + (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC1S)); + + stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4P) | + (0 << STM_TIM1_CCER_CC4E) | + (0 << STM_TIM1_CCER_CC3NP) | + (0 << STM_TIM1_CCER_CC3NE) | + (0 << STM_TIM1_CCER_CC3P) | + (0 << STM_TIM1_CCER_CC3E) | + (0 << STM_TIM1_CCER_CC2NP) | + (0 << STM_TIM1_CCER_CC2NE) | + (0 << STM_TIM1_CCER_CC2P) | + (0 << STM_TIM1_CCER_CC2E) | + (0 << STM_TIM1_CCER_CC1NE) | + (0 << STM_TIM1_CCER_CC1P) | + (1 << STM_TIM1_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 2 + stm_tim1.ccmr1 = ((0 << STM_TIM1_CCMR1_OC2CE) | + (STM_TIM1_CCMR_OCM_TOGGLE << STM_TIM1_CCMR1_OC2M) | + (0 << STM_TIM1_CCMR1_OC2PE) | + (0 << STM_TIM1_CCMR1_OC2FE) | + (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC2S) | + + (0 << STM_TIM1_CCMR1_OC1CE) | + (STM_TIM1_CCMR_OCM_FROZEN << STM_TIM1_CCMR1_OC1M) | + (0 << STM_TIM1_CCMR1_OC1PE) | + (0 << STM_TIM1_CCMR1_OC1FE) | + (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR1_CC1S)); + + stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4P) | + (0 << STM_TIM1_CCER_CC4E) | + (0 << STM_TIM1_CCER_CC3NP) | + (0 << STM_TIM1_CCER_CC3NE) | + (0 << STM_TIM1_CCER_CC3P) | + (0 << STM_TIM1_CCER_CC3E) | + (0 << STM_TIM1_CCER_CC2NP) | + (0 << STM_TIM1_CCER_CC2NE) | + (0 << STM_TIM1_CCER_CC2P) | + (1 << STM_TIM1_CCER_CC2E) | + (0 << STM_TIM1_CCER_CC1NE) | + (0 << STM_TIM1_CCER_CC1P) | + (0 << STM_TIM1_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 3 + stm_tim1.ccmr2 = ((0 << STM_TIM1_CCMR2_OC4CE) | + (STM_TIM1_CCMR_OCM_FROZEN << STM_TIM1_CCMR2_OC4M) | + (0 << STM_TIM1_CCMR2_OC4PE) | + (0 << STM_TIM1_CCMR2_OC4FE) | + (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR2_CC4S) | + + (0 << STM_TIM1_CCMR2_OC3CE) | + (STM_TIM1_CCMR_OCM_TOGGLE << STM_TIM1_CCMR2_OC3M) | + (0 << STM_TIM1_CCMR2_OC3PE) | + (0 << STM_TIM1_CCMR2_OC3FE) | + (STM_TIM1_CCMR_CCS_OUTPUT << STM_TIM1_CCMR2_CC3S)); + + stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4P) | + (0 << STM_TIM1_CCER_CC4E) | + (0 << STM_TIM1_CCER_CC3NP) | + (0 << STM_TIM1_CCER_CC3NE) | + (0 << STM_TIM1_CCER_CC3P) | + (1 << STM_TIM1_CCER_CC3E) | + (0 << STM_TIM1_CCER_CC2NP) | + (0 << STM_TIM1_CCER_CC2NE) | + (0 << STM_TIM1_CCER_CC2P) | + (0 << STM_TIM1_CCER_CC2E) | + (0 << STM_TIM1_CCER_CC1NE) | + (0 << STM_TIM1_CCER_CC1P) | + (0 << STM_TIM1_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 4 + stm_tim1.ccmr2 = ((0 << STM_TIM1_CCMR2_OC4CE) | + (STM_TIM1_CCMR2_OC4M_TOGGLE << STM_TIM1_CCMR2_OC4M) | + (0 << STM_TIM1_CCMR2_OC4PE) | + (0 << STM_TIM1_CCMR2_OC4FE) | + (STM_TIM1_CCMR2_CC4S_OUTPUT << STM_TIM1_CCMR2_CC4S) | + + (0 << STM_TIM1_CCMR2_OC3CE) | + (STM_TIM1_CCMR2_OC3M_FROZEN << STM_TIM1_CCMR2_OC3M) | + (0 << STM_TIM1_CCMR2_OC3PE) | + (0 << STM_TIM1_CCMR2_OC3FE) | + (STM_TIM1_CCMR2_CC3S_OUTPUT << STM_TIM1_CCMR2_CC3S)); + + stm_tim1.ccer = ((0 << STM_TIM1_CCER_CC4NP) | + (0 << STM_TIM1_CCER_CC4P) | + (1 << STM_TIM1_CCER_CC4E) | + (0 << STM_TIM1_CCER_CC3NP) | + (0 << STM_TIM1_CCER_CC3P) | + (0 << STM_TIM1_CCER_CC3E) | + (0 << STM_TIM1_CCER_CC2NP) | + (0 << STM_TIM1_CCER_CC2P) | + (0 << STM_TIM1_CCER_CC2E) | + (0 << STM_TIM1_CCER_CC1NP) | + (0 << STM_TIM1_CCER_CC1P) | + (0 << STM_TIM1_CCER_CC1E)); +#endif + /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */ + + stm_tim1.cr1 = ((STM_TIM1_CR1_CKD_1 << STM_TIM1_CR1_CKD) | + (0 << STM_TIM1_CR1_ARPE) | + (STM_TIM1_CR1_CMS_EDGE << STM_TIM1_CR1_CMS) | + (0 << STM_TIM1_CR1_DIR) | + (0 << STM_TIM1_CR1_OPM) | + (0 << STM_TIM1_CR1_URS) | + (0 << STM_TIM1_CR1_UDIS) | + (1 << STM_TIM1_CR1_CEN)); + + /* Update the values */ + stm_tim1.egr = (1 << STM_TIM1_EGR_UG); +#endif +#if BEEPER_TIMER == 2 || BEEPER_TIMER == 3 + + timer.cr2 = ((0 << STM_TIM23_CR2_TI1S) | + (STM_TIM23_CR2_MMS_RESET << STM_TIM23_CR2_MMS) | + (0 << STM_TIM23_CR2_CCDS)); + + /* Set prescaler to match cc1111 clocks + */ + timer.psc = AO_TIM_CLK / 750000; + + /* 1. Select the counter clock (internal, external, prescaler). + * + * Setting SMCR to zero means use the internal clock + */ + + timer.smcr = 0; + + /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */ + timer.arr = beep; + timer.ccr1 = beep; + + /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a + * DMA request is to be generated. + */ + /* don't want this */ + + /* 4. Select the output mode. For example, you must write + * OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output + * pin when CNT matches CCRx, CCRx preload is not used, OCx + * is enabled and active high. + */ + +#if BEEPER_CHANNEL == 1 + timer.ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) | + (STM_TIM23_CCMR1_OC2M_FROZEN << STM_TIM23_CCMR1_OC2M) | + (0 << STM_TIM23_CCMR1_OC2PE) | + (0 << STM_TIM23_CCMR1_OC2FE) | + (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) | + + (0 << STM_TIM23_CCMR1_OC1CE) | + (STM_TIM23_CCMR1_OC1M_TOGGLE << STM_TIM23_CCMR1_OC1M) | + (0 << STM_TIM23_CCMR1_OC1PE) | + (0 << STM_TIM23_CCMR1_OC1FE) | + (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S)); + + timer.ccer = ((0 << STM_TIM23_CCER_CC4P) | + (0 << STM_TIM23_CCER_CC4E) | + (0 << STM_TIM23_CCER_CC3NP) | + (0 << STM_TIM23_CCER_CC3P) | + (0 << STM_TIM23_CCER_CC3E) | + (0 << STM_TIM23_CCER_CC2NP) | + (0 << STM_TIM23_CCER_CC2P) | + (0 << STM_TIM23_CCER_CC2E) | + (0 << STM_TIM23_CCER_CC1P) | + (1 << STM_TIM23_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 2 + timer.ccmr1 = ((0 << STM_TIM23_CCMR1_OC2CE) | + (STM_TIM23_CCMR1_OC2M_TOGGLE << STM_TIM23_CCMR1_OC2M) | + (0 << STM_TIM23_CCMR1_OC2PE) | + (0 << STM_TIM23_CCMR1_OC2FE) | + (STM_TIM23_CCMR1_CC2S_OUTPUT << STM_TIM23_CCMR1_CC2S) | + + (0 << STM_TIM23_CCMR1_OC1CE) | + (STM_TIM23_CCMR1_OC1M_FROZEN << STM_TIM23_CCMR1_OC1M) | + (0 << STM_TIM23_CCMR1_OC1PE) | + (0 << STM_TIM23_CCMR1_OC1FE) | + (STM_TIM23_CCMR1_CC1S_OUTPUT << STM_TIM23_CCMR1_CC1S)); + + timer.ccer = ((0 << STM_TIM23_CCER_CC4P) | + (0 << STM_TIM23_CCER_CC4E) | + (0 << STM_TIM23_CCER_CC3NP) | + (0 << STM_TIM23_CCER_CC3P) | + (0 << STM_TIM23_CCER_CC3E) | + (0 << STM_TIM23_CCER_CC2NP) | + (0 << STM_TIM23_CCER_CC2P) | + (1 << STM_TIM23_CCER_CC2E) | + (0 << STM_TIM23_CCER_CC1P) | + (0 << STM_TIM23_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 3 + timer.ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) | + (STM_TIM23_CCMR2_OC4M_FROZEN << STM_TIM23_CCMR2_OC4M) | + (0 << STM_TIM23_CCMR2_OC4PE) | + (0 << STM_TIM23_CCMR2_OC4FE) | + (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) | + + (0 << STM_TIM23_CCMR2_OC3CE) | + (STM_TIM23_CCMR2_OC3M_TOGGLE << STM_TIM23_CCMR2_OC3M) | + (0 << STM_TIM23_CCMR2_OC3PE) | + (0 << STM_TIM23_CCMR2_OC3FE) | + (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S)); + + timer.ccer = ((0 << STM_TIM23_CCER_CC4P) | + (0 << STM_TIM23_CCER_CC4E) | + (0 << STM_TIM23_CCER_CC3NP) | + (0 << STM_TIM23_CCER_CC3P) | + (1 << STM_TIM23_CCER_CC3E) | + (0 << STM_TIM23_CCER_CC2NP) | + (0 << STM_TIM23_CCER_CC2P) | + (0 << STM_TIM23_CCER_CC2E) | + (0 << STM_TIM23_CCER_CC1P) | + (0 << STM_TIM23_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 4 + timer.ccmr2 = ((0 << STM_TIM23_CCMR2_OC4CE) | + (STM_TIM23_CCMR2_OC4M_TOGGLE << STM_TIM23_CCMR2_OC4M) | + (0 << STM_TIM23_CCMR2_OC4PE) | + (0 << STM_TIM23_CCMR2_OC4FE) | + (STM_TIM23_CCMR2_CC4S_OUTPUT << STM_TIM23_CCMR2_CC4S) | + + (0 << STM_TIM23_CCMR2_OC3CE) | + (STM_TIM23_CCMR2_OC3M_FROZEN << STM_TIM23_CCMR2_OC3M) | + (0 << STM_TIM23_CCMR2_OC3PE) | + (0 << STM_TIM23_CCMR2_OC3FE) | + (STM_TIM23_CCMR2_CC3S_OUTPUT << STM_TIM23_CCMR2_CC3S)); + + timer.ccer = ((0 << STM_TIM23_CCER_CC4P) | + (1 << STM_TIM23_CCER_CC4E) | + (0 << STM_TIM23_CCER_CC3NP) | + (0 << STM_TIM23_CCER_CC3P) | + (0 << STM_TIM23_CCER_CC3E) | + (0 << STM_TIM23_CCER_CC2NP) | + (0 << STM_TIM23_CCER_CC2P) | + (0 << STM_TIM23_CCER_CC2E) | + (0 << STM_TIM23_CCER_CC1P) | + (0 << STM_TIM23_CCER_CC1E)); +#endif + /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */ + + timer.cr1 = ((STM_TIM23_CR1_CKD_1 << STM_TIM23_CR1_CKD) | + (0 << STM_TIM23_CR1_ARPE) | + (STM_TIM23_CR1_CMS_EDGE << STM_TIM23_CR1_CMS) | + (0 << STM_TIM23_CR1_DIR) | + (0 << STM_TIM23_CR1_OPM) | + (0 << STM_TIM23_CR1_URS) | + (0 << STM_TIM23_CR1_UDIS) | + (1 << STM_TIM23_CR1_CEN)); + + /* Update the values */ + timer.egr = (1 << STM_TIM23_EGR_UG); + + /* Hook the timer up to the beeper pin */ + stm_afr_set(BEEPER_PORT, BEEPER_PIN, STM_AFR_AF2); +#endif + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + ao_enable_output(BEEPER_PORT, BEEPER_PIN, BEEPER, 0); + + /* Leave the timer off until requested */ + stm_rcc_enr &= ~(1 << STM_RCC_TIMER); +} diff --git a/src/stmf0/ao_crc.h b/src/stmf0/ao_crc.h index 7acc6f9c..b6d91023 100644 --- a/src/stmf0/ao_crc.h +++ b/src/stmf0/ao_crc.h @@ -35,7 +35,8 @@ static inline uint16_t ao_crc_in_32_out_16(uint32_t v) { stm_crc.dr.u32 = v; - return stm_crc.dr.u16; + v = stm_crc.dr.u32; + return v ^ (v >> 16); } static inline uint16_t diff --git a/src/stmf0/ao_flash_stm.c b/src/stmf0/ao_flash_stm.c index 2aeff388..2d57eea7 100644 --- a/src/stmf0/ao_flash_stm.c +++ b/src/stmf0/ao_flash_stm.c @@ -19,6 +19,12 @@ #include #include +/* Note that the HSI clock must be running for this code to work. + * Also, special care must be taken with the linker to ensure that the + * functions marked 'ramtext' land in ram and not rom. An example of that + * can be found in altos-loader.ld + */ + static uint8_t ao_flash_is_locked(void) { @@ -44,12 +50,7 @@ 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)) - ; -} +#define ao_flash_wait_bsy() do { while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)); } while (0) static void __attribute__ ((section(".ramtext"),noinline)) _ao_flash_erase_page(uint32_t *page) diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c index 79412483..fcd330f1 100644 --- a/src/stmf0/ao_interrupt.c +++ b/src/stmf0/ao_interrupt.c @@ -26,9 +26,11 @@ #define IS_FLASH_LOADER 0 #endif +#ifndef RELOCATE_INTERRUPT #if !IS_FLASH_LOADER #define RELOCATE_INTERRUPT 1 #endif +#endif extern void main(void); extern char __stack__; diff --git a/src/stmf0/ao_serial_stm.c b/src/stmf0/ao_serial_stm.c new file mode 100644 index 00000000..30b0dbd2 --- /dev/null +++ b/src/stmf0/ao_serial_stm.c @@ -0,0 +1,500 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include +#include + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); + while (!(stm_usart1.isr & (1 << STM_USART_ISR_TXE))); + stm_usart1.tdr = c; +} + +static int +_ao_usart_tx_start(struct ao_stm_usart *usart) +{ + if (!ao_fifo_empty(usart->tx_fifo)) { +#if HAS_SERIAL_SW_FLOW + if (usart->gpio_cts && ao_gpio_get(usart->gpio_cts, usart->pin_cts, foo) == 1) { + ao_exti_enable(usart->gpio_cts, usart->pin_cts); + return 0; + } +#endif + if (usart->reg->isr & (1 << STM_USART_ISR_TXE)) + { + usart->tx_running = 1; + usart->reg->cr1 |= (1 << STM_USART_CR1_TXEIE) | (1 << STM_USART_CR1_TCIE); + ao_fifo_remove(usart->tx_fifo, usart->reg->tdr); + ao_wakeup(&usart->tx_fifo); + return 1; + } + } + return 0; +} + +#if HAS_SERIAL_SW_FLOW +static void +_ao_usart_cts(struct ao_stm_usart *usart) +{ + if (_ao_usart_tx_start(usart)) + ao_exti_disable(usart->gpio_cts, usart->pin_cts); +} +#endif + +static void +_ao_usart_rx(struct ao_stm_usart *usart, int stdin) +{ + if (usart->reg->isr & (1 << STM_USART_ISR_RXNE)) { + usart->reg->icr = (1 << STM_USART_ICR_ORECF); + if (!ao_fifo_full(usart->rx_fifo)) { + ao_fifo_insert(usart->rx_fifo, usart->reg->rdr); + ao_wakeup(&usart->rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); +#if HAS_SERIAL_SW_FLOW + /* If the fifo is nearly full, turn off RTS and wait + * for it to drain a bunch + */ + if (usart->gpio_rts && ao_fifo_mostly(usart->rx_fifo)) { + ao_gpio_set(usart->gpio_rts, usart->pin_rts, usart->pin_rts, 1); + usart->rts = 0; + } +#endif + } else { + usart->reg->cr1 &= ~(1 << STM_USART_CR1_RXNEIE); + } + } +} + +static void +ao_usart_isr(struct ao_stm_usart *usart, int stdin) +{ + _ao_usart_rx(usart, stdin); + + if (!_ao_usart_tx_start(usart)) + usart->reg->cr1 &= ~(1<< STM_USART_CR1_TXEIE); + + if (usart->reg->isr & (1 << STM_USART_ISR_TC)) { + usart->tx_running = 0; + usart->reg->cr1 &= ~(1 << STM_USART_CR1_TCIE); + if (usart->draining) { + usart->draining = 0; + ao_wakeup(&usart->tx_fifo); + } + } +} + +static int +_ao_usart_pollchar(struct ao_stm_usart *usart) +{ + int c; + + if (ao_fifo_empty(usart->rx_fifo)) + c = AO_READ_AGAIN; + else { + uint8_t u; + ao_fifo_remove(usart->rx_fifo,u); + if ((usart->reg->cr1 & (1 << STM_USART_CR1_RXNEIE)) == 0) { + if (ao_fifo_barely(usart->rx_fifo)) + usart->reg->cr1 |= (1 << STM_USART_CR1_RXNEIE); + } +#if HAS_SERIAL_SW_FLOW + /* If we've cleared RTS, check if there's space now and turn it back on */ + if (usart->gpio_rts && usart->rts == 0 && ao_fifo_barely(usart->rx_fifo)) { + ao_gpio_set(usart->gpio_rts, usart->pin_rts, foo, 0); + usart->rts = 1; + } +#endif + c = u; + } + return c; +} + +static char +ao_usart_getchar(struct ao_stm_usart *usart) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_usart_pollchar(usart)) == AO_READ_AGAIN) + ao_sleep(&usart->rx_fifo); + ao_arch_release_interrupts(); + return (char) c; +} + +static inline uint8_t +_ao_usart_sleep_for(struct ao_stm_usart *usart, uint16_t timeout) +{ + return ao_sleep_for(&usart->rx_fifo, timeout); +} + +static void +ao_usart_putchar(struct ao_stm_usart *usart, char c) +{ + ao_arch_block_interrupts(); + while (ao_fifo_full(usart->tx_fifo)) + ao_sleep(&usart->tx_fifo); + ao_fifo_insert(usart->tx_fifo, c); + _ao_usart_tx_start(usart); + ao_arch_release_interrupts(); +} + +static void +ao_usart_drain(struct ao_stm_usart *usart) +{ + ao_arch_block_interrupts(); + while (!ao_fifo_empty(usart->tx_fifo) || usart->tx_running) { + usart->draining = 1; + ao_sleep(&usart->tx_fifo); + } + ao_arch_release_interrupts(); +} + +static const struct { + uint32_t brr; +} ao_usart_speeds[] = { + [AO_SERIAL_SPEED_4800] = { + AO_PCLK / 4800 + }, + [AO_SERIAL_SPEED_9600] = { + AO_PCLK / 9600 + }, + [AO_SERIAL_SPEED_19200] = { + AO_PCLK / 19200 + }, + [AO_SERIAL_SPEED_57600] = { + AO_PCLK / 57600 + }, + [AO_SERIAL_SPEED_115200] = { + AO_PCLK / 115200 + }, +}; + +static void +ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) +{ + if (speed > AO_SERIAL_SPEED_115200) + return; + usart->reg->brr = ao_usart_speeds[speed].brr; +} + +static void +ao_usart_init(struct ao_stm_usart *usart) +{ + usart->reg->cr1 = ((0 << STM_USART_CR1_M1) | + (0 << STM_USART_CR1_EOBIE) | + (0 << STM_USART_CR1_RTOIE) | + (0 << STM_USART_CR1_DEAT) | + (0 << STM_USART_CR1_DEDT) | + (0 << STM_USART_CR1_OVER8) | + (0 << STM_USART_CR1_CMIE) | + (0 << STM_USART_CR1_MME) | + (0 << STM_USART_CR1_M0) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | + (0 << STM_USART_CR1_TCIE) | + (1 << STM_USART_CR1_RXNEIE) | + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_UESM) | + (0 << STM_USART_CR1_UE)); + + usart->reg->cr2 = ((0 << STM_USART_CR2_ADD) | + (0 << STM_USART_CR2_RTOEN) | + (0 << STM_USART_CR2_ABRMOD) | + (0 << STM_USART_CR2_ABREN) | + (0 << STM_USART_CR2_MSBFIRST) | + (0 << STM_USART_CR2_DATAINV) | + (0 << STM_USART_CR2_TXINV) | + (0 << STM_USART_CR2_RXINV) | + (0 << STM_USART_CR2_SWAP) | + (0 << STM_USART_CR2_LINEN) | + (0 << STM_USART_CR2_STOP) | + (0 << STM_USART_CR2_CLKEN) | + (0 << STM_USART_CR2_CPOL) | + (0 << STM_USART_CR2_CHPA) | + (0 << STM_USART_CR2_LBCL) | + (0 << STM_USART_CR2_LBDIE) | + (0 << STM_USART_CR2_LBDL) | + (0 << STM_USART_CR2_ADDM7)); + + usart->reg->cr3 = ((0 << STM_USART_CR3_WUFIE) | + (0 << STM_USART_CR3_WUS) | + (0 << STM_USART_CR3_SCARCNT) | + (0 << STM_USART_CR3_DEP) | + (0 << STM_USART_CR3_DEM) | + (0 << STM_USART_CR3_DDRE) | + (0 << STM_USART_CR3_OVRDIS) | + (0 << STM_USART_CR3_ONEBIT) | + (0 << STM_USART_CR3_CTIIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); + + + /* Pick a 9600 baud rate */ + ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); + + /* Enable the usart */ + usart->reg->cr1 |= (1 << STM_USART_CR1_UE); + +} + +#if HAS_SERIAL_HW_FLOW +static void +ao_usart_set_flow(struct ao_stm_usart *usart) +{ + usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | + (1 << STM_USART_CR3_RTSE)); +} +#endif + +#if HAS_SERIAL_1 + +struct ao_stm_usart ao_stm_usart1; + +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_1_STDIN); } + +char +ao_serial1_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart1); +} + +void +ao_serial1_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart1, c); +} + +int +_ao_serial1_pollchar(void) +{ + return _ao_usart_pollchar(&ao_stm_usart1); +} + +uint8_t +_ao_serial1_sleep_for(uint16_t timeout) +{ + return _ao_usart_sleep_for(&ao_stm_usart1, timeout); +} + +void +ao_serial1_drain(void) +{ + ao_usart_drain(&ao_stm_usart1); +} + +void +ao_serial1_set_speed(uint8_t speed) +{ + ao_usart_drain(&ao_stm_usart1); + ao_usart_set_speed(&ao_stm_usart1, speed); +} +#endif /* HAS_SERIAL_1 */ + +#if HAS_SERIAL_2 + +struct ao_stm_usart ao_stm_usart2; + +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, USE_SERIAL_2_STDIN); } + +char +ao_serial2_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart2); +} + +void +ao_serial2_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart2, c); +} + +int +_ao_serial2_pollchar(void) +{ + return _ao_usart_pollchar(&ao_stm_usart2); +} + +uint8_t +_ao_serial2_sleep_for(uint16_t timeout) +{ + return _ao_usart_sleep_for(&ao_stm_usart2, timeout); +} + +void +ao_serial2_drain(void) +{ + ao_usart_drain(&ao_stm_usart2); +} + +void +ao_serial2_set_speed(uint8_t speed) +{ + ao_usart_drain(&ao_stm_usart2); + ao_usart_set_speed(&ao_stm_usart2, speed); +} + +#if HAS_SERIAL_SW_FLOW +void +ao_serial2_cts(void) +{ + _ao_usart_cts(&ao_stm_usart2); +} +#endif + +#endif /* HAS_SERIAL_2 */ + +#if HAS_SERIAL_SW_FLOW +static void +ao_serial_set_sw_rts_cts(struct ao_stm_usart *usart, + void (*isr)(void), + struct stm_gpio *port_rts, + int pin_rts, + struct stm_gpio *port_cts, + int pin_cts) +{ + /* Pull RTS low to note that there's space in the FIFO + */ + ao_enable_output(port_rts, pin_rts, foo, 0); + usart->gpio_rts = port_rts; + usart->pin_rts = pin_rts; + usart->rts = 1; + + ao_exti_setup(port_cts, pin_cts, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, isr); + usart->gpio_cts = port_cts; + usart->pin_cts = pin_cts; +} +#endif + +void +ao_serial_init(void) +{ +#if HAS_SERIAL_1 + /* + * TX RX + * PA9 PA10 + * PB6 PB7 + */ + +#if SERIAL_1_PA9_PA10 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF1); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF1); +#else +#if SERIAL_1_PB6_PB7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); + + stm_afr_set(&stm_gpiob, 6, STM_AFR_AF0); + stm_afr_set(&stm_gpiob, 7, STM_AFR_AF0); +#else +#error "No SERIAL_1 port configuration specified" +#endif +#endif + /* Enable USART */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); + + ao_stm_usart1.reg = &stm_usart1; + ao_usart_init(&ao_stm_usart1); + + stm_nvic_set_enable(STM_ISR_USART1_POS); + stm_nvic_set_priority(STM_ISR_USART1_POS, 4); +#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN + ao_add_stdio(_ao_serial1_pollchar, + ao_serial1_putchar, + NULL); +#endif +#endif + +#if HAS_SERIAL_2 + /* + * TX RX + * PA2 PA3 + * PA14 PA15 + */ + +# if SERIAL_2_PA2_PA3 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + + stm_afr_set(&stm_gpioa, 2, STM_AFR_AF1); + stm_afr_set(&stm_gpioa, 3, STM_AFR_AF1); +# if USE_SERIAL_2_FLOW +# if USE_SERIAL_2_SW_FLOW + ao_serial_set_sw_rts_cts(&ao_stm_usart2, + ao_serial2_cts, + SERIAL_2_PORT_RTS, + SERIAL_2_PIN_RTS, + SERIAL_2_PORT_CTS, + SERIAL_2_PIN_CTS); +# else + stm_afr_set(&stm_gpioa, 0, STM_AFR_AF1); + stm_afr_set(&stm_gpioa, 1, STM_AFR_AF1); +# endif +# endif +# else +# if SERIAL_2_PA14_PA15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + + stm_afr_set(&stm_gpioa, 14, STM_AFR_AF1); + stm_afr_set(&stm_gpioa, 15, STM_AFR_AF1); +# if USE_SERIAL_2_FLOW +# error "Don't know how to set flowcontrol for serial 2 on PA14" +# endif +# else +# if SERIAL_2_PA2_PA15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); + + stm_afr_set(&stm_gpioa, 2, STM_AFR_AF1); + stm_afr_set(&stm_gpioa, 15, STM_AFR_AF1); +# if USE_SERIAL_2_FLOW +# error "Don't know how to set flowcontrol for serial 2 on PA2_PA15" +# 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 && !USE_SERIAL_2_SW_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 && !DELAY_SERIAL_2_STDIN + ao_add_stdio(_ao_serial2_pollchar, + ao_serial2_putchar, + NULL); +# endif +#endif +} diff --git a/src/stmf0/ao_spi_stm.c b/src/stmf0/ao_spi_stm.c index 0448ad8c..5e76d6c3 100644 --- a/src/stmf0/ao_spi_stm.c +++ b/src/stmf0/ao_spi_stm.c @@ -536,12 +536,18 @@ void ao_spi_init(void) { #if HAS_SPI_1 +#ifndef SPI_1_PA5_PA6_PA7 +#error SPI_1_PA5_PA6_PA7 undefined +#endif # if SPI_1_PA5_PA6_PA7 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR); stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR); stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR); # endif +# ifndef SPI_1_PB3_PB4_PB5 +# error SPI_1_PB3_PB4_PB5 undefined +# endif # if SPI_1_PB3_PB4_PB5 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR); diff --git a/src/stmf0/ao_spi_stm_slave.c b/src/stmf0/ao_spi_stm_slave.c new file mode 100644 index 00000000..962ff2c6 --- /dev/null +++ b/src/stmf0/ao_spi_stm_slave.c @@ -0,0 +1,339 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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 + +struct ao_spi_stm_slave_info { + uint8_t miso_dma_index; + uint8_t mosi_dma_index; + struct stm_spi *stm_spi; +}; + +static uint8_t ao_spi_slave_mutex[STM_NUM_SPI]; +static uint8_t ao_spi_slave_index[STM_NUM_SPI]; + +static const struct ao_spi_stm_slave_info ao_spi_stm_slave_info[STM_NUM_SPI] = { + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), + &stm_spi1 + }, + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), + &stm_spi2 + } +}; + +static uint8_t spi_dev_null; + +void +ao_spi_slave_send(void *block, uint16_t len) +{ + struct stm_spi *stm_spi = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].miso_dma_index; + + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +uint8_t +ao_spi_slave_recv(void *block, uint16_t len) +{ + struct stm_spi *stm_spi = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_slave_info[AO_SPI_INDEX(SPI_SLAVE_INDEX)].miso_dma_index; + + /* Set up transmit DMA to make the SPI hardware actually run */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); + return 1; +} + +static void +ao_spi_slave_disable_index(uint8_t spi_index) +{ + /* Disable current config + */ + switch (AO_SPI_INDEX(spi_index)) { + case STM_SPI_INDEX(1): + switch (spi_index) { + case AO_SPI_1_PA5_PA6_PA7: + stm_gpio_set(&stm_gpioa, 5, 1); + stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT); + stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_gpio_set(&stm_gpiob, 3, 1); + stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT); + stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT); + break; + case AO_SPI_1_PE13_PE14_PE15: + stm_gpio_set(&stm_gpioe, 13, 1); + stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT); + break; + } + break; + case STM_SPI_INDEX(2): + switch (spi_index) { + case AO_SPI_2_PB13_PB14_PB15: + stm_gpio_set(&stm_gpiob, 13, 1); + stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT); + break; + case AO_SPI_2_PD1_PD3_PD4: + stm_gpio_set(&stm_gpiod, 1, 1); + stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT); + stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT); + break; + } + break; + } +} + +static void +ao_spi_slave_enable_index(uint8_t spi_index) +{ + switch (AO_SPI_INDEX(spi_index)) { + case STM_SPI_INDEX(1): + switch (spi_index) { + case AO_SPI_1_PA5_PA6_PA7: + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); + break; + case AO_SPI_1_PB3_PB4_PB5: + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); + break; + case AO_SPI_1_PE13_PE14_PE15: + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); + break; + } + break; + case STM_SPI_INDEX(2): + switch (spi_index) { + case AO_SPI_2_PB13_PB14_PB15: + stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); + break; + case AO_SPI_2_PD1_PD3_PD4: + stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); + break; + } + break; + } +} + +void +ao_spi_slave_get(uint8_t spi_index, uint32_t speed) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_slave_info[id].stm_spi; + + ao_mutex_get(&ao_spi_slave_mutex[id]); + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */ + (0 << STM_SPI_CR1_BIDIOE) | + (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ + (0 << STM_SPI_CR1_CRCNEXT) | + (0 << STM_SPI_CR1_DFF) | + (0 << STM_SPI_CR1_RXONLY) | + (1 << STM_SPI_CR1_SSM) | /* Software SS handling */ + (1 << STM_SPI_CR1_SSI) | /* ... */ + (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ + (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ + (speed << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (1 << STM_SPI_CR1_MSTR) | + (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ + (0 << STM_SPI_CR1_CPHA)); + if (spi_index != ao_spi_slave_index[id]) { + + /* Disable old config + */ + ao_spi_slave_disable_index(ao_spi_slave_index[id]); + + /* Enable new config + */ + ao_spi_slave_enable_index(spi_index); + + /* Remember current config + */ + ao_spi_slave_index[id] = spi_index; + } +} + +void +ao_spi_slave_put(uint8_t spi_index) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_slave_info[id].stm_spi; + + stm_spi->cr1 = 0; + ao_mutex_put(&ao_spi_slave_mutex[id]); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + uint8_t id = AO_SPI_INDEX(spi_index); + struct stm_spi *stm_spi = ao_spi_stm_slave_info[id].stm_spi; + + ao_spi_slave_disable_index(spi_index); + + stm_spi->cr1 = 0; + (void) stm_spi->sr; + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (0 << STM_SPI_CR2_TXDMAEN) | + (0 << STM_SPI_CR2_RXDMAEN)); +} + +void +ao_spi_slave_init(void) +{ +#if HAS_SPI_SLAVE_1 +# if SPI_1_PA5_PA6_PA7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); +# endif +# if SPI_1_PB3_PB4_PB5 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +# endif +# if SPI_1_PE13_PE14_PE15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); +# endif + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + ao_spi_slave_index[0] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(0); +#endif + +#if HAS_SPI_SLAVE_2 +# if SPI_2_PB13_PB14_PB15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +# endif +# if SPI_2_PD1_PD3_PD4 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); +# endif + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + ao_spi_slave_index[1] = AO_SPI_CONFIG_NONE; + ao_spi_channel_init(1); +#endif +} diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index bafa763a..e53a5dfd 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -1812,15 +1812,15 @@ extern struct stm_tim23 stm_tim2, stm_tim3; #define STM_TIM23_CCMR2_OC4CE 15 #define STM_TIM23_CCMR2_OC4M 12 -#define STM_TIM23_CCMR2_OCM_FROZEN 0 -#define STM_TIM23_CCMR2_OCM_SET_HIGH_ON_MATCH 1 -#define STM_TIM23_CCMR2_OCM_SET_LOW_ON_MATCH 2 -#define STM_TIM23_CCMR2_OCM_TOGGLE 3 -#define STM_TIM23_CCMR2_OCM_FORCE_LOW 4 -#define STM_TIM23_CCMR2_OCM_FORCE_HIGH 5 -#define STM_TIM23_CCMR2_OCM_PWM_MODE_1 6 -#define STM_TIM23_CCMR2_OCM_PWM_MODE_2 7 -#define STM_TIM23_CCMR2_OCM_MASK 7 +#define STM_TIM23_CCMR2_OC4M_FROZEN 0 +#define STM_TIM23_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 +#define STM_TIM23_CCMR2_OC4M_SET_LOW_ON_MATCH 2 +#define STM_TIM23_CCMR2_OC4M_TOGGLE 3 +#define STM_TIM23_CCMR2_OC4M_FORCE_LOW 4 +#define STM_TIM23_CCMR2_OC4M_FORCE_HIGH 5 +#define STM_TIM23_CCMR2_OC4M_PWM_MODE_1 6 +#define STM_TIM23_CCMR2_OC4M_PWM_MODE_2 7 +#define STM_TIM23_CCMR2_OC4M_MASK 7 #define STM_TIM23_CCMR2_OC4PE 11 #define STM_TIM23_CCMR2_OC4FE 10 #define STM_TIM23_CCMR2_CC4S 8 @@ -1832,15 +1832,15 @@ extern struct stm_tim23 stm_tim2, stm_tim3; #define STM_TIM23_CCMR2_OC3CE 7 #define STM_TIM23_CCMR2_OC3M 4 -#define STM_TIM23_CCMR2_OCM_FROZEN 0 -#define STM_TIM23_CCMR2_OCM_SET_HIGH_ON_MATCH 1 -#define STM_TIM23_CCMR2_OCM_SET_LOW_ON_MATCH 2 -#define STM_TIM23_CCMR2_OCM_TOGGLE 3 -#define STM_TIM23_CCMR2_OCM_FORCE_LOW 4 -#define STM_TIM23_CCMR2_OCM_FORCE_HIGH 5 +#define STM_TIM23_CCMR2_OC3M_FROZEN 0 +#define STM_TIM23_CCMR2_OC3M_SET_HIGH_ON_MATCH 1 +#define STM_TIM23_CCMR2_OC3M_SET_LOW_ON_MATCH 2 +#define STM_TIM23_CCMR2_OC3M_TOGGLE 3 +#define STM_TIM23_CCMR2_OC3M_FORCE_LOW 4 +#define STM_TIM23_CCMR2_OC3M_FORCE_HIGH 5 #define STM_TIM23_CCMR2_OC3M_PWM_MODE_1 6 -#define STM_TIM23_CCMR2_OCM_PWM_MODE_2 7 -#define STM_TIM23_CCMR2_OCM_MASK 7 +#define STM_TIM23_CCMR2_OC3M_PWM_MODE_2 7 +#define STM_TIM23_CCMR2_OC3M_MASK 7 #define STM_TIM23_CCMR2_OC3PE 11 #define STM_TIM23_CCMR2_OC3FE 2 #define STM_TIM23_CCMR2_CC3S 0 @@ -2010,4 +2010,129 @@ struct stm_exti { extern struct stm_exti stm_exti; +struct stm_usart { + vuint32_t cr1; /* control register 1 */ + vuint32_t cr2; /* control register 2 */ + vuint32_t cr3; /* control register 3 */ + vuint32_t brr; /* baud rate register */ + + vuint32_t gtpr; /* guard time and prescaler */ + vuint32_t rtor; /* receiver timeout register */ + vuint32_t rqr; /* request register */ + vuint32_t isr; /* interrupt and status register */ + + vuint32_t icr; /* interrupt flag clear register */ + vuint32_t rdr; /* receive data register */ + vuint32_t tdr; /* transmit data register */ +}; + +#define STM_USART_CR1_M1 28 +#define STM_USART_CR1_EOBIE 27 +#define STM_USART_CR1_RTOIE 26 +#define STM_USART_CR1_DEAT 21 +#define STM_USART_CR1_DEDT 16 +#define STM_USART_CR1_OVER8 15 +#define STM_USART_CR1_CMIE 14 +#define STM_USART_CR1_MME 13 +#define STM_USART_CR1_M0 12 +#define STM_USART_CR1_WAKE 11 +#define STM_USART_CR1_PCE 10 +#define STM_USART_CR1_PS 9 +#define STM_USART_CR1_PEIE 8 +#define STM_USART_CR1_TXEIE 7 +#define STM_USART_CR1_TCIE 6 +#define STM_USART_CR1_RXNEIE 5 +#define STM_USART_CR1_IDLEIE 4 +#define STM_USART_CR1_TE 3 +#define STM_USART_CR1_RE 2 +#define STM_USART_CR1_UESM 1 +#define STM_USART_CR1_UE 0 + +#define STM_USART_CR2_ADD 24 +#define STM_USART_CR2_RTOEN 23 +#define STM_USART_CR2_ABRMOD 21 +#define STM_USART_CR2_ABREN 20 +#define STM_USART_CR2_MSBFIRST 19 +#define STM_USART_CR2_DATAINV 18 +#define STM_USART_CR2_TXINV 17 +#define STM_USART_CR2_RXINV 16 +#define STM_USART_CR2_SWAP 15 +#define STM_USART_CR2_LINEN 14 +#define STM_USART_CR2_STOP 12 +#define STM_USART_CR2_CLKEN 11 +#define STM_USART_CR2_CPOL 10 +#define STM_USART_CR2_CHPA 9 +#define STM_USART_CR2_LBCL 8 +#define STM_USART_CR2_LBDIE 6 +#define STM_USART_CR2_LBDL 5 +#define STM_USART_CR2_ADDM7 4 + +#define STM_USART_CR3_WUFIE 22 +#define STM_USART_CR3_WUS 20 +#define STM_USART_CR3_SCARCNT 17 +#define STM_USART_CR3_DEP 15 +#define STM_USART_CR3_DEM 14 +#define STM_USART_CR3_DDRE 13 +#define STM_USART_CR3_OVRDIS 12 +#define STM_USART_CR3_ONEBIT 11 +#define STM_USART_CR3_CTIIE 10 +#define STM_USART_CR3_CTSE 9 +#define STM_USART_CR3_RTSE 8 +#define STM_USART_CR3_DMAT 7 +#define STM_USART_CR3_DMAR 6 +#define STM_USART_CR3_SCEN 5 +#define STM_USART_CR3_NACK 4 +#define STM_USART_CR3_HDSEL 3 +#define STM_USART_CR3_IRLP 2 +#define STM_USART_CR3_IREN 1 +#define STM_USART_CR3_EIE 0 + +#define STM_USART_GTPR_GT 8 +#define STM_USART_GTPR_PSC 0 + +#define STM_USART_RQR_TXFRQ 4 +#define STM_USART_RQR_RXFRQ 3 +#define STM_USART_RQR_MMRQ 2 +#define STM_USART_RQR_SBKRQ 1 +#define STM_USART_RQR_ABRRQ 0 + +#define STM_USART_ISR_REACK 22 +#define STM_USART_ISR_TEACK 21 +#define STM_USART_ISR_WUF 20 +#define STM_USART_ISR_RWU 19 +#define STM_USART_ISR_SBKF 18 +#define STM_USART_ISR_CMF 17 +#define STM_USART_ISR_BUSY 16 +#define STM_USART_ISR_ABRF 15 +#define STM_USART_ISR_ABRE 14 +#define STM_USART_ISR_EOBF 12 +#define STM_USART_ISR_RTOF 11 +#define STM_USART_ISR_CTS 10 +#define STM_USART_ISR_CTSIF 9 +#define STM_USART_ISR_LBDF 8 +#define STM_USART_ISR_TXE 7 +#define STM_USART_ISR_TC 6 +#define STM_USART_ISR_RXNE 5 +#define STM_USART_ISR_IDLE 4 +#define STM_USART_ISR_ORE 3 +#define STM_USART_ISR_NF 2 +#define STM_USART_ISR_FE 1 +#define STM_USART_ISR_PE 0 + +#define STM_USART_ICR_WUCF 20 +#define STM_USART_ICR_CMCF 17 +#define STM_USART_ICR_EOBCF 12 +#define STM_USART_ICR_RTOCF 11 +#define STM_USART_ICR_CTSCF 9 +#define STM_USART_ICR_LBDCF 8 +#define STM_USART_ICR_TCCF 6 +#define STM_USART_ICR_IDLECF 4 +#define STM_USART_ICR_ORECF 3 +#define STM_USART_ICR_NCF 2 +#define STM_USART_ICR_FECF 1 +#define STM_USART_ICR_PECF 0 + +extern struct stm_usart stm_usart1; +extern struct stm_usart stm_usart2; + #endif /* _STM32F0_H_ */ diff --git a/src/telebt-v3.0/Makefile b/src/telebt-v3.0/Makefile index a7ef4d64..40d1f6e4 100644 --- a/src/telebt-v3.0/Makefile +++ b/src/telebt-v3.0/Makefile @@ -58,7 +58,12 @@ ALTOS_SRC = \ ao_monitor.c \ $(PROFILE) \ $(SAMPLE_PROFILE) \ - $(STACK_GUARD) + $(STACK_GUARD) \ + ao_lco_func.c \ + ao_radio_cmac.c \ + ao_aes.c \ + ao_aes_tables.c \ + ao_lco_cmd.c PRODUCT=TeleBT-v3.0 PRODUCT_DEF=-DTELEBT_V_3_0 diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index 61cbe9bb..62dddf2a 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -80,6 +80,7 @@ #define HAS_TELEMETRY 0 #define HAS_APRS 0 #define HAS_ACCEL 0 +#define HAS_AES 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 /* CC1200 */ @@ -197,6 +198,7 @@ struct ao_adc { #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_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c index 9117863b..8775d993 100644 --- a/src/telebt-v3.0/ao_telebt.c +++ b/src/telebt-v3.0/ao_telebt.c @@ -22,6 +22,7 @@ #include #include #include +#include #if HAS_SAMPLE_PROFILE #include #endif @@ -44,6 +45,8 @@ main(void) ao_btm_init(); ao_cmd_init(); + ao_lco_cmd_init(); + ao_eeprom_init(); ao_usb_init(); diff --git a/src/teledongle-v3.0/ao_pins.h b/src/teledongle-v3.0/ao_pins.h index effc2322..be710aef 100644 --- a/src/teledongle-v3.0/ao_pins.h +++ b/src/teledongle-v3.0/ao_pins.h @@ -96,6 +96,7 @@ #define AO_CC1200_SPI_CS_PIN 3 #define AO_CC1200_SPI_BUS 0 #define AO_CC1200_SPI 0 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_8MHz #define AO_CC1200_INT_PORT 0 #define AO_CC1200_INT_PIN 2 diff --git a/src/telefiretwo-v0.1/ao_pins.h b/src/telefiretwo-v0.1/ao_pins.h index f56061b2..1e5c0d09 100644 --- a/src/telefiretwo-v0.1/ao_pins.h +++ b/src/telefiretwo-v0.1/ao_pins.h @@ -110,6 +110,7 @@ #define AO_CC1200_SPI_CS_PIN 7 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telefiretwo-v0.2/ao_pins.h b/src/telefiretwo-v0.2/ao_pins.h index 70af5dd1..469e9937 100644 --- a/src/telefiretwo-v0.2/ao_pins.h +++ b/src/telefiretwo-v0.2/ao_pins.h @@ -110,6 +110,7 @@ #define AO_CC1200_SPI_CS_PIN 7 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telefiretwo-v1.0/Makefile b/src/telefiretwo-v1.0/Makefile new file mode 100644 index 00000000..87d5d477 --- /dev/null +++ b/src/telefiretwo-v1.0/Makefile @@ -0,0 +1,95 @@ +# +# TeleFire build file +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_pins.h \ + ao_log.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pad.h \ + ao_product.h \ + ao_radio_spi.h \ + ao_radio_cmac.h \ + ao_cc1200_CC1200.h \ + ao_cc1200.h \ + stm32l.h +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_adc_stm.c \ + ao_data.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_beep_stm.c \ + ao_eeprom_stm.c \ + ao_storage.c \ + ao_m25.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_cc1200.c \ + ao_radio_cmac.c \ + ao_aes.c \ + ao_aes_tables.c \ + ao_pad.c \ + ao_radio_cmac_cmd.c \ + ao_log.c \ + ao_log_firetwo.c + +PRODUCT_SRC = \ + ao_telefiretwo.c + +PRODUCT=TeleFireTwo-v1.0 +PRODUCT_DEF=-DTELEFIRETWO_V_1_0 +IDPRODUCT=0x000f + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME = telefiretwo-v1.0 +PROG = $(PROGNAME)-$(VERSION).elf +HEX = $(PROGNAME)-$(VERSION).ihx + +SRC = $(ALTOS_SRC) $(PRODUCT_SRC) +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: + diff --git a/src/telefiretwo-v1.0/ao_pins.h b/src/telefiretwo-v1.0/ao_pins.h new file mode 100644 index 00000000..b2f5a5ab --- /dev/null +++ b/src/telefiretwo-v1.0/ao_pins.h @@ -0,0 +1,233 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define BEEPER_CHANNEL 4 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 1 +#define HAS_PAD 1 +#define USE_INTERNAL_FLASH 0 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 +#define AO_DATA_RING 32 +#define HAS_FIXED_PAD_BOX 1 + +#define LOG_ERASE_MARK 0x55 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +#define AO_CC1200_FOSC 40000000 + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM 1 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 +#define HAS_AES 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 /* CC1200 */ +#define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_GPIO (&stm_gpiob) +#define SPI_2_SCK 13 +#define SPI_2_MISO 14 +#define SPI_2_MOSI 15 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_I2C_1 0 + +#define HAS_I2C_2 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 0 + +#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */ + +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT (&stm_gpioa) +#define AO_M25_SPI_CS_MASK (1 << 15) +#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN 7 +#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST + +#define AO_CC1200_INT_PORT (&stm_gpiob) +#define AO_CC1200_INT_PIN (11) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#define LED_PORT_0 (&stm_gpioa) +#define LED_PORT_1 (&stm_gpiob) + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOBEN + +/* Port A, pins 4-6 */ +#define LED_PORT_0_SHIFT 4 +#define LED_PORT_0_MASK 0x7 +#define LED_PIN_GREEN 0 +#define LED_PIN_AMBER 1 +#define LED_PIN_RED 2 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_AMBER (1 << LED_PIN_AMBER) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +/* Port B, pins 4-5 */ +#define LED_PORT_1_SHIFT 0 +#define LED_PORT_1_MASK (0x3 << 4) +#define LED_PIN_CONT_0 4 +#define LED_PIN_ARMED 5 + +#define AO_LED_ARMED (1 << LED_PIN_ARMED) +#define AO_LED_CONTINUITY(c) (1 << (4 - (c))) +#define AO_LED_CONTINUITY_MASK (0x1 << 4) + +#define LEDS_AVAILABLE (LED_PORT_0_MASK|LED_PORT_1_MASK) + +/* Alarm A */ +#define AO_SIREN +#define AO_SIREN_PORT (&stm_gpiob) +#define AO_SIREN_PIN 8 + +/* Alarm B */ +#define AO_STROBE +#define AO_STROBE_PORT (&stm_gpiob) +#define AO_STROBE_PIN 9 + +#define SPI_CONST 0x00 + +#define AO_PAD_NUM 1 +#define AO_PAD_PORT (&stm_gpioa) + +#define AO_PAD_PIN_0 1 +#define AO_PAD_ADC_0 0 + +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0)) +#define AO_PAD_ALL_CHANNELS ((1 << 0)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +#define AO_PAD_ADC_PYRO 2 +#define AO_PAD_ADC_BATT 8 + +#define AO_PAD_ADC_THRUST 3 +#define AO_PAD_ADC_PRESSURE 18 + +#define AO_ADC_FIRST_PIN 0 + +#define AO_NUM_ADC 5 + +#define AO_ADC_SQ1 AO_PAD_ADC_0 +#define AO_ADC_SQ2 AO_PAD_ADC_PYRO +#define AO_ADC_SQ3 AO_PAD_ADC_BATT +#define AO_ADC_SQ4 AO_PAD_ADC_THRUST +#define AO_ADC_SQ5 AO_PAD_ADC_PRESSURE + +#define AO_PYRO_R_PYRO_SENSE 200 +#define AO_PYRO_R_SENSE_GND 22 + +#define AO_FIRE_R_POWER_FET 0 +#define AO_FIRE_R_FET_SENSE 200 +#define AO_FIRE_R_SENSE_GND 22 + +#define HAS_ADC_TEMP 0 + +struct ao_adc { + int16_t sense[AO_PAD_NUM]; + int16_t pyro; + int16_t batt; + int16_t thrust; + int16_t pressure; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d pyro: %5d batt %5d thrust %5d pressure %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], \ + (p)->adc.pyro, \ + (p)->adc.batt, \ + (p)->adc.thrust, \ + (p)->adc.pressure) + +#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \ + (1 << AO_PAD_ADC_PYRO) | \ + (1 << AO_PAD_ADC_BATT) | \ + (1 << AO_PAD_ADC_THRUST) | \ + (1 << AO_PAD_ADC_PRESSURE)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefiretwo-v1.0/ao_telefiretwo.c b/src/telefiretwo-v1.0/ao_telefiretwo.c new file mode 100644 index 00000000..115b3e91 --- /dev/null +++ b/src/telefiretwo-v1.0/ao_telefiretwo.c @@ -0,0 +1,73 @@ +/* + * Copyright © 2012 Keith Packard + * + * 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. + */ + +#include +#include +#include +#include +#include +#include + +static void +set_logging(void) +{ + ao_cmd_hex(); + ao_log_running = ao_cmd_lex_i; + ao_wakeup(&ao_log_running); +} + +__code struct ao_cmds ao_firetwo_cmds[] = { + { set_logging, "L <0 off, 1 on>\0Log sensors to flash" }, + { 0, NULL }, +}; + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_task_init(); + + ao_timer_init(); + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_cmd_register(&ao_firetwo_cmds[0]); + ao_cmd_init(); + + ao_adc_init(); + + ao_eeprom_init(); + ao_storage_init(); + ao_log_init(); + + ao_radio_init(); + + ao_usb_init(); + + ao_config_init(); + + ao_pad_init(); + +// ao_radio_cmac_cmd_init(); + + ao_start_scheduler(); +} diff --git a/src/telefiretwo-v1.0/flash-loader/.gitignore b/src/telefiretwo-v1.0/flash-loader/.gitignore new file mode 100644 index 00000000..65fe7eab --- /dev/null +++ b/src/telefiretwo-v1.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +*.elf +*.ihx diff --git a/src/telefiretwo-v1.0/flash-loader/Makefile b/src/telefiretwo-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..d429dcc4 --- /dev/null +++ b/src/telefiretwo-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telefiretwo-v1.0 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telefiretwo-v1.0/flash-loader/ao_pins.h b/src/telefiretwo-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..ded45a40 --- /dev/null +++ b/src/telefiretwo-v1.0/flash-loader/ao_pins.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiob +#define AO_BOOT_APPLICATION_PIN 6 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ diff --git a/src/telegps-v0.1/ao_pins.h b/src/telegps-v0.1/ao_pins.h index 96e8cfd7..5afc9498 100644 --- a/src/telegps-v0.1/ao_pins.h +++ b/src/telegps-v0.1/ao_pins.h @@ -148,6 +148,7 @@ #define AO_CC115L_SPI_CS_PIN 12 #define AO_CC115L_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC115L_SPI stm_spi2 +#define AO_CC115L_SPI_SPEED AO_SPI_SPEED_4MHz #define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 #define AO_CC115L_FIFO_INT_PORT (&stm_gpioa) @@ -183,4 +184,8 @@ #define AO_SDCARD_SPI_CS_PIN 4 #define AO_SDCARD_SPI stm_spi1 +#define SDCARD_DEBUG 1 +#define SDCARD_WARN 1 +#define SDCARD_TRACE 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/telegps-v0.1/ao_telegps.c b/src/telegps-v0.1/ao_telegps.c index eb8ab72d..f734d90f 100644 --- a/src/telegps-v0.1/ao_telegps.c +++ b/src/telegps-v0.1/ao_telegps.c @@ -49,16 +49,16 @@ main(void) ao_cmd_init(); ao_usb_init(); - ao_radio_init(); +// ao_radio_init(); ao_fat_init(); - ao_gps_init(); - ao_gps_report_mega_init(); +// ao_gps_init(); +// ao_gps_report_mega_init(); - ao_telemetry_init(); - ao_telemetry_set_interval(AO_SEC_TO_TICKS(1)); - ao_rdf_set(1); +// ao_telemetry_init(); +// ao_telemetry_set_interval(AO_SEC_TO_TICKS(1)); +// ao_rdf_set(1); #if HAS_SAMPLE_PROFILE ao_sample_profile_init(); diff --git a/src/telegps-v0.3/ao_pins.h b/src/telegps-v0.3/ao_pins.h index 9c650cc4..28ae30a4 100644 --- a/src/telegps-v0.3/ao_pins.h +++ b/src/telegps-v0.3/ao_pins.h @@ -95,6 +95,7 @@ #define AO_CC115L_SPI_CS_PORT 0 #define AO_CC115L_SPI_CS_PIN 3 #define AO_CC115L_SPI_BUS 0 +#define AO_CC115L_SPI_SPEED AO_SPI_SPEED_6MHz #define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 #define AO_CC115L_FIFO_INT_PORT 0 diff --git a/src/telegps-v1.0/ao_pins.h b/src/telegps-v1.0/ao_pins.h index 19774f63..9672ab03 100644 --- a/src/telegps-v1.0/ao_pins.h +++ b/src/telegps-v1.0/ao_pins.h @@ -97,6 +97,7 @@ #define AO_CC115L_SPI_CS_PORT 0 #define AO_CC115L_SPI_CS_PIN 3 #define AO_CC115L_SPI_BUS 0 +#define AO_CC115L_SPI_SPEED AO_SPI_SPEED_6MHz #define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 #define AO_CC115L_FIFO_INT_PORT 0 diff --git a/src/telegps-v2.0/Makefile b/src/telegps-v2.0/Makefile new file mode 100644 index 00000000..19d088d3 --- /dev/null +++ b/src/telegps-v2.0/Makefile @@ -0,0 +1,89 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + ao_tracker.h \ + ao_task.h \ + ao_cc1200.h \ + ao_fec.h \ + stm32f0.h \ + Makefile + + +ALTOS_SRC = \ + ao_adc_stm.c \ + ao_led.c \ + ao_interrupt.c \ + ao_boot_chain.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.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_serial_stm.c \ + ao_gps_ublox.c \ + ao_gps_show.c \ + ao_cc1200.c \ + ao_aprs.c \ + ao_tracker.c \ + ao_telemetry.c \ + ao_storage.c \ + ao_m25.c \ + ao_log.c \ + ao_log_gps.c \ + ao_distance.c \ + ao_sqrt.c \ + ao_data.c \ + ao_convert_volt.c \ + $(SAMPLE_PROFILE) + +PRODUCT=TeleGPS-v2.0 +PRODUCT_DEF=-DTELEGPS +IDPRODUCT=0x0025 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) $(PROFILE_DEF) -g -Os + +PROGNAME=telegps-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telegps.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) -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 ao_serial_stm.h $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telegps-v2.0/ao_pins.h b/src/telegps-v2.0/ao_pins.h new file mode 100644 index 00000000..c51f0afb --- /dev/null +++ b/src/telegps-v2.0/ao_pins.h @@ -0,0 +1,164 @@ +/* + * Copyright © 2017 Bdale Garbee + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPBEN +#define LED_PORT (&stm_gpiob) +#define LED_PIN_RED 5 +#define AO_LED_RED (1 << LED_PIN_RED) + +#define LEDS_AVAILABLE (AO_LED_RED) + +#define IS_FLASH_LOADER 0 +#define HAS_BEEP 0 + +#define AO_HSE 32000000 +#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3 +#define AO_PLLMUL 3 +#define AO_PLLDIV 1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER 1 +#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 + +#define AO_RCC_CFGR2_PLLDIV STM_RCC_CFGR2_PREDIV_1 + +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#define IS_FLASH_LOADER 0 + +/* ADC */ + +#define HAS_ADC 1 +#define AO_ADC_PIN0_PORT (&stm_gpioa) +#define AO_ADC_PIN0_PIN 0 +#define AO_ADC_PIN0_CH 0 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN)) + +#define AO_NUM_ADC 1 + +#define AO_DATA_RING 4 + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */ +#define AO_BATTERY_DIV_MINUS 100 /* 10k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV 33 + +struct ao_adc { + int16_t v_batt; +}; + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u batt: %5d\n", \ + (p)->tick, \ + (p)->adc.v_batt) + +/* SPI */ +#define HAS_SPI_1 1 +#define HAS_SPI_2 0 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_OSPEEDR STM_OSPEEDR_HIGH + +#define HAS_MS5607 0 + +/* Flash */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT (&stm_gpiob) +#define AO_M25_SPI_CS_MASK (1 << 0) +#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7 + +#define HAS_SERIAL_1 1 +#define SERIAL_1_PB6_PB7 1 +#define USE_SERIAL_1_STDIN 0 + +#define ao_gps_getchar ao_serial1_getchar +#define ao_gps_putchar ao_serial1_putchar +#define ao_gps_set_speed ao_serial1_set_speed +#define ao_gps_fifo (ao_usart_rx_fifo) + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 1 +#define HAS_RDF 1 +#define HAS_APRS 1 +#define HAS_RADIO_RECV 0 + +#define HAS_GPS 1 +#define HAS_FLIGHT 0 +#define HAS_LOG 1 +#define FLIGHT_LOG_APPEND 1 +#define HAS_TRACKER 1 +#define LOG_ADC 0 + +#define AO_CONFIG_DEFAULT_APRS_INTERVAL 0 +#define AO_CONFIG_DEFAULT_RADIO_POWER 0xc0 + +/* + * GPS + */ + +#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600 + + +/* + * Radio (cc1120) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpioa) +#define AO_CC1200_SPI_CS_PIN 5 +#define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7 +#define AO_CC1200_SPI stm_spi1 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST + +#define AO_CC1200_INT_PORT (&stm_gpioa) +#define AO_CC1200_INT_PIN 4 +#define AO_CC1200_MCU_WAKEUP_PORT (&stm_gpioa) +#define AO_CC1200_MCU_WAKEUP_PIN (0) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#define AO_CC1200_MARC_GPIO 3 +#define AO_CC1200_MARC_GPIO_IOCFG CC1200_IOCFG3 + +#define HAS_BOOT_RADIO 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telegps-v2.0/ao_telegps.c b/src/telegps-v2.0/ao_telegps.c new file mode 100644 index 00000000..7a923d11 --- /dev/null +++ b/src/telegps-v2.0/ao_telegps.c @@ -0,0 +1,68 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + */ + +#include +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_timer_init(); + + ao_spi_init(); + ao_exti_init(); + + ao_storage_init(); + + ao_serial_init(); + + ao_cmd_init(); + + ao_usb_init(); + ao_radio_init(); + +#if HAS_ADC + ao_adc_init(); +#endif + + ao_gps_init(); +#if HAS_LOG + ao_log_init(); +#endif + + ao_tracker_init(); + + ao_telemetry_init(); + +#if HAS_SAMPLE_PROFILE + ao_sample_profile_init(); +#endif + ao_config_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/telegps-v2.0/flash-loader/Makefile b/src/telegps-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..c0659698 --- /dev/null +++ b/src/telegps-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telegps-v2.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/telegps-v2.0/flash-loader/ao_pins.h b/src/telegps-v2.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..a83dbaa2 --- /dev/null +++ b/src/telegps-v2.0/flash-loader/ao_pins.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2017 Bdale Garbee + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 15 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v0.3/ao_pins.h b/src/telelco-v0.3/ao_pins.h index d874a19b..dd4aaafb 100644 --- a/src/telelco-v0.3/ao_pins.h +++ b/src/telelco-v0.3/ao_pins.h @@ -89,6 +89,7 @@ #define AO_CC1200_SPI_CS_PIN 0 #define AO_CC1200_SPI_BUS AO_SPI_2_PD1_PD3_PD4 #define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioc) #define AO_CC1200_INT_PIN (15) diff --git a/src/telelcotwo-v0.1/ao_pins.h b/src/telelcotwo-v0.1/ao_pins.h index 714a5c3a..60e94c67 100644 --- a/src/telelcotwo-v0.1/ao_pins.h +++ b/src/telelcotwo-v0.1/ao_pins.h @@ -91,6 +91,7 @@ #define AO_CC1200_SPI_CS_PIN 7 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpiob) #define AO_CC1200_INT_PIN (11) diff --git a/src/telemega-v2.0/ao_pins.h b/src/telemega-v2.0/ao_pins.h index b1c472da..c7c8ad19 100644 --- a/src/telemega-v2.0/ao_pins.h +++ b/src/telemega-v2.0/ao_pins.h @@ -309,6 +309,7 @@ struct ao_adc { #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_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioe) #define AO_CC1200_INT_PIN 1 diff --git a/src/telemetrum-v3.0/ao_pins.h b/src/telemetrum-v3.0/ao_pins.h index ccf2f18f..b937b422 100644 --- a/src/telemetrum-v3.0/ao_pins.h +++ b/src/telemetrum-v3.0/ao_pins.h @@ -259,6 +259,7 @@ struct ao_adc { #define AO_CC1200_SPI_CS_PIN 2 #define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_FAST #define AO_CC1200_INT_PORT (&stm_gpioa) #define AO_CC1200_INT_PIN (3) diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index 4f1d36df..d2aa4c2d 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -115,8 +115,8 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) -#define AO_SEND_MINI -#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMINI +#define AO_SEND_MINI AO_TELEMETRY_MINI2 +#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMINI2 /* * ADC diff --git a/src/telemini-v3.0/Makefile b/src/telemini-v3.0/Makefile new file mode 100644 index 00000000..4713b3ad --- /dev/null +++ b/src/telemini-v3.0/Makefile @@ -0,0 +1,93 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + ao_cc1200.h \ + ao_cc1200_CC1200.h \ + stm32f0.h + +# +# Common AltOS sources +# + +ALTOS_SRC = \ + ao_interrupt.c \ + ao_boot_chain.c \ + ao_romconfig.c \ + ao_product.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_report.c \ + ao_ignite.c \ + ao_flight.c \ + ao_kalman.c \ + ao_sample.c \ + ao_data.c \ + ao_convert_pa.c \ + ao_convert_volt.c \ + ao_task.c \ + ao_log.c \ + ao_log_mini.c \ + ao_cmd.c \ + ao_config.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_timer.c \ + ao_exti_stm.c \ + ao_spi_stm.c \ + ao_adc_stm.c \ + ao_usb_stm.c \ + ao_m25.c \ + ao_ms5607.c \ + ao_cc1200.c \ + ao_telemetry.c \ + ao_packet_slave.c \ + ao_beep_stm.c \ + ao_packet.c + +PRODUCT=TeleMini-v3.0 +PRODUCT_DEF=-DTELEMINI_V_3_0 +IDPRODUCT=0x0027 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=telemini-v3.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telemini.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) + $(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) + +load: $(PROG) + lpc-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telemini-v3.0/ao_pins.h b/src/telemini-v3.0/ao_pins.h new file mode 100644 index 00000000..351d28d8 --- /dev/null +++ b/src/telemini-v3.0/ao_pins.h @@ -0,0 +1,188 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define HAS_BEEP 1 +#define HAS_SERIAL_1 0 +#define HAS_BATTERY_REPORT 1 + +#define AO_STACK_SIZE 448 + +#define IS_FLASH_LOADER 0 + +/* 48MHz clock based on 16MHz reference */ +//#define AO_HSI48 1 +#define AO_HSE 16000000 +#define AO_RCC_CFGR_PLLMUL STM_RCC_CFGR_PLLMUL_3 +#define AO_RCC_CFGR2_PLLDIV STM_RCC_CFGR2_PREDIV_1 +#define AO_PLLMUL 3 +#define AO_PLLDIV 1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 40MHz */ +#define AO_APB_PRESCALER 1 +#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 +#define AO_USB_FORCE_IDLE 1 + +#define PACKET_HAS_SLAVE 1 + +#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMINI3 +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 112 * (uint32_t) 1024) + +#define HAS_BOOT_RADIO 0 + +#define HAS_ACCEL 0 +#define HAS_GPS 0 +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_FLIGHT 1 +#define HAS_EEPROM 1 +#define HAS_TELEMETRY 1 +#define AO_SEND_MINI AO_TELEMETRY_MINI3 +#define HAS_APRS 0 +#define HAS_LOG 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 +#define AO_SMALL_ALTITUDE_TABLE 1 + +/* Beeper is on Tim1 CH3 */ +#define BEEPER_CHANNEL 4 +#define BEEPER_TIMER 2 +#define BEEPER_PORT (&stm_gpioa) +#define BEEPER_PIN 3 + +/* SPI */ + +#define HAS_SPI_1 1 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 1 +#define SPI_1_OSPEEDR STM_OSPEEDR_MEDIUM + +/* M25 */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT (&stm_gpioa) +#define AO_M25_SPI_CS_MASK (1 << 4) +#define AO_M25_SPI_BUS AO_SPI_1_PA5_PA6_PA7 + +/* MS5607 */ + +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define AO_MS5607_PRIVATE_PINS 1 +#define AO_MS5607_CS_PORT (&stm_gpioa) +#define AO_MS5607_CS_PIN 15 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) +#define AO_MS5607_MISO_PORT (&stm_gpiob) +#define AO_MS5607_MISO_PIN 4 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) +#define AO_MS5607_SPI_INDEX AO_SPI_1_PB3_PB4_PB5 +#define AO_MS5607_SPI_SPEED AO_SPI_SPEED_12MHz + +/* CC1200 */ + +// #define AO_RADIO_CAL_DEFAULT 5695733 +#define AO_RADIO_CAL_DEFAULT 5695717 + +#define AO_FEC_DEBUG 0 +#define CC1200_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpiob) +#define AO_CC1200_SPI_CS_PIN 0 +#define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7 +#define AO_CC1200_SPI stm_spi1 +#define AO_CC1200_SPI_SPEED AO_SPI_SPEED_12MHz + +#define AO_CC1200_INT_PORT (&stm_gpiob) +#define AO_CC1200_INT_PIN 1 + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + + +#define AO_DATA_RING 16 + +/* + * ADC + */ + +#define HAS_ADC 1 + +#define AO_ADC_PIN0_PORT (&stm_gpioa) /* sense_m */ +#define AO_ADC_PIN0_PIN 0 +#define AO_ADC_PIN0_CH 0 +#define AO_ADC_PIN1_PORT (&stm_gpioa) /* sense_a */ +#define AO_ADC_PIN1_PIN 1 +#define AO_ADC_PIN1_CH 1 +#define AO_ADC_PIN2_PORT (&stm_gpioa) /* v_batt */ +#define AO_ADC_PIN2_PIN 2 +#define AO_ADC_PIN2_CH 2 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN)) + +#define AO_NUM_ADC 3 + +struct ao_adc { + int16_t sense_m; + int16_t sense_a; + int16_t v_batt; +}; + +/* + * Igniter + */ + +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +#define AO_IGNITER_DROGUE_PORT (&stm_gpiob) +#define AO_IGNITER_DROGUE_PIN 7 +#define AO_IGNITER_SET_DROGUE(v) ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) + +#define AO_IGNITER_MAIN_PORT (&stm_gpiob) +#define AO_IGNITER_MAIN_PIN 6 +#define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) + +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ + (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS 56 /* 5.6k */ +#define AO_BATTERY_DIV_MINUS 100 /* 10k */ + +/* + * Voltage divider on ADC igniter samplers + */ +#define AO_IGNITE_DIV_PLUS 100 /* 100k */ +#define AO_IGNITE_DIV_MINUS 27 /* 27k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV 33 diff --git a/src/telemini-v3.0/ao_telemini.c b/src/telemini-v3.0/ao_telemini.c new file mode 100644 index 00000000..82c1acd4 --- /dev/null +++ b/src/telemini-v3.0/ao_telemini.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 +#include + +void +main(void) +{ + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + + ao_dma_init(); + ao_spi_init(); + ao_exti_init(); + + ao_adc_init(); + +#if HAS_BEEP + ao_beep_init(); +#endif +#if HAS_SERIAL_1 + ao_serial_init(); +#endif +#if HAS_USB + ao_usb_init(); +#endif + ao_cmd_init(); + + ao_ms5607_init(); + + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); + ao_config_init(); + + ao_start_scheduler(); +} diff --git a/src/telemini-v3.0/flash-loader/Makefile b/src/telemini-v3.0/flash-loader/Makefile new file mode 100644 index 00000000..8b628552 --- /dev/null +++ b/src/telemini-v3.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telemini-v3.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/telemini-v3.0/flash-loader/ao_pins.h b/src/telemini-v3.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..fea9a645 --- /dev/null +++ b/src/telemini-v3.0/flash-loader/ao_pins.h @@ -0,0 +1,37 @@ +/* + * Copyright © 2013 Keith Packard + * + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* beeper to 3.3V for boot loader mode */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 3 +#define AO_BOOT_APPLICATION_VALUE 0 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_DOWN + +/* USB */ +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/test/Makefile b/src/test/Makefile index 02e1d22b..a22abe46 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,16 +1,16 @@ -vpath % ..:../kernel:../drivers:../util:../micropeak:../aes:../product +vpath % ..:../kernel:../drivers:../util:../micropeak:../aes:../product:../lisp PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ ao_flight_test_metrum \ ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \ ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \ - ao_ms5607_convert_test ao_quaternion_test + ao_ms5607_convert_test ao_quaternion_test ao_lisp_test INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h KALMAN=make-kalman -CFLAGS=-I.. -I. -I../kernel -I../drivers -I../micropeak -I../product -O0 -g -Wall +CFLAGS=-I.. -I. -I../kernel -I../drivers -I../micropeak -I../product -I../lisp -O0 -g -Wall -DAO_LISP_TEST -no-pie all: $(PROGS) ao_aprs_data.wav @@ -88,3 +88,12 @@ ao_ms5607_convert_test: ao_ms5607_convert_test.c ao_ms5607_convert_8051.c ao_int ao_quaternion_test: ao_quaternion_test.c ao_quaternion.h cc $(CFLAGS) -o $@ ao_quaternion_test.c -lm +AO_LISP_OBJS = ao_lisp_test.o ao_lisp_mem.o ao_lisp_cons.o ao_lisp_string.o \ + ao_lisp_atom.o ao_lisp_int.o ao_lisp_eval.o ao_lisp_poly.o \ + ao_lisp_builtin.o ao_lisp_read.o ao_lisp_rep.o ao_lisp_frame.o \ + ao_lisp_lambda.o ao_lisp_error.o ao_lisp_save.o ao_lisp_stack.o + +ao_lisp_test: $(AO_LISP_OBJS) + cc $(CFLAGS) -o $@ $(AO_LISP_OBJS) + +$(AO_LISP_OBJS): ao_lisp.h ao_lisp_const.h ao_lisp_os.h diff --git a/src/test/ao_aprs_test.c b/src/test/ao_aprs_test.c index 3852668a..941bf954 100644 --- a/src/test/ao_aprs_test.c +++ b/src/test/ao_aprs_test.c @@ -60,6 +60,20 @@ ao_aprs_bit(uint8_t bit) void ao_radio_send_aprs(ao_radio_fill_func fill); +static void +aprs_bit_debug(uint8_t tx_bit) +{ + fprintf (stderr, "bit %d\n", tx_bit); +} + +static void +aprs_byte_debug(uint8_t tx_byte) +{ + fprintf(stderr, "byte %02x\n", tx_byte); +} +#define APRS_BIT_DEBUG(x) aprs_bit_debug(x) +#define APRS_BYTE_DEBUG(y) aprs_byte_debug(y) + #include /* @@ -103,7 +117,7 @@ audio_gap(int secs) // This is where we go after reset. int main(int argc, char **argv) { - audio_gap(1); +// audio_gap(1); ao_gps_data.latitude = (45.0 + 28.25 / 60.0) * 10000000; ao_gps_data.longitude = (-(122 + 44.2649 / 60.0)) * 10000000; diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index bd7f2ff8..25ddb48f 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -58,6 +58,7 @@ int ao_gps_new; #define HAS_HMC5883 1 #define HAS_BEEP 1 #define AO_CONFIG_MAX_SIZE 1024 +#define AO_MMA655X_INVERT 0 struct ao_adc { int16_t sense[AO_ADC_NUM_SENSE]; @@ -71,6 +72,7 @@ struct ao_adc { #define AO_ADC_NUM_SENSE 2 #define HAS_MS5607 1 #define HAS_MMA655X 1 +#define AO_MMA655X_INVERT 1 #define HAS_BEEP 1 #define AO_CONFIG_MAX_SIZE 1024 @@ -373,6 +375,8 @@ uint16_t prev_tick; #define AO_PYRO_2 2 #define AO_PYRO_3 3 +#define PYRO_DBG 1 + static void ao_pyro_pin_set(uint8_t pin, uint8_t value) { diff --git a/src/test/ao_lisp_os.h b/src/test/ao_lisp_os.h new file mode 100644 index 00000000..9ff2e1fe --- /dev/null +++ b/src/test/ao_lisp_os.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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_LISP_OS_H_ +#define _AO_LISP_OS_H_ + +#include +#include +#include + +#define AO_LISP_POOL_TOTAL 3072 +#define AO_LISP_SAVE 1 +#define DBG_MEM_STATS 1 + +extern int ao_lisp_getc(void); + +static inline void +ao_lisp_os_flush() { + fflush(stdout); +} + +static inline void +ao_lisp_abort(void) +{ + abort(); +} + +static inline void +ao_lisp_os_led(int led) +{ + printf("leds set to 0x%x\n", led); +} + +static inline void +ao_lisp_os_delay(int delay) +{ + if (!delay) + return; + struct timespec ts = { + .tv_sec = delay / 1000, + .tv_nsec = (delay % 1000) * 1000000, + }; + nanosleep(&ts, NULL); +} +#endif diff --git a/src/test/ao_lisp_test.c b/src/test/ao_lisp_test.c new file mode 100644 index 00000000..68e3a202 --- /dev/null +++ b/src/test/ao_lisp_test.c @@ -0,0 +1,134 @@ +/* + * Copyright © 2016 Keith Packard + * + * 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. + */ + +#include "ao_lisp.h" +#include + +static FILE *ao_lisp_file; +static int newline = 1; + +static char save_file[] = "lisp.image"; + +int +ao_lisp_os_save(void) +{ + FILE *save = fopen(save_file, "w"); + + if (!save) { + perror(save_file); + return 0; + } + fwrite(ao_lisp_pool, 1, AO_LISP_POOL_TOTAL, save); + fclose(save); + return 1; +} + +int +ao_lisp_os_restore_save(struct ao_lisp_os_save *save, int offset) +{ + FILE *restore = fopen(save_file, "r"); + size_t ret; + + if (!restore) { + perror(save_file); + return 0; + } + fseek(restore, offset, SEEK_SET); + ret = fread(save, sizeof (struct ao_lisp_os_save), 1, restore); + fclose(restore); + if (ret != 1) + return 0; + return 1; +} + +int +ao_lisp_os_restore(void) +{ + FILE *restore = fopen(save_file, "r"); + size_t ret; + + if (!restore) { + perror(save_file); + return 0; + } + ret = fread(ao_lisp_pool, 1, AO_LISP_POOL_TOTAL, restore); + fclose(restore); + if (ret != AO_LISP_POOL_TOTAL) + return 0; + return 1; +} + +int +ao_lisp_getc(void) +{ + int c; + + if (ao_lisp_file) + return getc(ao_lisp_file); + + if (newline) { + printf("> "); + newline = 0; + } + c = getchar(); + if (c == '\n') + newline = 1; + return c; +} + +int +main (int argc, char **argv) +{ + while (*++argv) { + ao_lisp_file = fopen(*argv, "r"); + if (!ao_lisp_file) { + perror(*argv); + exit(1); + } + ao_lisp_read_eval_print(); + fclose(ao_lisp_file); + ao_lisp_file = NULL; + } + ao_lisp_read_eval_print(); + + printf ("collects: full: %d incremental %d\n", + ao_lisp_collects[AO_LISP_COLLECT_FULL], + ao_lisp_collects[AO_LISP_COLLECT_INCREMENTAL]); + + printf ("freed: full %d incremental %d\n", + ao_lisp_freed[AO_LISP_COLLECT_FULL], + ao_lisp_freed[AO_LISP_COLLECT_INCREMENTAL]); + + printf("loops: full %d incremental %d\n", + ao_lisp_loops[AO_LISP_COLLECT_FULL], + ao_lisp_loops[AO_LISP_COLLECT_INCREMENTAL]); + + printf("loops per collect: full %f incremental %f\n", + (double) ao_lisp_loops[AO_LISP_COLLECT_FULL] / + (double) ao_lisp_collects[AO_LISP_COLLECT_FULL], + (double) ao_lisp_loops[AO_LISP_COLLECT_INCREMENTAL] / + (double) ao_lisp_collects[AO_LISP_COLLECT_INCREMENTAL]); + + printf("freed per collect: full %f incremental %f\n", + (double) ao_lisp_freed[AO_LISP_COLLECT_FULL] / + (double) ao_lisp_collects[AO_LISP_COLLECT_FULL], + (double) ao_lisp_freed[AO_LISP_COLLECT_INCREMENTAL] / + (double) ao_lisp_collects[AO_LISP_COLLECT_INCREMENTAL]); + + printf("freed per loop: full %f incremental %f\n", + (double) ao_lisp_freed[AO_LISP_COLLECT_FULL] / + (double) ao_lisp_loops[AO_LISP_COLLECT_FULL], + (double) ao_lisp_freed[AO_LISP_COLLECT_INCREMENTAL] / + (double) ao_lisp_loops[AO_LISP_COLLECT_INCREMENTAL]); +} diff --git a/src/test/hanoi.lisp b/src/test/hanoi.lisp new file mode 100644 index 00000000..e2eb0fa0 --- /dev/null +++ b/src/test/hanoi.lisp @@ -0,0 +1,155 @@ +; +; Towers of Hanoi +; +; Copyright © 2016 Keith Packard +; +; 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. +; + + ; ANSI control sequences + +(defun move-to (col row) + (patom "\033[" row ";" col "H") + ) + +(defun clear () + (patom "\033[2J") + ) + +(defun display-string (x y str) + (move-to x y) + (patom str) + ) + + ; Here's the pieces to display + +(setq stack '(" * " " *** " " ***** " " ******* " " ********* " "***********")) + + ; Here's all of the stacks of pieces + ; This is generated when the program is run + +(setq stacks nil) + + ; Display one stack, clearing any + ; space above it + +(defun display-stack (x y clear stack) + (cond ((= 0 clear) + (cond (stack + (display-string x y (car stack)) + (display-stack x (1+ y) 0 (cdr stack)) + ) + ) + ) + (t + (display-string x y " ") + (display-stack x (1+ y) (1- clear) stack) + ) + ) + ) + + ; Position of the top of the stack on the screen + ; Shorter stacks start further down the screen + +(defun stack-pos (y stack) + (- y (length stack)) + ) + + ; Display all of the stacks, spaced 20 columns apart + +(defun display-stacks (x y stacks) + (cond (stacks + (display-stack x 0 (stack-pos y (car stacks)) (car stacks)) + (display-stacks (+ x 20) y (cdr stacks))) + ) + ) + + ; Display all of the stacks, then move the cursor + ; out of the way and flush the output + +(defun display () + (display-stacks 0 top stacks) + (move-to 1 21) + (flush) + ) + + ; Reset stacks to the starting state, with + ; all of the pieces in the first stack and the + ; other two empty + +(defun reset-stacks () + (setq stacks (list stack nil nil)) + (setq top (+ (length stack) 3)) + (length stack) + ) + + ; more functions which could usefully + ; be in the rom image + +(defun min (a b) + (cond ((< a b) a) + (b) + ) + ) + + ; Replace a stack in the list of stacks + ; with a new value + +(defun replace (list pos member) + (cond ((= pos 0) (cons member (cdr list))) + ((cons (car list) (replace (cdr list) (1- pos) member))) + ) + ) + + ; Move a piece from the top of one stack + ; to the top of another + +(setq move-delay 100) + +(defun move-piece (from to) + (let ((from-stack (nth stacks from)) + (to-stack (nth stacks to)) + (piece (car from-stack))) + (setq from-stack (cdr from-stack)) + (setq to-stack (cons piece to-stack)) + (setq stacks (replace stacks from from-stack)) + (setq stacks (replace stacks to to-stack)) + (display) + (delay move-delay) + ) + ) + +; The implementation of the game + +(defun _hanoi (n from to use) + (cond ((= 1 n) + (move-piece from to) + ) + (t + (_hanoi (1- n) from use to) + (_hanoi 1 from to use) + (_hanoi (1- n) use to from) + ) + ) + ) + + ; A pretty interface which + ; resets the state of the game, + ; clears the screen and runs + ; the program + +(defun hanoi () + (setq len (reset-stacks)) + (clear) + (_hanoi len 0 1 2) + (move-to 0 23) + t + )