pad_alt = ground_altitude;
}
+ data.new_gps = false;
+
gps_waiting = MIN_PAD_SAMPLES - npad;
if (gps_waiting < 0)
gps_waiting = 0;
}
public void resetData() {
- for (AltosUIGrapher g : graphers)
+ for (AltosUIGrapher g : graphers) {
g.clear();
+ g.setNotify(false);
+ }
if (dataSet != null) {
for (AltosUIDataPoint dataPoint : dataSet.dataPoints())
for (AltosUIGrapher g : graphers)
g.add(dataPoint);
}
+ for (AltosUIGrapher g : graphers) {
+ g.setNotify(true);
+ g.fireSeriesChanged();
+ }
}
public void units_changed(boolean imperial_units) {
public abstract void add(AltosUIDataPoint dataPoint);
public abstract void set_enable(boolean enable);
+
+ public abstract void setNotify(boolean notify);
+
+ public abstract void fireSeriesChanged();
}
this.enabled = enable;
}
+ public void setNotify(boolean notify) {
+ }
+
+ public void fireSeriesChanged() {
+ }
+
public AltosUIMarker (int fetch, Color color, XYPlot plot) {
this(fetch, color, plot, true);
}
-SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload ao-send-telem ao-sky-flash
+SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list \
+ ao-load ao-telem ao-stmload ao-send-telem ao-sky-flash \
+ ao-dumpflash
--- /dev/null
+ao-dumpflash
--- /dev/null
+bin_PROGRAMS=ao-dumpflash
+
+AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS)
+AO_DUMPLOG_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a
+
+ao_dumpflash_DEPENDENCIES = $(AO_DUMPLOG_LIBS)
+
+ao_dumpflash_LDADD=$(AO_DUMPLOG_LIBS) $(LIBUSB_LIBS)
+
+ao_dumpflash_SOURCES = ao-dumpflash.c
+
+man_MANS = ao-dumpflash.1
--- /dev/null
+.\"
+.\" Copyright © 2013 Keith Packard <keithp@keithp.com>
+.\"
+.\" This program is free software; you can redistribute it and/or modify
+.\" it under the terms of the GNU General Public License as published by
+.\" the Free Software Foundation; either version 2 of the License, or
+.\" (at your option) any later version.
+.\"
+.\" This program is distributed in the hope that it will be useful, but
+.\" WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+.\" General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public License along
+.\" with this program; if not, write to the Free Software Foundation, Inc.,
+.\" 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+.\"
+.\"
+.TH AO-DUMPFLASH 1 "ao-dumpflash" ""
+.SH NAME
+ao-dumpflash \- Fetch flash memory contents from AltOS device
+.SH SYNOPSIS
+.B "ao-dumpflash"
+[\--tty \fItty-device\fP]
+[\--device \fIaltos-device\fP]
+[\--output \fIoutput-file\fP]
+[\--remote\fP]
+[\--frequency \fIfrequency\fP]
+[\--call \fIcallsign\fP]
+.SH OPTIONS
+.TP
+\-T tty-device | --tty tty-device
+This selects which tty device ao-dumpflash uses to communicate with
+the target device.
+.TP
+\-D AltOS-device | --device AltOS-device
+Search for a connected device. This requires an argument of one of the
+following forms:
+.IP
+TeleMetrum:2
+.br
+TeleMetrum
+.br
+2
+.IP
+Leaving out the product name will cause the tool to select a suitable
+product, leaving out the serial number will cause the tool to match
+one of the available devices.
+.TP
+\-o output-file | --output output-file
+Write flash contents to the specified file rather than stdout.
+.TP
+\-R | --remote
+This uses the command radio link to download the flash from TeleMetrum
+through a TeleDongle.
+.TP
+\-F frequency | --frequency frequency
+Specifies the radio frequency to use for remote communications in
+kHz. Default is 434550.
+.TP
+\-C callsign | --call callsign
+Specifies the callsign to use for remote communications. Default is N0CALL.
+.SH DESCRIPTION
+.I ao-dumpflash
+downloads the entire flash memory contents from a connected AltOS device and writes
+it to either stdout or the specified output file.
+.SH USAGE
+.I ao-dumpflash
+connects to the specified target device and dumps the flash.
+.SH AUTHOR
+Keith Packard
--- /dev/null
+/*
+ * Copyright © 2009 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include "cc-usb.h"
+#include "cc.h"
+
+#define NUM_BLOCK 512
+
+static const struct option options[] = {
+ { .name = "tty", .has_arg = 1, .val = 'T' },
+ { .name = "device", .has_arg = 1, .val = 'D' },
+ { .name = "remote", .has_arg = 0, .val = 'R' },
+ { .name = "frequency", .has_arg = 1, .val = 'F' },
+ { .name = "call", .has_arg = 1, .val = 'C' },
+ { .name = "output", .has_arg = 1, .val = 'o' },
+ { 0, 0, 0, 0},
+};
+
+static void usage(char *program)
+{
+ fprintf(stderr, "usage: %s [--tty <tty-name>] [--device <device-name>] [--remote] [--frequency <radio-frequency>] [--call <radio-callsign>]\n", program);
+ exit(1);
+}
+
+int
+main (int argc, char **argv)
+{
+ struct cc_usb *cc;
+ char *tty = NULL;
+ char *device = NULL;
+ int c;
+ char line[8192];
+ FILE *out;
+ char *filename;
+ int serial_number = 0;
+ int freq = 434550;
+ char *call = "N0CALL";
+ int flight = 0;
+ char cmd;
+ int block;
+ int addr;
+ int received_addr;
+ int data[8];
+ int done;
+ int i;
+ int column;
+ int remote = 0;
+ int any_valid;
+ int invalid;
+ int storage_size = 0;
+ char *out_name;
+
+ while ((c = getopt_long(argc, argv, "T:D:F:C:o:R", options, NULL)) != -1) {
+ switch (c) {
+ case 'T':
+ tty = optarg;
+ break;
+ case 'D':
+ device = optarg;
+ break;
+ case 'R':
+ remote = 1;
+ break;
+ case 'F':
+ freq = atoi(optarg);
+ break;
+ case 'C':
+ call = optarg;
+ break;
+ case 'o':
+ out_name = optarg;
+ break;
+ default:
+ usage(argv[0]);
+ break;
+ }
+ }
+ if (!tty) {
+ if (remote)
+ tty = cc_usbdevs_find_by_arg(device, "TeleDongle");
+ else
+ tty = cc_usbdevs_find_by_arg(device, "TeleMetrum");
+ }
+ if (!tty)
+ tty = getenv("ALTOS_TTY");
+ if (!tty)
+ tty="/dev/ttyACM0";
+
+ cc = cc_usb_open(tty);
+ if (!cc)
+ exit(1);
+ if (remote)
+ cc_usb_open_remote(cc, freq, call);
+
+ if (out_name) {
+ out = fopen(out_name, "w");
+ if (!out) {
+ perror(out_name);
+ cc_usb_close(cc);
+ exit(1);
+ }
+ } else
+ out = stdout;
+
+ /* send a 'version' command followed by a 'flash' command */
+ cc_usb_printf(cc, "f\nv\n");
+ for (;;) {
+ cc_usb_getline(cc, line, sizeof (line));
+ if (sscanf(line, "serial-number %u", &serial_number) == 1)
+ continue;
+ if (sscanf(line, "Storage size: %u", &storage_size) == 1)
+ continue;
+ if (!strncmp(line, "software-version", 16))
+ break;
+ }
+ if (!serial_number) {
+ fprintf(stderr, "no serial number found\n");
+ cc_usb_close(cc);
+ exit(1);
+ }
+ if (!storage_size) {
+ fprintf(stderr, "no storage size found\n");
+ cc_usb_close(cc);
+ exit(1);
+ }
+ printf ("Serial number: %d\n", serial_number);
+ printf ("Storage size: %d\n", storage_size);
+ fprintf (stderr, "%7d of %7d", 0, storage_size/256);
+ for (block = 0; block < storage_size / 256; block++) {
+ cc_usb_printf(cc, "e %x\n", block);
+ fprintf (stderr, "\r%7d of %7d", block + 1, storage_size/256); fflush(stderr);
+ for (addr = 0; addr < 0x100;) {
+ cc_usb_getline(cc, line, sizeof (line));
+ if (sscanf(line, "00%x %x %x %x %x %x %x %x %x",
+ &received_addr,
+ &data[0], &data[1], &data[2], &data[3],
+ &data[4], &data[5], &data[6], &data[7]) == 9)
+ {
+ if (received_addr != addr)
+ fprintf(stderr, "data out of sync at 0x%x\n",
+ block * 256 + received_addr);
+
+ fprintf (out, "%08x", block * 256 + addr);
+ for (i = 0; i < 8; i++)
+ fprintf (out, " %02x", data[i]);
+ fprintf (out, "\n");
+
+ addr += 8;
+ }
+ }
+ }
+ fprintf(stderr, "\n");
+ cc_usb_close(cc);
+ exit (0);
+}
}
void
-cc_usb_open_remote(struct cc_usb *cc, int channel)
+cc_usb_open_remote(struct cc_usb *cc, int freq, char *call)
{
if (!cc->remote) {
- printf ("channel %d\n", channel);
- cc_usb_printf(cc, "\nc r %d\np\nE 0\n", channel);
+ fprintf (stderr, "freq %dkHz\n", freq);
+ fprintf (stderr, "call %s\n", call);
+ cc_usb_printf(cc, "\nc F %d\nc c %s\np\nE 0\n", freq, call);
do {
cc->in_count = cc->in_pos = 0;
_cc_usb_sync(cc, 100);
cc_usb_printf(struct cc_usb *cc, char *format, ...);
void
-cc_usb_open_remote(struct cc_usb *cc, int channel);
+cc_usb_open_remote(struct cc_usb *cc, int freq, char *call);
void
cc_usb_close_remote(struct cc_usb *cc);
uint8_t
ccdbg_flash_hex_image(struct ccdbg *dbg, struct hex_image *image)
{
- uint16_t offset;
uint16_t flash_prog;
uint16_t flash_len;
uint8_t fwt;
uint16_t flash_words;
uint8_t flash_words_high, flash_words_low;
uint16_t ram_addr;
- uint16_t pc;
uint8_t status;
uint16_t remain, this_time, start;
uint8_t verify[0x400];
if (this_time > 0x400)
this_time = 0x400;
- offset = ram_addr - (image->address + start);
-
ccdbg_debug(CC_DEBUG_FLASH, "Upload %d bytes at 0x%04x\n", this_time, ram_addr);
ccdbg_write_memory(dbg, ram_addr, image->data + start, this_time);
#if 0
ccdbg_write_uint8(dbg, flash_prog + FLASH_WORDS_LOW, flash_words_low);
ccdbg_set_pc(dbg, flash_prog);
- pc = ccdbg_get_pc(dbg);
ccdbg_debug(CC_DEBUG_FLASH, "Flashing %d bytes at 0x%04x\n",
this_time, flash_addr);
status = ccdbg_resume(dbg);
dnl Process this file with autoconf to create configure.
AC_PREREQ(2.57)
-AC_INIT([altos], 1.1.9.3)
+AC_INIT([altos], 1.2)
AC_CONFIG_SRCDIR([src/core/ao.h])
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
ao-tools/ao-stmload/Makefile
ao-tools/ao-send-telem/Makefile
ao-tools/ao-sky-flash/Makefile
+ao-tools/ao-dumpflash/Makefile
ao-utils/Makefile
src/Version
])
release-notes-0.9.html \
release-notes-0.9.2.html \
release-notes-1.0.1.html \
+ release-notes-1.1.html \
release-notes-1.1.1.html \
- release-notes-1.1.html
+ release-notes-1.2.html
RELNOTES_XSL=$(RELNOTES:.html=.xsl)
HTML=altusmetrum.html altos.html telemetry.html companion.html micropeak.html $(RELNOTES)
tower with a screw-driver trying to turn on your avionics before
installing igniters!
</para>
+ <para>
+ TeleMini is configured 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
+ offers an 'emergency recovery' mode. In this mode, TeleMini is
+ configured as follows:
+ <itemizedlist>
+ <listitem>
+ Sets the radio frequency to 434.550MHz
+ </listitem>
+ <listitem>
+ Sets the radio calibration back to the factory value.
+ </listitem>
+ <listitem>
+ Sets the callsign to N0CALL
+ </listitem>
+ <listitem>
+ Does not go to 'pad' mode after five seconds.
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ To get into 'emergency recovery' mode, first find the row of
+ four small holes opposite the switch wiring. Using a short
+ piece of small gauge wire, connect the outer two holes
+ together, then power TeleMini up. Once the red LED is lit,
+ disconnect the wire and the board should signal that it's in
+ 'idle' mode after the initial five second startup period.
+ </para>
</section>
<section>
<title>GPS </title>
<appendix
xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Release Notes</title>
+ <simplesect><title>Version 1.2</title><xi:include href="release-notes-1.2.xsl" xpointer="xpointer(/article/*)"/></simplesect>
<simplesect><title>Version 1.1.1</title><xi:include href="release-notes-1.1.1.xsl" xpointer="xpointer(/article/*)"/></simplesect>
<simplesect><title>Version 1.1</title><xi:include href="release-notes-1.1.xsl" xpointer="xpointer(/article/*)"/></simplesect>
<simplesect><title>Version 1.0.1</title><xi:include href="release-notes-1.0.1.xsl" xpointer="xpointer(/article/*)"/></simplesect>
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
+"/usr/share/xml/docbook/schema/dtd/4.5/docbookx.dtd">
+
+<article>
+ <para>
+ Version 1.2 is a minor release. It provides a few new features in AltosUI
+ and the AltOS firmware and fixes bugs.
+ </para>
+ <para>
+ AltOS Firmware Changes
+ <itemizedlist>
+ <listitem>
+ In TeleMini recovery mode (when booted with the outer two
+ debug pins connected together), the radio parameters are also
+ set back to defaults (434.550MHz, N0CALL, factory radio cal).
+ </listitem>
+ <listitem>
+ Add support for reflashing the SkyTraq GPS chips. This
+ requires special host-side code which currently only exists
+ for Linux.
+ </listitem>
+ <listitem>
+ Add MicroPeak support. This includes support for the ATtiny85
+ processor and adaptations to the core code to allow for
+ devices too small to run the multi-tasking scheduler.
+ </listitem>
+ <listitem>
+ Correct Kalman filter model error covariance matrix. The
+ values used previously assumed continuous measurements instead
+ of discrete measurements.
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ AltosUI Changes
+ <itemizedlist>
+ <listitem>
+ Handle missing GPS lock in 'Descent' tab. Previously, if the
+ GPS position of the pad was unknown, an exception would be
+ raised, breaking the Descent tab contents.
+ </listitem>
+ <listitem>
+ Add preliminary MegaMetrum support, including configuration,
+ data download and analysis.
+ </listitem>
+ <listitem>
+ Improve the graph, adding tool-tips to show values near the
+ cursor and making the displayed set of values configurable,
+ adding all of the flight data as options while leaving the
+ default settings alone so that the graph starts by showing
+ height, speed and acceleration.
+ </listitem>
+ <listitem>
+ Make the initial position of the AltosUI top level window
+ configurable. Along with this change, the other windows will
+ pop up at 'sensible' places now, instead of on top of one
+ another.
+ </listitem>
+ <listitem>
+ Add callsign to Monitor idle window and connecting
+ dialogs. This makes it clear which callsign is being used so
+ that the operator will be aware that it must match the flight
+ computer value or no communication will work.
+ </listitem>
+ <listitem>
+ When downloading flight data, display the block number so that
+ the user has some sense of progress. Unfortunately, we don't
+ know how many blocks will need to be downloaded, but at least
+ it isn't just sitting there doing nothing for a long time.
+ </listitem>
+ <listitem>
+ Add GPS data and a map to the graph window. This lets you see
+ a complete summary of the flight without needing to 'replay'
+ the whole thing.
+ </listitem>
+ </itemizedlist>
+ </para>
+ <para>
+ Distribution Changes
+ <itemizedlist>
+ <listitem>
+ Distribute Mac OS X packages in disk image ('.dmg') format to
+ greatly simplify installation.
+ </listitem>
+ <listitem>
+ Provide version numbers for the shared Java libraries to
+ ensure that upgrades work properly, and to allow for multiple
+ Altus Metrum software packages to be installed in the same
+ directory at the same time.
+ </listitem>
+ </itemizedlist>
+ </para>
+</article>
OVERLAPPED ov_write;
};
+#include <stdarg.h>
+
+static void
+log_message(char *fmt, ...)
+{
+ static FILE *log = NULL;
+ va_list a;
+
+ if (!log)
+ log = fopen("\\temp\\altos.txt", "w");
+ if (log) {
+ va_start(a, fmt);
+ vfprintf(log, fmt, a);
+ va_end(a);
+ fflush(log);
+ }
+}
+
static void
_altos_set_last_windows_error(char *file, int line)
{
sizeof (message) / sizeof (TCHAR),
NULL);
if (error != ERROR_SUCCESS)
- printf ("%s:%d %s\n", file, line, message);
+ log_message ("%s:%d %s\n", file, line, message);
altos_set_last_error(error, message);
}
KEY_READ);
if (dev_key == INVALID_HANDLE_VALUE) {
altos_set_last_windows_error();
- printf("cannot open device registry key\n");
continue;
}
symbolic, &symbolic_len);
if (result != 0) {
altos_set_last_windows_error();
- printf("cannot find SymbolicName value\n");
RegCloseKey(dev_key);
continue;
}
RegCloseKey(dev_key);
if (result != 0) {
altos_set_last_windows_error();
- printf("failed to get PortName\n");
continue;
}
&friendlyname_len))
{
altos_set_last_windows_error();
- printf("Failed to get friendlyname\n");
continue;
}
device->vendor = vid;
return 1;
}
result = GetLastError();
- if (result != ERROR_NO_MORE_ITEMS) {
+ if (result != ERROR_NO_MORE_ITEMS)
altos_set_last_windows_error();
- printf ("SetupDiEnumDeviceInfo failed error %d\n", (int) result);
- }
return 0;
}
return LIBALTOS_TIMEOUT;
break;
default:
+ altos_set_last_windows_error();
return LIBALTOS_ERROR;
}
return LIBALTOS_SUCCESS;
if (!WriteFile(file->handle, data, used, &put, &file->ov_write)) {
if (GetLastError() != ERROR_IO_PENDING) {
altos_set_last_windows_error();
- printf ("\tflush write error\n");
return LIBALTOS_ERROR;
}
ret = WaitForSingleObject(file->ov_write.hEvent, INFINITE);
case WAIT_OBJECT_0:
if (!GetOverlappedResult(file->handle, &file->ov_write, &put, FALSE)) {
altos_set_last_windows_error();
- printf ("\tflush result error\n");
return LIBALTOS_ERROR;
}
break;
default:
altos_set_last_windows_error();
- printf ("\tflush wait error\n");
return LIBALTOS_ERROR;
}
}
return LIBALTOS_SUCCESS;
}
+static HANDLE
+open_serial(char *full_name)
+{
+ HANDLE handle;
+ DCB dcb;
+
+ handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
+ 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!GetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ dcb.BaudRate = CBR_9600;
+ dcb.fBinary = TRUE;
+ dcb.fParity = FALSE;
+ dcb.fOutxCtsFlow = FALSE;
+ dcb.fOutxDsrFlow = FALSE;
+ dcb.fDtrControl = DTR_CONTROL_ENABLE;
+ dcb.fDsrSensitivity = FALSE;
+ dcb.fTXContinueOnXoff = FALSE;
+ dcb.fOutX = FALSE;
+ dcb.fInX = FALSE;
+ dcb.fErrorChar = FALSE;
+ dcb.fNull = FALSE;
+ dcb.fRtsControl = RTS_CONTROL_ENABLE;
+ dcb.fAbortOnError = FALSE;
+ dcb.XonLim = 10;
+ dcb.XoffLim = 10;
+ dcb.ByteSize = 8;
+ dcb.Parity = NOPARITY;
+ dcb.StopBits = ONESTOPBIT;
+ dcb.XonChar = 17;
+ dcb.XoffChar = 19;
+#if 0
+ dcb.ErrorChar = 0;
+ dcb.EofChar = 0;
+ dcb.EvtChar = 0;
+#endif
+ if (!SetCommState(handle, &dcb)) {
+ altos_set_last_windows_error();
+ CloseHandle(handle);
+ return INVALID_HANDLE_VALUE;
+ }
+ return handle;
+}
+
PUBLIC struct altos_file *
altos_open(struct altos_device *device)
{
struct altos_file *file = calloc (1, sizeof (struct altos_file));
char full_name[64];
COMMTIMEOUTS timeouts;
- DCB dcb;
if (!file)
return NULL;
strcpy(full_name, "\\\\.\\");
strcat(full_name, device->path);
- file->handle = CreateFile(full_name, GENERIC_READ|GENERIC_WRITE,
- 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, NULL);
+
+ file->handle = open_serial(full_name);
if (file->handle == INVALID_HANDLE_VALUE) {
- altos_set_last_windows_error();
- printf ("cannot open %s\n", full_name);
free(file);
return NULL;
}
- file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+
+ /* The FTDI driver doesn't appear to work right unless you open it twice */
+ if (device->vendor == 0x0403) {
+ CloseHandle(file->handle);
+ file->handle = open_serial(full_name);
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ free(file);
+ return NULL;
+ }
+ }
timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(file->handle, &timeouts);
- if (GetCommState(file->handle, &dcb)) {
- dcb.BaudRate = CBR_9600;
- (void) SetCommState(file->handle, &dcb);
- }
+ file->ov_read.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ file->ov_write.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
return file;
}
{
int ret;
while (file->in_read == file->in_used) {
- if (file->handle == INVALID_HANDLE_VALUE)
+ if (file->handle == INVALID_HANDLE_VALUE) {
+ altos_set_last_windows_error();
return LIBALTOS_ERROR;
+ }
ret = altos_fill(file, timeout);
if (ret)
return ret;
telescience-v0.1 telescience-pwm telepyro-v0.1 micropeak
ARMDIRS=\
- megametrum-v0.1 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1
+ megametrum-v0.1 megadongle-v0.1 stm-bringup stm-demo telelco-v0.1 \
+ telescience-v0.2
ifneq ($(shell which sdcc),)
SUBDIRS += $(SDCCDIRS)
#include "ao.h"
uint8_t
-ao_spi_slave_recv(uint8_t *buf, uint8_t len)
+ao_spi_slave_recv(void *buf, uint16_t len)
{
+ uint8_t *b = buf;
while (len--) {
while (!(SPSR & (1 << SPIF)))
if ((PINB & (1 << PINB0)))
return 0;
- *buf++ = SPDR;
+ *b++ = SPDR;
}
return 1;
}
void
-ao_spi_slave_send(uint8_t *buf, uint8_t len)
+ao_spi_slave_send(void *buf, uint16_t len)
{
+ uint8_t *b = buf;
while (len--) {
- SPDR = *buf++;
+ SPDR = *b++;
while (!(SPSR & (1 << SPIF)))
if ((PINB & (1 << PINB0)))
return;
*/
uint8_t
-ao_spi_slave_recv(uint8_t *buf, uint8_t len);
+ao_spi_slave_recv(void *buf, uint16_t len);
void
-ao_spi_slave_send(uint8_t *buf, uint8_t len);
+ao_spi_slave_send(void *buf, uint16_t len);
void
ao_spi_slave_init(void);
#define FOSC 32000000
-#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_1MHz)
+#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_4MHz)
#define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS)
#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS)
#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS)
ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE);
ao_alarm(AO_MS_TO_TICKS(10));
- cli();
+ ao_arch_block_interrupts();
while (!ao_hmc5883_done)
if (ao_sleep(&ao_hmc5883_done))
++ao_hmc5883_missed_irq;
- sei();
+ ao_arch_release_interrupts();
ao_clear_alarm();
ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample));
ao_i2c_put(AO_HMC5883_I2C_INDEX);
if (!present)
- ao_panic(AO_PANIC_SELF_TEST);
+ ao_panic(AO_PANIC_SELF_TEST_HMC5883);
ao_hmc5883_reg_write(HMC5883_CONFIG_A,
(HMC5883_CONFIG_A_MA_8 << HMC5883_CONFIG_A_MA) |
#define HAS_SPI_2 1
#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */
#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
#define SPI_2_PORT (&stm_gpiob)
#define SPI_2_SCK_PIN 13
#define SPI_1_PA5_PA6_PA7 1 /* Barometer */
#define SPI_1_PB3_PB4_PB5 0
#define SPI_1_PE13_PE14_PE15 1 /* Accelerometer */
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
#define HAS_SPI_2 1
#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */
#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
#define SPI_2_PORT (&stm_gpiob)
#define SPI_2_SCK_PIN 13
#define HAS_SPI_1 1
#define SPI_1_PB3_PB4_PB5 1
+#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz
#define HAS_SPI_2 0
/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */
-#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 /* This doesn't appear to work */
+#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2
#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4
#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8
#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16
#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128
#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256
-#define AO_SPI_SPEED_FAST AO_SPI_SPEED_4MHz
+#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz
/* Companion bus wants something no faster than 200kHz */
#if HAS_SPI_1
# if SPI_1_PA5_PA6_PA7
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
+ stm_ospeedr_set(&stm_gpioa, 5, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 6, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioa, 7, SPI_1_OSPEEDR);
# endif
# if SPI_1_PB3_PB4_PB5
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
+ stm_ospeedr_set(&stm_gpiob, 3, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 4, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 5, SPI_1_OSPEEDR);
# endif
# if SPI_1_PE13_PE14_PE15
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN);
+ stm_ospeedr_set(&stm_gpioe, 13, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioe, 14, SPI_1_OSPEEDR);
+ stm_ospeedr_set(&stm_gpioe, 15, SPI_1_OSPEEDR);
# endif
stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN);
ao_spi_index[0] = AO_SPI_CONFIG_NONE;
#if HAS_SPI_2
# if SPI_2_PB13_PB14_PB15
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
+ stm_ospeedr_set(&stm_gpiob, 13, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 14, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiob, 15, SPI_2_OSPEEDR);
# endif
# if SPI_2_PD1_PD3_PD4
stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN);
+ stm_ospeedr_set(&stm_gpiod, 1, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiod, 3, SPI_2_OSPEEDR);
+ stm_ospeedr_set(&stm_gpiod, 4, SPI_2_OSPEEDR);
# endif
stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN);
ao_spi_index[1] = AO_SPI_CONFIG_NONE;
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+
+struct ao_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);
+}
+
+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
+}
#define STM_LCD_CLR_UDDC (3)
#define STM_LCD_CLR_SOFC (1)
+/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */
+
struct stm_nvic {
- vuint32_t iser[3]; /* 0x000 */
+ vuint32_t iser[8]; /* 0x000 0xe000e100 Set Enable Register */
+
+ uint8_t _unused020[0x080 - 0x020];
+
+ vuint32_t icer[8]; /* 0x080 0xe000e180 Clear Enable Register */
- uint8_t _unused00c[0x080 - 0x00c];
+ uint8_t _unused0a0[0x100 - 0x0a0];
- vuint32_t icer[3]; /* 0x080 */
+ vuint32_t ispr[8]; /* 0x100 0xe000e200 Set Pending Register */
- uint8_t _unused08c[0x100 - 0x08c];
+ uint8_t _unused120[0x180 - 0x120];
- vuint32_t ispr[3]; /* 0x100 */
+ vuint32_t icpr[8]; /* 0x180 0xe000e280 Clear Pending Register */
- uint8_t _unused10c[0x180 - 0x10c];
+ uint8_t _unused1a0[0x200 - 0x1a0];
- vuint32_t icpr[3]; /* 0x180 */
+ vuint32_t iabr[8]; /* 0x200 0xe000e300 Active Bit Register */
- uint8_t _unused18c[0x200 - 0x18c];
+ uint8_t _unused220[0x300 - 0x220];
- vuint32_t iabr[3]; /* 0x200 */
+ vuint32_t ipr[60]; /* 0x300 0xe000e400 Priority Register */
- uint8_t _unused20c[0x300 - 0x20c];
+ uint8_t _unused3f0[0xc00 - 0x3f0];
- vuint32_t ipr[21]; /* 0x300 */
+ vuint32_t cpuid_base; /* 0xc00 0xe000ed00 CPUID Base Register */
+ vuint32_t ics; /* 0xc04 0xe000ed04 Interrupt Control State Register */
+ vuint32_t vto; /* 0xc08 0xe000ed08 Vector Table Offset Register */
+ vuint32_t ai_rc; /* 0xc0c 0xe000ed0c Application Interrupt/Reset Control Register */
+ vuint32_t sc; /* 0xc10 0xe000ed10 System Control Register */
+ vuint32_t cc; /* 0xc14 0xe000ed14 Configuration Control Register */
- uint8_t _unused324[0xe00 - 0x324];
+ uint8_t _unusedc18[0xe00 - 0xc18];
vuint32_t stir; /* 0xe00 */
};
#define HAS_TELEMETRY 0
#define HAS_AES 1
-#define HAS_SPI_1 1
-#define SPI_1_PA5_PA6_PA7 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
+#define HAS_SPI_2 1 /* CC1111 */
#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
--- /dev/null
+ao_product.h
+telescience-*.elf
--- /dev/null
+#
+# AltOS build
+#
+#
+
+include ../stm/Makefile.defs
+
+INC = \
+ ao.h \
+ ao_arch.h \
+ ao_arch_funcs.h \
+ ao_pins.h \
+ ao_product.h \
+ ao_cc1120_CC1120.h \
+ ao_task.h \
+ ao_whiten.h \
+ stm32l.h \
+ Makefile
+
+#PROFILE=ao_profile.c
+#PROFILE_DEF=-DAO_PROFILE=1
+
+#SAMPLE_PROFILE=ao_sample_profile.c \
+# ao_sample_profile_timer.c
+#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1
+
+#STACK_GUARD=ao_mpu_stm.c
+#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1
+
+ALTOS_SRC = \
+ ao_interrupt.c \
+ ao_product.c \
+ ao_romconfig.c \
+ ao_cmd.c \
+ ao_config.c \
+ ao_task.c \
+ ao_led.c \
+ ao_stdio.c \
+ ao_panic.c \
+ ao_timer.c \
+ ao_mutex.c \
+ ao_dma_stm.c \
+ ao_spi_stm.c \
+ ao_usb_stm.c \
+ ao_adc_stm.c \
+ ao_data.c \
+ ao_exti_stm.c \
+ ao_storage.c \
+ ao_m25.c \
+ ao_science_slave.c \
+ ao_spi_stm_slave.c \
+ ao_log_telescience.c \
+ ao_log_single.c
+
+PRODUCT=TeleScience-v0.2
+PRODUCT_DEF=-DTELESCIENCE
+IDPRODUCT=0x0011
+
+CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g
+
+PROGNAME=telescience-v0.2
+PROG=$(PROGNAME)-$(VERSION).elf
+
+SRC=$(ALTOS_SRC) ao_telescience.c
+OBJ=$(SRC:.c=.o)
+
+all: $(PROG)
+
+$(PROG): Makefile $(OBJ) altos.ld
+ $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc
+
+$(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
+ rm -f ao_product.h
+
+install:
+
+uninstall:
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#define HAS_TASK_QUEUE 1
+
+/* 8MHz High speed external crystal */
+#define AO_HSE 8000000
+
+/* PLLVCO = 96MHz (so that USB will work) */
+#define AO_PLLMUL 12
+#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12)
+
+/* SYSCLK = 32MHz (no need to go faster than CPU) */
+#define AO_PLLDIV 3
+#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3)
+
+/* HCLK = 32MHz (CPU clock) */
+#define AO_AHB_PRESCALER 1
+#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1
+
+/* Run APB1 at 16MHz (HCLK/2) */
+#define AO_APB1_PRESCALER 2
+#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+/* Run APB2 at 16MHz (HCLK/2) */
+#define AO_APB2_PRESCALER 2
+#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2
+
+#define HAS_SERIAL_1 0
+#define USE_SERIAL_1_STDIN 0
+#define SERIAL_1_PB6_PB7 0
+#define SERIAL_1_PA9_PA10 1
+
+#define HAS_SERIAL_2 0
+#define USE_SERIAL_2_STDIN 0
+#define SERIAL_2_PA2_PA3 0
+#define SERIAL_2_PD5_PD6 0
+
+#define HAS_SERIAL_3 0
+#define USE_SERIAL_3_STDIN 0
+#define SERIAL_3_PB10_PB11 0
+#define SERIAL_3_PC10_PC11 1
+#define SERIAL_3_PD8_PD9 0
+
+#define HAS_EEPROM 1
+#define USE_INTERNAL_FLASH 0
+#define HAS_USB 1
+#define HAS_BEEP 0
+#define HAS_RADIO 0
+#define HAS_TELEMETRY 0
+#define PACKET_HAS_SLAVE 0
+
+#define HAS_SPI_1 0
+#define HAS_SPI_SLAVE_1 1
+#define SPI_1_PA5_PA6_PA7 1
+#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 1
+#define SPI_2_PD1_PD3_PD4 0
+#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz
+
+#define SPI_2_PORT (&stm_gpiob)
+#define SPI_2_SCK_PIN 13
+#define SPI_2_MISO_PIN 14
+#define SPI_2_MOSI_PIN 15
+#define SPI_SLAVE_INDEX 1
+
+#define HAS_I2C_1 0
+#define I2C_1_PB8_PB9 0
+
+#define HAS_I2C_2 0
+#define I2C_2_PB10_PB11 0
+
+#define LOW_LEVEL_DEBUG 0
+
+#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN
+
+#define LED_PORT_0 (&stm_gpioa)
+#define LED_PORT_0_MASK (0xff)
+#define LED_PORT_0_SHIFT 0
+#define LED_PIN_RED 8
+#define LED_PIN_GREEN 9
+#define AO_LED_RED (1 << LED_PIN_RED)
+#define AO_LED_GREEN (1 << LED_PIN_GREEN)
+
+#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN)
+
+#define HAS_GPS 0
+#define HAS_FLIGHT 0
+#define HAS_ADC 1
+#define HAS_LOG 1
+
+/*
+ * SPI Flash memory
+ */
+
+#define M25_MAX_CHIPS 1
+#define AO_M25_SPI_CS_PORT (&stm_gpioa)
+#define AO_M25_SPI_CS_MASK (1 << 3)
+#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15
+
+/*
+ * ADC
+ */
+
+#define AO_DATA_RING 32
+#define AO_ADC_NUM 1
+
+struct ao_adc {
+ int16_t adc[AO_ADC_NUM];
+};
+
+#define AO_ADC_TEMP 16
+
+#define AO_ADC_RCC_AHBENR 0
+
+#define AO_NUM_ADC_PIN 0
+
+#define AO_NUM_ADC 1
+
+#define AO_ADC_SQ1 AO_ADC_TEMP
+
+
+#endif /* _AO_PINS_H_ */
--- /dev/null
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_exti.h>
+#include <ao_packet.h>
+#include <ao_send_packet.h>
+
+int
+main(void)
+{
+ ao_clock_init();
+
+#if HAS_STACK_GUARD
+ ao_mpu_init();
+#endif
+
+ ao_task_init();
+ ao_led_init(LEDS_AVAILABLE);
+ ao_led_on(AO_LED_GREEN);
+ ao_timer_init();
+
+ ao_spi_init();
+ ao_spi_slave_init();
+ ao_dma_init();
+ ao_exti_init();
+
+ ao_cmd_init();
+
+ ao_usb_init();
+ ao_config_init();
+
+ ao_storage_init();
+
+ ao_start_scheduler();
+ return 0;
+}