From 0cedc27e22a9fbc9ccfe1b403c84d728bb23220d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Sep 2014 15:00:25 -0700 Subject: altos: Fix ability to disable telemetry by setting interval to 0 For non-zero telemetry intervals, the radio code limits the value based on the data rate. However, a zero interval means that telemetry should be entirely disabled, so that value should be left alone when checking. Signed-off-by: Keith Packard --- src/kernel/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 56bd715e..27306a34 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -518,7 +518,7 @@ ao_telemetry_set_interval(uint16_t interval) }; ao_telemetry_desired_interval = interval; - if (interval < min_interval[ao_config.radio_rate]) + if (interval && interval < min_interval[ao_config.radio_rate]) interval = min_interval[ao_config.radio_rate]; #endif ao_telemetry_interval = interval; -- cgit v1.2.3 From 7ad8921b164103629b246c25860297454aa7ec6b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Sep 2014 15:56:14 -0700 Subject: altos/test: Add TMv2 test program to .gitignore --- src/test/.gitignore | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/test/.gitignore b/src/test/.gitignore index b8b2513e..9237780b 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -15,5 +15,6 @@ ao_fat_test ao_fec_test ao_flight_test_mm ao_flight_test_noisy_accel +ao_flight_test_metrum ao_micropeak_test ao_aes_test -- cgit v1.2.3 From d7ad490a33900a788b15d1600ebaa2a71e6f35ff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Sep 2014 15:57:21 -0700 Subject: altos: Add smaller altitude table file to .gitignore Signed-off-by: Keith Packard --- src/.gitignore | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/.gitignore b/src/.gitignore index a8628fae..aad18d4c 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,4 +1,5 @@ Makedefs altitude.h altitude-pa.h +altitude-pa-small.h ao_whiten.h -- cgit v1.2.3 From 807e62ccebc83eb6427a63431d06effa074e5e76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Sep 2014 19:56:13 -0700 Subject: altos: Make sure we don't beep out continuity twice in idle mode If the battery voltage report takes longer than the initialiation sequence, we could get to the state reporting after the state had switched from startup to idle. This would result in continuity being reported the first time through the loop. Then, as the state had already changed, we'd pass through the while test and go back to report continuity a second time. Fixed by using the state remembered before beeping out the voltage to decide whether to report the continuity. Signed-off-by: Keith Packard --- src/kernel/ao_report.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_report.c b/src/kernel/ao_report.c index 5314fc8f..f4253b3d 100644 --- a/src/kernel/ao_report.c +++ b/src/kernel/ao_report.c @@ -246,15 +246,15 @@ ao_report_continuity(void) __reentrant void ao_report(void) { - ao_report_state = ao_flight_state; for(;;) { + ao_report_state = ao_flight_state; #if HAS_BATTERY_REPORT - if (ao_flight_state == ao_flight_startup) + if (ao_report_state == ao_flight_startup) ao_report_battery(); else #endif ao_report_beep(); - if (ao_flight_state == ao_flight_landed) { + if (ao_report_state == ao_flight_landed) { ao_report_altitude(); #if HAS_FLIGHT ao_delay(AO_SEC_TO_TICKS(5)); @@ -262,7 +262,7 @@ ao_report(void) #endif } #if HAS_IGNITE_REPORT - if (ao_flight_state == ao_flight_idle) + if (ao_report_state == ao_flight_idle) ao_report_continuity(); while (ao_flight_state == ao_flight_pad) { uint8_t c; @@ -272,10 +272,8 @@ ao_report(void) pause(AO_MS_TO_TICKS(100)); } #endif - while (ao_report_state == ao_flight_state) ao_sleep(DATA_TO_XDATA(&ao_flight_state)); - ao_report_state = ao_flight_state; } } -- cgit v1.2.3 From b4eba3f3a58a9c35e3699ff14405b997c1318d91 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Sep 2014 22:53:39 -0700 Subject: altos: Make sure we drop the SPI mutex when aborting cc1120 recv The cc1120 receive code is 'twisty', in that it acquires the SPI mutex in the middle of an interrupt handler so that it can quickly start the radio when the signal comes in. This means we have to be careful to drop that mutex in all paths which leave the receive code, including when the packet receive is aborted mid-way through the process. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 3ea8b704..90d6cc75 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -1125,12 +1125,12 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) ao_exti_set_mode(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); - ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); - ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - rx_starting = 1; rx_task_id = ao_cur_task->task_id; + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_SRX); if (timeout) @@ -1148,8 +1148,9 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) ao_clear_alarm(); if (ao_radio_abort) { + if (rx_task_id_save == 0) + ao_radio_burst_read_stop(); ret = 0; - rx_task_id = 0; goto abort; } -- cgit v1.2.3 From 40c5535b65a75374fb1dbbd994c29324db814f5b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Sep 2014 12:56:04 -0700 Subject: altos: Handle antenna down in ao_flight_test Parse the Pad orientation config value and flip the accelerometer value back around in antenna down configuration. Signed-off-by: Keith Packard --- src/test/ao_flight_test.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 8b737ca1..fbbc4bd9 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -600,7 +600,7 @@ ao_insert(void) #if 1 printf("%7.2f height %8.2f accel %8.3f " -#if TELEMEGA && 0 +#if TELEMEGA && 1 "angle %5d " "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d " #endif @@ -608,7 +608,7 @@ ao_insert(void) time, height, accel, -#if TELEMEGA && 0 +#if TELEMEGA && 1 ao_sample_orient, ao_mpu6000_accel(ao_data_static.mpu6000.accel_x), @@ -764,6 +764,8 @@ ao_sleep(void *wchan) ao_data_static.hmc5883.z = int16(bytes, 24); #if HAS_MMA655X ao_data_static.mma655x = int16(bytes, 26); + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_data_static.mma655x = ao_data_accel_invert(ao_data_static.mma655x); #endif ao_records_read++; ao_insert(); @@ -900,6 +902,9 @@ ao_sleep(void *wchan) } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 && strcmp(words[1], "lockout:") == 0) { ao_config.apogee_lockout = atoi(words[2]); + } else if (nword >= 3 && strcmp(words[0], "Pad") == 0 && + strcmp(words[1], "orientation:") == 0) { + ao_config.pad_orientation = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { -- cgit v1.2.3 From 9521dc63671b69065d27fc1ccba6d20cc90643cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Oct 2014 00:04:39 -0700 Subject: altos: Record 32-bits for gyro calibration values The gyro ground calibration values are scaled by 512 to provide a bit more precision for the computations. This means they don't fit in 16 bits, so change the format of the flight log record. Also change the reported format so that AltosUI has a chance of figuring it out. Signed-off-by: Keith Packard --- src/kernel/ao_log.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index c13a2580..3354c243 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -43,11 +43,12 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */ +#define AO_LOG_FORMAT_TELEMEGA_OLD 5 /* 32 byte typed telemega records */ #define AO_LOG_FORMAT_EASYMINI 6 /* 16-byte MS5607 baro only, 3.0V supply */ #define AO_LOG_FORMAT_TELEMETRUM 7 /* 16-byte typed telemetrum records */ #define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */ #define AO_LOG_FORMAT_TELEGPS 9 /* 32 byte telegps records */ +#define AO_LOG_FORMAT_TELEMEGA 10 /* 32 byte typed telemega records with 32 bit gyro cal */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -208,6 +209,18 @@ struct ao_log_mega { uint16_t tick; /* 2 */ union { /* 4 */ /* AO_LOG_FLIGHT */ + struct { + uint16_t flight; /* 4 */ + int16_t ground_accel; /* 6 */ + uint32_t ground_pres; /* 8 */ + int16_t ground_accel_along; /* 12 */ + int16_t ground_accel_across; /* 14 */ + int16_t ground_accel_through; /* 16 */ + int16_t pad /* 18 */ + int32_t ground_roll; /* 20 */ + int32_t ground_pitch; /* 24 */ + int32_t ground_yaw; /* 28 */ + } flight; /* 32 */ struct { uint16_t flight; /* 4 */ int16_t ground_accel; /* 6 */ @@ -218,7 +231,7 @@ struct ao_log_mega { int16_t ground_roll; /* 18 */ int16_t ground_pitch; /* 20 */ int16_t ground_yaw; /* 22 */ - } flight; /* 24 */ + } flight_old; /* 24 */ /* AO_LOG_STATE */ struct { uint16_t state; -- cgit v1.2.3 From 62628c8b429d06ee834f0b6511c430cbeaab9303 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Oct 2014 00:30:54 -0700 Subject: altos: Fix syntax error with ao_log_mega change. Missed a semi-colon. Signed-off-by: Keith Packard --- src/kernel/ao_log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/kernel/ao_log.h b/src/kernel/ao_log.h index 3354c243..f86fb359 100644 --- a/src/kernel/ao_log.h +++ b/src/kernel/ao_log.h @@ -216,7 +216,7 @@ struct ao_log_mega { int16_t ground_accel_along; /* 12 */ int16_t ground_accel_across; /* 14 */ int16_t ground_accel_through; /* 16 */ - int16_t pad /* 18 */ + int16_t pad_18; /* 18 */ int32_t ground_roll; /* 20 */ int32_t ground_pitch; /* 24 */ int32_t ground_yaw; /* 28 */ -- cgit v1.2.3 From 27a467d802a80a33ea20eb5cda2558d03caa2c00 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Oct 2014 00:03:28 -0700 Subject: altos: Copy cc1120 driver to cc1200 driver and hack a bit The cc1200 is similar to the cc1120, although many registers have changed. This driver can send a bare carrier and an RDF tone, but does not yet receive or transmit telemetry data. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 1249 ++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_cc1200.h | 583 +++++++++++++++++++ src/drivers/ao_cc1200_CC1200.h | 56 ++ 3 files changed, 1888 insertions(+) create mode 100644 src/drivers/ao_cc1200.c create mode 100644 src/drivers/ao_cc1200.h create mode 100644 src/drivers/ao_cc1200_CC1200.h (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c new file mode 100644 index 00000000..a69cdc11 --- /dev/null +++ b/src/drivers/ao_cc1200.c @@ -0,0 +1,1249 @@ +/* + * 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 +#include +#include +#include +#include + +#define AO_RADIO_MAX_RECV sizeof(struct ao_packet) +#define AO_RADIO_MAX_SEND sizeof(struct ao_packet) + +static uint8_t ao_radio_mutex; + +static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */ +static uint8_t ao_radio_abort; /* radio operation should abort */ +static uint8_t ao_radio_mcu_wake; /* MARC status change */ +static uint8_t ao_radio_marc_status; /* Last read MARC status value */ +static uint8_t ao_radio_tx_finished; /* MARC status indicates TX finished */ + +int8_t ao_radio_rssi; /* Last received RSSI value */ + +#define CC1200_DEBUG 1 +#define CC1200_TRACE 1 + +extern const uint32_t ao_radio_cal; + +#define FOSC 32000000 + +#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz, task_id) +#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_125kHz) +#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_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS) +#define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1200_SPI_BUS) + +static uint8_t +ao_radio_reg_read(uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + +#if CC1200_TRACE + printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); +#endif + if (CC1200_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1200_READ) | + (0 << CC1200_BURST) | + CC1200_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1200_READ) | + (0 << CC1200_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); + ao_radio_spi_recv(data, 1); + ao_radio_deselect(); +#if CC1200_TRACE + printf (" %02x\n", data[0]); +#endif + return data[0]; +} + +static void +ao_radio_reg_write(uint16_t addr, uint8_t value) +{ + uint8_t data[3]; + uint8_t d; + +#if CC1200_TRACE + printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); +#endif + if (CC1200_IS_EXTENDED(addr)) { + data[0] = ((0 << CC1200_READ) | + (0 << CC1200_BURST) | + CC1200_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((0 << CC1200_READ) | + (0 << CC1200_BURST) | + addr); + d = 1; + } + data[d] = value; + ao_radio_select(); + ao_radio_spi_send(data, d+1); + ao_radio_deselect(); +#if CC1200_TRACE + (void) ao_radio_reg_read(addr); +#endif +} + +static uint8_t +ao_radio_strobe(uint8_t addr) +{ + uint8_t in; + +#if CC1200_TRACE + printf("\t\tao_radio_strobe (%02x): ", addr); flush(); +#endif + ao_radio_select(); + ao_radio_duplex(&addr, &in, 1); + ao_radio_deselect(); +#if CC1200_TRACE + printf("%02x\n", in); flush(); +#endif + return in; +} + +#if 0 +static uint8_t +ao_radio_fifo_read(uint8_t *data, uint8_t len) +{ + uint8_t addr = ((1 << CC1200_READ) | + (1 << CC1200_BURST) | + CC1200_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_recv(data, len); + ao_radio_deselect(); + return status; +} +#endif + +static uint8_t +ao_radio_fifo_write_start(void) +{ + uint8_t addr = ((0 << CC1200_READ) | + (1 << CC1200_BURST) | + CC1200_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + return status; +} + +static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_fifo_write(uint8_t *data, uint8_t len) +{ + uint8_t status = ao_radio_fifo_write_start(); + ao_radio_spi_send(data, len); + return ao_radio_fifo_write_stop(status); +} + +static uint8_t +ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +{ + uint8_t status = ao_radio_fifo_write_start(); + ao_radio_spi_send_fixed(data, len); + return ao_radio_fifo_write_stop(status); +} + +static uint8_t +ao_radio_tx_fifo_space(void) +{ + return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES); +} + +#if CC1200_DEBUG || CC1200_TRACE +static uint8_t +ao_radio_status(void) +{ + return ao_radio_strobe (CC1200_SNOP); +} +#endif + +void +ao_radio_recv_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_wake); +} + +#define ao_radio_rdf_value 0x55 + +static uint8_t +ao_radio_get_marc_status(void) +{ + return ao_radio_reg_read(CC1200_MARC_STATUS1); +} + +static void +ao_radio_check_marc_status(void) +{ + ao_radio_mcu_wake = 0; + ao_radio_marc_status = ao_radio_get_marc_status(); + + /* Anyt other than 'tx/rx finished' means an error occurred */ + if (ao_radio_marc_status & ~(CC1200_MARC_STATUS1_TX_FINISHED|CC1200_MARC_STATUS1_RX_FINISHED)) + ao_radio_abort = 1; + if (ao_radio_marc_status & (CC1200_MARC_STATUS1_TX_FINISHED)) + ao_radio_tx_finished = 1; +} + +static void +ao_radio_isr(void) +{ + ao_exti_disable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_start_tx(void) +{ + ao_exti_set_callback(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, ao_radio_isr); + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_tx_finished = 0; + ao_radio_strobe(CC1200_STX); +} + +static void +ao_radio_idle(void) +{ + for (;;) { + uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; + if (state == CC1200_STATUS_STATE_IDLE) + break; + if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR) + ao_radio_strobe(CC1200_SFTX); + if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR) + ao_radio_strobe(CC1200_SFRX); + } + /* Flush any pending TX bytes */ + ao_radio_strobe(CC1200_SFTX); +} + +/* + * Packet deviation + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * Deviation for 38400 baud should be 20.5kHz: + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + * + * Deviation for 9600 baud should be 5.125kHz: + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz + * + * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and + * cc115l can't do that, so we'll use 1.5kHz instead: + * + * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz + */ + +#define PACKET_DEV_M_384 80 +#define PACKET_DEV_E_384 5 + +#define PACKET_DEV_M_96 80 +#define PACKET_DEV_E_96 3 + +#define PACKET_DEV_M_24 137 +#define PACKET_DEV_E_24 1 + +/* + * For our packet data + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * Given the bit period of the baseband, T, the bandwidth of the + * baseband signal is B = 1/(2T). The overall bandwidth of the + * modulated signal is then Channel bandwidth = 2Δf + 2B. + * + * 38400 -- 2 * 20500 + 38400 = 79.4 kHz + * 9600 -- 2 * 5.125 + 9600 = 19.9 kHz + * 2400 -- 2 * 1.5 + 2400 = 5.4 khz + * + * Symbol rate 38400 Baud: + * + * DATARATE_M = 239914 + * DATARATE_E = 9 + * CHANBW = 79.4 (79.4) + * + * Symbol rate 9600 Baud: + * + * DATARATE_M = 239914 + * DATARATE_E = 7 + * CHANBW = 19.9 (round to 19.8) + * + * Symbol rate 2400 Baud: + * + * DATARATE_M = 239914 + * DATARATE_E = 5 + * CHANBW = 5.0 (round to 9.5) + */ + +#define PACKET_SYMBOL_RATE_M 239914 + +#define PACKET_SYMBOL_RATE_E_384 9 + +/* 200 / 2 = 100 */ +#define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ + (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + +#define PACKET_SYMBOL_RATE_E_96 7 +/* 200 / 10 = 20 */ +#define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ + (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + +#define PACKET_SYMBOL_RATE_E_24 5 +/* 200 / 25 = 8 */ +#define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ + (44 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + +static const uint16_t packet_setup[] = { + CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | + (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), +}; + +static const uint16_t packet_setup_384[] = { + CC1200_DEVIATION_M, PACKET_DEV_M_384, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_CHAN_BW, PACKET_CHAN_BW_384, + CC1200_PA_CFG0, 0x7b, +}; + +static const uint16_t packet_setup_96[] = { + CC1200_DEVIATION_M, PACKET_DEV_M_96, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_CHAN_BW, PACKET_CHAN_BW_96, + CC1200_PA_CFG0, 0x7d, +}; + +static const uint16_t packet_setup_24[] = { + CC1200_DEVIATION_M, PACKET_DEV_M_24, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_CHAN_BW, PACKET_CHAN_BW_24, + CC1200_PA_CFG0, 0x7e, +}; + +static const uint16_t packet_tx_setup[] = { + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG, +}; + +static const uint16_t packet_rx_setup[] = { + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1200_PKT_CFG2_PKT_FORMAT)), + AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_CLKEN_SOFT, +}; + +/* + * RDF deviation is 5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989 + */ + +#define RDF_DEV_E 3 +#define RDF_DEV_M 71 + +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone) + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 25166 + * DATARATE_E = 5 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ +#define RDF_SYMBOL_RATE_E 5 +#define RDF_SYMBOL_RATE_M 25166 +#define RDF_PACKET_LEN 50 + +static const uint16_t rdf_setup[] = { + CC1200_DEVIATION_M, RDF_DEV_M, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | + (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_PA_CFG0, 0x7e, +}; + +/* + * APRS deviation is 3kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz + */ + +#define APRS_DEV_E 2 +#define APRS_DEV_M 137 + +/* + * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate) + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 239914 + * DATARATE_E = 7 + * + * Rdata = 9599.998593330383301 + * + */ +#define APRS_SYMBOL_RATE_E 7 +#define APRS_SYMBOL_RATE_M 239914 + +static const uint16_t aprs_setup[] = { + CC1200_DEVIATION_M, APRS_DEV_M, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_PA_CFG0, 0x7d, +}; + +/* + * For Test mode, we want an unmodulated carrier. To do that, we + * set the deviation to zero and enable a preamble so that the radio + * turns on before we send any data + */ + +static const uint16_t test_setup[] = { + CC1200_DEVIATION_M, 0, + CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | + (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | + (0 << CC1200_MODCFG_DEV_E_DEV_E)), + CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), + CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), +}; + +#define AO_PKT_CFG0_INFINITE ((0 << CC1200_PKT_CFG0_RESERVED7) | \ + (CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) + +#define AO_PKT_CFG0_FIXED ((0 << CC1200_PKT_CFG0_RESERVED7) | \ + (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) + +static uint16_t ao_radio_mode; + +#define AO_RADIO_MODE_BITS_PACKET 1 +#define AO_RADIO_MODE_BITS_PACKET_TX 2 +#define AO_RADIO_MODE_BITS_TX_BUF 4 +#define AO_RADIO_MODE_BITS_TX_FINISH 8 +#define AO_RADIO_MODE_BITS_PACKET_RX 16 +#define AO_RADIO_MODE_BITS_RDF 32 +#define AO_RADIO_MODE_BITS_APRS 64 +#define AO_RADIO_MODE_BITS_TEST 128 +#define AO_RADIO_MODE_BITS_INFINITE 256 +#define AO_RADIO_MODE_BITS_FIXED 512 + +#define AO_RADIO_MODE_NONE 0 +#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX) +#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) + +static void +_ao_radio_set_regs(const uint16_t *regs, int nreg) +{ + int i; + + for (i = 0; i < nreg; i++) { + ao_radio_reg_write(regs[0], regs[1]); + regs += 2; + } +} + +#define ao_radio_set_regs(setup) _ao_radio_set_regs(setup, (sizeof (setup) / sizeof(setup[0])) >> 1) + +static void +ao_radio_set_mode(uint16_t new_mode) +{ + uint16_t changes; + + if (new_mode == ao_radio_mode) + return; + + changes = new_mode & (~ao_radio_mode); + + if (changes & AO_RADIO_MODE_BITS_PACKET) { + ao_radio_set_regs(packet_setup); + + switch (ao_config.radio_rate) { + default: + case AO_RADIO_RATE_38400: + ao_radio_set_regs(packet_setup_384); + break; + case AO_RADIO_RATE_9600: + ao_radio_set_regs(packet_setup_96); + break; + case AO_RADIO_RATE_2400: + ao_radio_set_regs(packet_setup_24); + break; + } + } + + if (changes & AO_RADIO_MODE_BITS_PACKET_TX) + ao_radio_set_regs(packet_tx_setup); + + if (changes & AO_RADIO_MODE_BITS_TX_BUF) + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR); + + if (changes & AO_RADIO_MODE_BITS_TX_FINISH) + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG); + + if (changes & AO_RADIO_MODE_BITS_PACKET_RX) + ao_radio_set_regs(packet_rx_setup); + + if (changes & AO_RADIO_MODE_BITS_RDF) + ao_radio_set_regs(rdf_setup); + + if (changes & AO_RADIO_MODE_BITS_APRS) + ao_radio_set_regs(aprs_setup); + + if (changes & AO_RADIO_MODE_BITS_TEST) + ao_radio_set_regs(test_setup); + + if (changes & AO_RADIO_MODE_BITS_INFINITE) + ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_INFINITE); + + if (changes & AO_RADIO_MODE_BITS_FIXED) + ao_radio_reg_write(CC1200_PKT_CFG0, AO_PKT_CFG0_FIXED); + + ao_radio_mode = new_mode; +} + +static const uint16_t radio_setup[] = { +#include "ao_cc1200_CC1200.h" +}; + +static uint8_t ao_radio_configured = 0; + +static void +ao_radio_setup(void) +{ +// ao_radio_strobe(CC1200_SRES); + + ao_radio_set_regs(radio_setup); + + ao_radio_mode = 0; + + ao_config_get(); + + ao_radio_configured = 1; +} + +static void +ao_radio_set_len(uint8_t len) +{ + static uint8_t last_len; + + if (len != last_len) { + ao_radio_reg_write(CC1200_PKT_LEN, len); + last_len = len; + } +} + +static void +ao_radio_get(uint8_t len) +{ + static uint32_t last_radio_setting; + static uint8_t last_radio_rate; + + ao_mutex_get(&ao_radio_mutex); + + if (!ao_radio_configured) + ao_radio_setup(); + if (ao_config.radio_setting != last_radio_setting) { + ao_radio_reg_write(CC1200_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting); + last_radio_setting = ao_config.radio_setting; + } + if (ao_config.radio_rate != last_radio_rate) { + ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET; + last_radio_rate = ao_config.radio_rate; + } + ao_radio_set_len(len); +} + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +static void +ao_rdf_start(uint8_t len) +{ + ao_radio_abort = 0; + ao_radio_get(len); + + ao_radio_set_mode(AO_RADIO_MODE_RDF); + ao_radio_wake = 0; + +} + +static void +ao_rdf_run(void) +{ + ao_radio_start_tx(); + + ao_arch_block_interrupts(); + while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) + ao_sleep(&ao_radio_wake); + ao_arch_release_interrupts(); + if (ao_radio_mcu_wake) + ao_radio_check_marc_status(); + if (!ao_radio_wake) + ao_radio_idle(); + ao_radio_put(); +} + +void +ao_radio_rdf(void) +{ + ao_rdf_start(AO_RADIO_RDF_LEN); + + ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); + + ao_rdf_run(); +} + +void +ao_radio_continuity(uint8_t c) +{ + uint8_t i; + uint8_t status; + + ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN); + + status = ao_radio_fifo_write_start(); + for (i = 0; i < 3; i++) { + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + if (i < c) + ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN); + else + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN); + } + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + status = ao_radio_fifo_write_stop(status); + (void) status; + ao_rdf_run(); +} + +void +ao_radio_rdf_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_test_cmd(void) +{ + uint8_t mode = 2; + static uint8_t radio_on; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2) && !radio_on) { +#if HAS_MONITOR + ao_monitor_disable(); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif + ao_radio_get(0xff); + ao_radio_set_mode(AO_RADIO_MODE_TEST); + ao_radio_strobe(CC1200_STX); +#if CC1200_TRACE + { int t; + for (t = 0; t < 10; t++) { + printf ("status: %02x\n", ao_radio_status()); + ao_delay(AO_MS_TO_TICKS(100)); + } + } +#endif + radio_on = 1; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1) && radio_on) { + ao_radio_idle(); + ao_radio_put(); + radio_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif + } +} + +static void +ao_radio_wait_isr(uint16_t timeout) +{ + if (timeout) + ao_alarm(timeout); + ao_arch_block_interrupts(); + while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort) + if (ao_sleep(&ao_radio_wake)) + ao_radio_abort = 1; + ao_arch_release_interrupts(); + if (timeout) + ao_clear_alarm(); + if (ao_radio_mcu_wake) + ao_radio_check_marc_status(); +} + +void +ao_radio_send(const void *d, uint8_t size) +{ + (void) d; + (void) size; +} + +#define AO_RADIO_LOTS 64 + +void +ao_radio_send_aprs(ao_radio_fill_func fill) +{ + uint8_t buf[AO_RADIO_LOTS], *b; + int cnt; + int total = 0; + uint8_t done = 0; + uint8_t started = 0; + uint8_t fifo_space; + + ao_radio_get(0xff); + fifo_space = CC1200_FIFO_SIZE; + while (!done) { + cnt = (*fill)(buf, sizeof(buf)); + if (cnt < 0) { + done = 1; + cnt = -cnt; + } + total += cnt; + + /* At the last buffer, set the total length */ + if (done) + ao_radio_set_len(total & 0xff); + + b = buf; + while (cnt) { + uint8_t this_len = cnt; + + /* Wait for some space in the fifo */ + while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) { + ao_radio_wake = 0; + ao_radio_wait_isr(0); + } + if (ao_radio_abort) + break; + if (this_len > fifo_space) + this_len = fifo_space; + + cnt -= this_len; + + if (done) { + if (cnt) + ao_radio_set_mode(AO_RADIO_MODE_APRS_LAST_BUF); + else + ao_radio_set_mode(AO_RADIO_MODE_APRS_FINISH); + } else + ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF); + + ao_radio_fifo_write(b, this_len); + b += this_len; + + if (!started) { + ao_radio_start_tx(); + started = 1; + } else + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + } + if (ao_radio_abort) { + ao_radio_idle(); + break; + } + /* Wait for the transmitter to go idle */ + ao_radio_wake = 0; + ao_radio_wait_isr(0); + } + ao_radio_put(); +} + +uint8_t +ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) +{ + (void) d; + (void) size; + (void) timeout; + return 0; +} + + +#if CC1200_DEBUG +static char *cc1200_state_name[] = { + [CC1200_STATUS_STATE_IDLE] = "IDLE", + [CC1200_STATUS_STATE_RX] = "RX", + [CC1200_STATUS_STATE_TX] = "TX", + [CC1200_STATUS_STATE_FSTXON] = "FSTXON", + [CC1200_STATUS_STATE_CALIBRATE] = "CALIBRATE", + [CC1200_STATUS_STATE_SETTLING] = "SETTLING", + [CC1200_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR", + [CC1200_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR", +}; + +struct ao_cc1200_reg { + uint16_t addr; + char *name; +}; + +static const struct ao_cc1200_reg ao_cc1200_reg[] = { + { .addr = CC1200_IOCFG3, .name = "IOCFG3" }, + { .addr = CC1200_IOCFG2, .name = "IOCFG2" }, + { .addr = CC1200_IOCFG1, .name = "IOCFG1" }, + { .addr = CC1200_IOCFG0, .name = "IOCFG0" }, + { .addr = CC1200_SYNC3, .name = "SYNC3" }, + { .addr = CC1200_SYNC2, .name = "SYNC2" }, + { .addr = CC1200_SYNC1, .name = "SYNC1" }, + { .addr = CC1200_SYNC0, .name = "SYNC0" }, + { .addr = CC1200_SYNC_CFG1, .name = "SYNC_CFG1" }, + { .addr = CC1200_SYNC_CFG0, .name = "SYNC_CFG0" }, + { .addr = CC1200_DEVIATION_M, .name = "DEVIATION_M" }, + { .addr = CC1200_MODCFG_DEV_E, .name = "MODCFG_DEV_E" }, + { .addr = CC1200_DCFILT_CFG, .name = "DCFILT_CFG" }, + { .addr = CC1200_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" }, + { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" }, + { .addr = CC1200_IQIC, .name = "IQIC" }, + { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" }, + { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" }, + { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" }, + { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" }, + { .addr = CC1200_SYMBOL_RATE1, .name = "SYMBOL_RATE1" }, + { .addr = CC1200_SYMBOL_RATE0, .name = "SYMBOL_RATE0" }, + { .addr = CC1200_AGC_REF, .name = "AGC_REF" }, + { .addr = CC1200_AGC_CS_THR, .name = "AGC_CS_THR" }, + { .addr = CC1200_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" }, + { .addr = CC1200_AGC_CFG3, .name = "AGC_CFG3" }, + { .addr = CC1200_AGC_CFG2, .name = "AGC_CFG2" }, + { .addr = CC1200_AGC_CFG1, .name = "AGC_CFG1" }, + { .addr = CC1200_AGC_CFG0, .name = "AGC_CFG0" }, + { .addr = CC1200_FIFO_CFG, .name = "FIFO_CFG" }, + { .addr = CC1200_DEV_ADDR, .name = "DEV_ADDR" }, + { .addr = CC1200_SETTLING_CFG, .name = "SETTLING_CFG" }, + { .addr = CC1200_FS_CFG, .name = "FS_CFG" }, + { .addr = CC1200_WOR_CFG1, .name = "WOR_CFG1" }, + { .addr = CC1200_WOR_CFG0, .name = "WOR_CFG0" }, + { .addr = CC1200_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" }, + { .addr = CC1200_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" }, + { .addr = CC1200_RXDCM_TIME, .name = "RXDCM_TIME" }, + { .addr = CC1200_PKT_CFG2, .name = "PKT_CFG2" }, + { .addr = CC1200_PKT_CFG1, .name = "PKT_CFG1" }, + { .addr = CC1200_PKT_CFG0, .name = "PKT_CFG0" }, + { .addr = CC1200_RFEND_CFG1, .name = "RFEND_CFG1" }, + { .addr = CC1200_RFEND_CFG0, .name = "RFEND_CFG0" }, + { .addr = CC1200_PA_CFG1, .name = "PA_CFG1" }, + { .addr = CC1200_PA_CFG0, .name = "PA_CFG0" }, + { .addr = CC1200_PKT_LEN, .name = "PKT_LEN" }, + { .addr = CC1200_IF_MIX_CFG, .name = "IF_MIX_CFG" }, + { .addr = CC1200_FREQOFF_CFG, .name = "FREQOFF_CFG" }, + { .addr = CC1200_TOC_CFG, .name = "TOC_CFG" }, + { .addr = CC1200_MARC_SPARE, .name = "MARC_SPARE" }, + { .addr = CC1200_ECG_CFG, .name = "ECG_CFG" }, + { .addr = CC1200_EXT_CTRL, .name = "EXT_CTRL" }, + { .addr = CC1200_RCCAL_FINE, .name = "RCCAL_FINE" }, + { .addr = CC1200_RCCAL_COARSE, .name = "RCCAL_COARSE" }, + { .addr = CC1200_RCCAL_OFFSET, .name = "RCCAL_OFFSET" }, + { .addr = CC1200_FREQOFF1, .name = "FREQOFF1" }, + { .addr = CC1200_FREQOFF0, .name = "FREQOFF0" }, + { .addr = CC1200_FREQ2, .name = "FREQ2" }, + { .addr = CC1200_FREQ1, .name = "FREQ1" }, + { .addr = CC1200_FREQ0, .name = "FREQ0" }, + { .addr = CC1200_IF_ADC2, .name = "IF_ADC2" }, + { .addr = CC1200_IF_ADC1, .name = "IF_ADC1" }, + { .addr = CC1200_IF_ADC0, .name = "IF_ADC0" }, + { .addr = CC1200_FS_DIG1, .name = "FS_DIG1" }, + { .addr = CC1200_FS_DIG0, .name = "FS_DIG0" }, + { .addr = CC1200_FS_CAL3, .name = "FS_CAL3" }, + { .addr = CC1200_FS_CAL2, .name = "FS_CAL2" }, + { .addr = CC1200_FS_CAL1, .name = "FS_CAL1" }, + { .addr = CC1200_FS_CAL0, .name = "FS_CAL0" }, + { .addr = CC1200_FS_CHP, .name = "FS_CHP" }, + { .addr = CC1200_FS_DIVTWO, .name = "FS_DIVTWO" }, + { .addr = CC1200_FS_DSM1, .name = "FS_DSM1" }, + { .addr = CC1200_FS_DSM0, .name = "FS_DSM0" }, + { .addr = CC1200_FS_DVC1, .name = "FS_DVC1" }, + { .addr = CC1200_FS_DVC0, .name = "FS_DVC0" }, + { .addr = CC1200_FS_LBI, .name = "FS_LBI" }, + { .addr = CC1200_FS_PFD, .name = "FS_PFD" }, + { .addr = CC1200_FS_PRE, .name = "FS_PRE" }, + { .addr = CC1200_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" }, + { .addr = CC1200_FS_SPARE, .name = "FS_SPARE" }, + { .addr = CC1200_FS_VCO4, .name = "FS_VCO4" }, + { .addr = CC1200_FS_VCO3, .name = "FS_VCO3" }, + { .addr = CC1200_FS_VCO2, .name = "FS_VCO2" }, + { .addr = CC1200_FS_VCO1, .name = "FS_VCO1" }, + { .addr = CC1200_FS_VCO0, .name = "FS_VCO0" }, + { .addr = CC1200_GBIAS6, .name = "GBIAS6" }, + { .addr = CC1200_GBIAS5, .name = "GBIAS5" }, + { .addr = CC1200_GBIAS4, .name = "GBIAS4" }, + { .addr = CC1200_GBIAS3, .name = "GBIAS3" }, + { .addr = CC1200_GBIAS2, .name = "GBIAS2" }, + { .addr = CC1200_GBIAS1, .name = "GBIAS1" }, + { .addr = CC1200_GBIAS0, .name = "GBIAS0" }, + { .addr = CC1200_IFAMP, .name = "IFAMP" }, + { .addr = CC1200_LNA, .name = "LNA" }, + { .addr = CC1200_RXMIX, .name = "RXMIX" }, + { .addr = CC1200_XOSC5, .name = "XOSC5" }, + { .addr = CC1200_XOSC4, .name = "XOSC4" }, + { .addr = CC1200_XOSC3, .name = "XOSC3" }, + { .addr = CC1200_XOSC2, .name = "XOSC2" }, + { .addr = CC1200_XOSC1, .name = "XOSC1" }, + { .addr = CC1200_XOSC0, .name = "XOSC0" }, + { .addr = CC1200_ANALOG_SPARE, .name = "ANALOG_SPARE" }, + { .addr = CC1200_PA_CFG3, .name = "PA_CFG3" }, + { .addr = CC1200_WOR_TIME1, .name = "WOR_TIME1" }, + { .addr = CC1200_WOR_TIME0, .name = "WOR_TIME0" }, + { .addr = CC1200_WOR_CAPTURE1, .name = "WOR_CAPTURE1" }, + { .addr = CC1200_WOR_CAPTURE0, .name = "WOR_CAPTURE0" }, + { .addr = CC1200_BIST, .name = "BIST" }, + { .addr = CC1200_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" }, + { .addr = CC1200_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" }, + { .addr = CC1200_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" }, + { .addr = CC1200_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" }, + { .addr = CC1200_IQIE_I1, .name = "IQIE_I1" }, + { .addr = CC1200_IQIE_I0, .name = "IQIE_I0" }, + { .addr = CC1200_IQIE_Q1, .name = "IQIE_Q1" }, + { .addr = CC1200_IQIE_Q0, .name = "IQIE_Q0" }, + { .addr = CC1200_RSSI1, .name = "RSSI1" }, + { .addr = CC1200_RSSI0, .name = "RSSI0" }, + { .addr = CC1200_MARCSTATE, .name = "MARCSTATE" }, + { .addr = CC1200_LQI_VAL, .name = "LQI_VAL" }, + { .addr = CC1200_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" }, + { .addr = CC1200_DEM_STATUS, .name = "DEM_STATUS" }, + { .addr = CC1200_FREQOFF_EST1, .name = "FREQOFF_EST1" }, + { .addr = CC1200_FREQOFF_EST0, .name = "FREQOFF_EST0" }, + { .addr = CC1200_AGC_GAIN3, .name = "AGC_GAIN3" }, + { .addr = CC1200_AGC_GAIN2, .name = "AGC_GAIN2" }, + { .addr = CC1200_AGC_GAIN1, .name = "AGC_GAIN1" }, + { .addr = CC1200_AGC_GAIN0, .name = "AGC_GAIN0" }, + { .addr = CC1200_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" }, + { .addr = CC1200_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" }, + { .addr = CC1200_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" }, + { .addr = CC1200_RNDGEN, .name = "RNDGEN" }, + { .addr = CC1200_MAGN2, .name = "MAGN2" }, + { .addr = CC1200_MAGN1, .name = "MAGN1" }, + { .addr = CC1200_MAGN0, .name = "MAGN0" }, + { .addr = CC1200_ANG1, .name = "ANG1" }, + { .addr = CC1200_ANG0, .name = "ANG0" }, + { .addr = CC1200_CHFILT_I2, .name = "CHFILT_I2" }, + { .addr = CC1200_CHFILT_I1, .name = "CHFILT_I1" }, + { .addr = CC1200_CHFILT_I0, .name = "CHFILT_I0" }, + { .addr = CC1200_CHFILT_Q2, .name = "CHFILT_Q2" }, + { .addr = CC1200_CHFILT_Q1, .name = "CHFILT_Q1" }, + { .addr = CC1200_CHFILT_Q0, .name = "CHFILT_Q0" }, + { .addr = CC1200_GPIO_STATUS, .name = "GPIO_STATUS" }, + { .addr = CC1200_FSCAL_CTRL, .name = "FSCAL_CTRL" }, + { .addr = CC1200_PHASE_ADJUST, .name = "PHASE_ADJUST" }, + { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" }, + { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" }, + { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" }, + { .addr = CC1200_RX_STATUS, .name = "RX_STATUS" }, + { .addr = CC1200_TX_STATUS, .name = "TX_STATUS" }, + { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" }, + { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" }, + { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" }, + { .addr = CC1200_FSRF_TEST, .name = "FSRF_TEST" }, + { .addr = CC1200_PRE_TEST, .name = "PRE_TEST" }, + { .addr = CC1200_PRE_OVR, .name = "PRE_OVR" }, + { .addr = CC1200_ADC_TEST, .name = "ADC_TEST" }, + { .addr = CC1200_DVC_TEST, .name = "DVC_TEST" }, + { .addr = CC1200_ATEST, .name = "ATEST" }, + { .addr = CC1200_ATEST_LVDS, .name = "ATEST_LVDS" }, + { .addr = CC1200_ATEST_MODE, .name = "ATEST_MODE" }, + { .addr = CC1200_XOSC_TEST1, .name = "XOSC_TEST1" }, + { .addr = CC1200_XOSC_TEST0, .name = "XOSC_TEST0" }, + { .addr = CC1200_RXFIRST, .name = "RXFIRST" }, + { .addr = CC1200_TXFIRST, .name = "TXFIRST" }, + { .addr = CC1200_RXLAST, .name = "RXLAST" }, + { .addr = CC1200_TXLAST, .name = "TXLAST" }, + { .addr = CC1200_NUM_TXBYTES, .name = "NUM_TXBYTES" }, + { .addr = CC1200_NUM_RXBYTES, .name = "NUM_RXBYTES" }, + { .addr = CC1200_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" }, + { .addr = CC1200_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" }, +}; + +#define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0]) + +static void ao_radio_show(void) { + uint8_t status = ao_radio_status(); + unsigned int i; + + ao_radio_get(0xff); + status = ao_radio_status(); + printf ("Status: %02x\n", status); + printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1); + printf ("STATE: %s\n", cc1200_state_name[(status >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK]); + printf ("MARC: %02x\n", ao_radio_get_marc_status()); + + for (i = 0; i < AO_NUM_CC1200_REG; i++) + printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1200_reg[i].addr), ao_cc1200_reg[i].name); + + ao_radio_put(); +} + +static void ao_radio_beep(void) { + ao_radio_rdf(); +} + +static void ao_radio_packet(void) { + static const uint8_t packet[] = { +#if 1 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#else + 3, 1, 2, 3 +#endif + }; + + ao_radio_send(packet, sizeof (packet)); +} + +void +ao_radio_test_recv(void) +{ + uint8_t bytes[34]; + uint8_t b; + + if (ao_radio_recv(bytes, 34, 0)) { + if (bytes[33] & 0x80) + printf ("CRC OK"); + else + printf ("CRC BAD"); + printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32])); + for (b = 0; b < 32; b++) + printf (" %02x", bytes[b]); + printf ("\n"); + } +} + +#if HAS_APRS +#include + +static void +ao_radio_aprs(void) +{ + ao_packet_slave_stop(); + ao_aprs_send(); +} +#endif +#endif + +static void +ao_radio_strobe_test(void) +{ + uint8_t r; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + r = ao_radio_strobe(ao_cmd_lex_i); + printf ("Strobe %02x -> %02x (rdy %d state %d)\n", + ao_cmd_lex_i, + r, + r >> 7, + (r >> 4) & 0x7); +} + +static void +ao_radio_write_test(void) +{ + uint16_t addr; + uint8_t data; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + addr = ao_cmd_lex_i; + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + data = ao_cmd_lex_i; + printf ("Write %04x = %02x\n", addr, data); + ao_radio_reg_write(addr, data); +} + +static void +ao_radio_read_test(void) +{ + uint16_t addr; + uint8_t data; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + addr = ao_cmd_lex_i; + data = ao_radio_reg_read(addr); + printf ("Read %04x = %02x\n", addr, data); +} + +static const struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, +#if CC1200_DEBUG +#if HAS_APRS + { ao_radio_aprs, "G\0Send APRS packet" }, +#endif + { ao_radio_show, "R\0Show CC1200 status" }, + { ao_radio_beep, "b\0Emit an RDF beacon" }, + { ao_radio_packet, "p\0Send a test packet" }, + { ao_radio_test_recv, "q\0Recv a test packet" }, +#endif + { ao_radio_strobe_test, "S \0Strobe radio" }, + { ao_radio_write_test, "W \0Write radio reg" }, + { ao_radio_read_test, "R \0Read radio reg" }, + { 0, NULL } +}; + +void +ao_radio_init(void) +{ + ao_radio_configured = 0; + ao_spi_init_cs (AO_CC1200_SPI_CS_PORT, (1 << AO_CC1200_SPI_CS_PIN)); + +#if 0 + AO_CC1200_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1200_SPI_CS_PIN)); + for (i = 0; i < 10000; i++) { + if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0) + break; + } + AO_CC1200_SPI_CS_PORT->bsrr = (1 << AO_CC1200_SPI_CS_PIN); + if (i == 10000) + ao_panic(AO_PANIC_SELF_TEST_CC1200); +#endif + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_CC1200_INT_PORT); + ao_exti_setup(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH, + ao_radio_isr); + + ao_cmd_register(&ao_radio_cmds[0]); +} diff --git a/src/drivers/ao_cc1200.h b/src/drivers/ao_cc1200.h new file mode 100644 index 00000000..987f9bda --- /dev/null +++ b/src/drivers/ao_cc1200.h @@ -0,0 +1,583 @@ +/* + * 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. + */ + +#ifndef _AO_CC1200_H_ +#define _AO_CC1200_H_ + +#define CC1200_READ (7) +#define CC1200_BURST (6) + +/* Register space */ +#define CC1200_IOCFG3 0x00 +#define CC1200_IOCFG_GPIO_ATRAN 7 +#define CC1200_IOCFG_GPIO_INV 6 +#define CC1200_IOCFG_GPIO_CFG 0 +#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR 0 +#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1 +#define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR 2 +#define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR_PKT 3 +#define CC1200_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4 +#define CC1200_IOCFG_GPIO_CFG_TXFIFO_UNDERFLOW 5 +#define CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX 6 +#define CC1200_IOCFG_GPIO_CFG_CRC_OK 7 +#define CC1200_IOCFG_GPIO_CFG_SERIAL_CLK 8 +#define CC1200_IOCFG_GPIO_CFG_SERIAL_RX 9 +#define CC1200_IOCFG_GPIO_CFG_PQT_REACHED 11 +#define CC1200_IOCFG_GPIO_CFG_PQT_VALID 12 +#define CC1200_IOCFG_GPIO_CFG_RSSI_VALID 13 +#define CC1200_IOCFG_GPIO3_CFG_RSSI_UPDATE 14 +#define CC1200_IOCFG_GPIO2_CFG_RSSI_UPDATE 14 +#define CC1200_IOCFG_GPIO1_CFG_AGC_HOLD 14 +#define CC1200_IOCFG_GPIO0_CFG_AGC_UPDATE 14 +#define CC1200_IOCFG_GPIO3_CFG_CGA_STATUS 15 +#define CC1200_IOCFG_GPIO2_CFG_TXONCCA_DONE 15 +#define CC1200_IOCFG_GPIO1_CFG_CCA_STATUS 15 +#define CC1200_IOCFG_GPIO0_CFG_TXONCCA_FAILED 15 +#define CC1200_IOCFG_GPIO_CFG_CARRIER_SENSE_VALID 16 +#define CC1200_IOCFG_GPIO_CFG_CARRIER_SENSE 17 +#define CC1200_IOCFG_GPIO3_CFG_DSSS_CLK 18 +#define CC1200_IOCFG_GPIO2_CFG_DSSS_DATA0 18 +#define CC1200_IOCFG_GPIO1_CFG_DSSS_CLK 18 +#define CC1200_IOCFG_GPIO0_CFG_DSSS_DATA1 18 +#define CC1200_IOCFG_GPIO_CFG_PKT_CRC_OK 19 +#define CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP 20 +#define CC1200_IOCFG_GPIO_CFG_SYNC_LOW0_HIGH1 21 +#define CC1200_IOCFG_GPIO_CFG_LNA_PA_REG_PD 23 +#define CC1200_IOCFG_GPIO_CFG_LNA_PD 24 +#define CC1200_IOCFG_GPIO_CFG_PA_RD 25 +#define CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG 26 +#define CC1200_IOCFG_GPIO_CFG_IMAGE_FOUND 28 +#define CC1200_IOCFG_GPIO_CFG_CLKEN_SOFT 29 +#define CC1200_IOCFG_GPIO_CFG_SOFT_TX_DATA_CLK 30 +#define CC1200_IOCFG_GPIO_CFG_RSSI_STEP_FOUND 33 +#define CC1200_IOCFG_GPIO_CFG_RSSI_STEP_EVENT 34 +#define CC1200_IOCFG_GPIO_CFG_ANTENNA_SELECT 36 +#define CC1200_IOCFG_GPIO_CFG_MARC_2PIN_STATUS1 37 +#define CC1200_IOCFG_GPIO_CFG_MARC_2PIN_STATUS0 38 +#define CC1200_IOCFG_GPIO2_CFG_TXFIFO_OVERFLOW 39 +#define CC1200_IOCFG_GPIO0_CFG_RXFIFO_UNDERFLOW 39 +#define CC1200_IOCFG_GPIO3_CFG_MAGN_VALID 40 +#define CC1200_IOCFG_GPIO2_CFG_CHFILT_VALID 40 +#define CC1200_IOCFG_GPIO1_CFG_RCC_CAL_VALID 40 +#define CC1200_IOCFG_GPIO0_CFG_CHFILTER_STARTUP_VALID 40 +#define CC1200_IOCFG_GPIO3_CFG_COLLISION_FOUND 41 +#define CC1200_IOCFG_GPIO2_CFG_SYNC_EVENT 41 +#define CC1200_IOCFG_GPIO1_CFG_COLLISION_FOUND 41 +#define CC1200_IOCFG_GPIO0_CFG_COLLISION_EVENT 41 +#define CC1200_IOCFG_GPIO_CFG_PA_RAMP_UP 42 +#define CC1200_IOCFG_GPIO3_CFG_CRC_FAILED 43 +#define CC1200_IOCFG_GPIO2_CFG_LENGTH_FAILED 43 +#define CC1200_IOCFG_GPIO1_CFG_ADDR_FAILED 43 +#define CC1200_IOCFG_GPIO0_CFG_UART_FRAMING_ERROR 43 +#define CC1200_IOCFG_GPIO_CFG_AGC_STABLE_GAIN 44 +#define CC1200_IOCFG_GPIO_CFG_AGC_UPDATE 45 +#define CC1200_IOCFG_GPIO3_CFG_ADC_CLOCK 46 +#define CC1200_IOCFG_GPIO2_CFG_ADC_Q_DATA_SAMPLE 46 +#define CC1200_IOCFG_GPIO1_CFG_ADC_CLOCK 46 +#define CC1200_IOCFG_GPIO0_CFG_ADC_I_DATA_SAMPLE 46 +#define CC1200_IOCFG_GPIO_CFG_HIGHZ 48 +#define CC1200_IOCFG_GPIO_CFG_EXT_CLOCK 49 +#define CC1200_IOCFG_GPIO_CFG_CHIP_RDY 50 +#define CC1200_IOCFG_GPIO_CFG_HW0 51 +#define CC1200_IOCFG_GPIO_CFG_CLOCK_32K 54 +#define CC1200_IOCFG_GPIO_CFG_WOR_EVENT0 55 +#define CC1200_IOCFG_GPIO_CFG_WOR_EVENT1 56 +#define CC1200_IOCFG_GPIO_CFG_WOR_EVENT2 57 +#define CC1200_IOCFG_GPIO_CFG_XOSC_STABLE 59 +#define CC1200_IOCFG_GPIO_CFG_EXT_OSC_EN 60 +#define CC1200_IOCFG_GPIO_CFG_MASK 0x3f + +#define CC1200_IOCFG3 0x00 +#define CC1200_IOCFG2 0x01 +#define CC1200_IOCFG1 0x02 +#define CC1200_IOCFG0 0x03 +#define CC1200_SYNC3 0x04 +#define CC1200_SYNC2 0x05 +#define CC1200_SYNC1 0x06 +#define CC1200_SYNC0 0x07 + +#define CC1200_SYNC_CFG1 0x08 + +#define CC1200_SYNC_CFG1_SYNC_MODE 5 +#define CC1200_SYNC_CFG1_SYNC_MODE_NONE 0 +#define CC1200_SYNC_CFG1_SYNC_MODE_11_BITS 1 +#define CC1200_SYNC_CFG1_SYNC_MODE_16_BITS 2 +#define CC1200_SYNC_CFG1_SYNC_MODE_18_BITS 3 +#define CC1200_SYNC_CFG1_SYNC_MODE_24_BITS 4 +#define CC1200_SYNC_CFG1_SYNC_MODE_32_BITS 5 +#define CC1200_SYNC_CFG1_SYNC_MODE_16H_BITS 6 +#define CC1200_SYNC_CFG1_SYNC_MODE_16D_BITS 7 +#define CC1200_SYNC_CFG1_SYNC_MODE_MASK 7 + +#define CC1200_SYNC_CFG1_SYNC_THR 0 +#define CC1200_SYNC_CFG1_SYNC_MASK 0x1f + +#define CC1200_SYNC_CFG0 0x09 +#define CC1200_SYNC_CFG0_AUTO_CLEAR 5 +#define CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION 4 +#define CC1200_SYNC_CFG0_PQT_GATING_EN 3 +#define CC1200_SYNC_CFG0_EXT_SYNC_DETECT 2 + +#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK 0 +#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_1 0 +#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_2 1 +#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_LEVEL_3 2 +#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_DISABLED 3 +#define CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_MASK 3 + +#define CC1200_DEVIATION_M 0x0a +#define CC1200_MODCFG_DEV_E 0x0b +#define CC1200_MODCFG_DEV_E_MODEM_MODE 6 +#define CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL 0 +#define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_REPEAT 1 +#define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_PN 2 +#define CC1200_MODCFG_DEV_E_MODEM_MODE_CARRIER_SENSE 3 +#define CC1200_MODCFG_DEV_E_MODEM_MODE_MASK 3 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT 3 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_MASK 7 +#define CC1200_MODCFG_DEV_E_DEV_E 0 +#define CC1200_MODCFG_DEV_E_DEV_E_MASK 7 + +#define CC1200_DCFILT_CFG 0x0c +#define CC1200_PREAMBLE_CFG1 0x0d +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE 2 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE 0 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_0_5_BYTE 1 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_1_BYTE 2 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_1_5_BYTE 3 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_2_BYTES 4 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_3_BYTES 5 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES 6 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_5_BYTES 7 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_6_BYTES 8 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_7_BYTES 9 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_8_BYTES 10 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_12_BYTES 11 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_24_BYTES 12 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_30_BYTES 13 +#define CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_MASK 0xf + +#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD 0 +#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA 0 +#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_55 1 +#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_33 2 +#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_CC 3 +#define CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_MASK 3 + +#define CC1200_PREAMBLE_CFG0 0x0e +#define CC1200_PREAMBLE_CFG0_PQT_EN 7 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT 4 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 0 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_12 1 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_13 2 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_15 3 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_16 4 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_17 5 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_24 6 +#define CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_32 7 +#define CC1200_PREAMBLE_CFG0_PQT 0 +#define CC1200_PREAMBLE_CFG0_PQT_MASK 0xf + +#define CC1200_IQIC 0x0f +#define CC1200_CHAN_BW 0x10 +#define CC1200_CHAN_BW_ADC_CIC_DECFACT 6 +#define CC1200_CHAN_BW_ADC_CIC_DECFACT_12 0 +#define CC1200_CHAN_BW_ADC_CIC_DECFACT_24 1 +#define CC1200_CHAN_BW_ADC_CIC_DECFACT_48 2 +#define CC1200_CHAN_BW_BB_CIC_DECFACT 0 + +#define CC1200_MDMCFG1 0x11 +#define CC1200_MDMCFG1_CARRIER_SENSE_GATE 7 +#define CC1200_MDMCFG1_FIFO_EN 6 +#define CC1200_MDMCFG1_MANCHESTER_EN 5 +#define CC1200_MDMCFG1_INVERT_DATA_EN 4 +#define CC1200_MDMCFG1_COLLISION_DETECT_EN 3 +#define CC1200_MDMCFG1_DVGA_GAIN 1 +#define CC1200_MDMCFG1_DVGA_GAIN_0 0 +#define CC1200_MDMCFG1_DVGA_GAIN_3 1 +#define CC1200_MDMCFG1_DVGA_GAIN_6 2 +#define CC1200_MDMCFG1_DVGA_GAIN_9 3 +#define CC1200_MDMCFG1_DVGA_GAIN_MASK 3 +#define CC1200_MDMCFG1_SINGLE_ADC_EN 0 + +#define CC1200_MDMCFG0 0x12 +#define CC1200_MDMCFG0_TRANSPARENT_MODE_EN 6 +#define CC1200_MDMCFG0_TRANSPARENT_INTFACT 4 +#define CC1200_MDMCFG0_DATA_FILTER_EN 3 +#define CC1200_MDMCFG0_VITERBI_EN 2 + +#define CC1200_SYMBOL_RATE2 0x13 +#define CC1200_SYMBOL_RATE2_DATARATE_E 4 +#define CC1200_SYMBOL_RATE2_DATARATE_E_MASK 0xf +#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16 0 +#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK 0xf + +#define CC1200_SYMBOL_RATE1 0x14 +#define CC1200_SYMBOL_RATE0 0x15 +#define CC1200_AGC_REF 0x16 +#define CC1200_AGC_CS_THR 0x17 +#define CC1200_AGC_GAIN_ADJUST 0x18 + +#define CC1200_AGC_CFG3 0x19 +#define CC1200_AGC_CFG3_RSSI_STEP_THR 7 +#define CC1200_AGC_CFG3_AGC_MIN_GAIN 0 +#define CC1200_AGC_CFG3_AGC_MIN_GAIN_MASK 0x1f + +#define CC1200_AGC_CFG2 0x1a +#define CC1200_AGC_CFG2_START_PREVIOUS_GAIN_EN 7 +#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE 5 +#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_OPTIMIZE_LINEARITY 0 +#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_NORMAL 1 +#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_LOW_POWER 2 +#define CC1200_AGC_CFG2_FE_PERFORMANCE_MODE_MASK 3 +#define CC1200_AGC_CFG2_AGC_MAX_GAIN 0 +#define CC1200_AGC_CFG2_AGC_MAX_MASK 0x1f + +#define CC1200_AGC_CFG1 0x1b +#define CC1200_AGC_CFG1_RSSI_STEP_THR 6 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE 3 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE_8 0 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE_16 1 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE_32 2 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE_64 3 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE_128 4 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE_256 5 +#define CC1200_AGC_CFG1_AGC_WIN_SIZE_MASK 7 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT 0 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_24 0 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_32 1 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_40 2 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_48 3 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_64 4 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_80 5 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_96 6 +#define CC1200_AGC_CFG1_AGC_SETTLE_WAIT_127 7 + +#define CC1200_AGC_CFG0 0x1c + +#define CC1200_AGC_CFG0_AGC_HYST_LEVEL 6 +#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_2 0 +#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_4 1 +#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_7 2 +#define CC1200_AGC_CFG0_AGC_HYST_LEVEL_10 3 + +#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT 4 +#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_60 0 +#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_30 1 +#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_18 2 +#define CC1200_AGC_CFG0_AGC_SLEWRATE_LIMIT_9 3 + +#define CC1200_AGC_CFG0_RSSI_VALID_CNT 2 +#define CC1200_AGC_CFG0_RSSI_VALID_CNT_2 0 +#define CC1200_AGC_CFG0_RSSI_VALID_CNT_3 1 +#define CC1200_AGC_CFG0_RSSI_VALID_CNT_5 2 +#define CC1200_AGC_CFG0_RSSI_VALID_CNT_9 3 + +#define CC1200_AGC_CFG0_AGC_ASK_DECAY 0 +#define CC1200_AGC_CFG0_AGC_ASK_DECAY_1200 0 +#define CC1200_AGC_CFG0_AGC_ASK_DECAY_2400 1 +#define CC1200_AGC_CFG0_AGC_ASK_DECAY_4700 2 +#define CC1200_AGC_CFG0_AGC_ASK_DECAY_9500 3 + +#define CC1200_FIFO_CFG 0x1d +#define CC1200_FIFO_CFG_CRC_AUTOFLUSH 7 +#define CC1200_FIFO_CFG_FIFO_THR 0 + +#define CC1200_DEV_ADDR 0x1e +#define CC1200_SETTLING_CFG 0x1f +#define CC1200_SETTLING_CFG_FS_AUTOCAL 3 +#define CC1200_SETTLING_CFG_FS_AUTOCAL_NEVER 0 +#define CC1200_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON 1 +#define CC1200_SETTLING_CFG_FS_AUTOCAL_ON_TO_IDLE 2 +#define CC1200_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME 3 +#define CC1200_SETTLING_CFG_FS_AUTOCAL_MASK 3 +#define CC1200_SETTLING_CFG_LOCK_TIME 1 +#define CC1200_SETTLING_CFG_LOCK_TIME_50_20 0 +#define CC1200_SETTLING_CFG_LOCK_TIME_75_30 1 +#define CC1200_SETTLING_CFG_LOCK_TIME_100_40 2 +#define CC1200_SETTLING_CFG_LOCK_TIME_150_60 3 +#define CC1200_SETTLING_CFG_LOCK_TIME_MASK 3 +#define CC1200_SETTLING_CFG_FSREG_TIME 0 +#define CC1200_SETTLING_CFG_FSREG_TIME_30 0 +#define CC1200_SETTLING_CFG_FSREG_TIME_60 1 +#define CC1200_SETTLING_CFG_FSREG_TIME_MASK 1 + +#define CC1200_FS_CFG 0x20 +#define CC1200_FS_CFG_LOCK_EN 4 +#define CC1200_FS_CFG_FSD_BANDSELECT 0 +#define CC1200_FS_CFG_FSD_BANDSELECT_820_960 2 +#define CC1200_FS_CFG_FSD_BANDSELECT_410_480 4 +#define CC1200_FS_CFG_FSD_BANDSELECT_273_320 6 +#define CC1200_FS_CFG_FSD_BANDSELECT_205_240 8 +#define CC1200_FS_CFG_FSD_BANDSELECT_164_192 10 +#define CC1200_FS_CFG_FSD_BANDSELECT_136_160 11 +#define CC1200_FS_CFG_FSD_BANDSELECT_MASK 0xf + +#define CC1200_WOR_CFG1 0x21 +#define CC1200_WOR_CFG0 0x22 +#define CC1200_WOR_EVENT0_MSB 0x23 +#define CC1200_WOR_EVENT0_LSB 0x24 +#define CC1200_RXDCM_TIME 0x25 +#define CC1200_PKT_CFG2 0x26 +#define CC1200_PKT_CFG2_CCA_MODE 2 +#define CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR 0 +#define CC1200_PKT_CFG2_CCA_MODE_RSSI_THRESHOLD 1 +#define CC1200_PKT_CFG2_CCA_MODE_NOT_RECEIVING 2 +#define CC1200_PKT_CFG2_CCA_MODE_RSSI_OR_NOT 3 +#define CC1200_PKT_CFG2_CCA_MODE_RSSI_AND_ETSI_LBT 4 +#define CC1200_PKT_CFG2_CCA_MODE_MASK 7 +#define CC1200_PKT_CFG2_PKT_FORMAT 0 +#define CC1200_PKT_CFG2_PKT_FORMAT_NORMAL 0 +#define CC1200_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL 1 +#define CC1200_PKT_CFG2_PKT_FORMAT_RANDOM 2 +#define CC1200_PKT_CFG2_PKT_FORMAT_TRANSPARENT_SERIAL 3 +#define CC1200_PKT_CFG2_PKT_FORMAT_MASK 3 + +#define CC1200_PKT_CFG1 0x27 +#define CC1200_PKT_CFG1_WHITE_DATA 6 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG 4 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE 0 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_CHECK 1 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_BROADCAST 2 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_FF_BROADCAST 3 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG_MASK 3 +#define CC1200_PKT_CFG1_CRC_CFG 2 +#define CC1200_PKT_CFG1_CRC_CFG_DISABLED 0 +#define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES 1 +#define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ZEROS 2 +#define CC1200_PKT_CFG1_CRC_CFG_MASK 3 +#define CC1200_PKT_CFG1_BYTE_SWAP_EN 1 +#define CC1200_PKT_CFG1_APPEND_STATUS 0 + +#define CC1200_PKT_CFG0 0x28 +#define CC1200_PKT_CFG0_RESERVED7 7 +#define CC1200_PKT_CFG0_LENGTH_CONFIG 5 +#define CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED 0 +#define CC1200_PKT_CFG0_LENGTH_CONFIG_VARIABLE 1 +#define CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE 2 +#define CC1200_PKT_CFG0_LENGTH_CONFIG_VARIABLE_5LSB 3 +#define CC1200_PKT_CFG0_LENGTH_CONFIG_MASK 3 +#define CC1200_PKT_CFG0_PKG_BIT_LEN 2 +#define CC1200_PKT_CFG0_PKG_BIT_LEN_MASK 7 +#define CC1200_PKT_CFG0_UART_MODE_EN 1 +#define CC1200_PKT_CFG0_UART_SWAP_EN 0 + +#define CC1200_RFEND_CFG1 0x29 +#define CC1200_RFEND_CFG0 0x2a +#define CC1200_PA_CFG1 0x2b +#define CC1200_PA_CFG0 0x2c +#define CC1200_ASK_CFG 0x2d +#define CC1200_PKT_LEN 0x2e + +#define CC1200_EXTENDED 0x2f + +/* Command strobes */ +#define CC1200_SRES 0x30 +#define CC1200_SFSTXON 0x31 +#define CC1200_SXOFF 0x32 +#define CC1200_SCAL 0x33 +#define CC1200_SRX 0x34 +#define CC1200_STX 0x35 +#define CC1200_SIDLE 0x36 +#define CC1200_SAFC 0x37 +#define CC1200_SWOR 0x38 +#define CC1200_SPWD 0x39 +#define CC1200_SFRX 0x3a +#define CC1200_SFTX 0x3b +#define CC1200_SWORRST 0x3c +#define CC1200_SNOP 0x3d + +#define CC1200_DIRECT_FIFO 0x3e +#define CC1200_FIFO 0x3f + +#define CC1200_FIFO_SIZE 128 + +/* Extended register space */ + +#define CC1200_EXTENDED_BIT 0x8000 + +#define CC1200_IS_EXTENDED(r) ((r) & CC1200_EXTENDED_BIT) + +#define CC1200_IF_MIX_CFG (CC1200_EXTENDED_BIT | 0x00) +#define CC1200_FREQOFF_CFG (CC1200_EXTENDED_BIT | 0x01) +#define CC1200_TOC_CFG (CC1200_EXTENDED_BIT | 0x02) +#define CC1200_MARC_SPARE (CC1200_EXTENDED_BIT | 0x03) +#define CC1200_ECG_CFG (CC1200_EXTENDED_BIT | 0x04) +#define CC1200_MDMCFG2 (CC1200_EXTENDED_BIT | 0x05) + +# define CC1200_MDMCFG2_ASK_SHAPE 6 +# define CC1200_MDMCFG2_SYMBOL_MAP_CFG 4 +# define CC1200_MDMCFG2_UPSAMPLER_P 1 +# define CC1200_MDMCFG2_CFM_DATA_EN 0 + +#define CC1200_EXT_CTRL (CC1200_EXTENDED_BIT | 0x06) +#define CC1200_RCCAL_FINE (CC1200_EXTENDED_BIT | 0x07) +#define CC1200_RCCAL_COARSE (CC1200_EXTENDED_BIT | 0x08) +#define CC1200_RCCAL_OFFSET (CC1200_EXTENDED_BIT | 0x09) +#define CC1200_FREQOFF1 (CC1200_EXTENDED_BIT | 0x0A) +#define CC1200_FREQOFF0 (CC1200_EXTENDED_BIT | 0x0B) +#define CC1200_FREQ2 (CC1200_EXTENDED_BIT | 0x0C) +#define CC1200_FREQ1 (CC1200_EXTENDED_BIT | 0x0D) +#define CC1200_FREQ0 (CC1200_EXTENDED_BIT | 0x0E) +#define CC1200_IF_ADC2 (CC1200_EXTENDED_BIT | 0x0F) +#define CC1200_IF_ADC1 (CC1200_EXTENDED_BIT | 0x10) +#define CC1200_IF_ADC0 (CC1200_EXTENDED_BIT | 0x11) +#define CC1200_FS_DIG1 (CC1200_EXTENDED_BIT | 0x12) +#define CC1200_FS_DIG0 (CC1200_EXTENDED_BIT | 0x13) +#define CC1200_FS_CAL3 (CC1200_EXTENDED_BIT | 0x14) +#define CC1200_FS_CAL2 (CC1200_EXTENDED_BIT | 0x15) +#define CC1200_FS_CAL1 (CC1200_EXTENDED_BIT | 0x16) +#define CC1200_FS_CAL0 (CC1200_EXTENDED_BIT | 0x17) +#define CC1200_FS_CHP (CC1200_EXTENDED_BIT | 0x18) +#define CC1200_FS_DIVTWO (CC1200_EXTENDED_BIT | 0x19) +#define CC1200_FS_DSM1 (CC1200_EXTENDED_BIT | 0x1A) +#define CC1200_FS_DSM0 (CC1200_EXTENDED_BIT | 0x1B) +#define CC1200_FS_DVC1 (CC1200_EXTENDED_BIT | 0x1C) +#define CC1200_FS_DVC0 (CC1200_EXTENDED_BIT | 0x1D) +#define CC1200_FS_LBI (CC1200_EXTENDED_BIT | 0x1E) +#define CC1200_FS_PFD (CC1200_EXTENDED_BIT | 0x1F) +#define CC1200_FS_PRE (CC1200_EXTENDED_BIT | 0x20) +#define CC1200_FS_REG_DIV_CML (CC1200_EXTENDED_BIT | 0x21) +#define CC1200_FS_SPARE (CC1200_EXTENDED_BIT | 0x22) +#define CC1200_FS_VCO4 (CC1200_EXTENDED_BIT | 0x23) +#define CC1200_FS_VCO3 (CC1200_EXTENDED_BIT | 0x24) +#define CC1200_FS_VCO2 (CC1200_EXTENDED_BIT | 0x25) +#define CC1200_FS_VCO1 (CC1200_EXTENDED_BIT | 0x26) +#define CC1200_FS_VCO0 (CC1200_EXTENDED_BIT | 0x27) +#define CC1200_GBIAS6 (CC1200_EXTENDED_BIT | 0x28) +#define CC1200_GBIAS5 (CC1200_EXTENDED_BIT | 0x29) +#define CC1200_GBIAS4 (CC1200_EXTENDED_BIT | 0x2A) +#define CC1200_GBIAS3 (CC1200_EXTENDED_BIT | 0x2B) +#define CC1200_GBIAS2 (CC1200_EXTENDED_BIT | 0x2C) +#define CC1200_GBIAS1 (CC1200_EXTENDED_BIT | 0x2D) +#define CC1200_GBIAS0 (CC1200_EXTENDED_BIT | 0x2E) +#define CC1200_IFAMP (CC1200_EXTENDED_BIT | 0x2F) +#define CC1200_LNA (CC1200_EXTENDED_BIT | 0x30) +#define CC1200_RXMIX (CC1200_EXTENDED_BIT | 0x31) +#define CC1200_XOSC5 (CC1200_EXTENDED_BIT | 0x32) +#define CC1200_XOSC4 (CC1200_EXTENDED_BIT | 0x33) +#define CC1200_XOSC3 (CC1200_EXTENDED_BIT | 0x34) +#define CC1200_XOSC2 (CC1200_EXTENDED_BIT | 0x35) +#define CC1200_XOSC1 (CC1200_EXTENDED_BIT | 0x36) +#define CC1200_XOSC0 (CC1200_EXTENDED_BIT | 0x37) +#define CC1200_ANALOG_SPARE (CC1200_EXTENDED_BIT | 0x38) +#define CC1200_PA_CFG3 (CC1200_EXTENDED_BIT | 0x39) +#define CC1200_WOR_TIME1 (CC1200_EXTENDED_BIT | 0x64) +#define CC1200_WOR_TIME0 (CC1200_EXTENDED_BIT | 0x65) +#define CC1200_WOR_CAPTURE1 (CC1200_EXTENDED_BIT | 0x66) +#define CC1200_WOR_CAPTURE0 (CC1200_EXTENDED_BIT | 0x67) +#define CC1200_BIST (CC1200_EXTENDED_BIT | 0x68) +#define CC1200_DCFILTOFFSET_I1 (CC1200_EXTENDED_BIT | 0x69) +#define CC1200_DCFILTOFFSET_I0 (CC1200_EXTENDED_BIT | 0x6A) +#define CC1200_DCFILTOFFSET_Q1 (CC1200_EXTENDED_BIT | 0x6B) +#define CC1200_DCFILTOFFSET_Q0 (CC1200_EXTENDED_BIT | 0x6C) +#define CC1200_IQIE_I1 (CC1200_EXTENDED_BIT | 0x6D) +#define CC1200_IQIE_I0 (CC1200_EXTENDED_BIT | 0x6E) +#define CC1200_IQIE_Q1 (CC1200_EXTENDED_BIT | 0x6f) +#define CC1200_IQIE_Q0 (CC1200_EXTENDED_BIT | 0x70) +#define CC1200_RSSI1 (CC1200_EXTENDED_BIT | 0x71) +#define CC1200_RSSI0 (CC1200_EXTENDED_BIT | 0x72) +#define CC1200_MARCSTATE (CC1200_EXTENDED_BIT | 0x73) +#define CC1200_LQI_VAL (CC1200_EXTENDED_BIT | 0x74) +#define CC1200_PQT_SYNC_ERR (CC1200_EXTENDED_BIT | 0x75) +#define CC1200_DEM_STATUS (CC1200_EXTENDED_BIT | 0x76) +#define CC1200_FREQOFF_EST1 (CC1200_EXTENDED_BIT | 0x77) +#define CC1200_FREQOFF_EST0 (CC1200_EXTENDED_BIT | 0x78) +#define CC1200_AGC_GAIN3 (CC1200_EXTENDED_BIT | 0x79) +#define CC1200_AGC_GAIN2 (CC1200_EXTENDED_BIT | 0x7a) +#define CC1200_AGC_GAIN1 (CC1200_EXTENDED_BIT | 0x7b) +#define CC1200_AGC_GAIN0 (CC1200_EXTENDED_BIT | 0x7c) +#define CC1200_SOFT_RX_DATA_OUT (CC1200_EXTENDED_BIT | 0x7d) +#define CC1200_SOFT_TX_DATA_IN (CC1200_EXTENDED_BIT | 0x7e) +#define CC1200_ASK_SOFT_RX_DATA (CC1200_EXTENDED_BIT | 0x7f) +#define CC1200_RNDGEN (CC1200_EXTENDED_BIT | 0x80) +#define CC1200_MAGN2 (CC1200_EXTENDED_BIT | 0x81) +#define CC1200_MAGN1 (CC1200_EXTENDED_BIT | 0x82) +#define CC1200_MAGN0 (CC1200_EXTENDED_BIT | 0x83) +#define CC1200_ANG1 (CC1200_EXTENDED_BIT | 0x84) +#define CC1200_ANG0 (CC1200_EXTENDED_BIT | 0x85) +#define CC1200_CHFILT_I2 (CC1200_EXTENDED_BIT | 0x86) +#define CC1200_CHFILT_I1 (CC1200_EXTENDED_BIT | 0x87) +#define CC1200_CHFILT_I0 (CC1200_EXTENDED_BIT | 0x88) +#define CC1200_CHFILT_Q2 (CC1200_EXTENDED_BIT | 0x89) +#define CC1200_CHFILT_Q1 (CC1200_EXTENDED_BIT | 0x8a) +#define CC1200_CHFILT_Q0 (CC1200_EXTENDED_BIT | 0x8b) +#define CC1200_GPIO_STATUS (CC1200_EXTENDED_BIT | 0x8c) +#define CC1200_FSCAL_CTRL (CC1200_EXTENDED_BIT | 0x8d) +#define CC1200_PHASE_ADJUST (CC1200_EXTENDED_BIT | 0x8e) +#define CC1200_PARTNUMBER (CC1200_EXTENDED_BIT | 0x8f) +#define CC1200_PARTVERSION (CC1200_EXTENDED_BIT | 0x90) +#define CC1200_SERIAL_STATUS (CC1200_EXTENDED_BIT | 0x91) +#define CC1200_RX_STATUS (CC1200_EXTENDED_BIT | 0x92) +#define CC1200_TX_STATUS (CC1200_EXTENDED_BIT | 0x93) +#define CC1200_MARC_STATUS1 (CC1200_EXTENDED_BIT | 0x94) +# define CC1200_MARC_STATUS1_NO_FAILURE 0 +# define CC1200_MARC_STATUS1_RX_TIMEOUT 1 +# define CC1200_MARC_STATUS1_RX_TERMINATION 2 +# define CC1200_MARC_STATUS1_EWOR_SYNC_LOST 3 +# define CC1200_MARC_STATUS1_MAXIMUM_LENGTH 4 +# define CC1200_MARC_STATUS1_ADDRESS 5 +# define CC1200_MARC_STATUS1_CRC 6 +# define CC1200_MARC_STATUS1_TX_FIFO_OVERFLOW 7 +# define CC1200_MARC_STATUS1_TX_FIFO_UNDERFLOW 8 +# define CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW 9 +# define CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW 10 +# define CC1200_MARC_STATUS1_TX_ON_CCA_FAILED 11 +# define CC1200_MARC_STATUS1_TX_FINISHED 0x40 +# define CC1200_MARC_STATUS1_RX_FINISHED 0x80 +#define CC1200_MARC_STATUS0 (CC1200_EXTENDED_BIT | 0x95) +#define CC1200_PA_IFAMP_TEST (CC1200_EXTENDED_BIT | 0x96) +#define CC1200_FSRF_TEST (CC1200_EXTENDED_BIT | 0x97) +#define CC1200_PRE_TEST (CC1200_EXTENDED_BIT | 0x98) +#define CC1200_PRE_OVR (CC1200_EXTENDED_BIT | 0x99) +#define CC1200_ADC_TEST (CC1200_EXTENDED_BIT | 0x9a) +#define CC1200_DVC_TEST (CC1200_EXTENDED_BIT | 0x9b) +#define CC1200_ATEST (CC1200_EXTENDED_BIT | 0x9c) +#define CC1200_ATEST_LVDS (CC1200_EXTENDED_BIT | 0x9d) +#define CC1200_ATEST_MODE (CC1200_EXTENDED_BIT | 0x9e) +#define CC1200_XOSC_TEST1 (CC1200_EXTENDED_BIT | 0x9f) +#define CC1200_XOSC_TEST0 (CC1200_EXTENDED_BIT | 0xa0) +#define CC1200_RXFIRST (CC1200_EXTENDED_BIT | 0xd2) +#define CC1200_TXFIRST (CC1200_EXTENDED_BIT | 0xd3) +#define CC1200_RXLAST (CC1200_EXTENDED_BIT | 0xd4) +#define CC1200_TXLAST (CC1200_EXTENDED_BIT | 0xd5) +#define CC1200_NUM_TXBYTES (CC1200_EXTENDED_BIT | 0xd6) +#define CC1200_NUM_RXBYTES (CC1200_EXTENDED_BIT | 0xd7) +#define CC1200_FIFO_NUM_TXBYTES (CC1200_EXTENDED_BIT | 0xd8) +#define CC1200_FIFO_NUM_RXBYTES (CC1200_EXTENDED_BIT | 0xd9) +#define CC1200_RXFIFO_PRE_BUF (CC1200_EXTENDED_BIT | 0xda) +#define CC1200_AES_WORKSPACE_0 (CC1200_EXTENDED_BIT | 0xe0) + +/* Status byte */ +#define CC1200_STATUS_CHIP_RDY 7 +#define CC1200_STATUS_STATE 4 +#define CC1200_STATUS_STATE_IDLE 0 +#define CC1200_STATUS_STATE_RX 1 +#define CC1200_STATUS_STATE_TX 2 +#define CC1200_STATUS_STATE_FSTXON 3 +#define CC1200_STATUS_STATE_CALIBRATE 4 +#define CC1200_STATUS_STATE_SETTLING 5 +#define CC1200_STATUS_STATE_RX_FIFO_ERROR 6 +#define CC1200_STATUS_STATE_TX_FIFO_ERROR 7 +#define CC1200_STATUS_STATE_MASK 7 + +#endif /* _AO_CC1200_H_ */ diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h new file mode 100644 index 00000000..670e89ef --- /dev/null +++ b/src/drivers/ao_cc1200_CC1200.h @@ -0,0 +1,56 @@ +/*************************************************************** + * SmartRF Studio(tm) Export + * + * Radio register settings specifed with address, value + * + * RF device: CC1200 + * + ***************************************************************/ + + + CC1200_IOCFG2, 0x06, /* GPIO2 IO Pin Configuration */ + CC1200_SYNC1, 0x6e, /* Sync Word Configuration [15:8] */ + CC1200_SYNC0, 0x4e, /* Sync Word Configuration [7:0] */ + CC1200_SYNC_CFG1, 0xea, /* Sync Word Detection Configuration Reg. 1 */ + CC1200_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ + CC1200_DCFILT_CFG, 0x5d, /* Digital DC Removal Configuration */ + CC1200_PREAMBLE_CFG0, 0x8a, /* Preamble Detection Configuration Reg. 0 */ + CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */ + CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */ + CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */ + CC1200_MDMCFG0, 0x05, /* General Modem Parameter Configuration Reg. 0 */ + CC1200_SYMBOL_RATE2, 0x93, /* Symbol Rate Configuration Exponent and Mantissa [1.. */ + CC1200_AGC_REF, 0x37, /* AGC Reference Level Configuration */ + CC1200_AGC_CS_THR, 0xec, /* Carrier Sense Threshold Configuration */ + CC1200_AGC_CFG1, 0x51, /* Automatic Gain Control Configuration Reg. 1 */ + CC1200_AGC_CFG0, 0x87, /* Automatic Gain Control Configuration Reg. 0 */ + CC1200_FIFO_CFG, 0x00, /* FIFO Configuration */ + CC1200_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */ + CC1200_PKT_CFG2, 0x20, /* Packet Configuration Reg. 2 */ + CC1200_PKT_CFG1, 0xc3, /* Packet Configuration Reg. 1 */ + CC1200_PKT_CFG0, 0x20, /* Packet Configuration Reg. 0 */ + CC1200_PA_CFG1, 0x3f, /* Power Amplifier Configuration Reg. 1 */ + CC1200_PA_CFG0, 0x53, /* Power Amplifier Configuration Reg. 0 */ + CC1200_PKT_LEN, 0xff, /* Packet Length Configuration */ + CC1200_IF_MIX_CFG, 0x1c, /* IF Mix Configuration */ + CC1200_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */ + CC1200_MDMCFG2, 0x0c, /* General Modem Parameter Configuration Reg. 2 */ + CC1200_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ + CC1200_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ + CC1200_FREQ0, 0x33, /* Frequency Configuration [7:0] */ + CC1200_IF_ADC1, 0xee, /* Analog to Digital Converter Configuration Reg. 1 */ + CC1200_IF_ADC0, 0x10, /* Analog to Digital Converter Configuration Reg. 0 */ + CC1200_FS_DIG1, 0x07, /* Frequency Synthesizer Digital Reg. 1 */ + CC1200_FS_DIG0, 0xaf, /* Frequency Synthesizer Digital Reg. 0 */ + CC1200_FS_CAL1, 0x40, /* Frequency Synthesizer Calibration Reg. 1 */ + CC1200_FS_CAL0, 0x0e, /* Frequency Synthesizer Calibration Reg. 0 */ + CC1200_FS_DIVTWO, 0x03, /* Frequency Synthesizer Divide by 2 */ + CC1200_FS_DSM0, 0x33, /* FS Digital Synthesizer Module Configuration Reg. 0 */ + CC1200_FS_DVC0, 0x17, /* Frequency Synthesizer Divider Chain Configuration .. */ + CC1200_FS_PFD, 0x00, /* Frequency Synthesizer Phase Frequency Detector Con.. */ + CC1200_FS_PRE, 0x6e, /* Frequency Synthesizer Prescaler Configuration */ + CC1200_FS_REG_DIV_CML, 0x1c, /* Frequency Synthesizer Divider Regulator Configurat.. */ + CC1200_FS_SPARE, 0xac, /* Frequency Synthesizer Spare */ + CC1200_FS_VCO0, 0xb5, /* FS Voltage Controlled Oscillator Configuration Reg.. */ + CC1200_XOSC5, 0x0e, /* Crystal Oscillator Configuration Reg. 5 */ + CC1200_XOSC1, 0x03, /* Crystal Oscillator Configuration Reg. 1 */ -- cgit v1.2.3 From ffda6989e856e66a1bea253e82cb70f51ada3e7a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Oct 2014 00:07:10 -0700 Subject: altos: Add prototype TeleDongle v1.9 code Lights up the hardware, sends carrier and RDF tones. A bit more cc1200 work to be done still. Signed-off-by: Keith Packard --- src/teledongle-v1.9/.gitignore | 2 + src/teledongle-v1.9/Makefile | 89 ++++++++++++++++++ src/teledongle-v1.9/ao_pins.h | 146 +++++++++++++++++++++++++++++ src/teledongle-v1.9/ao_teledongle.c | 54 +++++++++++ src/teledongle-v1.9/flash-loader/Makefile | 7 ++ src/teledongle-v1.9/flash-loader/ao_pins.h | 34 +++++++ 6 files changed, 332 insertions(+) create mode 100644 src/teledongle-v1.9/.gitignore create mode 100644 src/teledongle-v1.9/Makefile create mode 100644 src/teledongle-v1.9/ao_pins.h create mode 100644 src/teledongle-v1.9/ao_teledongle.c create mode 100644 src/teledongle-v1.9/flash-loader/Makefile create mode 100644 src/teledongle-v1.9/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/teledongle-v1.9/.gitignore b/src/teledongle-v1.9/.gitignore new file mode 100644 index 00000000..9a30cbb6 --- /dev/null +++ b/src/teledongle-v1.9/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +teledongle-*.elf diff --git a/src/teledongle-v1.9/Makefile b/src/teledongle-v1.9/Makefile new file mode 100644 index 00000000..a8999c27 --- /dev/null +++ b/src/teledongle-v1.9/Makefile @@ -0,0 +1,89 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + ao_whiten.h \ + stm32l.h \ + 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 + +# ao_monitor.c \ +# ao_rssi.c \ +# ao_send_packet.c \ +# ao_packet_master.c \ +# ao_packet.c + + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cc1200.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_eeprom_stm.c + +PRODUCT=TeleDongle-v1.9 +PRODUCT_DEF=-DTELEDONGLE +IDPRODUCT=0x000c + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=teledongle-v1.9 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_teledongle.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/teledongle-v1.9/ao_pins.h b/src/teledongle-v1.9/ao_pins.h new file mode 100644 index 00000000..bbc42a5d --- /dev/null +++ b/src/teledongle-v1.9/ao_pins.h @@ -0,0 +1,146 @@ +/* + * 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. + */ + +/* Using TeleMetrum v1.9 board */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE 1 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1 0 +#define USE_SERIAL_1_STDIN 0 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 0 + +#define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 0 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 0 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 0 +#define SERIAL_3_PD8_PD9 0 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 1 +#define USE_STORAGE_CONFIG 0 +#define USE_EEPROM_CONFIG 1 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 0 +#define HAS_RSSI 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 /* Barometer */ +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 /* Accelerometer */ + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 /* Radio */ +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define SPI_2_PORT (&stm_gpiob) +#define SPI_2_SCK_PIN 13 +#define SPI_2_MISO_PIN 14 +#define SPI_2_MOSI_PIN 15 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 1 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT_0 (&stm_gpioc) +#define LED_PORT_0_MASK (0xffff) +#define LED_PORT_0_SHIFT 0 +#define LED_PIN_RED 8 +#define LED_PIN_GREEN 9 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS 0 +#define HAS_FLIGHT 0 +#define HAS_ADC 0 +#define HAS_LOG 0 + +/* + * Telemetry monitoring + */ +#define HAS_MONITOR 0 +#define LEGACY_MONITOR 0 +#define HAS_MONITOR_PUT 1 +#define AO_MONITOR_LED AO_LED_GREEN + +/* + * Radio (cc1200) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x6ca333 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpioc) +#define AO_CC1200_SPI_CS_PIN 5 +#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI stm_spi2 + +#define AO_CC1200_INT_PORT (&stm_gpioe) +#define AO_CC1200_INT_PIN 1 + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +/* + * Profiling Viterbi decoding + */ + +#ifndef AO_PROFILE +#define AO_PROFILE 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/teledongle-v1.9/ao_teledongle.c b/src/teledongle-v1.9/ao_teledongle.c new file mode 100644 index 00000000..ac1e3c9f --- /dev/null +++ b/src/teledongle-v1.9/ao_teledongle.c @@ -0,0 +1,54 @@ +/* + * 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 +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_cmd_init(); + + ao_usb_init(); + ao_radio_init(); +// ao_monitor_init(); +// ao_rssi_init(AO_LED_RED); +// ao_packet_master_init(); +// ao_send_packet_init(); + + ao_config_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/teledongle-v1.9/flash-loader/Makefile b/src/teledongle-v1.9/flash-loader/Makefile new file mode 100644 index 00000000..70ddaad4 --- /dev/null +++ b/src/teledongle-v1.9/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=teledongle-v1.9 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/teledongle-v1.9/flash-loader/ao_pins.h b/src/teledongle-v1.9/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/teledongle-v1.9/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiod +#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 484b530a16a54ca8fde412c3f466bfe7eed978cd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 Oct 2014 05:32:00 +0200 Subject: altos: Mark STM ao_spi_send as taking const pointer We don't write to this, so let it be const for type checking Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 2 +- src/stm/ao_spi_stm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 7ad3b4b8..42f1a2e5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -74,7 +74,7 @@ void ao_spi_put(uint8_t spi_index); void -ao_spi_send(void *block, uint16_t len, uint8_t spi_index); +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index); void ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 885af544..7eaa3924 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -42,7 +42,7 @@ static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { static uint8_t spi_dev_null; void -ao_spi_send(void *block, uint16_t len, uint8_t spi_index) +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index) { struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; @@ -51,7 +51,7 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, &stm_spi->dr, - block, + (void *) block, len, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | -- cgit v1.2.3 From 7fea8b245cdccc1ec77aa559433952f339676473 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 Oct 2014 05:35:10 +0200 Subject: altos: Expose telemetry altitude macros even without GPS This allows for APRS testing in the new teledongle code Signed-off-by: Keith Packard --- src/kernel/ao_telemetry.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_telemetry.h b/src/kernel/ao_telemetry.h index 83d432cf..340c388e 100644 --- a/src/kernel/ao_telemetry.h +++ b/src/kernel/ao_telemetry.h @@ -116,8 +116,6 @@ struct ao_telemetry_location { /* 32 */ }; -#if HAS_GPS - #ifndef HAS_WIDE_GPS #define HAS_WIDE_GPS 1 #endif @@ -135,8 +133,6 @@ typedef int16_t gps_alt_t; (l)->altitude_low = (a))) #endif /* HAS_WIDE_GPS */ -#endif /* HAS_GPS */ - #define AO_TELEMETRY_SATELLITE 0x06 struct ao_telemetry_satellite_info { -- cgit v1.2.3 From 4a3fe79266a77f8fc001117f49db1d2f14f9e6b6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 Oct 2014 05:34:06 +0200 Subject: altos: Complete cc1200 driver Deal with differences between cc1120 and cc1200, including built-in packet support and various register changes. This now works to send and receive telemetry, as well as send APRS and RDF. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 554 ++++++++++++++++++++++++++--------------- src/drivers/ao_cc1200.h | 129 +++++++--- src/drivers/ao_cc1200_CC1200.h | 72 +++++- 3 files changed, 499 insertions(+), 256 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index a69cdc11..39d3d522 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -21,30 +21,24 @@ #include #include -#define AO_RADIO_MAX_RECV sizeof(struct ao_packet) -#define AO_RADIO_MAX_SEND sizeof(struct ao_packet) - static uint8_t ao_radio_mutex; static uint8_t ao_radio_wake; /* radio ready. Also used as sleep address */ static uint8_t ao_radio_abort; /* radio operation should abort */ -static uint8_t ao_radio_mcu_wake; /* MARC status change */ -static uint8_t ao_radio_marc_status; /* Last read MARC status value */ -static uint8_t ao_radio_tx_finished; /* MARC status indicates TX finished */ int8_t ao_radio_rssi; /* Last received RSSI value */ -#define CC1200_DEBUG 1 -#define CC1200_TRACE 1 +#define CC1200_DEBUG 0 +#define CC1200_LOW_LEVEL_DEBUG 0 +#define CC1200_TRACE 0 +#define CC1200_APRS_TRACE 0 extern const uint32_t ao_radio_cal; -#define FOSC 32000000 +#define FOSC 40000000 -#define ao_radio_try_select(task_id) ao_spi_try_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz, task_id) #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_125kHz) #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_sync(d,l) ao_spi_send_sync((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1200_SPI_BUS) @@ -128,7 +122,6 @@ ao_radio_strobe(uint8_t addr) return in; } -#if 0 static uint8_t ao_radio_fifo_read(uint8_t *data, uint8_t len) { @@ -143,7 +136,6 @@ ao_radio_fifo_read(uint8_t *data, uint8_t len) ao_radio_deselect(); return status; } -#endif static uint8_t ao_radio_fifo_write_start(void) @@ -164,7 +156,7 @@ static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { } static uint8_t -ao_radio_fifo_write(uint8_t *data, uint8_t len) +ao_radio_fifo_write(const uint8_t *data, uint8_t len) { uint8_t status = ao_radio_fifo_write_start(); ao_radio_spi_send(data, len); @@ -185,13 +177,11 @@ ao_radio_tx_fifo_space(void) return CC1200_FIFO_SIZE - ao_radio_reg_read(CC1200_NUM_TXBYTES); } -#if CC1200_DEBUG || CC1200_TRACE static uint8_t ao_radio_status(void) { return ao_radio_strobe (CC1200_SNOP); } -#endif void ao_radio_recv_abort(void) @@ -202,25 +192,6 @@ ao_radio_recv_abort(void) #define ao_radio_rdf_value 0x55 -static uint8_t -ao_radio_get_marc_status(void) -{ - return ao_radio_reg_read(CC1200_MARC_STATUS1); -} - -static void -ao_radio_check_marc_status(void) -{ - ao_radio_mcu_wake = 0; - ao_radio_marc_status = ao_radio_get_marc_status(); - - /* Anyt other than 'tx/rx finished' means an error occurred */ - if (ao_radio_marc_status & ~(CC1200_MARC_STATUS1_TX_FINISHED|CC1200_MARC_STATUS1_RX_FINISHED)) - ao_radio_abort = 1; - if (ao_radio_marc_status & (CC1200_MARC_STATUS1_TX_FINISHED)) - ao_radio_tx_finished = 1; -} - static void ao_radio_isr(void) { @@ -232,19 +203,27 @@ ao_radio_isr(void) static void ao_radio_start_tx(void) { - ao_exti_set_callback(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, ao_radio_isr); ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); - ao_radio_tx_finished = 0; ao_radio_strobe(CC1200_STX); } +static void +ao_radio_start_rx(void) +{ + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_strobe(CC1200_SRX); +} + static void ao_radio_idle(void) { for (;;) { uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; - if (state == CC1200_STATUS_STATE_IDLE) + if (state == CC1200_STATUS_STATE_IDLE) { + ao_radio_strobe(CC1200_SFTX); + ao_radio_strobe(CC1200_SFRX); break; + } if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR) ao_radio_strobe(CC1200_SFTX); if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR) @@ -257,30 +236,30 @@ ao_radio_idle(void) /* * Packet deviation * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * fdev = fosc >> 22 * (256 + dev_m) << dev_e * * Deviation for 38400 baud should be 20.5kHz: * - * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 3) = 20523Hz * * Deviation for 9600 baud should be 5.125kHz: * - * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 3) = 5127Hz + * 40e6 / (2 ** 22) * (256 + 13) * (2 ** 1) = 5131Hz * * Deviation for 2400 baud should be 1.28125kHz, but cc1111 and * cc115l can't do that, so we'll use 1.5kHz instead: * - * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 1) = 1499Hz + * 40e6 / (2 ** 21) * (79) = 1506Hz */ -#define PACKET_DEV_M_384 80 -#define PACKET_DEV_E_384 5 +#define PACKET_DEV_M_384 13 +#define PACKET_DEV_E_384 3 -#define PACKET_DEV_M_96 80 -#define PACKET_DEV_E_96 3 +#define PACKET_DEV_M_96 13 +#define PACKET_DEV_E_96 1 -#define PACKET_DEV_M_24 137 -#define PACKET_DEV_E_24 1 +#define PACKET_DEV_M_24 79 +#define PACKET_DEV_E_24 0 /* * For our packet data @@ -299,37 +278,37 @@ ao_radio_idle(void) * * Symbol rate 38400 Baud: * - * DATARATE_M = 239914 - * DATARATE_E = 9 - * CHANBW = 79.4 (79.4) + * DATARATE_M = 1013008 + * DATARATE_E = 8 + * CHANBW = 104.16667 * * Symbol rate 9600 Baud: * - * DATARATE_M = 239914 - * DATARATE_E = 7 - * CHANBW = 19.9 (round to 19.8) + * DATARATE_M = 1013008 + * DATARATE_E = 6 + * CHANBW = 26.042 (round to 19.8) * * Symbol rate 2400 Baud: * - * DATARATE_M = 239914 - * DATARATE_E = 5 + * DATARATE_M = 1013008 + * DATARATE_E = 4 * CHANBW = 5.0 (round to 9.5) */ -#define PACKET_SYMBOL_RATE_M 239914 +#define PACKET_SYMBOL_RATE_M 1013008 -#define PACKET_SYMBOL_RATE_E_384 9 +#define PACKET_SYMBOL_RATE_E_384 8 /* 200 / 2 = 100 */ #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ - (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + (16 << CC1200_CHAN_BW_BB_CIC_DECFACT)) -#define PACKET_SYMBOL_RATE_E_96 7 +#define PACKET_SYMBOL_RATE_E_96 6 /* 200 / 10 = 20 */ #define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ - (21 << CC1200_CHAN_BW_BB_CIC_DECFACT)) + (16 << CC1200_CHAN_BW_BB_CIC_DECFACT)) -#define PACKET_SYMBOL_RATE_E_24 5 +#define PACKET_SYMBOL_RATE_E_24 4 /* 200 / 25 = 8 */ #define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ (44 << CC1200_CHAN_BW_BB_CIC_DECFACT)) @@ -337,17 +316,17 @@ ao_radio_idle(void) static const uint16_t packet_setup[] = { CC1200_SYMBOL_RATE1, ((PACKET_SYMBOL_RATE_M >> 8) & 0xff), CC1200_SYMBOL_RATE0, ((PACKET_SYMBOL_RATE_M >> 0) & 0xff), - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | - (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | - (0 << CC1200_PKT_CFG1_APPEND_STATUS)), - CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | - (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | - (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | - (0 << CC1200_PKT_CFG0_UART_MODE_EN) | - (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((1 << CC1200_PKT_CFG1_FEC_EN) | + (1 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) | + (1 << CC1200_PKT_CFG1_APPEND_STATUS)), CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), }; @@ -357,10 +336,14 @@ static const uint16_t packet_setup_384[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (PACKET_DEV_E_384 << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_384 << CC1200_SYMBOL_RATE2_DATARATE_E) | (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), CC1200_CHAN_BW, PACKET_CHAN_BW_384, - CC1200_PA_CFG0, 0x7b, + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; static const uint16_t packet_setup_96[] = { @@ -368,10 +351,14 @@ static const uint16_t packet_setup_96[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (PACKET_DEV_E_96 << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_96 << CC1200_SYMBOL_RATE2_DATARATE_E) | (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), CC1200_CHAN_BW, PACKET_CHAN_BW_96, - CC1200_PA_CFG0, 0x7d, + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_32 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; static const uint16_t packet_setup_24[] = { @@ -379,34 +366,27 @@ static const uint16_t packet_setup_24[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (PACKET_DEV_E_24 << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((PACKET_SYMBOL_RATE_E_24 << CC1200_SYMBOL_RATE2_DATARATE_E) | (((PACKET_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), CC1200_CHAN_BW, PACKET_CHAN_BW_24, - CC1200_PA_CFG0, 0x7e, -}; - -static const uint16_t packet_tx_setup[] = { - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG, -}; - -static const uint16_t packet_rx_setup[] = { - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1200_PKT_CFG2_PKT_FORMAT)), - AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_CLKEN_SOFT, + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_64 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; /* - * RDF deviation is 5kHz + * RDF deviation is 3kHz * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0 + * fdev = fosc >> 21 * dev_m dev_e == 0 * - * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989 + * 40e6 / (2 ** 21) * 157 = 2995Hz */ -#define RDF_DEV_E 3 -#define RDF_DEV_M 71 +#define RDF_DEV_E 0 +#define RDF_DEV_M 157 /* * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone) @@ -415,13 +395,13 @@ static const uint16_t packet_rx_setup[] = { * Rdata = -------------------------------------- * fosc * 2 ** 39 * - * DATARATE_M = 25166 - * DATARATE_E = 5 + * DATARATE_M = 669411 + * DATARATE_E = 4 * * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes */ -#define RDF_SYMBOL_RATE_E 5 -#define RDF_SYMBOL_RATE_M 25166 +#define RDF_SYMBOL_RATE_E 4 +#define RDF_SYMBOL_RATE_M 669411 #define RDF_PACKET_LEN 50 static const uint16_t rdf_setup[] = { @@ -429,36 +409,42 @@ static const uint16_t rdf_setup[] = { CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (RDF_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((RDF_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | (((RDF_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), - CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff), - CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff), - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | - (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | - (0 << CC1200_PKT_CFG1_APPEND_STATUS)), - CC1200_PKT_CFG0, ((0 << CC1200_PKT_CFG0_RESERVED7) | - (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | - (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | - (0 << CC1200_PKT_CFG0_UART_MODE_EN) | - (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), - CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | - (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), - CC1200_PA_CFG0, 0x7e, + CC1200_SYMBOL_RATE1, ((RDF_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((RDF_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((0 << CC1200_PKT_CFG1_FEC_EN) | + (0 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PREAMBLE_CFG1, + ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((0 << CC1200_MDMCFG2_ASK_SHAPE) | + (0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (12 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; /* * APRS deviation is 3kHz * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * fdev = fosc >> 22 * (256 + dev_m) << dev_e dev_e != 0 + * fdev = fosc >> 21 * dev_m dev_e == 0 * - * 32e6Hz / (2 ** 24) * (256 + 137) * (2 ** 2) = 2998Hz + * 40e6 / (2 ** 21) * 157 = 2995Hz */ -#define APRS_DEV_E 2 -#define APRS_DEV_M 137 +#define APRS_DEV_E 0 +#define APRS_DEV_M 157 /* * For our APRS beacon, set the symbol rate to 9.6kBaud (8x oversampling for 1200 baud data rate) @@ -467,33 +453,48 @@ static const uint16_t rdf_setup[] = { * Rdata = -------------------------------------- * fosc * 2 ** 39 * - * DATARATE_M = 239914 - * DATARATE_E = 7 + * DATARATE_M = 1013008 + * DATARATE_E = 6 * * Rdata = 9599.998593330383301 * */ -#define APRS_SYMBOL_RATE_E 7 -#define APRS_SYMBOL_RATE_M 239914 +#define APRS_SYMBOL_RATE_E 6 +#define APRS_SYMBOL_RATE_M 1013008 static const uint16_t aprs_setup[] = { CC1200_DEVIATION_M, APRS_DEV_M, CC1200_MODCFG_DEV_E, ((CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1200_MODCFG_DEV_E_MODEM_MODE) | (CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1200_MODCFG_DEV_E_MOD_FORMAT) | (APRS_DEV_E << CC1200_MODCFG_DEV_E_DEV_E)), - CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | + CC1200_SYMBOL_RATE2, ((APRS_SYMBOL_RATE_E << CC1200_SYMBOL_RATE2_DATARATE_E) | (((APRS_SYMBOL_RATE_M >> 16) & CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK) << CC1200_SYMBOL_RATE2_DATARATE_M_19_16)), - CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), - CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), - CC1200_PKT_CFG2, ((CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | - (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), - CC1200_PKT_CFG1, ((0 << CC1200_PKT_CFG1_WHITE_DATA) | - (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | - (0 << CC1200_PKT_CFG1_APPEND_STATUS)), - CC1200_PREAMBLE_CFG1, ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | - (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), - CC1200_PA_CFG0, 0x7d, + CC1200_SYMBOL_RATE1, ((APRS_SYMBOL_RATE_M >> 8) & 0xff), + CC1200_SYMBOL_RATE0, ((APRS_SYMBOL_RATE_M >> 0) & 0xff), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((0 << CC1200_PKT_CFG1_FEC_EN) | + (0 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_DISABLED << CC1200_PKT_CFG1_CRC_CFG) | + (0 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */ + ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_PREAMBLE_CFG1, + ((CC1200_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1200_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), }; /* @@ -521,14 +522,12 @@ static const uint16_t test_setup[] = { (CC1200_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1200_PREAMBLE_CFG1_PREAMBLE_WORD)), }; -#define AO_PKT_CFG0_INFINITE ((0 << CC1200_PKT_CFG0_RESERVED7) | \ - (CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ +#define AO_PKT_CFG0_INFINITE ((CC1200_PKT_CFG0_LENGTH_CONFIG_INFINITE << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) -#define AO_PKT_CFG0_FIXED ((0 << CC1200_PKT_CFG0_RESERVED7) | \ - (CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ +#define AO_PKT_CFG0_FIXED ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | \ (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | \ (0 << CC1200_PKT_CFG0_UART_MODE_EN) | \ (0 << CC1200_PKT_CFG0_UART_SWAP_EN)) @@ -536,10 +535,9 @@ static const uint16_t test_setup[] = { static uint16_t ao_radio_mode; #define AO_RADIO_MODE_BITS_PACKET 1 -#define AO_RADIO_MODE_BITS_PACKET_TX 2 #define AO_RADIO_MODE_BITS_TX_BUF 4 #define AO_RADIO_MODE_BITS_TX_FINISH 8 -#define AO_RADIO_MODE_BITS_PACKET_RX 16 +#define AO_RADIO_MODE_BITS_RX 16 #define AO_RADIO_MODE_BITS_RDF 32 #define AO_RADIO_MODE_BITS_APRS 64 #define AO_RADIO_MODE_BITS_TEST 128 @@ -547,14 +545,13 @@ static uint16_t ao_radio_mode; #define AO_RADIO_MODE_BITS_FIXED 512 #define AO_RADIO_MODE_NONE 0 -#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX) -#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) -#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) -#define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_PACKET_TX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_RX) +#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) static void _ao_radio_set_regs(const uint16_t *regs, int nreg) @@ -596,17 +593,14 @@ ao_radio_set_mode(uint16_t new_mode) } } - if (changes & AO_RADIO_MODE_BITS_PACKET_TX) - ao_radio_set_regs(packet_tx_setup); - if (changes & AO_RADIO_MODE_BITS_TX_BUF) ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR); if (changes & AO_RADIO_MODE_BITS_TX_FINISH) - ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); - if (changes & AO_RADIO_MODE_BITS_PACKET_RX) - ao_radio_set_regs(packet_rx_setup); + if (changes & AO_RADIO_MODE_BITS_RX) + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); if (changes & AO_RADIO_MODE_BITS_RDF) ao_radio_set_regs(rdf_setup); @@ -635,7 +629,7 @@ static uint8_t ao_radio_configured = 0; static void ao_radio_setup(void) { -// ao_radio_strobe(CC1200_SRES); + ao_radio_strobe(CC1200_SRES); ao_radio_set_regs(radio_setup); @@ -682,6 +676,56 @@ ao_radio_get(uint8_t len) #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) +static inline uint8_t +ao_radio_state(void) +{ + return (ao_radio_status() >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; +} + +#if CC1200_DEBUG +void +ao_radio_show_state(char *where) +{ + printf("%s: state %d len %d rxbytes %d\n", + where, ao_radio_state(), + ao_radio_reg_read(CC1200_PKT_LEN), + ao_radio_reg_read(CC1200_NUM_RXBYTES)); +} +#else +#define ao_radio_show_state(where) +#endif + +/* Wait for the radio to signal an interrupt + */ +static void +ao_radio_wait_isr(uint16_t timeout) +{ + uint8_t state; + + state = ao_radio_state(); + switch (state) { + case CC1200_STATUS_STATE_IDLE: + case CC1200_STATUS_STATE_RX_FIFO_ERROR: + case CC1200_STATUS_STATE_TX_FIFO_ERROR: +#if CC1200_LOW_LEVEL_DEBUG + printf("before wait, state %d\n", state); flush(); +#endif + ao_radio_abort = 1; + return; + } + + if (timeout) + ao_alarm(timeout); + + ao_arch_block_interrupts(); + while (!ao_radio_wake && !ao_radio_abort) + if (ao_sleep(&ao_radio_wake)) + ao_radio_abort = 1; + ao_arch_release_interrupts(); + if (timeout) + ao_clear_alarm(); +} + static void ao_rdf_start(uint8_t len) { @@ -690,20 +734,13 @@ ao_rdf_start(uint8_t len) ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - } static void -ao_rdf_run(void) +ao_radio_run(void) { ao_radio_start_tx(); - - ao_arch_block_interrupts(); - while (!ao_radio_wake && !ao_radio_abort && !ao_radio_mcu_wake) - ao_sleep(&ao_radio_wake); - ao_arch_release_interrupts(); - if (ao_radio_mcu_wake) - ao_radio_check_marc_status(); + ao_radio_wait_isr(0); if (!ao_radio_wake) ao_radio_idle(); ao_radio_put(); @@ -716,7 +753,7 @@ ao_radio_rdf(void) ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); - ao_rdf_run(); + ao_radio_run(); } void @@ -738,7 +775,7 @@ ao_radio_continuity(uint8_t c) ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); status = ao_radio_fifo_write_stop(status); (void) status; - ao_rdf_run(); + ao_radio_run(); } void @@ -794,29 +831,18 @@ ao_radio_test_cmd(void) } } -static void -ao_radio_wait_isr(uint16_t timeout) -{ - if (timeout) - ao_alarm(timeout); - ao_arch_block_interrupts(); - while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort) - if (ao_sleep(&ao_radio_wake)) - ao_radio_abort = 1; - ao_arch_release_interrupts(); - if (timeout) - ao_clear_alarm(); - if (ao_radio_mcu_wake) - ao_radio_check_marc_status(); -} - void ao_radio_send(const void *d, uint8_t size) { - (void) d; - (void) size; + ao_radio_get(size); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX); + + ao_radio_fifo_write(d, size); + + ao_radio_run(); } + #define AO_RADIO_LOTS 64 void @@ -837,6 +863,9 @@ ao_radio_send_aprs(ao_radio_fill_func fill) done = 1; cnt = -cnt; } +#if CC1200_APRS_TRACE + printf("APRS fill %d bytes done %d\n", cnt, done); +#endif total += cnt; /* At the last buffer, set the total length */ @@ -849,8 +878,11 @@ ao_radio_send_aprs(ao_radio_fill_func fill) /* Wait for some space in the fifo */ while (!ao_radio_abort && (fifo_space = ao_radio_tx_fifo_space()) == 0) { +#if CC1200_APRS_TRACE + printf("APRS space %d cnt %d\n", fifo_space, cnt); flush(); +#endif ao_radio_wake = 0; - ao_radio_wait_isr(0); + ao_radio_wait_isr(AO_MS_TO_TICKS(1000)); } if (ao_radio_abort) break; @@ -867,33 +899,130 @@ ao_radio_send_aprs(ao_radio_fill_func fill) } else ao_radio_set_mode(AO_RADIO_MODE_APRS_BUF); + ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + ao_radio_fifo_write(b, this_len); b += this_len; - +#if CC1200_APRS_TRACE + printf("APRS write fifo %d space now %d\n", this_len, ao_radio_tx_fifo_space()); +#endif if (!started) { - ao_radio_start_tx(); +#if CC1200_APRS_TRACE + printf("APRS start\n"); +#endif + ao_radio_strobe(CC1200_STX); +#if CC1200_APRS_TRACE + { int t; + for (t = 0; t < 20; t++) { + uint8_t status = ao_radio_status(); + uint8_t space = ao_radio_tx_fifo_space(); + printf ("status: %02x fifo %d\n", status, space); + if ((status >> 4) == 2) + break; + ao_delay(AO_MS_TO_TICKS(0)); + } + } +#endif started = 1; - } else - ao_exti_enable(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN); + } } if (ao_radio_abort) { ao_radio_idle(); break; } - /* Wait for the transmitter to go idle */ - ao_radio_wake = 0; - ao_radio_wait_isr(0); } + /* Wait for the transmitter to go idle */ + ao_radio_wake = 0; +#if CC1200_APRS_TRACE + printf("APRS wait idle\n"); flush(); +#endif + ao_radio_wait_isr(AO_MS_TO_TICKS(1000)); +#if CC1200_APRS_TRACE + printf("APRS abort %d\n", ao_radio_abort); +#endif ao_radio_put(); } +#if 0 +static uint8_t +ao_radio_marc_state(void) +{ + return ao_radio_reg_read(CC1200_MARCSTATE); +} + +static uint8_t +ao_radio_modem_status1(void) +{ + return ao_radio_reg_read(CC1200_MODEM_STATUS1); +} + +static uint8_t +ao_radio_modem_status0(void) +{ + return ao_radio_reg_read(CC1200_MODEM_STATUS0); +} + +struct ao_radio_state { + char where[4]; + uint8_t marc_state; + uint8_t marc_status1; + uint8_t marc_status0; + uint8_t modem_status1; + uint8_t modem_status0; +}; + +static void +ao_radio_fill_state(char *where, struct ao_radio_state *s) +{ + strcpy(s->where, where); + s->marc_state = ao_radio_marc_state(); + s->marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1); + s->marc_status0 = ao_radio_reg_read(CC1200_MARC_STATUS0); + s->modem_status1 = ao_radio_modem_status1(); + s->modem_status0 = ao_radio_modem_status0(); +} + +static void +ao_radio_dump_state(struct ao_radio_state *s) +{ + printf ("%s: marc %2x marc1 %2x marc0 %2x modem1 %2x modem0 %2x\n", + s->where, s->marc_state, s->marc_status1, s->marc_status0, s->modem_status1, s->modem_status0); +} +#endif + uint8_t ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) { - (void) d; - (void) size; - (void) timeout; - return 0; + ao_radio_abort = 0; + ao_radio_wake = 0; + ao_radio_get(size - 2); + ao_radio_idle(); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); + ao_radio_wake = 0; + ao_radio_start_rx(); + ao_radio_wait_isr(timeout); + if (ao_radio_wake) { + int8_t rssi; + uint8_t status; + + status = ao_radio_fifo_read(d, size); + (void) status; + rssi = ((int8_t *) d)[size - 2]; + ao_radio_rssi = rssi; + + /* Bound it to the representable range */ + if (rssi > -11) + rssi = -11; + + /* Write it back to the packet */ + ((int8_t *) d)[size-2] = AO_RADIO_FROM_RSSI(rssi); + } else { + ao_radio_idle(); + ao_radio_rssi = 0; + } + + ao_radio_put(); + return ao_radio_wake; } @@ -932,6 +1061,7 @@ static const struct ao_cc1200_reg ao_cc1200_reg[] = { { .addr = CC1200_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" }, { .addr = CC1200_IQIC, .name = "IQIC" }, { .addr = CC1200_CHAN_BW, .name = "CHAN_BW" }, + { .addr = CC1200_MDMCFG2, .name = "MDMCFG2" }, { .addr = CC1200_MDMCFG1, .name = "MDMCFG1" }, { .addr = CC1200_MDMCFG0, .name = "MDMCFG0" }, { .addr = CC1200_SYMBOL_RATE2, .name = "SYMBOL_RATE2" }, @@ -1064,8 +1194,8 @@ static const struct ao_cc1200_reg ao_cc1200_reg[] = { { .addr = CC1200_PARTNUMBER, .name = "PARTNUMBER" }, { .addr = CC1200_PARTVERSION, .name = "PARTVERSION" }, { .addr = CC1200_SERIAL_STATUS, .name = "SERIAL_STATUS" }, - { .addr = CC1200_RX_STATUS, .name = "RX_STATUS" }, - { .addr = CC1200_TX_STATUS, .name = "TX_STATUS" }, + { .addr = CC1200_MODEM_STATUS1, .name = "MODEM_STATUS1" }, + { .addr = CC1200_MODEM_STATUS0, .name = "MODEM_STATUS0" }, { .addr = CC1200_MARC_STATUS1, .name = "MARC_STATUS1" }, { .addr = CC1200_MARC_STATUS0, .name = "MARC_STATUS0" }, { .addr = CC1200_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" }, @@ -1091,11 +1221,17 @@ static const struct ao_cc1200_reg ao_cc1200_reg[] = { #define AO_NUM_CC1200_REG (sizeof ao_cc1200_reg / sizeof ao_cc1200_reg[0]) +static uint8_t +ao_radio_get_marc_status(void) +{ + return ao_radio_reg_read(CC1200_MARC_STATUS1); +} + static void ao_radio_show(void) { - uint8_t status = ao_radio_status(); + uint8_t status; unsigned int i; - ao_radio_get(0xff); + ao_mutex_get(&ao_radio_mutex); status = ao_radio_status(); printf ("Status: %02x\n", status); printf ("CHIP_RDY: %d\n", (status >> CC1200_STATUS_CHIP_RDY) & 1); @@ -1141,6 +1277,8 @@ ao_radio_test_recv(void) printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32])); for (b = 0; b < 32; b++) printf (" %02x", bytes[b]); + + printf (" RSSI %02x LQI %02x", bytes[32], bytes[33]); printf ("\n"); } } @@ -1151,12 +1289,15 @@ ao_radio_test_recv(void) static void ao_radio_aprs(void) { +#if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif ao_aprs_send(); } #endif #endif +#if CC1200_LOW_LEVEL_DEBUG static void ao_radio_strobe_test(void) { @@ -1204,6 +1345,7 @@ ao_radio_read_test(void) data = ao_radio_reg_read(addr); printf ("Read %04x = %02x\n", addr, data); } +#endif static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, @@ -1216,9 +1358,11 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_packet, "p\0Send a test packet" }, { ao_radio_test_recv, "q\0Recv a test packet" }, #endif - { ao_radio_strobe_test, "S \0Strobe radio" }, +#if CC1200_LOW_LEVEL_DEBUG + { ao_radio_strobe_test, "A \0Strobe radio" }, { ao_radio_write_test, "W \0Write radio reg" }, - { ao_radio_read_test, "R \0Read radio reg" }, + { ao_radio_read_test, "B \0Read radio reg" }, +#endif { 0, NULL } }; diff --git a/src/drivers/ao_cc1200.h b/src/drivers/ao_cc1200.h index 987f9bda..b04775fd 100644 --- a/src/drivers/ao_cc1200.h +++ b/src/drivers/ao_cc1200.h @@ -27,7 +27,7 @@ #define CC1200_IOCFG_GPIO_INV 6 #define CC1200_IOCFG_GPIO_CFG 0 #define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR 0 -#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1 +#define CC1200_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1 #define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR 2 #define CC1200_IOCFG_GPIO_CFG_TXFIFO_THR_PKT 3 #define CC1200_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4 @@ -101,7 +101,6 @@ #define CC1200_IOCFG_GPIO_CFG_EXT_OSC_EN 60 #define CC1200_IOCFG_GPIO_CFG_MASK 0x3f -#define CC1200_IOCFG3 0x00 #define CC1200_IOCFG2 0x01 #define CC1200_IOCFG1 0x02 #define CC1200_IOCFG0 0x03 @@ -141,21 +140,21 @@ #define CC1200_DEVIATION_M 0x0a #define CC1200_MODCFG_DEV_E 0x0b -#define CC1200_MODCFG_DEV_E_MODEM_MODE 6 +#define CC1200_MODCFG_DEV_E_MODEM_MODE 6 #define CC1200_MODCFG_DEV_E_MODEM_MODE_NORMAL 0 #define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_REPEAT 1 #define CC1200_MODCFG_DEV_E_MODEM_MODE_DSSS_PN 2 #define CC1200_MODCFG_DEV_E_MODEM_MODE_CARRIER_SENSE 3 #define CC1200_MODCFG_DEV_E_MODEM_MODE_MASK 3 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT 3 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5 -#define CC1200_MODCFG_DEV_E_MOD_FORMAT_MASK 7 -#define CC1200_MODCFG_DEV_E_DEV_E 0 -#define CC1200_MODCFG_DEV_E_DEV_E_MASK 7 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT 3 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5 +#define CC1200_MODCFG_DEV_E_MOD_FORMAT_MASK 7 +#define CC1200_MODCFG_DEV_E_DEV_E 0 +#define CC1200_MODCFG_DEV_E_DEV_E_MASK 7 #define CC1200_DCFILT_CFG 0x0c #define CC1200_PREAMBLE_CFG1 0x0d @@ -226,10 +225,10 @@ #define CC1200_MDMCFG0_VITERBI_EN 2 #define CC1200_SYMBOL_RATE2 0x13 -#define CC1200_SYMBOL_RATE2_DATARATE_E 4 -#define CC1200_SYMBOL_RATE2_DATARATE_E_MASK 0xf -#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16 0 -#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK 0xf +#define CC1200_SYMBOL_RATE2_DATARATE_E 4 +#define CC1200_SYMBOL_RATE2_DATARATE_E_MASK 0xf +#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16 0 +#define CC1200_SYMBOL_RATE2_DATARATE_M_19_16_MASK 0xf #define CC1200_SYMBOL_RATE1 0x14 #define CC1200_SYMBOL_RATE0 0x15 @@ -338,6 +337,8 @@ #define CC1200_WOR_EVENT0_LSB 0x24 #define CC1200_RXDCM_TIME 0x25 #define CC1200_PKT_CFG2 0x26 +#define CC1200_PKT_CFG2_BYTE_SWAP_EN 6 +#define CC1200_PKT_CFG2_FG_MODE_EN 5 #define CC1200_PKT_CFG2_CCA_MODE 2 #define CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR 0 #define CC1200_PKT_CFG2_CCA_MODE_RSSI_THRESHOLD 1 @@ -353,19 +354,20 @@ #define CC1200_PKT_CFG2_PKT_FORMAT_MASK 3 #define CC1200_PKT_CFG1 0x27 +#define CC1200_PKT_CFG1_FEC_EN 7 #define CC1200_PKT_CFG1_WHITE_DATA 6 -#define CC1200_PKT_CFG1_ADDR_CHECK_CFG 4 +#define CC1200_PKT_CFG1_PN9_SWAP_EN 5 +#define CC1200_PKT_CFG1_ADDR_CHECK_CFG 3 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE 0 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_CHECK 1 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_BROADCAST 2 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_00_FF_BROADCAST 3 #define CC1200_PKT_CFG1_ADDR_CHECK_CFG_MASK 3 -#define CC1200_PKT_CFG1_CRC_CFG 2 +#define CC1200_PKT_CFG1_CRC_CFG 1 #define CC1200_PKT_CFG1_CRC_CFG_DISABLED 0 #define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES 1 #define CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ZEROS 2 #define CC1200_PKT_CFG1_CRC_CFG_MASK 3 -#define CC1200_PKT_CFG1_BYTE_SWAP_EN 1 #define CC1200_PKT_CFG1_APPEND_STATUS 0 #define CC1200_PKT_CFG0 0x28 @@ -382,13 +384,29 @@ #define CC1200_PKT_CFG0_UART_SWAP_EN 0 #define CC1200_RFEND_CFG1 0x29 +#define CC1200_RFEND_CFG1_RXOFF_MODE 4 +#define CC1200_RFEND_CFG1_RXOFF_MODE_IDLE 0 +#define CC1200_RFEND_CFG1_RXOFF_MODE_FSTXON 1 +#define CC1200_RFEND_CFG1_RXOFF_MODE_TX 2 +#define CC1200_RFEND_CFG1_RXOFF_MODE_RX 3 +#define CC1200_RFEND_CFG1_RX_TIME 1 +#define CC1200_RFEND_CFG1_RX_TIME_INFINITE 7 +#define CC1200_RFEND_CFG1_RX_TIME_QUAL 0 #define CC1200_RFEND_CFG0 0x2a +#define CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN 6 +#define CC1200_RFEND_CFG0_TXOFF_MODE 4 +#define CC1200_RFEND_CFG0_TXOFF_MODE_IDLE 0 +#define CC1200_RFEND_CFG0_TXOFF_MODE_FSTXON 1 +#define CC1200_RFEND_CFG0_TXOFF_MODE_TX 2 +#define CC1200_RFEND_CFG0_TXOFF_MODE_RX 3 +#define CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN 3 +#define CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG 0 #define CC1200_PA_CFG1 0x2b #define CC1200_PA_CFG0 0x2c #define CC1200_ASK_CFG 0x2d #define CC1200_PKT_LEN 0x2e -#define CC1200_EXTENDED 0x2f +#define CC1200_EXTENDED 0x2f /* Command strobes */ #define CC1200_SRES 0x30 @@ -424,10 +442,25 @@ #define CC1200_ECG_CFG (CC1200_EXTENDED_BIT | 0x04) #define CC1200_MDMCFG2 (CC1200_EXTENDED_BIT | 0x05) -# define CC1200_MDMCFG2_ASK_SHAPE 6 -# define CC1200_MDMCFG2_SYMBOL_MAP_CFG 4 -# define CC1200_MDMCFG2_UPSAMPLER_P 1 -# define CC1200_MDMCFG2_CFM_DATA_EN 0 +#define CC1200_MDMCFG2_ASK_SHAPE 6 +#define CC1200_MDMCFG2_ASK_SHAPE_8 0 +#define CC1200_MDMCFG2_ASK_SHAPE_16 1 +#define CC1200_MDMCFG2_ASK_SHAPE_32 2 +#define CC1200_MDMCFG2_ASK_SHAPE_128 3 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG 4 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 0 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_1 1 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_2 2 +#define CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_3 3 +#define CC1200_MDMCFG2_UPSAMPLER_P 1 +#define CC1200_MDMCFG2_UPSAMPLER_P_1 0 +#define CC1200_MDMCFG2_UPSAMPLER_P_2 1 +#define CC1200_MDMCFG2_UPSAMPLER_P_4 2 +#define CC1200_MDMCFG2_UPSAMPLER_P_8 3 +#define CC1200_MDMCFG2_UPSAMPLER_P_16 4 +#define CC1200_MDMCFG2_UPSAMPLER_P_32 5 +#define CC1200_MDMCFG2_UPSAMPLER_P_64 6 +#define CC1200_MDMCFG2_CFM_DATA_EN 0 #define CC1200_EXT_CTRL (CC1200_EXTENDED_BIT | 0x06) #define CC1200_RCCAL_FINE (CC1200_EXTENDED_BIT | 0x07) @@ -527,23 +560,39 @@ #define CC1200_PARTNUMBER (CC1200_EXTENDED_BIT | 0x8f) #define CC1200_PARTVERSION (CC1200_EXTENDED_BIT | 0x90) #define CC1200_SERIAL_STATUS (CC1200_EXTENDED_BIT | 0x91) -#define CC1200_RX_STATUS (CC1200_EXTENDED_BIT | 0x92) -#define CC1200_TX_STATUS (CC1200_EXTENDED_BIT | 0x93) +#define CC1200_MODEM_STATUS1 (CC1200_EXTENDED_BIT | 0x92) +#define CC1200_MODEM_STATUS1_SYNC_FOUND 7 +#define CC1200_MODEM_STATUS1_RXFIFO_FULL 6 +#define CC1200_MODEM_STATUS1_RXFIFO_THR 5 +#define CC1200_MODEM_STATUS1_RXFIFO_EMPTY 4 +#define CC1200_MODEM_STATUS1_RXFIFO_OVERFLOW 3 +#define CC1200_MODEM_STATUS1_RXFIFO_UNDERFLOW 2 +#define CC1200_MODEM_STATUS1_PQT_REACHED 1 +#define CC1200_MODEM_STATUS1_PQT_VALID 0 + +#define CC1200_MODEM_STATUS0 (CC1200_EXTENDED_BIT | 0x93) +#define CC1200_MODEM_STATUS0_FEC_RX_OVERFLOW 6 +#define CC1200_MODEM_STATUS0_SYNC_SENT 4 +#define CC1200_MODEM_STATUS0_TXFIFO_FULL 3 +#define CC1200_MODEM_STATUS0_TXFIFO_THR 2 +#define CC1200_MODEM_STATUS0_TXFIFO_OVERFLOW 1 +#define CC1200_MODEM_STATUS0_TXFIFO_UNDERFLOW 0 + #define CC1200_MARC_STATUS1 (CC1200_EXTENDED_BIT | 0x94) -# define CC1200_MARC_STATUS1_NO_FAILURE 0 -# define CC1200_MARC_STATUS1_RX_TIMEOUT 1 -# define CC1200_MARC_STATUS1_RX_TERMINATION 2 -# define CC1200_MARC_STATUS1_EWOR_SYNC_LOST 3 -# define CC1200_MARC_STATUS1_MAXIMUM_LENGTH 4 -# define CC1200_MARC_STATUS1_ADDRESS 5 -# define CC1200_MARC_STATUS1_CRC 6 -# define CC1200_MARC_STATUS1_TX_FIFO_OVERFLOW 7 -# define CC1200_MARC_STATUS1_TX_FIFO_UNDERFLOW 8 -# define CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW 9 -# define CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW 10 -# define CC1200_MARC_STATUS1_TX_ON_CCA_FAILED 11 -# define CC1200_MARC_STATUS1_TX_FINISHED 0x40 -# define CC1200_MARC_STATUS1_RX_FINISHED 0x80 +#define CC1200_MARC_STATUS1_NO_FAILURE 0 +#define CC1200_MARC_STATUS1_RX_TIMEOUT 1 +#define CC1200_MARC_STATUS1_RX_TERMINATION 2 +#define CC1200_MARC_STATUS1_EWOR_SYNC_LOST 3 +#define CC1200_MARC_STATUS1_MAXIMUM_LENGTH 4 +#define CC1200_MARC_STATUS1_ADDRESS 5 +#define CC1200_MARC_STATUS1_CRC 6 +#define CC1200_MARC_STATUS1_TX_FIFO_OVERFLOW 7 +#define CC1200_MARC_STATUS1_TX_FIFO_UNDERFLOW 8 +#define CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW 9 +#define CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW 10 +#define CC1200_MARC_STATUS1_TX_ON_CCA_FAILED 11 +#define CC1200_MARC_STATUS1_TX_FINISHED 0x40 +#define CC1200_MARC_STATUS1_RX_FINISHED 0x80 #define CC1200_MARC_STATUS0 (CC1200_EXTENDED_BIT | 0x95) #define CC1200_PA_IFAMP_TEST (CC1200_EXTENDED_BIT | 0x96) #define CC1200_FSRF_TEST (CC1200_EXTENDED_BIT | 0x97) diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index 670e89ef..8d5c3b2a 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -7,34 +7,84 @@ * ***************************************************************/ +#ifndef AO_CC1200_AGC_GAIN_ADJUST +#define AO_CC1200_AGC_GAIN_ADJUST -81 +#endif CC1200_IOCFG2, 0x06, /* GPIO2 IO Pin Configuration */ - CC1200_SYNC1, 0x6e, /* Sync Word Configuration [15:8] */ - CC1200_SYNC0, 0x4e, /* Sync Word Configuration [7:0] */ - CC1200_SYNC_CFG1, 0xea, /* Sync Word Detection Configuration Reg. 1 */ + CC1200_SYNC3, 0xD3, /* Sync Word Configuration [23:16] */ + CC1200_SYNC2, 0x91, /* Sync Word Configuration [23:16] */ + CC1200_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */ + CC1200_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ + CC1200_SYNC_CFG1, /* Sync Word Detection Configuration Reg. 1 */ + ((CC1200_SYNC_CFG1_SYNC_MODE_16_BITS << CC1200_SYNC_CFG1_SYNC_MODE) | + (0xc << CC1200_SYNC_CFG1_SYNC_THR)), + CC1200_SYNC_CFG0, /* Sync Word Detection Configuration Reg. 0 */ + ((1 << CC1200_SYNC_CFG0_AUTO_CLEAR) | + (0 << CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION) | + (1 << CC1200_SYNC_CFG0_PQT_GATING_EN) | + (0 << CC1200_SYNC_CFG0_EXT_SYNC_DETECT) | + (CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK_DISABLED << CC1200_SYNC_CFG0_SYNC_STRICT_SYNC_CHECK)), CC1200_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ CC1200_DCFILT_CFG, 0x5d, /* Digital DC Removal Configuration */ - CC1200_PREAMBLE_CFG0, 0x8a, /* Preamble Detection Configuration Reg. 0 */ + CC1200_PREAMBLE_CFG0, /* Preamble Detection Configuration Reg. 0 */ + ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) | + (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_24 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) | + (2 << CC1200_PREAMBLE_CFG0_PQT)), CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */ CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */ CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */ CC1200_MDMCFG0, 0x05, /* General Modem Parameter Configuration Reg. 0 */ CC1200_SYMBOL_RATE2, 0x93, /* Symbol Rate Configuration Exponent and Mantissa [1.. */ - CC1200_AGC_REF, 0x37, /* AGC Reference Level Configuration */ + CC1200_AGC_REF, 0x27, /* AGC Reference Level Configuration */ CC1200_AGC_CS_THR, 0xec, /* Carrier Sense Threshold Configuration */ + CC1200_AGC_GAIN_ADJUST, /* RSSI adjustment */ + AO_CC1200_AGC_GAIN_ADJUST, CC1200_AGC_CFG1, 0x51, /* Automatic Gain Control Configuration Reg. 1 */ CC1200_AGC_CFG0, 0x87, /* Automatic Gain Control Configuration Reg. 0 */ - CC1200_FIFO_CFG, 0x00, /* FIFO Configuration */ - CC1200_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */ - CC1200_PKT_CFG2, 0x20, /* Packet Configuration Reg. 2 */ - CC1200_PKT_CFG1, 0xc3, /* Packet Configuration Reg. 1 */ - CC1200_PKT_CFG0, 0x20, /* Packet Configuration Reg. 0 */ + CC1200_FIFO_CFG, 0x40, /* FIFO Configuration */ + CC1200_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ + ((CC1200_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1200_SETTLING_CFG_FS_AUTOCAL) | + (CC1200_SETTLING_CFG_LOCK_TIME_75_30 << CC1200_SETTLING_CFG_LOCK_TIME) | + (CC1200_SETTLING_CFG_FSREG_TIME_60 << CC1200_SETTLING_CFG_FSREG_TIME)), + CC1200_FS_CFG, /* Frequency Synthesizer Configuration */ + ((1 << CC1200_FS_CFG_LOCK_EN) | + (CC1200_FS_CFG_FSD_BANDSELECT_410_480 << CC1200_FS_CFG_FSD_BANDSELECT)), + CC1200_PKT_CFG2, /* Packet Configuration Reg. 2 */ + ((0 << CC1200_PKT_CFG2_FG_MODE_EN) | + (CC1200_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1200_PKT_CFG2_CCA_MODE) | + (CC1200_PKT_CFG2_PKT_FORMAT_NORMAL << CC1200_PKT_CFG2_PKT_FORMAT)), + CC1200_PKT_CFG1, /* Packet Configuration Reg. 1 */ + ((1 << CC1200_PKT_CFG1_FEC_EN) | + (1 << CC1200_PKT_CFG1_WHITE_DATA) | + (0 << CC1200_PKT_CFG1_PN9_SWAP_EN) | + (CC1200_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1200_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1200_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES << CC1200_PKT_CFG1_CRC_CFG) | + (1 << CC1200_PKT_CFG1_APPEND_STATUS)), + CC1200_PKT_CFG0, /* Packet Configuration Reg. 0 */ + ((CC1200_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1200_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1200_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1200_PKT_CFG0_UART_MODE_EN) | + (0 << CC1200_PKT_CFG0_UART_SWAP_EN)), + CC1200_RFEND_CFG1, /* RFEND Configuration Reg. 1 */ + ((CC1200_RFEND_CFG1_RXOFF_MODE_IDLE << CC1200_RFEND_CFG1_RXOFF_MODE) | + (CC1200_RFEND_CFG1_RX_TIME_INFINITE << CC1200_RFEND_CFG1_RX_TIME) | + (0 << CC1200_RFEND_CFG1_RX_TIME_QUAL)), + CC1200_RFEND_CFG0, /* RFEND Configuration Reg. 0 */ + ((0 << CC1200_RFEND_CFG0_CAL_END_WAKE_UP_EN) | + (CC1200_RFEND_CFG0_TXOFF_MODE_IDLE << CC1200_RFEND_CFG0_TXOFF_MODE) | + (1 << CC1200_RFEND_CFG0_TERM_ON_BAD_PACKET_EN) | + (0 << CC1200_RFEND_CFG0_ANT_DIV_RX_TERM_CFG)), CC1200_PA_CFG1, 0x3f, /* Power Amplifier Configuration Reg. 1 */ CC1200_PA_CFG0, 0x53, /* Power Amplifier Configuration Reg. 0 */ CC1200_PKT_LEN, 0xff, /* Packet Length Configuration */ CC1200_IF_MIX_CFG, 0x1c, /* IF Mix Configuration */ CC1200_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */ - CC1200_MDMCFG2, 0x0c, /* General Modem Parameter Configuration Reg. 2 */ + CC1200_MDMCFG2, /* General Modem Parameter Configuration Reg. 2 */ + ((CC1200_MDMCFG2_ASK_SHAPE_8 << CC1200_MDMCFG2_ASK_SHAPE) | + (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | + (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) | + (0 << CC1200_MDMCFG2_CFM_DATA_EN)), CC1200_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ CC1200_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ CC1200_FREQ0, 0x33, /* Frequency Configuration [7:0] */ -- cgit v1.2.3 From cb83b5432e1320726ad496ded78cced7274618b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 Oct 2014 05:36:18 +0200 Subject: altos/teledongle-v1.9: Add remaining code to complete the project This turns the prototype board into a full teledongle Signed-off-by: Keith Packard --- src/teledongle-v1.9/Makefile | 16 ++++++++-------- src/teledongle-v1.9/ao_pins.h | 4 ++-- src/teledongle-v1.9/ao_teledongle.c | 8 ++++---- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/teledongle-v1.9/Makefile b/src/teledongle-v1.9/Makefile index a8999c27..d800d610 100644 --- a/src/teledongle-v1.9/Makefile +++ b/src/teledongle-v1.9/Makefile @@ -15,6 +15,8 @@ INC = \ ao_task.h \ ao_whiten.h \ stm32l.h \ + ao_cc1200.h \ + ao_cc1200_CC1200.h \ Makefile #PROFILE=ao_profile.c @@ -27,13 +29,6 @@ INC = \ #STACK_GUARD=ao_mpu_stm.c #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 -# ao_monitor.c \ -# ao_rssi.c \ -# ao_send_packet.c \ -# ao_packet_master.c \ -# ao_packet.c - - ALTOS_SRC = \ ao_boot_chain.c \ ao_interrupt.c \ @@ -53,7 +48,12 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_usb_stm.c \ ao_exti_stm.c \ - ao_eeprom_stm.c + ao_send_packet.c \ + ao_eeprom_stm.c \ + ao_monitor.c \ + ao_rssi.c \ + ao_packet_master.c \ + ao_packet.c PRODUCT=TeleDongle-v1.9 PRODUCT_DEF=-DTELEDONGLE diff --git a/src/teledongle-v1.9/ao_pins.h b/src/teledongle-v1.9/ao_pins.h index bbc42a5d..86dd0459 100644 --- a/src/teledongle-v1.9/ao_pins.h +++ b/src/teledongle-v1.9/ao_pins.h @@ -110,7 +110,7 @@ /* * Telemetry monitoring */ -#define HAS_MONITOR 0 +#define HAS_MONITOR 1 #define LEGACY_MONITOR 0 #define HAS_MONITOR_PUT 1 #define AO_MONITOR_LED AO_LED_GREEN @@ -121,7 +121,7 @@ /* gets pretty close to 434.550 */ -#define AO_RADIO_CAL_DEFAULT 0x6ca333 +#define AO_RADIO_CAL_DEFAULT 5695733 #define AO_FEC_DEBUG 0 #define AO_CC1200_SPI_CS_PORT (&stm_gpioc) diff --git a/src/teledongle-v1.9/ao_teledongle.c b/src/teledongle-v1.9/ao_teledongle.c index ac1e3c9f..68d6de60 100644 --- a/src/teledongle-v1.9/ao_teledongle.c +++ b/src/teledongle-v1.9/ao_teledongle.c @@ -42,10 +42,10 @@ main(void) ao_usb_init(); ao_radio_init(); -// ao_monitor_init(); -// ao_rssi_init(AO_LED_RED); -// ao_packet_master_init(); -// ao_send_packet_init(); + ao_monitor_init(); + ao_rssi_init(AO_LED_RED); + ao_packet_master_init(); + ao_send_packet_init(); ao_config_init(); -- cgit v1.2.3 From 9102183b40f0b32d4fb6d24502b79a6431184310 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 10:17:48 -0700 Subject: altos: Sort out ao_gps_print altitude fetching ao_gps_print is used by both teledongle/telebt and the host-based GPS test code. The first instance uses the old internal GPS structure, containing just a 16-bit altitude while the second uses an ao_telemetry structure, which contains 32 bits split into two members. Signed-off-by: Keith Packard --- src/kernel/ao_gps_print.c | 6 +++--- src/test/ao_gps_test_ublox.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_gps_print.c b/src/kernel/ao_gps_print.c index d26021da..6d9ee346 100644 --- a/src/kernel/ao_gps_print.c +++ b/src/kernel/ao_gps_print.c @@ -20,8 +20,8 @@ #endif #include "ao_telem.h" -#ifndef AO_TELEMETRY_LOCATION_ALTITUDE -#define AO_TELEMETRY_LOCATION_ALTITUDE(l) ((l)->altitude) +#ifndef AO_GPS_ORIG_ALTITUDE +#define AO_GPS_ORIG_ALTITUDE(l) ((l)->altitude) #endif void @@ -46,7 +46,7 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant AO_TELEM_GPS_ALTITUDE " %d ", (long) gps_data->latitude, (long) gps_data->longitude, - AO_TELEMETRY_LOCATION_ALTITUDE(gps_data)); + AO_GPS_ORIG_ALTITUDE(gps_data)); if (gps_data->flags & AO_GPS_DATE_VALID) printf(AO_TELEM_GPS_YEAR " %d " diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index 5ea205d6..83efbb4f 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -59,6 +59,7 @@ struct ao_telemetry_location { typedef int32_t gps_alt_t; #define AO_TELEMETRY_LOCATION_ALTITUDE(l) (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low)) +#define AO_GPS_ORIG_ALTITUDE(l) AO_TELEMETRY_LOCATION_ALTITUDE(l) #define AO_TELEMETRY_LOCATION_SET_ALTITUDE(l,a) (((l)->altitude_high = (a) >> 16), \ ((l)->altitude_low = (a))) -- cgit v1.2.3 From 51ef3fad6435c0b21945d48fbbaa5a4c092c4960 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 10:20:07 -0700 Subject: altos: Increase PQT value for cc1200 improving sensitivity The PQT value indicates how 'good' the preamble is; higher values allow a lower quality of preamble to pass the test, permitting more packets to be decoded. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200_CC1200.h | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index 8d5c3b2a..ab642f70 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -7,6 +7,22 @@ * ***************************************************************/ +/* + * Values affecting receive sensitivity: + * + * + * PQT - sets how good the preamble needs to look before + * we start looking for a sync word + * SYNC_THR - sets how good the sync needs to be before we + * start decoding a packet + */ + +/* Values depending on data rate + * + * DCFILT_BW_SETTLE + * DCFILT_BW + */ + #ifndef AO_CC1200_AGC_GAIN_ADJUST #define AO_CC1200_AGC_GAIN_ADJUST -81 #endif @@ -18,7 +34,7 @@ CC1200_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ CC1200_SYNC_CFG1, /* Sync Word Detection Configuration Reg. 1 */ ((CC1200_SYNC_CFG1_SYNC_MODE_16_BITS << CC1200_SYNC_CFG1_SYNC_MODE) | - (0xc << CC1200_SYNC_CFG1_SYNC_THR)), + (12 << CC1200_SYNC_CFG1_SYNC_THR)), CC1200_SYNC_CFG0, /* Sync Word Detection Configuration Reg. 0 */ ((1 << CC1200_SYNC_CFG0_AUTO_CLEAR) | (0 << CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION) | @@ -29,8 +45,8 @@ CC1200_DCFILT_CFG, 0x5d, /* Digital DC Removal Configuration */ CC1200_PREAMBLE_CFG0, /* Preamble Detection Configuration Reg. 0 */ ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) | - (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_24 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) | - (2 << CC1200_PREAMBLE_CFG0_PQT)), + (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) | + (12 << CC1200_PREAMBLE_CFG0_PQT)), CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */ CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */ CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */ -- cgit v1.2.3 From ae4be19f8ab0899a879a10aec28dc381f44dd2c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 10:21:30 -0700 Subject: altos: Build TeleDongle v1.9 by default Signed-off-by: Keith Packard --- src/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 20126de6..a5d7b0f3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,6 +35,7 @@ ARMM3DIRS=\ telegps-v1.0 telegps-v1.0/flash-loader \ telelco-v0.2 telelco-v0.2/flash-loader \ telescience-v0.2 telescience-v0.2/flash-loader \ + teledongle-v1.9 teledongle-v1.9/flash-loader \ teleballoon-v2.0 ARMM0DIRS=\ -- cgit v1.2.3 From 3f7263f57b1b697d92ed6c3d62956e5bdfc11f24 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 11:20:44 -0700 Subject: altos: Remove old AO_SEND_ALL_BARO bits This was used for testing the original TeleMini which couldn't log data at full speed. Signed-off-by: Keith Packard --- src/kernel/ao.h | 6 ------ src/kernel/ao_telemetry.c | 30 ------------------------------ 2 files changed, 36 deletions(-) (limited to 'src') diff --git a/src/kernel/ao.h b/src/kernel/ao.h index ad5bbf8e..244421f3 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -518,15 +518,9 @@ struct ao_telemetry_raw_recv { /* Set delay between telemetry reports (0 to disable) */ -#ifdef AO_SEND_ALL_BARO -#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(100) -#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) -#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(100) -#else #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) #define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) #define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) -#endif void ao_telemetry_reset_interval(void); diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 27306a34..5b56d025 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -269,30 +269,6 @@ ao_send_mini(void) #endif /* AO_SEND_MINI */ -#ifdef AO_SEND_ALL_BARO -static uint8_t ao_baro_sample; - -static void -ao_send_baro(void) -{ - uint8_t sample = ao_sample_data; - uint8_t samples = (sample - ao_baro_sample) & (AO_DATA_RING - 1); - - if (samples > 12) { - ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_DATA_RING - 1); - samples = 12; - } - telemetry.generic.tick = ao_data_ring[sample].tick; - telemetry.generic.type = AO_TELEMETRY_BARO; - telemetry.baro.samples = samples; - for (sample = 0; sample < samples; sample++) { - telemetry.baro.baro[sample] = ao_data_ring[ao_baro_sample].adc.pres; - ao_baro_sample = ao_data_ring_next(ao_baro_sample); - } - ao_radio_send(&telemetry, sizeof (telemetry)); -} -#endif - static __pdata int8_t ao_telemetry_config_max; static __pdata int8_t ao_telemetry_config_cur; @@ -422,10 +398,6 @@ ao_telemetry(void) if (!(ao_config.radio_enable & AO_RADIO_DISABLE_TELEMETRY)) #endif { -#ifdef AO_SEND_ALL_BARO - ao_send_baro(); -#endif - #if HAS_FLIGHT # ifdef AO_SEND_MEGA ao_send_mega_sensor(); @@ -453,7 +425,6 @@ ao_telemetry(void) ao_send_satellite(); #endif } -#ifndef AO_SEND_ALL_BARO #if HAS_RDF if (ao_rdf && #if HAS_APRS @@ -481,7 +452,6 @@ ao_telemetry(void) ao_aprs_send(); } #endif /* HAS_APRS */ -#endif /* !AO_SEND_ALL_BARO */ time += ao_telemetry_interval; delay = time - ao_time(); if (delay > 0) { -- cgit v1.2.3 From c831f1ffb378c20b7513d209d60cdd5dee9db85b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 17:44:48 -0700 Subject: altos: Perform cc1200 calibration less often. Tweak radio params This performs calibration after every 4 operations, or when the frequency changes. This reduces the time it takes to get to receive mode. This also makes the sync and preamble qualifiers more strict to reject bad packets. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 16 +++++++++------- src/drivers/ao_cc1200_CC1200.h | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 39d3d522..a3c1cbd4 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -219,18 +219,18 @@ ao_radio_idle(void) { for (;;) { uint8_t state = (ao_radio_strobe(CC1200_SIDLE) >> CC1200_STATUS_STATE) & CC1200_STATUS_STATE_MASK; - if (state == CC1200_STATUS_STATE_IDLE) { - ao_radio_strobe(CC1200_SFTX); - ao_radio_strobe(CC1200_SFRX); + if (state == CC1200_STATUS_STATE_IDLE) break; - } if (state == CC1200_STATUS_STATE_TX_FIFO_ERROR) ao_radio_strobe(CC1200_SFTX); if (state == CC1200_STATUS_STATE_RX_FIFO_ERROR) ao_radio_strobe(CC1200_SFRX); } - /* Flush any pending TX bytes */ + /* Flush any pending data in the fifos */ ao_radio_strobe(CC1200_SFTX); + ao_radio_strobe(CC1200_SFRX); + /* Make sure the RF calibration is current */ + ao_radio_strobe(CC1200_SCAL); } /* @@ -635,6 +635,8 @@ ao_radio_setup(void) ao_radio_mode = 0; + ao_radio_idle(); + ao_config_get(); ao_radio_configured = 1; @@ -666,6 +668,7 @@ ao_radio_get(uint8_t len) ao_radio_reg_write(CC1200_FREQ1, ao_config.radio_setting >> 8); ao_radio_reg_write(CC1200_FREQ0, ao_config.radio_setting); last_radio_setting = ao_config.radio_setting; + ao_radio_strobe(CC1200_SCAL); } if (ao_config.radio_rate != last_radio_rate) { ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET; @@ -994,9 +997,8 @@ uint8_t ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) { ao_radio_abort = 0; - ao_radio_wake = 0; + ao_radio_get(size - 2); - ao_radio_idle(); ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); ao_radio_wake = 0; ao_radio_start_rx(); diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index ab642f70..c078c09d 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -34,7 +34,7 @@ CC1200_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ CC1200_SYNC_CFG1, /* Sync Word Detection Configuration Reg. 1 */ ((CC1200_SYNC_CFG1_SYNC_MODE_16_BITS << CC1200_SYNC_CFG1_SYNC_MODE) | - (12 << CC1200_SYNC_CFG1_SYNC_THR)), + (11 << CC1200_SYNC_CFG1_SYNC_THR)), CC1200_SYNC_CFG0, /* Sync Word Detection Configuration Reg. 0 */ ((1 << CC1200_SYNC_CFG0_AUTO_CLEAR) | (0 << CC1200_SYNC_CFG0_RX_CONFIG_LIMITATION) | @@ -46,7 +46,7 @@ CC1200_PREAMBLE_CFG0, /* Preamble Detection Configuration Reg. 0 */ ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) | (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) | - (12 << CC1200_PREAMBLE_CFG0_PQT)), + (6 << CC1200_PREAMBLE_CFG0_PQT)), CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */ CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */ CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */ @@ -60,7 +60,7 @@ CC1200_AGC_CFG0, 0x87, /* Automatic Gain Control Configuration Reg. 0 */ CC1200_FIFO_CFG, 0x40, /* FIFO Configuration */ CC1200_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ - ((CC1200_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1200_SETTLING_CFG_FS_AUTOCAL) | + ((CC1200_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME << CC1200_SETTLING_CFG_FS_AUTOCAL) | (CC1200_SETTLING_CFG_LOCK_TIME_75_30 << CC1200_SETTLING_CFG_LOCK_TIME) | (CC1200_SETTLING_CFG_FSREG_TIME_60 << CC1200_SETTLING_CFG_FSREG_TIME)), CC1200_FS_CFG, /* Frequency Synthesizer Configuration */ -- cgit v1.2.3 From 4d51570ed8776461d084726149923c5be43d622e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 19:56:25 -0700 Subject: altos: Fix up telemetry delay computations With RDF, APRS and telemetry all being sent at varying rates, computing when to send the next radio data is not as simple as sending telemetry and then figuring out whether to send RDF and/or APRS. Fix this by computing times for the next telemetry/rdf/aprs packet, and only sending each when that time has passed. Compute the delay until the next radio activity as the minimum time to any transmission. This also adds code to the config bits to reset the radio times whenever something changes that might affect which radio data to send next. Signed-off-by: Keith Packard --- src/kernel/ao_config.c | 9 ++- src/kernel/ao_telemetry.c | 143 +++++++++++++++++++++++++++++----------------- src/kernel/ao_telemetry.h | 6 ++ 3 files changed, 104 insertions(+), 54 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 6b8a1813..8dab7c42 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -557,10 +557,10 @@ ao_config_radio_rate_set(void) __reentrant } _ao_config_edit_start(); ao_config.radio_rate = ao_cmd_lex_i; + _ao_config_edit_finish(); #if HAS_TELEMETRY ao_telemetry_reset_interval(); #endif - _ao_config_edit_finish(); #if HAS_RADIO_RECV ao_radio_recv_abort(); #endif @@ -684,6 +684,9 @@ ao_config_radio_enable_set(void) __reentrant _ao_config_edit_start(); ao_config.radio_enable = ao_cmd_lex_i; _ao_config_edit_finish(); +#if HAS_TELEMETRY && HAS_RADIO_RATE + ao_telemetry_reset_interval(); +#endif } #endif /* HAS_RADIO */ @@ -735,6 +738,7 @@ ao_config_aprs_set(void) _ao_config_edit_start(); ao_config.aprs_interval = ao_cmd_lex_i; _ao_config_edit_finish(); + ao_telemetry_reset_interval(); } #endif /* HAS_APRS */ @@ -825,6 +829,9 @@ ao_config_tracker_set(void) ao_config.tracker_motion = m; ao_config.tracker_interval = i; _ao_config_edit_finish(); +#if HAS_TELEMETRY + ao_telemetry_reset_interval(); +#endif } #endif /* HAS_TRACKER */ diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 5b56d025..868b3260 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -19,19 +19,32 @@ #include "ao_log.h" #include "ao_product.h" -#ifndef HAS_RDF -#define HAS_RDF 1 -#endif - static __pdata uint16_t ao_telemetry_interval; #if HAS_RADIO_RATE static __xdata uint16_t ao_telemetry_desired_interval; #endif +/* TeleMetrum v1.0 just doesn't have enough space to + * manage the more complicated telemetry scheduling, so + * it loses the ability to disable telem/rdf separately + */ + +#if defined(TELEMETRUM_V_1_0) +#define SIMPLIFY +#endif + +#ifdef SIMPLIFY +#define ao_telemetry_time time +#define RDF_SPACE __pdata +#else +#define RDF_SPACE __xdata +static __pdata uint16_t ao_telemetry_time; +#endif + #if HAS_RDF -static __pdata uint8_t ao_rdf = 0; -static __pdata uint16_t ao_rdf_time; +static RDF_SPACE uint8_t ao_rdf = 0; +static RDF_SPACE uint16_t ao_rdf_time; #endif #if HAS_APRS @@ -308,6 +321,7 @@ ao_send_configuration(void) #if HAS_GPS +static __pdata int8_t ao_telemetry_gps_max; static __pdata int8_t ao_telemetry_loc_cur; static __pdata int8_t ao_telemetry_sat_cur; @@ -324,7 +338,7 @@ ao_send_location(void) telemetry.location.tick = ao_gps_tick; ao_mutex_put(&ao_gps_mutex); ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_loc_cur = ao_telemetry_config_max; + ao_telemetry_loc_cur = ao_telemetry_gps_max; } } @@ -341,7 +355,7 @@ ao_send_satellite(void) AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); ao_mutex_put(&ao_gps_mutex); ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_sat_cur = ao_telemetry_config_max; + ao_telemetry_sat_cur = ao_telemetry_gps_max; } } #endif @@ -387,6 +401,7 @@ ao_telemetry(void) while (ao_telemetry_interval == 0) ao_sleep(&telemetry); time = ao_time(); + ao_telemetry_time = time; #if HAS_RDF ao_rdf_time = time; #endif @@ -394,73 +409,85 @@ ao_telemetry(void) ao_aprs_time = time; #endif while (ao_telemetry_interval) { -#if HAS_APRS + time = ao_time() + AO_SEC_TO_TICKS(100); +#ifndef SIMPLIFY if (!(ao_config.radio_enable & AO_RADIO_DISABLE_TELEMETRY)) #endif { -#if HAS_FLIGHT +#ifndef SIMPLIFY + if ( (int16_t) (ao_time() - ao_telemetry_time) >= 0) +#endif + { + ao_telemetry_time = ao_time() + ao_telemetry_interval; # ifdef AO_SEND_MEGA - ao_send_mega_sensor(); - ao_send_mega_data(); + ao_send_mega_sensor(); + ao_send_mega_data(); # endif # ifdef AO_SEND_METRUM - ao_send_metrum_sensor(); - ao_send_metrum_data(); + ao_send_metrum_sensor(); + ao_send_metrum_data(); # endif # ifdef AO_SEND_MINI - ao_send_mini(); + ao_send_mini(); # endif # ifdef AO_TELEMETRY_SENSOR - ao_send_sensor(); + ao_send_sensor(); # endif -#endif /* HAS_FLIGHT */ - #if HAS_COMPANION - if (ao_companion_running) - ao_send_companion(); + if (ao_companion_running) + ao_send_companion(); #endif - ao_send_configuration(); #if HAS_GPS - ao_send_location(); - ao_send_satellite(); + ao_send_location(); + ao_send_satellite(); +#endif + ao_send_configuration(); + } +#ifndef SIMPLIFY + time = ao_telemetry_time; #endif } #if HAS_RDF - if (ao_rdf && -#if HAS_APRS - !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF) && -#endif /* HAS_APRS */ - (int16_t) (ao_time() - ao_rdf_time) >= 0) + if (ao_rdf +#ifndef SIMPLIFY + && !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF) +#endif + ) { + if ((int16_t) (ao_time() - ao_rdf_time) >= 0) { #if HAS_IGNITE_REPORT - uint8_t c; -#endif /* HAS_IGNITE_REPORT */ - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + uint8_t c; +#endif + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; #if HAS_IGNITE_REPORT - if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter())) - ao_radio_continuity(c); - else -#endif /* HAS_IGNITE_REPORT*/ - ao_radio_rdf(); + if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter())) + ao_radio_continuity(c); + else +#endif + ao_radio_rdf(); + } +#ifndef SIMPLIFY + if ((int16_t) (time - ao_rdf_time) > 0) + time = ao_rdf_time; +#endif } #endif /* HAS_RDF */ #if HAS_APRS - if (ao_config.aprs_interval != 0 && - (int16_t) (ao_time() - ao_aprs_time) >= 0) - { - ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval); - ao_aprs_send(); + if (ao_config.aprs_interval != 0) { + if ((int16_t) (ao_time() - ao_aprs_time) >= 0) { + ao_aprs_time = ao_time() + AO_SEC_TO_TICKS(ao_config.aprs_interval); + ao_aprs_send(); + } + if ((int16_t) (time - ao_aprs_time) > 0) + time = ao_aprs_time; } #endif /* HAS_APRS */ - time += ao_telemetry_interval; delay = time - ao_time(); if (delay > 0) { ao_alarm(delay); ao_sleep(&telemetry); ao_clear_alarm(); } - else - time = ao_time(); } } } @@ -517,21 +544,31 @@ ao_telemetry_set_interval(uint16_t interval) ao_telemetry_companion_cur = cur; #endif - ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval; -#if HAS_COMPANION - if (ao_telemetry_config_max > cur) - cur++; - ao_telemetry_config_cur = cur; -#endif - #if HAS_GPS - if (ao_telemetry_config_max > cur) + ao_telemetry_gps_max = AO_SEC_TO_TICKS(1) / interval; + if (ao_telemetry_gps_max > cur) cur++; ao_telemetry_loc_cur = cur; - if (ao_telemetry_config_max > cur) + if (ao_telemetry_gps_max > cur) cur++; ao_telemetry_sat_cur = cur; #endif + + ao_telemetry_config_max = AO_SEC_TO_TICKS(5) / interval; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_config_cur = cur; + +#ifndef SIMPLIFY + ao_telemetry_time = +#if HAS_RDF + ao_rdf_time = +#endif +#if HAS_APRS + ao_aprs_time = +#endif + ao_time(); +#endif ao_wakeup(&telemetry); } diff --git a/src/kernel/ao_telemetry.h b/src/kernel/ao_telemetry.h index 340c388e..711e0d36 100644 --- a/src/kernel/ao_telemetry.h +++ b/src/kernel/ao_telemetry.h @@ -120,6 +120,12 @@ struct ao_telemetry_location { #define HAS_WIDE_GPS 1 #endif +#ifdef HAS_TELEMETRY +#ifndef HAS_RDF +#define HAS_RDF 1 +#endif +#endif + #if HAS_WIDE_GPS typedef int32_t gps_alt_t; #define AO_TELEMETRY_LOCATION_ALTITUDE(l) (((gps_alt_t) (l)->altitude_high << 16) | ((l)->altitude_low)) -- cgit v1.2.3 From ef00182c79bd7a56fbc5d782cb8f4aa0079bb86f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 25 Oct 2014 21:14:25 -0700 Subject: altos: Increase CC1200 SPI data rate to 8MHz This got set to 125kHz to make debugging with a logic analyzer easier and never changed back to a reasonable speed. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index a3c1cbd4..fdaa6754 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -37,7 +37,7 @@ extern const uint32_t ao_radio_cal; #define FOSC 40000000 -#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_125kHz) +#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_8MHz) #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) -- cgit v1.2.3 From b67556949aa080fc5e70771e972de880e44eca12 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 Nov 2014 22:11:44 -0800 Subject: altos: Rename microwater to microsplash Signed-off-by: Keith Packard --- src/microsplash/.gitignore | 2 + src/microsplash/Makefile | 121 +++++++++++++++++++++++++++++++++++++++++++++ src/microsplash/ao_pins.h | 70 ++++++++++++++++++++++++++ src/microwater/.gitignore | 2 - src/microwater/Makefile | 121 --------------------------------------------- src/microwater/ao_pins.h | 70 -------------------------- 6 files changed, 193 insertions(+), 193 deletions(-) create mode 100644 src/microsplash/.gitignore create mode 100644 src/microsplash/Makefile create mode 100644 src/microsplash/ao_pins.h delete mode 100644 src/microwater/.gitignore delete mode 100644 src/microwater/Makefile delete mode 100644 src/microwater/ao_pins.h (limited to 'src') diff --git a/src/microsplash/.gitignore b/src/microsplash/.gitignore new file mode 100644 index 00000000..0573d989 --- /dev/null +++ b/src/microsplash/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +microwater-* diff --git a/src/microsplash/Makefile b/src/microsplash/Makefile new file mode 100644 index 00000000..10cb825b --- /dev/null +++ b/src/microsplash/Makefile @@ -0,0 +1,121 @@ +# +# Tiny AltOS build +# +# +vpath % ../attiny:../drivers:../kernel:../product:.. +vpath ao-make-product.5c ../util +vpath make-altitude-pa ../util + +include ../avr/Makefile.defs + +PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries +PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex + +MCU=attiny85 +DUDECPUTYPE=t85 +#PROGRAMMER=stk500v2 -P usb +LOADSLOW=-i 32 -B 32 +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: + +#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x + +ALTOS_SRC = \ + ao_micropeak.c \ + ao_spi_attiny.c \ + ao_led.c \ + ao_clock.c \ + ao_ms5607.c \ + ao_exti.c \ + ao_convert_pa.c \ + ao_report_micro.c \ + ao_notask.c \ + ao_eeprom_tiny.c \ + ao_panic.c \ + ao_log_micro.c \ + ao_async.c \ + ao_microflight.c \ + ao_microkalman.c + +INC=\ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_exti.h \ + ao_ms5607.h \ + ao_log_micro.h \ + ao_micropeak.h \ + altitude-pa.h + +IDPRODUCT=0 +PRODUCT=MicroSplash-v0.1 +PRODUCT_DEF=-DMICROPEAK +CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY + +NICKLE=nickle + +PROG=microsplash-v1.0 + +SRC=$(ALTOS_SRC) +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) $(PROG).hex + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +load-slow: $(PROG).hex + $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.o: ao_product.c ao_product.h + +%.o : %.c $(INC) + $(call quiet,CC) -c $(CFLAGS) $< + +distclean: clean + +clean: + rm -f *.o $(PROG) $(PROG).hex + rm -f ao_product.h + + +publish: $(PROG).hex + cp -a $(PROG).hex $(PUBLISH_FILE) + +load-product: + $(LOADCMD) $(LOADARG)$(PUBLISH_FILE) + +load-product-slow: + $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE) + +../altitude-pa.h: make-altitude-pa + nickle $< > $@ + +install: + +uninstall: + +$(OBJ): ao_product.h $(INC) diff --git a/src/microsplash/ao_pins.h b/src/microsplash/ao_pins.h new file mode 100644 index 00000000..37885ec2 --- /dev/null +++ b/src/microsplash/ao_pins.h @@ -0,0 +1,70 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ +#include + +#define AO_LED_ORANGE (1<<4) +#define AO_LED_SERIAL 4 +#define AO_LED_PANIC AO_LED_ORANGE +#define AO_LED_REPORT AO_LED_ORANGE +#define LEDS_AVAILABLE (AO_LED_ORANGE) +#define USE_SERIAL_1_STDIN 0 +#define HAS_USB 0 +#define PACKET_HAS_SLAVE 0 +#define HAS_SERIAL_1 0 +#define HAS_TASK 0 +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define HAS_EEPROM 0 +#define HAS_BEEP 0 +#define AVR_CLOCK 250000UL + +/* SPI */ +#define SPI_PORT PORTB +#define SPI_PIN PINB +#define SPI_DIR DDRB +#define AO_MS5607_CS_PORT PORTB +#define AO_MS5607_CS_PIN 3 + +/* MS5607 */ +#define AO_MS5607_SPI_INDEX 0 +#define AO_MS5607_MISO_PORT PORTB +#define AO_MS5607_MISO_PIN 0 +#define AO_MS5607_BARO_OVERSAMPLE 4096 +#define AO_MS5607_TEMP_OVERSAMPLE 1024 + +/* I2C */ +#define I2C_PORT PORTB +#define I2C_PIN PINB +#define I2C_DIR DDRB +#define I2C_PIN_SCL PINB2 +#define I2C_PIN_SDA PINB0 + +#define AO_CONST_ATTRIB PROGMEM +typedef int32_t alt_t; +#define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o])) + +#define AO_ALT_VALUE(x) ((x) * (alt_t) 10) + +/* Pressure change (in Pa) to detect boost */ +#ifndef BOOST_DETECT +#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */ +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/microwater/.gitignore b/src/microwater/.gitignore deleted file mode 100644 index 0573d989..00000000 --- a/src/microwater/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ao_product.h -microwater-* diff --git a/src/microwater/Makefile b/src/microwater/Makefile deleted file mode 100644 index a49cda4b..00000000 --- a/src/microwater/Makefile +++ /dev/null @@ -1,121 +0,0 @@ -# -# Tiny AltOS build -# -# -vpath % ../attiny:../drivers:../kernel:../product:.. -vpath ao-make-product.5c ../util -vpath make-altitude-pa ../util - -include ../avr/Makefile.defs - -PUBLISH_DIR=$(HOME)/altusmetrumllc/Binaries -PUBLISH_FILE=$(PUBLISH_DIR)/$(PROG)-$(VERSION).hex - -MCU=attiny85 -DUDECPUTYPE=t85 -#PROGRAMMER=stk500v2 -P usb -LOADSLOW=-i 32 -B 32 -LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: - -#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x - -ALTOS_SRC = \ - ao_micropeak.c \ - ao_spi_attiny.c \ - ao_led.c \ - ao_clock.c \ - ao_ms5607.c \ - ao_exti.c \ - ao_convert_pa.c \ - ao_report_micro.c \ - ao_notask.c \ - ao_eeprom_tiny.c \ - ao_panic.c \ - ao_log_micro.c \ - ao_async.c \ - ao_microflight.c \ - ao_microkalman.c - -INC=\ - ao.h \ - ao_pins.h \ - ao_arch.h \ - ao_arch_funcs.h \ - ao_exti.h \ - ao_ms5607.h \ - ao_log_micro.h \ - ao_micropeak.h \ - altitude-pa.h - -IDPRODUCT=0 -PRODUCT=MicroWater-v0.1 -PRODUCT_DEF=-DMICROPEAK -CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../kernel -I.. -I../drivers -I../product -CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY - -NICKLE=nickle - -PROG=microwater-v0.1 - -SRC=$(ALTOS_SRC) -OBJ=$(SRC:.c=.o) - -V=0 -# The user has explicitly enabled quiet compilation. -ifeq ($(V),0) -quiet = @printf " $1 $2 $@\n"; $($1) -endif -# Otherwise, print the full command line. -quiet ?= $($1) - -all: $(PROG) $(PROG).hex - -CHECK=sh ../util/check-avr-mem - -$(PROG): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) - $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) - -$(PROG).hex: $(PROG) - avr-size $(PROG) - $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ - - -load: $(PROG).hex - $(LOADCMD) $(LOADARG)$(PROG).hex - -load-slow: $(PROG).hex - $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -ao_product.o: ao_product.c ao_product.h - -%.o : %.c $(INC) - $(call quiet,CC) -c $(CFLAGS) $< - -distclean: clean - -clean: - rm -f *.o $(PROG) $(PROG).hex - rm -f ao_product.h - - -publish: $(PROG).hex - cp -a $(PROG).hex $(PUBLISH_FILE) - -load-product: - $(LOADCMD) $(LOADARG)$(PUBLISH_FILE) - -load-product-slow: - $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PUBLISH_FILE) - -../altitude-pa.h: make-altitude-pa - nickle $< > $@ - -install: - -uninstall: - -$(OBJ): ao_product.h $(INC) diff --git a/src/microwater/ao_pins.h b/src/microwater/ao_pins.h deleted file mode 100644 index 37885ec2..00000000 --- a/src/microwater/ao_pins.h +++ /dev/null @@ -1,70 +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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ -#include - -#define AO_LED_ORANGE (1<<4) -#define AO_LED_SERIAL 4 -#define AO_LED_PANIC AO_LED_ORANGE -#define AO_LED_REPORT AO_LED_ORANGE -#define LEDS_AVAILABLE (AO_LED_ORANGE) -#define USE_SERIAL_1_STDIN 0 -#define HAS_USB 0 -#define PACKET_HAS_SLAVE 0 -#define HAS_SERIAL_1 0 -#define HAS_TASK 0 -#define HAS_MS5607 1 -#define HAS_MS5611 0 -#define HAS_EEPROM 0 -#define HAS_BEEP 0 -#define AVR_CLOCK 250000UL - -/* SPI */ -#define SPI_PORT PORTB -#define SPI_PIN PINB -#define SPI_DIR DDRB -#define AO_MS5607_CS_PORT PORTB -#define AO_MS5607_CS_PIN 3 - -/* MS5607 */ -#define AO_MS5607_SPI_INDEX 0 -#define AO_MS5607_MISO_PORT PORTB -#define AO_MS5607_MISO_PIN 0 -#define AO_MS5607_BARO_OVERSAMPLE 4096 -#define AO_MS5607_TEMP_OVERSAMPLE 1024 - -/* I2C */ -#define I2C_PORT PORTB -#define I2C_PIN PINB -#define I2C_DIR DDRB -#define I2C_PIN_SCL PINB2 -#define I2C_PIN_SDA PINB0 - -#define AO_CONST_ATTRIB PROGMEM -typedef int32_t alt_t; -#define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o])) - -#define AO_ALT_VALUE(x) ((x) * (alt_t) 10) - -/* Pressure change (in Pa) to detect boost */ -#ifndef BOOST_DETECT -#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */ -#endif - -#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From f2060d6ca222a04608e598baf59757f12ea2ec70 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 13:27:29 -0800 Subject: Move teledongle 1.9 to 1.8; there's a new 1.9 1.9 is now the lpc11u14-based form-factor prototype board. Signed-off-by: Keith Packard --- src/teledongle-v1.8/.gitignore | 2 + src/teledongle-v1.8/Makefile | 89 ++++++++++++++++++++++ src/teledongle-v1.8/ao_pins.h | 146 ++++++++++++++++++++++++++++++++++++ src/teledongle-v1.8/ao_teledongle.c | 54 +++++++++++++ 4 files changed, 291 insertions(+) create mode 100644 src/teledongle-v1.8/.gitignore create mode 100644 src/teledongle-v1.8/Makefile create mode 100644 src/teledongle-v1.8/ao_pins.h create mode 100644 src/teledongle-v1.8/ao_teledongle.c (limited to 'src') diff --git a/src/teledongle-v1.8/.gitignore b/src/teledongle-v1.8/.gitignore new file mode 100644 index 00000000..9a30cbb6 --- /dev/null +++ b/src/teledongle-v1.8/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +teledongle-*.elf diff --git a/src/teledongle-v1.8/Makefile b/src/teledongle-v1.8/Makefile new file mode 100644 index 00000000..dc5e246c --- /dev/null +++ b/src/teledongle-v1.8/Makefile @@ -0,0 +1,89 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + ao_whiten.h \ + stm32l.h \ + ao_cc1200.h \ + ao_cc1200_CC1200.h \ + Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +# ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cc1200.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_send_packet.c \ + ao_eeprom_stm.c \ + ao_monitor.c \ + ao_rssi.c \ + ao_packet_master.c \ + ao_packet.c + +PRODUCT=TeleDongle-v1.8 +PRODUCT_DEF=-DTELEDONGLE +IDPRODUCT=0x000c + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=teledongle-v1.8 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_teledongle.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/teledongle-v1.8/ao_pins.h b/src/teledongle-v1.8/ao_pins.h new file mode 100644 index 00000000..86dd0459 --- /dev/null +++ b/src/teledongle-v1.8/ao_pins.h @@ -0,0 +1,146 @@ +/* + * 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. + */ + +/* Using TeleMetrum v1.9 board */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE 1 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1 0 +#define USE_SERIAL_1_STDIN 0 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 0 + +#define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 0 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 0 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 0 +#define SERIAL_3_PD8_PD9 0 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 1 +#define USE_STORAGE_CONFIG 0 +#define USE_EEPROM_CONFIG 1 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 0 +#define HAS_RSSI 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 /* Barometer */ +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 /* Accelerometer */ + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 /* Radio */ +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define SPI_2_PORT (&stm_gpiob) +#define SPI_2_SCK_PIN 13 +#define SPI_2_MISO_PIN 14 +#define SPI_2_MOSI_PIN 15 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 1 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT_0 (&stm_gpioc) +#define LED_PORT_0_MASK (0xffff) +#define LED_PORT_0_SHIFT 0 +#define LED_PIN_RED 8 +#define LED_PIN_GREEN 9 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS 0 +#define HAS_FLIGHT 0 +#define HAS_ADC 0 +#define HAS_LOG 0 + +/* + * Telemetry monitoring + */ +#define HAS_MONITOR 1 +#define LEGACY_MONITOR 0 +#define HAS_MONITOR_PUT 1 +#define AO_MONITOR_LED AO_LED_GREEN + +/* + * Radio (cc1200) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpioc) +#define AO_CC1200_SPI_CS_PIN 5 +#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1200_SPI stm_spi2 + +#define AO_CC1200_INT_PORT (&stm_gpioe) +#define AO_CC1200_INT_PIN 1 + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +/* + * Profiling Viterbi decoding + */ + +#ifndef AO_PROFILE +#define AO_PROFILE 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/teledongle-v1.8/ao_teledongle.c b/src/teledongle-v1.8/ao_teledongle.c new file mode 100644 index 00000000..68d6de60 --- /dev/null +++ b/src/teledongle-v1.8/ao_teledongle.c @@ -0,0 +1,54 @@ +/* + * 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 +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_cmd_init(); + + ao_usb_init(); + ao_radio_init(); + ao_monitor_init(); + ao_rssi_init(AO_LED_RED); + ao_packet_master_init(); + ao_send_packet_init(); + + ao_config_init(); + + ao_start_scheduler(); + return 0; +} -- cgit v1.2.3 From f2e5ffd839fe5be99359e4c86a96f03148bac698 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 15:58:42 -0800 Subject: altos: Declare port register type only in arch header Instead of defaulting to 8 bits, explicitly require declaration of the type of the port register for each architecture. Signed-off-by: Keith Packard --- src/attiny/ao_arch.h | 2 ++ src/avr/ao_arch.h | 2 ++ src/cc1111/ao_arch.h | 2 ++ src/kernel/ao.h | 4 ---- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/attiny/ao_arch.h b/src/attiny/ao_arch.h index 8140dd30..6ca12af6 100644 --- a/src/attiny/ao_arch.h +++ b/src/attiny/ao_arch.h @@ -31,6 +31,8 @@ #define AO_STACK_SIZE 116 +#define AO_PORT_TYPE uint8_t + /* Various definitions to make GCC look more like SDCC */ #define ao_arch_naked_declare __attribute__((naked)) diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index d626e830..f8c7f042 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -41,6 +41,8 @@ #define AO_STACK_SIZE 116 #endif +#define AO_PORT_TYPE uint8_t + /* Various definitions to make GCC look more like SDCC */ #define ao_arch_naked_declare __attribute__((naked)) diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index fcac331b..b3c6b5dc 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -40,6 +40,8 @@ #define AO_STACK_END 0xfe #define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) +#define AO_PORT_TYPE uint8_t + #define ao_arch_reboot() do { \ WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \ ao_delay(AO_SEC_TO_TICKS(2)); \ diff --git a/src/kernel/ao.h b/src/kernel/ao.h index 244421f3..48b06490 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -43,10 +43,6 @@ #define HAS_TASK 1 #endif -#ifndef AO_PORT_TYPE -#define AO_PORT_TYPE uint8_t -#endif - typedef AO_PORT_TYPE ao_port_t; #if HAS_TASK -- cgit v1.2.3 From 80a0397dde2f787fb20fd2520b274b826c68ed5a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 16:00:06 -0800 Subject: altos: Stop attempting to ramp power on CC115L The PA register on the 115L isn't in any way monotonic, making the old code broken. Just rempve it instead of fixing it; we don't ramp anywhere else... Signed-off-by: Keith Packard --- src/drivers/ao_cc115l.c | 52 +++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index cf61acfe..9e116d62 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -246,6 +246,8 @@ ao_radio_idle(void) } /* Flush any pending TX bytes */ ao_radio_strobe(CC115L_SFTX); + /* Make sure the RF calibration is current */ + ao_radio_strobe(CC115L_SCAL); } /* @@ -325,23 +327,22 @@ static const struct { static const uint16_t packet_setup[] = { CC115L_MDMCFG3, (PACKET_DRATE_M), - CC115L_MDMCFG2, (0x00 | - (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) | + CC115L_MDMCFG2, ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) | (0 << CC115L_MDMCFG2_MANCHESTER_EN) | (CC115L_MDMCFG2_SYNC_MODE_16BITS << CC115L_MDMCFG2_SYNC_MODE)), }; /* - * RDF deviation is 5kHz + * RDF deviation is 3kHz * * fdev = fosc >> 17 * (8 + dev_m) << dev_e * - * 26e6 / (2 ** 17) * (8 + 4) * (2 ** 1) = 4761Hz + * 26e6 / (2 ** 17) * (8 + 7) * (2 ** 0) = 2975 */ -#define RDF_DEV_E 1 -#define RDF_DEV_M 4 +#define RDF_DEV_E 0 +#define RDF_DEV_M 7 /* * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone) @@ -364,8 +365,7 @@ static const uint16_t rdf_setup[] = { CC115L_MDMCFG4, ((0xf << 4) | (RDF_DRATE_E << CC115L_MDMCFG4_DRATE_E)), CC115L_MDMCFG3, (RDF_DRATE_M), - CC115L_MDMCFG2, (0x00 | - (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) | + CC115L_MDMCFG2, ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) | (0 << CC115L_MDMCFG2_MANCHESTER_EN) | (CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)), }; @@ -401,8 +401,7 @@ static const uint16_t aprs_setup[] = { CC115L_MDMCFG4, ((0xf << 4) | (APRS_DRATE_E << CC115L_MDMCFG4_DRATE_E)), CC115L_MDMCFG3, (APRS_DRATE_M), - CC115L_MDMCFG2, (0x00 | - (CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) | + CC115L_MDMCFG2, ((CC115L_MDMCFG2_MOD_FORMAT_GFSK << CC115L_MDMCFG2_MOD_FORMAT) | (0 << CC115L_MDMCFG2_MANCHESTER_EN) | (CC115L_MDMCFG2_SYNC_MODE_NONE << CC115L_MDMCFG2_SYNC_MODE)), }; @@ -491,16 +490,21 @@ static const uint16_t radio_setup[] = { AO_CC115L_DONE_INT_GPIO_IOCFG, CC115L_IOCFG_GPIO_CFG_PA_PD | (1 << CC115L_IOCFG_GPIO_INV), CC115L_FIFOTHR, 0x47, /* TX FIFO Thresholds */ - CC115L_MDMCFG1, (0x00 | - (CC115L_MDMCFG1_NUM_PREAMBLE_4 << CC115L_MDMCFG1_NUM_PREAMBLE) | - (1 << CC115L_MDMCFG1_CHANSPC_E)), + CC115L_MDMCFG1, /* Modem Configuration */ + ((CC115L_MDMCFG1_NUM_PREAMBLE_4 << CC115L_MDMCFG1_NUM_PREAMBLE) | + (1 << CC115L_MDMCFG1_CHANSPC_E)), CC115L_MDMCFG0, 248, /* Channel spacing M value (100kHz channels) */ + CC115L_MCSM1, 0x30, /* Main Radio Control State Machine Configuration */ CC115L_MCSM0, 0x38, /* Main Radio Control State Machine Configuration */ CC115L_RESERVED_0X20, 0xfb, /* Use setting from SmartRF Studio */ + CC115L_FREND0, 0x10, /* Front End TX Configuration */ CC115L_FSCAL3, 0xe9, /* Frequency Synthesizer Calibration */ CC115L_FSCAL2, 0x2a, /* Frequency Synthesizer Calibration */ CC115L_FSCAL1, 0x00, /* Frequency Synthesizer Calibration */ CC115L_FSCAL0, 0x1f, /* Frequency Synthesizer Calibration */ + CC115L_RESERVED_0X29, 0x59, /* RESERVED */ + CC115L_RESERVED_0X2A, 0x7f, /* RESERVED */ + CC115L_RESERVED_0X2B, 0x3f, /* RESERVED */ CC115L_TEST2, 0x81, /* Various Test Settings */ CC115L_TEST1, 0x35, /* Various Test Settings */ CC115L_TEST0, 0x09, /* Various Test Settings */ @@ -508,6 +512,12 @@ static const uint16_t radio_setup[] = { static uint8_t ao_radio_configured = 0; +#if HAS_RADIO_POWER +#define RADIO_POWER ao_config.radio_power +#else +#define RADIO_POWER 0xc0 +#endif + static void ao_radio_setup(void) { @@ -523,6 +533,8 @@ ao_radio_setup(void) ao_config_get(); + ao_radio_reg_write(CC115L_PA, RADIO_POWER); + ao_radio_strobe(CC115L_SCAL); ao_radio_configured = 1; @@ -553,6 +565,8 @@ ao_radio_get(void) ao_radio_reg_write(CC115L_FREQ1, ao_config.radio_setting >> 8); ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting); last_radio_setting = ao_config.radio_setting; + /* Make sure the RF calibration is current */ + ao_radio_strobe(CC115L_SCAL); } if (ao_config.radio_rate != last_radio_rate) { ao_radio_mode &= ~AO_RADIO_MODE_BITS_PACKET_TX; @@ -666,23 +680,11 @@ ao_radio_rdf_abort(void) #define POWER_STEP 0x08 -#if HAS_RADIO_POWER -#define RADIO_POWER ao_config.radio_power -#else -#define RADIO_POWER 0xc0 -#endif - static void ao_radio_stx(void) { - uint8_t power; ao_radio_pa_on(); - ao_radio_reg_write(CC115L_PA, 0); ao_radio_strobe(CC115L_STX); - for (power = POWER_STEP; power < RADIO_POWER; power += POWER_STEP) - ao_radio_reg_write(CC115L_PA, power); - if (power != RADIO_POWER) - ao_radio_reg_write(CC115L_PA, RADIO_POWER); } static void -- cgit v1.2.3 From 2f0ff9675017655846a8abc617b4dc9a3666d0b9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 16:01:24 -0800 Subject: altos: Use AO_SPO_SPEED_FAST for CC1200 This asks for the fastest available SPI speed, instead of fixing it to 8MHz, which may not be supported on every architecture. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index fdaa6754..8f31d2b4 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -37,7 +37,7 @@ extern const uint32_t ao_radio_cal; #define FOSC 40000000 -#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_8MHz) +#define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_FAST) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1200_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1200_SPI_BUS) -- cgit v1.2.3 From d3dd45b060c996153ff8195bd371e9e1f3b15efb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 16:02:47 -0800 Subject: altos: Use other TeleDongle LED for CRC-invalid packet reporting Instead of blinking out some fake-o RSSI indication, just blink the red LED when a packet with a bad CRC is received. Signed-off-by: Keith Packard --- src/kernel/ao.h | 1 + src/kernel/ao_monitor.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/kernel/ao.h b/src/kernel/ao.h index 48b06490..16d600aa 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -652,6 +652,7 @@ union ao_monitor { extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; #define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) +#define ao_monitor_ring_prev(n) (((n) - 1) & (AO_MONITOR_RING - 1)) extern __data uint8_t ao_monitoring; extern __data uint8_t ao_monitor_head; diff --git a/src/kernel/ao_monitor.c b/src/kernel/ao_monitor.c index 2d75c41c..cba0d80a 100644 --- a/src/kernel/ao_monitor.c +++ b/src/kernel/ao_monitor.c @@ -94,9 +94,18 @@ __xdata struct ao_task ao_monitor_blink_task; void ao_monitor_blink(void) { +#ifdef AO_MONITOR_BAD + uint8_t *recv; +#endif for (;;) { ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100)); +#ifdef AO_MONITOR_BAD + recv = (uint8_t *) &ao_monitor_ring[ao_monitor_ring_prev(ao_monitor_head)]; + if (ao_monitoring && !(recv[ao_monitoring + 1] & AO_RADIO_STATUS_CRC_OK)) + ao_led_for(AO_MONITOR_BAD, AO_MS_TO_TICKS(100)); + else +#endif + ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100)); } } #endif -- cgit v1.2.3 From 58db263cc835be0abb972654c2d7369718c88b37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 16:04:14 -0800 Subject: altos/lpc: Declare SPI send parameters as const This matches STM Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 4 ++-- src/lpc/ao_spi_lpc.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 21a7a8e5..ff8a184d 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -201,7 +201,7 @@ void ao_spi_put(uint8_t spi_index); void -ao_spi_send(void *block, uint16_t len, uint8_t spi_index); +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index); void ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); @@ -210,7 +210,7 @@ void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void -ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); +ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index); extern uint16_t ao_spi_speed[LPC_NUM_SPI]; diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index e72b8286..bc8f9c69 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -43,9 +43,9 @@ static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 } } while (0) void -ao_spi_send(void *block, uint16_t len, uint8_t id) +ao_spi_send(const void *block, uint16_t len, uint8_t id) { - uint8_t *b = block; + const uint8_t *b = block; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; spi_loop(len, *b++, (void)); @@ -69,9 +69,9 @@ ao_spi_recv(void *block, uint16_t len, uint8_t id) } void -ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t id) +ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t id) { - uint8_t *o = out; + const uint8_t *o = out; uint8_t *i = in; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; -- cgit v1.2.3 From 6a082d9b5ed169b9d4153885f3535987e5ae5d84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 16:04:56 -0800 Subject: altos/lpc: Disable JTAG when using pins for GPIO JTAG is enabled by default, making those pins not support GPIO unless specifically configured. Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 12 ++++++++++++ src/lpc/ao_led_lpc.c | 11 ++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index ff8a184d..69f2cbfb 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -30,8 +30,19 @@ #define ao_gpio_get(port, bit, pin) (lpc_gpio.byte[lpc_all_bit(port,bit)]) +#define PORT0_JTAG_REGS ((1 << 11) | (1 << 12) | (1 << 14)) + +static inline void lpc_set_gpio(int port, int bit) { + if (port == 0 && (1 << bit) & (PORT0_JTAG_REGS)) { + vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); + + *_ioconf = (*_ioconf & ~LPC_IOCONF_FUNC_MASK) | LPC_IOCONF_FUNC_PIO0_11; + } +} + #define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ + lpc_set_gpio(port,bit); \ ao_gpio_set(port, bit, pin, v); \ lpc_gpio.dir[port] |= (1 << bit); \ } while (0) @@ -52,6 +63,7 @@ #define ao_enable_input(port,bit,mode) do { \ ao_enable_port(port); \ + lpc_set_gpio(port,bit); \ lpc_gpio.dir[port] &= ~(1 << bit); \ ao_gpio_set_mode(port,bit,mode); \ } while (0) diff --git a/src/lpc/ao_led_lpc.c b/src/lpc/ao_led_lpc.c index d983437c..a0b293b9 100644 --- a/src/lpc/ao_led_lpc.c +++ b/src/lpc/ao_led_lpc.c @@ -59,6 +59,15 @@ void ao_led_init(AO_PORT_TYPE enable) { ao_led_enable = enable; - lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO); + ao_enable_port(LED_PORT); + if (LED_PORT == 0) { + if (enable & (1 << 11)) + lpc_ioconf.pio0_11 = LPC_IOCONF_FUNC_PIO0_11 | (1 << LPC_IOCONF_ADMODE); + if (enable & (1 << 12)) + lpc_ioconf.pio0_12 = LPC_IOCONF_FUNC_PIO0_12 | (1 << LPC_IOCONF_ADMODE); + if (enable & (1 << 14)) + lpc_ioconf.pio0_14 = LPC_IOCONF_FUNC_PIO0_14 | (1 << LPC_IOCONF_ADMODE); + } lpc_gpio.dir[LED_PORT] |= enable; + ao_led_off(enable); } -- cgit v1.2.3 From 7f742824673e5e6034defdb09b66d4d56eb8d4fe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 16:05:49 -0800 Subject: altos/teledongle-v1.9: Switch to NXP processor as on prototype boards Signed-off-by: Keith Packard --- src/teledongle-v1.9/Makefile | 32 ++++------ src/teledongle-v1.9/ao_pins.h | 97 ++++++++++-------------------- src/teledongle-v1.9/ao_teledongle.c | 3 +- src/teledongle-v1.9/flash-loader/Makefile | 2 +- src/teledongle-v1.9/flash-loader/ao_pins.h | 17 +++--- 5 files changed, 54 insertions(+), 97 deletions(-) (limited to 'src') diff --git a/src/teledongle-v1.9/Makefile b/src/teledongle-v1.9/Makefile index d800d610..78deb9e2 100644 --- a/src/teledongle-v1.9/Makefile +++ b/src/teledongle-v1.9/Makefile @@ -3,7 +3,7 @@ # # -include ../stm/Makefile.defs +include ../lpc/Makefile.defs INC = \ ao.h \ @@ -14,21 +14,11 @@ INC = \ ao_product.h \ ao_task.h \ ao_whiten.h \ - stm32l.h \ + lpc.h \ ao_cc1200.h \ ao_cc1200_CC1200.h \ Makefile -#PROFILE=ao_profile.c -#PROFILE_DEF=-DAO_PROFILE=1 - -#SAMPLE_PROFILE=ao_sample_profile.c \ -# ao_sample_profile_timer.c -#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 - -#STACK_GUARD=ao_mpu_stm.c -#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 - ALTOS_SRC = \ ao_boot_chain.c \ ao_interrupt.c \ @@ -38,20 +28,17 @@ ALTOS_SRC = \ ao_cmd.c \ ao_config.c \ ao_task.c \ - ao_led.c \ + ao_led_lpc.c \ ao_stdio.c \ ao_panic.c \ - ao_timer.c \ + ao_timer_lpc.c \ ao_mutex.c \ ao_freq.c \ - ao_dma_stm.c \ - ao_spi_stm.c \ - ao_usb_stm.c \ - ao_exti_stm.c \ + ao_spi_lpc.c \ + ao_usb_lpc.c \ + ao_exti_lpc.c \ ao_send_packet.c \ - ao_eeprom_stm.c \ ao_monitor.c \ - ao_rssi.c \ ao_packet_master.c \ ao_packet.c @@ -59,7 +46,7 @@ PRODUCT=TeleDongle-v1.9 PRODUCT_DEF=-DTELEDONGLE IDPRODUCT=0x000c -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -Os -g PROGNAME=teledongle-v1.9 PROG=$(PROGNAME)-$(VERSION).elf @@ -78,6 +65,9 @@ $(OBJ): $(INC) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ +load: $(PROG) + lpc-load $(PROG) + distclean: clean clean: diff --git a/src/teledongle-v1.9/ao_pins.h b/src/teledongle-v1.9/ao_pins.h index 86dd0459..f8889c4a 100644 --- a/src/teledongle-v1.9/ao_pins.h +++ b/src/teledongle-v1.9/ao_pins.h @@ -20,83 +20,49 @@ #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 +#define AO_STACK_SIZE 324 -/* Run APB1 at 16MHz (HCLK/2) */ -#define AO_APB1_PRESCALER 2 -#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 +#define HAS_TASK_QUEUE 1 -/* Run APB2 at 16MHz (HCLK/2) */ -#define AO_APB2_PRESCALER 2 -#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 +#define IS_FLASH_LOADER 0 -#define HAS_SERIAL_1 0 -#define USE_SERIAL_1_STDIN 0 -#define SERIAL_1_PB6_PB7 0 -#define SERIAL_1_PA9_PA10 0 +/* Crystal on the board */ +#define AO_LPC_CLKIN 12000000 -#define HAS_SERIAL_2 0 -#define USE_SERIAL_2_STDIN 0 -#define SERIAL_2_PA2_PA3 0 -#define SERIAL_2_PD5_PD6 0 +/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ +#define AO_LPC_CLKOUT 48000000 -#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 +/* System clock frequency */ +#define AO_LPC_SYSCLK 24000000 -#define HAS_EEPROM 1 -#define USE_INTERNAL_FLASH 1 +#define HAS_EEPROM 0 +#define USE_INTERNAL_FLASH 0 #define USE_STORAGE_CONFIG 0 -#define USE_EEPROM_CONFIG 1 +#define USE_EEPROM_CONFIG 0 + #define HAS_USB 1 +#define HAS_USB_CONNECT 0 +#define HAS_USB_VBUS 0 +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + #define HAS_BEEP 0 #define HAS_RADIO 1 #define HAS_TELEMETRY 0 -#define HAS_RSSI 1 - -#define HAS_SPI_1 0 -#define SPI_1_PA5_PA6_PA7 0 /* Barometer */ -#define SPI_1_PB3_PB4_PB5 0 -#define SPI_1_PE13_PE14_PE15 0 /* Accelerometer */ - -#define HAS_SPI_2 1 -#define SPI_2_PB13_PB14_PB15 1 /* Radio */ -#define SPI_2_PD1_PD3_PD4 0 -#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz +#define HAS_RSSI 0 -#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 HAS_SPI_0 1 +#define SPI_SCK0_P0_6 1 #define PACKET_HAS_SLAVE 0 #define PACKET_HAS_MASTER 1 #define LOW_LEVEL_DEBUG 0 -#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOCEN -#define LED_PORT_0 (&stm_gpioc) -#define LED_PORT_0_MASK (0xffff) -#define LED_PORT_0_SHIFT 0 -#define LED_PIN_RED 8 -#define LED_PIN_GREEN 9 +#define LED_PORT 0 +#define LED_PIN_RED 14 +#define LED_PIN_GREEN 7 #define AO_LED_RED (1 << LED_PIN_RED) #define AO_LED_GREEN (1 << LED_PIN_GREEN) @@ -114,6 +80,7 @@ #define LEGACY_MONITOR 0 #define HAS_MONITOR_PUT 1 #define AO_MONITOR_LED AO_LED_GREEN +#define AO_MONITOR_BAD AO_LED_RED /* * Radio (cc1200) @@ -124,13 +91,13 @@ #define AO_RADIO_CAL_DEFAULT 5695733 #define AO_FEC_DEBUG 0 -#define AO_CC1200_SPI_CS_PORT (&stm_gpioc) -#define AO_CC1200_SPI_CS_PIN 5 -#define AO_CC1200_SPI_BUS AO_SPI_2_PB13_PB14_PB15 -#define AO_CC1200_SPI stm_spi2 +#define AO_CC1200_SPI_CS_PORT 0 +#define AO_CC1200_SPI_CS_PIN 3 +#define AO_CC1200_SPI_BUS 0 +#define AO_CC1200_SPI 0 -#define AO_CC1200_INT_PORT (&stm_gpioe) -#define AO_CC1200_INT_PIN 1 +#define AO_CC1200_INT_PORT 0 +#define AO_CC1200_INT_PIN 2 #define AO_CC1200_INT_GPIO 2 #define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 diff --git a/src/teledongle-v1.9/ao_teledongle.c b/src/teledongle-v1.9/ao_teledongle.c index 68d6de60..02b93efe 100644 --- a/src/teledongle-v1.9/ao_teledongle.c +++ b/src/teledongle-v1.9/ao_teledongle.c @@ -35,7 +35,6 @@ main(void) ao_timer_init(); ao_spi_init(); - ao_dma_init(); ao_exti_init(); ao_cmd_init(); @@ -43,12 +42,12 @@ main(void) ao_usb_init(); ao_radio_init(); ao_monitor_init(); - ao_rssi_init(AO_LED_RED); ao_packet_master_init(); ao_send_packet_init(); ao_config_init(); + ao_led_off(AO_LED_RED); ao_start_scheduler(); return 0; } diff --git a/src/teledongle-v1.9/flash-loader/Makefile b/src/teledongle-v1.9/flash-loader/Makefile index 70ddaad4..a5642b46 100644 --- a/src/teledongle-v1.9/flash-loader/Makefile +++ b/src/teledongle-v1.9/flash-loader/Makefile @@ -4,4 +4,4 @@ TOPDIR=../.. HARDWARE=teledongle-v1.9 -include $(TOPDIR)/stm/Makefile-flash.defs +include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/teledongle-v1.9/flash-loader/ao_pins.h b/src/teledongle-v1.9/flash-loader/ao_pins.h index 1af92f13..aee5be27 100644 --- a/src/teledongle-v1.9/flash-loader/ao_pins.h +++ b/src/teledongle-v1.9/flash-loader/ao_pins.h @@ -18,17 +18,18 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -/* External crystal at 8MHz */ -#define AO_HSE 8000000 +#include -#include +/* Debug port TXD (pin 6) */ -/* Companion port cs_companion0 PD0 */ - -#define AO_BOOT_PIN 1 -#define AO_BOOT_APPLICATION_GPIO stm_gpiod -#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO 0 +#define AO_BOOT_APPLICATION_PIN 19 #define AO_BOOT_APPLICATION_VALUE 1 #define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 437eba2ff27b2b7dfd0f363819b9a43ab8b28ead Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Nov 2014 20:04:47 -0800 Subject: altos: Reset interrupt flags before TX in CC1200 driver Failing to reset the flags set during interrupt leads to short-circuiting transmission and not a lot of packets going out. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 8f31d2b4..930680b2 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -28,8 +28,14 @@ static uint8_t ao_radio_abort; /* radio operation should abort */ int8_t ao_radio_rssi; /* Last received RSSI value */ +#ifndef CC1200_DEBUG #define CC1200_DEBUG 0 +#endif + +#ifndef CC1200_LOW_LEVEL_DEBUG #define CC1200_LOW_LEVEL_DEBUG 0 +#endif + #define CC1200_TRACE 0 #define CC1200_APRS_TRACE 0 @@ -742,6 +748,8 @@ ao_rdf_start(uint8_t len) static void ao_radio_run(void) { + ao_radio_wake = 0; + ao_radio_abort = 0; ao_radio_start_tx(); ao_radio_wait_isr(0); if (!ao_radio_wake) @@ -858,6 +866,7 @@ ao_radio_send_aprs(ao_radio_fill_func fill) uint8_t started = 0; uint8_t fifo_space; + ao_radio_abort = 0; ao_radio_get(0xff); fifo_space = CC1200_FIFO_SIZE; while (!done) { -- cgit v1.2.3 From abdf3177293c57e659017b64819c13f11c126011 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Nov 2014 13:41:27 -0800 Subject: altos/microsplash: fix .gitignore to ignore resulting binary --- src/microsplash/.gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/microsplash/.gitignore b/src/microsplash/.gitignore index 0573d989..5f6fe3b2 100644 --- a/src/microsplash/.gitignore +++ b/src/microsplash/.gitignore @@ -1,2 +1,2 @@ ao_product.h -microwater-* +microsplash-* -- cgit v1.2.3 From 54f7ab842a8cba3003cd5a9deb2515151263ca2e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Nov 2014 16:38:12 -0800 Subject: altos: Allow TeleMega to be built without MPU6000 Robert Braibish's board has a dead MPU6000; this fix lets the TeleMega firmware build without that driver so the rest of the board could be verified. Signed-off-by: Keith Packard --- src/kernel/ao_telemetry.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/kernel/ao_telemetry.c b/src/kernel/ao_telemetry.c index 868b3260..e2197f7a 100644 --- a/src/kernel/ao_telemetry.c +++ b/src/kernel/ao_telemetry.c @@ -133,7 +133,9 @@ ao_send_mega_sensor(void) telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR; +#if HAS_MPU6000 telemetry.mega_sensor.orient = ao_sample_orient; +#endif telemetry.mega_sensor.accel = ao_data_accel(packet); telemetry.mega_sensor.pres = ao_data_pres(packet); telemetry.mega_sensor.temp = ao_data_temp(packet); -- cgit v1.2.3 From 2163f6e6b341b7840f03e89d568699b8ea186435 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Nov 2014 16:39:18 -0800 Subject: altos/teledongle-v1.8: Make this the same as teledongle v1.9 Remove RSSI LED blinking, add CRC error LED Signed-off-by: Keith Packard --- src/teledongle-v1.8/Makefile | 1 - src/teledongle-v1.8/ao_pins.h | 3 ++- src/teledongle-v1.8/ao_teledongle.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/teledongle-v1.8/Makefile b/src/teledongle-v1.8/Makefile index dc5e246c..6c05ce9f 100644 --- a/src/teledongle-v1.8/Makefile +++ b/src/teledongle-v1.8/Makefile @@ -51,7 +51,6 @@ ALTOS_SRC = \ ao_send_packet.c \ ao_eeprom_stm.c \ ao_monitor.c \ - ao_rssi.c \ ao_packet_master.c \ ao_packet.c diff --git a/src/teledongle-v1.8/ao_pins.h b/src/teledongle-v1.8/ao_pins.h index 86dd0459..cff3e5e8 100644 --- a/src/teledongle-v1.8/ao_pins.h +++ b/src/teledongle-v1.8/ao_pins.h @@ -69,7 +69,7 @@ #define HAS_BEEP 0 #define HAS_RADIO 1 #define HAS_TELEMETRY 0 -#define HAS_RSSI 1 +#define HAS_RSSI 0 #define HAS_SPI_1 0 #define SPI_1_PA5_PA6_PA7 0 /* Barometer */ @@ -114,6 +114,7 @@ #define LEGACY_MONITOR 0 #define HAS_MONITOR_PUT 1 #define AO_MONITOR_LED AO_LED_GREEN +#define AO_MONITOR_BAD AO_LED_RED /* * Radio (cc1200) diff --git a/src/teledongle-v1.8/ao_teledongle.c b/src/teledongle-v1.8/ao_teledongle.c index 68d6de60..5ce6b15b 100644 --- a/src/teledongle-v1.8/ao_teledongle.c +++ b/src/teledongle-v1.8/ao_teledongle.c @@ -43,12 +43,12 @@ main(void) ao_usb_init(); ao_radio_init(); ao_monitor_init(); - ao_rssi_init(AO_LED_RED); ao_packet_master_init(); ao_send_packet_init(); ao_config_init(); + ao_led_off(AO_LED_RED); ao_start_scheduler(); return 0; } -- cgit v1.2.3 From eabeb76a2a9acb624ae364c4f0f315bfc3549d98 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Nov 2014 18:31:15 -0800 Subject: altos/cc1200: Wait for packet to be placed in FIFO during receive This changes the receive code to use MCU_STATUS, waiting for MARC_STATUS1 to indicate that the packet is in the fifo before reading it out. It also fixes the receive timeout code to keep receiving if the preamble or sync have been seen when the timeout fires. This makes TeleLCO able to use short timeouts during scanning while still successfully receiving packets. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 103 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 930680b2..93bb2c6c 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -599,14 +599,20 @@ ao_radio_set_mode(uint16_t new_mode) } } - if (changes & AO_RADIO_MODE_BITS_TX_BUF) + if (changes & AO_RADIO_MODE_BITS_TX_BUF) { ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_TXFIFO_THR); + ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); + } - if (changes & AO_RADIO_MODE_BITS_TX_FINISH) + if (changes & AO_RADIO_MODE_BITS_TX_FINISH) { ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); + ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH); + } - if (changes & AO_RADIO_MODE_BITS_RX) - ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_PKT_SYNC_RXTX); + if (changes & AO_RADIO_MODE_BITS_RX) { + ao_radio_reg_write(AO_CC1200_INT_GPIO_IOCFG, CC1200_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); + ao_exti_set_mode(AO_CC1200_INT_PORT, AO_CC1200_INT_PIN, AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_HIGH); + } if (changes & AO_RADIO_MODE_BITS_RDF) ao_radio_set_regs(rdf_setup); @@ -709,20 +715,6 @@ ao_radio_show_state(char *where) static void ao_radio_wait_isr(uint16_t timeout) { - uint8_t state; - - state = ao_radio_state(); - switch (state) { - case CC1200_STATUS_STATE_IDLE: - case CC1200_STATUS_STATE_RX_FIFO_ERROR: - case CC1200_STATUS_STATE_TX_FIFO_ERROR: -#if CC1200_LOW_LEVEL_DEBUG - printf("before wait, state %d\n", state); flush(); -#endif - ao_radio_abort = 1; - return; - } - if (timeout) ao_alarm(timeout); @@ -731,6 +723,7 @@ ao_radio_wait_isr(uint16_t timeout) if (ao_sleep(&ao_radio_wake)) ao_radio_abort = 1; ao_arch_release_interrupts(); + if (timeout) ao_clear_alarm(); } @@ -1005,14 +998,80 @@ ao_radio_dump_state(struct ao_radio_state *s) uint8_t ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) { - ao_radio_abort = 0; + uint8_t success = 0; + ao_radio_abort = 0; ao_radio_get(size - 2); ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); ao_radio_wake = 0; ao_radio_start_rx(); - ao_radio_wait_isr(timeout); - if (ao_radio_wake) { + + while (!ao_radio_abort) { + ao_radio_wait_isr(timeout); + if (ao_radio_wake) { + uint8_t marc_status1 = ao_radio_reg_read(CC1200_MARC_STATUS1); + + /* Check the receiver status to see what happened + */ + switch (marc_status1) { + case CC1200_MARC_STATUS1_RX_FINISHED: + case CC1200_MARC_STATUS1_ADDRESS: + case CC1200_MARC_STATUS1_CRC: + /* Normal return, go fetch the bytes from the FIFO + * and give them back to the caller + */ + success = 1; + break; + case CC1200_MARC_STATUS1_RX_TIMEOUT: + case CC1200_MARC_STATUS1_RX_TERMINATION: + case CC1200_MARC_STATUS1_EWOR_SYNC_LOST: + case CC1200_MARC_STATUS1_MAXIMUM_LENGTH: + case CC1200_MARC_STATUS1_RX_FIFO_OVERFLOW: + case CC1200_MARC_STATUS1_RX_FIFO_UNDERFLOW: + /* Something weird happened; reset the radio and + * return failure + */ + success = 0; + break; + default: + /* some other status; go wait for the radio to do something useful + */ + continue; + } + break; + } else { + uint8_t modem_status1 = ao_radio_reg_read(CC1200_MODEM_STATUS1); + + /* Check to see if the packet header has been seen, in which case we'll + * want to keep waiting for the rest of the packet to appear + */ + if (modem_status1 & ((1 << CC1200_MODEM_STATUS1_SYNC_FOUND) | + (1 << CC1200_MODEM_STATUS1_PQT_REACHED))) + { + ao_radio_abort = 0; + + /* Set a timeout based on the packet length so that we make sure to + * wait long enough to receive the whole thing. + * + * timeout = bits * FEC expansion / rate + */ + switch (ao_config.radio_rate) { + default: + case AO_RADIO_RATE_38400: + timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 384) + 1; + break; + case AO_RADIO_RATE_9600: + timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 96) + 1; + break; + case AO_RADIO_RATE_2400: + timeout = AO_MS_TO_TICKS(size * (8 * 2 * 10) / 24) + 1; + break; + } + } + } + } + + if (success) { int8_t rssi; uint8_t status; @@ -1033,7 +1092,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) } ao_radio_put(); - return ao_radio_wake; + return success; } -- cgit v1.2.3 From 0e3eeaf59688dac92eb3a27d589923126cb34e00 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Nov 2014 18:50:57 -0800 Subject: altos/cc1200: Open up preamble detect to improve sensitivity Increase soft decision PQT value to max (15) to ensure that we detect even weak packets. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200_CC1200.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index c078c09d..c5497196 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -46,7 +46,7 @@ CC1200_PREAMBLE_CFG0, /* Preamble Detection Configuration Reg. 0 */ ((1 << CC1200_PREAMBLE_CFG0_PQT_EN) | (CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT_11 << CC1200_PREAMBLE_CFG0_PQT_VALID_TIMEOUT) | - (6 << CC1200_PREAMBLE_CFG0_PQT)), + (15 << CC1200_PREAMBLE_CFG0_PQT)), CC1200_IQIC, 0xcb, /* Digital Image Channel Compensation Configuration */ CC1200_CHAN_BW, 0x11, /* Channel Filter Configuration */ CC1200_MDMCFG1, 0x40, /* General Modem Parameter Configuration Reg. 1 */ -- cgit v1.2.3 From b6462ca3a7e99fe390ec97f94c23d36fab8c294d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Nov 2014 18:56:40 -0800 Subject: altos/cc1200: With PQT wide open, we can't use PQT_REACHED for start Because we're allowing even signals only weakly correlated with the preamble through to sync detection, we can't use the PQT_REACHED symbol to tell when a packet header has been seen. Instead, just look for SYNC_FOUND. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 93bb2c6c..8546900e 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -1045,8 +1045,7 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) /* Check to see if the packet header has been seen, in which case we'll * want to keep waiting for the rest of the packet to appear */ - if (modem_status1 & ((1 << CC1200_MODEM_STATUS1_SYNC_FOUND) | - (1 << CC1200_MODEM_STATUS1_PQT_REACHED))) + if (modem_status1 & (1 << CC1200_MODEM_STATUS1_SYNC_FOUND)) { ao_radio_abort = 0; -- cgit v1.2.3 From 014dcc1f179237dc247fafa4a2cff91809260681 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Dec 2014 17:10:33 -0800 Subject: altos: Document cc115l power measured at RF setting 0x03 as -31.75dBm We built a custom TeleGPS load for radio sensitivity measurements with the lowest documented power level setting (0x03), and measured the power out at that value of -31.75dBm on the test board. Signed-off-by: Keith Packard --- src/drivers/ao_cc115l.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index 9e116d62..6b76e7d3 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -515,7 +515,13 @@ static uint8_t ao_radio_configured = 0; #if HAS_RADIO_POWER #define RADIO_POWER ao_config.radio_power #else -#define RADIO_POWER 0xc0 + +#if 0 +#define RADIO_POWER 0x03 /* -31.75dBm on the test board */ +#endif + +#define RADIO_POWER 0xc0 /* full power */ + #endif static void -- cgit v1.2.3 From 213a6604ec225e843f30244e6f94d0ebb3d27e46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Dec 2014 17:11:51 -0800 Subject: altos: Adjust CC1200 RSSI reporting value On the test setup, we were about 13dB off, so tweak the settings to suit. This result wasn't tested; it's just a rough offset until we get a production run of TeleDongle boards back to do more systematic measurements. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200_CC1200.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index c5497196..35673123 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -24,7 +24,7 @@ */ #ifndef AO_CC1200_AGC_GAIN_ADJUST -#define AO_CC1200_AGC_GAIN_ADJUST -81 +#define AO_CC1200_AGC_GAIN_ADJUST -94 #endif CC1200_IOCFG2, 0x06, /* GPIO2 IO Pin Configuration */ -- cgit v1.2.3 From 2a053d3d157e00b6a6406f4f78ddb8e298b6c4b7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Dec 2014 17:27:09 -0800 Subject: altos/lpc: Switch LPC SPI driver to interrupt-driven This improves performance for SPI transfers, while allowing other tasks to get work done during longer SPI transfers. Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 3 + src/lpc/ao_arch_funcs.h | 2 - src/lpc/ao_spi_lpc.c | 143 +++++++++++++++++++++++++++++++++++++----------- 3 files changed, 115 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 5fbb8dfa..42faf06f 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -130,12 +130,15 @@ ao_serial_init(void); /* SPI definitions */ #define AO_SPI_SPEED_12MHz 4 +#define AO_SPI_SPEED_8MHz 6 #define AO_SPI_SPEED_6MHz 8 #define AO_SPI_SPEED_4MHz 12 #define AO_SPI_SPEED_2MHz 24 #define AO_SPI_SPEED_1MHz 48 #define AO_SPI_SPEED_500kHz 96 #define AO_SPI_SPEED_250kHz 192 +#define AO_SPI_SPEED_125kHz 384 +#define AO_SPI_SPEED_62500Hz 768 #define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 69f2cbfb..fbe641d8 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -224,8 +224,6 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t spi_index); -extern uint16_t ao_spi_speed[LPC_NUM_SPI]; - void ao_spi_init(void); diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index bc8f9c69..5a358919 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -19,63 +19,130 @@ static uint8_t ao_spi_mutex[LPC_NUM_SPI]; +struct ao_lpc_ssp_state { + int tx_count; + const uint8_t *tx; + int tx_inc; + int rx_count; + uint8_t *rx; + int rx_inc; +}; + +static struct ao_lpc_ssp_state ao_lpc_ssp_state[LPC_NUM_SPI]; + static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 }; -#define tx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_TNF))) != (1 << LPC_SSP_SR_TNF) -#define rx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_RNE))) != (1 << LPC_SSP_SR_RNE) - -#define spi_loop(len, put, get) do { \ - while (len--) { \ - /* Wait for space in the fifo */ \ - while (tx_busy(lpc_ssp)) \ - ; \ - \ - /* send a byte */ \ - lpc_ssp->dr = put; \ - \ - /* Wait for byte to appear in the fifo */ \ - while (rx_busy(lpc_ssp)) \ - ; \ - \ - /* recv a byte */ \ - get lpc_ssp->dr; \ - } \ - } while (0) +static inline void +ao_lpc_ssp_recv(struct lpc_ssp *lpc_ssp, struct ao_lpc_ssp_state *state) +{ + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) && + state->rx_count) + { + /* RX ready, read a byte */ + *state->rx = lpc_ssp->dr; + state->rx += state->rx_inc; + state->rx_count--; + } +} + +static void +ao_lpc_ssp_isr(struct lpc_ssp *lpc_ssp, struct ao_lpc_ssp_state *state) +{ + ao_lpc_ssp_recv(lpc_ssp, state); + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_TNF)) && + state->tx_count) + { + /* TX ready, write a byte */ + lpc_ssp->dr = *state->tx; + state->tx += state->tx_inc; + state->tx_count--; + ao_lpc_ssp_recv(lpc_ssp, state); + } + if (!state->rx_count) { + lpc_ssp->imsc &= ~(1 << LPC_SSP_IMSC_TXIM); + ao_wakeup(state); + } +} + +void +lpc_ssp0_isr(void) +{ + ao_lpc_ssp_isr(&lpc_ssp0, &ao_lpc_ssp_state[0]); +} + +void +lpc_ssp1_isr(void) +{ + ao_lpc_ssp_isr(&lpc_ssp1, &ao_lpc_ssp_state[1]); +} + +static void +ao_spi_run(struct lpc_ssp *lpc_ssp, struct ao_lpc_ssp_state *state) +{ + ao_arch_block_interrupts(); + lpc_ssp->imsc = (1 << LPC_SSP_IMSC_TXIM); + while (state->rx_count) + ao_sleep(state); + ao_arch_release_interrupts(); +} + +static uint8_t ao_spi_tx_dummy = 0xff; +static uint8_t ao_spi_rx_dummy; void ao_spi_send(const void *block, uint16_t len, uint8_t id) { - const uint8_t *b = block; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - spi_loop(len, *b++, (void)); + state->tx_count = state->rx_count = len; + state->tx = block; + state->tx_inc = 1; + state->rx = &ao_spi_rx_dummy; + state->rx_inc = 0; + ao_spi_run(lpc_ssp, state); } void ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t id) { struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - spi_loop(len, value, (void)); + state->tx_count = state->rx_count = len; + state->tx = &value; + state->tx_inc = 0; + state->rx = &ao_spi_rx_dummy; + state->rx_inc = 0; + ao_spi_run(lpc_ssp, state); } void ao_spi_recv(void *block, uint16_t len, uint8_t id) { - uint8_t *b = block; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - spi_loop(len, 0xff, *b++ =); + state->tx_count = state->rx_count = len; + state->tx = &ao_spi_tx_dummy; + state->tx_inc = 0; + state->rx = block; + state->rx_inc = 1; + ao_spi_run(lpc_ssp, state); } void ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t id) { - const uint8_t *o = out; - uint8_t *i = in; struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - spi_loop(len, *o++, *i++ =); + state->tx_count = state->rx_count = len; + state->tx = out; + state->tx_inc = 1; + state->rx = in; + state->rx_inc = 1; + ao_spi_run(lpc_ssp, state); } void @@ -84,7 +151,7 @@ ao_spi_get(uint8_t id, uint32_t speed) struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; ao_mutex_get(&ao_spi_mutex[id]); - + /* Set the clock prescale */ lpc_ssp->cpsr = speed; } @@ -101,6 +168,11 @@ ao_spi_channel_init(uint8_t id) struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; uint8_t d; + /* Clear interrupt registers */ + lpc_ssp->imsc = 0; + lpc_ssp->ris = 0; + lpc_ssp->mis = 0; + lpc_ssp->cr0 = ((LPC_SSP_CR0_DSS_8 << LPC_SSP_CR0_DSS) | (LPC_SSP_CR0_FRF_SPI << LPC_SSP_CR0_FRF) | (0 << LPC_SSP_CR0_CPOL) | @@ -151,7 +223,11 @@ ao_spi_init(void) lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); ao_spi_channel_init(0); -#endif + + /* Configure NVIC */ + lpc_nvic_set_enable(LPC_ISR_SSP0_POS); + lpc_nvic_set_priority(LPC_ISR_SSP0_POS, 0); +#endif #if HAS_SPI_1 @@ -190,7 +266,7 @@ ao_spi_init(void) #ifndef HAS_MOSI1 #error "No pin specified for MOSI1" #endif - + /* Enable the device */ lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP1); @@ -201,5 +277,10 @@ ao_spi_init(void) lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); ao_spi_channel_init(1); + + /* Configure NVIC */ + lpc_nvic_set_enable(LPC_ISR_SSP1_POS); + lpc_nvic_set_priority(LPC_ISR_SSP1_POS, 0); + #endif /* HAS_SPI_1 */ } -- cgit v1.2.3 From e05e0c6b71a1df65f188e00622e9632eb27510fd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Jan 2015 22:09:26 +1300 Subject: Set version to 1.5.9.1 --- configure.ac | 2 +- icon/application-vnd.altusmetrum.micropeak.svg | 1 - src/kernel/ao_config.c | 7 +- src/lpc/ao_arch.h | 2 + src/lpc/ao_arch_funcs.h | 6 + src/lpc/ao_usb_lpc.c | 76 +++++++--- src/usbtrng/ao_pins.h | 2 + src/usbtrng/ao_usbtrng.c | 195 ++++++++++++++++++++++++- 8 files changed, 264 insertions(+), 27 deletions(-) delete mode 120000 icon/application-vnd.altusmetrum.micropeak.svg (limited to 'src') diff --git a/configure.ac b/configure.ac index a38ef092..2c7b19c5 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.5.9.0) +AC_INIT([altos], 1.5.9.1) AC_CONFIG_SRCDIR([src/kernel/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/icon/application-vnd.altusmetrum.micropeak.svg b/icon/application-vnd.altusmetrum.micropeak.svg deleted file mode 120000 index 6efd3200..00000000 --- a/icon/application-vnd.altusmetrum.micropeak.svg +++ /dev/null @@ -1 +0,0 @@ -altusmetrum-micropeak.svg \ No newline at end of file diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 8dab7c42..83a8cd77 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -388,6 +388,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant uint16_t i; int32_t accel_total; uint8_t cal_data_ring; + int16_t min = 32767, max = -32768; #if HAS_GYRO int32_t accel_along_total = 0; int32_t accel_across_total = 0; @@ -405,7 +406,10 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant while (i) { ao_sleep(DATA_TO_XDATA(&ao_sample_data)); while (i && cal_data_ring != ao_sample_data) { - accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); + int16_t v = ao_data_accel(&ao_data_ring[cal_data_ring]); + accel_total += (int32_t) v; + if (v < min) min = v; + if (v > max) max = v; #if HAS_GYRO accel_along_total += (int32_t) ao_data_along(&ao_data_ring[cal_data_ring]); accel_across_total += (int32_t) ao_data_across(&ao_data_ring[cal_data_ring]); @@ -420,6 +424,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant accel_cal_across = accel_across_total >> ACCEL_CALIBRATE_SHIFT; accel_cal_through = accel_through_total >> ACCEL_CALIBRATE_SHIFT; #endif + printf ("total %d min %d max %d\n", accel_total, min, max); return accel_total >> ACCEL_CALIBRATE_SHIFT; } diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 42faf06f..1b4c61f2 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -124,6 +124,8 @@ ao_adc_init(void); #define AO_USB_OUT_EP 2 #define AO_USB_IN_EP 3 +extern uint8_t ao_usb_out_avail; + void ao_serial_init(void); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index fbe641d8..b963d3ab 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -249,4 +249,10 @@ static inline void ao_arch_start_scheduler(void) { asm("isb"); } +void * +ao_usb_alloc(uint16_t len); + +void +ao_usb_write(void *block, int len); + #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 12f5d8e6..499de9e9 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -80,14 +80,12 @@ static uint8_t *ao_usb_ep0_setup_buffer; static uint8_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ -static uint8_t *ao_usb_in_tx_buffer; -static uint8_t *ao_usb_out_rx_buffer; - -/* Our data buffers */ -static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t *ao_usb_in_tx_buffer[2]; +static uint8_t ao_usb_in_tx_cur; static uint8_t ao_usb_tx_count; -static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t *ao_usb_out_rx_buffer[2]; +static uint8_t ao_usb_out_rx_cur; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; extern struct lpc_usb_endpoint lpc_usb_endpoint; @@ -108,7 +106,7 @@ static uint8_t ao_usb_in_pending; /* Marks when an OUT packet has been received by the hardware * but not pulled to the shadow buffer. */ -static uint8_t ao_usb_out_avail; +uint8_t ao_usb_out_avail; uint8_t ao_usb_running; static uint8_t ao_usb_configuration; @@ -362,12 +360,16 @@ ao_usb_set_configuration(void) /* Set up the INT end point */ ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); - + /* Set up the OUT end point */ - ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL); + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE * 2, &ao_usb_out_rx_buffer[0], 0, NULL); + ao_usb_out_rx_buffer[1] = ao_usb_out_rx_buffer[0] + AO_USB_OUT_SIZE; + ao_usb_out_rx_cur = 0; /* Set up the IN end point */ - ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer); + ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE * 2, &ao_usb_in_tx_buffer[0]); + ao_usb_in_tx_buffer[1] = ao_usb_in_tx_buffer[0] + AO_USB_IN_SIZE; + ao_usb_in_tx_cur = 0; ao_usb_running = 1; } @@ -716,8 +718,8 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count); - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer[ao_usb_in_tx_cur], ao_usb_tx_count); + ao_usb_in_tx_cur = 1 - ao_usb_in_tx_cur; ao_usb_tx_count = 0; _tx_dbg0("in_send end"); } @@ -769,10 +771,12 @@ ao_usb_putchar(char c) ao_arch_block_interrupts(); _ao_usb_in_wait(); + ao_arch_release_interrupts(); ao_usb_in_flushed = 0; - ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c; + ao_arch_block_interrupts(); /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) { _tx_dbg0("putchar full"); @@ -782,6 +786,43 @@ ao_usb_putchar(char c) ao_arch_release_interrupts(); } +void * +ao_usb_alloc(uint16_t len) +{ + return ao_usb_alloc_sram(len); +} + +void +ao_usb_write(void *block, int len) +{ + uint8_t *b = block; + int this_time; + + if (!ao_usb_running) + return; + + if (!ao_usb_in_flushed) + ao_usb_flush(); + + while (len) { + ao_usb_in_flushed = 0; + this_time = AO_USB_IN_SIZE; + if (this_time > len) + this_time = len; + b += this_time; + len -= this_time; + + ao_arch_block_interrupts(); + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + ao_usb_in_pending = 1; + if (this_time != AO_USB_IN_SIZE) + ao_usb_in_flushed = 1; + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), b, this_time); + ao_arch_release_interrupts(); + } +} + static void _ao_usb_out_recv(void) { @@ -792,13 +833,12 @@ _ao_usb_out_recv(void) _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); - debug_data("Fill OUT len %d:", ao_usb_rx_count); - memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); - debug_data("\n"); + debug_data("Fill OUT len %d\n", ao_usb_rx_count); ao_usb_rx_pos = 0; + ao_usb_rx_out_cur = 1 - ao_usb_rx_out_cur; /* ACK the packet */ - ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_rx_out_cur], AO_USB_OUT_SIZE); } int @@ -823,7 +863,7 @@ _ao_usb_pollchar(void) } /* Pull a character out of the fifo */ - c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + c = ao_usb_rx_buffer[ao_usb_rx_out_cur][ao_usb_rx_pos++]; return c; } diff --git a/src/usbtrng/ao_pins.h b/src/usbtrng/ao_pins.h index b1fa6eb9..0f2b1ea6 100644 --- a/src/usbtrng/ao_pins.h +++ b/src/usbtrng/ao_pins.h @@ -71,3 +71,5 @@ */ #define HAS_SCK1 0 #define HAS_MOSI1 0 + +#define AO_ADC_6 1 diff --git a/src/usbtrng/ao_usbtrng.c b/src/usbtrng/ao_usbtrng.c index 6b4d20fe..66e12337 100644 --- a/src/usbtrng/ao_usbtrng.c +++ b/src/usbtrng/ao_usbtrng.c @@ -18,7 +18,53 @@ #include #define AO_TRNG_SPI_BUS 1 -#define AO_TRNG_SPI_SPEED AO_SPI_SPEED_250kHz + +static uint32_t spi_speed = AO_SPI_SPEED_4MHz; + +#define AO_TRNG_SPI_BUF 1024 + +#if 0 + +static uint8_t *spi_buf; +static uint8_t *spi_head, *spi_tail; +static uint8_t spi_wakeup; + +static void +ao_trng_run(void) +{ + int this_time; + uint8_t *end; + + if (!spi_buf) + spi_buf = ao_usb_alloc(AO_TRNG_SPI_BUF); + flush(); + ao_spi_get(AO_TRNG_SPI_BUS, spi_speed); + spi_tail = spi_buf; + spi_head = spi_buf; + ao_spi_recv_ring_start(spi_buf, AO_TRNG_SPI_BUF, &spi_head, &spi_tail, &spi_wakeup, AO_TRNG_SPI_BUS); + while (!ao_usb_out_avail) { + ao_arch_block_interrupts(); + while (spi_head == spi_tail) { + spi_wakeup = 0; + ao_sleep(&spi_wakeup); + } + ao_arch_release_interrupts(); + if (spi_tail > spi_head) + end = spi_buf + AO_TRNG_SPI_BUF; + else + end = spi_head; + this_time = end - spi_tail; + if (this_time > 64) + this_time = 64; + ao_usb_write(spi_tail, this_time); + spi_tail += this_time; + if (spi_tail == spi_buf + AO_TRNG_SPI_BUF) + spi_tail = spi_buf; + } + ao_spi_put(AO_TRNG_SPI_BUS); + getchar(); +} + static void ao_trng_test(void) @@ -26,16 +72,153 @@ ao_trng_test(void) static uint8_t random[32]; uint8_t i; - ao_spi_get(AO_TRNG_SPI_BUS, AO_TRNG_SPI_SPEED); + ao_spi_get(AO_TRNG_SPI_BUS, spi_speed); ao_spi_recv(random, sizeof (random), AO_TRNG_SPI_BUS); ao_spi_put(AO_TRNG_SPI_BUS); for (i = 0; i < sizeof (random); i++) printf (" %02x", random[i]); printf ("\n"); } +#endif + +#define ADC_RING_SIZE 512 + +static uint8_t *adc_ring; +static uint16_t adc_head, adc_tail; +static uint16_t adc_wake; + +void lpc_adc_isr(void) +{ + uint16_t avail; + uint16_t this, next; + + this = adc_head; + next = (this + 1) & (ADC_RING_SIZE - 1); + if (next == adc_tail) { + lpc_adc.inten = 0; + return; + } + adc_ring[this] = lpc_adc.dr[6] >> 8; + adc_head = next; + + /* If there are enough entries, wake up any waiters + */ + avail = (next - adc_tail) & (ADC_RING_SIZE - 1); + if (avail >= adc_wake) { + adc_wake = 0; + ao_wakeup(&adc_wake); + } +} + +#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 450000) + +static void +ao_trng_adc_init(void) +{ + adc_ring = ao_usb_alloc(ADC_RING_SIZE); + + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC); + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD); + + /* Enable interrupt when AO_ADC_6 is complete */ + lpc_adc.inten = 0; + + lpc_nvic_set_enable(LPC_ISR_ADC_POS); + lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY); + +#if AO_ADC_0 + ao_enable_analog(0, 11, 0); +#endif +#if AO_ADC_1 + ao_enable_analog(0, 12, 1); +#endif +#if AO_ADC_2 + ao_enable_analog(0, 13, 2); +#endif +#if AO_ADC_3 + ao_enable_analog(0, 14, 3); +#endif +#if AO_ADC_4 + ao_enable_analog(0, 15, 4); +#endif +#if AO_ADC_5 + ao_enable_analog(0, 16, 5); +#endif +#if AO_ADC_6 + ao_enable_analog(0, 22, 6); +#endif +#if AO_ADC_7 + ao_enable_analog(0, 23, 7); +#endif + + lpc_adc.cr = ((1 << (LPC_ADC_CR_SEL + 6)) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (1 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_9 << LPC_ADC_CR_CLKS)); +} + +static void +ao_trng_adc_dump(void) +{ + int i; + + while (((adc_head - adc_tail) & (ADC_RING_SIZE - 1)) < 16) { + lpc_adc.inten = (1 << (LPC_ADC_INTEN_ADINTEN + 6)); + adc_wake = 16; + ao_sleep(&adc_wake); + } + printf("adc_head %d tail %d\n", adc_head, adc_tail); + + for (i = 0; i < 16; i++) { + printf(" %4d", adc_ring[adc_tail]); + adc_tail = (adc_tail + 1) & (ADC_RING_SIZE - 1); + } + printf("\n"); + lpc_adc.inten = 0; +} + +static void +ao_trng_run(void) +{ + uint16_t this_time; + flush(); + + while (!ao_usb_out_avail) { + ao_arch_block_interrupts(); + while (((adc_head - adc_tail) & (ADC_RING_SIZE - 1)) < 64) { + lpc_adc.inten = (1 << (LPC_ADC_INTEN_ADINTEN + 6)); + adc_wake = 64; + ao_sleep(&adc_wake); + } + ao_arch_release_interrupts(); + + this_time = ADC_RING_SIZE - adc_tail; + if (this_time > 64) + this_time = 64; + ao_usb_write(&adc_ring[adc_tail], this_time); + adc_tail = (adc_tail + this_time) & (ADC_RING_SIZE - 1); + } + lpc_adc.inten = 0; +} + +static void +ao_trng_speed(void) +{ + ao_cmd_decimal(); + + if (ao_cmd_lex_u32 == 0 || ao_cmd_status != ao_cmd_success) { + ao_cmd_status = ao_cmd_success; + printf ("Current spi speed %d\n", spi_speed); + } else { + spi_speed = ao_cmd_lex_u32; + } +} static const struct ao_cmds ao_trng_cmds[] = { - { ao_trng_test, "R\0Dump some random numbers" }, +// { ao_trng_test, "R\0Dump some random numbers" }, + { ao_trng_run, "s\0Send random bits until char" }, + { ao_trng_speed, "S \0Set SPI speed (48MHz/speed)" }, + { ao_trng_adc_dump, "a\0Dump ADC data" }, { 0, NULL } }; @@ -46,15 +229,15 @@ main(void) ao_task_init(); ao_timer_init(); - ao_spi_init(); +// ao_spi_init(); ao_usb_init(); + ao_trng_adc_init(); + ao_serial_init(); ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_GREEN); - ao_cmd_init(); ao_cmd_register(ao_trng_cmds); -- cgit v1.2.3 From 291eec859606b73b43072cd2debfbb92659e0d95 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Jan 2015 20:34:43 -0800 Subject: altos: Get rid of some accidental debug code I was debugging the accelerometer calibration code and left some printfs in it, which made TM run out of flash space. Signed-off-by: Keith Packard --- src/kernel/ao_config.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 83a8cd77..8dab7c42 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -388,7 +388,6 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant uint16_t i; int32_t accel_total; uint8_t cal_data_ring; - int16_t min = 32767, max = -32768; #if HAS_GYRO int32_t accel_along_total = 0; int32_t accel_across_total = 0; @@ -406,10 +405,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant while (i) { ao_sleep(DATA_TO_XDATA(&ao_sample_data)); while (i && cal_data_ring != ao_sample_data) { - int16_t v = ao_data_accel(&ao_data_ring[cal_data_ring]); - accel_total += (int32_t) v; - if (v < min) min = v; - if (v > max) max = v; + accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); #if HAS_GYRO accel_along_total += (int32_t) ao_data_along(&ao_data_ring[cal_data_ring]); accel_across_total += (int32_t) ao_data_across(&ao_data_ring[cal_data_ring]); @@ -424,7 +420,6 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant accel_cal_across = accel_across_total >> ACCEL_CALIBRATE_SHIFT; accel_cal_through = accel_through_total >> ACCEL_CALIBRATE_SHIFT; #endif - printf ("total %d min %d max %d\n", accel_total, min, max); return accel_total >> ACCEL_CALIBRATE_SHIFT; } -- cgit v1.2.3 From 41a0604ad1ea1a03e2db7d41731dbadf466b45db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Jan 2015 21:31:45 -0800 Subject: altos/lpc: Fix double-buffered USB changes These got merged when we were down in Auckland, but before they'd been finished. Transmitting worked fine, but receiving was mis-configuring the OUT buffer size in the hardware. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 499de9e9..af304b8a 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -273,7 +273,7 @@ static uint8_t * ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes) { uint8_t *addr = ao_usb_alloc_sram(nbytes); - + ao_usb_set_ep(ep, addr, set_nbytes); return addr; } @@ -292,11 +292,11 @@ ao_usb_disable_ep(vuint32_t *ep) } static void -ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) +ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint16_t out_set_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) { uint8_t *addr; - addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_bytes); + addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_set_bytes); if (out_addr) *out_addr = addr; ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); @@ -359,15 +359,15 @@ ao_usb_set_configuration(void) debug ("ao_usb_set_configuration\n"); /* Set up the INT end point */ - ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); + ao_usb_enable_epn(AO_USB_INT_EP, 0, 0, NULL, 0, NULL); /* Set up the OUT end point */ - ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE * 2, &ao_usb_out_rx_buffer[0], 0, NULL); + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE * 2, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer[0], 0, NULL); ao_usb_out_rx_buffer[1] = ao_usb_out_rx_buffer[0] + AO_USB_OUT_SIZE; ao_usb_out_rx_cur = 0; /* Set up the IN end point */ - ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE * 2, &ao_usb_in_tx_buffer[0]); + ao_usb_enable_epn(AO_USB_IN_EP, 0, 0, NULL, AO_USB_IN_SIZE * 2, &ao_usb_in_tx_buffer[0]); ao_usb_in_tx_buffer[1] = ao_usb_in_tx_buffer[0] + AO_USB_IN_SIZE; ao_usb_in_tx_cur = 0; @@ -771,12 +771,10 @@ ao_usb_putchar(char c) ao_arch_block_interrupts(); _ao_usb_in_wait(); - ao_arch_release_interrupts(); ao_usb_in_flushed = 0; ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c; - ao_arch_block_interrupts(); /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) { _tx_dbg0("putchar full"); @@ -786,6 +784,7 @@ ao_usb_putchar(char c) ao_arch_release_interrupts(); } +#if HAS_AO_USB_WRITE void * ao_usb_alloc(uint16_t len) { @@ -809,8 +808,6 @@ ao_usb_write(void *block, int len) this_time = AO_USB_IN_SIZE; if (this_time > len) this_time = len; - b += this_time; - len -= this_time; ao_arch_block_interrupts(); while (ao_usb_in_pending) @@ -820,8 +817,11 @@ ao_usb_write(void *block, int len) ao_usb_in_flushed = 1; ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), b, this_time); ao_arch_release_interrupts(); + b += this_time; + len -= this_time; } } +#endif static void _ao_usb_out_recv(void) @@ -835,10 +835,10 @@ _ao_usb_out_recv(void) debug ("recv %d\n", ao_usb_rx_count); debug_data("Fill OUT len %d\n", ao_usb_rx_count); ao_usb_rx_pos = 0; - ao_usb_rx_out_cur = 1 - ao_usb_rx_out_cur; + ao_usb_out_rx_cur = 1 - ao_usb_out_rx_cur; /* ACK the packet */ - ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_rx_out_cur], AO_USB_OUT_SIZE); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_out_rx_cur], AO_USB_OUT_SIZE); } int @@ -863,7 +863,7 @@ _ao_usb_pollchar(void) } /* Pull a character out of the fifo */ - c = ao_usb_rx_buffer[ao_usb_rx_out_cur][ao_usb_rx_pos++]; + c = ao_usb_out_rx_buffer[ao_usb_out_rx_cur][ao_usb_rx_pos++]; return c; } @@ -937,7 +937,7 @@ ao_usb_enable(void) /* Enable USB PHY */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD); - + /* Turn on USB PLL */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD); -- cgit v1.2.3 From 0e7d1c89fea98eabca738f10cbfebec631be3bb7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 24 Jan 2015 11:18:59 -0800 Subject: altos: Add support for TeleBT v3.0 Add support to the BTM driver for non-CC1111 interrupts Add HW flow control to STM serial driver Signed-off-by: Keith Packard --- src/Makefile | 3 +- src/drivers/ao_btm.c | 52 ++++++++- src/kernel/ao_serial.h | 12 ++ src/stm/ao_led.c | 2 +- src/stm/ao_serial_stm.c | 59 +++++++++- src/telebt-v3.0/ao_pins.h | 202 +++++++++++++++++++++++++++++++++ src/telebt-v3.0/ao_telebt.c | 57 ++++++++++ src/telebt-v3.0/flash-loader/ao_pins.h | 34 ++++++ 8 files changed, 410 insertions(+), 11 deletions(-) create mode 100644 src/telebt-v3.0/ao_pins.h create mode 100644 src/telebt-v3.0/ao_telebt.c create mode 100644 src/telebt-v3.0/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index a5d7b0f3..c8563c9d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -36,7 +36,8 @@ ARMM3DIRS=\ telelco-v0.2 telelco-v0.2/flash-loader \ telescience-v0.2 telescience-v0.2/flash-loader \ teledongle-v1.9 teledongle-v1.9/flash-loader \ - teleballoon-v2.0 + teleballoon-v2.0 \ + telebt-v3.0 telebt-v3.0/flash-loader ARMM0DIRS=\ easymini-v1.0 easymini-v1.0/flash-loader diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 3b6028a0..9ea638ba 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -16,13 +16,16 @@ */ #include "ao.h" +#ifdef AO_BTM_INT_PORT +#include +#endif #ifndef ao_serial_btm_getchar #define ao_serial_btm_putchar ao_serial1_putchar #define _ao_serial_btm_pollchar _ao_serial1_pollchar +#define _ao_serial_btm_sleep() ao_sleep((void *) &ao_serial1_rx_fifo) #define ao_serial_btm_set_speed ao_serial1_set_speed #define ao_serial_btm_drain ao_serial1_drain -#define ao_serial_btm_rx_fifo ao_serial1_rx_fifo #endif int8_t ao_btm_stdio; @@ -125,7 +128,7 @@ ao_btm_getchar(void) ao_arch_block_interrupts(); while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) { ao_alarm(AO_MS_TO_TICKS(10)); - c = ao_sleep(&ao_serial_btm_rx_fifo); + c = _ao_serial_btm_sleep(); ao_clear_alarm(); if (c) { c = AO_READ_AGAIN; @@ -146,6 +149,7 @@ ao_btm_get_line(void) { uint8_t ao_btm_reply_len = 0; int c; + uint8_t l; while ((c = ao_btm_getchar()) != AO_READ_AGAIN) { ao_btm_log_in_char(c); @@ -154,8 +158,8 @@ ao_btm_get_line(void) if (c == '\r' || c == '\n') break; } - for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) - ao_btm_reply[c++] = '\0'; + for (l = ao_btm_reply_len; l < sizeof (ao_btm_reply);) + ao_btm_reply[l++] = '\0'; return ao_btm_reply_len; } @@ -214,7 +218,7 @@ ao_btm_string(__code char *cmd) { char c; - while (c = *cmd++) + while ((c = *cmd++) != '\0') ao_btm_putchar(c); } @@ -263,6 +267,12 @@ ao_btm_try_speed(uint8_t speed) void ao_btm(void) { +#ifdef AO_BTM_RESET_PORT + ao_gpio_set(AO_BTM_RESET_PORT, AO_BTM_RESET_PIN, AO_BTM_RESET, 0); + ao_delay(AO_MS_TO_TICKS(20)); + ao_gpio_set(AO_BTM_RESET_PORT, AO_BTM_RESET_PIN, AO_BTM_RESET, 1); +#endif + /* * Wait for the bluetooth device to boot */ @@ -316,6 +326,7 @@ __xdata struct ao_task ao_btm_task; #define BT_PDIR P2DIR #define BT_PINP P2INP #define BT_IEN2_PIE IEN2_P2IE +#define BT_CC1111 1 #endif #if BT_LINK_ON_P1 #define BT_PICTL_ICON PICTL_P1ICON @@ -323,11 +334,13 @@ __xdata struct ao_task ao_btm_task; #define BT_PDIR P1DIR #define BT_PINP P1INP #define BT_IEN2_PIE IEN2_P1IE +#define BT_CC1111 1 #endif void ao_btm_check_link() { +#if BT_CC1111 ao_arch_critical( /* Check the pin and configure the interrupt detector to wait for the * pin to flip the other way @@ -340,8 +353,10 @@ ao_btm_check_link() PICTL &= ~BT_PICTL_ICON; } ); +#endif } +#if BT_CC1111 void ao_btm_isr(void) #if BT_LINK_ON_P1 @@ -357,6 +372,16 @@ ao_btm_isr(void) } BT_PIFG = 0; } +#endif + +#ifdef AO_BTM_INT_PORT +void +ao_btm_isr(void) +{ + ao_btm_check_link(); + ao_wakeup(&ao_btm_connected); +} +#endif void ao_btm_init (void) @@ -365,6 +390,18 @@ ao_btm_init (void) ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); +#ifdef AO_BTM_RESET_PORT + ao_enable_output(AO_BTM_RESET_PORT,AO_BTM_RESET_PIN,AO_BTM_RESET,0); +#endif + +#ifdef AO_BTM_INT_PORT + ao_enable_port(AO_BTM_INT_PORT); + ao_exti_setup(AO_BTM_INT_PORT, AO_BTM_INT_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_LOW, + ao_btm_isr); +#endif + +#if BT_CC1111 #if BT_LINK_ON_P1 /* * Configure ser reset line @@ -386,10 +423,15 @@ ao_btm_init (void) /* Enable interrupts */ IEN2 |= BT_IEN2_PIE; +#endif /* Check current pin state */ ao_btm_check_link(); +#ifdef AO_BTM_INT_PORT + ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN); +#endif + #if BT_LINK_ON_P2 /* Eable the pin interrupt */ PICTL |= PICTL_P2IEN; diff --git a/src/kernel/ao_serial.h b/src/kernel/ao_serial.h index baf213c0..dbc9f8e4 100644 --- a/src/kernel/ao_serial.h +++ b/src/kernel/ao_serial.h @@ -34,6 +34,9 @@ ao_serial0_getchar(void); int _ao_serial0_pollchar(void); +uint8_t +_ao_serial0_sleep(void); + void ao_serial0_putchar(char c); @@ -54,6 +57,9 @@ ao_serial1_getchar(void); int _ao_serial1_pollchar(void); +uint8_t +_ao_serial1_sleep(void); + void ao_serial1_putchar(char c); @@ -74,6 +80,9 @@ ao_serial2_getchar(void); int _ao_serial2_pollchar(void); +uint8_t +_ao_serial2_sleep(void); + void ao_serial2_putchar(char c); @@ -94,6 +103,9 @@ ao_serial3_getchar(void); int _ao_serial3_pollchar(void); +uint8_t +_ao_serial3_sleep(void); + void ao_serial3_putchar(char c); diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c index 0acab106..9b61cf62 100644 --- a/src/stm/ao_led.c +++ b/src/stm/ao_led.c @@ -86,7 +86,7 @@ ao_led_for(uint16_t colors, uint16_t ticks) __reentrant stm_moder_set(port, bit, STM_MODER_OUTPUT); \ stm_otyper_set(port, bit, STM_OTYPER_PUSH_PULL); \ } while (0) - + void ao_led_init(uint16_t enable) { diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 2133c584..e356b944 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -63,7 +63,7 @@ int _ao_usart_pollchar(struct ao_stm_usart *usart) { int c; - + if (ao_fifo_empty(usart->rx_fifo)) c = AO_READ_AGAIN; else { @@ -85,6 +85,12 @@ ao_usart_getchar(struct ao_stm_usart *usart) return (char) c; } +static inline uint8_t +_ao_usart_sleep(struct ao_stm_usart *usart) +{ + return ao_sleep(&usart->rx_fifo); +} + void ao_usart_putchar(struct ao_stm_usart *usart, char c) { @@ -179,6 +185,13 @@ ao_usart_init(struct ao_stm_usart *usart) ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); } +void +ao_usart_set_flow(struct ao_stm_usart *usart) +{ + usart->reg->cr3 |= ((1 << STM_USART_CR3_CTSE) | + (1 << STM_USART_CR3_RTSE)); +} + #if HAS_SERIAL_1 struct ao_stm_usart ao_stm_usart1; @@ -203,6 +216,18 @@ _ao_serial1_pollchar(void) return _ao_usart_pollchar(&ao_stm_usart1); } +uint8_t +_ao_serial1_sleep(void) +{ + return _ao_usart_sleep(&ao_stm_usart1); +} + +void +ao_serial1_drain(void) +{ + ao_usart_drain(&ao_stm_usart1); +} + void ao_serial1_set_speed(uint8_t speed) { @@ -234,6 +259,18 @@ _ao_serial2_pollchar(void) return _ao_usart_pollchar(&ao_stm_usart2); } +uint8_t +_ao_serial2_sleep(void) +{ + return _ao_usart_sleep(&ao_stm_usart2); +} + +void +ao_serial2_drain(void) +{ + ao_usart_drain(&ao_stm_usart2); +} + void ao_serial2_set_speed(uint8_t speed) { @@ -265,6 +302,12 @@ _ao_serial3_pollchar(void) return _ao_usart_pollchar(&ao_stm_usart3); } +uint8_t +_ao_serial3_sleep(void) +{ + return _ao_usart_sleep(&ao_stm_usart3); +} + void ao_serial3_set_speed(uint8_t speed) { @@ -324,21 +367,31 @@ ao_serial_init(void) stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); +#if USE_SERIAL_2_FLOW + stm_afr_set(&stm_gpioa, 0, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 1, STM_AFR_AF7); +#endif #else #if SERIAL_2_PD5_PD6 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); stm_afr_set(&stm_gpiod, 5, STM_AFR_AF7); stm_afr_set(&stm_gpiod, 6, STM_AFR_AF7); +#if USE_SERIAL_2_FLOW +#error "Don't know how to set flowcontrol for serial 2 on PD" +#endif #else #error "No SERIAL_2 port configuration specified" -#endif +#endif #endif /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); ao_stm_usart2.reg = &stm_usart2; ao_usart_init(&ao_stm_usart2); +#if USE_SERIAL_2_FLOW + ao_usart_set_flow(&ao_stm_usart2); +#endif stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, 4); @@ -393,5 +446,3 @@ ao_serial_init(void) #endif #endif } - - diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h new file mode 100644 index 00000000..0d03f94d --- /dev/null +++ b/src/telebt-v3.0/ao_pins.h @@ -0,0 +1,202 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE 1 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1 0 +#define USE_SERIAL_1_STDIN 0 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 1 + +#define HAS_SERIAL_2 1 +#define USE_SERIAL_2_STDIN 0 +#define USE_SERIAL_2_FLOW 1 +#define SERIAL_2_PA2_PA3 1 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 1 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 1 +#define SERIAL_3_PC10_PC11 0 +#define SERIAL_3_PD8_PD9 0 + +#define AO_CONFIG_MAX_SIZE 1024 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_BATTERY_REPORT 0 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 0 +#define HAS_APRS 0 +#define HAS_ACCEL 0 + +#define HAS_SPI_1 1 +#define SPI_1_PA5_PA6_PA7 1 /* CC1200 */ +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_SPI_2 0 +#define SPI_2_PB13_PB14_PB15 0 +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_I2C_1 0 +#define I2C_1_PB8_PB9 0 + +#define HAS_I2C_2 0 +#define I2C_2_PB10_PB11 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 1 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_0_ENABLE STM_RCC_AHBENR_GPIOAEN +#define LED_PORT_1_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT_0 (&stm_gpioa) +#define LED_PORT_1 (&stm_gpioc) +#define LED_PORT_0_SHIFT 0 +#define LED_PORT_1_SHIFT 0 +#define LED_PIN_RED (4 + LED_PORT_0_SHIFT) +#define LED_PIN_BLUE (15 + LED_PORT_1_SHIFT) +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_BLUE (1 << LED_PIN_BLUE) +#define LED_PORT_0_MASK (AO_LED_RED) +#define LED_PORT_1_MASK (AO_LED_BLUE) +#define AO_BT_LED AO_LED_BLUE + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_BLUE) + +#define HAS_GPS 0 +#define HAS_FLIGHT 0 +#define HAS_ADC 1 +#define HAS_ADC_TEMP 0 +#define HAS_LOG 0 + +/* + * ADC + */ +#define AO_DATA_RING 32 +#define AO_ADC_NUM_SENSE 2 + +struct ao_adc { + int16_t v_batt; +}; + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u %5d batt: %5d\n", \ + (p)->tick, \ + (p)->adc.v_batt); + +#define AO_ADC_V_BATT 8 +#define AO_ADC_V_BATT_PORT (&stm_gpiob) +#define AO_ADC_V_BATT_PIN 0 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOEEN)) + +#define AO_NUM_ADC_PIN 1 + +#define AO_ADC_PIN0_PORT AO_ADC_V_BATT_PORT +#define AO_ADC_PIN0_PIN AO_ADC_V_BATT_PIN + +#define AO_NUM_ADC (AO_NUM_ADC_PIN) + +#define AO_ADC_SQ1 AO_ADC_V_BATT + +/* + * Voltage divider on ADC battery sampler + */ +#define AO_BATTERY_DIV_PLUS 51 /* 5.6k */ +#define AO_BATTERY_DIV_MINUS 100 /* 10k */ + +/* + * ADC reference in decivolts + */ +#define AO_ADC_REFERENCE_DV 33 + +/* + * BTM + */ +#define HAS_BTM 1 + +#define ao_serial_btm_getchar ao_serial2_getchar +#define ao_serial_btm_putchar ao_serial2_putchar +#define _ao_serial_btm_pollchar _ao_serial2_pollchar +#define _ao_serial_btm_sleep _ao_serial2_sleep +#define ao_serial_btm_set_speed ao_serial2_set_speed +#define ao_serial_btm_drain ao_serial2_drain +#define ao_serial_btm_rx_fifo ao_serial2_rx_fifo + +#define AO_BTM_INT_PORT (&stm_gpioa) +#define AO_BTM_INT_PIN 15 +#define AO_BTM_RESET_PORT (&stm_gpiob) +#define AO_BTM_RESET_PIN 3 + +/* + * Radio (cc1200) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x6ca333 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpiob) +#define AO_CC1200_SPI_CS_PIN 10 +#define AO_CC1200_SPI_BUS AO_SPI_1_PA5_PA6_PA7 +#define AO_CC1200_SPI stm_spi1 + +#define AO_CC1200_INT_PORT (&stm_gpiob) +#define AO_CC1200_INT_PIN (11) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#define HAS_BOOT_RADIO 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c new file mode 100644 index 00000000..f3906e3f --- /dev/null +++ b/src/telebt-v3.0/ao_telebt.c @@ -0,0 +1,57 @@ +/* + * 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 +#include +#include +#include +#include +#if HAS_SAMPLE_PROFILE +#include +#endif + +int +main(void) +{ + ao_clock_init(); + + ao_task_init(); + ao_serial_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_adc_init(); + ao_btm_init(); + ao_cmd_init(); + + ao_eeprom_init(); + + ao_usb_init(); + ao_radio_init(); + ao_packet_master_init(); + + ao_config_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/telebt-v3.0/flash-loader/ao_pins.h b/src/telebt-v3.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..8711548d --- /dev/null +++ b/src/telebt-v3.0/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +/* Blue LED */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioc +#define AO_BOOT_APPLICATION_PIN 15 +#define AO_BOOT_APPLICATION_VALUE 0 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_DOWN + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 02f03df6d089cafae99f8ce15dcbd87f6e78d749 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Jan 2015 16:42:39 -0800 Subject: altos: Initial STMF04x support Basic clock configuration, OS support, LED and USB drivers. Signed-off-by: Keith Packard --- src/stmf0/Makefile-stmf0.defs | 47 + src/stmf0/Makefile.defs | 9 + src/stmf0/altos.ld | 97 ++ src/stmf0/ao_arch.h | 157 ++++ src/stmf0/ao_arch_funcs.h | 398 ++++++++ src/stmf0/ao_boot_chain.c | 67 ++ src/stmf0/ao_boot_pin.c | 46 + src/stmf0/ao_interrupt.c | 167 ++++ src/stmf0/ao_led.c | 125 +++ src/stmf0/ao_romconfig.c | 27 + src/stmf0/ao_timer.c | 262 ++++++ src/stmf0/ao_usb_stm.c | 1090 ++++++++++++++++++++++ src/stmf0/registers.ld | 60 ++ src/stmf0/stm32f0.h | 1995 +++++++++++++++++++++++++++++++++++++++++ 14 files changed, 4547 insertions(+) create mode 100644 src/stmf0/Makefile-stmf0.defs create mode 100644 src/stmf0/Makefile.defs create mode 100644 src/stmf0/altos.ld create mode 100644 src/stmf0/ao_arch.h create mode 100644 src/stmf0/ao_arch_funcs.h create mode 100644 src/stmf0/ao_boot_chain.c create mode 100644 src/stmf0/ao_boot_pin.c create mode 100644 src/stmf0/ao_interrupt.c create mode 100644 src/stmf0/ao_led.c create mode 100644 src/stmf0/ao_romconfig.c create mode 100644 src/stmf0/ao_timer.c create mode 100644 src/stmf0/ao_usb_stm.c create mode 100644 src/stmf0/registers.ld create mode 100644 src/stmf0/stm32f0.h (limited to 'src') diff --git a/src/stmf0/Makefile-stmf0.defs b/src/stmf0/Makefile-stmf0.defs new file mode 100644 index 00000000..4862f46e --- /dev/null +++ b/src/stmf0/Makefile-stmf0.defs @@ -0,0 +1,47 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +include $(TOPDIR)/Makedefs + +vpath % $(TOPDIR)/stmf0:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/kernel:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR):$(TOPDIR)/math +vpath make-altitude $(TOPDIR)/util +vpath make-kalman $(TOPDIR)/util +vpath kalman.5c $(TOPDIR)/kalman +vpath kalman_filter.5c $(TOPDIR)/kalman +vpath load_csv.5c $(TOPDIR)/kalman +vpath matrix.5c $(TOPDIR)/kalman +vpath ao-make-product.5c $(TOPDIR)/util + +.SUFFIXES: .elf .ihx + +.elf.ihx: + $(ELFTOHEX) --output=$@ $*.elf + +ifndef VERSION +include $(TOPDIR)/Version +endif + +ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex +CC=$(ARM_CC) + +WARN_FLAGS=-Wall -Wextra -Werror + +AO_CFLAGS=-I. -I$(TOPDIR)/stmf0 -I$(TOPDIR)/kernel -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -I$(TOPDIR)/math $(PDCLIB_INCLUDES) +STMF0_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb\ + -ffreestanding -nostdlib $(AO_CFLAGS) $(WARN_FLAGS) + +NICKLE=nickle + +LIBS=$(PDCLIB_LIBS_M0) -lgcc + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: + $(call quiet,CC) -c $(CFLAGS) -o $@ $< diff --git a/src/stmf0/Makefile.defs b/src/stmf0/Makefile.defs new file mode 100644 index 00000000..a1d93eb5 --- /dev/null +++ b/src/stmf0/Makefile.defs @@ -0,0 +1,9 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +include $(TOPDIR)/stmf0/Makefile-stmf0.defs + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos.ld + +.DEFAULT_GOAL=all diff --git a/src/stmf0/altos.ld b/src/stmf0/altos.ld new file mode 100644 index 00000000..6672c1fd --- /dev/null +++ b/src/stmf0/altos.ld @@ -0,0 +1,97 @@ +/* + * 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. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 5632 + stack (!w) : ORIGIN = 0x20001600, 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/stmf0/ao_arch.h b/src/stmf0/ao_arch.h new file mode 100644 index 00000000..6ee71ef9 --- /dev/null +++ b/src/stmf0/ao_arch.h @@ -0,0 +1,157 @@ +/* + * 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. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include +#include + +/* + * STM32F0 definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 512 + +#define AO_LED_TYPE uint16_t + +#ifndef AO_TICK_TYPE +#define AO_TICK_TYPE uint16_t +#define AO_TICK_SIGNED int16_t +#endif + +#define AO_PORT_TYPE uint16_t + +/* Various definitions to make GCC look more like SDCC */ + +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __interrupt(n) +#define __at(n) + +#define ao_arch_reboot() \ + (stm_scb.aircr = ((STM_SCB_AIRCR_VECTKEY_KEY << STM_SCB_AIRCR_VECTKEY) | \ + (1 << STM_SCB_AIRCR_SYSRESETREQ))) + +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); +extern void ao_avr_stdio_init(void); + + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const + +extern const uint16_t ao_romconfig_version; +extern const uint16_t ao_romconfig_check; +extern const uint16_t ao_serial_number; +extern const uint32_t ao_radio_cal; + +#define ao_arch_task_members\ + uint32_t *sp; /* saved stack pointer */ + +#define ao_arch_block_interrupts() asm("cpsid i") +#define ao_arch_release_interrupts() asm("cpsie i") + +/* + * ao_timer.c + * + * For the stm32f042, we want to use the USB-based HSI48 clock + */ + +#if AO_HSI48 + +#define AO_SYSCLK 48000000 +#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) + +#endif + +#if AO_HSE || AO_HSI + +#if AO_HSE +#define AO_PLLSRC AO_HSE +#else +#define AO_PLLSRC STM_HSI_FREQ +#endif + +#define AO_PLLVCO (AO_PLLSRC * AO_PLLMUL) +#define AO_SYSCLK (AO_PLLVCO / AO_PLLDIV) + +#endif + +#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) +#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) +#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) +#define AO_SYSTICK (AO_HCLK) + +#if AO_APB1_PRESCALER == 1 +#define AO_TIM23467_CLK AO_PCLK1 +#else +#define AO_TIM23467_CLK (2 * AO_PCLK1) +#endif + +#if AO_APB2_PRESCALER == 1 +#define AO_TIM91011_CLK AO_PCLK2 +#else +#define AO_TIM91011_CLK (2 * AO_PCLK2) +#endif + +#define AO_STM_NVIC_HIGH_PRIORITY 4 +#define AO_STM_NVIC_CLOCK_PRIORITY 6 +#define AO_STM_NVIC_MED_PRIORITY 8 +#define AO_STM_NVIC_LOW_PRIORITY 10 + +void ao_lcd_stm_init(void); + +void ao_lcd_font_init(void); + +void ao_lcd_font_string(char *s); + +extern const uint32_t ao_radio_cal; + +void +ao_adc_init(); + +/* ADC maximum reported value */ +#define AO_ADC_MAX 4095 + +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x08001000) +#define AO_BOOT_APPLICATION_BOUND ((uint32_t *) (0x08000000 + stm_flash_size())) +#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x08000000) +#define HAS_BOOT_LOADER 1 + +#endif /* _AO_ARCH_H_ */ + + diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h new file mode 100644 index 00000000..2f2f8f43 --- /dev/null +++ b/src/stmf0/ao_arch_funcs.h @@ -0,0 +1,398 @@ +/* + * 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. + */ + +#ifndef _AO_ARCH_FUNCS_H_ +#define _AO_ARCH_FUNCS_H_ + +/* ao_spi_stm.c + */ + +/* PCLK is set to 16MHz (HCLK 32MHz, APB prescaler 2) */ + +#define AO_SPI_SPEED_8MHz STM_SPI_CR1_BR_PCLK_2 +#define AO_SPI_SPEED_4MHz STM_SPI_CR1_BR_PCLK_4 +#define AO_SPI_SPEED_2MHz STM_SPI_CR1_BR_PCLK_8 +#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 +#define AO_SPI_SPEED_500kHz STM_SPI_CR1_BR_PCLK_32 +#define AO_SPI_SPEED_250kHz STM_SPI_CR1_BR_PCLK_64 +#define AO_SPI_SPEED_125kHz STM_SPI_CR1_BR_PCLK_128 +#define AO_SPI_SPEED_62500Hz STM_SPI_CR1_BR_PCLK_256 + +#define AO_SPI_SPEED_FAST AO_SPI_SPEED_8MHz + +/* Companion bus wants something no faster than 200kHz */ + +#define AO_SPI_SPEED_200kHz AO_SPI_SPEED_125kHz + +#define AO_SPI_CONFIG_1 0x00 +#define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1 +#define AO_SPI_2_CONFIG_PB13_PB14_PB15 AO_SPI_CONFIG_1 + +#define AO_SPI_CONFIG_2 0x04 +#define AO_SPI_1_CONFIG_PB3_PB4_PB5 AO_SPI_CONFIG_2 +#define AO_SPI_2_CONFIG_PD1_PD3_PD4 AO_SPI_CONFIG_2 + +#define AO_SPI_CONFIG_3 0x08 +#define AO_SPI_1_CONFIG_PE13_PE14_PE15 AO_SPI_CONFIG_3 + +#define AO_SPI_CONFIG_NONE 0x0c + +#define AO_SPI_INDEX_MASK 0x01 +#define AO_SPI_CONFIG_MASK 0x0c + +#define AO_SPI_1_PA5_PA6_PA7 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA5_PA6_PA7) +#define AO_SPI_1_PB3_PB4_PB5 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PB3_PB4_PB5) +#define AO_SPI_1_PE13_PE14_PE15 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PE13_PE14_PE15) + +#define AO_SPI_2_PB13_PB14_PB15 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PB13_PB14_PB15) +#define AO_SPI_2_PD1_PD3_PD4 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PD1_PD3_PD4) + +#define AO_SPI_INDEX(id) ((id) & AO_SPI_INDEX_MASK) +#define AO_SPI_CONFIG(id) ((id) & AO_SPI_CONFIG_MASK) + +uint8_t +ao_spi_try_get(uint8_t spi_index, uint32_t speed, uint8_t task_id); + +void +ao_spi_get(uint8_t spi_index, uint32_t speed); + +void +ao_spi_put(uint8_t spi_index); + +void +ao_spi_send(const void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); + +void +ao_spi_send_sync(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); + +extern uint16_t ao_spi_speed[STM_NUM_SPI]; + +void +ao_spi_init(void); + +#define ao_spi_set_cs(reg,mask) ((reg)->bsrr = ((uint32_t) (mask)) << 16) +#define ao_spi_clr_cs(reg,mask) ((reg)->bsrr = (mask)) + +#define ao_spi_get_mask(reg,mask,bus, speed) do { \ + ao_spi_get(bus, speed); \ + ao_spi_set_cs(reg,mask); \ + } while (0) + +static inline uint8_t +ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t speed, uint8_t task_id) +{ + if (!ao_spi_try_get(bus, speed, task_id)) + return 0; + ao_spi_set_cs(reg, mask); + return 1; +} + +#define ao_spi_put_mask(reg,mask,bus) do { \ + ao_spi_clr_cs(reg,mask); \ + ao_spi_put(bus); \ + } while (0) + +#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<stack + AO_STACK_SIZE); + uint32_t a = (uint32_t) start; + int i; + + /* Return address (goes into LR) */ + ARM_PUSH32(sp, a); + + /* Clear register values r0-r7 */ + i = 8; + while (i--) + ARM_PUSH32(sp, 0); + + /* APSR */ + ARM_PUSH32(sp, 0); + + /* PRIMASK with interrupts enabled */ + ARM_PUSH32(sp, 0); + + task->sp = sp; +} + +static inline void ao_arch_save_regs(void) { + /* Save general registers */ + asm("push {r0-r7,lr}\n"); + + /* Save APSR */ + asm("mrs r0,apsr"); + asm("push {r0}"); + + /* Save PRIMASK */ + asm("mrs r0,primask"); + asm("push {r0}"); +} + +static inline void ao_arch_save_stack(void) { + uint32_t *sp; + asm("mov %0,sp" : "=&r" (sp) ); + ao_cur_task->sp = (sp); + if ((uint8_t *) sp < &ao_cur_task->stack[0]) + ao_panic (AO_PANIC_STACK); +} + +static inline void ao_arch_restore_stack(void) { + uint32_t sp; + sp = (uint32_t) ao_cur_task->sp; + + /* Switch stacks */ + asm("mov sp, %0" : : "r" (sp) ); + + /* Restore PRIMASK */ + asm("pop {r0}"); + asm("msr primask,r0"); + + /* Restore APSR */ + asm("pop {r0}"); + asm("msr apsr_nczvq,r0"); + + /* Restore general registers */ + asm("pop {r0-r7,pc}\n"); +} + +#ifndef HAS_SAMPLE_PROFILE +#define HAS_SAMPLE_PROFILE 0 +#endif + +#if !HAS_SAMPLE_PROFILE +#define HAS_ARCH_START_SCHEDULER 1 + +static inline void ao_arch_start_scheduler(void) { + uint32_t sp; + uint32_t control; + + asm("mrs %0,msp" : "=&r" (sp)); + asm("msr psp,%0" : : "r" (sp)); + asm("mrs %0,control" : "=&r" (control)); + control |= (1 << 1); + asm("msr control,%0" : : "r" (control)); + asm("isb"); +} +#endif + +#define ao_arch_isr_stack() + +#endif + +#define ao_arch_wait_interrupt() do { \ + asm("\twfi\n"); \ + ao_arch_release_interrupts(); \ + asm(".global ao_idle_loc\nao_idle_loc:"); \ + ao_arch_block_interrupts(); \ + } while (0) + +#define ao_arch_critical(b) do { \ + uint32_t __mask = ao_arch_irqsave(); \ + do { b } while (0); \ + ao_arch_irqrestore(__mask); \ + } while (0) + +void +ao_clock_enable_crs(void); + +void +ao_clock_disable_crs(void); + +#endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stmf0/ao_boot_chain.c b/src/stmf0/ao_boot_chain.c new file mode 100644 index 00000000..bcebf033 --- /dev/null +++ b/src/stmf0/ao_boot_chain.c @@ -0,0 +1,67 @@ +/* + * 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. + */ + +#include +#include + +void +ao_boot_chain(uint32_t *base) +{ + uint32_t sp; + uint32_t pc; + + sp = base[0]; + pc = base[1]; + if (0x08000100 <= pc && pc <= 0x08200000 && (pc & 1) == 1) { + asm ("mov sp, %0" : : "r" (sp)); + asm ("mov lr, %0" : : "r" (pc)); + asm ("bx lr"); + } +} + +#define AO_BOOT_SIGNAL 0x5a5aa5a5 +#define AO_BOOT_CHECK 0xc3c33c3c + +struct ao_boot { + uint32_t *base; + uint32_t signal; + uint32_t check; +}; + +static struct ao_boot __attribute__ ((section(".boot"))) ao_boot; + +int +ao_boot_check_chain(void) +{ + if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) { + ao_boot.signal = 0; + ao_boot.check = 0; + if (ao_boot.base == AO_BOOT_FORCE_LOADER) + return 0; + ao_boot_chain(ao_boot.base); + } + return 1; +} + +void +ao_boot_reboot(uint32_t *base) +{ + ao_boot.base = base; + ao_boot.signal = AO_BOOT_SIGNAL; + ao_boot.check = AO_BOOT_CHECK; + ao_arch_reboot(); +} diff --git a/src/stmf0/ao_boot_pin.c b/src/stmf0/ao_boot_pin.c new file mode 100644 index 00000000..e825b618 --- /dev/null +++ b/src/stmf0/ao_boot_pin.c @@ -0,0 +1,46 @@ +/* + * 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. + */ + +#include +#include +#include + +void +ao_boot_check_pin(void) +{ + uint16_t v; + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Enable the input pin */ + ao_enable_input(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, + AO_BOOT_APPLICATION_MODE); + + for (v = 0; v < 100; v++) + ao_arch_nop(); + + /* Read the value */ + v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN); + + /* Reset the chip to turn off the port and the power interface clock */ + ao_gpio_set_mode(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0); + ao_disable_port(&AO_BOOT_APPLICATION_GPIO); + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); + if (v == AO_BOOT_APPLICATION_VALUE) + ao_boot_chain(AO_BOOT_APPLICATION_BASE); +} diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c new file mode 100644 index 00000000..99a88dcb --- /dev/null +++ b/src/stmf0/ao_interrupt.c @@ -0,0 +1,167 @@ +/* + * 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 +#include "stm32f0.h" +#include +#include + +extern void main(void); +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +/* Interrupt functions */ + +void stm_halt_isr(void) +{ + ao_panic(AO_PANIC_CRASH); +} + +void stm_ignore_isr(void) +{ +} + +const void *stm_interrupt_vector[]; + +uint32_t +stm_flash_size(void) { + uint16_t dev_id = stm_dev_id(); + uint16_t kbytes = 0; + + switch (dev_id) { + case 0x445: + kbytes = 32; /* assume 32kB until we figure this out */ + break; + } + return (uint32_t) kbytes * 1024; +} + +void start(void) +{ +#if 0 +#ifdef AO_BOOT_CHAIN + if (ao_boot_check_chain()) { +#ifdef AO_BOOT_PIN + ao_boot_check_pin(); +#endif + } +#endif +#endif + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +#define STRINGIFY(x) #x + +#define isr(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr)) + +#define isr_halt(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr)) + +isr(nmi) +isr_halt(hardfault) +isr_halt(memmanage) +isr_halt(busfault) +isr_halt(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(rtc) +isr(flash) +isr(rcc_crs) +isr(exti0_1) +isr(exti2_3) +isr(exti4_15) +isr(tsc) +isr(dma_ch1) +isr(dma_ch2_3_dma2_ch1_2) +isr(dma_ch4_5_6_7_dma2_ch3_4_5) +isr(adc_comp) +isr(tim1_brk_up_trg_com) +isr(tim1_cc) +isr(tim2) +isr(tim3) +isr(tim6_dac) +isr(tim7) +isr(tim14) +isr(tim15) +isr(tim16) +isr(tim17) +isr(i2c1) +isr(i2c2) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3_4_5_6_7_8) +isr(cec_can) +isr(usb) + +#define i(addr,name) [(addr)/4] = stm_ ## name ## _isr + +__attribute__ ((section(".interrupt"))) +const void *stm_interrupt_vector[] = { + [0] = &__stack__, + [1] = start, + i(0x08, nmi), + i(0x0c, hardfault), + i(0x2c, svc), + i(0x30, debugmon), + i(0x38, pendsv), + i(0x3c, systick), + i(0x40, wwdg), /* IRQ0 */ + i(0x44, pvd), + i(0x48, rtc), + i(0x4c, flash), + i(0x50, rcc_crs), + i(0x54, exti0_1), + i(0x58, exti2_3), + i(0x5c, exti4_15), + i(0x60, tsc), + i(0x64, dma_ch1), + i(0x68, dma_ch2_3_dma2_ch1_2), + i(0x6c, dma_ch4_5_6_7_dma2_ch3_4_5), + i(0x70, adc_comp), + i(0x74, tim1_brk_up_trg_com), + i(0x78, tim1_cc), + i(0x7c, tim2), + i(0x80, tim3), + i(0x84, tim6_dac), + i(0x88, tim7), + i(0x8c, tim14), + i(0x90, tim15), + i(0x94, tim16), + i(0x98, tim17), + i(0x9c, i2c1), + i(0xa0, i2c2), + i(0xa4, spi1), + i(0xa8, spi2), + i(0xac, usart1), + i(0xb0, usart2), + i(0xb4, usart3_4_5_6_7_8), + i(0xb8, cec_can), + i(0xbc, usb), +}; diff --git a/src/stmf0/ao_led.c b/src/stmf0/ao_led.c new file mode 100644 index 00000000..9b61cf62 --- /dev/null +++ b/src/stmf0/ao_led.c @@ -0,0 +1,125 @@ +/* + * 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" + +__pdata uint16_t ao_led_enable; + +void +ao_led_on(uint16_t colors) +{ +#ifdef LED_PORT + LED_PORT->bsrr = (colors & ao_led_enable); +#else +#ifdef LED_PORT_0 + LED_PORT_0->bsrr = ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; +#endif +#ifdef LED_PORT_1 + LED_PORT_1->bsrr = ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; +#endif +#endif +} + +void +ao_led_off(uint16_t colors) +{ +#ifdef LED_PORT + LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16; +#else +#ifdef LED_PORT_0 + LED_PORT_0->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_0_MASK) << (LED_PORT_0_SHIFT + 16); +#endif +#ifdef LED_PORT_1 + LED_PORT_1->bsrr = ((uint32_t) (colors & ao_led_enable) & LED_PORT_1_MASK) << (LED_PORT_1_SHIFT + 16); +#endif +#endif +} + +void +ao_led_set(uint16_t colors) +{ + uint16_t on = colors & ao_led_enable; + uint16_t off = ~colors & ao_led_enable; + + ao_led_off(off); + ao_led_on(on); +} + +void +ao_led_toggle(uint16_t colors) +{ +#ifdef LED_PORT + LED_PORT->odr ^= (colors & ao_led_enable); +#else +#ifdef LED_PORT_0 + LED_PORT_0->odr ^= ((colors & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; +#endif +#ifdef LED_PORT_1 + LED_PORT_1->odr ^= ((colors & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; +#endif +#endif +} + +void +ao_led_for(uint16_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +#define init_led_pin(port, bit) do { \ + stm_moder_set(port, bit, STM_MODER_OUTPUT); \ + stm_otyper_set(port, bit, STM_OTYPER_PUSH_PULL); \ + } while (0) + +void +ao_led_init(uint16_t enable) +{ + int bit; + + ao_led_enable = enable; +#ifdef LED_PORT + stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE); + LED_PORT->odr &= ~enable; +#else +#ifdef LED_PORT_0 + stm_rcc.ahbenr |= (1 << LED_PORT_0_ENABLE); + LED_PORT_0->odr &= ~((enable & ao_led_enable) & LED_PORT_0_MASK) << LED_PORT_0_SHIFT; +#endif +#ifdef LED_PORT_1 + stm_rcc.ahbenr |= (1 << LED_PORT_1_ENABLE); + LED_PORT_1->odr &= ~((enable & ao_led_enable) & LED_PORT_1_MASK) << LED_PORT_1_SHIFT; +#endif +#endif + for (bit = 0; bit < 16; bit++) { + if (enable & (1 << bit)) { +#ifdef LED_PORT + init_led_pin(LED_PORT, bit); +#else +#ifdef LED_PORT_0 + if (LED_PORT_0_MASK & (1 << bit)) + init_led_pin(LED_PORT_0, bit + LED_PORT_0_SHIFT); +#endif +#ifdef LED_PORT_1 + if (LED_PORT_1_MASK & (1 << bit)) + init_led_pin(LED_PORT_1, bit + LED_PORT_1_SHIFT); +#endif +#endif + } + } +} diff --git a/src/stmf0/ao_romconfig.c b/src/stmf0/ao_romconfig.c new file mode 100644 index 00000000..5da15072 --- /dev/null +++ b/src/stmf0/ao_romconfig.c @@ -0,0 +1,27 @@ +/* + * 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 "ao.h" + +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; +#ifndef AO_RADIO_CAL_DEFAULT +#define AO_RADIO_CAL_DEFAULT 0x01020304 +#endif +AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; + diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c new file mode 100644 index 00000000..82a4cad6 --- /dev/null +++ b/src/stmf0/ao_timer.c @@ -0,0 +1,262 @@ +/* + * 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" +#include +#if HAS_FAKE_FLIGHT +#include +#endif + +#ifndef HAS_TICK +#define HAS_TICK 1 +#endif + +#if HAS_TICK +volatile AO_TICK_TYPE ao_tick_count; + +AO_TICK_TYPE +ao_time(void) +{ + return ao_tick_count; +} + +#if AO_DATA_ALL +volatile __data uint8_t ao_data_interval = 1; +volatile __data uint8_t ao_data_count; +#endif + +void stm_systick_isr(void) +{ + if (stm_systick.csr & (1 << STM_SYSTICK_CSR_COUNTFLAG)) { + ++ao_tick_count; +#if HAS_TASK_QUEUE + if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) + ao_task_check_alarm((uint16_t) ao_tick_count); +#endif +#if AO_DATA_ALL + if (++ao_data_count == ao_data_interval) { + ao_data_count = 0; +#if HAS_FAKE_FLIGHT + if (ao_fake_flight_active) + ao_fake_flight_poll(); + else +#endif + ao_adc_poll(); +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) + ao_wakeup((void *) &ao_data_count); +#endif + } +#endif +#ifdef AO_TIMER_HOOK + AO_TIMER_HOOK; +#endif + } +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) +{ + ao_arch_critical( + ao_data_interval = interval; + ao_data_count = 0; + ); +} +#endif + +#define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1) + +void +ao_timer_init(void) +{ + stm_systick.rvr = SYSTICK_RELOAD; + stm_systick.cvr = 0; + stm_systick.csr = ((1 << STM_SYSTICK_CSR_ENABLE) | + (1 << STM_SYSTICK_CSR_TICKINT) | + (STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 << STM_SYSTICK_CSR_CLKSOURCE)); +} + +#endif + +static void +ao_clock_enable_crs(void) +{ + /* Enable crs interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_CRSEN); + + /* Disable error counter */ + stm_crs.cr = ((stm_crs.cr & (1 << 4)) | + (32 << STM_CRS_CR_TRIM) | + (0 << STM_CRS_CR_SWSYNC) | + (0 << STM_CRS_CR_AUTOTRIMEN) | + (0 << STM_CRS_CR_CEN) | + (0 << STM_CRS_CR_ESYNCIE) | + (0 << STM_CRS_CR_ERRIE) | + (0 << STM_CRS_CR_SYNCWARNIE) | + (0 << STM_CRS_CR_SYNCOKIE)); + + /* Configure for USB source */ + stm_crs.cfgr = ((stm_crs.cfgr & ((1 << 30) | (1 << 27))) | + (0 << STM_CRS_CFGR_SYNCPOL) | + (STM_CRS_CFGR_SYNCSRC_USB << STM_CRS_CFGR_SYNCSRC) | + (STM_CRS_CFGR_SYNCDIV_1 << STM_CRS_CFGR_SYNCDIV) | + (0x22 << STM_CRS_CFGR_FELIM) | + (((48000000 / 1000) - 1) << STM_CRS_CFGR_RELOAD)); + + /* Enable error counter, set auto trim */ + stm_crs.cr = ((stm_crs.cr & (1 << 4)) | + (32 << STM_CRS_CR_TRIM) | + (0 << STM_CRS_CR_SWSYNC) | + (1 << STM_CRS_CR_AUTOTRIMEN) | + (1 << STM_CRS_CR_CEN) | + (0 << STM_CRS_CR_ESYNCIE) | + (0 << STM_CRS_CR_ERRIE) | + (0 << STM_CRS_CR_SYNCWARNIE) | + (0 << STM_CRS_CR_SYNCOKIE)); + +} + +void +ao_clock_init(void) +{ + uint32_t cfgr; + + /* Switch to HSI while messing about */ + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) + ao_arch_nop(); + + stm_rcc.cfgr = (stm_rcc.cfgr & ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW)) | + (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + + /* wait for system to switch to HSI */ + while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + ao_arch_nop(); + + /* reset the clock config, leaving us running on the HSI */ + stm_rcc.cfgr &= (uint32_t)0x0000000f; + + /* reset PLLON, CSSON, HSEBYP, HSEON */ + stm_rcc.cr &= 0x0000ffff; + + /* Disable all interrupts */ + stm_rcc.cir = 0; + +#if AO_HSE +#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSE +#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSE +#define STM_PLLSRC AO_HSE +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 1 + +#if AO_HSE_BYPASS + stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP); +#else + stm_rcc.cr &= ~(1 << STM_RCC_CR_HSEBYP); +#endif + /* Enable HSE clock */ + stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) + asm("nop"); +#endif + + +#if AO_HSI48 +#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSI48 +#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSI48 + + /* Turn HSI48 clock on */ + stm_rcc.cr2 |= (1 << STM_RCC_CR2_HSI48ON); + + /* Wait for clock to stabilize */ + while ((stm_rcc.cr2 & (1 << STM_RCC_CR2_HSI48RDY)) == 0) + ao_arch_nop(); + + ao_clock_enable_crs(); +#endif + +#ifndef STM_RCC_CFGR_SWS_TARGET_CLOCK +#define STM_HSI 16000000 +#define STM_RCC_CFGR_SWS_TARGET_CLOCK STM_RCC_CFGR_SWS_HSI +#define STM_RCC_CFGR_SW_TARGET_CLOCK STM_RCC_CFGR_SW_HSI +#define STM_PLLSRC STM_HSI +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK 0 +#endif + +#ifdef STM_PLLSRC +#error No code for PLL initialization yet +#endif + + /* Set flash latency to tolerate 48MHz SYSCLK -> 1 wait state */ + + /* Enable prefetch */ + stm_flash.acr |= (1 << STM_FLASH_ACR_PRFTBE); + + /* Enable 1 wait state so the CPU can run at 48MHz */ + stm_flash.acr |= (STM_FLASH_ACR_LATENCY_1 << STM_FLASH_ACR_LATENCY); + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* HCLK to 48MHz -> AHB prescaler = /1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE)) + ao_arch_nop(); + + /* APB Prescaler = AO_APB_PRESCALER */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE_MASK << STM_RCC_CFGR_PPRE); + cfgr |= (AO_RCC_CFGR_PPRE_DIV << STM_RCC_CFGR_PPRE); + stm_rcc.cfgr = cfgr; + + /* Switch to the desired system clock */ + + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_TARGET_CLOCK << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + for (;;) { + uint32_t c, part, mask, val; + + c = stm_rcc.cfgr; + mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); + val = (STM_RCC_CFGR_SWS_TARGET_CLOCK << STM_RCC_CFGR_SWS); + part = c & mask; + if (part == val) + break; + } + + /* Clear reset flags */ + stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); + +#if DEBUG_THE_CLOCK + /* Output SYSCLK on PA8 for measurments */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_afr_set(&stm_gpioa, 8, STM_AFR_AF0); + stm_moder_set(&stm_gpioa, 8, STM_MODER_ALTERNATE); + stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_40MHz); + + stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE); + stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL); +#endif +} diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c new file mode 100644 index 00000000..b9d86368 --- /dev/null +++ b/src/stmf0/ao_usb_stm.c @@ -0,0 +1,1090 @@ +/* + * 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" +#include "ao_usb.h" +#include "ao_product.h" + +#define USB_DEBUG 0 +#define USB_DEBUG_DATA 0 +#define USB_ECHO 0 + +#ifndef USE_USB_STDIO +#define USE_USB_STDIO 1 +#endif + +#if USE_USB_STDIO +#define AO_USB_OUT_SLEEP_ADDR (&ao_stdin_ready) +#else +#define AO_USB_OUT_SLEEP_ADDR (&ao_usb_out_avail) +#endif + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args); +#else +#define debug(format, args...) +#endif + +#if USB_DEBUG_DATA +#define debug_data(format, args...) printf(format, ## args); +#else +#define debug_data(format, args...) +#endif + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} ao_usb_setup; + +static uint8_t ao_usb_ep0_state; + +/* Pending EP0 IN data */ +static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */ +static uint8_t ao_usb_ep0_in_len; /* Remaining amount */ + +/* Temp buffer for smaller EP0 in data */ +static uint8_t ao_usb_ep0_in_buf[2]; + +/* Pending EP0 OUT data */ +static uint8_t *ao_usb_ep0_out_data; +static uint8_t ao_usb_ep0_out_len; + +/* + * Objects allocated in special USB memory + */ + +/* Buffer description tables */ +static union stm_usb_bdt *ao_usb_bdt; +/* USB address of end of allocated storage */ +static uint16_t ao_usb_sram_addr; + +/* Pointer to ep0 tx/rx buffers in USB memory */ +static uint16_t *ao_usb_ep0_tx_buffer; +static uint16_t *ao_usb_ep0_rx_buffer; + +/* Pointer to bulk data tx/rx buffers in USB memory */ +static uint16_t *ao_usb_in_tx_buffer; +static uint16_t *ao_usb_out_rx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ +static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t ao_usb_tx_count; + +static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t ao_usb_rx_count, ao_usb_rx_pos; + +/* + * End point register indices + */ + +#define AO_USB_CONTROL_EPR 0 +#define AO_USB_INT_EPR 1 +#define AO_USB_OUT_EPR 2 +#define AO_USB_IN_EPR 3 + +/* Marks when we don't need to send an IN packet. + * This happens only when the last IN packet is not full, + * otherwise the host will expect to keep seeing packets. + * Send a zero-length packet as required + */ +static uint8_t ao_usb_in_flushed; + +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ +static uint8_t ao_usb_in_pending; + +/* Marks when an OUT packet has been received by the hardware + * but not pulled to the shadow buffer. + */ +static uint8_t ao_usb_out_avail; +uint8_t ao_usb_running; +static uint8_t ao_usb_configuration; + +#define AO_USB_EP0_GOT_RESET 1 +#define AO_USB_EP0_GOT_SETUP 2 +#define AO_USB_EP0_GOT_RX_DATA 4 +#define AO_USB_EP0_GOT_TX_ACK 8 + +static uint8_t ao_usb_ep0_receive; +static uint8_t ao_usb_address; +static uint8_t ao_usb_address_pending; + +static inline uint32_t set_toggle(uint32_t current_value, + uint32_t mask, + uint32_t desired_value) +{ + return (current_value ^ desired_value) & mask; +} + +static inline uint16_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) +{ + return (uint16_t *) (stm_usb_sram + sram_addr); +} + +static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_STAT_RX) & STM_USB_EPR_STAT_RX_MASK; +} + +static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_STAT_TX) & STM_USB_EPR_STAT_TX_MASK; +} + +static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_CTR_RX) & 1; +} + +static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_CTR_TX) & 1; +} + +static inline uint32_t ao_usb_epr_setup(uint32_t epr) { + return (epr >> STM_USB_EPR_SETUP) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_DTOG_RX) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_DTOG_TX) & 1; +} + +/* + * Set current device address and mark the + * interface as active + */ +void +ao_usb_set_address(uint8_t address) +{ + debug("ao_usb_set_address %02x\n", address); + stm_usb.daddr = (1 << STM_USB_DADDR_EF) | address; + ao_usb_address_pending = 0; +} + +/* + * Write these values to preserve register contents under HW changes + */ + +#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX)) + +#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) + +/* + * These bits are purely under sw control, so preserve them in the + * register by re-writing what was read + */ +#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \ + (1 << STM_USB_EPR_EP_KIND) | \ + (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) + +#define TX_DBG 0 +#define RX_DBG 0 + +#if TX_DBG +#define _tx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _tx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _tx_dbg0(msg) +#define _tx_dbg1(msg,value) +#endif + +#if RX_DBG +#define _rx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _rx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _rx_dbg0(msg) +#define _rx_dbg1(msg,value) +#endif + +#if TX_DBG || RX_DBG +static void _dbg(int line, char *msg, uint32_t value); +#endif + +/* + * Set the state of the specified endpoint register to a new + * value. This is tricky because the bits toggle where the new + * value is one, and we need to write invariant values in other + * spots of the register. This hardware is strange... + */ +static void +_ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + uint16_t epr_write, epr_old; + + _tx_dbg1("set_stat_tx top", stat_tx); + epr_old = epr_write = stm_usb.epr[ep].r; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, + stat_tx << STM_USB_EPR_STAT_TX); + stm_usb.epr[ep].r = epr_write; + _tx_dbg1("set_stat_tx bottom", epr_write); +} + +static void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + ao_arch_block_interrupts(); + _ao_usb_set_stat_tx(ep, stat_tx); + ao_arch_release_interrupts(); +} + +static void +_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + uint16_t epr_write, epr_old; + + epr_write = epr_old = stm_usb.epr[ep].r; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, + stat_rx << STM_USB_EPR_STAT_RX); + stm_usb.epr[ep].r = epr_write; +} + +static void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + ao_arch_block_interrupts(); + _ao_usb_set_stat_rx(ep, stat_rx); + ao_arch_release_interrupts(); +} + +/* + * Set just endpoint 0, for use during startup + */ + +static void +ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) +{ + uint16_t epr; + + ao_arch_block_interrupts(); + epr = stm_usb.epr[ep].r; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (stat_rx << STM_USB_EPR_STAT_RX)) | + (type << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (stat_tx << STM_USB_EPR_STAT_TX)) | + (addr << STM_USB_EPR_EA)); + stm_usb.epr[ep].r = epr; + ao_arch_release_interrupts(); + debug ("writing epr[%d] 0x%04x wrote 0x%04x\n", + ep, epr, stm_usb.epr[ep].r); +} + +static void +ao_usb_init_btable(void) +{ + ao_usb_sram_addr = 0; + + ao_usb_bdt = (void *) stm_usb_sram; + + ao_usb_sram_addr += 8 * STM_USB_BDT_SIZE; + + /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ + + ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_tx = 0; + ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_CONTROL_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + +} + +static void +ao_usb_set_ep0(void) +{ + int e; + + ao_usb_init_btable(); + + /* buffer table is at the start of USB memory */ + stm_usb.btable = 0; + + ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP, + STM_USB_EPR_EP_TYPE_CONTROL, + STM_USB_EPR_STAT_RX_VALID, + STM_USB_EPR_STAT_TX_NAK); + + /* Clear all of the other endpoints */ + for (e = 1; e < 8; e++) { + ao_usb_init_ep(e, 0, + STM_USB_EPR_EP_TYPE_CONTROL, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_DISABLED); + } + + ao_usb_set_address(0); +} + +static void +ao_usb_set_configuration(void) +{ + debug ("ao_usb_set_configuration\n"); + + /* Set up the INT end point */ + ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_INT_SIZE; + + ao_usb_init_ep(AO_USB_INT_EPR, + AO_USB_INT_EP, + STM_USB_EPR_EP_TYPE_INTERRUPT, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK); + + /* Set up the OUT end point */ + ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_OUT_SIZE; + + ao_usb_init_ep(AO_USB_OUT_EPR, + AO_USB_OUT_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_VALID, + STM_USB_EPR_STAT_TX_DISABLED); + + /* Set up the IN end point */ + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_IN_SIZE; + + ao_usb_init_ep(AO_USB_IN_EPR, + AO_USB_IN_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK); + + ao_usb_running = 1; +} + +static uint16_t control_count; +static uint16_t int_count; +static uint16_t in_count; +static uint16_t out_count; +static uint16_t reset_count; + +/* The USB memory must be accessed in 16-bit units + */ + +static void +ao_usb_write(const uint8_t *src, uint16_t *base, uint16_t bytes) +{ + while (bytes >= 2) { + *base++ = src[0] | (src[1] << 8); + src += 2; + bytes -= 2; + } + if (bytes) + *base = *src; +} + +static void +ao_usb_read(uint8_t *dst, uint16_t *base, uint16_t bytes) +{ + while (bytes >= 2) { + uint16_t s = *base++; + dst[0] = s; + dst[1] = s >> 8; + dst += 2; + bytes -= 2; + } + if (bytes) + *dst = *base; +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + uint8_t this_len; + + /* Check to see if the endpoint is still busy */ + if (ao_usb_epr_stat_tx(stm_usb.epr[0].r) == STM_USB_EPR_STAT_TX_VALID) { + debug("EP0 not accepting IN data\n"); + return; + } + + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + if (this_len < AO_USB_CONTROL_SIZE) + ao_usb_ep0_state = AO_USB_EP0_IDLE; + + ao_usb_ep0_in_len -= this_len; + + debug_data ("Flush EP0 len %d:", this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len); + debug_data ("\n"); + ao_usb_ep0_in_data += this_len; + + /* Mark the endpoint as TX valid to send the packet */ + ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len; + ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, STM_USB_EPR_STAT_TX_VALID); + debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[AO_USB_CONTROL_EPR]); +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(void) +{ + uint16_t len = ao_usb_bdt[0].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + + /* Pull all of the data out of the packet */ + debug_data ("Fill EP0 len %d:", len); + ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, len); + debug_data ("\n"); + ao_usb_ep0_out_data += len; + + /* ACK the packet */ + ao_usb_set_stat_rx(0, STM_USB_EPR_STAT_RX_VALID); +} + +static void +ao_usb_ep0_in_reset(void) +{ + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; +} + +static void +ao_usb_ep0_in_queue_byte(uint8_t a) +{ + if (ao_usb_ep0_in_len < sizeof (ao_usb_ep0_in_buf)) + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_in_set(const uint8_t *data, uint8_t len) +{ + ao_usb_ep0_in_data = data; + ao_usb_ep0_in_len = len; +} + +static void +ao_usb_ep0_out_set(uint8_t *data, uint8_t len) +{ + ao_usb_ep0_out_data = data; + ao_usb_ep0_out_len = len; +} + +static void +ao_usb_ep0_in_start(uint16_t max) +{ + /* Don't send more than asked for */ + if (ao_usb_ep0_in_len > max) + ao_usb_ep0_in_len = max; + ao_usb_ep0_flush(); +} + +static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *descriptor; + uint8_t type = value >> 8; + uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + uint8_t len; + if (type == AO_USB_DESC_CONFIGURATION) + len = descriptor[2]; + else + len = descriptor[0]; + ao_usb_ep0_in_set(descriptor, len); + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_set((uint8_t *) &ao_usb_setup, 8); + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + if ((ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) || ao_usb_setup.length == 0) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + + ao_usb_ep0_in_reset(); + + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_address = ao_usb_setup.value; + ao_usb_address_pending = 1; + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_in_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case AO_USB_SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_set((uint8_t *) &ao_usb_line_coding, 7); + break; + case AO_USB_GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_set((const uint8_t *) &ao_usb_line_coding, 7); + break; + case AO_USB_SET_CONTROL_LINE_STATE: + break; + } + break; + } + + /* If we're not waiting to receive data from the host, + * queue an IN response + */ + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_in_start(ao_usb_setup.length); +} + +static void +ao_usb_ep0_handle(uint8_t receive) +{ + ao_usb_ep0_receive = 0; + if (receive & AO_USB_EP0_GOT_RESET) { + debug ("\treset\n"); + ao_usb_set_ep0(); + return; + } + if (receive & AO_USB_EP0_GOT_SETUP) { + debug ("\tsetup\n"); + ao_usb_ep0_setup(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); + } + } + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + +#if HAS_FLIGHT && AO_USB_FORCE_IDLE + ao_flight_force_idle = 1; +#endif + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) + ao_usb_set_address(ao_usb_address); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); + } +} + +void +stm_usb_isr(void) +{ + uint32_t istr = stm_usb.istr; + + stm_usb.istr = ~istr; + if (istr & (1 << STM_USB_ISTR_CTR)) { + uint8_t ep = istr & STM_USB_ISTR_EP_ID_MASK; + uint16_t epr, epr_write; + + /* Preserve the SW write bits, don't mess with most HW writable bits, + * clear the CTR_RX and CTR_TX bits + */ + epr = stm_usb.epr[ep].r; + epr_write = epr; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write &= ~(1 << STM_USB_EPR_CTR_RX); + epr_write &= ~(1 << STM_USB_EPR_CTR_TX); + stm_usb.epr[ep].r = epr_write; + + switch (ep) { + case 0: + ++control_count; + if (ao_usb_epr_ctr_rx(epr)) { + if (ao_usb_epr_setup(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + } + if (ao_usb_epr_ctr_tx(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + ao_usb_ep0_handle(ao_usb_ep0_receive); + break; + case AO_USB_OUT_EPR: + ++out_count; + if (ao_usb_epr_ctr_rx(epr)) { + _rx_dbg1("RX ISR", epr); + ao_usb_out_avail = 1; + _rx_dbg0("out avail set"); + ao_wakeup(AO_USB_OUT_SLEEP_ADDR); + _rx_dbg0("stdin awoken"); + } + break; + case AO_USB_IN_EPR: + ++in_count; + _tx_dbg1("TX ISR", epr); + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + break; + case AO_USB_INT_EPR: + ++int_count; + if (ao_usb_epr_ctr_tx(epr)) + _ao_usb_set_stat_tx(AO_USB_INT_EPR, STM_USB_EPR_STAT_TX_NAK); + break; + } + return; + } + + if (istr & (1 << STM_USB_ISTR_RESET)) { + ++reset_count; + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_usb_ep0_handle(ao_usb_ep0_receive); + } + +} + +/* Queue the current IN buffer for transmission */ +static void +_ao_usb_in_send(void) +{ + _tx_dbg0("in_send start"); + debug ("send %d\n", ao_usb_tx_count); + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + ao_usb_in_pending = 1; + if (ao_usb_tx_count != AO_USB_IN_SIZE) + ao_usb_in_flushed = 1; + ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; + ao_usb_tx_count = 0; + _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); + _tx_dbg0("in_send end"); +} + +/* Wait for a free IN buffer. Interrupts are blocked */ +static void +_ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + if (ao_usb_tx_count < AO_USB_IN_SIZE) + break; + + _tx_dbg0("in_wait top"); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + _tx_dbg0("in_wait bottom"); + } +} + +void +ao_usb_flush(void) +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + ao_arch_block_interrupts(); + while (!ao_usb_in_flushed) { + _tx_dbg0("flush top"); + _ao_usb_in_send(); + _tx_dbg0("flush end"); + } + ao_arch_release_interrupts(); +} + +void +ao_usb_putchar(char c) +{ + if (!ao_usb_running) + return; + + ao_arch_block_interrupts(); + _ao_usb_in_wait(); + + ao_usb_in_flushed = 0; + ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + + /* Send the packet when full */ + if (ao_usb_tx_count == AO_USB_IN_SIZE) { + _tx_dbg0("putchar full"); + _ao_usb_in_send(); + _tx_dbg0("putchar flushed"); + } + ao_arch_release_interrupts(); +} + +static void +_ao_usb_out_recv(void) +{ + _rx_dbg0("out_recv top"); + ao_usb_out_avail = 0; + + ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + _rx_dbg1("out_recv count", ao_usb_rx_count); + debug ("recv %d\n", ao_usb_rx_count); + debug_data("Fill OUT len %d:", ao_usb_rx_count); + ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); + debug_data("\n"); + ao_usb_rx_pos = 0; + + /* ACK the packet */ + _ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); +} + +int +_ao_usb_pollchar(void) +{ + uint8_t c; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + if (ao_usb_rx_pos != ao_usb_rx_count) + break; + + _rx_dbg0("poll check"); + /* Check to see if a packet has arrived */ + if (!ao_usb_out_avail) { + _rx_dbg0("poll none"); + return AO_READ_AGAIN; + } + _ao_usb_out_recv(); + } + + /* Pull a character out of the fifo */ + c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + return c; +} + +char +ao_usb_getchar(void) +{ + int c; + + ao_arch_block_interrupts(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(AO_USB_OUT_SLEEP_ADDR); + ao_arch_release_interrupts(); + return c; +} + +void +ao_usb_disable(void) +{ + ao_arch_block_interrupts(); + stm_usb.cntr = (1 << STM_USB_CNTR_FRES); + stm_usb.istr = 0; + + /* Disable USB pull-up */ + stm_usb.bcdr &= ~(1 << STM_USB_BCDR_DPPU); + + /* Switch off the device */ + stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES); + + /* Disable the interface */ + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN); + ao_arch_release_interrupts(); +} + +void +ao_usb_enable(void) +{ + int t; + + /* Select HSI48 as USB clock source */ + stm_rcc.cfgr3 &= ~(1 << STM_RCC_CFGR3_USBSW); + + /* Enable USB device */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USBEN); + + /* Clear reset condition */ + stm_rcc.apb1rstr &= ~(1 << STM_RCC_APB1RSTR_USBRST); + + /* Disable USB pull-up */ + stm_usb.bcdr &= ~(1 << STM_USB_BCDR_DPPU); + + /* Do not touch the GPIOA configuration; USB takes priority + * over GPIO on pins A11 and A12, but if you select alternate + * input 10 (the documented correct selection), then USB is + * pulled low and doesn't work at all + */ + + ao_arch_block_interrupts(); + + /* Route interrupts */ + stm_nvic_set_enable(STM_ISR_USB_POS); + stm_nvic_set_priority(STM_ISR_USB_POS, 3); + + ao_usb_configuration = 0; + + /* Set up buffer descriptors */ + ao_usb_init_btable(); + + /* Reset the USB controller */ + stm_usb.cntr = (1 << STM_USB_CNTR_FRES); + + /* Clear the reset bit */ + stm_usb.cntr = 0; + + /* Clear any spurious interrupts */ + stm_usb.istr = 0; + + ao_usb_set_ep0(); + + debug ("ao_usb_enable\n"); + + /* Enable interrupts */ + stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) | + (0 << STM_USB_CNTR_PMAOVRM) | + (0 << STM_USB_CNTR_ERRM) | + (0 << STM_USB_CNTR_WKUPM) | + (0 << STM_USB_CNTR_SUSPM) | + (1 << STM_USB_CNTR_RESETM) | + (0 << STM_USB_CNTR_SOFM) | + (0 << STM_USB_CNTR_ESOFM) | + (0 << STM_USB_CNTR_RESUME) | + (0 << STM_USB_CNTR_FSUSP) | + (0 << STM_USB_CNTR_LP_MODE) | + (0 << STM_USB_CNTR_PDWN) | + (0 << STM_USB_CNTR_FRES)); + + ao_arch_release_interrupts(); + + for (t = 0; t < 1000; t++) + ao_arch_nop(); + + /* Enable USB pull-up */ + stm_usb.bcdr |= (1 << STM_USB_BCDR_DPPU); +} + +#if USB_ECHO +struct ao_task ao_usb_echo_task; + +static void +ao_usb_echo(void) +{ + char c; + + for (;;) { + c = ao_usb_getchar(); + ao_usb_putchar(c); + ao_usb_flush(); + } +} +#endif + +#if USB_DEBUG +static void +ao_usb_irq(void) +{ + printf ("control: %d out: %d in: %d int: %d reset: %d\n", + control_count, out_count, in_count, int_count, reset_count); +} + +__code struct ao_cmds ao_usb_cmds[] = { + { ao_usb_irq, "I\0Show USB interrupt counts" }, + { 0, NULL } +}; +#endif + +void +ao_usb_init(void) +{ + ao_usb_enable(); + + debug ("ao_usb_init\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; +#if USB_ECHO + ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); +#endif +#if USB_DEBUG + ao_cmd_register(&ao_usb_cmds[0]); +#endif +#if !USB_ECHO +#if USE_USB_STDIO + ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +#endif +#endif +} + +#if TX_DBG || RX_DBG + +struct ao_usb_dbg { + int line; + char *msg; + uint32_t value; + uint32_t primask; +#if TX_DBG + uint16_t in_count; + uint32_t in_epr; + uint32_t in_pending; + uint32_t tx_count; + uint32_t in_flushed; +#endif +#if RX_DBG + uint8_t rx_count; + uint8_t rx_pos; + uint8_t out_avail; + uint32_t out_epr; +#endif +}; + +#define NUM_USB_DBG 128 + +static struct ao_usb_dbg dbg[128]; +static int dbg_i; + +static void _dbg(int line, char *msg, uint32_t value) +{ + uint32_t primask; + dbg[dbg_i].line = line; + dbg[dbg_i].msg = msg; + dbg[dbg_i].value = value; + asm("mrs %0,primask" : "=&r" (primask)); + dbg[dbg_i].primask = primask; +#if TX_DBG + dbg[dbg_i].in_count = in_count; + dbg[dbg_i].in_epr = stm_usb.epr[AO_USB_IN_EPR]; + dbg[dbg_i].in_pending = ao_usb_in_pending; + dbg[dbg_i].tx_count = ao_usb_tx_count; + dbg[dbg_i].in_flushed = ao_usb_in_flushed; +#endif +#if RX_DBG + dbg[dbg_i].rx_count = ao_usb_rx_count; + dbg[dbg_i].rx_pos = ao_usb_rx_pos; + dbg[dbg_i].out_avail = ao_usb_out_avail; + dbg[dbg_i].out_epr = stm_usb.epr[AO_USB_OUT_EPR]; +#endif + if (++dbg_i == NUM_USB_DBG) + dbg_i = 0; +} +#endif diff --git a/src/stmf0/registers.ld b/src/stmf0/registers.ld new file mode 100644 index 00000000..5358f15a --- /dev/null +++ b/src/stmf0/registers.ld @@ -0,0 +1,60 @@ +stm_gpiof = 0x48001400; +stm_gpioc = 0x48000800; +stm_gpiob = 0x48000400; +stm_gpioa = 0x48000000; + +stm_tsc = 0x40024000; +stm_crc = 0x40023000; +stm_flash = 0x40022000; +stm_rcc = 0x40021000; +stm_dma = 0x40020000; +stm_dbgmcu = 0x40015800; +stm_tim17 = 0x40014800; +stm_tim16 = 0x40014400; +stm_usart1 = 0x40013800; +stm_spi1 = 0x40013000; +stm_tim1 = 0x40012c00; +stm_adc = 0x40012400; + +stm_exti = 0x40010400; +stm_syscfg = 0x40010000; + +stm_cec = 0x40007800; + +stm_pwr = 0x40007000; +stm_crs = 0x40006c00; + +stm_bxcan = 0x40006400; +stm_usb_sram = 0x40006000; +stm_usb = 0x40005c00; + +stm_i2c1 = 0x40005400; + +stm_usart2 = 0x40004400; + +stm_spi2 = 0x40003800; /* docs are broken here */ + +stm_iwdg = 0x40003000; +stm_wwdg = 0x40002c00; +stm_rtc = 0x40002800; + +stm_tim14 = 0x40002000; + +stm_tim3 = 0x40000400; +stm_tim2 = 0x40000000; + +stm_systick = 0xe000e010; + +stm_nvic = 0xe000e100; + +stm_scb = 0xe000ed00; + +stm_mpu = 0xe000ed90; + +stm_dbg_mcu = 0xe0042000; + +/* calibration data in system memory */ +stm_temp_cal = 0x1ff80078; +stm_flash_size_medium = 0x1ff8004c; +stm_flash_size_large = 0x1ff800cc; +stm_device_id = 0x1ff80050; diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h new file mode 100644 index 00000000..2adfeee0 --- /dev/null +++ b/src/stmf0/stm32f0.h @@ -0,0 +1,1995 @@ +/* + * 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. + */ + +#ifndef _STM32F0_H_ +#define _STM32F0_H_ + +#include + +typedef volatile uint32_t vuint32_t; +typedef volatile void * vvoid_t; +typedef volatile uint16_t vuint16_t; + +struct stm_gpio { + vuint32_t moder; + vuint32_t otyper; + vuint32_t ospeedr; + vuint32_t pupdr; + + vuint32_t idr; + vuint32_t odr; + vuint32_t bsrr; + vuint32_t lckr; + + vuint32_t afrl; + vuint32_t afrh; + vuint32_t brr; +}; + +#define STM_MODER_SHIFT(pin) ((pin) << 1) +#define STM_MODER_MASK 3 +#define STM_MODER_INPUT 0 +#define STM_MODER_OUTPUT 1 +#define STM_MODER_ALTERNATE 2 +#define STM_MODER_ANALOG 3 + +static inline void +stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->moder = ((gpio->moder & + ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) | + value << STM_MODER_SHIFT(pin)); +} + +static inline uint32_t +stm_moder_get(struct stm_gpio *gpio, int pin) { + return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK; +} + +#define STM_OTYPER_SHIFT(pin) (pin) +#define STM_OTYPER_MASK 1 +#define STM_OTYPER_PUSH_PULL 0 +#define STM_OTYPER_OPEN_DRAIN 1 + +static inline void +stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->otyper = ((gpio->otyper & + ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) | + value << STM_OTYPER_SHIFT(pin)); +} + +static inline uint32_t +stm_otyper_get(struct stm_gpio *gpio, int pin) { + return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK; +} + +#define STM_OSPEEDR_SHIFT(pin) ((pin) << 1) +#define STM_OSPEEDR_MASK 3 +#define STM_OSPEEDR_LOW 0 /* 2MHz */ +#define STM_OSPEEDR_MEDIUM 1 /* 10MHz */ +#define STM_OSPEEDR_HIGH 3 /* 10-50MHz */ + +static inline void +stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->ospeedr = ((gpio->ospeedr & + ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) | + value << STM_OSPEEDR_SHIFT(pin)); +} + +static inline uint32_t +stm_ospeedr_get(struct stm_gpio *gpio, int pin) { + return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK; +} + +#define STM_PUPDR_SHIFT(pin) ((pin) << 1) +#define STM_PUPDR_MASK 3 +#define STM_PUPDR_NONE 0 +#define STM_PUPDR_PULL_UP 1 +#define STM_PUPDR_PULL_DOWN 2 +#define STM_PUPDR_RESERVED 3 + +static inline void +stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + gpio->pupdr = ((gpio->pupdr & + ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | + value << STM_PUPDR_SHIFT(pin)); +} + +static inline uint32_t +stm_pupdr_get(struct stm_gpio *gpio, int pin) { + return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; +} + +#define STM_AFR_SHIFT(pin) ((pin) << 2) +#define STM_AFR_MASK 0xf +#define STM_AFR_NONE 0 +#define STM_AFR_AF0 0x0 +#define STM_AFR_AF1 0x1 +#define STM_AFR_AF2 0x2 +#define STM_AFR_AF3 0x3 +#define STM_AFR_AF4 0x4 +#define STM_AFR_AF5 0x5 +#define STM_AFR_AF6 0x6 +#define STM_AFR_AF7 0x7 + +static inline void +stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + /* + * Set alternate pin mode too + */ + stm_moder_set(gpio, pin, STM_MODER_ALTERNATE); + if (pin < 8) + gpio->afrl = ((gpio->afrl & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + else { + pin -= 8; + gpio->afrh = ((gpio->afrh & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + } +} + +static inline uint32_t +stm_afr_get(struct stm_gpio *gpio, int pin) { + if (pin < 8) + return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + else { + pin -= 8; + return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + } +} + +static inline void +stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); +} + +static inline uint8_t +stm_gpio_get(struct stm_gpio *gpio, int pin) { + return (gpio->idr >> pin) & 1; +} + +static inline uint16_t +stm_gpio_get_all(struct stm_gpio *gpio) { + return gpio->idr; +} + +/* + * We can't define these in registers.ld or our fancy + * ao_enable_gpio macro will expand into a huge pile of code + * as the compiler won't do correct constant folding and + * dead-code elimination + */ + +extern struct stm_gpio stm_gpioa; +extern struct stm_gpio stm_gpiob; +extern struct stm_gpio stm_gpioc; +extern struct stm_gpio stm_gpiof; + +#define stm_gpiof (*((struct stm_gpio *) 0x48001400)) +#define stm_gpioc (*((struct stm_gpio *) 0x48000800)) +#define stm_gpiob (*((struct stm_gpio *) 0x48000400)) +#define stm_gpioa (*((struct stm_gpio *) 0x48000000)) + +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; /* */ + vuint32_t rqr; /* */ + vuint32_t isr; /* */ + + vuint32_t icr; /* */ + vuint32_t rdr; /* */ + vuint32_t tdr; /* */ +}; + +extern struct stm_usart stm_usart1; +extern struct stm_usart stm_usart2; + +#define STM_USART_SR_CTS (9) /* CTS flag */ +#define STM_USART_SR_LBD (8) /* LIN break detection flag */ +#define STM_USART_SR_TXE (7) /* Transmit data register empty */ +#define STM_USART_SR_TC (6) /* Transmission complete */ +#define STM_USART_SR_RXNE (5) /* Read data register not empty */ +#define STM_USART_SR_IDLE (4) /* IDLE line detected */ +#define STM_USART_SR_ORE (3) /* Overrun error */ +#define STM_USART_SR_NF (2) /* Noise detected flag */ +#define STM_USART_SR_FE (1) /* Framing error */ +#define STM_USART_SR_PE (0) /* Parity error */ + +#define STM_USART_CR1_OVER8 (15) /* Oversampling mode */ +#define STM_USART_CR1_UE (13) /* USART enable */ +#define STM_USART_CR1_M (12) /* Word length */ +#define STM_USART_CR1_WAKE (11) /* Wakeup method */ +#define STM_USART_CR1_PCE (10) /* Parity control enable */ +#define STM_USART_CR1_PS (9) /* Parity selection */ +#define STM_USART_CR1_PEIE (8) /* PE interrupt enable */ +#define STM_USART_CR1_TXEIE (7) /* TXE interrupt enable */ +#define STM_USART_CR1_TCIE (6) /* Transmission complete interrupt enable */ +#define STM_USART_CR1_RXNEIE (5) /* RXNE interrupt enable */ +#define STM_USART_CR1_IDLEIE (4) /* IDLE interrupt enable */ +#define STM_USART_CR1_TE (3) /* Transmitter enable */ +#define STM_USART_CR1_RE (2) /* Receiver enable */ +#define STM_USART_CR1_RWU (1) /* Receiver wakeup */ +#define STM_USART_CR1_SBK (0) /* Send break */ + +#define STM_USART_CR2_LINEN (14) /* LIN mode enable */ +#define STM_USART_CR2_STOP (12) /* STOP bits */ +#define STM_USART_CR2_STOP_MASK 3 +#define STM_USART_CR2_STOP_1 0 +#define STM_USART_CR2_STOP_0_5 1 +#define STM_USART_CR2_STOP_2 2 +#define STM_USART_CR2_STOP_1_5 3 + +#define STM_USART_CR2_CLKEN (11) /* Clock enable */ +#define STM_USART_CR2_CPOL (10) /* Clock polarity */ +#define STM_USART_CR2_CPHA (9) /* Clock phase */ +#define STM_USART_CR2_LBCL (8) /* Last bit clock pulse */ +#define STM_USART_CR2_LBDIE (6) /* LIN break detection interrupt enable */ +#define STM_USART_CR2_LBDL (5) /* lin break detection length */ +#define STM_USART_CR2_ADD (0) +#define STM_USART_CR2_ADD_MASK 0xf + +#define STM_USART_CR3_ONEBITE (11) /* One sample bit method enable */ +#define STM_USART_CR3_CTSIE (10) /* CTS interrupt enable */ +#define STM_USART_CR3_CTSE (9) /* CTS enable */ +#define STM_USART_CR3_RTSE (8) /* RTS enable */ +#define STM_USART_CR3_DMAT (7) /* DMA enable transmitter */ +#define STM_USART_CR3_DMAR (6) /* DMA enable receiver */ +#define STM_USART_CR3_SCEN (5) /* Smartcard mode enable */ +#define STM_USART_CR3_NACK (4) /* Smartcard NACK enable */ +#define STM_USART_CR3_HDSEL (3) /* Half-duplex selection */ +#define STM_USART_CR3_IRLP (2) /* IrDA low-power */ +#define STM_USART_CR3_IREN (1) /* IrDA mode enable */ +#define STM_USART_CR3_EIE (0) /* Error interrupt enable */ + +struct stm_tim { +}; + +extern struct stm_tim stm_tim9; + +struct stm_tim1011 { + vuint32_t cr1; + uint32_t unused_4; + vuint32_t smcr; + vuint32_t dier; + vuint32_t sr; + vuint32_t egr; + vuint32_t ccmr1; + uint32_t unused_1c; + vuint32_t ccer; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; + uint32_t unused_30; + vuint32_t ccr1; + uint32_t unused_38; + uint32_t unused_3c; + uint32_t unused_40; + uint32_t unused_44; + uint32_t unused_48; + uint32_t unused_4c; + vuint32_t or; +}; + +extern struct stm_tim1011 stm_tim10; +extern struct stm_tim1011 stm_tim11; + +#define STM_TIM1011_CR1_CKD 8 +#define STM_TIM1011_CR1_CKD_1 0 +#define STM_TIM1011_CR1_CKD_2 1 +#define STM_TIM1011_CR1_CKD_4 2 +#define STM_TIM1011_CR1_CKD_MASK 3 +#define STM_TIM1011_CR1_ARPE 7 +#define STM_TIM1011_CR1_URS 2 +#define STM_TIM1011_CR1_UDIS 1 +#define STM_TIM1011_CR1_CEN 0 + +#define STM_TIM1011_SMCR_ETP 15 +#define STM_TIM1011_SMCR_ECE 14 +#define STM_TIM1011_SMCR_ETPS 12 +#define STM_TIM1011_SMCR_ETPS_OFF 0 +#define STM_TIM1011_SMCR_ETPS_2 1 +#define STM_TIM1011_SMCR_ETPS_4 2 +#define STM_TIM1011_SMCR_ETPS_8 3 +#define STM_TIM1011_SMCR_ETPS_MASK 3 +#define STM_TIM1011_SMCR_ETF 8 +#define STM_TIM1011_SMCR_ETF_NONE 0 +#define STM_TIM1011_SMCR_ETF_CK_INT_2 1 +#define STM_TIM1011_SMCR_ETF_CK_INT_4 2 +#define STM_TIM1011_SMCR_ETF_CK_INT_8 3 +#define STM_TIM1011_SMCR_ETF_DTS_2_6 4 +#define STM_TIM1011_SMCR_ETF_DTS_2_8 5 +#define STM_TIM1011_SMCR_ETF_DTS_4_6 6 +#define STM_TIM1011_SMCR_ETF_DTS_4_8 7 +#define STM_TIM1011_SMCR_ETF_DTS_8_6 8 +#define STM_TIM1011_SMCR_ETF_DTS_8_8 9 +#define STM_TIM1011_SMCR_ETF_DTS_16_5 10 +#define STM_TIM1011_SMCR_ETF_DTS_16_6 11 +#define STM_TIM1011_SMCR_ETF_DTS_16_8 12 +#define STM_TIM1011_SMCR_ETF_DTS_32_5 13 +#define STM_TIM1011_SMCR_ETF_DTS_32_6 14 +#define STM_TIM1011_SMCR_ETF_DTS_32_8 15 +#define STM_TIM1011_SMCR_ETF_MASK 15 + +#define STM_TIM1011_DIER_CC1E 1 +#define STM_TIM1011_DIER_UIE 0 + +#define STM_TIM1011_SR_CC1OF 9 +#define STM_TIM1011_SR_CC1IF 1 +#define STM_TIM1011_SR_UIF 0 + +#define STM_TIM1011_EGR_CC1G 1 +#define STM_TIM1011_EGR_UG 0 + +#define STM_TIM1011_CCMR1_OC1CE 7 +#define STM_TIM1011_CCMR1_OC1M 4 +#define STM_TIM1011_CCMR1_OC1M_FROZEN 0 +#define STM_TIM1011_CCMR1_OC1M_SET_1_ACTIVE_ON_MATCH 1 +#define STM_TIM1011_CCMR1_OC1M_SET_1_INACTIVE_ON_MATCH 2 +#define STM_TIM1011_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM1011_CCMR1_OC1M_FORCE_INACTIVE 4 +#define STM_TIM1011_CCMR1_OC1M_FORCE_ACTIVE 5 +#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM1011_CCMR1_OC1M_MASK 7 +#define STM_TIM1011_CCMR1_OC1PE 3 +#define STM_TIM1011_CCMR1_OC1FE 2 +#define STM_TIM1011_CCMR1_CC1S 0 +#define STM_TIM1011_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM1011_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM1011_CCMR1_CC1S_MASK 3 + +#define STM_TIM1011_CCMR1_IC1F_NONE 0 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_2 1 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_4 2 +#define STM_TIM1011_CCMR1_IC1F_CK_INT_8 3 +#define STM_TIM1011_CCMR1_IC1F_DTS_2_6 4 +#define STM_TIM1011_CCMR1_IC1F_DTS_2_8 5 +#define STM_TIM1011_CCMR1_IC1F_DTS_4_6 6 +#define STM_TIM1011_CCMR1_IC1F_DTS_4_8 7 +#define STM_TIM1011_CCMR1_IC1F_DTS_8_6 8 +#define STM_TIM1011_CCMR1_IC1F_DTS_8_8 9 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_5 10 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_6 11 +#define STM_TIM1011_CCMR1_IC1F_DTS_16_8 12 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_5 13 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_6 14 +#define STM_TIM1011_CCMR1_IC1F_DTS_32_8 15 +#define STM_TIM1011_CCMR1_IC1F_MASK 15 +#define STM_TIM1011_CCMR1_IC1PSC 2 +#define STM_TIM1011_CCMR1_IC1PSC_1 0 +#define STM_TIM1011_CCMR1_IC1PSC_2 1 +#define STM_TIM1011_CCMR1_IC1PSC_4 2 +#define STM_TIM1011_CCMR1_IC1PSC_8 3 +#define STM_TIM1011_CCMR1_IC1PSC_MASK 3 +#define STM_TIM1011_CCMR1_CC1S 0 + +#define STM_TIM1011_CCER_CC1NP 3 +#define STM_TIM1011_CCER_CC1P 1 +#define STM_TIM1011_CCER_CC1E 0 + +#define STM_TIM1011_OR_TI1_RMP_RI 3 +#define STM_TIM1011_ETR_RMP 2 +#define STM_TIM1011_TI1_RMP 0 +#define STM_TIM1011_TI1_RMP_GPIO 0 +#define STM_TIM1011_TI1_RMP_LSI 1 +#define STM_TIM1011_TI1_RMP_LSE 2 +#define STM_TIM1011_TI1_RMP_RTC 3 +#define STM_TIM1011_TI1_RMP_MASK 3 + +/* Flash interface */ + +struct stm_flash { + vuint32_t acr; + vuint32_t keyr; + vuint32_t optkeyr; + vuint32_t sr; + + vuint32_t cr; + vuint32_t ar; + vuint32_t unused_0x18; + vuint32_t obr; + + vuint32_t wrpr; +}; + +extern struct stm_flash stm_flash; + +#define STM_FLASH_ACR_PRFTBS (5) +#define STM_FLASH_ACR_PRFTBE (4) +#define STM_FLASH_ACR_LATENCY (0) +#define STM_FLASH_ACR_LATENCY_0 0 +#define STM_FLASH_ACR_LATENCY_1 1 + +#define STM_FLASH_PECR_OBL_LAUNCH 18 +#define STM_FLASH_PECR_ERRIE 17 +#define STM_FLASH_PECR_EOPIE 16 +#define STM_FLASH_PECR_FPRG 10 +#define STM_FLASH_PECR_ERASE 9 +#define STM_FLASH_PECR_FTDW 8 +#define STM_FLASH_PECR_DATA 4 +#define STM_FLASH_PECR_PROG 3 +#define STM_FLASH_PECR_OPTLOCK 2 +#define STM_FLASH_PECR_PRGLOCK 1 +#define STM_FLASH_PECR_PELOCK 0 + +#define STM_FLASH_SR_OPTVERR 11 +#define STM_FLASH_SR_SIZERR 10 +#define STM_FLASH_SR_PGAERR 9 +#define STM_FLASH_SR_WRPERR 8 +#define STM_FLASH_SR_READY 3 +#define STM_FLASH_SR_ENDHV 2 +#define STM_FLASH_SR_EOP 1 +#define STM_FLASH_SR_BSY 0 + +#define STM_FLASH_PEKEYR_PEKEY1 0x89ABCDEF +#define STM_FLASH_PEKEYR_PEKEY2 0x02030405 + +#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF +#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516 + +struct stm_rcc { + vuint32_t cr; + vuint32_t cfgr; + vuint32_t cir; + vuint32_t apb2rstr; + + vuint32_t apb1rstr; + vuint32_t ahbenr; + vuint32_t apb2enr; + vuint32_t apb1enr; + + vuint32_t bdcr; + vuint32_t csr; + vuint32_t ahbrstr; + vuint32_t cfgr2; + + vuint32_t cfgr3; + vuint32_t cr2; +}; + +extern struct stm_rcc stm_rcc; + +/* Nominal high speed internal oscillator frequency is 16MHz */ +#define STM_HSI_FREQ 16000000 + +#define STM_RCC_CR_PLLRDY (25) +#define STM_RCC_CR_PLLON (24) +#define STM_RCC_CR_CSSON (19) +#define STM_RCC_CR_HSEBYP (18) +#define STM_RCC_CR_HSERDY (17) +#define STM_RCC_CR_HSEON (16) +#define STM_RCC_CR_HSICAL (8) +#define STM_RCC_CR_HSITRIM (3) +#define STM_RCC_CR_HSIRDY (1) +#define STM_RCC_CR_HSION (0) + +#define STM_RCC_CFGR_PLL_NODIV (31) +#define STM_RCC_CFGR_PLL_NODIV_DIV_1 1 +#define STM_RCC_CFGR_PLL_NODIV_DIV_2 0 + +#define STM_RCC_CFGR_MCOPRE (28) +#define STM_RCC_CFGR_MCOPRE_DIV_1 0 +#define STM_RCC_CFGR_MCOPRE_DIV_2 1 +#define STM_RCC_CFGR_MCOPRE_DIV_4 2 +#define STM_RCC_CFGR_MCOPRE_DIV_8 3 +#define STM_RCC_CFGR_MCOPRE_DIV_16 4 +#define STM_RCC_CFGR_MCOPRE_DIV_32 5 +#define STM_RCC_CFGR_MCOPRE_DIV_64 6 +#define STM_RCC_CFGR_MCOPRE_DIV_128 7 +#define STM_RCC_CFGR_MCOPRE_DIV_MASK 7 + +#define STM_RCC_CFGR_MCO (24) +# define STM_RCC_CFGR_MCO_DISABLE 0 + +#define STM_RCC_CFGR_PLLMUL (18) +#define STM_RCC_CFGR_PLLMUL_2 0 +#define STM_RCC_CFGR_PLLMUL_3 1 +#define STM_RCC_CFGR_PLLMUL_4 2 +#define STM_RCC_CFGR_PLLMUL_5 3 +#define STM_RCC_CFGR_PLLMUL_6 4 +#define STM_RCC_CFGR_PLLMUL_7 5 +#define STM_RCC_CFGR_PLLMUL_8 6 +#define STM_RCC_CFGR_PLLMUL_9 7 +#define STM_RCC_CFGR_PLLMUL_10 8 +#define STM_RCC_CFGR_PLLMUL_11 9 +#define STM_RCC_CFGR_PLLMUL_12 10 +#define STM_RCC_CFGR_PLLMUL_13 11 +#define STM_RCC_CFGR_PLLMUL_14 12 +#define STM_RCC_CFGR_PLLMUL_15 13 +#define STM_RCC_CFGR_PLLMUL_16 14 +#define STM_RCC_CFGR_PLLMUL_MASK 0xf + +#define STM_RCC_CFGR_PLLXTPRE (17) + +#define STM_RCC_CFGR_PLLSRC (15) +# define STM_RCC_CFGR_PLLSRC_HSI_DIV_2 0 +# define STM_RCC_CFGR_PLLSRC_HSI 1 +# define STM_RCC_CFGR_PLLSRC_HSE 2 +# define STM_RCC_CFGR_PLLSRC_HSI48 3 + +#define STM_RCC_CFGR_ADCPRE (14) + +#define STM_RCC_CFGR_PPRE (8) +#define STM_RCC_CFGR_PPRE_DIV_1 0 +#define STM_RCC_CFGR_PPRE_DIV_2 4 +#define STM_RCC_CFGR_PPRE_DIV_4 5 +#define STM_RCC_CFGR_PPRE_DIV_8 6 +#define STM_RCC_CFGR_PPRE_DIV_16 7 +#define STM_RCC_CFGR_PPRE_MASK 7 + +#define STM_RCC_CFGR_HPRE (4) +#define STM_RCC_CFGR_HPRE_DIV_1 0 +#define STM_RCC_CFGR_HPRE_DIV_2 8 +#define STM_RCC_CFGR_HPRE_DIV_4 9 +#define STM_RCC_CFGR_HPRE_DIV_8 0xa +#define STM_RCC_CFGR_HPRE_DIV_16 0xb +#define STM_RCC_CFGR_HPRE_DIV_64 0xc +#define STM_RCC_CFGR_HPRE_DIV_128 0xd +#define STM_RCC_CFGR_HPRE_DIV_256 0xe +#define STM_RCC_CFGR_HPRE_DIV_512 0xf +#define STM_RCC_CFGR_HPRE_MASK 0xf + +#define STM_RCC_CFGR_SWS (2) +#define STM_RCC_CFGR_SWS_HSI 0 +#define STM_RCC_CFGR_SWS_HSE 1 +#define STM_RCC_CFGR_SWS_PLL 2 +#define STM_RCC_CFGR_SWS_HSI48 3 +#define STM_RCC_CFGR_SWS_MASK 3 + +#define STM_RCC_CFGR_SW (0) +#define STM_RCC_CFGR_SW_HSI 0 +#define STM_RCC_CFGR_SW_HSE 1 +#define STM_RCC_CFGR_SW_PLL 2 +#define STM_RCC_CFGR_SW_HSI48 3 +#define STM_RCC_CFGR_SW_MASK 3 + +#define STM_RCC_APB1RSTR_CECRST 30 +#define STM_RCC_APB1RSTR_DACRST 29 +#define STM_RCC_APB1RSTR_PWRRST 28 +#define STM_RCC_APB1RSTR_CRSRST 27 +#define STM_RCC_APB1RSTR_CANRST 25 +#define STM_RCC_APB1RSTR_USBRST 23 +#define STM_RCC_APB1RSTR_I2C2RST 22 +#define STM_RCC_APB1RSTR_I1C1RST 21 +#define STM_RCC_APB1RSTR_USART5RST 20 +#define STM_RCC_APB1RSTR_USART4RST 19 +#define STM_RCC_APB1RSTR_USART3RST 18 +#define STM_RCC_APB1RSTR_USART2RST 17 +#define STM_RCC_APB1RSTR_SPI2RST 14 +#define STM_RCC_APB1RSTR_WWDGRST 11 +#define STM_RCC_APB1RSTR_TIM14RST 8 +#define STM_RCC_APB1RSTR_TIM7RST 5 +#define STM_RCC_APB1RSTR_TIM6RST 4 +#define STM_RCC_APB1RSTR_TIM3RST 1 +#define STM_RCC_APB1RSTR_TIM2RST 0 + +#define STM_RCC_AHBENR_TSCEN 24 +#define STM_RCC_AHBENR_IOPFEN 22 +#define STM_RCC_AHBENR_IOPEEN 21 +#define STM_RCC_AHBENR_IOPDEN 20 +#define STM_RCC_AHBENR_IOPCEN 19 +#define STM_RCC_AHBENR_IOPBEN 18 +#define STM_RCC_AHBENR_IOPAEN 17 +#define STM_RCC_AHBENR_CRCEN 6 +#define STM_RCC_AHBENR_FLITFEN 4 +#define STM_RCC_AHBENR_SRAMEN 2 +#define STM_RCC_AHBENR_DMA2EN 1 +#define STM_RCC_AHBENR_DMAEM 0 + +#define STM_RCC_APB2ENR_DBGMCUEN 22 +#define STM_RCC_APB2ENR_TIM17EN 18 +#define STM_RCC_APB2ENR_TIM16EN 17 +#define STM_RCC_APB2ENR_TIM15EN 16 +#define STM_RCC_APB2ENR_USART1EN 14 +#define STM_RCC_APB2ENR_SPI1EN 12 +#define STM_RCC_APB2ENR_TIM1EN 11 +#define STM_RCC_APB2ENR_ADCEN 9 +#define STM_RCC_APB2ENR_USART8EN 7 +#define STM_RCC_APB2ENR_USART7EN 6 +#define STM_RCC_APB2ENR_USART6EN 5 +#define STM_RCC_APB2ENR_SYSCFGCOMPEN 0 + +#define STM_RCC_APB1ENR_CECEN 30 +#define STM_RCC_APB1ENR_DACEN 29 +#define STM_RCC_APB1ENR_PWREN 28 +#define STM_RCC_APB1ENR_CRSEN 27 +#define STM_RCC_APB1ENR_CANEN 25 +#define STM_RCC_APB1ENR_USBEN 23 +#define STM_RCC_APB1ENR_I2C2EN 22 +#define STM_RCC_APB1ENR_IC21EN 21 +#define STM_RCC_APB1ENR_USART5EN 20 +#define STM_RCC_APB1ENR_USART4EN 19 +#define STM_RCC_APB1ENR_USART3EN 18 +#define STM_RCC_APB1ENR_USART2EN 17 +#define STM_RCC_APB1ENR_SPI2EN 14 +#define STM_RCC_APB1ENR_WWDGEN 11 +#define STM_RCC_APB1ENR_TIM14EN 8 +#define STM_RCC_APB1ENR_TIM7EN 5 +#define STM_RCC_APB1ENR_TIM6EN 4 +#define STM_RCC_APB1ENR_TIM3EN 1 +#define STM_RCC_APB1ENR_TIM2EN 0 + +#define STM_RCC_CSR_LPWRRSTF (31) +#define STM_RCC_CSR_WWDGRSTF (30) +#define STM_RCC_CSR_IWDGRSTF (29) +#define STM_RCC_CSR_SFTRSTF (28) +#define STM_RCC_CSR_PORRSTF (27) +#define STM_RCC_CSR_PINRSTF (26) +#define STM_RCC_CSR_OBLRSTF (25) +#define STM_RCC_CSR_RMVF (24) +#define STM_RCC_CSR_V18PWRRSTF (23) +#define STM_RCC_CSR_LSIRDY (1) +#define STM_RCC_CSR_LSION (0) + +#define STM_RCC_CR2_HSI48CAL 24 +#define STM_RCC_CR2_HSI48RDY 17 +#define STM_RCC_CR2_HSI48ON 16 +#define STM_RCC_CR2_HSI14CAL 8 +#define STM_RCC_CR2_HSI14TRIM 3 +#define STM_RCC_CR2_HSI14DIS 2 +#define STM_RCC_CR2_HSI14RDY 1 +#define STM_RCC_CR2_HSI14ON 0 + +#define STM_RCC_CFGR3_USART3SW 18 +#define STM_RCC_CFGR3_USART2SW 16 +#define STM_RCC_CFGR3_ADCSW 8 +#define STM_RCC_CFGR3_USBSW 7 +#define STM_RCC_CFGR3_CECSW 6 +#define STM_RCC_CFGR3_I2C1SW 4 +#define STM_RCC_CFGR3_USART1SW 0 + +struct stm_crs { + vuint32_t cr; + vuint32_t cfgr; + vuint32_t isr; + vuint32_t icr; +}; + +extern struct stm_crs stm_crs; + +#define STM_CRS_CR_TRIM 8 +#define STM_CRS_CR_SWSYNC 7 +#define STM_CRS_CR_AUTOTRIMEN 6 +#define STM_CRS_CR_CEN 5 +#define STM_CRS_CR_ESYNCIE 3 +#define STM_CRS_CR_ERRIE 2 +#define STM_CRS_CR_SYNCWARNIE 1 +#define STM_CRS_CR_SYNCOKIE 0 + +#define STM_CRS_CFGR_SYNCPOL 31 +#define STM_CRS_CFGR_SYNCSRC 28 +#define STM_CRS_CFGR_SYNCSRC_GPIO 0 +#define STM_CRS_CFGR_SYNCSRC_LSE 1 +#define STM_CRS_CFGR_SYNCSRC_USB 2 +#define STM_CRS_CFGR_SYNCDIV 24 +#define STM_CRS_CFGR_SYNCDIV_1 0 +#define STM_CRS_CFGR_SYNCDIV_2 1 +#define STM_CRS_CFGR_SYNCDIV_4 2 +#define STM_CRS_CFGR_SYNCDIV_8 3 +#define STM_CRS_CFGR_SYNCDIV_16 4 +#define STM_CRS_CFGR_SYNCDIV_32 5 +#define STM_CRS_CFGR_SYNCDIV_64 6 +#define STM_CRS_CFGR_SYNCDIV_128 7 +#define STM_CRS_CFGR_FELIM 16 +#define STM_CRS_CFGR_RELOAD 0 + +#define STM_CRS_ISR_FECAP 16 +#define STM_CRS_ISR_FEDIR 15 +#define STM_CRS_ISR_TRIMOVF 10 +#define STM_CRS_ISR_SYNCMISS 9 +#define STM_CRS_ISR_SYNCERR 8 +#define STM_CRS_ISR_ESYNCF 3 +#define STM_CRS_ISR_ERRF 2 +#define STM_CRS_ISR_SYNCWARNF 1 +#define STM_CRS_ISR_SYNCOKF 0 + +#define STM_CRS_ICR_ESYNCC 3 +#define STM_CRS_ICR_ERRC 2 +#define STM_CRS_ICR_SYNCWARNC 1 +#define STM_CRS_ICR_SYNCOKC 0 + +struct stm_pwr { + vuint32_t cr; + vuint32_t csr; +}; + +extern struct stm_pwr stm_pwr; + +#define STM_PWR_CR_DBP (8) + +#define STM_PWR_CR_PLS (5) +#define STM_PWR_CR_PLS_2_0 0 +#define STM_PWR_CR_PLS_2_1 1 +#define STM_PWR_CR_PLS_2_2 2 +#define STM_PWR_CR_PLS_2_3 3 +#define STM_PWR_CR_PLS_2_4 4 +#define STM_PWR_CR_PLS_2_5 5 +#define STM_PWR_CR_PLS_2_6 6 +#define STM_PWR_CR_PLS_EXT 7 +#define STM_PWR_CR_PLS_MASK 7 + +#define STM_PWR_CR_PVDE (4) +#define STM_PWR_CR_CSBF (3) +#define STM_PWR_CR_CWUF (2) +#define STM_PWR_CR_PDDS (1) +#define STM_PWR_CR_LPSDSR (0) + +#define STM_PWR_CSR_EWUP3 (10) +#define STM_PWR_CSR_EWUP2 (9) +#define STM_PWR_CSR_EWUP1 (8) +#define STM_PWR_CSR_REGLPF (5) +#define STM_PWR_CSR_VOSF (4) +#define STM_PWR_CSR_VREFINTRDYF (3) +#define STM_PWR_CSR_PVDO (2) +#define STM_PWR_CSR_SBF (1) +#define STM_PWR_CSR_WUF (0) + +struct stm_tim67 { + vuint32_t cr1; + vuint32_t cr2; + uint32_t _unused_08; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + uint32_t _unused_18; + uint32_t _unused_1c; + + uint32_t _unused_20; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; +}; + +extern struct stm_tim67 stm_tim6; + +#define STM_TIM67_CR1_ARPE (7) +#define STM_TIM67_CR1_OPM (3) +#define STM_TIM67_CR1_URS (2) +#define STM_TIM67_CR1_UDIS (1) +#define STM_TIM67_CR1_CEN (0) + +#define STM_TIM67_CR2_MMS (4) +#define STM_TIM67_CR2_MMS_RESET 0 +#define STM_TIM67_CR2_MMS_ENABLE 1 +#define STM_TIM67_CR2_MMS_UPDATE 2 +#define STM_TIM67_CR2_MMS_MASK 7 + +#define STM_TIM67_DIER_UDE (8) +#define STM_TIM67_DIER_UIE (0) + +#define STM_TIM67_SR_UIF (0) + +#define STM_TIM67_EGR_UG (0) + +struct stm_lcd { + vuint32_t cr; + vuint32_t fcr; + vuint32_t sr; + vuint32_t clr; + uint32_t unused_0x10; + vuint32_t ram[8*2]; +}; + +extern struct stm_lcd stm_lcd; + +#define STM_LCD_CR_MUX_SEG (7) + +#define STM_LCD_CR_BIAS (5) +#define STM_LCD_CR_BIAS_1_4 0 +#define STM_LCD_CR_BIAS_1_2 1 +#define STM_LCD_CR_BIAS_1_3 2 +#define STM_LCD_CR_BIAS_MASK 3 + +#define STM_LCD_CR_DUTY (2) +#define STM_LCD_CR_DUTY_STATIC 0 +#define STM_LCD_CR_DUTY_1_2 1 +#define STM_LCD_CR_DUTY_1_3 2 +#define STM_LCD_CR_DUTY_1_4 3 +#define STM_LCD_CR_DUTY_1_8 4 +#define STM_LCD_CR_DUTY_MASK 7 + +#define STM_LCD_CR_VSEL (1) +#define STM_LCD_CR_LCDEN (0) + +#define STM_LCD_FCR_PS (22) +#define STM_LCD_FCR_PS_1 0x0 +#define STM_LCD_FCR_PS_2 0x1 +#define STM_LCD_FCR_PS_4 0x2 +#define STM_LCD_FCR_PS_8 0x3 +#define STM_LCD_FCR_PS_16 0x4 +#define STM_LCD_FCR_PS_32 0x5 +#define STM_LCD_FCR_PS_64 0x6 +#define STM_LCD_FCR_PS_128 0x7 +#define STM_LCD_FCR_PS_256 0x8 +#define STM_LCD_FCR_PS_512 0x9 +#define STM_LCD_FCR_PS_1024 0xa +#define STM_LCD_FCR_PS_2048 0xb +#define STM_LCD_FCR_PS_4096 0xc +#define STM_LCD_FCR_PS_8192 0xd +#define STM_LCD_FCR_PS_16384 0xe +#define STM_LCD_FCR_PS_32768 0xf +#define STM_LCD_FCR_PS_MASK 0xf + +#define STM_LCD_FCR_DIV (18) +#define STM_LCD_FCR_DIV_16 0x0 +#define STM_LCD_FCR_DIV_17 0x1 +#define STM_LCD_FCR_DIV_18 0x2 +#define STM_LCD_FCR_DIV_19 0x3 +#define STM_LCD_FCR_DIV_20 0x4 +#define STM_LCD_FCR_DIV_21 0x5 +#define STM_LCD_FCR_DIV_22 0x6 +#define STM_LCD_FCR_DIV_23 0x7 +#define STM_LCD_FCR_DIV_24 0x8 +#define STM_LCD_FCR_DIV_25 0x9 +#define STM_LCD_FCR_DIV_26 0xa +#define STM_LCD_FCR_DIV_27 0xb +#define STM_LCD_FCR_DIV_28 0xc +#define STM_LCD_FCR_DIV_29 0xd +#define STM_LCD_FCR_DIV_30 0xe +#define STM_LCD_FCR_DIV_31 0xf +#define STM_LCD_FCR_DIV_MASK 0xf + +#define STM_LCD_FCR_BLINK (16) +#define STM_LCD_FCR_BLINK_DISABLE 0 +#define STM_LCD_FCR_BLINK_SEG0_COM0 1 +#define STM_LCD_FCR_BLINK_SEG0_COMALL 2 +#define STM_LCD_FCR_BLINK_SEGALL_COMALL 3 +#define STM_LCD_FCR_BLINK_MASK 3 + +#define STM_LCD_FCR_BLINKF (13) +#define STM_LCD_FCR_BLINKF_8 0 +#define STM_LCD_FCR_BLINKF_16 1 +#define STM_LCD_FCR_BLINKF_32 2 +#define STM_LCD_FCR_BLINKF_64 3 +#define STM_LCD_FCR_BLINKF_128 4 +#define STM_LCD_FCR_BLINKF_256 5 +#define STM_LCD_FCR_BLINKF_512 6 +#define STM_LCD_FCR_BLINKF_1024 7 +#define STM_LCD_FCR_BLINKF_MASK 7 + +#define STM_LCD_FCR_CC (10) +#define STM_LCD_FCR_CC_MASK 7 + +#define STM_LCD_FCR_DEAD (7) +#define STM_LCD_FCR_DEAD_MASK 7 + +#define STM_LCD_FCR_PON (4) +#define STM_LCD_FCR_PON_MASK 7 + +#define STM_LCD_FCR_UDDIE (3) +#define STM_LCD_FCR_SOFIE (1) +#define STM_LCD_FCR_HD (0) + +#define STM_LCD_SR_FCRSF (5) +#define STM_LCD_SR_RDY (4) +#define STM_LCD_SR_UDD (3) +#define STM_LCD_SR_UDR (2) +#define STM_LCD_SR_SOF (1) +#define STM_LCD_SR_ENS (0) + +#define STM_LCD_CLR_UDDC (3) +#define STM_LCD_CLR_SOFC (1) + +/* The SYSTICK starts at 0xe000e010 */ + +struct stm_systick { + vuint32_t csr; + vuint32_t rvr; + vuint32_t cvr; + vuint32_t calib; +}; + +extern struct stm_systick stm_systick; + +#define STM_SYSTICK_CSR_ENABLE 0 +#define STM_SYSTICK_CSR_TICKINT 1 +#define STM_SYSTICK_CSR_CLKSOURCE 2 +#define STM_SYSTICK_CSR_CLKSOURCE_EXTERNAL 0 +#define STM_SYSTICK_CSR_CLKSOURCE_HCLK_8 1 +#define STM_SYSTICK_CSR_COUNTFLAG 16 + +/* The NVIC starts at 0xe000e100, so add that to the offsets to find the absolute address */ + +struct stm_nvic { + vuint32_t iser; /* 0x000 0xe000e100 Set Enable Register */ + + uint8_t _unused020[0x080 - 0x004]; + + vuint32_t icer; /* 0x080 0xe000e180 Clear Enable Register */ + + uint8_t _unused0a0[0x100 - 0x084]; + + vuint32_t ispr; /* 0x100 0xe000e200 Set Pending Register */ + + uint8_t _unused120[0x180 - 0x104]; + + vuint32_t icpr; /* 0x180 0xe000e280 Clear Pending Register */ + + uint8_t _unused1a0[0x300 - 0x184]; + + vuint32_t ipr[8]; /* 0x300 0xe000e400 Priority Register */ +}; + +extern struct stm_nvic stm_nvic; + +#define IRQ_MASK(irq) (1 << (irq)) +#define IRQ_BOOL(v,irq) (((v) >> (irq)) & 1) + +static inline void +stm_nvic_set_enable(int irq) { + stm_nvic.iser = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_enable(int irq) { + stm_nvic.icer = IRQ_MASK(irq); +} + +static inline int +stm_nvic_enabled(int irq) { + return IRQ_BOOL(stm_nvic.iser, irq); +} + +static inline void +stm_nvic_set_pending(int irq) { + stm_nvic.ispr = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_pending(int irq) { + stm_nvic.icpr = IRQ_MASK(irq); +} + +static inline int +stm_nvic_pending(int irq) { + return IRQ_BOOL(stm_nvic.ispr, irq); +} + +#define IRQ_PRIO_REG(irq) ((irq) >> 2) +#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3) +#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq)) + +static inline void +stm_nvic_set_priority(int irq, uint8_t prio) { + int n = IRQ_PRIO_REG(irq); + uint32_t v; + + v = stm_nvic.ipr[n]; + v &= ~IRQ_PRIO_MASK(irq); + v |= (prio) << IRQ_PRIO_BIT(irq); + stm_nvic.ipr[n] = v; +} + +static inline uint8_t +stm_nvic_get_priority(int irq) { + return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); +} + +struct stm_scb { + vuint32_t cpuid; + vuint32_t icsr; + vuint32_t vtor; + vuint32_t aircr; + + vuint32_t scr; + vuint32_t ccr; + vuint32_t shpr1; + vuint32_t shpr2; + + vuint32_t shpr3; + vuint32_t shcrs; + vuint32_t cfsr; + vuint32_t hfsr; + + uint32_t unused_30; + vuint32_t mmfar; + vuint32_t bfar; +}; + +extern struct stm_scb stm_scb; + +#define STM_SCB_AIRCR_VECTKEY 16 +#define STM_SCB_AIRCR_VECTKEY_KEY 0x05fa +#define STM_SCB_AIRCR_PRIGROUP 8 +#define STM_SCB_AIRCR_SYSRESETREQ 2 +#define STM_SCB_AIRCR_VECTCLRACTIVE 1 +#define STM_SCB_AIRCR_VECTRESET 0 + +struct stm_mpu { + vuint32_t typer; + vuint32_t cr; + vuint32_t rnr; + vuint32_t rbar; + + vuint32_t rasr; + vuint32_t rbar_a1; + vuint32_t rasr_a1; + vuint32_t rbar_a2; + vuint32_t rasr_a2; + vuint32_t rbar_a3; + vuint32_t rasr_a3; +}; + +extern struct stm_mpu stm_mpu; + +#define STM_MPU_TYPER_IREGION 16 +#define STM_MPU_TYPER_IREGION_MASK 0xff +#define STM_MPU_TYPER_DREGION 8 +#define STM_MPU_TYPER_DREGION_MASK 0xff +#define STM_MPU_TYPER_SEPARATE 0 + +#define STM_MPU_CR_PRIVDEFENA 2 +#define STM_MPU_CR_HFNMIENA 1 +#define STM_MPU_CR_ENABLE 0 + +#define STM_MPU_RNR_REGION 0 +#define STM_MPU_RNR_REGION_MASK 0xff + +#define STM_MPU_RBAR_ADDR 5 +#define STM_MPU_RBAR_ADDR_MASK 0x7ffffff + +#define STM_MPU_RBAR_VALID 4 +#define STM_MPU_RBAR_REGION 0 +#define STM_MPU_RBAR_REGION_MASK 0xf + +#define STM_MPU_RASR_XN 28 +#define STM_MPU_RASR_AP 24 +#define STM_MPU_RASR_AP_NONE_NONE 0 +#define STM_MPU_RASR_AP_RW_NONE 1 +#define STM_MPU_RASR_AP_RW_RO 2 +#define STM_MPU_RASR_AP_RW_RW 3 +#define STM_MPU_RASR_AP_RO_NONE 5 +#define STM_MPU_RASR_AP_RO_RO 6 +#define STM_MPU_RASR_AP_MASK 7 +#define STM_MPU_RASR_TEX 19 +#define STM_MPU_RASR_TEX_MASK 7 +#define STM_MPU_RASR_S 18 +#define STM_MPU_RASR_C 17 +#define STM_MPU_RASR_B 16 +#define STM_MPU_RASR_SRD 8 +#define STM_MPU_RASR_SRD_MASK 0xff +#define STM_MPU_RASR_SIZE 1 +#define STM_MPU_RASR_SIZE_MASK 0x1f +#define STM_MPU_RASR_ENABLE 0 + +#define isr(name) void stm_ ## name ## _isr(void); + +isr(nmi) +isr(hardfault) +isr(memmanage) +isr(busfault) +isr(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(tamper_stamp) +isr(rtc_wkup) +isr(flash) +isr(rcc) +isr(exti0) +isr(exti1) +isr(exti2) +isr(exti3) +isr(exti4) +isr(dma1_channel1) +isr(dma1_channel2) +isr(dma1_channel3) +isr(dma1_channel4) +isr(dma1_channel5) +isr(dma1_channel6) +isr(dma1_channel7) +isr(adc1) +isr(usb_hp) +isr(usb_lp) +isr(dac) +isr(comp) +isr(exti9_5) +isr(lcd) +isr(tim9) +isr(tim10) +isr(tim11) +isr(tim2) +isr(tim3) +isr(tim4) +isr(i2c1_ev) +isr(i2c1_er) +isr(i2c2_ev) +isr(i2c2_er) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(exti15_10) +isr(rtc_alarm) +isr(usb_fs_wkup) +isr(tim6) +isr(tim7) + +#undef isr + +#define STM_ISR_WWDG_POS 0 +#define STM_ISR_PVD_VDDIO2_POS 1 +#define STM_ISR_RTC_POS 2 +#define STM_ISR_FLASH_POS 3 +#define STM_ISR_RCC_CRS_POS 4 +#define STM_ISR_EXTI0_1_POS 5 +#define STM_ISR_EXTI2_3_POS 6 +#define STM_ISR_EXTI4_15_POS 7 +#define STM_ISR_TSC_POS 8 +#define STM_ISR_DMA_CH1_POS 9 +#define STM_ISR_DMA_CH2_3_DMA2_CH1_2_POS 10 +#define STM_ISR_DMA_CH44_5_6_7_DMA2_CH3_4_5_POS 11 +#define STM_ISR_ADC_COMP_POS 12 +#define STM_ISR_TIM1_BRK_UP_TRG_COM_POS 13 +#define STM_ISR_TIM1_CC_POS 14 +#define STM_ISR_TIM2_POS 15 +#define STM_ISR_TIM3_POS 16 +#define STM_ISR_TIM6_DAC_POS 17 +#define STM_ISR_TIM7_POS 18 +#define STM_ISR_TIM14_POS 19 +#define STM_ISR_TIM15_POS 20 +#define STM_ISR_TIM16_POS 21 +#define STM_ISR_TIM17_POS 22 +#define STM_ISR_I2C1_POS 23 +#define STM_ISR_I2C2_POS 24 +#define STM_ISR_SPI1_POS 25 +#define STM_ISR_SPI2_POS 26 +#define STM_ISR_USART1_POS 27 +#define STM_ISR_USART2_POS 28 +#define STM_ISR_UASART3_4_5_6_7_8_POS 29 +#define STM_ISR_CEC_CAN_POS 30 +#define STM_ISR_USB_POS 31 + +struct stm_syscfg { + vuint32_t cfgr1; + vuint32_t exticr[4]; + vuint32_t cfgr2; +}; + +extern struct stm_syscfg stm_syscfg; + +#if 0 +static inline void +stm_exticr_set(struct stm_gpio *gpio, int pin) { + uint8_t reg = pin >> 2; + uint8_t shift = (pin & 3) << 2; + uint8_t val = 0; + + /* Enable SYSCFG */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN); + + if (gpio == &stm_gpioa) + val = STM_SYSCFG_EXTICR_PA; + else if (gpio == &stm_gpiob) + val = STM_SYSCFG_EXTICR_PB; + else if (gpio == &stm_gpioc) + val = STM_SYSCFG_EXTICR_PC; + else if (gpio == &stm_gpiof) + val = STM_SYSCFG_EXTICR_PF; + + stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift; +} +#endif + + +struct stm_dma_channel { + vuint32_t ccr; + vuint32_t cndtr; + vvoid_t cpar; + vvoid_t cmar; + vuint32_t reserved; +}; + +#define STM_NUM_DMA 7 + +struct stm_dma { + vuint32_t isr; + vuint32_t ifcr; + struct stm_dma_channel channel[STM_NUM_DMA]; +}; + +extern struct stm_dma stm_dma; + +/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh) + */ + +#define STM_DMA_INDEX(channel) ((channel) - 1) + +#define STM_DMA_ISR(index) ((index) << 2) +#define STM_DMA_ISR_MASK 0xf +#define STM_DMA_ISR_TEIF 3 +#define STM_DMA_ISR_HTIF 2 +#define STM_DMA_ISR_TCIF 1 +#define STM_DMA_ISR_GIF 0 + +#define STM_DMA_IFCR(index) ((index) << 2) +#define STM_DMA_IFCR_MASK 0xf +#define STM_DMA_IFCR_CTEIF 3 +#define STM_DMA_IFCR_CHTIF 2 +#define STM_DMA_IFCR_CTCIF 1 +#define STM_DMA_IFCR_CGIF 0 + +#define STM_DMA_CCR_MEM2MEM (14) + +#define STM_DMA_CCR_PL (12) +#define STM_DMA_CCR_PL_LOW (0) +#define STM_DMA_CCR_PL_MEDIUM (1) +#define STM_DMA_CCR_PL_HIGH (2) +#define STM_DMA_CCR_PL_VERY_HIGH (3) +#define STM_DMA_CCR_PL_MASK (3) + +#define STM_DMA_CCR_MSIZE (10) +#define STM_DMA_CCR_MSIZE_8 (0) +#define STM_DMA_CCR_MSIZE_16 (1) +#define STM_DMA_CCR_MSIZE_32 (2) +#define STM_DMA_CCR_MSIZE_MASK (3) + +#define STM_DMA_CCR_PSIZE (8) +#define STM_DMA_CCR_PSIZE_8 (0) +#define STM_DMA_CCR_PSIZE_16 (1) +#define STM_DMA_CCR_PSIZE_32 (2) +#define STM_DMA_CCR_PSIZE_MASK (3) + +#define STM_DMA_CCR_MINC (7) +#define STM_DMA_CCR_PINC (6) +#define STM_DMA_CCR_CIRC (5) +#define STM_DMA_CCR_DIR (4) +#define STM_DMA_CCR_DIR_PER_TO_MEM 0 +#define STM_DMA_CCR_DIR_MEM_TO_PER 1 +#define STM_DMA_CCR_TEIE (3) +#define STM_DMA_CCR_HTIE (2) +#define STM_DMA_CCR_TCIE (1) +#define STM_DMA_CCR_EN (0) + +#define STM_DMA_CHANNEL_ADC1 1 +#define STM_DMA_CHANNEL_SPI1_RX 2 +#define STM_DMA_CHANNEL_SPI1_TX 3 +#define STM_DMA_CHANNEL_SPI2_RX 4 +#define STM_DMA_CHANNEL_SPI2_TX 5 +#define STM_DMA_CHANNEL_USART3_TX 2 +#define STM_DMA_CHANNEL_USART3_RX 3 +#define STM_DMA_CHANNEL_USART1_TX 4 +#define STM_DMA_CHANNEL_USART1_RX 5 +#define STM_DMA_CHANNEL_USART2_RX 6 +#define STM_DMA_CHANNEL_USART2_TX 7 +#define STM_DMA_CHANNEL_I2C2_TX 4 +#define STM_DMA_CHANNEL_I2C2_RX 5 +#define STM_DMA_CHANNEL_I2C1_TX 6 +#define STM_DMA_CHANNEL_I2C1_RX 7 +#define STM_DMA_CHANNEL_TIM2_CH3 1 +#define STM_DMA_CHANNEL_TIM2_UP 2 +#define STM_DMA_CHANNEL_TIM2_CH1 5 +#define STM_DMA_CHANNEL_TIM2_CH2 7 +#define STM_DMA_CHANNEL_TIM2_CH4 7 +#define STM_DMA_CHANNEL_TIM3_CH3 2 +#define STM_DMA_CHANNEL_TIM3_CH4 3 +#define STM_DMA_CHANNEL_TIM3_UP 3 +#define STM_DMA_CHANNEL_TIM3_CH1 6 +#define STM_DMA_CHANNEL_TIM3_TRIG 6 +#define STM_DMA_CHANNEL_TIM4_CH1 1 +#define STM_DMA_CHANNEL_TIM4_CH2 4 +#define STM_DMA_CHANNEL_TIM4_CH3 5 +#define STM_DMA_CHANNEL_TIM4_UP 7 +#define STM_DMA_CHANNEL_TIM6_UP_DA 2 +#define STM_DMA_CHANNEL_C_CHANNEL1 2 +#define STM_DMA_CHANNEL_TIM7_UP_DA 3 +#define STM_DMA_CHANNEL_C_CHANNEL2 3 + +/* + * Only spi channel 1 and 2 can use DMA + */ +#define STM_NUM_SPI 2 + +struct stm_spi { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t sr; + vuint32_t dr; + vuint32_t crcpr; + vuint32_t rxcrcr; + vuint32_t txcrcr; +}; + +extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; + +/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh) + */ + +#define STM_SPI_INDEX(channel) ((channel) - 1) + +#define STM_SPI_CR1_BIDIMODE 15 +#define STM_SPI_CR1_BIDIOE 14 +#define STM_SPI_CR1_CRCEN 13 +#define STM_SPI_CR1_CRCNEXT 12 +#define STM_SPI_CR1_DFF 11 +#define STM_SPI_CR1_RXONLY 10 +#define STM_SPI_CR1_SSM 9 +#define STM_SPI_CR1_SSI 8 +#define STM_SPI_CR1_LSBFIRST 7 +#define STM_SPI_CR1_SPE 6 +#define STM_SPI_CR1_BR 3 +#define STM_SPI_CR1_BR_PCLK_2 0 +#define STM_SPI_CR1_BR_PCLK_4 1 +#define STM_SPI_CR1_BR_PCLK_8 2 +#define STM_SPI_CR1_BR_PCLK_16 3 +#define STM_SPI_CR1_BR_PCLK_32 4 +#define STM_SPI_CR1_BR_PCLK_64 5 +#define STM_SPI_CR1_BR_PCLK_128 6 +#define STM_SPI_CR1_BR_PCLK_256 7 +#define STM_SPI_CR1_BR_MASK 7 + +#define STM_SPI_CR1_MSTR 2 +#define STM_SPI_CR1_CPOL 1 +#define STM_SPI_CR1_CPHA 0 + +#define STM_SPI_CR2_TXEIE 7 +#define STM_SPI_CR2_RXNEIE 6 +#define STM_SPI_CR2_ERRIE 5 +#define STM_SPI_CR2_SSOE 2 +#define STM_SPI_CR2_TXDMAEN 1 +#define STM_SPI_CR2_RXDMAEN 0 + +#define STM_SPI_SR_BSY 7 +#define STM_SPI_SR_OVR 6 +#define STM_SPI_SR_MODF 5 +#define STM_SPI_SR_CRCERR 4 +#define STM_SPI_SR_TXE 1 +#define STM_SPI_SR_RXNE 0 + +struct stm_adc { + vuint32_t sr; + vuint32_t cr1; + vuint32_t cr2; + vuint32_t smpr1; + vuint32_t smpr2; + vuint32_t smpr3; + vuint32_t jofr1; + vuint32_t jofr2; + vuint32_t jofr3; + vuint32_t jofr4; + vuint32_t htr; + vuint32_t ltr; + vuint32_t sqr1; + vuint32_t sqr2; + vuint32_t sqr3; + vuint32_t sqr4; + vuint32_t sqr5; + vuint32_t jsqr; + vuint32_t jdr1; + vuint32_t jdr2; + vuint32_t jdr3; + vuint32_t jdr4; + vuint32_t dr; + uint8_t reserved[0x300 - 0x5c]; + vuint32_t csr; + vuint32_t ccr; +}; + +extern struct stm_adc stm_adc; + +#define STM_ADC_SR_JCNR 9 +#define STM_ADC_SR_RCNR 8 +#define STM_ADC_SR_ADONS 6 +#define STM_ADC_SR_OVR 5 +#define STM_ADC_SR_STRT 4 +#define STM_ADC_SR_JSTRT 3 +#define STM_ADC_SR_JEOC 2 +#define STM_ADC_SR_EOC 1 +#define STM_ADC_SR_AWD 0 + +#define STM_ADC_CR1_OVRIE 26 +#define STM_ADC_CR1_RES 24 +#define STM_ADC_CR1_RES_12 0 +#define STM_ADC_CR1_RES_10 1 +#define STM_ADC_CR1_RES_8 2 +#define STM_ADC_CR1_RES_6 3 +#define STM_ADC_CR1_RES_MASK 3 +#define STM_ADC_CR1_AWDEN 23 +#define STM_ADC_CR1_JAWDEN 22 +#define STM_ADC_CR1_PDI 17 +#define STM_ADC_CR1_PDD 16 +#define STM_ADC_CR1_DISCNUM 13 +#define STM_ADC_CR1_DISCNUM_1 0 +#define STM_ADC_CR1_DISCNUM_2 1 +#define STM_ADC_CR1_DISCNUM_3 2 +#define STM_ADC_CR1_DISCNUM_4 3 +#define STM_ADC_CR1_DISCNUM_5 4 +#define STM_ADC_CR1_DISCNUM_6 5 +#define STM_ADC_CR1_DISCNUM_7 6 +#define STM_ADC_CR1_DISCNUM_8 7 +#define STM_ADC_CR1_DISCNUM_MASK 7 +#define STM_ADC_CR1_JDISCEN 12 +#define STM_ADC_CR1_DISCEN 11 +#define STM_ADC_CR1_JAUTO 10 +#define STM_ADC_CR1_AWDSGL 9 +#define STM_ADC_CR1_SCAN 8 +#define STM_ADC_CR1_JEOCIE 7 +#define STM_ADC_CR1_AWDIE 6 +#define STM_ADC_CR1_EOCIE 5 +#define STM_ADC_CR1_AWDCH 0 +#define STM_ADC_CR1_AWDCH_MASK 0x1f + +#define STM_ADC_CR2_SWSTART 30 +#define STM_ADC_CR2_EXTEN 28 +#define STM_ADC_CR2_EXTEN_DISABLE 0 +#define STM_ADC_CR2_EXTEN_RISING 1 +#define STM_ADC_CR2_EXTEN_FALLING 2 +#define STM_ADC_CR2_EXTEN_BOTH 3 +#define STM_ADC_CR2_EXTEN_MASK 3 +#define STM_ADC_CR2_EXTSEL 24 +#define STM_ADC_CR2_EXTSEL_TIM9_CC2 0 +#define STM_ADC_CR2_EXTSEL_TIM9_TRGO 1 +#define STM_ADC_CR2_EXTSEL_TIM2_CC3 2 +#define STM_ADC_CR2_EXTSEL_TIM2_CC2 3 +#define STM_ADC_CR2_EXTSEL_TIM3_TRGO 4 +#define STM_ADC_CR2_EXTSEL_TIM4_CC4 5 +#define STM_ADC_CR2_EXTSEL_TIM2_TRGO 6 +#define STM_ADC_CR2_EXTSEL_TIM3_CC1 7 +#define STM_ADC_CR2_EXTSEL_TIM3_CC3 8 +#define STM_ADC_CR2_EXTSEL_TIM4_TRGO 9 +#define STM_ADC_CR2_EXTSEL_TIM6_TRGO 10 +#define STM_ADC_CR2_EXTSEL_EXTI_11 15 +#define STM_ADC_CR2_EXTSEL_MASK 15 +#define STM_ADC_CR2_JWSTART 22 +#define STM_ADC_CR2_JEXTEN 20 +#define STM_ADC_CR2_JEXTEN_DISABLE 0 +#define STM_ADC_CR2_JEXTEN_RISING 1 +#define STM_ADC_CR2_JEXTEN_FALLING 2 +#define STM_ADC_CR2_JEXTEN_BOTH 3 +#define STM_ADC_CR2_JEXTEN_MASK 3 +#define STM_ADC_CR2_JEXTSEL 16 +#define STM_ADC_CR2_JEXTSEL_TIM9_CC1 0 +#define STM_ADC_CR2_JEXTSEL_TIM9_TRGO 1 +#define STM_ADC_CR2_JEXTSEL_TIM2_TRGO 2 +#define STM_ADC_CR2_JEXTSEL_TIM2_CC1 3 +#define STM_ADC_CR2_JEXTSEL_TIM3_CC4 4 +#define STM_ADC_CR2_JEXTSEL_TIM4_TRGO 5 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC1 6 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC2 7 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC3 8 +#define STM_ADC_CR2_JEXTSEL_TIM10_CC1 9 +#define STM_ADC_CR2_JEXTSEL_TIM7_TRGO 10 +#define STM_ADC_CR2_JEXTSEL_EXTI_15 15 +#define STM_ADC_CR2_JEXTSEL_MASK 15 +#define STM_ADC_CR2_ALIGN 11 +#define STM_ADC_CR2_EOCS 10 +#define STM_ADC_CR2_DDS 9 +#define STM_ADC_CR2_DMA 8 +#define STM_ADC_CR2_DELS 4 +#define STM_ADC_CR2_DELS_NONE 0 +#define STM_ADC_CR2_DELS_UNTIL_READ 1 +#define STM_ADC_CR2_DELS_7 2 +#define STM_ADC_CR2_DELS_15 3 +#define STM_ADC_CR2_DELS_31 4 +#define STM_ADC_CR2_DELS_63 5 +#define STM_ADC_CR2_DELS_127 6 +#define STM_ADC_CR2_DELS_255 7 +#define STM_ADC_CR2_DELS_MASK 7 +#define STM_ADC_CR2_CONT 1 +#define STM_ADC_CR2_ADON 0 + +#define STM_ADC_CCR_TSVREFE 23 +#define STM_ADC_CCR_ADCPRE 16 +#define STM_ADC_CCR_ADCPRE_HSI_1 0 +#define STM_ADC_CCR_ADCPRE_HSI_2 1 +#define STM_ADC_CCR_ADCPRE_HSI_4 2 +#define STM_ADC_CCR_ADCPRE_MASK 3 + +struct stm_temp_cal { + uint16_t vref; + uint16_t ts_cal_cold; + uint16_t reserved; + uint16_t ts_cal_hot; +}; + +extern struct stm_temp_cal stm_temp_cal; + +#define stm_temp_cal_cold 25 +#define stm_temp_cal_hot 110 + +struct stm_dbg_mcu { + uint32_t idcode; +}; + +extern struct stm_dbg_mcu stm_dbg_mcu; + +static inline uint16_t +stm_dev_id(void) { + return stm_dbg_mcu.idcode & 0xfff; +} + +struct stm_flash_size { + uint16_t f_size; +}; + +extern struct stm_flash_size stm_flash_size_medium; +extern struct stm_flash_size stm_flash_size_large; + +/* Returns flash size in bytes */ +extern uint32_t +stm_flash_size(void); + +struct stm_device_id { + uint32_t u_id0; + uint32_t u_id1; + uint32_t u_id2; +}; + +extern struct stm_device_id stm_device_id; + +#define STM_NUM_I2C 2 + +#define STM_I2C_INDEX(channel) ((channel) - 1) + +struct stm_i2c { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t oar1; + vuint32_t oar2; + vuint32_t dr; + vuint32_t sr1; + vuint32_t sr2; + vuint32_t ccr; + vuint32_t trise; +}; + +extern struct stm_i2c stm_i2c1, stm_i2c2; + +#define STM_I2C_CR1_SWRST 15 +#define STM_I2C_CR1_ALERT 13 +#define STM_I2C_CR1_PEC 12 +#define STM_I2C_CR1_POS 11 +#define STM_I2C_CR1_ACK 10 +#define STM_I2C_CR1_STOP 9 +#define STM_I2C_CR1_START 8 +#define STM_I2C_CR1_NOSTRETCH 7 +#define STM_I2C_CR1_ENGC 6 +#define STM_I2C_CR1_ENPEC 5 +#define STM_I2C_CR1_ENARP 4 +#define STM_I2C_CR1_SMBTYPE 3 +#define STM_I2C_CR1_SMBUS 1 +#define STM_I2C_CR1_PE 0 + +#define STM_I2C_CR2_LAST 12 +#define STM_I2C_CR2_DMAEN 11 +#define STM_I2C_CR2_ITBUFEN 10 +#define STM_I2C_CR2_ITEVTEN 9 +#define STM_I2C_CR2_ITERREN 8 +#define STM_I2C_CR2_FREQ 0 +#define STM_I2C_CR2_FREQ_2_MHZ 2 +#define STM_I2C_CR2_FREQ_4_MHZ 4 +#define STM_I2C_CR2_FREQ_8_MHZ 8 +#define STM_I2C_CR2_FREQ_16_MHZ 16 +#define STM_I2C_CR2_FREQ_32_MHZ 32 +#define STM_I2C_CR2_FREQ_MASK 0x3f + +#define STM_I2C_SR1_SMBALERT 15 +#define STM_I2C_SR1_TIMEOUT 14 +#define STM_I2C_SR1_PECERR 12 +#define STM_I2C_SR1_OVR 11 +#define STM_I2C_SR1_AF 10 +#define STM_I2C_SR1_ARLO 9 +#define STM_I2C_SR1_BERR 8 +#define STM_I2C_SR1_TXE 7 +#define STM_I2C_SR1_RXNE 6 +#define STM_I2C_SR1_STOPF 4 +#define STM_I2C_SR1_ADD10 3 +#define STM_I2C_SR1_BTF 2 +#define STM_I2C_SR1_ADDR 1 +#define STM_I2C_SR1_SB 0 + +#define STM_I2C_SR2_PEC 8 +#define STM_I2C_SR2_PEC_MASK 0xff00 +#define STM_I2C_SR2_DUALF 7 +#define STM_I2C_SR2_SMBHOST 6 +#define STM_I2C_SR2_SMBDEFAULT 5 +#define STM_I2C_SR2_GENCALL 4 +#define STM_I2C_SR2_TRA 2 +#define STM_I2C_SR2_BUSY 1 +#define STM_I2C_SR2_MSL 0 + +#define STM_I2C_CCR_FS 15 +#define STM_I2C_CCR_DUTY 14 +#define STM_I2C_CCR_CCR 0 +#define STM_I2C_CCR_MASK 0x7ff + +struct stm_tim234 { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t smcr; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + vuint32_t ccmr1; + vuint32_t ccmr2; + + vuint32_t ccer; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; + + uint32_t reserved_30; + vuint32_t ccr1; + vuint32_t ccr2; + vuint32_t ccr3; + + vuint32_t ccr4; + uint32_t reserved_44; + vuint32_t dcr; + vuint32_t dmar; + + uint32_t reserved_50; +}; + +extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; + +#define STM_TIM234_CR1_CKD 8 +#define STM_TIM234_CR1_CKD_1 0 +#define STM_TIM234_CR1_CKD_2 1 +#define STM_TIM234_CR1_CKD_4 2 +#define STM_TIM234_CR1_CKD_MASK 3 +#define STM_TIM234_CR1_ARPE 7 +#define STM_TIM234_CR1_CMS 5 +#define STM_TIM234_CR1_CMS_EDGE 0 +#define STM_TIM234_CR1_CMS_CENTER_1 1 +#define STM_TIM234_CR1_CMS_CENTER_2 2 +#define STM_TIM234_CR1_CMS_CENTER_3 3 +#define STM_TIM234_CR1_CMS_MASK 3 +#define STM_TIM234_CR1_DIR 4 +#define STM_TIM234_CR1_DIR_UP 0 +#define STM_TIM234_CR1_DIR_DOWN 1 +#define STM_TIM234_CR1_OPM 3 +#define STM_TIM234_CR1_URS 2 +#define STM_TIM234_CR1_UDIS 1 +#define STM_TIM234_CR1_CEN 0 + +#define STM_TIM234_CR2_TI1S 7 +#define STM_TIM234_CR2_MMS 4 +#define STM_TIM234_CR2_MMS_RESET 0 +#define STM_TIM234_CR2_MMS_ENABLE 1 +#define STM_TIM234_CR2_MMS_UPDATE 2 +#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3 +#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4 +#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5 +#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6 +#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7 +#define STM_TIM234_CR2_MMS_MASK 7 +#define STM_TIM234_CR2_CCDS 3 + +#define STM_TIM234_SMCR_ETP 15 +#define STM_TIM234_SMCR_ECE 14 +#define STM_TIM234_SMCR_ETPS 12 +#define STM_TIM234_SMCR_ETPS_OFF 0 +#define STM_TIM234_SMCR_ETPS_DIV_2 1 +#define STM_TIM234_SMCR_ETPS_DIV_4 2 +#define STM_TIM234_SMCR_ETPS_DIV_8 3 +#define STM_TIM234_SMCR_ETPS_MASK 3 +#define STM_TIM234_SMCR_ETF 8 +#define STM_TIM234_SMCR_ETF_NONE 0 +#define STM_TIM234_SMCR_ETF_INT_N_2 1 +#define STM_TIM234_SMCR_ETF_INT_N_4 2 +#define STM_TIM234_SMCR_ETF_INT_N_8 3 +#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4 +#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5 +#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6 +#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7 +#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8 +#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9 +#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10 +#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11 +#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12 +#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13 +#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14 +#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15 +#define STM_TIM234_SMCR_ETF_MASK 15 +#define STM_TIM234_SMCR_MSM 7 +#define STM_TIM234_SMCR_TS 4 +#define STM_TIM234_SMCR_TS_ITR0 0 +#define STM_TIM234_SMCR_TS_ITR1 1 +#define STM_TIM234_SMCR_TS_ITR2 2 +#define STM_TIM234_SMCR_TS_ITR3 3 +#define STM_TIM234_SMCR_TS_TI1F_ED 4 +#define STM_TIM234_SMCR_TS_TI1FP1 5 +#define STM_TIM234_SMCR_TS_TI2FP2 6 +#define STM_TIM234_SMCR_TS_ETRF 7 +#define STM_TIM234_SMCR_TS_MASK 7 +#define STM_TIM234_SMCR_OCCS 3 +#define STM_TIM234_SMCR_SMS 0 +#define STM_TIM234_SMCR_SMS_DISABLE 0 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3 +#define STM_TIM234_SMCR_SMS_RESET_MODE 4 +#define STM_TIM234_SMCR_SMS_GATED_MODE 5 +#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6 +#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7 +#define STM_TIM234_SMCR_SMS_MASK 7 + +#define STM_TIM234_SR_CC4OF 12 +#define STM_TIM234_SR_CC3OF 11 +#define STM_TIM234_SR_CC2OF 10 +#define STM_TIM234_SR_CC1OF 9 +#define STM_TIM234_SR_TIF 6 +#define STM_TIM234_SR_CC4IF 4 +#define STM_TIM234_SR_CC3IF 3 +#define STM_TIM234_SR_CC2IF 2 +#define STM_TIM234_SR_CC1IF 1 +#define STM_TIM234_SR_UIF 0 + +#define STM_TIM234_EGR_TG 6 +#define STM_TIM234_EGR_CC4G 4 +#define STM_TIM234_EGR_CC3G 3 +#define STM_TIM234_EGR_CC2G 2 +#define STM_TIM234_EGR_CC1G 1 +#define STM_TIM234_EGR_UG 0 + +#define STM_TIM234_CCMR1_OC2CE 15 +#define STM_TIM234_CCMR1_OC2M 12 +#define STM_TIM234_CCMR1_OC2M_FROZEN 0 +#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC2M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC2M_MASK 7 +#define STM_TIM234_CCMR1_OC2PE 11 +#define STM_TIM234_CCMR1_OC2FE 10 +#define STM_TIM234_CCMR1_CC2S 8 +#define STM_TIM234_CCMR1_CC2S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2 +#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC2S_MASK 3 + +#define STM_TIM234_CCMR1_OC1CE 7 +#define STM_TIM234_CCMR1_OC1M 4 +#define STM_TIM234_CCMR1_OC1M_FROZEN 0 +#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC1M_MASK 7 +#define STM_TIM234_CCMR1_OC1PE 11 +#define STM_TIM234_CCMR1_OC1FE 2 +#define STM_TIM234_CCMR1_CC1S 0 +#define STM_TIM234_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC1S_MASK 3 + +#define STM_TIM234_CCMR2_OC4CE 15 +#define STM_TIM234_CCMR2_OC4M 12 +#define STM_TIM234_CCMR2_OC4M_FROZEN 0 +#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC4M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC4M_MASK 7 +#define STM_TIM234_CCMR2_OC4PE 11 +#define STM_TIM234_CCMR2_OC4FE 10 +#define STM_TIM234_CCMR2_CC4S 8 +#define STM_TIM234_CCMR2_CC4S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2 +#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC4S_MASK 3 + +#define STM_TIM234_CCMR2_OC3CE 7 +#define STM_TIM234_CCMR2_OC3M 4 +#define STM_TIM234_CCMR2_OC3M_FROZEN 0 +#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC3M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC3M_MASK 7 +#define STM_TIM234_CCMR2_OC3PE 11 +#define STM_TIM234_CCMR2_OC3FE 2 +#define STM_TIM234_CCMR2_CC3S 0 +#define STM_TIM234_CCMR2_CC3S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2 +#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC3S_MASK 3 + +#define STM_TIM234_CCER_CC4NP 15 +#define STM_TIM234_CCER_CC4P 13 +#define STM_TIM234_CCER_CC4E 12 +#define STM_TIM234_CCER_CC3NP 11 +#define STM_TIM234_CCER_CC3P 9 +#define STM_TIM234_CCER_CC3E 8 +#define STM_TIM234_CCER_CC2NP 7 +#define STM_TIM234_CCER_CC2P 5 +#define STM_TIM234_CCER_CC2E 4 +#define STM_TIM234_CCER_CC1NP 3 +#define STM_TIM234_CCER_CC1P 1 +#define STM_TIM234_CCER_CC1E 0 + +struct stm_usb { + struct { + vuint16_t r; + uint16_t _; + } epr[8]; + uint8_t reserved_20[0x40 - 0x20]; + vuint16_t cntr; + uint16_t reserved_42; + vuint16_t istr; + uint16_t reserved_46; + vuint16_t fnr; + uint16_t reserved_4a; + vuint16_t daddr; + uint16_t reserved_4e; + vuint16_t btable; + uint16_t reserved_52; + vuint16_t lpmcsr; + uint16_t reserved_56; + vuint16_t bcdr; + uint16_t reserved_5a; +}; + +extern struct stm_usb stm_usb; + +#define STM_USB_EPR_CTR_RX 15 +#define STM_USB_EPR_CTR_RX_WRITE_INVARIANT 1 +#define STM_USB_EPR_DTOG_RX 14 +#define STM_USB_EPR_DTOG_RX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_RX 12 +#define STM_USB_EPR_STAT_RX_DISABLED 0 +#define STM_USB_EPR_STAT_RX_STALL 1 +#define STM_USB_EPR_STAT_RX_NAK 2 +#define STM_USB_EPR_STAT_RX_VALID 3 +#define STM_USB_EPR_STAT_RX_MASK 3 +#define STM_USB_EPR_STAT_RX_WRITE_INVARIANT 0 +#define STM_USB_EPR_SETUP 11 +#define STM_USB_EPR_EP_TYPE 9 +#define STM_USB_EPR_EP_TYPE_BULK 0 +#define STM_USB_EPR_EP_TYPE_CONTROL 1 +#define STM_USB_EPR_EP_TYPE_ISO 2 +#define STM_USB_EPR_EP_TYPE_INTERRUPT 3 +#define STM_USB_EPR_EP_TYPE_MASK 3 +#define STM_USB_EPR_EP_KIND 8 +#define STM_USB_EPR_EP_KIND_DBL_BUF 1 /* Bulk */ +#define STM_USB_EPR_EP_KIND_STATUS_OUT 1 /* Control */ +#define STM_USB_EPR_CTR_TX 7 +#define STM_USB_CTR_TX_WRITE_INVARIANT 1 +#define STM_USB_EPR_DTOG_TX 6 +#define STM_USB_EPR_DTOG_TX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_TX 4 +#define STM_USB_EPR_STAT_TX_DISABLED 0 +#define STM_USB_EPR_STAT_TX_STALL 1 +#define STM_USB_EPR_STAT_TX_NAK 2 +#define STM_USB_EPR_STAT_TX_VALID 3 +#define STM_USB_EPR_STAT_TX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_TX_MASK 3 +#define STM_USB_EPR_EA 0 +#define STM_USB_EPR_EA_MASK 0xf + +#define STM_USB_CNTR_CTRM 15 +#define STM_USB_CNTR_PMAOVRM 14 +#define STM_USB_CNTR_ERRM 13 +#define STM_USB_CNTR_WKUPM 12 +#define STM_USB_CNTR_SUSPM 11 +#define STM_USB_CNTR_RESETM 10 +#define STM_USB_CNTR_SOFM 9 +#define STM_USB_CNTR_ESOFM 8 +#define STM_USB_CNTR_RESUME 4 +#define STM_USB_CNTR_FSUSP 3 +#define STM_USB_CNTR_LP_MODE 2 +#define STM_USB_CNTR_PDWN 1 +#define STM_USB_CNTR_FRES 0 + +#define STM_USB_ISTR_CTR 15 +#define STM_USB_ISTR_PMAOVR 14 +#define STM_USB_ISTR_ERR 13 +#define STM_USB_ISTR_WKUP 12 +#define STM_USB_ISTR_SUSP 11 +#define STM_USB_ISTR_RESET 10 +#define STM_USB_ISTR_SOF 9 +#define STM_USB_ISTR_ESOF 8 +#define STM_USB_L1REQ 7 +#define STM_USB_ISTR_DIR 4 +#define STM_USB_ISTR_EP_ID 0 +#define STM_USB_ISTR_EP_ID_MASK 0xf + +#define STM_USB_FNR_RXDP 15 +#define STM_USB_FNR_RXDM 14 +#define STM_USB_FNR_LCK 13 +#define STM_USB_FNR_LSOF 11 +#define STM_USB_FNR_LSOF_MASK 0x3 +#define STM_USB_FNR_FN 0 +#define STM_USB_FNR_FN_MASK 0x7ff + +#define STM_USB_DADDR_EF 7 +#define STM_USB_DADDR_ADD 0 +#define STM_USB_DADDR_ADD_MASK 0x7f + +#define STM_USB_BCDR_DPPU 15 +#define STM_USB_BCDR_PS2DET 7 +#define STM_USB_BCDR_SDET 6 +#define STM_USB_BCDR_PDET 5 +#define STM_USB_BCDR_DCDET 4 +#define STM_USB_BCDR_SDEN 3 +#define STM_USB_BCDR_PDEN 2 +#define STM_USB_BCDR_DCDEN 1 +#define STM_USB_BCDR_BCDEN 0 + +union stm_usb_bdt { + struct { + vuint16_t addr_tx; + vuint16_t count_tx; + vuint16_t addr_rx; + vuint16_t count_rx; + } single; + struct { + vuint16_t addr; + vuint16_t count; + } double_tx[2]; + struct { + vuint16_t addr; + vuint16_t count; + } double_rx[2]; +}; + +#define STM_USB_BDT_COUNT_RX_BL_SIZE 15 +#define STM_USB_BDT_COUNT_RX_NUM_BLOCK 10 +#define STM_USB_BDT_COUNT_RX_NUM_BLOCK_MASK 0x1f +#define STM_USB_BDT_COUNT_RX_COUNT_RX 0 +#define STM_USB_BDT_COUNT_RX_COUNT_RX_MASK 0x1ff + +#define STM_USB_BDT_SIZE 8 + +extern uint8_t stm_usb_sram[]; + +struct stm_exti { + vuint32_t imr; + vuint32_t emr; + vuint32_t rtsr; + vuint32_t ftsr; + + vuint32_t swier; + vuint32_t pr; +}; + +extern struct stm_exti stm_exti; + +#endif /* _STM32F0_H_ */ -- cgit v1.2.3 From 02e1058fa52ee7c867ea6c9031ebb9e21d14889c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Jan 2015 16:43:48 -0800 Subject: altos: USBtrng v2.0 hardware bringup Gets the USB connection running and blinks the LEDs. Signed-off-by: Keith Packard --- src/usbtrng-v2.0/Makefile | 64 +++++++++++++++++++++++++++++++++++++++++++ src/usbtrng-v2.0/ao_pins.h | 45 ++++++++++++++++++++++++++++++ src/usbtrng-v2.0/ao_usbtrng.c | 45 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) create mode 100644 src/usbtrng-v2.0/Makefile create mode 100644 src/usbtrng-v2.0/ao_pins.h create mode 100644 src/usbtrng-v2.0/ao_usbtrng.c (limited to 'src') diff --git a/src/usbtrng-v2.0/Makefile b/src/usbtrng-v2.0/Makefile new file mode 100644 index 00000000..0d237630 --- /dev/null +++ b/src/usbtrng-v2.0/Makefile @@ -0,0 +1,64 @@ +# +# AltOS build +# +# + +include ../stmf0/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + stm32f0.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_timer.c \ + ao_panic.c \ + ao_stdio.c \ + ao_led.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_cmd.c \ + ao_usb_stm.c \ + ao_task.c \ + ao_product.c + +PRODUCT=usbtrng-v2.0 +PRODUCT_DEF=-DUSBTRNG_V_2_0 +IDPRODUCT=0x0028 + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +PROGNAME=usbtrng-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_usbtrng.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/usbtrng-v2.0/ao_pins.h b/src/usbtrng-v2.0/ao_pins.h new file mode 100644 index 00000000..bbf5e153 --- /dev/null +++ b/src/usbtrng-v2.0/ao_pins.h @@ -0,0 +1,45 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define LED_PORT_ENABLE STM_RCC_AHBENR_IOPAEN +#define LED_PORT (&stm_gpioa) +#define LED_PIN_RED 2 +#define LED_PIN_GREEN 3 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define HAS_BEEP 0 + +/* 48MHz clock based on USB */ +#define AO_HSI48 1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER 1 +#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/usbtrng-v2.0/ao_usbtrng.c b/src/usbtrng-v2.0/ao_usbtrng.c new file mode 100644 index 00000000..9b6fd4f1 --- /dev/null +++ b/src/usbtrng-v2.0/ao_usbtrng.c @@ -0,0 +1,45 @@ +/* + * Copyright © 2014 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 + +static void ao_blink(void) +{ + for (;;) { + ao_led_toggle(LEDS_AVAILABLE); + ao_delay(AO_MS_TO_TICKS(500)); + } +} + +struct ao_task blink_task; + +void main(void) +{ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + + ao_cmd_init(); + + ao_usb_init(); + + ao_add_task(&blink_task, ao_blink, "blink"); + + ao_start_scheduler(); +} -- cgit v1.2.3 From df881bce8576f091b2d8cb53b8ce8a43aeedecde Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Jan 2015 19:35:19 -0800 Subject: altos: Add self-flash support for STM32F042 processor Also moves the usual address for applications out of the way of the flash loader. Signed-off-by: Keith Packard --- src/stmf0/Makefile-flash.defs | 61 +++++++++++++++++++ src/stmf0/altos-loader.ld | 94 ++++++++++++++++++++++++++++ src/stmf0/altos.ld | 18 +++--- src/stmf0/ao_arch_funcs.h | 33 ++++------ src/stmf0/ao_boot_chain.c | 2 +- src/stmf0/ao_flash.h | 27 +++++++++ src/stmf0/ao_flash_loader_stm.c | 39 ++++++++++++ src/stmf0/ao_flash_stm.c | 131 ++++++++++++++++++++++++++++++++++++++++ src/stmf0/ao_flash_stm_pins.h | 38 ++++++++++++ src/stmf0/ao_interrupt.c | 19 +++++- src/stmf0/ao_timer.c | 4 ++ src/stmf0/registers.ld | 7 +-- src/stmf0/stm32f0.h | 101 +++++++++++++++++++++++-------- 13 files changed, 513 insertions(+), 61 deletions(-) create mode 100644 src/stmf0/Makefile-flash.defs create mode 100644 src/stmf0/altos-loader.ld create mode 100644 src/stmf0/ao_flash.h create mode 100644 src/stmf0/ao_flash_loader_stm.c create mode 100644 src/stmf0/ao_flash_stm.c create mode 100644 src/stmf0/ao_flash_stm_pins.h (limited to 'src') diff --git a/src/stmf0/Makefile-flash.defs b/src/stmf0/Makefile-flash.defs new file mode 100644 index 00000000..706b93ee --- /dev/null +++ b/src/stmf0/Makefile-flash.defs @@ -0,0 +1,61 @@ +include $(TOPDIR)/stmf0/Makefile-stmf0.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_flash_pins.h \ + ao_flash_stm_pins.h \ + ao_flash_task.h \ + ao_pins.h \ + ao_product.h \ + Makefile + +# +# Common AltOS sources +# +SRC = \ + ao_interrupt.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_boot_pin.c \ + ao_product.c \ + ao_notask.c \ + ao_timer.c \ + ao_usb_stm.c \ + ao_flash_stm.c \ + ao_flash_task.c \ + ao_flash_loader_stm.c + +OBJ=$(SRC:.c=.o) + +PRODUCT=AltosFlash +PRODUCT_DEF=-DALTOS_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld + +PROGNAME=altos-flash +PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf + +$(PROG): Makefile $(OBJ) altos-loader.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +ao_product.h: ao-make-product.5c $(TOPDIR)/Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +all: $(PROG) + +distclean: clean + +clean: + rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/stmf0/altos-loader.ld b/src/stmf0/altos-loader.ld new file mode 100644 index 00000000..2feb515d --- /dev/null +++ b/src/stmf0/altos-loader.ld @@ -0,0 +1,94 @@ +/* + * 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. + */ + +MEMORY { + rom : ORIGIN = 0x08000000, LENGTH = 4K + ram : ORIGIN = 0x20000000, LENGTH = 6K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + *(.text*) /* Executable code */ + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.rodata*) /* Constants */ + } > rom + __text_end__ = .; + + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot (NOLOAD) : { + __boot_start__ = .; + *(.boot) + __boot_end__ = .; + } >ram + + /* Functions placed in RAM (required for flashing) + * + * Align to 8 bytes as that's what the ARM likes text + * segment alignments to be, and if we don't, then + * we end up with a mismatch between the location in + * ROM and the desired location in RAM. I don't + * entirely understand this, but at least this appears + * to work... + */ + + .textram BLOCK(8): { + __data_start__ = .; + __text_ram_start__ = .; + *(.ramtext) + __text_ram_end = .; + } >ram AT>rom + + /* Data -- relocated to RAM, but written to ROM + */ + .data : { + *(.data) /* initialized data */ + __data_end__ = .; + } >ram AT>rom + + + .bss : { + __bss_start__ = .; + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(end = .); +} + +ENTRY(start); + + diff --git a/src/stmf0/altos.ld b/src/stmf0/altos.ld index 6672c1fd..742d8419 100644 --- a/src/stmf0/altos.ld +++ b/src/stmf0/altos.ld @@ -16,9 +16,9 @@ */ MEMORY { - rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K - ram (!w) : ORIGIN = 0x20000000, LENGTH = 5632 - stack (!w) : ORIGIN = 0x20001600, LENGTH = 512 + rom (rx) : ORIGIN = 0x08001000, LENGTH = 28K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 6k - 128 + stack (!w) : ORIGIN = 0x20000000 + 6k - 128, LENGTH = 128 } INCLUDE registers.ld @@ -30,12 +30,15 @@ SECTIONS { * Rom contents */ - .text ORIGIN(rom) : { - __text_start__ = .; + .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) { + __interrupt_start__ = .; + __interrupt_rom__ = ORIGIN(rom); *(.interrupt) /* Interrupt vectors */ + __interrupt_end__ = .; + } > ram - . = ORIGIN(rom) + 0x100; - + .text ORIGIN(rom) + 0x100 : { + __text_start__ = .; /* Ick. What I want is to specify the * addresses of some global constants so @@ -49,6 +52,7 @@ SECTIONS { */ ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) + *(.text*) /* Executable code */ *(.rodata*) /* Constants */ diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index 2f2f8f43..a5c6764b 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -120,31 +120,26 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s #define ao_enable_port(port) do { \ if ((port) == &stm_gpioa) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \ else if ((port) == &stm_gpiob) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \ else if ((port) == &stm_gpioc) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); \ - else if ((port) == &stm_gpiod) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); \ - else if ((port) == &stm_gpioe) \ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \ + else if ((port) == &stm_gpiof) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \ } while (0) #define ao_disable_port(port) do { \ if ((port) == &stm_gpioa) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOAEN); \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \ else if ((port) == &stm_gpiob) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOBEN); \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \ else if ((port) == &stm_gpioc) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOCEN); \ - else if ((port) == &stm_gpiod) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIODEN); \ - else if ((port) == &stm_gpioe) \ - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOEEN); \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \ + else if ((port) == &stm_gpiof) \ + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \ } while (0) - #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) #define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit) @@ -163,7 +158,7 @@ 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_enable_input(port,bit,mode) do { \ ao_enable_port(port); \ stm_moder_set(port, bit, STM_MODER_INPUT); \ @@ -389,10 +384,4 @@ static inline void ao_arch_start_scheduler(void) { ao_arch_irqrestore(__mask); \ } while (0) -void -ao_clock_enable_crs(void); - -void -ao_clock_disable_crs(void); - #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stmf0/ao_boot_chain.c b/src/stmf0/ao_boot_chain.c index bcebf033..83a543a0 100644 --- a/src/stmf0/ao_boot_chain.c +++ b/src/stmf0/ao_boot_chain.c @@ -43,7 +43,7 @@ struct ao_boot { }; static struct ao_boot __attribute__ ((section(".boot"))) ao_boot; - + int ao_boot_check_chain(void) { diff --git a/src/stmf0/ao_flash.h b/src/stmf0/ao_flash.h new file mode 100644 index 00000000..09ca5ac1 --- /dev/null +++ b/src/stmf0/ao_flash.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _AO_FLASH_STM_H_ +#define _AO_FLASH_STM_H_ + +void +ao_flash_erase_page(uint32_t *page); + +void +ao_flash_page(uint32_t *page, uint32_t *src); + +#endif /* _AO_FLASH_STM_H_ */ diff --git a/src/stmf0/ao_flash_loader_stm.c b/src/stmf0/ao_flash_loader_stm.c new file mode 100644 index 00000000..6bf89234 --- /dev/null +++ b/src/stmf0/ao_flash_loader_stm.c @@ -0,0 +1,39 @@ +/* + * 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. + */ + +#include "ao.h" +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + + ao_usb_init(); + +#if HAS_TICK + ao_timer_init(); +#endif + +#ifdef AO_FLASH_LOADER_INIT + AO_FLASH_LOADER_INIT; +#endif + ao_flash_task(); + return 0; +} diff --git a/src/stmf0/ao_flash_stm.c b/src/stmf0/ao_flash_stm.c new file mode 100644 index 00000000..5fe0e619 --- /dev/null +++ b/src/stmf0/ao_flash_stm.c @@ -0,0 +1,131 @@ +/* + * 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. + */ + +#include +#include + +static uint8_t +ao_flash_is_locked(void) +{ + return (stm_flash.cr & (1 << STM_FLASH_CR_LOCK)) != 0; +} + +static void +ao_flash_unlock(void) +{ + if (!ao_flash_is_locked()) + return; + + /* Unlock FLASH_CR register */ + stm_flash.keyr = STM_FLASH_KEYR_KEY1; + stm_flash.keyr = STM_FLASH_KEYR_KEY2; + if (ao_flash_is_locked()) + ao_panic(AO_PANIC_FLASH); +} + +static void +ao_flash_lock(void) +{ + stm_flash.cr |= (1 << STM_FLASH_CR_LOCK); +} + +static void +ao_flash_wait_bsy(void) +{ + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + +static void __attribute__ ((section(".ramtext"),noinline)) +_ao_flash_erase_page(uint32_t *page) +{ + stm_flash.cr |= (1 << STM_FLASH_CR_PER); + + stm_flash.ar = (uintptr_t) page; + + stm_flash.cr |= (1 << STM_FLASH_CR_STRT); + + ao_flash_wait_bsy(); + + stm_flash.cr &= ~(1 << STM_FLASH_CR_PER); +} + +static uint32_t +stm_flash_page_size(void) +{ + uint16_t dev_id = stm_dev_id(); + + switch (dev_id) { + case 0x440: /* stm32f05x */ + case 0x444: /* stm32f03x */ + case 0x445: /* stm32f04x */ + return 1024; + case 0x442: /* stm32f09x */ + case 0x448: /* stm32f07x */ + return 2048; + } + ao_panic(AO_PANIC_FLASH); + return 0; +} + +void +ao_flash_erase_page(uint32_t *page) +{ + /* Erase the whole page at the start. This assumes we'll be flashing things + * in memory order + */ + + if ((uintptr_t) page & (stm_flash_page_size() - 1)) + return; + + ao_arch_block_interrupts(); + ao_flash_unlock(); + + _ao_flash_erase_page(page); + + ao_flash_lock(); + ao_arch_release_interrupts(); +} + +static void __attribute__ ((section(".ramtext"), noinline)) +_ao_flash_page(uint16_t *dst, uint16_t *src) +{ + uint8_t i; + + stm_flash.cr |= (1 << STM_FLASH_CR_PG); + + for (i = 0; i < 128; i++) { + *dst++ = *src++; + ao_flash_wait_bsy(); + } + + stm_flash.cr &= ~(1 << STM_FLASH_CR_PG); +} + +void +ao_flash_page(uint32_t *page, uint32_t *src) +{ + ao_flash_erase_page(page); + + ao_arch_block_interrupts(); + ao_flash_unlock(); + + _ao_flash_page((uint16_t *) page, (uint16_t *) src); + + ao_flash_lock(); + ao_arch_release_interrupts(); +} diff --git a/src/stmf0/ao_flash_stm_pins.h b/src/stmf0/ao_flash_stm_pins.h new file mode 100644 index 00000000..ab60b4f3 --- /dev/null +++ b/src/stmf0/ao_flash_stm_pins.h @@ -0,0 +1,38 @@ +/* + * 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. + */ + +#ifndef _AO_FLASH_STM_PINS_H_ +#define _AO_FLASH_STM_PINS_H_ + +#include + +/* 48MHz clock based on USB */ +#define AO_HSI48 1 + +/* HCLK = 48MHz */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* APB = 48MHz */ +#define AO_APB_PRESCALER 1 +#define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 + +#define HAS_USB 1 + +#define AO_NEED_HSI 1 + +#endif /* _AO_FLASH_STM_PINS_H_ */ diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c index 99a88dcb..b6a3147f 100644 --- a/src/stmf0/ao_interrupt.c +++ b/src/stmf0/ao_interrupt.c @@ -20,11 +20,23 @@ #include #include +#ifndef IS_FLASH_LOADER +#error Should define IS_FLASH_LOADER +#define IS_FLASH_LOADER 0 +#endif + +#if !IS_FLASH_LOADER +#define RELOCATE_INTERRUPT 1 +#endif + extern void main(void); extern char __stack__; extern char __text_start__, __text_end__; extern char __data_start__, __data_end__; extern char __bss_start__, __bss_end__; +#if RELOCATE_INTERRUPT +extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__; +#endif /* Interrupt functions */ @@ -46,7 +58,7 @@ stm_flash_size(void) { switch (dev_id) { case 0x445: - kbytes = 32; /* assume 32kB until we figure this out */ + kbytes = stm_flash_size_04x.f_size; break; } return (uint32_t) kbytes * 1024; @@ -54,7 +66,6 @@ stm_flash_size(void) { void start(void) { -#if 0 #ifdef AO_BOOT_CHAIN if (ao_boot_check_chain()) { #ifdef AO_BOOT_PIN @@ -62,6 +73,10 @@ void start(void) #endif } #endif +#if RELOCATE_INTERRUPT + memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__); + stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) | + (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE); #endif memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); diff --git a/src/stmf0/ao_timer.c b/src/stmf0/ao_timer.c index 82a4cad6..3aae7e55 100644 --- a/src/stmf0/ao_timer.c +++ b/src/stmf0/ao_timer.c @@ -247,6 +247,10 @@ ao_clock_init(void) /* Clear reset flags */ stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); +#if !AO_HSI && !AO_NEED_HSI + /* Turn off the HSI clock */ + stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION); +#endif #if DEBUG_THE_CLOCK /* Output SYSCLK on PA8 for measurments */ diff --git a/src/stmf0/registers.ld b/src/stmf0/registers.ld index 5358f15a..598fc1af 100644 --- a/src/stmf0/registers.ld +++ b/src/stmf0/registers.ld @@ -51,10 +51,7 @@ stm_scb = 0xe000ed00; stm_mpu = 0xe000ed90; -stm_dbg_mcu = 0xe0042000; - /* calibration data in system memory */ -stm_temp_cal = 0x1ff80078; -stm_flash_size_medium = 0x1ff8004c; -stm_flash_size_large = 0x1ff800cc; +stm_cal = 0x1ffff7b8; +stm_flash_size_04x = 0x1ffff7cc; stm_device_id = 0x1ff80050; diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index 2adfeee0..504db433 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -435,20 +435,41 @@ extern struct stm_flash stm_flash; #define STM_FLASH_PECR_PRGLOCK 1 #define STM_FLASH_PECR_PELOCK 0 -#define STM_FLASH_SR_OPTVERR 11 -#define STM_FLASH_SR_SIZERR 10 -#define STM_FLASH_SR_PGAERR 9 -#define STM_FLASH_SR_WRPERR 8 -#define STM_FLASH_SR_READY 3 -#define STM_FLASH_SR_ENDHV 2 -#define STM_FLASH_SR_EOP 1 +#define STM_FLASH_SR_EOP 5 +#define STM_FLASH_SR_WRPRTERR 4 +#define STM_FLASH_SR_PGERR 2 #define STM_FLASH_SR_BSY 0 -#define STM_FLASH_PEKEYR_PEKEY1 0x89ABCDEF -#define STM_FLASH_PEKEYR_PEKEY2 0x02030405 - -#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF -#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516 +#define STM_FLASH_CR_OBL_LAUNCH 13 +#define STM_FLASH_CR_EOPIE 12 +#define STM_FLASH_CR_ERRIE 10 +#define STM_FLASH_CR_OPTWRE 9 +#define STM_FLASH_CR_LOCK 7 +#define STM_FLASH_CR_STRT 6 +#define STM_FLASH_CR_OPTER 5 +#define STM_FLASH_CR_OPTPG 4 +#define STM_FLASH_CR_MER 2 +#define STM_FLASH_CR_PER 1 +#define STM_FLASH_CR_PG 0 + +#define STM_FLASH_OBR_DATA1 24 +#define STM_FLASH_OBR_DATA0 16 +#define STM_FLASH_OBR_BOOT_SEL 15 +#define STM_FLASH_OBR_RAM_PARITY_CHECK 14 +#define STM_FLASH_OBR_VDDA_MONITOR 13 +#define STM_FLASH_OBR_NBOOT1 12 +#define STM_FLASH_OBR_NBOOT0 11 +#define STM_FLASH_OBR_NRST_STDBY 10 +#define STM_FLASH_OBR_NRST_STOP 9 +#define STM_FLASH_OBR_WDG_SW 8 +#define STM_FLASH_OBR_RDPRT 1 +#define STM_FLASH_OBR_RDPRT_LEVEL0 0 +#define STM_FLASH_OBR_RDPRT_LEVEL1 1 +#define STM_FLASH_OBR_RDPRT_LEVEL2 3 +#define STM_FLASH_OBR_OPTERR 0 + +#define STM_FLASH_KEYR_KEY1 0x45670123 +#define STM_FLASH_KEYR_KEY2 0xcdef89ab struct stm_rcc { vuint32_t cr; @@ -1176,6 +1197,39 @@ struct stm_syscfg { extern struct stm_syscfg stm_syscfg; +#define STM_SYSCFG_CFGR1_TIM3_DMA_RMP 30 +#define STM_SYSCFG_CFGR1_TIM2_DMA_RMP 29 +#define STM_SYSCFG_CFGR1_TIM1_DMA_RMP 28 +#define STM_SYSCFG_CFGR1_I2C1_DMA_RMP 27 +#define STM_SYSCFG_CFGR1_USART3_DMA_RMP 26 +#define STM_SYSCFG_CFGR1_USART2_DMA_RMP 25 +#define STM_SYSCFG_CFGR1_SPI2_DMA_RMP 24 +#define STM_SYSCFG_CFGR1_I2C_PA10_FMP 23 +#define STM_SYSCFG_CFGR1_I2C_PA9_FMP 22 +#define STM_SYSCFG_CFGR1_I2C2_FMP 21 +#define STM_SYSCFG_CFGR1_I2C1_FMP 20 +#define STM_SYSCFG_CFGR1_I2C_PB9_FMP 19 +#define STM_SYSCFG_CFGR1_I2C_PB8_FMP 18 +#define STM_SYSCFG_CFGR1_I2C_PB7_FMP 17 +#define STM_SYSCFG_CFGR1_I2C_PB6_FMP 16 +#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP2 14 +#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP2 13 +#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP 12 +#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP 11 +#define STM_SYSCFG_CFGR1_USART1_RX_DMA_RMP 10 +#define STM_SYSCFG_CFGR1_USART1_TX_DMA_RMP 9 +#define STM_SYSCFG_CFGR1_ADC_DMA_RMP 8 +#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL 6 +#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL_TIMER16 0 +#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART1 1 +#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART4 2 +#define STM_SYSCFG_CFGR1_PA11_PA12_RMP 4 +#define STM_SYSCFG_CFGR1_MEM_MODE 0 +#define STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH 0 +#define STM_SYSCFG_CFGR1_MEM_MODE_SYSTEM_FLASH 1 +#define STM_SYSCFG_CFGR1_MEM_MODE_SRAM 3 +#define STM_SYSCFG_CFGR1_MEM_MODE_MASK 3 + #if 0 static inline void stm_exticr_set(struct stm_gpio *gpio, int pin) { @@ -1503,35 +1557,34 @@ extern struct stm_adc stm_adc; #define STM_ADC_CCR_ADCPRE_HSI_4 2 #define STM_ADC_CCR_ADCPRE_MASK 3 -struct stm_temp_cal { - uint16_t vref; - uint16_t ts_cal_cold; - uint16_t reserved; - uint16_t ts_cal_hot; +struct stm_cal { + uint16_t ts_cal_cold; /* 30°C */ + uint16_t vrefint_cal; + uint16_t unused_c0; + uint16_t ts_cal_hot; /* 110°C */ }; -extern struct stm_temp_cal stm_temp_cal; +extern struct stm_cal stm_cal; -#define stm_temp_cal_cold 25 +#define stm_temp_cal_cold 30 #define stm_temp_cal_hot 110 -struct stm_dbg_mcu { +struct stm_dbgmcu { uint32_t idcode; }; -extern struct stm_dbg_mcu stm_dbg_mcu; +extern struct stm_dbgmcu stm_dbgmcu; static inline uint16_t stm_dev_id(void) { - return stm_dbg_mcu.idcode & 0xfff; + return stm_dbgmcu.idcode & 0xfff; } struct stm_flash_size { uint16_t f_size; }; -extern struct stm_flash_size stm_flash_size_medium; -extern struct stm_flash_size stm_flash_size_large; +extern struct stm_flash_size stm_flash_size_04x; /* Returns flash size in bytes */ extern uint32_t -- cgit v1.2.3 From 02b07a202839d6e68b3f0db7f8965478661db140 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Jan 2015 19:37:05 -0800 Subject: altos: Add flash-loader to usbtrng-v2.0 Uses the new STM32F042 flash loading bits. Signed-off-by: Keith Packard --- src/usbtrng-v2.0/.gitignore | 2 ++ src/usbtrng-v2.0/ao_pins.h | 2 ++ src/usbtrng-v2.0/flash-loader/.gitignore | 2 ++ src/usbtrng-v2.0/flash-loader/Makefile | 8 ++++++++ src/usbtrng-v2.0/flash-loader/ao_pins.h | 31 +++++++++++++++++++++++++++++++ 5 files changed, 45 insertions(+) create mode 100644 src/usbtrng-v2.0/.gitignore create mode 100644 src/usbtrng-v2.0/flash-loader/.gitignore create mode 100644 src/usbtrng-v2.0/flash-loader/Makefile create mode 100644 src/usbtrng-v2.0/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/usbtrng-v2.0/.gitignore b/src/usbtrng-v2.0/.gitignore new file mode 100644 index 00000000..93b38d11 --- /dev/null +++ b/src/usbtrng-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +usbtrng-* diff --git a/src/usbtrng-v2.0/ao_pins.h b/src/usbtrng-v2.0/ao_pins.h index bbf5e153..b84a88e9 100644 --- a/src/usbtrng-v2.0/ao_pins.h +++ b/src/usbtrng-v2.0/ao_pins.h @@ -42,4 +42,6 @@ #define HAS_USB 1 +#define IS_FLASH_LOADER 0 + #endif /* _AO_PINS_H_ */ diff --git a/src/usbtrng-v2.0/flash-loader/.gitignore b/src/usbtrng-v2.0/flash-loader/.gitignore new file mode 100644 index 00000000..32dbbbcf --- /dev/null +++ b/src/usbtrng-v2.0/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +usbtrng* diff --git a/src/usbtrng-v2.0/flash-loader/Makefile b/src/usbtrng-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..a2bf199f --- /dev/null +++ b/src/usbtrng-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=usbtrng-v2.0 +include $(TOPDIR)/stmf0/Makefile-flash.defs diff --git a/src/usbtrng-v2.0/flash-loader/ao_pins.h b/src/usbtrng-v2.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..9fa8b715 --- /dev/null +++ b/src/usbtrng-v2.0/flash-loader/ao_pins.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Red LED */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 2 +#define AO_BOOT_APPLICATION_VALUE 0 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_DOWN + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 32c68670af9f8aa690c64d64502e559c0df0c1db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Jan 2015 19:58:38 -0800 Subject: ao-tools: Add --wait option to ao-usbload This waits forever for USB writes to complete, instead of timing out after five seconds. Useful when debugging the device. Signed-off-by: Keith Packard --- ao-tools/ao-usbload/ao-usbload.c | 12 ++++++++++-- ao-tools/lib/cc-usb.c | 12 +++++++----- ao-tools/lib/cc-usb.h | 2 ++ src/stm/stm32l.h | 2 +- 4 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-usbload/ao-usbload.c b/ao-tools/ao-usbload/ao-usbload.c index fd34fbdc..1b217e55 100644 --- a/ao-tools/ao-usbload/ao-usbload.c +++ b/ao-tools/ao-usbload/ao-usbload.c @@ -86,12 +86,13 @@ static const struct option options[] = { { .name = "cal", .has_arg = 1, .val = 'c' }, { .name = "serial", .has_arg = 1, .val = 's' }, { .name = "verbose", .has_arg = 1, .val = 'v' }, + { .name = "wait", .has_arg = 0, .val = 'w' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--raw] [--verbose=] [--device=] [-tty=] [--cal=] [--serial=] file.{elf,ihx}\n", program); + fprintf(stderr, "usage: %s [--raw] [--verbose=] [--device=] [-tty=] [--cal=] [--serial=] [--wait] file.{elf,ihx}\n", program); exit(1); } @@ -145,7 +146,7 @@ main (int argc, char **argv) uint32_t flash_base, flash_bound; int has_flash_size = 0; - while ((c = getopt_long(argc, argv, "rT:D:c:s:v:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "wrT:D:c:s:v:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -156,6 +157,9 @@ main (int argc, char **argv) case 'r': raw = 1; break; + case 'w': + cc_default_timeout = -1; + break; case 'c': cal = strtoul(optarg, &cal_end, 10); if (cal_end == optarg || *cal_end != '\0') @@ -208,6 +212,10 @@ main (int argc, char **argv) this_tty = cc_usbdevs_find_by_arg(device, "AltosFlash"); if (!this_tty) this_tty = cc_usbdevs_find_by_arg(device, "TeleMega"); + if (!this_tty) + this_tty = cc_usbdevs_find_by_arg(device, "TeleMetrum"); + if (!this_tty) + this_tty = cc_usbdevs_find_by_arg(device, "TeleGPS"); if (!this_tty) this_tty = getenv("ALTOS_TTY"); if (!this_tty) diff --git a/ao-tools/lib/cc-usb.c b/ao-tools/lib/cc-usb.c index 38dfff04..1a4dc7a1 100644 --- a/ao-tools/lib/cc-usb.c +++ b/ao-tools/lib/cc-usb.c @@ -152,6 +152,8 @@ cc_usb_dbg(int indent, uint8_t *bytes, int len) } } +int cc_default_timeout = 5000; + /* * Flush pending writes, fill pending reads */ @@ -227,7 +229,7 @@ _cc_usb_sync(struct cc_usb *cc, int wait_for_input, int write_timeout) void cc_usb_sync(struct cc_usb *cc) { - if (_cc_usb_sync(cc, 0, 5000) < 0) { + if (_cc_usb_sync(cc, 0, cc_default_timeout) < 0) { fprintf(stderr, "USB link timeout\n"); exit(1); } @@ -268,7 +270,7 @@ int cc_usb_getchar_timeout(struct cc_usb *cc, int timeout) { while (cc->in_pos == cc->in_count) { - if (_cc_usb_sync(cc, timeout, 5000) < 0) { + if (_cc_usb_sync(cc, timeout, cc_default_timeout) < 0) { fprintf(stderr, "USB link timeout\n"); exit(1); } @@ -279,7 +281,7 @@ cc_usb_getchar_timeout(struct cc_usb *cc, int timeout) int cc_usb_getchar(struct cc_usb *cc) { - return cc_usb_getchar_timeout(cc, 5000); + return cc_usb_getchar_timeout(cc, cc_default_timeout); } void @@ -400,7 +402,7 @@ cc_usb_open_remote(struct cc_usb *cc, int freq, char *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, 5000); + _cc_usb_sync(cc, 100, cc_default_timeout); } while (cc->in_count > 0); cc->remote = 1; } @@ -459,7 +461,7 @@ cc_usb_open(char *tty) cc_usb_printf(cc, "\nE 0\nm 0\n"); do { cc->in_count = cc->in_pos = 0; - _cc_usb_sync(cc, 100, 5000); + _cc_usb_sync(cc, 100, cc_default_timeout); } while (cc->in_count > 0); return cc; } diff --git a/ao-tools/lib/cc-usb.h b/ao-tools/lib/cc-usb.h index e08a956b..9ed198cd 100644 --- a/ao-tools/lib/cc-usb.h +++ b/ao-tools/lib/cc-usb.h @@ -23,6 +23,8 @@ struct cc_usb; +extern int cc_default_timeout; + struct cc_usb * cc_usb_open(char *tty); diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 799cccbd..c5c28e76 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1515,7 +1515,7 @@ extern struct stm_dbg_mcu stm_dbg_mcu; static inline uint16_t stm_dev_id(void) { - return stm_dbg_mcu.idcode & 0xfff; + return stm_dbgmcu.idcode & 0xfff; } struct stm_flash_size { -- cgit v1.2.3 From e1d5bcb1968e280b8ebdf6c8b12e8a87167fd890 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jan 2015 22:10:47 -0800 Subject: altos/stmf0: Fix linker scripts to make ao_boot work The flash loader ended up assuming ao_boot was at the start of ram, while the application stuck it after the interrupt table (where it needs to go). Signed-off-by: Keith Packard --- src/stmf0/altos-loader.ld | 9 +++++---- src/stmf0/altos.ld | 5 +---- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/stmf0/altos-loader.ld b/src/stmf0/altos-loader.ld index 2feb515d..86cf1838 100644 --- a/src/stmf0/altos-loader.ld +++ b/src/stmf0/altos-loader.ld @@ -29,14 +29,15 @@ SECTIONS { * Rom contents */ - .text : { + .interrupt : { __text_start__ = .; *(.interrupt) /* Interrupt vectors */ + } > rom - . = ORIGIN(rom) + 0x100; - + .text ORIGIN(rom) + 0x100 : { ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) + *(.text*) /* Executable code */ *(.ARM.exidx* .gnu.linkonce.armexidx.*) *(.rodata*) /* Constants */ @@ -47,7 +48,7 @@ SECTIONS { * the application and bootloader share the same addresses. * This must be all uninitialized data */ - .boot (NOLOAD) : { + .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : { __boot_start__ = .; *(.boot) __boot_end__ = .; diff --git a/src/stmf0/altos.ld b/src/stmf0/altos.ld index 742d8419..9dbc83d0 100644 --- a/src/stmf0/altos.ld +++ b/src/stmf0/altos.ld @@ -54,13 +54,10 @@ SECTIONS { ao_product.o(.romconfig*) *(.text*) /* Executable code */ + *(.ARM.exidx* .gnu.linkonce.armexidx.*) *(.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 -- cgit v1.2.3 From a01effc2f64c757c907e0f4937b4d3710b97bde0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jan 2015 22:12:40 -0800 Subject: altos/stmf0: Add faster USB path This adds a way to allocate private USB buffers for sending data without needing to copy it again. It requires ensuring that all accesses are 16 bits aligned to 16 bit boundaries. Signed-off-by: Keith Packard --- src/stmf0/ao_arch_funcs.h | 13 ++++++++++ src/stmf0/ao_usb_stm.c | 66 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 71 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/stmf0/ao_arch_funcs.h b/src/stmf0/ao_arch_funcs.h index a5c6764b..3db96be2 100644 --- a/src/stmf0/ao_arch_funcs.h +++ b/src/stmf0/ao_arch_funcs.h @@ -384,4 +384,17 @@ static inline void ao_arch_start_scheduler(void) { ao_arch_irqrestore(__mask); \ } while (0) +/* ao_usb_stm.c */ + +#if AO_USB_DIRECTIO +uint16_t * +ao_usb_alloc(void); + +void +ao_usb_free(uint16_t *buffer); + +void +ao_usb_write(uint16_t *buffer, uint16_t len); +#endif /* AO_USB_DIRECTIO */ + #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index b9d86368..e0ff541a 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -80,6 +80,7 @@ static uint16_t *ao_usb_ep0_tx_buffer; static uint16_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ +static uint16_t ao_usb_in_tx_offset; static uint16_t *ao_usb_in_tx_buffer; static uint16_t *ao_usb_out_rx_buffer; @@ -141,6 +142,13 @@ static inline uint16_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) return (uint16_t *) (stm_usb_sram + sram_addr); } +#if AO_USB_DIRECTIO +static inline uint16_t ao_usb_packet_buffer_offset(uint16_t *addr) +{ + return (uint16_t) ((uint8_t *) addr - stm_usb_sram); +} +#endif + static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { return (epr >> STM_USB_EPR_STAT_RX) & STM_USB_EPR_STAT_RX_MASK; } @@ -368,7 +376,6 @@ ao_usb_set_configuration(void) /* Set up the INT end point */ ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_INT_SIZE; ao_usb_init_ep(AO_USB_INT_EPR, @@ -393,7 +400,8 @@ ao_usb_set_configuration(void) /* Set up the IN end point */ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_in_tx_offset = ao_usb_sram_addr; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_in_tx_offset); ao_usb_sram_addr += AO_USB_IN_SIZE; ao_usb_init_ep(AO_USB_IN_EPR, @@ -415,7 +423,7 @@ static uint16_t reset_count; */ static void -ao_usb_write(const uint8_t *src, uint16_t *base, uint16_t bytes) +ao_usb_copy_tx(const uint8_t *src, uint16_t *base, uint16_t bytes) { while (bytes >= 2) { *base++ = src[0] | (src[1] << 8); @@ -427,7 +435,7 @@ ao_usb_write(const uint8_t *src, uint16_t *base, uint16_t bytes) } static void -ao_usb_read(uint8_t *dst, uint16_t *base, uint16_t bytes) +ao_usb_copy_rx(uint8_t *dst, uint16_t *base, uint16_t bytes) { while (bytes >= 2) { uint16_t s = *base++; @@ -462,7 +470,7 @@ ao_usb_ep0_flush(void) ao_usb_ep0_in_len -= this_len; debug_data ("Flush EP0 len %d:", this_len); - ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len); + ao_usb_copy_tx(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, this_len); debug_data ("\n"); ao_usb_ep0_in_data += this_len; @@ -484,7 +492,7 @@ ao_usb_ep0_fill(void) /* Pull all of the data out of the packet */ debug_data ("Fill EP0 len %d:", len); - ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, len); + ao_usb_copy_rx(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, len); debug_data ("\n"); ao_usb_ep0_out_data += len; @@ -773,7 +781,8 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_copy_tx(ao_usb_tx_buffer, ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_in_tx_offset; ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; ao_usb_tx_count = 0; _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); @@ -851,7 +860,7 @@ _ao_usb_out_recv(void) _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); debug_data("Fill OUT len %d:", ao_usb_rx_count); - ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); + ao_usb_copy_rx(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); debug_data("\n"); ao_usb_rx_pos = 0; @@ -897,6 +906,47 @@ ao_usb_getchar(void) return c; } +#if AO_USB_DIRECTIO +uint16_t * +ao_usb_alloc(void) +{ + uint16_t *buffer; + + if (!ao_usb_running) + return NULL; + buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_IN_SIZE; + return buffer; +} + +void +ao_usb_free(uint16_t *addr) +{ + uint16_t offset = ao_usb_packet_buffer_offset(addr); + if (offset < ao_usb_sram_addr) + ao_usb_sram_addr = offset; +} + +void +ao_usb_write(uint16_t *buffer, uint16_t len) +{ + ao_arch_block_interrupts(); + + /* Flush any pending regular */ + if (ao_usb_tx_count) + _ao_usb_in_send(); + + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + ao_usb_in_pending = 1; + ao_usb_in_flushed = (len != AO_USB_IN_SIZE); + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_packet_buffer_offset(buffer); + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = len; + _ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); + ao_arch_release_interrupts(); +} +#endif + void ao_usb_disable(void) { -- cgit v1.2.3 From 729bb7a405460db8d44c9ff6ee903b28c7499a02 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jan 2015 22:14:57 -0800 Subject: altos/stmf0: Add ADC and DMA APIs The ADC api is what USBtrng wants; a way to repeatedly read a single ADC input as fast as possible. Signed-off-by: Keith Packard --- src/stmf0/ao_adc_fast.c | 188 ++++++++++++++++++++++++++++ src/stmf0/ao_adc_fast.h | 27 ++++ src/stmf0/ao_dma_stm.c | 141 +++++++++++++++++++++ src/stmf0/ao_interrupt.c | 11 +- src/stmf0/stm32f0.h | 314 ++++++++++++++++++++++++----------------------- 5 files changed, 522 insertions(+), 159 deletions(-) create mode 100644 src/stmf0/ao_adc_fast.c create mode 100644 src/stmf0/ao_adc_fast.h create mode 100644 src/stmf0/ao_dma_stm.c (limited to 'src') diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c new file mode 100644 index 00000000..5885ae4f --- /dev/null +++ b/src/stmf0/ao_adc_fast.c @@ -0,0 +1,188 @@ +/* + * 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 + +static uint8_t ao_adc_done; + +/* + * Callback from DMA ISR + * + * Mark time in ring, shut down DMA engine + */ +static void ao_adc_dma_done(int index) +{ + (void) index; + ao_adc_done = 1; + ao_wakeup(&ao_adc_done); +} + +/* + * Start the ADC sequence using the DMA engine + */ +void +ao_adc_read(uint16_t *dest, int len) +{ + ao_adc_done = 0; + stm_adc.isr = 0; + ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), + &stm_adc.dr, + dest, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done); + ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); + + stm_adc.cr |= (1 << STM_ADC_CR_ADSTART); + ao_arch_block_interrupts(); + while (!ao_adc_done) + ao_sleep(&ao_adc_done); + ao_arch_release_interrupts(); + + ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); + + stm_adc.cr |= (1 << STM_ADC_CR_ADSTP); + while ((stm_adc.cr & (1 << STM_ADC_CR_ADSTP)) != 0) + ; +} + +void +ao_adc_init(void) +{ + uint32_t chselr; + int i; + + /* Reset ADC */ + stm_rcc.apb2rstr |= (1 << STM_RCC_APB2RSTR_ADCRST); + stm_rcc.apb2rstr &= ~(1 << STM_RCC_APB2RSTR_ADCRST); + + /* Turn on ADC pins */ + stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR; + +#ifdef AO_ADC_PIN0_PORT + stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN1_PORT + stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN2_PORT + stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN3_PORT + stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN4_PORT + stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN5_PORT + stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN6_PORT + stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN7_PORT + stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN24_PORT + #error "Too many ADC ports" +#endif + + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADCEN); + + chselr = 0; +#if AO_NUM_ADC > 0 + chselr |= (1 << AO_ADC_PIN0_CH); +#endif +#if AO_NUM_ADC > 1 + chselr |= (1 << AO_ADC_PIN1_CH); +#endif +#if AO_NUM_ADC > 2 + chselr |= (1 << AO_ADC_PIN2_CH); +#endif +#if AO_NUM_ADC > 3 + chselr |= (1 << AO_ADC_PIN3_CH); +#endif +#if AO_NUM_ADC > 4 + chselr |= (1 << AO_ADC_PIN4_CH); +#endif +#if AO_NUM_ADC > 5 + chselr |= (1 << AO_ADC_PIN5_CH); +#endif +#if AO_NUM_ADC > 6 + chselr |= (1 << AO_ADC_PIN6_CH); +#endif +#if AO_NUM_ADC > 7 + chselr |= (1 << AO_ADC_PIN7_CH); +#endif +#if AO_NUM_ADC > 8 +#error Need more ADC defines +#endif + stm_adc.chselr = chselr; + + /* Set the clock */ + stm_adc.cfgr2 = STM_ADC_CFGR2_CKMODE_PCLK_2 << STM_ADC_CFGR2_CKMODE; + + /* Shortest sample time */ + stm_adc.smpr = STM_ADC_SMPR_SMP_1_5 << STM_ADC_SMPR_SMP; + + /* Calibrate */ + stm_adc.cr |= (1 << STM_ADC_CR_ADCAL); + for (i = 0; i < 0xf000; i++) { + if ((stm_adc.cr & (1 << STM_ADC_CR_ADCAL)) == 0) + break; + } + + /* Enable */ + stm_adc.cr |= (1 << STM_ADC_CR_ADEN); + while ((stm_adc.isr & (1 << STM_ADC_ISR_ADRDY)) == 0) + ; + + stm_adc.cfgr1 = ((0 << STM_ADC_CFGR1_AWDCH) | + (0 << STM_ADC_CFGR1_AWDEN) | + (0 << STM_ADC_CFGR1_AWDSGL) | + (0 << STM_ADC_CFGR1_DISCEN) | + (0 << STM_ADC_CFGR1_AUTOOFF) | + (1 << STM_ADC_CFGR1_WAIT) | + (1 << STM_ADC_CFGR1_CONT) | + (0 << STM_ADC_CFGR1_OVRMOD) | + (STM_ADC_CFGR1_EXTEN_DISABLE << STM_ADC_CFGR1_EXTEN) | + (0 << STM_ADC_CFGR1_ALIGN) | + (STM_ADC_CFGR1_RES_12 << STM_ADC_CFGR1_RES) | + (STM_ADC_CFGR1_SCANDIR_UP << STM_ADC_CFGR1_SCANDIR) | + (STM_ADC_CFGR1_DMACFG_ONESHOT << STM_ADC_CFGR1_DMACFG) | + (1 << STM_ADC_CFGR1_DMAEN)); + stm_adc.ccr = 0; + + /* Clear any stale status bits */ + stm_adc.isr = 0; + + /* Turn on syscfg */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN); + + /* Set ADC to use DMA channel 1 (option 1) */ + stm_syscfg.cfgr1 &= ~(1 << STM_SYSCFG_CFGR1_ADC_DMA_RMP); + + ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); +} diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h new file mode 100644 index 00000000..a2408d14 --- /dev/null +++ b/src/stmf0/ao_adc_fast.h @@ -0,0 +1,27 @@ +/* + * 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. + */ + +#ifndef _AO_ADC_FAST_H_ +#define _AO_ADC_FAST_H_ + +void +ao_adc_read(uint16_t *dest, int len); + +void +ao_adc_init(void); + +#endif /* _AO_ADC_FAST_H_ */ diff --git a/src/stmf0/ao_dma_stm.c b/src/stmf0/ao_dma_stm.c new file mode 100644 index 00000000..78fabe18 --- /dev/null +++ b/src/stmf0/ao_dma_stm.c @@ -0,0 +1,141 @@ +/* + * 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" + +struct ao_dma_config { + void (*isr)(int index); +}; + +uint8_t ao_dma_done[STM_NUM_DMA]; + +static struct ao_dma_config ao_dma_config[STM_NUM_DMA]; +static uint8_t ao_dma_allocated[STM_NUM_DMA]; +static uint8_t ao_dma_mutex[STM_NUM_DMA]; +static uint8_t ao_dma_active; + +#define id(ch) STM_DMA_INDEX(ch) +#define id_mask(id) (STM_DMA_ISR_MASK << (id)) +#define ch_mask(ch) id_mask(id(ch)) + +static void +ao_dma_isr(uint8_t low_index, uint8_t high_index, uint32_t mask) { + /* Get channel interrupt bits */ + uint32_t isr = stm_dma.isr & mask; + uint8_t index; + + /* Ack them */ + stm_dma.ifcr = isr; + for (index = low_index; index <= high_index; index++) { + if (isr & id_mask(index)) { + if (ao_dma_config[index].isr) + (*ao_dma_config[index].isr)(index); + else { + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); + } + } + } +} + +void stm_dma_ch1_isr(void) { ao_dma_isr(id(1), id(1), ch_mask(1)); } +void stm_dma_ch2_3_isr(void) { ao_dma_isr(id(2), id(3), ch_mask(2) | ch_mask(3)); } +void stm_dma1_ch4_5_6_isr(void) { ao_dma_isr(id(4), id(6), ch_mask(4) | ch_mask(5) | ch_mask(6)); } + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr) +{ + if (ao_dma_allocated[index]) { + if (ao_dma_mutex[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_mutex[index] = 1; + } else + ao_mutex_get(&ao_dma_mutex[index]); + ao_arch_critical( + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMAEN); + ); + stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); + stm_dma.channel[index].cndtr = count; + stm_dma.channel[index].cpar = peripheral; + stm_dma.channel[index].cmar = memory; + ao_dma_config[index].isr = NULL; +} + +void +ao_dma_set_isr(uint8_t index, void (*isr)(int)) +{ + ao_dma_config[index].isr = isr; +} + +void +ao_dma_start(uint8_t index) +{ + ao_dma_done[index] = 0; + stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN); +} + +void +ao_dma_done_transfer(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_arch_critical( + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMAEN); + ); + if (ao_dma_allocated[index]) + ao_dma_mutex[index] = 0; + else + ao_mutex_put(&ao_dma_mutex[index]); +} + +void +ao_dma_abort(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_wakeup(&ao_dma_done[index]); +} + +void +ao_dma_alloc(uint8_t index) +{ + if (ao_dma_allocated[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_allocated[index] = 1; +} + +#define STM_NUM_DMA_ISR 3 + +void +ao_dma_init(void) +{ + int isr_id; + int index; + + for (isr_id = 0; isr_id < STM_NUM_DMA_ISR; isr_id++) { + stm_nvic_set_enable(STM_ISR_DMA_CH1_POS + isr_id); + stm_nvic_set_priority(STM_ISR_DMA_CH1_POS + isr_id, 4); + } + for (index = 0; index < STM_NUM_DMA; index++) { + ao_dma_allocated[index] = 0; + ao_dma_mutex[index] = 0; + } +} diff --git a/src/stmf0/ao_interrupt.c b/src/stmf0/ao_interrupt.c index b6a3147f..c6d8ef34 100644 --- a/src/stmf0/ao_interrupt.c +++ b/src/stmf0/ao_interrupt.c @@ -74,6 +74,9 @@ void start(void) } #endif #if RELOCATE_INTERRUPT + /* Turn on syscfg */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN); + memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__); stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) | (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE); @@ -112,8 +115,8 @@ isr(exti2_3) isr(exti4_15) isr(tsc) isr(dma_ch1) -isr(dma_ch2_3_dma2_ch1_2) -isr(dma_ch4_5_6_7_dma2_ch3_4_5) +isr(dma_ch2_3) +isr(dma_ch4_5_6) isr(adc_comp) isr(tim1_brk_up_trg_com) isr(tim1_cc) @@ -157,8 +160,8 @@ const void *stm_interrupt_vector[] = { i(0x5c, exti4_15), i(0x60, tsc), i(0x64, dma_ch1), - i(0x68, dma_ch2_3_dma2_ch1_2), - i(0x6c, dma_ch4_5_6_7_dma2_ch3_4_5), + i(0x68, dma_ch2_3), + i(0x6c, dma_ch4_5_6), i(0x70, adc_comp), i(0x74, tim1_brk_up_trg_com), i(0x78, tim1_cc), diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index 504db433..456f7631 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -587,6 +587,19 @@ extern struct stm_rcc stm_rcc; #define STM_RCC_CFGR_SW_HSI48 3 #define STM_RCC_CFGR_SW_MASK 3 +#define STM_RCC_APB2RSTR_DBGMCURST 22 +#define STM_RCC_APB2RSTR_TIM17RST 18 +#define STM_RCC_APB2RSTR_TIM16RST 17 +#define STM_RCC_APB2RSTR_TIM15RST 16 +#define STM_RCC_APB2RSTR_USART1RST 14 +#define STM_RCC_APB2RSTR_SPI1RST 12 +#define STM_RCC_APB2RSTR_TIM1RST 11 +#define STM_RCC_APB2RSTR_ADCRST 9 +#define STM_RCC_APB2RSTR_USART8RST 7 +#define STM_RCC_APB2RSTR_USART7RST 6 +#define STM_RCC_APB2RSTR_USART6RST 5 +#define STM_RCC_APB2RSTR_SYSCFGRST 1 + #define STM_RCC_APB1RSTR_CECRST 30 #define STM_RCC_APB1RSTR_DACRST 29 #define STM_RCC_APB1RSTR_PWRRST 28 @@ -618,7 +631,7 @@ extern struct stm_rcc stm_rcc; #define STM_RCC_AHBENR_FLITFEN 4 #define STM_RCC_AHBENR_SRAMEN 2 #define STM_RCC_AHBENR_DMA2EN 1 -#define STM_RCC_AHBENR_DMAEM 0 +#define STM_RCC_AHBENR_DMAEN 0 #define STM_RCC_APB2ENR_DBGMCUEN 22 #define STM_RCC_APB2ENR_TIM17EN 18 @@ -1262,7 +1275,7 @@ struct stm_dma_channel { vuint32_t reserved; }; -#define STM_NUM_DMA 7 +#define STM_NUM_DMA 6 struct stm_dma { vuint32_t isr; @@ -1272,7 +1285,7 @@ struct stm_dma { extern struct stm_dma stm_dma; -/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh) +/* DMA channels go from 1 to 6, instead of 0 to 5 (sigh) */ #define STM_DMA_INDEX(channel) ((channel) - 1) @@ -1323,39 +1336,70 @@ extern struct stm_dma stm_dma; #define STM_DMA_CCR_TCIE (1) #define STM_DMA_CCR_EN (0) -#define STM_DMA_CHANNEL_ADC1 1 +/* DMA channel assignments. When a peripheral has multiple channels + * (indicated with _), then it can be configured to either + * channel using syscfg.cfgr1 + */ + +#define STM_DMA_CHANNEL_ADC_1 1 +#define STM_DMA_CHANNEL_ADC_2 2 + #define STM_DMA_CHANNEL_SPI1_RX 2 #define STM_DMA_CHANNEL_SPI1_TX 3 + #define STM_DMA_CHANNEL_SPI2_RX 4 #define STM_DMA_CHANNEL_SPI2_TX 5 -#define STM_DMA_CHANNEL_USART3_TX 2 -#define STM_DMA_CHANNEL_USART3_RX 3 -#define STM_DMA_CHANNEL_USART1_TX 4 -#define STM_DMA_CHANNEL_USART1_RX 5 -#define STM_DMA_CHANNEL_USART2_RX 6 -#define STM_DMA_CHANNEL_USART2_TX 7 + +#define STM_DMA_CHANNEL_USART1_TX_1 2 +#define STM_DMA_CHANNEL_USART1_RX_1 3 +#define STM_DMA_CHANNEL_USART1_TX_2 4 +#define STM_DMA_CHANNEL_USART1_RX_2 5 + +#define STM_DMA_CHANNEL_USART2_RX 4 +#define STM_DMA_CHANNEL_USART2_TX 5 + +#define STM_DMA_CHANNEL_I2C1_TX 2 +#define STM_DMA_CHANNEL_I2C1_RX 3 + #define STM_DMA_CHANNEL_I2C2_TX 4 #define STM_DMA_CHANNEL_I2C2_RX 5 -#define STM_DMA_CHANNEL_I2C1_TX 6 -#define STM_DMA_CHANNEL_I2C1_RX 7 + +#define STM_DMA_CHANNEL_TIM1_CH1 2 +#define STM_DMA_CHANNEL_TIM1_CH2 3 +#define STM_DMA_CHANNEL_TIM1_CH4 4 +#define STM_DMA_CHANNEL_TIM1_TRIG 4 +#define STM_DMA_CHANNEL_TIM1_COM 4 +#define STM_DMA_CHANNEL_TIM1_CH3 5 +#define STM_DMA_CHANNEL_TIM1_UP 5 + #define STM_DMA_CHANNEL_TIM2_CH3 1 #define STM_DMA_CHANNEL_TIM2_UP 2 +#define STM_DMA_CHANNEL_TIM2_CH2 3 +#define STM_DMA_CHANNEL_TIM2_CH4 4 #define STM_DMA_CHANNEL_TIM2_CH1 5 -#define STM_DMA_CHANNEL_TIM2_CH2 7 -#define STM_DMA_CHANNEL_TIM2_CH4 7 + #define STM_DMA_CHANNEL_TIM3_CH3 2 #define STM_DMA_CHANNEL_TIM3_CH4 3 #define STM_DMA_CHANNEL_TIM3_UP 3 -#define STM_DMA_CHANNEL_TIM3_CH1 6 -#define STM_DMA_CHANNEL_TIM3_TRIG 6 -#define STM_DMA_CHANNEL_TIM4_CH1 1 -#define STM_DMA_CHANNEL_TIM4_CH2 4 -#define STM_DMA_CHANNEL_TIM4_CH3 5 -#define STM_DMA_CHANNEL_TIM4_UP 7 -#define STM_DMA_CHANNEL_TIM6_UP_DA 2 -#define STM_DMA_CHANNEL_C_CHANNEL1 2 -#define STM_DMA_CHANNEL_TIM7_UP_DA 3 -#define STM_DMA_CHANNEL_C_CHANNEL2 3 +#define STM_DMA_CHANNEL_TIM3_CH1 4 +#define STM_DMA_CHANNEL_TIM3_TRIG 4 + +#define STM_DMA_CHANNEL_TIM6_UP_DAC 2 + +#define STM_DMA_CHANNEL_TIM15_CH1 5 +#define STM_DMA_CHANNEL_TIM15_UP 5 +#define STM_DMA_CHANNEL_TIM15_TRIG 5 +#define STM_DMA_CHANNEL_TIM15_COM 5 + +#define STM_DMA_CHANNEL_TIM16_CH1_1 3 +#define STM_DMA_CHANNEL_TIM16_UP_1 3 +#define STM_DMA_CHANNEL_TIM16_CH1_2 4 +#define STM_DMA_CHANNEL_TIM16_UP_2 4 + +#define STM_DMA_CHANNEL_TIM17_CH1_1 1 +#define STM_DMA_CHANNEL_TIM17_UP_1 1 +#define STM_DMA_CHANNEL_TIM17_CH1_2 2 +#define STM_DMA_CHANNEL_TIM17_UP_2 2 /* * Only spi channel 1 and 2 can use DMA @@ -1419,143 +1463,103 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_SR_RXNE 0 struct stm_adc { - vuint32_t sr; - vuint32_t cr1; - vuint32_t cr2; - vuint32_t smpr1; - vuint32_t smpr2; - vuint32_t smpr3; - vuint32_t jofr1; - vuint32_t jofr2; - vuint32_t jofr3; - vuint32_t jofr4; - vuint32_t htr; - vuint32_t ltr; - vuint32_t sqr1; - vuint32_t sqr2; - vuint32_t sqr3; - vuint32_t sqr4; - vuint32_t sqr5; - vuint32_t jsqr; - vuint32_t jdr1; - vuint32_t jdr2; - vuint32_t jdr3; - vuint32_t jdr4; + vuint32_t isr; + vuint32_t ier; + vuint32_t cr; + vuint32_t cfgr1; + + vuint32_t cfgr2; + vuint32_t smpr; + vuint32_t r_18; + vuint32_t r_1c; + + vuint32_t tr; + vuint32_t r_24; + vuint32_t chselr; + vuint32_t r_2c; + + vuint32_t r_30[4]; + vuint32_t dr; - uint8_t reserved[0x300 - 0x5c]; - vuint32_t csr; + + uint8_t r_44[0x308 - 0x44]; vuint32_t ccr; }; extern struct stm_adc stm_adc; -#define STM_ADC_SR_JCNR 9 -#define STM_ADC_SR_RCNR 8 -#define STM_ADC_SR_ADONS 6 -#define STM_ADC_SR_OVR 5 -#define STM_ADC_SR_STRT 4 -#define STM_ADC_SR_JSTRT 3 -#define STM_ADC_SR_JEOC 2 -#define STM_ADC_SR_EOC 1 -#define STM_ADC_SR_AWD 0 - -#define STM_ADC_CR1_OVRIE 26 -#define STM_ADC_CR1_RES 24 -#define STM_ADC_CR1_RES_12 0 -#define STM_ADC_CR1_RES_10 1 -#define STM_ADC_CR1_RES_8 2 -#define STM_ADC_CR1_RES_6 3 -#define STM_ADC_CR1_RES_MASK 3 -#define STM_ADC_CR1_AWDEN 23 -#define STM_ADC_CR1_JAWDEN 22 -#define STM_ADC_CR1_PDI 17 -#define STM_ADC_CR1_PDD 16 -#define STM_ADC_CR1_DISCNUM 13 -#define STM_ADC_CR1_DISCNUM_1 0 -#define STM_ADC_CR1_DISCNUM_2 1 -#define STM_ADC_CR1_DISCNUM_3 2 -#define STM_ADC_CR1_DISCNUM_4 3 -#define STM_ADC_CR1_DISCNUM_5 4 -#define STM_ADC_CR1_DISCNUM_6 5 -#define STM_ADC_CR1_DISCNUM_7 6 -#define STM_ADC_CR1_DISCNUM_8 7 -#define STM_ADC_CR1_DISCNUM_MASK 7 -#define STM_ADC_CR1_JDISCEN 12 -#define STM_ADC_CR1_DISCEN 11 -#define STM_ADC_CR1_JAUTO 10 -#define STM_ADC_CR1_AWDSGL 9 -#define STM_ADC_CR1_SCAN 8 -#define STM_ADC_CR1_JEOCIE 7 -#define STM_ADC_CR1_AWDIE 6 -#define STM_ADC_CR1_EOCIE 5 -#define STM_ADC_CR1_AWDCH 0 -#define STM_ADC_CR1_AWDCH_MASK 0x1f - -#define STM_ADC_CR2_SWSTART 30 -#define STM_ADC_CR2_EXTEN 28 -#define STM_ADC_CR2_EXTEN_DISABLE 0 -#define STM_ADC_CR2_EXTEN_RISING 1 -#define STM_ADC_CR2_EXTEN_FALLING 2 -#define STM_ADC_CR2_EXTEN_BOTH 3 -#define STM_ADC_CR2_EXTEN_MASK 3 -#define STM_ADC_CR2_EXTSEL 24 -#define STM_ADC_CR2_EXTSEL_TIM9_CC2 0 -#define STM_ADC_CR2_EXTSEL_TIM9_TRGO 1 -#define STM_ADC_CR2_EXTSEL_TIM2_CC3 2 -#define STM_ADC_CR2_EXTSEL_TIM2_CC2 3 -#define STM_ADC_CR2_EXTSEL_TIM3_TRGO 4 -#define STM_ADC_CR2_EXTSEL_TIM4_CC4 5 -#define STM_ADC_CR2_EXTSEL_TIM2_TRGO 6 -#define STM_ADC_CR2_EXTSEL_TIM3_CC1 7 -#define STM_ADC_CR2_EXTSEL_TIM3_CC3 8 -#define STM_ADC_CR2_EXTSEL_TIM4_TRGO 9 -#define STM_ADC_CR2_EXTSEL_TIM6_TRGO 10 -#define STM_ADC_CR2_EXTSEL_EXTI_11 15 -#define STM_ADC_CR2_EXTSEL_MASK 15 -#define STM_ADC_CR2_JWSTART 22 -#define STM_ADC_CR2_JEXTEN 20 -#define STM_ADC_CR2_JEXTEN_DISABLE 0 -#define STM_ADC_CR2_JEXTEN_RISING 1 -#define STM_ADC_CR2_JEXTEN_FALLING 2 -#define STM_ADC_CR2_JEXTEN_BOTH 3 -#define STM_ADC_CR2_JEXTEN_MASK 3 -#define STM_ADC_CR2_JEXTSEL 16 -#define STM_ADC_CR2_JEXTSEL_TIM9_CC1 0 -#define STM_ADC_CR2_JEXTSEL_TIM9_TRGO 1 -#define STM_ADC_CR2_JEXTSEL_TIM2_TRGO 2 -#define STM_ADC_CR2_JEXTSEL_TIM2_CC1 3 -#define STM_ADC_CR2_JEXTSEL_TIM3_CC4 4 -#define STM_ADC_CR2_JEXTSEL_TIM4_TRGO 5 -#define STM_ADC_CR2_JEXTSEL_TIM4_CC1 6 -#define STM_ADC_CR2_JEXTSEL_TIM4_CC2 7 -#define STM_ADC_CR2_JEXTSEL_TIM4_CC3 8 -#define STM_ADC_CR2_JEXTSEL_TIM10_CC1 9 -#define STM_ADC_CR2_JEXTSEL_TIM7_TRGO 10 -#define STM_ADC_CR2_JEXTSEL_EXTI_15 15 -#define STM_ADC_CR2_JEXTSEL_MASK 15 -#define STM_ADC_CR2_ALIGN 11 -#define STM_ADC_CR2_EOCS 10 -#define STM_ADC_CR2_DDS 9 -#define STM_ADC_CR2_DMA 8 -#define STM_ADC_CR2_DELS 4 -#define STM_ADC_CR2_DELS_NONE 0 -#define STM_ADC_CR2_DELS_UNTIL_READ 1 -#define STM_ADC_CR2_DELS_7 2 -#define STM_ADC_CR2_DELS_15 3 -#define STM_ADC_CR2_DELS_31 4 -#define STM_ADC_CR2_DELS_63 5 -#define STM_ADC_CR2_DELS_127 6 -#define STM_ADC_CR2_DELS_255 7 -#define STM_ADC_CR2_DELS_MASK 7 -#define STM_ADC_CR2_CONT 1 -#define STM_ADC_CR2_ADON 0 - -#define STM_ADC_CCR_TSVREFE 23 -#define STM_ADC_CCR_ADCPRE 16 -#define STM_ADC_CCR_ADCPRE_HSI_1 0 -#define STM_ADC_CCR_ADCPRE_HSI_2 1 -#define STM_ADC_CCR_ADCPRE_HSI_4 2 -#define STM_ADC_CCR_ADCPRE_MASK 3 +#define STM_ADC_ISR_AWD 7 +#define STM_ADC_ISR_OVR 4 +#define STM_ADC_ISR_EOSEQ 3 +#define STM_ADC_ISR_EOC 2 +#define STM_ADC_ISR_EOSMP 1 +#define STM_ADC_ISR_ADRDY 0 + +#define STM_ADC_IER_AWDIE 7 +#define STM_ADC_IER_OVRIE 4 +#define STM_ADC_IER_EOSEQIE 3 +#define STM_ADC_IER_EOCIE 2 +#define STM_ADC_IER_EOSMPIE 1 +#define STM_ADC_IER_ADRDYIE 0 + +#define STM_ADC_CR_ADCAL 31 +#define STM_ADC_CR_ADSTP 4 +#define STM_ADC_CR_ADSTART 2 +#define STM_ADC_CR_ADDIS 1 +#define STM_ADC_CR_ADEN 0 + +#define STM_ADC_CFGR1_AWDCH 26 +#define STM_ADC_CFGR1_AWDEN 23 +#define STM_ADC_CFGR1_AWDSGL 22 +#define STM_ADC_CFGR1_DISCEN 16 +#define STM_ADC_CFGR1_AUTOOFF 15 +#define STM_ADC_CFGR1_WAIT 14 +#define STM_ADC_CFGR1_CONT 13 +#define STM_ADC_CFGR1_OVRMOD 12 +#define STM_ADC_CFGR1_EXTEN 10 +#define STM_ADC_CFGR1_EXTEN_DISABLE 0 +#define STM_ADC_CFGR1_EXTEN_RISING 1 +#define STM_ADC_CFGR1_EXTEN_FALLING 2 +#define STM_ADC_CFGR1_EXTEN_BOTH 3 +#define STM_ADC_CFGR1_EXTEN_MASK 3 + +#define STM_ADC_CFGR1_EXTSEL 6 +#define STM_ADC_CFGR1_ALIGN 5 +#define STM_ADC_CFGR1_RES 3 +#define STM_ADC_CFGR1_RES_12 0 +#define STM_ADC_CFGR1_RES_10 1 +#define STM_ADC_CFGR1_RES_8 2 +#define STM_ADC_CFGR1_RES_6 3 +#define STM_ADC_CFGR1_RES_MASK 3 +#define STM_ADC_CFGR1_SCANDIR 2 +#define STM_ADC_CFGR1_SCANDIR_UP 0 +#define STM_ADC_CFGR1_SCANDIR_DOWN 1 +#define STM_ADC_CFGR1_DMACFG 1 +#define STM_ADC_CFGR1_DMACFG_ONESHOT 0 +#define STM_ADC_CFGR1_DMACFG_CIRCULAR 1 +#define STM_ADC_CFGR1_DMAEN 0 + +#define STM_ADC_CFGR2_CKMODE 30 +#define STM_ADC_CFGR2_CKMODE_ADCCLK 0 +#define STM_ADC_CFGR2_CKMODE_PCLK_2 1 +#define STM_ADC_CFGR2_CKMODE_PCLK_4 2 + +#define STM_ADC_SMPR_SMP 0 +#define STM_ADC_SMPR_SMP_1_5 0 +#define STM_ADC_SMPR_SMP_7_5 1 +#define STM_ADC_SMPR_SMP_13_5 2 +#define STM_ADC_SMPR_SMP_28_5 3 +#define STM_ADC_SMPR_SMP_41_5 4 +#define STM_ADC_SMPR_SMP_55_5 5 +#define STM_ADC_SMPR_SMP_71_5 6 +#define STM_ADC_SMPR_SMP_239_5 7 + +#define STM_ADC_TR_HT 16 +#define STM_ADC_TR_LT 0 + +#define STM_ADC_CCR_VBATEN 24 +#define STM_ADC_CCR_TSEN 23 +#define STM_ADC_CCR_VREFEN 22 struct stm_cal { uint16_t ts_cal_cold; /* 30°C */ -- cgit v1.2.3 From ac1a58af4d281a9bc3572dc503982a94e439a4c1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jan 2015 22:16:18 -0800 Subject: altos/usbtrng-v2.0: Add random output command Read chunks of random ADC data, do some CRC16 computations to de-bias and merge 4 bytes of input data into 2 bytes of output data, then dump that out over USB. Signed-off-by: Keith Packard --- src/usbtrng-v2.0/Makefile | 3 ++ src/usbtrng-v2.0/ao_pins.h | 11 ++++++ src/usbtrng-v2.0/ao_usbtrng.c | 92 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 100 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/usbtrng-v2.0/Makefile b/src/usbtrng-v2.0/Makefile index 0d237630..2806d377 100644 --- a/src/usbtrng-v2.0/Makefile +++ b/src/usbtrng-v2.0/Makefile @@ -21,6 +21,9 @@ ALTOS_SRC = \ ao_interrupt.c \ ao_timer.c \ ao_panic.c \ + ao_mutex.c \ + ao_dma_stm.c \ + ao_adc_fast.c \ ao_stdio.c \ ao_led.c \ ao_romconfig.c \ diff --git a/src/usbtrng-v2.0/ao_pins.h b/src/usbtrng-v2.0/ao_pins.h index b84a88e9..90efb864 100644 --- a/src/usbtrng-v2.0/ao_pins.h +++ b/src/usbtrng-v2.0/ao_pins.h @@ -41,7 +41,18 @@ #define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 #define HAS_USB 1 +#define AO_USB_DIRECTIO 1 #define IS_FLASH_LOADER 0 +/* ADC */ + +#define AO_ADC_PIN0_PORT (&stm_gpioa) +#define AO_ADC_PIN0_PIN 6 +#define AO_ADC_PIN0_CH 6 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_IOPAEN)) + +#define AO_NUM_ADC 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/usbtrng-v2.0/ao_usbtrng.c b/src/usbtrng-v2.0/ao_usbtrng.c index 9b6fd4f1..c5ed5603 100644 --- a/src/usbtrng-v2.0/ao_usbtrng.c +++ b/src/usbtrng-v2.0/ao_usbtrng.c @@ -16,16 +16,93 @@ */ #include +#include -static void ao_blink(void) +static const uint16_t crc16_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, +}; + +static void +ao_trng_fetch(void) { - for (;;) { - ao_led_toggle(LEDS_AVAILABLE); - ao_delay(AO_MS_TO_TICKS(500)); + static uint16_t *buffer[2]; + static uint16_t adc_in[AO_USB_IN_SIZE]; /* twice as many as we need */ + uint32_t kbytes = 1; + uint32_t count; + int usb_buf_id; + int i, j; + uint16_t crc16 = 0; + uint16_t *buf; + uint8_t *rnd; + + if (!buffer[0]) { + buffer[0] = ao_usb_alloc(); + buffer[1] = ao_usb_alloc(); + if (!buffer[0]) + return; + } + + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) + kbytes = ao_cmd_lex_u32; + else + ao_cmd_status = ao_cmd_success; + usb_buf_id = 0; + count = kbytes * (1024/AO_USB_IN_SIZE); + ao_led_on(AO_LED_GREEN); + while (count--) { + ao_adc_read(adc_in, AO_USB_IN_SIZE); + rnd = (uint8_t *) adc_in; + buf = buffer[usb_buf_id]; + for (i = 0; i < 32; i++) { + for (j = 0; j < 4; j++) + crc16 = (crc16 >> 8) ^ crc16_table[(crc16 ^ *rnd++) & 0xff]; + *buf++ = crc16; + } + ao_led_toggle(AO_LED_GREEN|AO_LED_RED); + ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); + ao_led_toggle(AO_LED_GREEN|AO_LED_RED); + usb_buf_id = 1-usb_buf_id; } + ao_led_off(AO_LED_GREEN|AO_LED_RED); + ao_usb_flush(); } -struct ao_task blink_task; +static const struct ao_cmds usbtrng_cmds[] = { + { ao_trng_fetch, "f\0Fetch a block of numbers" }, + { 0, NULL }, +}; void main(void) { @@ -34,12 +111,15 @@ void main(void) ao_clock_init(); ao_task_init(); ao_timer_init(); + ao_dma_init(); + ao_adc_init(); ao_cmd_init(); ao_usb_init(); - ao_add_task(&blink_task, ao_blink, "blink"); + ao_cmd_register(usbtrng_cmds); + ao_led_off(AO_LED_RED); ao_start_scheduler(); } -- cgit v1.2.3 From ee91e1da606c8a8fade278a3aeae9c1cc9014b84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jan 2015 22:22:00 -0800 Subject: altos/stm: Fix typo in stm32l.h This crept in while working on the stmf0 bits. oops. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index c5c28e76..799cccbd 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1515,7 +1515,7 @@ extern struct stm_dbg_mcu stm_dbg_mcu; static inline uint16_t stm_dev_id(void) { - return stm_dbgmcu.idcode & 0xfff; + return stm_dbg_mcu.idcode & 0xfff; } struct stm_flash_size { -- cgit v1.2.3 From 79f3434013650fe4e3d76e5eb56a10000ee34249 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jan 2015 09:36:19 -0800 Subject: altos/stmf0: Remove remaining stm32l bits from stm32f0 code These were left over from the stm32f0 initial implementation work; now it's more useful to list only the bits which are valid. Signed-off-by: Keith Packard --- src/stmf0/stm32f0.h | 417 ---------------------------------------------------- 1 file changed, 417 deletions(-) (limited to 'src') diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index 456f7631..32864ced 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -186,219 +186,6 @@ extern struct stm_gpio stm_gpiof; #define stm_gpiob (*((struct stm_gpio *) 0x48000400)) #define stm_gpioa (*((struct stm_gpio *) 0x48000000)) -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; /* */ - vuint32_t rqr; /* */ - vuint32_t isr; /* */ - - vuint32_t icr; /* */ - vuint32_t rdr; /* */ - vuint32_t tdr; /* */ -}; - -extern struct stm_usart stm_usart1; -extern struct stm_usart stm_usart2; - -#define STM_USART_SR_CTS (9) /* CTS flag */ -#define STM_USART_SR_LBD (8) /* LIN break detection flag */ -#define STM_USART_SR_TXE (7) /* Transmit data register empty */ -#define STM_USART_SR_TC (6) /* Transmission complete */ -#define STM_USART_SR_RXNE (5) /* Read data register not empty */ -#define STM_USART_SR_IDLE (4) /* IDLE line detected */ -#define STM_USART_SR_ORE (3) /* Overrun error */ -#define STM_USART_SR_NF (2) /* Noise detected flag */ -#define STM_USART_SR_FE (1) /* Framing error */ -#define STM_USART_SR_PE (0) /* Parity error */ - -#define STM_USART_CR1_OVER8 (15) /* Oversampling mode */ -#define STM_USART_CR1_UE (13) /* USART enable */ -#define STM_USART_CR1_M (12) /* Word length */ -#define STM_USART_CR1_WAKE (11) /* Wakeup method */ -#define STM_USART_CR1_PCE (10) /* Parity control enable */ -#define STM_USART_CR1_PS (9) /* Parity selection */ -#define STM_USART_CR1_PEIE (8) /* PE interrupt enable */ -#define STM_USART_CR1_TXEIE (7) /* TXE interrupt enable */ -#define STM_USART_CR1_TCIE (6) /* Transmission complete interrupt enable */ -#define STM_USART_CR1_RXNEIE (5) /* RXNE interrupt enable */ -#define STM_USART_CR1_IDLEIE (4) /* IDLE interrupt enable */ -#define STM_USART_CR1_TE (3) /* Transmitter enable */ -#define STM_USART_CR1_RE (2) /* Receiver enable */ -#define STM_USART_CR1_RWU (1) /* Receiver wakeup */ -#define STM_USART_CR1_SBK (0) /* Send break */ - -#define STM_USART_CR2_LINEN (14) /* LIN mode enable */ -#define STM_USART_CR2_STOP (12) /* STOP bits */ -#define STM_USART_CR2_STOP_MASK 3 -#define STM_USART_CR2_STOP_1 0 -#define STM_USART_CR2_STOP_0_5 1 -#define STM_USART_CR2_STOP_2 2 -#define STM_USART_CR2_STOP_1_5 3 - -#define STM_USART_CR2_CLKEN (11) /* Clock enable */ -#define STM_USART_CR2_CPOL (10) /* Clock polarity */ -#define STM_USART_CR2_CPHA (9) /* Clock phase */ -#define STM_USART_CR2_LBCL (8) /* Last bit clock pulse */ -#define STM_USART_CR2_LBDIE (6) /* LIN break detection interrupt enable */ -#define STM_USART_CR2_LBDL (5) /* lin break detection length */ -#define STM_USART_CR2_ADD (0) -#define STM_USART_CR2_ADD_MASK 0xf - -#define STM_USART_CR3_ONEBITE (11) /* One sample bit method enable */ -#define STM_USART_CR3_CTSIE (10) /* CTS interrupt enable */ -#define STM_USART_CR3_CTSE (9) /* CTS enable */ -#define STM_USART_CR3_RTSE (8) /* RTS enable */ -#define STM_USART_CR3_DMAT (7) /* DMA enable transmitter */ -#define STM_USART_CR3_DMAR (6) /* DMA enable receiver */ -#define STM_USART_CR3_SCEN (5) /* Smartcard mode enable */ -#define STM_USART_CR3_NACK (4) /* Smartcard NACK enable */ -#define STM_USART_CR3_HDSEL (3) /* Half-duplex selection */ -#define STM_USART_CR3_IRLP (2) /* IrDA low-power */ -#define STM_USART_CR3_IREN (1) /* IrDA mode enable */ -#define STM_USART_CR3_EIE (0) /* Error interrupt enable */ - -struct stm_tim { -}; - -extern struct stm_tim stm_tim9; - -struct stm_tim1011 { - vuint32_t cr1; - uint32_t unused_4; - vuint32_t smcr; - vuint32_t dier; - vuint32_t sr; - vuint32_t egr; - vuint32_t ccmr1; - uint32_t unused_1c; - vuint32_t ccer; - vuint32_t cnt; - vuint32_t psc; - vuint32_t arr; - uint32_t unused_30; - vuint32_t ccr1; - uint32_t unused_38; - uint32_t unused_3c; - uint32_t unused_40; - uint32_t unused_44; - uint32_t unused_48; - uint32_t unused_4c; - vuint32_t or; -}; - -extern struct stm_tim1011 stm_tim10; -extern struct stm_tim1011 stm_tim11; - -#define STM_TIM1011_CR1_CKD 8 -#define STM_TIM1011_CR1_CKD_1 0 -#define STM_TIM1011_CR1_CKD_2 1 -#define STM_TIM1011_CR1_CKD_4 2 -#define STM_TIM1011_CR1_CKD_MASK 3 -#define STM_TIM1011_CR1_ARPE 7 -#define STM_TIM1011_CR1_URS 2 -#define STM_TIM1011_CR1_UDIS 1 -#define STM_TIM1011_CR1_CEN 0 - -#define STM_TIM1011_SMCR_ETP 15 -#define STM_TIM1011_SMCR_ECE 14 -#define STM_TIM1011_SMCR_ETPS 12 -#define STM_TIM1011_SMCR_ETPS_OFF 0 -#define STM_TIM1011_SMCR_ETPS_2 1 -#define STM_TIM1011_SMCR_ETPS_4 2 -#define STM_TIM1011_SMCR_ETPS_8 3 -#define STM_TIM1011_SMCR_ETPS_MASK 3 -#define STM_TIM1011_SMCR_ETF 8 -#define STM_TIM1011_SMCR_ETF_NONE 0 -#define STM_TIM1011_SMCR_ETF_CK_INT_2 1 -#define STM_TIM1011_SMCR_ETF_CK_INT_4 2 -#define STM_TIM1011_SMCR_ETF_CK_INT_8 3 -#define STM_TIM1011_SMCR_ETF_DTS_2_6 4 -#define STM_TIM1011_SMCR_ETF_DTS_2_8 5 -#define STM_TIM1011_SMCR_ETF_DTS_4_6 6 -#define STM_TIM1011_SMCR_ETF_DTS_4_8 7 -#define STM_TIM1011_SMCR_ETF_DTS_8_6 8 -#define STM_TIM1011_SMCR_ETF_DTS_8_8 9 -#define STM_TIM1011_SMCR_ETF_DTS_16_5 10 -#define STM_TIM1011_SMCR_ETF_DTS_16_6 11 -#define STM_TIM1011_SMCR_ETF_DTS_16_8 12 -#define STM_TIM1011_SMCR_ETF_DTS_32_5 13 -#define STM_TIM1011_SMCR_ETF_DTS_32_6 14 -#define STM_TIM1011_SMCR_ETF_DTS_32_8 15 -#define STM_TIM1011_SMCR_ETF_MASK 15 - -#define STM_TIM1011_DIER_CC1E 1 -#define STM_TIM1011_DIER_UIE 0 - -#define STM_TIM1011_SR_CC1OF 9 -#define STM_TIM1011_SR_CC1IF 1 -#define STM_TIM1011_SR_UIF 0 - -#define STM_TIM1011_EGR_CC1G 1 -#define STM_TIM1011_EGR_UG 0 - -#define STM_TIM1011_CCMR1_OC1CE 7 -#define STM_TIM1011_CCMR1_OC1M 4 -#define STM_TIM1011_CCMR1_OC1M_FROZEN 0 -#define STM_TIM1011_CCMR1_OC1M_SET_1_ACTIVE_ON_MATCH 1 -#define STM_TIM1011_CCMR1_OC1M_SET_1_INACTIVE_ON_MATCH 2 -#define STM_TIM1011_CCMR1_OC1M_TOGGLE 3 -#define STM_TIM1011_CCMR1_OC1M_FORCE_INACTIVE 4 -#define STM_TIM1011_CCMR1_OC1M_FORCE_ACTIVE 5 -#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_1 6 -#define STM_TIM1011_CCMR1_OC1M_PWM_MODE_2 7 -#define STM_TIM1011_CCMR1_OC1M_MASK 7 -#define STM_TIM1011_CCMR1_OC1PE 3 -#define STM_TIM1011_CCMR1_OC1FE 2 -#define STM_TIM1011_CCMR1_CC1S 0 -#define STM_TIM1011_CCMR1_CC1S_OUTPUT 0 -#define STM_TIM1011_CCMR1_CC1S_INPUT_TI1 1 -#define STM_TIM1011_CCMR1_CC1S_INPUT_TI2 2 -#define STM_TIM1011_CCMR1_CC1S_INPUT_TRC 3 -#define STM_TIM1011_CCMR1_CC1S_MASK 3 - -#define STM_TIM1011_CCMR1_IC1F_NONE 0 -#define STM_TIM1011_CCMR1_IC1F_CK_INT_2 1 -#define STM_TIM1011_CCMR1_IC1F_CK_INT_4 2 -#define STM_TIM1011_CCMR1_IC1F_CK_INT_8 3 -#define STM_TIM1011_CCMR1_IC1F_DTS_2_6 4 -#define STM_TIM1011_CCMR1_IC1F_DTS_2_8 5 -#define STM_TIM1011_CCMR1_IC1F_DTS_4_6 6 -#define STM_TIM1011_CCMR1_IC1F_DTS_4_8 7 -#define STM_TIM1011_CCMR1_IC1F_DTS_8_6 8 -#define STM_TIM1011_CCMR1_IC1F_DTS_8_8 9 -#define STM_TIM1011_CCMR1_IC1F_DTS_16_5 10 -#define STM_TIM1011_CCMR1_IC1F_DTS_16_6 11 -#define STM_TIM1011_CCMR1_IC1F_DTS_16_8 12 -#define STM_TIM1011_CCMR1_IC1F_DTS_32_5 13 -#define STM_TIM1011_CCMR1_IC1F_DTS_32_6 14 -#define STM_TIM1011_CCMR1_IC1F_DTS_32_8 15 -#define STM_TIM1011_CCMR1_IC1F_MASK 15 -#define STM_TIM1011_CCMR1_IC1PSC 2 -#define STM_TIM1011_CCMR1_IC1PSC_1 0 -#define STM_TIM1011_CCMR1_IC1PSC_2 1 -#define STM_TIM1011_CCMR1_IC1PSC_4 2 -#define STM_TIM1011_CCMR1_IC1PSC_8 3 -#define STM_TIM1011_CCMR1_IC1PSC_MASK 3 -#define STM_TIM1011_CCMR1_CC1S 0 - -#define STM_TIM1011_CCER_CC1NP 3 -#define STM_TIM1011_CCER_CC1P 1 -#define STM_TIM1011_CCER_CC1E 0 - -#define STM_TIM1011_OR_TI1_RMP_RI 3 -#define STM_TIM1011_ETR_RMP 2 -#define STM_TIM1011_TI1_RMP 0 -#define STM_TIM1011_TI1_RMP_GPIO 0 -#define STM_TIM1011_TI1_RMP_LSI 1 -#define STM_TIM1011_TI1_RMP_LSE 2 -#define STM_TIM1011_TI1_RMP_RTC 3 -#define STM_TIM1011_TI1_RMP_MASK 3 - /* Flash interface */ struct stm_flash { @@ -781,153 +568,6 @@ extern struct stm_pwr stm_pwr; #define STM_PWR_CSR_SBF (1) #define STM_PWR_CSR_WUF (0) -struct stm_tim67 { - vuint32_t cr1; - vuint32_t cr2; - uint32_t _unused_08; - vuint32_t dier; - - vuint32_t sr; - vuint32_t egr; - uint32_t _unused_18; - uint32_t _unused_1c; - - uint32_t _unused_20; - vuint32_t cnt; - vuint32_t psc; - vuint32_t arr; -}; - -extern struct stm_tim67 stm_tim6; - -#define STM_TIM67_CR1_ARPE (7) -#define STM_TIM67_CR1_OPM (3) -#define STM_TIM67_CR1_URS (2) -#define STM_TIM67_CR1_UDIS (1) -#define STM_TIM67_CR1_CEN (0) - -#define STM_TIM67_CR2_MMS (4) -#define STM_TIM67_CR2_MMS_RESET 0 -#define STM_TIM67_CR2_MMS_ENABLE 1 -#define STM_TIM67_CR2_MMS_UPDATE 2 -#define STM_TIM67_CR2_MMS_MASK 7 - -#define STM_TIM67_DIER_UDE (8) -#define STM_TIM67_DIER_UIE (0) - -#define STM_TIM67_SR_UIF (0) - -#define STM_TIM67_EGR_UG (0) - -struct stm_lcd { - vuint32_t cr; - vuint32_t fcr; - vuint32_t sr; - vuint32_t clr; - uint32_t unused_0x10; - vuint32_t ram[8*2]; -}; - -extern struct stm_lcd stm_lcd; - -#define STM_LCD_CR_MUX_SEG (7) - -#define STM_LCD_CR_BIAS (5) -#define STM_LCD_CR_BIAS_1_4 0 -#define STM_LCD_CR_BIAS_1_2 1 -#define STM_LCD_CR_BIAS_1_3 2 -#define STM_LCD_CR_BIAS_MASK 3 - -#define STM_LCD_CR_DUTY (2) -#define STM_LCD_CR_DUTY_STATIC 0 -#define STM_LCD_CR_DUTY_1_2 1 -#define STM_LCD_CR_DUTY_1_3 2 -#define STM_LCD_CR_DUTY_1_4 3 -#define STM_LCD_CR_DUTY_1_8 4 -#define STM_LCD_CR_DUTY_MASK 7 - -#define STM_LCD_CR_VSEL (1) -#define STM_LCD_CR_LCDEN (0) - -#define STM_LCD_FCR_PS (22) -#define STM_LCD_FCR_PS_1 0x0 -#define STM_LCD_FCR_PS_2 0x1 -#define STM_LCD_FCR_PS_4 0x2 -#define STM_LCD_FCR_PS_8 0x3 -#define STM_LCD_FCR_PS_16 0x4 -#define STM_LCD_FCR_PS_32 0x5 -#define STM_LCD_FCR_PS_64 0x6 -#define STM_LCD_FCR_PS_128 0x7 -#define STM_LCD_FCR_PS_256 0x8 -#define STM_LCD_FCR_PS_512 0x9 -#define STM_LCD_FCR_PS_1024 0xa -#define STM_LCD_FCR_PS_2048 0xb -#define STM_LCD_FCR_PS_4096 0xc -#define STM_LCD_FCR_PS_8192 0xd -#define STM_LCD_FCR_PS_16384 0xe -#define STM_LCD_FCR_PS_32768 0xf -#define STM_LCD_FCR_PS_MASK 0xf - -#define STM_LCD_FCR_DIV (18) -#define STM_LCD_FCR_DIV_16 0x0 -#define STM_LCD_FCR_DIV_17 0x1 -#define STM_LCD_FCR_DIV_18 0x2 -#define STM_LCD_FCR_DIV_19 0x3 -#define STM_LCD_FCR_DIV_20 0x4 -#define STM_LCD_FCR_DIV_21 0x5 -#define STM_LCD_FCR_DIV_22 0x6 -#define STM_LCD_FCR_DIV_23 0x7 -#define STM_LCD_FCR_DIV_24 0x8 -#define STM_LCD_FCR_DIV_25 0x9 -#define STM_LCD_FCR_DIV_26 0xa -#define STM_LCD_FCR_DIV_27 0xb -#define STM_LCD_FCR_DIV_28 0xc -#define STM_LCD_FCR_DIV_29 0xd -#define STM_LCD_FCR_DIV_30 0xe -#define STM_LCD_FCR_DIV_31 0xf -#define STM_LCD_FCR_DIV_MASK 0xf - -#define STM_LCD_FCR_BLINK (16) -#define STM_LCD_FCR_BLINK_DISABLE 0 -#define STM_LCD_FCR_BLINK_SEG0_COM0 1 -#define STM_LCD_FCR_BLINK_SEG0_COMALL 2 -#define STM_LCD_FCR_BLINK_SEGALL_COMALL 3 -#define STM_LCD_FCR_BLINK_MASK 3 - -#define STM_LCD_FCR_BLINKF (13) -#define STM_LCD_FCR_BLINKF_8 0 -#define STM_LCD_FCR_BLINKF_16 1 -#define STM_LCD_FCR_BLINKF_32 2 -#define STM_LCD_FCR_BLINKF_64 3 -#define STM_LCD_FCR_BLINKF_128 4 -#define STM_LCD_FCR_BLINKF_256 5 -#define STM_LCD_FCR_BLINKF_512 6 -#define STM_LCD_FCR_BLINKF_1024 7 -#define STM_LCD_FCR_BLINKF_MASK 7 - -#define STM_LCD_FCR_CC (10) -#define STM_LCD_FCR_CC_MASK 7 - -#define STM_LCD_FCR_DEAD (7) -#define STM_LCD_FCR_DEAD_MASK 7 - -#define STM_LCD_FCR_PON (4) -#define STM_LCD_FCR_PON_MASK 7 - -#define STM_LCD_FCR_UDDIE (3) -#define STM_LCD_FCR_SOFIE (1) -#define STM_LCD_FCR_HD (0) - -#define STM_LCD_SR_FCRSF (5) -#define STM_LCD_SR_RDY (4) -#define STM_LCD_SR_UDD (3) -#define STM_LCD_SR_UDR (2) -#define STM_LCD_SR_SOF (1) -#define STM_LCD_SR_ENS (0) - -#define STM_LCD_CLR_UDDC (3) -#define STM_LCD_CLR_SOFC (1) - /* The SYSTICK starts at 0xe000e010 */ struct stm_systick { @@ -1053,63 +693,6 @@ extern struct stm_scb stm_scb; #define STM_SCB_AIRCR_VECTCLRACTIVE 1 #define STM_SCB_AIRCR_VECTRESET 0 -struct stm_mpu { - vuint32_t typer; - vuint32_t cr; - vuint32_t rnr; - vuint32_t rbar; - - vuint32_t rasr; - vuint32_t rbar_a1; - vuint32_t rasr_a1; - vuint32_t rbar_a2; - vuint32_t rasr_a2; - vuint32_t rbar_a3; - vuint32_t rasr_a3; -}; - -extern struct stm_mpu stm_mpu; - -#define STM_MPU_TYPER_IREGION 16 -#define STM_MPU_TYPER_IREGION_MASK 0xff -#define STM_MPU_TYPER_DREGION 8 -#define STM_MPU_TYPER_DREGION_MASK 0xff -#define STM_MPU_TYPER_SEPARATE 0 - -#define STM_MPU_CR_PRIVDEFENA 2 -#define STM_MPU_CR_HFNMIENA 1 -#define STM_MPU_CR_ENABLE 0 - -#define STM_MPU_RNR_REGION 0 -#define STM_MPU_RNR_REGION_MASK 0xff - -#define STM_MPU_RBAR_ADDR 5 -#define STM_MPU_RBAR_ADDR_MASK 0x7ffffff - -#define STM_MPU_RBAR_VALID 4 -#define STM_MPU_RBAR_REGION 0 -#define STM_MPU_RBAR_REGION_MASK 0xf - -#define STM_MPU_RASR_XN 28 -#define STM_MPU_RASR_AP 24 -#define STM_MPU_RASR_AP_NONE_NONE 0 -#define STM_MPU_RASR_AP_RW_NONE 1 -#define STM_MPU_RASR_AP_RW_RO 2 -#define STM_MPU_RASR_AP_RW_RW 3 -#define STM_MPU_RASR_AP_RO_NONE 5 -#define STM_MPU_RASR_AP_RO_RO 6 -#define STM_MPU_RASR_AP_MASK 7 -#define STM_MPU_RASR_TEX 19 -#define STM_MPU_RASR_TEX_MASK 7 -#define STM_MPU_RASR_S 18 -#define STM_MPU_RASR_C 17 -#define STM_MPU_RASR_B 16 -#define STM_MPU_RASR_SRD 8 -#define STM_MPU_RASR_SRD_MASK 0xff -#define STM_MPU_RASR_SIZE 1 -#define STM_MPU_RASR_SIZE_MASK 0x1f -#define STM_MPU_RASR_ENABLE 0 - #define isr(name) void stm_ ## name ## _isr(void); isr(nmi) -- cgit v1.2.3 From a95d6776dea86cdc4bdc3512505ba7e75365c127 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jan 2015 16:55:27 -0800 Subject: altos/stmf0: Add CRC driver Sets up the stm32f0 CRC hardware, exposing inline functions to access it. DMA access is possible, but usbtrng can't use that. Signed-off-by: Keith Packard --- src/stmf0/ao_crc.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/stmf0/stm32f0.h | 32 +++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/stmf0/ao_crc.h (limited to 'src') diff --git a/src/stmf0/ao_crc.h b/src/stmf0/ao_crc.h new file mode 100644 index 00000000..cd011d3a --- /dev/null +++ b/src/stmf0/ao_crc.h @@ -0,0 +1,58 @@ +/* + * 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. + */ + +#ifndef _AO_CRC_H_ +#define _AO_CRC_H_ + +#define AO_CRC_16_CCITT 0x1021 +#define AO_CRC_16_CDMA2000 0xc867 +#define AO_CRC_16_DECT 0x0589 +#define AO_CRC_16_T10_DIF 0x8bb7 +#define AO_CRC_16_DNP 0x3d65 +#define AO_CRC_16_ANSI 0x8005 +#define AO_CRC_16_DEFAULT AO_CRC_16_ANSI + +#define AO_CRC_32_ANSI 0x04c11db7 +#define AO_CRC_32_C 0x1edc6f41 + +#define AO_CRC_32_DEFAULT AO_CRC_32_ANSI + +static inline uint16_t +ao_crc_in_32_out_16(uint32_t v) { + stm_crc.dr.u32 = v; + return stm_crc.dr.u16; +} + +static inline uint16_t +ao_crc_in_16_out_16(uint16_t v) { + stm_crc.dr.u16 = v; + return stm_crc.dr.u16; +} + +static inline uint16_t +ao_crc_in_8_out_16(uint8_t v) { + stm_crc.dr.u8 = v; + return stm_crc.dr.u16; +} + +void +ao_crc_reset(void); + +void +ao_crc_init(void); + +#endif /* _AO_CRC_H_ */ diff --git a/src/stmf0/stm32f0.h b/src/stmf0/stm32f0.h index 32864ced..ce8ca456 100644 --- a/src/stmf0/stm32f0.h +++ b/src/stmf0/stm32f0.h @@ -23,6 +23,7 @@ typedef volatile uint32_t vuint32_t; typedef volatile void * vvoid_t; typedef volatile uint16_t vuint16_t; +typedef volatile uint8_t vuint8_t; struct stm_gpio { vuint32_t moder; @@ -568,6 +569,37 @@ extern struct stm_pwr stm_pwr; #define STM_PWR_CSR_SBF (1) #define STM_PWR_CSR_WUF (0) +struct stm_crc { + union { + vuint32_t u32; + vuint16_t u16; + vuint8_t u8; + } dr; + vuint32_t idr; + vuint32_t cr; + uint32_t _0c; + + vuint32_t init; + vuint32_t pol; +}; + +extern struct stm_crc stm_crc; + +#define stm_crc (*((struct stm_crc *) 0x40023000)) + +#define STM_CRC_CR_REV_OUT 7 +#define STM_CRC_CR_REV_IN 5 +#define STM_CRC_CR_REV_IN_NONE 0 +#define STM_CRC_CR_REV_IN_BY_BYTE 1 +#define STM_CRC_CR_REV_IN_BY_HALF_WORD 2 +#define STM_CRC_CR_REV_IN_BY_WORD 3 +#define STM_CRC_CR_POLYSIZE 3 +#define STM_CRC_CR_POLYSIZE_32 0 +#define STM_CRC_CR_POLYSIZE_16 1 +#define STM_CRC_CR_POLYSIZE_8 2 +#define STM_CRC_CR_POLYSIZE_7 3 +#define STM_CRC_CR_RESET 0 + /* The SYSTICK starts at 0xe000e010 */ struct stm_systick { -- cgit v1.2.3 From 3749426af1e900a1b3354922fdd7e8b3bfa38084 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jan 2015 17:18:42 -0800 Subject: altos/usbtrng-v2.0: Use stmf042 hardware CRC unit Switch from software to hardware for CRC computation. I think this must be faster, right? Signed-off-by: Keith Packard --- src/usbtrng-v2.0/Makefile | 1 + src/usbtrng-v2.0/ao_pins.h | 4 +++ src/usbtrng-v2.0/ao_usbtrng.c | 60 ++++++++++--------------------------------- 3 files changed, 18 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/usbtrng-v2.0/Makefile b/src/usbtrng-v2.0/Makefile index 2806d377..abbdbbcc 100644 --- a/src/usbtrng-v2.0/Makefile +++ b/src/usbtrng-v2.0/Makefile @@ -24,6 +24,7 @@ ALTOS_SRC = \ ao_mutex.c \ ao_dma_stm.c \ ao_adc_fast.c \ + ao_crc_stm.c \ ao_stdio.c \ ao_led.c \ ao_romconfig.c \ diff --git a/src/usbtrng-v2.0/ao_pins.h b/src/usbtrng-v2.0/ao_pins.h index 90efb864..f22678be 100644 --- a/src/usbtrng-v2.0/ao_pins.h +++ b/src/usbtrng-v2.0/ao_pins.h @@ -55,4 +55,8 @@ #define AO_NUM_ADC 1 +/* CRC */ +#define AO_CRC_WIDTH 32 +#define AO_CRC_INIT 0xffffffff + #endif /* _AO_PINS_H_ */ diff --git a/src/usbtrng-v2.0/ao_usbtrng.c b/src/usbtrng-v2.0/ao_usbtrng.c index c5ed5603..26cfbac9 100644 --- a/src/usbtrng-v2.0/ao_usbtrng.c +++ b/src/usbtrng-v2.0/ao_usbtrng.c @@ -17,54 +17,19 @@ #include #include - -static const uint16_t crc16_table[256] = { - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040, -}; +#include static void ao_trng_fetch(void) { static uint16_t *buffer[2]; - static uint16_t adc_in[AO_USB_IN_SIZE]; /* twice as many as we need */ + static uint32_t adc_in[AO_USB_IN_SIZE/2]; /* twice as many as we need */ uint32_t kbytes = 1; uint32_t count; int usb_buf_id; - int i, j; - uint16_t crc16 = 0; + int i; uint16_t *buf; - uint8_t *rnd; + uint32_t *rnd; if (!buffer[0]) { buffer[0] = ao_usb_alloc(); @@ -80,16 +45,16 @@ ao_trng_fetch(void) ao_cmd_status = ao_cmd_success; usb_buf_id = 0; count = kbytes * (1024/AO_USB_IN_SIZE); + + ao_crc_reset(); + ao_led_on(AO_LED_GREEN); while (count--) { - ao_adc_read(adc_in, AO_USB_IN_SIZE); - rnd = (uint8_t *) adc_in; + ao_adc_read((uint16_t *) adc_in, AO_USB_IN_SIZE); + rnd = adc_in; buf = buffer[usb_buf_id]; - for (i = 0; i < 32; i++) { - for (j = 0; j < 4; j++) - crc16 = (crc16 >> 8) ^ crc16_table[(crc16 ^ *rnd++) & 0xff]; - *buf++ = crc16; - } + for (i = 0; i < 32; i++) + *buf++ = ao_crc_in_32_out_16(*rnd++); ao_led_toggle(AO_LED_GREEN|AO_LED_RED); ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); ao_led_toggle(AO_LED_GREEN|AO_LED_RED); @@ -100,7 +65,7 @@ ao_trng_fetch(void) } static const struct ao_cmds usbtrng_cmds[] = { - { ao_trng_fetch, "f\0Fetch a block of numbers" }, + { ao_trng_fetch, "f \0Fetch a block of numbers" }, { 0, NULL }, }; @@ -113,6 +78,7 @@ void main(void) ao_timer_init(); ao_dma_init(); ao_adc_init(); + ao_crc_init(); ao_cmd_init(); -- cgit v1.2.3 From 8ca1f234586225caea1040bc229b63491dadc1cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Jan 2015 20:41:15 -0800 Subject: altos/stmf0: Re-implement fast ADC code for stmf0 This creates a ring buffer for ADC data so that ADC fetching can run in parallel with other activities. Signed-off-by: Keith Packard --- src/kernel/ao.h | 1 + src/stmf0/ao_adc_fast.c | 42 +++++++++++++++-------------- src/stmf0/ao_adc_fast.h | 62 +++++++++++++++++++++++++++++++++++++++++++ src/usbtrng-v2.0/ao_usbtrng.c | 10 ++++--- 4 files changed, 91 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/kernel/ao.h b/src/kernel/ao.h index 16d600aa..59a469ae 100644 --- a/src/kernel/ao.h +++ b/src/kernel/ao.h @@ -72,6 +72,7 @@ typedef AO_PORT_TYPE ao_port_t; #define AO_PANIC_BUFIO 15 /* Mis-using bufio API */ #define AO_PANIC_EXTI 16 /* Mis-using exti API */ #define AO_PANIC_FAST_TIMER 17 /* Mis-using fast timer API */ +#define AO_PANIC_ADC 18 /* Mis-using ADC interface */ #define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */ #define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */ #define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */ diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index 5885ae4f..be9b5986 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -18,7 +18,10 @@ #include #include -static uint8_t ao_adc_done; +uint16_t ao_adc_ring[AO_ADC_RING_SIZE]; + +uint16_t ao_adc_ring_head, ao_adc_ring_tail; +uint8_t ao_adc_running; /* * Callback from DMA ISR @@ -28,22 +31,30 @@ static uint8_t ao_adc_done; static void ao_adc_dma_done(int index) { (void) index; - ao_adc_done = 1; - ao_wakeup(&ao_adc_done); + ao_adc_ring_head += AO_ADC_RING_CHUNK; + if (ao_adc_ring_head == AO_ADC_RING_SIZE) + ao_adc_ring_head = 0; + ao_adc_running = 0; + ao_wakeup(&ao_adc_ring_head); + ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); } -/* - * Start the ADC sequence using the DMA engine - */ void -ao_adc_read(uint16_t *dest, int len) +_ao_adc_start(void) { - ao_adc_done = 0; + uint16_t *buf; + + if (ao_adc_running) + return; + if (_ao_adc_space() < AO_ADC_RING_CHUNK) + return; + ao_adc_running = 1; + buf = ao_adc_ring + ao_adc_ring_head; stm_adc.isr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), &stm_adc.dr, - dest, - len, + buf, + AO_ADC_RING_CHUNK, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) | @@ -56,16 +67,6 @@ ao_adc_read(uint16_t *dest, int len) ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); stm_adc.cr |= (1 << STM_ADC_CR_ADSTART); - ao_arch_block_interrupts(); - while (!ao_adc_done) - ao_sleep(&ao_adc_done); - ao_arch_release_interrupts(); - - ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); - - stm_adc.cr |= (1 << STM_ADC_CR_ADSTP); - while ((stm_adc.cr & (1 << STM_ADC_CR_ADSTP)) != 0) - ; } void @@ -185,4 +186,5 @@ ao_adc_init(void) stm_syscfg.cfgr1 &= ~(1 << STM_SYSCFG_CFGR1_ADC_DMA_RMP); ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1)); + ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC_1), ao_adc_dma_done); } diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h index a2408d14..eec45505 100644 --- a/src/stmf0/ao_adc_fast.h +++ b/src/stmf0/ao_adc_fast.h @@ -24,4 +24,66 @@ ao_adc_read(uint16_t *dest, int len); void ao_adc_init(void); +/* Total ring size in samples */ +#define AO_ADC_RING_SIZE 256 +/* Number of samples fetched per ao_adc_start call */ +#define AO_ADC_RING_CHUNK (AO_ADC_RING_SIZE >> 1) + +extern uint16_t ao_adc_ring[AO_ADC_RING_SIZE]; + +#define ao_adc_ring_step(pos,inc) (((pos) + (inc)) & (AO_ADC_RING_SIZE - 1)) + +extern uint16_t ao_adc_ring_head, ao_adc_ring_tail; +extern uint8_t ao_adc_running; + +void +_ao_adc_start(void); + +static inline uint16_t +_ao_adc_remain(void) +{ + if (ao_adc_ring_tail > ao_adc_ring_head) + return AO_ADC_RING_SIZE - ao_adc_ring_tail; + return ao_adc_ring_head - ao_adc_ring_tail; +} + +static inline uint16_t +_ao_adc_space(void) +{ + if (ao_adc_ring_head == ao_adc_ring_tail) + return AO_ADC_RING_SIZE; + if (ao_adc_ring_head > ao_adc_ring_tail) + return AO_ADC_RING_SIZE - ao_adc_ring_head; + return ao_adc_ring_tail - ao_adc_ring_head; +} + +static inline uint16_t * +ao_adc_get(uint16_t n) +{ + if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE) + ao_panic(AO_PANIC_ADC); + ao_arch_block_interrupts(); + while (_ao_adc_remain() < n) { + if (!ao_adc_running) + _ao_adc_start(); + ao_sleep(&ao_adc_ring_head); + } + ao_arch_release_interrupts(); + return &ao_adc_ring[ao_adc_ring_tail]; +} + +static inline void +ao_adc_ack(uint16_t n) +{ + if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE) + ao_panic(AO_PANIC_ADC); + ao_arch_block_interrupts(); + ao_adc_ring_tail += n; + if (ao_adc_ring_tail == AO_ADC_RING_SIZE) + ao_adc_ring_tail = 0; + if (!ao_adc_running && _ao_adc_space() >= AO_ADC_RING_CHUNK) + _ao_adc_start(); + ao_arch_release_interrupts(); +} + #endif /* _AO_ADC_FAST_H_ */ diff --git a/src/usbtrng-v2.0/ao_usbtrng.c b/src/usbtrng-v2.0/ao_usbtrng.c index 26cfbac9..e1f43cdd 100644 --- a/src/usbtrng-v2.0/ao_usbtrng.c +++ b/src/usbtrng-v2.0/ao_usbtrng.c @@ -23,7 +23,6 @@ static void ao_trng_fetch(void) { static uint16_t *buffer[2]; - static uint32_t adc_in[AO_USB_IN_SIZE/2]; /* twice as many as we need */ uint32_t kbytes = 1; uint32_t count; int usb_buf_id; @@ -50,18 +49,21 @@ ao_trng_fetch(void) ao_led_on(AO_LED_GREEN); while (count--) { - ao_adc_read((uint16_t *) adc_in, AO_USB_IN_SIZE); - rnd = adc_in; buf = buffer[usb_buf_id]; +// printf ("before get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush(); + rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ +// printf ("after get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush(); for (i = 0; i < 32; i++) *buf++ = ao_crc_in_32_out_16(*rnd++); + ao_adc_ack(AO_USB_IN_SIZE); +// printf ("after ack: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush(); ao_led_toggle(AO_LED_GREEN|AO_LED_RED); ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); ao_led_toggle(AO_LED_GREEN|AO_LED_RED); usb_buf_id = 1-usb_buf_id; } ao_led_off(AO_LED_GREEN|AO_LED_RED); - ao_usb_flush(); + flush(); } static const struct ao_cmds usbtrng_cmds[] = { -- cgit v1.2.3 From bfa5c70a827ac8be23ca48797edc14e13461d6ac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Jan 2015 14:03:55 +0100 Subject: Oops, forgot the TeleBT-v3.0 Makefile git doesn't warn about files named 'Makefile' because they're supposed to be generated... Signed-off-by: Keith Packard --- src/telebt-v3.0/Makefile | 93 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/telebt-v3.0/Makefile (limited to 'src') diff --git a/src/telebt-v3.0/Makefile b/src/telebt-v3.0/Makefile new file mode 100644 index 00000000..6331a7b2 --- /dev/null +++ b/src/telebt-v3.0/Makefile @@ -0,0 +1,93 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_pins.h \ + ao_product.h \ + ao_cc1200_CC1200.h \ + ao_profile.h \ + ao_task.h \ + stm32l.h \ + Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +# ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_data.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_serial_stm.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_cc1200.c \ + ao_adc_stm.c \ + ao_btm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_eeprom_stm.c \ + ao_convert_volt.c \ + ao_packet_master.c \ + ao_packet.c \ + $(PROFILE) \ + $(SAMPLE_PROFILE) \ + $(STACK_GUARD) + +PRODUCT=TeleBT-v3.0 +PRODUCT_DEF=-DTELEBT_V_3_0 +IDPRODUCT=0x000e + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=telebt-v3.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telebt.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: -- cgit v1.2.3 From 252211e9e54a1e6f4efe2df6382ce60c909de70c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Jan 2015 14:04:50 +0100 Subject: And, also add the TeleBT v3.0 flash loader Makefile Signed-off-by: Keith Packard --- src/telebt-v3.0/flash-loader/Makefile | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/telebt-v3.0/flash-loader/Makefile (limited to 'src') diff --git a/src/telebt-v3.0/flash-loader/Makefile b/src/telebt-v3.0/flash-loader/Makefile new file mode 100644 index 00000000..a1c5168f --- /dev/null +++ b/src/telebt-v3.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telebt-v3.0 +include $(TOPDIR)/stm/Makefile-flash.defs -- cgit v1.2.3 From 44a503a8cf3778cad5469c592e8ccbae58e44b97 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:36:51 +0100 Subject: altos/stm: Add ability to delay STDIO usage for serial ports Bluetooth needs to delay adding the serial port to stdio until the link is up and running. The cc1111 serial driver had DELAY_SERIAL_*_STDIN bits which have been added to the STM serial driver. Signed-off-by: Keith Packard --- src/stm/ao_serial_stm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index e356b944..2568cf43 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -348,7 +348,7 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); -#if USE_SERIAL_1_STDIN +#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN ao_add_stdio(_ao_serial1_pollchar, ao_serial1_putchar, NULL); @@ -395,7 +395,7 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, 4); -#if USE_SERIAL_2_STDIN +#if USE_SERIAL_2_STDIN && !DELAY_SERIAL_2_STDIN ao_add_stdio(_ao_serial2_pollchar, ao_serial2_putchar, NULL); @@ -439,7 +439,7 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART3_POS); stm_nvic_set_priority(STM_ISR_USART3_POS, 4); -#if USE_SERIAL_3_STDIN +#if USE_SERIAL_3_STDIN && !DELAY_SERIAL_3_STDIN ao_add_stdio(_ao_serial3_pollchar, ao_serial3_putchar, NULL); -- cgit v1.2.3 From 870428a909025988a8cd834755ea166e2d1e34ca Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:39:17 +0100 Subject: altos/btm: Add fancier debug. Pull serial reset port low. Adds an interactive debugging mode to help diagnose BTM issues. Discovered that the serial reset pin on the BTM needs to be pulled low for the device to work correctly. Leave the bt link interrupt disabled until things are initialized. Signed-off-by: Keith Packard --- src/drivers/ao_btm.c | 144 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 93 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 9ea638ba..e6b28688 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -35,7 +35,7 @@ __xdata uint8_t ao_btm_connected; #if BT_DEBUG __xdata char ao_btm_buffer[256]; -int ao_btm_ptr; +uint16_t ao_btm_ptr; char ao_btm_dir; static void @@ -84,6 +84,10 @@ ao_btm_dump(void) putchar(ao_btm_buffer[i]); } putchar('\n'); + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success && ao_cmd_lex_i) + ao_btm_ptr = 0; + ao_cmd_status = ao_cmd_success; } static void @@ -98,9 +102,44 @@ ao_btm_speed(void) ao_cmd_status = ao_cmd_syntax_error; } +static uint8_t ao_btm_enable; + +static void +ao_btm_do_echo(void) +{ + int c; + while (ao_btm_enable) { + ao_arch_block_interrupts(); + while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable) + _ao_serial_btm_sleep(); + ao_arch_release_interrupts(); + if (c != AO_READ_AGAIN) { + putchar(c); + flush(); + } + } + ao_exit(); +} + +static struct ao_task ao_btm_echo_task; + +static void +ao_btm_send(void) +{ + int c; + ao_btm_enable = 1; + ao_add_task(&ao_btm_echo_task, ao_btm_do_echo, "btm-echo"); + while ((c = getchar()) != '~') { + ao_serial_btm_putchar(c); + } + ao_btm_enable = 0; + ao_wakeup((void *) &ao_serial_btm_rx_fifo); +} + __code struct ao_cmds ao_btm_cmds[] = { { ao_btm_dump, "d\0Dump btm buffer." }, { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, + { ao_btm_send, "S\0BTM interactive mode. ~ to exit." }, { 0, NULL }, }; @@ -260,6 +299,52 @@ ao_btm_try_speed(uint8_t speed) return 0; } +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#define BT_CC1111 1 +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#define BT_CC1111 1 +#endif + +void +ao_btm_check_link() +{ +#if BT_CC1111 + ao_arch_critical( + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { + ao_btm_connected = 0; + PICTL |= BT_PICTL_ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~BT_PICTL_ICON; + } + ); +#else + ao_arch_block_interrupts(); + if (ao_gpio_get(AO_BTM_INT_PORT, AO_BTM_INT_PIN, AO_BTM_INT) == 0) { + ao_btm_connected = 1; + } else { + ao_btm_connected = 0; + } + ao_arch_release_interrupts(); +#endif +} + +__xdata struct ao_task ao_btm_task; + /* * A thread to initialize the bluetooth device and * hang around to blink the LED when connected @@ -267,12 +352,6 @@ ao_btm_try_speed(uint8_t speed) void ao_btm(void) { -#ifdef AO_BTM_RESET_PORT - ao_gpio_set(AO_BTM_RESET_PORT, AO_BTM_RESET_PIN, AO_BTM_RESET, 0); - ao_delay(AO_MS_TO_TICKS(20)); - ao_gpio_set(AO_BTM_RESET_PORT, AO_BTM_RESET_PIN, AO_BTM_RESET, 1); -#endif - /* * Wait for the bluetooth device to boot */ @@ -308,6 +387,13 @@ ao_btm(void) NULL); ao_btm_echo(0); + /* Check current pin state */ + ao_btm_check_link(); + +#ifdef AO_BTM_INT_PORT + ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN); +#endif + for (;;) { while (!ao_btm_connected) ao_sleep(&ao_btm_connected); @@ -318,43 +404,6 @@ ao_btm(void) } } -__xdata struct ao_task ao_btm_task; - -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#define BT_CC1111 1 -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#define BT_CC1111 1 -#endif - -void -ao_btm_check_link() -{ -#if BT_CC1111 - ao_arch_critical( - /* Check the pin and configure the interrupt detector to wait for the - * pin to flip the other way - */ - if (BT_LINK_PIN) { - ao_btm_connected = 0; - PICTL |= BT_PICTL_ICON; - } else { - ao_btm_connected = 1; - PICTL &= ~BT_PICTL_ICON; - } - ); -#endif -} #if BT_CC1111 void @@ -425,13 +474,6 @@ ao_btm_init (void) IEN2 |= BT_IEN2_PIE; #endif - /* Check current pin state */ - ao_btm_check_link(); - -#ifdef AO_BTM_INT_PORT - ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN); -#endif - #if BT_LINK_ON_P2 /* Eable the pin interrupt */ PICTL |= PICTL_P2IEN; -- cgit v1.2.3 From a138e05ae6241a6743ca9f64528124f5f6c8e0ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:42:01 +0100 Subject: altos: Always include a check for stdio overflow For some reason, the check for running out of space to record stdio devices was disabled when only one device was expected. Signed-off-by: Keith Packard --- src/kernel/ao_stdio.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_stdio.c b/src/kernel/ao_stdio.c index 99118137..1d65fcf5 100644 --- a/src/kernel/ao_stdio.c +++ b/src/kernel/ao_stdio.c @@ -142,10 +142,8 @@ ao_add_stdio(int (*_pollchar)(void), void (*putchar)(char), void (*flush)(void)) __reentrant { -#if AO_NUM_STDIOS > 1 if (ao_num_stdios == AO_NUM_STDIOS) ao_panic(AO_PANIC_STDIO); -#endif ao_stdios[ao_num_stdios]._pollchar = _pollchar; ao_stdios[ao_num_stdios].putchar = putchar; ao_stdios[ao_num_stdios].flush = flush; -- cgit v1.2.3 From 845ae016d700c37948e053ead5f7e2778356fda3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:43:06 +0100 Subject: altos/telebt-v3.0: Fix stdio setup for BTM Make sure the BTM module is allowed to be included in stdio, but delay adding that until the BT link is running. Signed-off-by: Keith Packard --- src/telebt-v3.0/ao_pins.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index 0d03f94d..f178c349 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -49,12 +49,13 @@ #define SERIAL_1_PA9_PA10 1 #define HAS_SERIAL_2 1 -#define USE_SERIAL_2_STDIN 0 +#define USE_SERIAL_2_STDIN 1 +#define DELAY_SERIAL_2_STDIN 1 #define USE_SERIAL_2_FLOW 1 #define SERIAL_2_PA2_PA3 1 #define SERIAL_2_PD5_PD6 0 -#define HAS_SERIAL_3 1 +#define HAS_SERIAL_3 0 #define USE_SERIAL_3_STDIN 0 #define SERIAL_3_PB10_PB11 1 #define SERIAL_3_PC10_PC11 0 @@ -170,7 +171,7 @@ struct ao_adc { #define _ao_serial_btm_sleep _ao_serial2_sleep #define ao_serial_btm_set_speed ao_serial2_set_speed #define ao_serial_btm_drain ao_serial2_drain -#define ao_serial_btm_rx_fifo ao_serial2_rx_fifo +#define ao_serial_btm_rx_fifo (ao_stm_usart2.rx_fifo) #define AO_BTM_INT_PORT (&stm_gpioa) #define AO_BTM_INT_PIN 15 -- cgit v1.2.3 From 466d3e977ca279f97944141fcc12c04f4f58212e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:44:07 +0100 Subject: altos/telebt-v3.0: Turn red LED off after initialization This lets the user know the device successfully initialized. Signed-off-by: Keith Packard --- src/telebt-v3.0/ao_telebt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c index f3906e3f..133383ef 100644 --- a/src/telebt-v3.0/ao_telebt.c +++ b/src/telebt-v3.0/ao_telebt.c @@ -52,6 +52,8 @@ main(void) ao_config_init(); + ao_led_off(AO_LED_RED); + ao_start_scheduler(); return 0; } -- cgit v1.2.3 From 8f9e192e9d1c6fab9843939ff9117f6bb3725943 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:44:52 +0100 Subject: altos/stmf0: Support PA11/PA12 remapping Small pin-count versions of the STMF0 can remap PA11/PA12 on the same pins as PA9/PA10. These are used by USB, so have the USB driver deal with remapping them. Signed-off-by: Keith Packard --- src/stmf0/ao_usb_stm.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/stmf0/ao_usb_stm.c b/src/stmf0/ao_usb_stm.c index e0ff541a..3ea7da5e 100644 --- a/src/stmf0/ao_usb_stm.c +++ b/src/stmf0/ao_usb_stm.c @@ -23,6 +23,10 @@ #define USB_DEBUG_DATA 0 #define USB_ECHO 0 +#ifndef AO_PA11_PA12_RMP +#error "must define AO_PA11_PA12_RMP" +#endif + #ifndef USE_USB_STDIO #define USE_USB_STDIO 1 #endif @@ -1069,6 +1073,12 @@ __code struct ao_cmds ao_usb_cmds[] = { void ao_usb_init(void) { + /* Turn on syscfg */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGCOMPEN); + + /* Set PA11/PA12 remapping bit */ + stm_syscfg.cfgr1 |= (AO_PA11_PA12_RMP << STM_SYSCFG_CFGR1_PA11_PA12_RMP); + ao_usb_enable(); debug ("ao_usb_init\n"); -- cgit v1.2.3 From 6eb145d48cfcabf757093433bd2314a80e490a17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:46:40 +0100 Subject: altos/usbtrng-v2.0: Select PA11/PA12 mapping config value Signed-off-by: Keith Packard --- src/usbtrng-v2.0/ao_pins.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/usbtrng-v2.0/ao_pins.h b/src/usbtrng-v2.0/ao_pins.h index f22678be..23759444 100644 --- a/src/usbtrng-v2.0/ao_pins.h +++ b/src/usbtrng-v2.0/ao_pins.h @@ -40,8 +40,9 @@ #define AO_APB_PRESCALER 1 #define AO_RCC_CFGR_PPRE_DIV STM_RCC_CFGR_PPRE_DIV_1 -#define HAS_USB 1 -#define AO_USB_DIRECTIO 1 +#define HAS_USB 1 +#define AO_USB_DIRECTIO 1 +#define AO_PA11_PA12_RMP 0 #define IS_FLASH_LOADER 0 -- cgit v1.2.3 From be443d8d50ad8f59a74bf2f4e810a7359ff72132 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Feb 2015 16:57:14 +0100 Subject: altos/telebt-v3.0: Add monitor bits Will be useful to actually be able to receive telemetry Signed-off-by: Keith Packard --- src/telebt-v3.0/Makefile | 1 + src/telebt-v3.0/ao_pins.h | 5 +++++ src/telebt-v3.0/ao_telebt.c | 1 + 3 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/telebt-v3.0/Makefile b/src/telebt-v3.0/Makefile index 6331a7b2..a7ef4d64 100644 --- a/src/telebt-v3.0/Makefile +++ b/src/telebt-v3.0/Makefile @@ -55,6 +55,7 @@ ALTOS_SRC = \ ao_convert_volt.c \ ao_packet_master.c \ ao_packet.c \ + ao_monitor.c \ $(PROFILE) \ $(SAMPLE_PROFILE) \ $(STACK_GUARD) diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index f178c349..bcda90d1 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -200,4 +200,9 @@ struct ao_adc { #define HAS_BOOT_RADIO 0 +/* Monitor bits */ +#define HAS_MONITOR 1 +#define LEGACY_MONITOR 0 +#define AO_MONITOR_LED AO_LED_RED + #endif /* _AO_PINS_H_ */ diff --git a/src/telebt-v3.0/ao_telebt.c b/src/telebt-v3.0/ao_telebt.c index 133383ef..44ee4f3d 100644 --- a/src/telebt-v3.0/ao_telebt.c +++ b/src/telebt-v3.0/ao_telebt.c @@ -49,6 +49,7 @@ main(void) ao_usb_init(); ao_radio_init(); ao_packet_master_init(); + ao_monitor_init(); ao_config_init(); -- cgit v1.2.3 From dbafa16cfa897b2a5c6cf455cf8675e83eb0d7d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Feb 2015 20:30:15 -0800 Subject: altos/telebt-v3.0: Set initial radio cal to a sensible value CC1200 uses a different xtal than CC1120, so the default calibration needs to change. This value hit 434.550 on SN 2407, so it seems like a reasonable place to start. Signed-off-by: Keith Packard --- src/telebt-v3.0/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/telebt-v3.0/ao_pins.h b/src/telebt-v3.0/ao_pins.h index bcda90d1..838f0dfc 100644 --- a/src/telebt-v3.0/ao_pins.h +++ b/src/telebt-v3.0/ao_pins.h @@ -184,7 +184,7 @@ struct ao_adc { /* gets pretty close to 434.550 */ -#define AO_RADIO_CAL_DEFAULT 0x6ca333 +#define AO_RADIO_CAL_DEFAULT 5695485 #define AO_FEC_DEBUG 0 #define AO_CC1200_SPI_CS_PORT (&stm_gpiob) -- cgit v1.2.3 From bc41ab47b928b837724f8bc6b84d0b5b47c25df3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Feb 2015 20:33:04 -0800 Subject: altos: Rename teledongle-v1.9 as teledongle-v3.0 No hardware changes from the 1.9 prototypes to the 3.0 final version. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/teledongle-v1.9/.gitignore | 2 - src/teledongle-v1.9/Makefile | 79 -------------------- src/teledongle-v1.9/ao_pins.h | 113 ----------------------------- src/teledongle-v1.9/ao_teledongle.c | 53 -------------- src/teledongle-v1.9/flash-loader/Makefile | 7 -- src/teledongle-v1.9/flash-loader/ao_pins.h | 35 --------- src/teledongle-v3.0/.gitignore | 2 + src/teledongle-v3.0/Makefile | 79 ++++++++++++++++++++ src/teledongle-v3.0/ao_pins.h | 113 +++++++++++++++++++++++++++++ src/teledongle-v3.0/ao_teledongle.c | 53 ++++++++++++++ src/teledongle-v3.0/flash-loader/Makefile | 7 ++ src/teledongle-v3.0/flash-loader/ao_pins.h | 35 +++++++++ 13 files changed, 290 insertions(+), 290 deletions(-) delete mode 100644 src/teledongle-v1.9/.gitignore delete mode 100644 src/teledongle-v1.9/Makefile delete mode 100644 src/teledongle-v1.9/ao_pins.h delete mode 100644 src/teledongle-v1.9/ao_teledongle.c delete mode 100644 src/teledongle-v1.9/flash-loader/Makefile delete mode 100644 src/teledongle-v1.9/flash-loader/ao_pins.h create mode 100644 src/teledongle-v3.0/.gitignore create mode 100644 src/teledongle-v3.0/Makefile create mode 100644 src/teledongle-v3.0/ao_pins.h create mode 100644 src/teledongle-v3.0/ao_teledongle.c create mode 100644 src/teledongle-v3.0/flash-loader/Makefile create mode 100644 src/teledongle-v3.0/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index c8563c9d..05e99c7f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,7 +35,7 @@ ARMM3DIRS=\ telegps-v1.0 telegps-v1.0/flash-loader \ telelco-v0.2 telelco-v0.2/flash-loader \ telescience-v0.2 telescience-v0.2/flash-loader \ - teledongle-v1.9 teledongle-v1.9/flash-loader \ + teledongle-v3.0 teledongle-v3.0/flash-loader \ teleballoon-v2.0 \ telebt-v3.0 telebt-v3.0/flash-loader diff --git a/src/teledongle-v1.9/.gitignore b/src/teledongle-v1.9/.gitignore deleted file mode 100644 index 9a30cbb6..00000000 --- a/src/teledongle-v1.9/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ao_product.h -teledongle-*.elf diff --git a/src/teledongle-v1.9/Makefile b/src/teledongle-v1.9/Makefile deleted file mode 100644 index 78deb9e2..00000000 --- a/src/teledongle-v1.9/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -# -# AltOS build -# -# - -include ../lpc/Makefile.defs - -INC = \ - ao.h \ - ao_arch.h \ - ao_arch_funcs.h \ - ao_boot.h \ - ao_pins.h \ - ao_product.h \ - ao_task.h \ - ao_whiten.h \ - lpc.h \ - ao_cc1200.h \ - ao_cc1200_CC1200.h \ - Makefile - -ALTOS_SRC = \ - ao_boot_chain.c \ - ao_interrupt.c \ - ao_product.c \ - ao_romconfig.c \ - ao_cc1200.c \ - ao_cmd.c \ - ao_config.c \ - ao_task.c \ - ao_led_lpc.c \ - ao_stdio.c \ - ao_panic.c \ - ao_timer_lpc.c \ - ao_mutex.c \ - ao_freq.c \ - ao_spi_lpc.c \ - ao_usb_lpc.c \ - ao_exti_lpc.c \ - ao_send_packet.c \ - ao_monitor.c \ - ao_packet_master.c \ - ao_packet.c - -PRODUCT=TeleDongle-v1.9 -PRODUCT_DEF=-DTELEDONGLE -IDPRODUCT=0x000c - -CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -Os -g - -PROGNAME=teledongle-v1.9 -PROG=$(PROGNAME)-$(VERSION).elf -HEX=$(PROGNAME)-$(VERSION).ihx - -SRC=$(ALTOS_SRC) ao_teledongle.c -OBJ=$(SRC:.c=.o) - -all: $(PROG) $(HEX) - -$(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) - -$(OBJ): $(INC) - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -load: $(PROG) - lpc-load $(PROG) - -distclean: clean - -clean: - rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx - rm -f ao_product.h - -install: - -uninstall: diff --git a/src/teledongle-v1.9/ao_pins.h b/src/teledongle-v1.9/ao_pins.h deleted file mode 100644 index f8889c4a..00000000 --- a/src/teledongle-v1.9/ao_pins.h +++ /dev/null @@ -1,113 +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; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -/* Using TeleMetrum v1.9 board */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#define AO_STACK_SIZE 324 - -#define HAS_TASK_QUEUE 1 - -#define IS_FLASH_LOADER 0 - -/* Crystal on the board */ -#define AO_LPC_CLKIN 12000000 - -/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ -#define AO_LPC_CLKOUT 48000000 - -/* System clock frequency */ -#define AO_LPC_SYSCLK 24000000 - -#define HAS_EEPROM 0 -#define USE_INTERNAL_FLASH 0 -#define USE_STORAGE_CONFIG 0 -#define USE_EEPROM_CONFIG 0 - -#define HAS_USB 1 -#define HAS_USB_CONNECT 0 -#define HAS_USB_VBUS 0 -#define HAS_USB_PULLUP 1 -#define AO_USB_PULLUP_PORT 0 -#define AO_USB_PULLUP_PIN 20 - -#define HAS_BEEP 0 -#define HAS_RADIO 1 -#define HAS_TELEMETRY 0 -#define HAS_RSSI 0 - -#define HAS_SPI_0 1 -#define SPI_SCK0_P0_6 1 - -#define PACKET_HAS_SLAVE 0 -#define PACKET_HAS_MASTER 1 - -#define LOW_LEVEL_DEBUG 0 - -#define LED_PORT 0 -#define LED_PIN_RED 14 -#define LED_PIN_GREEN 7 -#define AO_LED_RED (1 << LED_PIN_RED) -#define AO_LED_GREEN (1 << LED_PIN_GREEN) - -#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) - -#define HAS_GPS 0 -#define HAS_FLIGHT 0 -#define HAS_ADC 0 -#define HAS_LOG 0 - -/* - * Telemetry monitoring - */ -#define HAS_MONITOR 1 -#define LEGACY_MONITOR 0 -#define HAS_MONITOR_PUT 1 -#define AO_MONITOR_LED AO_LED_GREEN -#define AO_MONITOR_BAD AO_LED_RED - -/* - * Radio (cc1200) - */ - -/* gets pretty close to 434.550 */ - -#define AO_RADIO_CAL_DEFAULT 5695733 - -#define AO_FEC_DEBUG 0 -#define AO_CC1200_SPI_CS_PORT 0 -#define AO_CC1200_SPI_CS_PIN 3 -#define AO_CC1200_SPI_BUS 0 -#define AO_CC1200_SPI 0 - -#define AO_CC1200_INT_PORT 0 -#define AO_CC1200_INT_PIN 2 - -#define AO_CC1200_INT_GPIO 2 -#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 - -/* - * Profiling Viterbi decoding - */ - -#ifndef AO_PROFILE -#define AO_PROFILE 0 -#endif - -#endif /* _AO_PINS_H_ */ diff --git a/src/teledongle-v1.9/ao_teledongle.c b/src/teledongle-v1.9/ao_teledongle.c deleted file mode 100644 index 02b93efe..00000000 --- a/src/teledongle-v1.9/ao_teledongle.c +++ /dev/null @@ -1,53 +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; 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 -#include -#include - -int -main(void) -{ - ao_clock_init(); - -#if HAS_STACK_GUARD - ao_mpu_init(); -#endif - - ao_task_init(); - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - ao_timer_init(); - - ao_spi_init(); - ao_exti_init(); - - ao_cmd_init(); - - ao_usb_init(); - ao_radio_init(); - ao_monitor_init(); - ao_packet_master_init(); - ao_send_packet_init(); - - ao_config_init(); - - ao_led_off(AO_LED_RED); - ao_start_scheduler(); - return 0; -} diff --git a/src/teledongle-v1.9/flash-loader/Makefile b/src/teledongle-v1.9/flash-loader/Makefile deleted file mode 100644 index a5642b46..00000000 --- a/src/teledongle-v1.9/flash-loader/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -# -# AltOS flash loader build -# - -TOPDIR=../.. -HARDWARE=teledongle-v1.9 -include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/teledongle-v1.9/flash-loader/ao_pins.h b/src/teledongle-v1.9/flash-loader/ao_pins.h deleted file mode 100644 index aee5be27..00000000 --- a/src/teledongle-v1.9/flash-loader/ao_pins.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * 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. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#include - -/* Debug port TXD (pin 6) */ - -#define AO_BOOT_PIN 1 -#define AO_BOOT_APPLICATION_GPIO 0 -#define AO_BOOT_APPLICATION_PIN 19 -#define AO_BOOT_APPLICATION_VALUE 1 -#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP - -#define HAS_USB_PULLUP 1 -#define AO_USB_PULLUP_PORT 0 -#define AO_USB_PULLUP_PIN 20 - -#endif /* _AO_PINS_H_ */ diff --git a/src/teledongle-v3.0/.gitignore b/src/teledongle-v3.0/.gitignore new file mode 100644 index 00000000..9a30cbb6 --- /dev/null +++ b/src/teledongle-v3.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +teledongle-*.elf diff --git a/src/teledongle-v3.0/Makefile b/src/teledongle-v3.0/Makefile new file mode 100644 index 00000000..a656cde5 --- /dev/null +++ b/src/teledongle-v3.0/Makefile @@ -0,0 +1,79 @@ +# +# AltOS build +# +# + +include ../lpc/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + ao_whiten.h \ + lpc.h \ + ao_cc1200.h \ + ao_cc1200_CC1200.h \ + Makefile + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cc1200.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led_lpc.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer_lpc.c \ + ao_mutex.c \ + ao_freq.c \ + ao_spi_lpc.c \ + ao_usb_lpc.c \ + ao_exti_lpc.c \ + ao_send_packet.c \ + ao_monitor.c \ + ao_packet_master.c \ + ao_packet.c + +PRODUCT=TeleDongle-v3.0 +PRODUCT_DEF=-DTELEDONGLE +IDPRODUCT=0x000c + +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -Os -g + +PROGNAME=teledongle-v3.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_teledongle.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +load: $(PROG) + lpc-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/teledongle-v3.0/ao_pins.h b/src/teledongle-v3.0/ao_pins.h new file mode 100644 index 00000000..c023b2cf --- /dev/null +++ b/src/teledongle-v3.0/ao_pins.h @@ -0,0 +1,113 @@ +/* + * 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. + */ + +/* Using TeleDongle v3.0 board */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define AO_STACK_SIZE 324 + +#define HAS_TASK_QUEUE 1 + +#define IS_FLASH_LOADER 0 + +/* Crystal on the board */ +#define AO_LPC_CLKIN 12000000 + +/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ +#define AO_LPC_CLKOUT 48000000 + +/* System clock frequency */ +#define AO_LPC_SYSCLK 24000000 + +#define HAS_EEPROM 0 +#define USE_INTERNAL_FLASH 0 +#define USE_STORAGE_CONFIG 0 +#define USE_EEPROM_CONFIG 0 + +#define HAS_USB 1 +#define HAS_USB_CONNECT 0 +#define HAS_USB_VBUS 0 +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#define HAS_BEEP 0 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 0 +#define HAS_RSSI 0 + +#define HAS_SPI_0 1 +#define SPI_SCK0_P0_6 1 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 1 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT 0 +#define LED_PIN_RED 14 +#define LED_PIN_GREEN 7 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS 0 +#define HAS_FLIGHT 0 +#define HAS_ADC 0 +#define HAS_LOG 0 + +/* + * Telemetry monitoring + */ +#define HAS_MONITOR 1 +#define LEGACY_MONITOR 0 +#define HAS_MONITOR_PUT 1 +#define AO_MONITOR_LED AO_LED_GREEN +#define AO_MONITOR_BAD AO_LED_RED + +/* + * Radio (cc1200) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT 0 +#define AO_CC1200_SPI_CS_PIN 3 +#define AO_CC1200_SPI_BUS 0 +#define AO_CC1200_SPI 0 + +#define AO_CC1200_INT_PORT 0 +#define AO_CC1200_INT_PIN 2 + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +/* + * Profiling Viterbi decoding + */ + +#ifndef AO_PROFILE +#define AO_PROFILE 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/teledongle-v3.0/ao_teledongle.c b/src/teledongle-v3.0/ao_teledongle.c new file mode 100644 index 00000000..02b93efe --- /dev/null +++ b/src/teledongle-v3.0/ao_teledongle.c @@ -0,0 +1,53 @@ +/* + * 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 +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + + ao_spi_init(); + ao_exti_init(); + + ao_cmd_init(); + + ao_usb_init(); + ao_radio_init(); + ao_monitor_init(); + ao_packet_master_init(); + ao_send_packet_init(); + + ao_config_init(); + + ao_led_off(AO_LED_RED); + ao_start_scheduler(); + return 0; +} diff --git a/src/teledongle-v3.0/flash-loader/Makefile b/src/teledongle-v3.0/flash-loader/Makefile new file mode 100644 index 00000000..b8325114 --- /dev/null +++ b/src/teledongle-v3.0/flash-loader/Makefile @@ -0,0 +1,7 @@ +# +# AltOS flash loader build +# + +TOPDIR=../.. +HARDWARE=teledongle-v3.0 +include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/teledongle-v3.0/flash-loader/ao_pins.h b/src/teledongle-v3.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..aee5be27 --- /dev/null +++ b/src/teledongle-v3.0/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; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +/* Debug port TXD (pin 6) */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO 0 +#define AO_BOOT_APPLICATION_PIN 19 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From ef69872c824668146a3876f1f3d0d2e51d3e4c8d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Feb 2015 14:54:27 -0800 Subject: Revert "altos/lpc: Fix double-buffered USB changes" This reverts commit 41a0604ad1ea1a03e2db7d41731dbadf466b45db. --- src/lpc/ao_usb_lpc.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index af304b8a..499de9e9 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -273,7 +273,7 @@ static uint8_t * ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes) { uint8_t *addr = ao_usb_alloc_sram(nbytes); - + ao_usb_set_ep(ep, addr, set_nbytes); return addr; } @@ -292,11 +292,11 @@ ao_usb_disable_ep(vuint32_t *ep) } static void -ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint16_t out_set_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) +ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) { uint8_t *addr; - addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_set_bytes); + addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_bytes); if (out_addr) *out_addr = addr; ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); @@ -359,15 +359,15 @@ ao_usb_set_configuration(void) debug ("ao_usb_set_configuration\n"); /* Set up the INT end point */ - ao_usb_enable_epn(AO_USB_INT_EP, 0, 0, NULL, 0, NULL); + ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); /* Set up the OUT end point */ - ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE * 2, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer[0], 0, NULL); + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE * 2, &ao_usb_out_rx_buffer[0], 0, NULL); ao_usb_out_rx_buffer[1] = ao_usb_out_rx_buffer[0] + AO_USB_OUT_SIZE; ao_usb_out_rx_cur = 0; /* Set up the IN end point */ - ao_usb_enable_epn(AO_USB_IN_EP, 0, 0, NULL, AO_USB_IN_SIZE * 2, &ao_usb_in_tx_buffer[0]); + ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE * 2, &ao_usb_in_tx_buffer[0]); ao_usb_in_tx_buffer[1] = ao_usb_in_tx_buffer[0] + AO_USB_IN_SIZE; ao_usb_in_tx_cur = 0; @@ -771,10 +771,12 @@ ao_usb_putchar(char c) ao_arch_block_interrupts(); _ao_usb_in_wait(); + ao_arch_release_interrupts(); ao_usb_in_flushed = 0; ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c; + ao_arch_block_interrupts(); /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) { _tx_dbg0("putchar full"); @@ -784,7 +786,6 @@ ao_usb_putchar(char c) ao_arch_release_interrupts(); } -#if HAS_AO_USB_WRITE void * ao_usb_alloc(uint16_t len) { @@ -808,6 +809,8 @@ ao_usb_write(void *block, int len) this_time = AO_USB_IN_SIZE; if (this_time > len) this_time = len; + b += this_time; + len -= this_time; ao_arch_block_interrupts(); while (ao_usb_in_pending) @@ -817,11 +820,8 @@ ao_usb_write(void *block, int len) ao_usb_in_flushed = 1; ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), b, this_time); ao_arch_release_interrupts(); - b += this_time; - len -= this_time; } } -#endif static void _ao_usb_out_recv(void) @@ -835,10 +835,10 @@ _ao_usb_out_recv(void) debug ("recv %d\n", ao_usb_rx_count); debug_data("Fill OUT len %d\n", ao_usb_rx_count); ao_usb_rx_pos = 0; - ao_usb_out_rx_cur = 1 - ao_usb_out_rx_cur; + ao_usb_rx_out_cur = 1 - ao_usb_rx_out_cur; /* ACK the packet */ - ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_out_rx_cur], AO_USB_OUT_SIZE); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_rx_out_cur], AO_USB_OUT_SIZE); } int @@ -863,7 +863,7 @@ _ao_usb_pollchar(void) } /* Pull a character out of the fifo */ - c = ao_usb_out_rx_buffer[ao_usb_out_rx_cur][ao_usb_rx_pos++]; + c = ao_usb_rx_buffer[ao_usb_rx_out_cur][ao_usb_rx_pos++]; return c; } @@ -937,7 +937,7 @@ ao_usb_enable(void) /* Enable USB PHY */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD); - + /* Turn on USB PLL */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD); -- cgit v1.2.3 From 5bf39f674b3d5ee98b55f42562a5ba1a9328ff07 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Feb 2015 14:56:13 -0800 Subject: Revert LPC usb performance improvements There's something screwy going on, sticking garbage in the input buffer at boot time Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 2 -- src/lpc/ao_arch_funcs.h | 6 ---- src/lpc/ao_usb_lpc.c | 76 ++++++++++++------------------------------------- 3 files changed, 18 insertions(+), 66 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 1b4c61f2..42faf06f 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -124,8 +124,6 @@ ao_adc_init(void); #define AO_USB_OUT_EP 2 #define AO_USB_IN_EP 3 -extern uint8_t ao_usb_out_avail; - void ao_serial_init(void); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index b963d3ab..fbe641d8 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -249,10 +249,4 @@ static inline void ao_arch_start_scheduler(void) { asm("isb"); } -void * -ao_usb_alloc(uint16_t len); - -void -ao_usb_write(void *block, int len); - #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 499de9e9..12f5d8e6 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -80,12 +80,14 @@ static uint8_t *ao_usb_ep0_setup_buffer; static uint8_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ -static uint8_t *ao_usb_in_tx_buffer[2]; -static uint8_t ao_usb_in_tx_cur; +static uint8_t *ao_usb_in_tx_buffer; +static uint8_t *ao_usb_out_rx_buffer; + +/* Our data buffers */ +static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; static uint8_t ao_usb_tx_count; -static uint8_t *ao_usb_out_rx_buffer[2]; -static uint8_t ao_usb_out_rx_cur; +static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; extern struct lpc_usb_endpoint lpc_usb_endpoint; @@ -106,7 +108,7 @@ static uint8_t ao_usb_in_pending; /* Marks when an OUT packet has been received by the hardware * but not pulled to the shadow buffer. */ -uint8_t ao_usb_out_avail; +static uint8_t ao_usb_out_avail; uint8_t ao_usb_running; static uint8_t ao_usb_configuration; @@ -360,16 +362,12 @@ ao_usb_set_configuration(void) /* Set up the INT end point */ ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); - + /* Set up the OUT end point */ - ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE * 2, &ao_usb_out_rx_buffer[0], 0, NULL); - ao_usb_out_rx_buffer[1] = ao_usb_out_rx_buffer[0] + AO_USB_OUT_SIZE; - ao_usb_out_rx_cur = 0; + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL); /* Set up the IN end point */ - ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE * 2, &ao_usb_in_tx_buffer[0]); - ao_usb_in_tx_buffer[1] = ao_usb_in_tx_buffer[0] + AO_USB_IN_SIZE; - ao_usb_in_tx_cur = 0; + ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer); ao_usb_running = 1; } @@ -718,8 +716,8 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer[ao_usb_in_tx_cur], ao_usb_tx_count); - ao_usb_in_tx_cur = 1 - ao_usb_in_tx_cur; + memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count); + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer, ao_usb_tx_count); ao_usb_tx_count = 0; _tx_dbg0("in_send end"); } @@ -771,12 +769,10 @@ ao_usb_putchar(char c) ao_arch_block_interrupts(); _ao_usb_in_wait(); - ao_arch_release_interrupts(); ao_usb_in_flushed = 0; - ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c; + ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; - ao_arch_block_interrupts(); /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) { _tx_dbg0("putchar full"); @@ -786,43 +782,6 @@ ao_usb_putchar(char c) ao_arch_release_interrupts(); } -void * -ao_usb_alloc(uint16_t len) -{ - return ao_usb_alloc_sram(len); -} - -void -ao_usb_write(void *block, int len) -{ - uint8_t *b = block; - int this_time; - - if (!ao_usb_running) - return; - - if (!ao_usb_in_flushed) - ao_usb_flush(); - - while (len) { - ao_usb_in_flushed = 0; - this_time = AO_USB_IN_SIZE; - if (this_time > len) - this_time = len; - b += this_time; - len -= this_time; - - ao_arch_block_interrupts(); - while (ao_usb_in_pending) - ao_sleep(&ao_usb_in_pending); - ao_usb_in_pending = 1; - if (this_time != AO_USB_IN_SIZE) - ao_usb_in_flushed = 1; - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), b, this_time); - ao_arch_release_interrupts(); - } -} - static void _ao_usb_out_recv(void) { @@ -833,12 +792,13 @@ _ao_usb_out_recv(void) _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); - debug_data("Fill OUT len %d\n", ao_usb_rx_count); + debug_data("Fill OUT len %d:", ao_usb_rx_count); + memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); + debug_data("\n"); ao_usb_rx_pos = 0; - ao_usb_rx_out_cur = 1 - ao_usb_rx_out_cur; /* ACK the packet */ - ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_rx_out_cur], AO_USB_OUT_SIZE); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE); } int @@ -863,7 +823,7 @@ _ao_usb_pollchar(void) } /* Pull a character out of the fifo */ - c = ao_usb_rx_buffer[ao_usb_rx_out_cur][ao_usb_rx_pos++]; + c = ao_usb_rx_buffer[ao_usb_rx_pos++]; return c; } -- cgit v1.2.3 From 2bde76fe852d7908a968168580be4cd4dc0333d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Feb 2015 15:01:03 -0800 Subject: altos/teledongle-v3.0: Shrink stacks to 320 bytes to fit in ram The old USB code had static in/out buffers in ram Signed-off-by: Keith Packard --- src/teledongle-v3.0/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/teledongle-v3.0/ao_pins.h b/src/teledongle-v3.0/ao_pins.h index c023b2cf..52a86fcb 100644 --- a/src/teledongle-v3.0/ao_pins.h +++ b/src/teledongle-v3.0/ao_pins.h @@ -20,7 +20,7 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#define AO_STACK_SIZE 324 +#define AO_STACK_SIZE 320 #define HAS_TASK_QUEUE 1 -- cgit v1.2.3 From a01ce949611b0c18df54c3f3877a43d27699c258 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Feb 2015 15:34:05 -0800 Subject: altos/easymini-v1.0: Shrink stack to deal with USB changes Reverting the USB double buffering means using more RAM, need to shrink the EasyMini stack to accomodate that. Signed-off-by: Keith Packard --- src/easymini-v1.0/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/easymini-v1.0/ao_pins.h b/src/easymini-v1.0/ao_pins.h index 0edde5a2..1d794497 100644 --- a/src/easymini-v1.0/ao_pins.h +++ b/src/easymini-v1.0/ao_pins.h @@ -18,7 +18,7 @@ #define HAS_BEEP 1 #define HAS_BATTERY_REPORT 1 -#define AO_STACK_SIZE 384 +#define AO_STACK_SIZE 376 #define IS_FLASH_LOADER 0 -- cgit v1.2.3 From 0671b3c8c24c9f33be77a10315c4669f33c516d7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Feb 2015 16:08:44 -0800 Subject: altos/lpc: Clean up USB endpoint access functions The USB device endpoints can have two pointers in them, but we use only the first. Fix the access functions to take an index as to which we want so that we can disable the other address registers with them instead of requiring open-coded access. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 12f5d8e6..78fbac39 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -234,15 +234,15 @@ ao_usb_ep0_in(void) } static inline vuint32_t * -ao_usb_epn_out(uint8_t n) +ao_usb_epn_out(uint8_t n, uint8_t i) { - return &lpc_usb_endpoint.epn[n-1].out[0]; + return &lpc_usb_endpoint.epn[n-1].out[i]; } static inline vuint32_t * -ao_usb_epn_in(uint8_t n) +ao_usb_epn_in(uint8_t n, uint8_t i) { - return &lpc_usb_endpoint.epn[n-1].in[0]; + return &lpc_usb_endpoint.epn[n-1].in[i]; } #if UNUSED @@ -256,26 +256,26 @@ ao_usb_set_epn_in(uint8_t n, uint8_t *addr, uint16_t nbytes) static void ao_usb_set_epn_out(uint8_t n, uint8_t *addr, uint16_t nbytes) { - ao_usb_set_ep(ao_usb_epn_out(n), addr, nbytes); + ao_usb_set_ep(ao_usb_epn_out(n, 0), addr, nbytes); } static inline uint16_t ao_usb_epn_out_count(uint8_t n) { - return ao_usb_ep_count(ao_usb_epn_out(n)); + return ao_usb_ep_count(ao_usb_epn_out(n, 0)); } static inline uint16_t ao_usb_epn_in_count(uint8_t n) { - return ao_usb_ep_count(ao_usb_epn_in(n)); + return ao_usb_ep_count(ao_usb_epn_in(n, 0)); } static uint8_t * ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes) { uint8_t *addr = ao_usb_alloc_sram(nbytes); - + ao_usb_set_ep(ep, addr, set_nbytes); return addr; } @@ -298,24 +298,24 @@ ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in { uint8_t *addr; - addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_bytes); + addr = ao_usb_enable_ep(ao_usb_epn_out(n, 0), out_bytes, out_bytes); if (out_addr) *out_addr = addr; - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); + ao_usb_disable_ep(ao_usb_epn_out(n, 1)); - addr = ao_usb_enable_ep(ao_usb_epn_in(n), in_bytes, 0); + addr = ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_bytes, 0); if (in_addr) *in_addr = addr; - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); + ao_usb_disable_ep(ao_usb_epn_in(n, 1)); } static void ao_usb_disable_epn(uint8_t n) { - ao_usb_disable_ep(ao_usb_epn_out(n)); - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); - ao_usb_disable_ep(ao_usb_epn_in(n)); - ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); + ao_usb_disable_ep(ao_usb_epn_out(n, 0)); + ao_usb_disable_ep(ao_usb_epn_out(n, 1)); + ao_usb_disable_ep(ao_usb_epn_in(n, 0)); + ao_usb_disable_ep(ao_usb_epn_in(n, 1)); } static void @@ -717,7 +717,7 @@ _ao_usb_in_send(void) if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count); - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP, 0), ao_usb_in_tx_buffer, ao_usb_tx_count); ao_usb_tx_count = 0; _tx_dbg0("in_send end"); } @@ -897,7 +897,7 @@ ao_usb_enable(void) /* Enable USB PHY */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD); - + /* Turn on USB PLL */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD); @@ -1044,7 +1044,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].primask = primask; #if TX_DBG dbg[dbg_i].in_count = in_count; - dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP); + dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP, 0); dbg[dbg_i].in_pending = ao_usb_in_pending; dbg[dbg_i].tx_count = ao_usb_tx_count; dbg[dbg_i].in_flushed = ao_usb_in_flushed; @@ -1053,7 +1053,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].rx_count = ao_usb_rx_count; dbg[dbg_i].rx_pos = ao_usb_rx_pos; dbg[dbg_i].out_avail = ao_usb_out_avail; - dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP); + dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP, 0); #endif if (++dbg_i == NUM_USB_DBG) dbg_i = 0; -- cgit v1.2.3 From 9fac8b639d2142c90eb95771cda1f6559e987db2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Jan 2015 22:09:26 +1300 Subject: altos/lpc: Double buffer USB data transfers This allocates twice the space in the USB memory so that transactions can be double buffered without using separate CPU memory. Signed-off-by: Keith Packard Conflicts: src/lpc/ao_usb_lpc.c --- src/lpc/ao_usb_lpc.c | 57 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 78fbac39..0dfaece4 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -80,14 +80,12 @@ static uint8_t *ao_usb_ep0_setup_buffer; static uint8_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ -static uint8_t *ao_usb_in_tx_buffer; -static uint8_t *ao_usb_out_rx_buffer; - -/* Our data buffers */ -static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t *ao_usb_in_tx_buffer[2]; +static uint8_t ao_usb_in_tx_cur; static uint8_t ao_usb_tx_count; -static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t *ao_usb_out_rx_buffer[2]; +static uint8_t ao_usb_out_rx_cur; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; extern struct lpc_usb_endpoint lpc_usb_endpoint; @@ -294,18 +292,24 @@ ao_usb_disable_ep(vuint32_t *ep) } static void -ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) +ao_usb_enable_epn(uint8_t n, + uint16_t out_bytes, uint8_t *out_addrs[2], + uint16_t in_bytes, uint8_t *in_addrs[2]) { uint8_t *addr; - addr = ao_usb_enable_ep(ao_usb_epn_out(n, 0), out_bytes, out_bytes); - if (out_addr) - *out_addr = addr; + addr = ao_usb_enable_ep(ao_usb_epn_out(n, 0), out_bytes * 2, out_bytes); + if (out_addrs) { + out_addrs[0] = addr; + out_addrs[1] = addr + out_bytes; + } ao_usb_disable_ep(ao_usb_epn_out(n, 1)); - addr = ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_bytes, 0); - if (in_addr) - *in_addr = addr; + addr = ao_usb_enable_ep(ao_usb_epn_in(n, 0), in_bytes * 2, 0); + if (in_addrs) { + in_addrs[0] = addr; + in_addrs[1] = addr + in_bytes; + } ao_usb_disable_ep(ao_usb_epn_in(n, 1)); } @@ -362,12 +366,18 @@ ao_usb_set_configuration(void) /* Set up the INT end point */ ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); - + /* Set up the OUT end point */ - ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL); + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, ao_usb_out_rx_buffer, 0, NULL); + + /* Set the current RX pointer to the *other* buffer so that when buffer 0 gets + * data, we'll switch to it and pull bytes from there + */ + ao_usb_out_rx_cur = 1; /* Set up the IN end point */ - ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer); + ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, ao_usb_in_tx_buffer); + ao_usb_in_tx_cur = 0; ao_usb_running = 1; } @@ -716,8 +726,8 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count); - ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP, 0), ao_usb_in_tx_buffer, ao_usb_tx_count); + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP, 0), ao_usb_in_tx_buffer[ao_usb_in_tx_cur], ao_usb_tx_count); + ao_usb_in_tx_cur = 1 - ao_usb_in_tx_cur; ao_usb_tx_count = 0; _tx_dbg0("in_send end"); } @@ -771,7 +781,7 @@ ao_usb_putchar(char c) _ao_usb_in_wait(); ao_usb_in_flushed = 0; - ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + ao_usb_in_tx_buffer[ao_usb_in_tx_cur][ao_usb_tx_count++] = (uint8_t) c; /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) { @@ -792,13 +802,12 @@ _ao_usb_out_recv(void) _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); - debug_data("Fill OUT len %d:", ao_usb_rx_count); - memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); - debug_data("\n"); + debug_data("Fill OUT len %d\n", ao_usb_rx_count); ao_usb_rx_pos = 0; + ao_usb_out_rx_cur = 1 - ao_usb_out_rx_cur; /* ACK the packet */ - ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer[1-ao_usb_out_rx_cur], AO_USB_OUT_SIZE); } int @@ -823,7 +832,7 @@ _ao_usb_pollchar(void) } /* Pull a character out of the fifo */ - c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + c = ao_usb_out_rx_buffer[ao_usb_out_rx_cur][ao_usb_rx_pos++]; return c; } -- cgit v1.2.3 From 4b52f67abd0f9ed6d8208556007d75e7ee735cf0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Feb 2015 01:05:03 -0800 Subject: altos/drivers: Increase SPI speed of CC115L to 6MHz The datasheet says that the maximum for back-to-back data is 6.5MHz. Signed-off-by: Keith Packard --- src/drivers/ao_cc115l.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index 6b76e7d3..0246ba02 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -38,7 +38,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_1MHz) +#define ao_radio_select() ao_spi_get_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS,AO_SPI_SPEED_6MHz) #define ao_radio_deselect() ao_spi_put_mask(AO_CC115L_SPI_CS_PORT,(1 << AO_CC115L_SPI_CS_PIN),AO_CC115L_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC115L_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC115L_SPI_BUS) -- cgit v1.2.3 From f9f235bce84df3a6c0261e9d256aac544f87f70f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Feb 2015 01:05:57 -0800 Subject: altos/lpc: Give up on interrupt-driven SPI driver There are just too many limitations in when interrupts are delivered to make them useful. Instead, just drive the SPI directly with the CPU. At higher spi speeds (6Mhz or more), it's probably faster to do it this way anyways. Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 133 ++++++++++----------------------------------------- 1 file changed, 25 insertions(+), 108 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index 5a358919..f091c89c 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -19,130 +19,56 @@ static uint8_t ao_spi_mutex[LPC_NUM_SPI]; -struct ao_lpc_ssp_state { - int tx_count; - const uint8_t *tx; - int tx_inc; - int rx_count; - uint8_t *rx; - int rx_inc; -}; - -static struct ao_lpc_ssp_state ao_lpc_ssp_state[LPC_NUM_SPI]; - static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 }; -static inline void -ao_lpc_ssp_recv(struct lpc_ssp *lpc_ssp, struct ao_lpc_ssp_state *state) -{ - while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) && - state->rx_count) - { - /* RX ready, read a byte */ - *state->rx = lpc_ssp->dr; - state->rx += state->rx_inc; - state->rx_count--; - } -} - -static void -ao_lpc_ssp_isr(struct lpc_ssp *lpc_ssp, struct ao_lpc_ssp_state *state) -{ - ao_lpc_ssp_recv(lpc_ssp, state); - while ((lpc_ssp->sr & (1 << LPC_SSP_SR_TNF)) && - state->tx_count) - { - /* TX ready, write a byte */ - lpc_ssp->dr = *state->tx; - state->tx += state->tx_inc; - state->tx_count--; - ao_lpc_ssp_recv(lpc_ssp, state); - } - if (!state->rx_count) { - lpc_ssp->imsc &= ~(1 << LPC_SSP_IMSC_TXIM); - ao_wakeup(state); - } -} - -void -lpc_ssp0_isr(void) -{ - ao_lpc_ssp_isr(&lpc_ssp0, &ao_lpc_ssp_state[0]); -} - -void -lpc_ssp1_isr(void) -{ - ao_lpc_ssp_isr(&lpc_ssp1, &ao_lpc_ssp_state[1]); -} - -static void -ao_spi_run(struct lpc_ssp *lpc_ssp, struct ao_lpc_ssp_state *state) -{ - ao_arch_block_interrupts(); - lpc_ssp->imsc = (1 << LPC_SSP_IMSC_TXIM); - while (state->rx_count) - ao_sleep(state); - ao_arch_release_interrupts(); -} - -static uint8_t ao_spi_tx_dummy = 0xff; -static uint8_t ao_spi_rx_dummy; +#define spi_loop(len, put, get) do { \ + while (len--) { \ + /* send a byte */ \ + lpc_ssp->dr = put; \ + /* wait for the received byte to appear */ \ + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_RNE)) == 0) \ + ; \ + /* receive a byte */ \ + get lpc_ssp->dr; \ + } \ + /* Wait for the SSP to go idle (it already should be) */ \ + while (lpc_ssp->sr & (1 << LPC_SSP_SR_BSY)); \ + } while (0) void ao_spi_send(const void *block, uint16_t len, uint8_t id) { struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; - struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - - state->tx_count = state->rx_count = len; - state->tx = block; - state->tx_inc = 1; - state->rx = &ao_spi_rx_dummy; - state->rx_inc = 0; - ao_spi_run(lpc_ssp, state); + const uint8_t *o = block; + + spi_loop(len, *o++, (void)); } void ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t id) { struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; - struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - - state->tx_count = state->rx_count = len; - state->tx = &value; - state->tx_inc = 0; - state->rx = &ao_spi_rx_dummy; - state->rx_inc = 0; - ao_spi_run(lpc_ssp, state); + + spi_loop(len, value, (void)); } void ao_spi_recv(void *block, uint16_t len, uint8_t id) { struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; - struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - - state->tx_count = state->rx_count = len; - state->tx = &ao_spi_tx_dummy; - state->tx_inc = 0; - state->rx = block; - state->rx_inc = 1; - ao_spi_run(lpc_ssp, state); + uint8_t *i = block; + + spi_loop(len, 0xff, *i++ =); } void ao_spi_duplex(const void *out, void *in, uint16_t len, uint8_t id) { struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; - struct ao_lpc_ssp_state *state = &ao_lpc_ssp_state[id]; - - state->tx_count = state->rx_count = len; - state->tx = out; - state->tx_inc = 1; - state->rx = in; - state->rx_inc = 1; - ao_spi_run(lpc_ssp, state); + const uint8_t *o = out; + uint8_t *i = in; + + spi_loop(len, *o++, *i++ =); } void @@ -223,10 +149,6 @@ ao_spi_init(void) lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); ao_spi_channel_init(0); - - /* Configure NVIC */ - lpc_nvic_set_enable(LPC_ISR_SSP0_POS); - lpc_nvic_set_priority(LPC_ISR_SSP0_POS, 0); #endif #if HAS_SPI_1 @@ -277,10 +199,5 @@ ao_spi_init(void) lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); ao_spi_channel_init(1); - - /* Configure NVIC */ - lpc_nvic_set_enable(LPC_ISR_SSP1_POS); - lpc_nvic_set_priority(LPC_ISR_SSP1_POS, 0); - #endif /* HAS_SPI_1 */ } -- cgit v1.2.3 From 211cb482e4da04dc032432abc236ef8b5a5e732f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Feb 2015 01:30:21 -0800 Subject: altos: Separate out ao_tracker force from dbg Allow enabling telemetry when USB is connected without also enabling the motion debugging output. Signed-off-by: Keith Packard --- src/kernel/ao_tracker.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/kernel/ao_tracker.c b/src/kernel/ao_tracker.c index 9b007af8..962f145d 100644 --- a/src/kernel/ao_tracker.c +++ b/src/kernel/ao_tracker.c @@ -132,7 +132,7 @@ ao_tracker(void) if (height < 0) height = -height; - if (ao_tracker_force_telem) + if (ao_tracker_force_telem > 1) printf("head %d ring %d ground_distance %d height %d\n", gps_head, ring, ground_distance, height); if (ground_distance > ao_config.tracker_motion || height > (ao_config.tracker_motion << 1)) @@ -141,7 +141,7 @@ ao_tracker(void) break; } } - if (ao_tracker_force_telem) { + if (ao_tracker_force_telem > 1) { printf ("moving %d started %d\n", moving, log_started); flush(); } @@ -191,11 +191,9 @@ static struct ao_task ao_tracker_task; static void ao_tracker_set_telem(void) { - uint8_t telem; ao_cmd_hex(); - telem = ao_cmd_lex_i; if (ao_cmd_status == ao_cmd_success) - ao_tracker_force_telem = telem; + ao_tracker_force_telem = ao_cmd_lex_i; ao_cmd_status = ao_cmd_success; printf ("flight: %d\n", ao_flight_number); printf ("force_telem: %d\n", ao_tracker_force_telem); @@ -211,7 +209,7 @@ ao_tracker_set_telem(void) } static const struct ao_cmds ao_tracker_cmds[] = { - { ao_tracker_set_telem, "t \0Set telem on USB" }, + { ao_tracker_set_telem, "t \0Set telem on USB (0 off, 1 on, 2 dbg)" }, { 0, NULL }, }; -- cgit v1.2.3 From 0d08c427188f7b748d9ea7651143bc843e9c2691 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Feb 2015 13:09:18 -0800 Subject: altos: ao_packet_getchar needs to return 'int' so AO_READ_AGAIN works With ao_packet_getchar returning 'char', AO_READ_AGAIN would get converted to 0xff instead of -1 on return, making ao_packet_echo either produce a bogus character on output, breaking command responses, or wedge and never exit when the link was dropped. Signed-off-by: Keith Packard --- src/drivers/ao_packet_master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 23545049..42a4f5bf 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -17,7 +17,7 @@ #include "ao.h" -static char +static int ao_packet_getchar(void) { int c; -- cgit v1.2.3