Andriy Makukha
/
football_project_wo_output
football_project_wo_output
Fork of football_project by
Diff: main.cpp
- Revision:
- 76:6638d83939d5
- Parent:
- 75:1b357bee1839
- Child:
- 78:43a6b54f0372
--- a/main.cpp Sun Apr 03 08:56:32 2016 +0000 +++ b/main.cpp Wed Apr 27 08:36:40 2016 +0000 @@ -1,683 +1,54 @@ -/* - * TA test - * - * Updated for New TA Baseboard (rev Aug-Nov 2015.) - * - * TODO maybe have a mode where the serial port I/O can be swapped, - * such that what the nRF generates is sent out the serial port, - * and what comes in the serial port goes into the nRF. - * Maybe could use the now-unused CTS pin for that. - * - * Using - * rev 327 of BLE_API - * rev 102 of nRF51822 w/ modification--See below - * rev 97 of mbed lib - * corresponding to: - * rev 493 of mbed-src w/ modification to targets/hal/TARGET_NORDIC/TARGET_MCU_NRF51822/serial_api.c - * so things compile properly.* - * * Now using $Sub$$UART0_IRQHandler to override UART0_IRQHandler without needing to use lib source. - * - * *** Now using mbed-src again to modify startup code to use full 32k RAM on QFAC part 20160104 ALS - * while still using RBL BLE Nano as a target: - * Copied files nRF51822.sct and startup_nRF51822.s - * from targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_ARM_STD/TARGET_MCU_NORDIC_32K - * to targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/TOOLCHAIN_ARM_STD/TARGET_MCU_NORDIC_16K - * (Stomping the 16k settings w/ 32k settings.) - * - * Changed - * nRF51822/nordic/pstorage_platform.h PSTORAGE_MIN_BLOCK_SIZE changed from 0x010 to 4. - */ +#include <RFM69.h> +#include <SPI.h> -/* mbed Microcontroller Library - * Copyright (c) 2006-2013 ARM Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <cstdarg> -#include <cstdio> -#include "mbed.h" -// #include "rtos.h" -#include "BLEDevice.h" - -#include "DFUService.h" -#include "UARTService.h" -#include "DeviceInformationService.h" -#include "BatteryService.h" - -#include "MTSSerialFlowControl.h" -#include "PhoneAppIO.h" - -#include "types.h" -#include "TA.h" -#include "DataStore.hh" -// #include "Radio.hh" - -#define NEED_CONSOLE_OUTPUT 0 /* Set this if you need debug messages on the console; - * it will have an impact on code-size and power consumption. */ - -#define LOOPBACK_MODE 0 // Loopback mode - -// #if NEED_CONSOLE_OUTPUT -// #define DEBUG(...) { printf(__VA_ARGS__); } -// #else -// #define DEBUG(...) /* nothing */ -// #endif /* #if NEED_CONSOLE_OUTPUT */ - -void loop(); -void setup(); -void getRadioInput(char *ibuffer, int size); - -#define BLENANO 0 // BLE Nano vs. TA New Baseboard (rev Aug-Nov 2015.) - -#if BLENANO -#define SERTX USBTX -#define SERRX USBRX -#else // Same RTS pin used by all (P0_08) and unused CTS (P0_10) -#define SERTX P0_18 -#define SERRX P0_17 -#endif - -static Timer tmr; - -unsigned long millis() -{ - return tmr.read_ms(); -} - -unsigned long micros() -{ - return tmr.read_us(); -} +#define NODE_ID 1 // ID of the current node +#define SEND_TO_ID 2 // ID to send messages to -extern "C" -{ -#include "softdevice_handler.h" // Attempt to get pstorage enqueued cmd callbacks. -#include "app_timer.h" -#include "pstorage.h" - -// void My_UART0_IRQHandler(); - - void pin_mode( PinName, PinMode ); -} - -#if BLENANO -#define ADC_IN_BATT P0_6 -#define CHARGING_IN P0_29 -#else -#define ADC_IN_BATT P0_4 -#define CHARGING_IN P0_2 -#endif -AnalogIn batt( ADC_IN_BATT ); - -// DigitalOut rts( RTS_PIN_NUMBER ); -DigitalIn cts( CTS_PIN_NUMBER, PullDown ); // We'll use as a mode switch for serial data source. TODO +#define NETWORKID 101 //the same on all nodes that talk to each other -// Check if we should swap serial Rx/Tx for early rev of "Little Brain" -DigitalIn trSwp( P0_30, PullUp ); - -// Wait to settle. -int foo = (wait( 0.1 ), 0); - -// Not using "LED" or "LED1" because target NRF51822 for FOTA uses different pins. -static DigitalOut led0( P0_19, 1 ); // TA New Baseboard LED High=On ("STATUS") (OK on Nano: LED Low=On) -static DigitalOut led1( P0_21, 0 ); // TA New Baseboard High=On (OK on Nano: NC) -DigitalOut led2( P0_22, 1 ); // TA New Baseboard High=On (OK on Nano: NC) - -// DigitalOut led1( P0_3, 0 ); // TA Baseboard High=On (OK on Nano: Alt RxD) -// DigitalOut led1( (trSwp ? P0_4 : P0_3), 0 ); // TA Baseboard High=On (And don't use P0_4 on Nano) - -// DigitalOut buzz( P0_20, 1 ); // TA New Baseboard Low=On (OK on Nano: NC) - -int tickTock = 0; // Counter used by periodicCallback(). - -class ChgChg : public InterruptIn -{ - public: - ChgChg( PinName pin, PinMode pull=PullUp ) : InterruptIn( pin ) - { - mode( pull ); // Set pull mode - fall( this, &ChgChg::chargeStart ); // Attach ISR for fall - rise( this, &ChgChg::chargeStop ); // Attach ISR for rise +#define FREQUENCY RF69_915MHZ - led0 = !read(); - } - void chargeStart() - { - led0 = 1; - tickTock = 0; // Trigger batt level update. - } - void chargeStop() - { - led0 = 0; - tickTock = 0; // Trigger batt level update. - } -}; -ChgChg notcharge( CHARGING_IN, PullUp ); - - -// App timer, app scheduler, and pstorage are already setup by bootloader. - -static BLEDevice ble; - +Serial pc(USBTX, USBRX); -// Note: From the datasheet: -// PSELRXD, PSELRTS, PSELTRTS and PSELTXD must only be configured when the UART is disabled. -// But a version of serial_init() erroneously enabled the uart before the setting of those, -// which messed up flow control. Apparently the setting is ONCE per ON mode. ARGH! -// So we made our own versions of Serial and SerialBase (MySerial and MySerialBase) -// to not use serial_init() in serial_api.c, so flow control is setup correctly * -// MTSSerial now uses our MySerial instead of Serial, and now uses hw flow control by default * -// [* We can't change the uart interrupt vector, so we comment-out the handler in -// serial_api.c, and rebuild the mbed lib for low-level hw flow control to work.] - No need now. -// * Now using $Sub$$UART0_IRQHandler to override UART0_IRQHandler without needing to use lib source. -// NVIC_SetVector( UART0_IRQn, (uint32_t)My_UART0_IRQHandler ); // Might have worked--No need. -// -// MTSSerialFlowControl uses "manual" (non-hardware-low-level) flow control based on its -// internal buffer--Rx servicing usually is fast enough not to need hw flow control, so it's okay. -// -// mts::MTSSerialFlowControl pcfc( (trSwp ? SERRX : SERTX), (trSwp ? SERTX : SERRX), RTS_PIN_NUMBER, CTS_PIN_NUMBER, 384, 2688 ); -//mts::MTSSerial pcfc( (trSwp ? SERRX : SERTX), (trSwp ? SERTX : SERRX), 128, 64, RTS_PIN_NUMBER, NC ); // 256, 1280 // 256, 2560 - -uint8_t txPayload[TXRX_BUF_LEN +1] = { 0 }; - - -char deviceName[6]; // "TAF00"; -Gap::address_t macAddr; -Gap::addr_type_t *pAdType; -static const uint16_t uuid16_list[] = { GattService::UUID_DEVICE_INFORMATION_SERVICE, - GattService::UUID_BATTERY_SERVICE }; -static uint8_t batt_and_id[] = { GattService::UUID_BATTERY_SERVICE & 0xff, - GattService::UUID_BATTERY_SERVICE >> 8, - 99, // Batt level - 'T', 'X' }; // Custom ID trick - -UARTService *uartServicePtr; -PhoneAppIO *phoneP; -BatteryService *battServiceP; - -// Buffer for holding data from the phone -// to the device -static char phoneToDev[MAX_LEN] = {0}; +static RFM69 radio(P0_24,P0_23,P0_25,P0_28,P0_7); +static bool promiscuousMode = true; // set 'true' to sniff all packets on the same network -extern TA ta; - -//// extern void radio_init(); -extern void radio_loop(int mac); - -#ifdef MASTER -bool is_master = true; -#else -bool is_master = false; -#endif - -void setAdvData() -{ - ble.accumulateAdvertisingPayload( GapAdvertisingData::BREDR_NOT_SUPPORTED | - GapAdvertisingData::LE_GENERAL_DISCOVERABLE ); - ble.setAdvertisingType( GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED ); - - // Get MAC addr so we can create a device name using it. - ble.getAddress( pAdType, macAddr ); - - sprintf( deviceName, "%c%02X%02X", (is_master?'T':'S'), macAddr[1], macAddr[0] ); - - ble.accumulateAdvertisingPayload( GapAdvertisingData::COMPLETE_LOCAL_NAME, - (const uint8_t *)deviceName, strlen(deviceName) ); - -// Moved to scan response packet to give more room in AD packet... -// ble.accumulateAdvertisingPayload( GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, -// (const uint8_t *)UARTServiceUUID_reversed, sizeof(UARTServiceUUID_reversed) ); - - ble.accumulateAdvertisingPayload( GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, - (uint8_t *)uuid16_list, sizeof( uuid16_list ) ); - ble.accumulateAdvertisingPayload( GapAdvertisingData::SERVICE_DATA, - (uint8_t *)batt_and_id, sizeof( batt_and_id ) ); // Batt lev + "TX" - - ble.accumulateScanResponse( GapAdvertisingData::INCOMPLETE_LIST_128BIT_SERVICE_IDS, - (const uint8_t *)UARTServiceUUID_reversed, sizeof( UARTServiceUUID_reversed ) ); -} - -void updateBatt( uint8_t pct ) -{ - static uint8_t prev; - static bool wasCharging; - - if( notcharge ) - { - if( wasCharging ) ta.beep_off(); // Alarm Clock TMP TODO remove once hardware is fixed. - - if( pct > 100 ) pct = 100; - - if( wasCharging ) - { - pct = 102; // Show 102% at charger unplug. - tickTock = 50; // Cause another normal update in 5s (60 -50 = 10 half s). - - } else - { - // Use if we update quite often. -// if( abs( (int)prev -(int)pct ) < 3 ) return; // Don't register change of less than 3%. - } - - prev = pct; - wasCharging = false; - - } else // Charging - { - // Plugged-in seems to add ~23% to level, so checking for 99% is like 76% unplugged. - // But I had a failure with a smaller gap, so reduced another 8%. Also: Prevent alarm initially. - if( millis() > 5000 && /* pct < 100 && TMP to prevent alarm on disconnected battery */ - pct >= 90 /* 91 */ ) ta.beep( 15000 ); // Alarm Clock TMP TODO remove once hardware is fixed. - - if( !wasCharging ) - pct = 101; // Show 101% at start of charging. - wasCharging = true; // Force show when done charging. - } - - if( pct <= 15 /* 10 */ ) ta.batteryLow = true; - - batt_and_id[2] = pct; - ble.clearAdvertisingPayload(); - setAdvData(); - ble.setAdvertisingPayload(); - - if( NULL != battServiceP ) battServiceP->updateBatteryLevel( pct ); -} - -uint8_t getLastBattLevel() -{ - return batt_and_id[2]; -} - -bool isCharging() -{ - return !notcharge; -} - -#define BAT_TOP 793 // 3250 // 52000 -#define BAT_BOT 684 // 2800 // 44800 -uint8_t getBattLevel() +int main() { - int battI = (int)(batt * 1000.f); - // Normalize to usable range... - // Note: These levels should also give 0% if powered by programmer. - if( battI > BAT_TOP ) battI = BAT_TOP; // Fully charged reading ~3.85V - if( battI < BAT_BOT ) battI = BAT_BOT; // Device failing reading ~3.32V - battI-= BAT_BOT; - return (uint8_t)(battI*100 / (BAT_TOP-BAT_BOT)); -} - -// True when connected to a phone -bool connected = false; - -void connectionCallback( Gap::Handle_t, Gap::addr_type_t peerAddrType, - const Gap::address_t peerAddr, const Gap::ConnectionParams_t *connParams ) -{ - connected = true; - - // DEBUG( "Connected!\n\r" ); - -// char dummy; -// writeToPhone( "Hi. Curr stack bot: 0x%08X\r\n", &dummy ); -} - -void disconnectionCallback( Gap::Handle_t handle, Gap::DisconnectionReason_t reason ) -{ - connected = false; + unsigned long last_send = 0L; + char tx_buff[100] = {0}; + char rx_buff[100] = {0}; + + pc.baud(9600); + pc.printf("RFM69 test starting with ID: %d\r\n", NODE_ID); + + radio.initialize(FREQUENCY, NODE_ID, NETWORKID); + radio.encrypt(0); + radio.promiscuous(promiscuousMode); - updateBatt( getBattLevel() ); - - // DEBUG( "Disconnected!\n\r" ); - // DEBUG( "Restarting the advertising process\n\r" ); - ble.startAdvertising(); - - ta.post_color(0); -} - -bool updateCharacteristic( GattAttribute::Handle_t handle, const uint8_t *data, uint16_t bytesRead ) -{ - ble_error_t err = ble.updateCharacteristicValue( handle, data, bytesRead ); - - if( (err == BLE_ERROR_BUFFER_OVERFLOW) || - (err == BLE_ERROR_PARAM_OUT_OF_RANGE) ) - { - // pcfc.printf( "\r\nBLE %d! ", err ); - - } else if ( err == BLE_STACK_BUSY ) - { - // Common error when pumping data. - } - - return (err != BLE_ERROR_NONE); -} - -extern "C" void writeToPhone(char *format, ...) -{ - if( NULL == phoneP ) return; + Timer t; + t.start(); - va_list arg; - va_start( arg, format ); - - phoneP->vprintf( format, arg ); - // Also write same to serial port... TODO - // pcfc.vprintf( format, arg ); - - va_end(arg); -} - -// Byte bits to ASCII. -extern "C" void writeBitsToPhone( uint8_t byte, uint8_t minbits ) -{ - static char ascbits[9] = { 0 }; - int pos = 0; - if( 0 == minbits ) minbits = 1; - - uint16_t ibyt = byte & 0xFF; - bool leading0 = true; - - for( short b=7; b >= 0; b-- ) + while (true) { - ibyt<<=1; - if( ibyt & 0x100 ) + unsigned long current_time = t.read_ms(); + + if (current_time - last_send > 2000L) { - leading0 = false; - ascbits[pos++] = '1'; - - } else if( !leading0 || (b < minbits) ) - { - ascbits[pos++] = '0'; - } - } - ascbits[pos] = '\0'; - - writeToPhone( "%s", ascbits ); -} - -void onDataWritten( const GattCharacteristicWriteCBParams *params ) -{ - if( phoneP != NULL ) - { - uint16_t bytesRead = phoneP->maybeHandleRead( params ); // Also writes to txPayload + // Send message + snprintf(tx_buff, sizeof(tx_buff), "msg frm: %d at %lu", NODE_ID, current_time); + radio.send(SEND_TO_ID, tx_buff, strlen(tx_buff)); + last_send = current_time; + + pc.printf("Sent: %s\r\n", tx_buff); + } - if( 0 != bytesRead ) + if (radio.receiveDone()) { - /* - DEBUG( "received %u bytes\n\r", bytesRead ); - - // Also write to serial port... -// pcfc.printf( "From app: " ); - pcfc.write( (char *)txPayload, bytesRead ); -// pcfc.printf( "\r\n" ); - */ - - return; + memset(rx_buff, 0x00, sizeof(rx_buff)); + memcpy(rx_buff, (char*)radio.DATA, radio.DATALEN > sizeof(rx_buff)-1 ? sizeof(rx_buff)-1 : radio.DATALEN); + + pc.printf("Got: %s\r\n", rx_buff); } } -} - -void onDataSent( unsigned count ) -{ -} - -void toPhoneChk( void ) -{ - if( phoneP != NULL ) - { - /* - char ch; - // Get any data from serial port buffer--Full lines if avail--Last line after >= 20 chars. - for( int cnt=1; 0 != pcfc.atomicRead( ch ); cnt++ ) - { - /// For from-serial straight to-phone. - /// if( 0 > phoneP->putchar( ch ) ) - /// { - /// pcfc.printf( " * " ); - /// break; - /// } - - // For from-serial inject-to-dev as-if from phone. - phoneP->injectHandleRead( &ch, 1 ); - - if( (cnt >= 20) && ('\n' == ch) ) break; - } - */ - // Write to outgoing characteristic if anything is pending. - if( 0 != phoneP->maybeHandleWrite() ) - { - // pcfc.printf( "ToPhoneHandler \r\n" ); - } - } -} - -void periodicCallback( void ) -{ - static unsigned long prevMillis = millis() +125; - static int callCnt = 0; - - unsigned long elapsedMillis = millis() -prevMillis; - - if( elapsedMillis >= 125 ) - { - do - { - prevMillis = millis(); - -// if( is_master && ((callCnt % 3) == 0) ) writeToPhone( "Rnd: %x\r\n", rndHW() ); - - if( (callCnt % 4) != 0 ) break; - -#if BLENANO - led0 = !led0; -#endif - led1 = !led1; - led2 = !led2; -// rts = !rts; - - // Check battery level every 30s. - if( 0 == (tickTock % 60 ) ) updateBatt( getBattLevel() ); - - tickTock++; - - } while( false ); - - callCnt++; - } -} - -#define LOOPUS 1250 -#define LOOPMS (LOOPUS/1000) /* 2 */ /* 5 */ /* 25 */ - -int main( void ) -{ - init_datastore(); - - wait_us(400); - - //is_master = datastore_is_master(); - -// Ticker ticker; -//////ticker.attach( periodicCallback, 0.125 /** 0.2 **/ /** 0.5 **/ /* 1 */ ); - -/////pcfc.baud( 57600 ); - - ble.init(); - - ble.onConnection( connectionCallback ); - ble.onDisconnection( disconnectionCallback ); - ble.onDataWritten( onDataWritten ); - ble.onDataSent( onDataSent ); - - /* setup advertising */ - setAdvData(); - - /////pcfc.printf( "\r\nHello! I am \"%s\"\r\n", deviceName ); - - /* -#if LOOPBACK_MODE - pcfc.printf( "\r\nIn BLE Loopback mode.\r\n" ); -#endif - */ - - srnd( rndHW() ); // Seed the sw RNG w/ the hw. - - DeviceInformationService deviceInfo( ble, "TRX", "TrueAgility", "SN0001", "hw-rev1", "fw-rev1" ); - BatteryService battService( ble ); - battServiceP = &battService; - - updateBatt( getBattLevel() ); - - /* Enable over-the-air firmware updates. Instantiating DFUService introduces a - * control characteristic which can be used to trigger the application to - * handover control to a resident bootloader. */ - DFUService dfu( ble ); - - UARTService uartService( ble ); - uartServicePtr = &uartService; - - ble.setAdvertisingInterval( Gap::MSEC_TO_ADVERTISEMENT_DURATION_UNITS( is_master ? 132 : 132 ) ); - - ble.startAdvertising(); - - PhoneAppIO *phone = new PhoneAppIO( ble, - uartServicePtr->getRXCharacteristicHandle(), - uartServicePtr->getTXCharacteristicHandle() ); - - phone->loopbackMode = LOOPBACK_MODE; - phoneP = phone; - - setup(); -/// radio_init(); //// Moved back to TA::initialize() - tmr.start(); - - int mac_addr = ((int)macAddr[0]); - mac_addr |= ((int)macAddr[1] << 8); - - unsigned long lastMicros = micros(); - unsigned long lastMillis = millis(); - unsigned long currMicros = lastMicros +LOOPUS; - unsigned long currMillis = lastMillis +LOOPMS; - - //// Test stuff... - unsigned long countLoop = 0L; - unsigned long overage = 0L; - //// - -init_datastore(); - - // Main Loop - while( true ) // for( uint32_t loop=1; ;loop++ ) - { -// ble.waitForEvent(); - - currMicros = micros(); - currMillis = millis(); - - if( currMicros -lastMicros < LOOPUS ) - { - continue; - } - - //// Test stuff... - overage += ((currMicros -lastMicros) -LOOPUS); - countLoop++; - if( (countLoop * LOOPUS) >= 30000000 ) - { - if( Dbg ) writeToPhone( "Loop avg over: %.2fus\r", (float)overage / (float)countLoop ); - // writeToPhone( "RSSI: %d\r", get_rssi() ); -// read_all_regs(); - countLoop = 0L; - overage = 0L; - } - //// - - lastMicros = currMicros; - lastMillis = currMillis; - - periodicCallback(); - - toPhoneChk(); // Write any pending data to phone. - - if( is_master || Dbg || RDbg ) - { - int bytes = MIN( MAX_LEN, phoneP->readable() ); - getRadioInput( phoneToDev, phoneP->read( phoneToDev, bytes, 1 ) ); - } - - loop(); - radio_loop( mac_addr ); - } -} - -/**@brief Function for error handling, which is called when an error has occurred. - * - * @warning This handler is an example only and does not fit a final product. You need to analyze - * how your product is supposed to react in case of error. - * - * @param[in] error_code Error code supplied to the handler. - * @param[in] line_num Line number where the handler is called. - * @param[in] p_file_name Pointer to the file name. - */ -void $Sub$$app_error_handler( uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name ) -{ - // nrf_gpio_pin_set( ASSERT_LED_PIN_NO ); - //led1 = 1; - - // This call can be used for debug purposes during application development. - // @note CAUTION: Activating this code will write the stack to flash on an error. - // This function should NOT be used in a final product. - // It is intended STRICTLY for development/debugging purposes. - // The flash write will happen EVEN if the radio is active, thus interrupting - // any communication. - // Use with care. Uncomment the line below to use. - // ble_debug_assert_handler(error_code, line_num, p_file_name); - - // On assert, the system can only recover with a reset. - NVIC_SystemReset(); -} - -uint32_t rndHW() -{ - uint32_t rndVal; - uint8_t bytes_available; - for(;;) - { - sd_rand_application_bytes_available_get( &bytes_available ); - if( bytes_available >= 4 ) - { - if( NRF_SUCCESS == sd_rand_application_vector_get( (uint8_t *)&rndVal, 4 ) ) - break; - } - } - - return rndVal; -} - -static uint32_t rndZ = 0xCAFE, rndW = 0xF00D; -// Seed for rnd() -void srnd( uint32_t seed ) -{ - rndZ = 0xCAFE; - rndW = seed; -} - -// Simple RNG -- Allows cross-platform compat if we want to run -// an apples-to-apples freeform competition by using same seed. -uint32_t rnd() -{ - rndZ = 36969 * (rndZ & 0xffff) + (rndZ >>16); - rndW = 18000 * (rndW & 0xffff) + (rndW >>16); - - return ((rndZ <<16) + rndW); -} - -/* EOF */ +} \ No newline at end of file