/** * \callgraph * \brief This is the callback function that pstorage calls back to when a Flash event has completed for the block handle * a request was made for. The callback function is set in ladybug_flash_init() in the pstorage_param.cb parameter * \sa ladybug_flash_init() * @param handle * @param op_code * @param result * @param p_data * @param data_len */ void ladybug_flash_handler(pstorage_handle_t * handle, uint8_t op_code, uint32_t result, uint8_t * p_data, uint32_t data_len) { SEGGER_RTT_WriteString(0,"---> in flash_handler\n"); //check if there is an error. If so, the code will go to the error handler APP_ERROR_CHECK(result); //now that the error has been checked, set the waiting flag to "off" since //this is a way to let the code that made the flash action request that the //request is finished. //since i am using only one block, i don't need to associate with a block id... m_mypstorage_wait_flag = 0; //for testing purposes, see what op code was being handled... switch (op_code) { case PSTORAGE_LOAD_OP_CODE: SEGGER_RTT_WriteString(0,".... READ flash\n"); break; case PSTORAGE_STORE_OP_CODE: SEGGER_RTT_WriteString(0,".... WRITE flash\n"); break; case PSTORAGE_UPDATE_OP_CODE: SEGGER_RTT_WriteString(0,".... UPDATE flash\n"); break; case PSTORAGE_CLEAR_OP_CODE: SEGGER_RTT_WriteString(0,".... CLEAR flash\n"); break; default: break; } }
/**@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. * \note I decided to use the SEGGER_RTT printing functionality. My understanding is the SEGGER_RTT calls can be left in code with no effect * when there is no terminal to output. The con of this approach is I can't hook up a UART enabled terminal session and see what is going on without the debugger present. * * @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 app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name) { // This call can be used for debug purposes during application development. // The SEGGER_RTT APIs will not cause a problem in production so I'm leaving them in. SEGGER_RTT_WriteString(0,"--->>>BUMMER!! In app_error_handler\n"); SEGGER_RTT_printf(0,"error code: %d (or 0X%X if assert..base for BLE = 0x3000) Line number: %d file name: ",error_code,error_code,line_num); SEGGER_RTT_WriteString(0,p_file_name); SEGGER_RTT_WriteString(0,"\n"); // ble_debug_assert_handler(error_code, line_num, p_file_name); }
/** * \callgraph * \brief This is a helper function to easily print out the hex value of each byte within an array of bytes * @param dest_bytes the array of bytes to print out. * @param num_bytes the number of bytes in the array. */ void display_bytes(uint8_t *dest_bytes,int num_bytes){ SEGGER_RTT_WriteString(0,"****BYTES****\n"); for (int i = 0; i < num_bytes; i++) { if (i > 0) SEGGER_RTT_WriteString(0,":"); SEGGER_RTT_printf(0,"%02X",*dest_bytes); dest_bytes++; } SEGGER_RTT_WriteString(0,"\n"); }
/** * \brief I think of main as providing initialization and BLE event handling. One of the event handlers is used by the LBL's service and is defined * in the service_init() function. service_init() calls into the LBL's BLE service's initialization code which identifies the UUIDs of the LBL service. * \note Call service_init BEFORE advertising_init() * The BLE event dispatcher (ble_evt_dispatch()) calls the LBL's BLE event dispatcher. Communications with a client is through the client read/writing to characteristics. * \note I assume the power_manage() function does a "good job" interacting with the SoftDevice stack to minimize the amount of power used up by the LBL. I don't know how to fine tune * power management at this time. I use examples from the nRF51 SDK as a crutch, assuming the code for most of main functionality is "cookie cutter" across examples and the Nordic engineers that * write the examples realizes example code would be copy/pasted into our stuff. * @return while main is defined as an int, nothing is really returned. */ int main(void) { //call flash_init() before initializing service.. the ble_lbl_service uses flash to access pH4 and 7 calibration info.... (wow - too many dependencies!) //initialize pstorage() - the way i'll read/write from flash. POR is to use flash to store the calibration info for pH 4 and pH 7.. //Note in the S110 Softdevice documentation for pstorage, there is a note: // For implementation of interface included in the example, SoftDevice should be enabled and scheduler (if used) should be initialized prior to initializing this module. // ladybug_flash_init(); //a good part of this is "cookie cutter" from the nRF51 SDK...my-o-my there is a lot of code for BLE (within SoftDevice) and once SoftDevice is initialized - unfortunately - there is no longer source code debugging. ble_stack_init(); // The app timers rely on the BLE stack being initialized. This means app timer initialization must happen after BLE initialization. timers_init(); // (pstorage api access to) flash and the app timer used within the read/write flash functions require BLE and timers init first. ladybug_flash_init(); // The device name is needed as a GAP parameter. This is the first time a flash action (flash read) happens which means BLE and app timer init must happen first. char *p_deviceName; ladybug_get_device_name(&p_deviceName); SEGGER_RTT_printf(0,"Device name: %s \n",p_deviceName); SEGGER_RTT_printf(0,"String length: %d\n",strlen(p_deviceName)); gap_params_init(p_deviceName); //call service_init() before calling advertising_init()...service_init() calls into the LBL's BLE initialization code (where the LBL peripheral service and characteristics are defined) service_init(); advertising_init(); conn_params_init(); sec_params_init(); advertising_start(); // Enter main loop for (;;) { //Lazy write of values stored in flash //writing can get messed up if it is done inline with other BLE/sensing activity, and there is no rush. storeCalibrationValues_t *p_storeCalibrationValues; if (true == ladybug_there_are_calibration_values_to_write(&p_storeCalibrationValues)){ SEGGER_RTT_printf(0,"Writing calibration values to flash. Number of bytes: %d\n",sizeof(storeCalibrationValues_t)); ladybug_flash_write(calibrationValues,(uint8_t *)p_storeCalibrationValues,sizeof(storeCalibrationValues_t),did_flash_write); } storePlantInfo_t *p_storePlantInfo; if (true == ladybug_there_are_plantInfo_values_to_write(&p_storePlantInfo)){ SEGGER_RTT_WriteString(0,"...Writing plantInfo values to flash\n"); ladybug_flash_write(plantInfo,(uint8_t *)p_storePlantInfo,sizeof(storePlantInfo_t),did_flash_write); } char *p_deviceName; if (true == ladybug_the_device_name_has_been_updated(&p_deviceName)){ SEGGER_RTT_WriteString(0,"Writing device name to flash\n"); ladybug_flash_write(deviceName,(uint8_t *)p_deviceName,DEVNAME_MAX_LEN,did_flash_write); } power_manage(); } }
/*** * The Ladybug stores info that is maintained across restarts of the device. This info includes the device name, plant info (type of plant and growth stage), as well as * calibration values. This function figures out what block handle has been initialized based on what info has been requested to read, reads the info from flash, then writes * the info to the p_bytes_to_read memory buffer. * @param data_to_read let the function know what type of data to read * @param p_bytes_to_read give the function a buffer to write the data after reading from flash * @sa LADYBUG_ERROR_UNSURE_WHAT_DATA_TO_READ */ void ladybug_flash_read(flash_rw_t data_to_read,uint8_t *p_bytes_to_read,void(*did_flash_action)(uint32_t err_code)){ SEGGER_RTT_WriteString(0,"==> IN ladybug_flash_read\n"); pstorage_handle_t * p_handle; m_flash_return = did_flash_action; //set the block handle to the block of flash set aside in flash_init for the data type to read //point the bytes to the location holding the bytes in memory. switch (data_to_read) { case plantInfo: p_handle = &m_block_plantInfo_store_handle; break; case calibrationValues: p_handle = &m_block_calibration_store_handle; break; case deviceName: p_handle = &m_block_device_name_store_handle; break; default: //this is an error case. The function doesn't know what to read. APP_ERROR_CHECK(LADYBUG_ERROR_FLASH_UNSURE_WHAT_DATA_TO_READ); break; } // There is a chance the Flash activity doesn't happen so we use a timer to prevent waiting forever. m_mypstorage_wait_flag = 1; start_timer(); uint32_t err_code = pstorage_load(p_bytes_to_read, p_handle, BLOCK_SIZE, 0); while(m_mypstorage_wait_flag) { } APP_ERROR_CHECK(err_code); // Flash activity completed so stop timer. stop_timer(); }
/** * \callgraph *\brief Initialize the blocks of flash memory used for reading/writing. *\details Uses Nordic's pstorage software abstraction/API to cleanly access flash when the SoftDevice (for BLE) * is also running. */ void ladybug_flash_init() { SEGGER_RTT_WriteString(0,"==> IN ladybug_flash_init\n"); pstorage_module_param_t pstorage_param; //Used when registering with pstorage pstorage_handle_t handle; //used to access the chunk-o-flash requested when registering //First thing is to initialize pstorage uint32_t err_code = pstorage_init(); //if initialization was not successful, the error routine will be called and the code won't proceed. APP_ERROR_CHECK(err_code); //Next is to register amount of flash needed. The smallest amount that can be requested is 16 bytes. I'm requesting //32 bytes because this is the number of bytes needed for plant_info. Two blocks are used...one for plant info and one for hydro values. I must make a //block request for the larger amount of bytes pstorage_param.block_size = BLOCK_SIZE; //request three blocks - one will be for pH, one for plant_info, and one for device name pstorage_param.block_count = 3; //assign a callback so know when a command has finished. pstorage_param.cb = ladybug_flash_handler; err_code = pstorage_register(&pstorage_param, &handle); APP_ERROR_CHECK(err_code); //Then get the handles to the blocks of flash pstorage_block_identifier_get(&handle, 0, &m_block_calibration_store_handle); pstorage_block_identifier_get(&handle,1,&m_block_plantInfo_store_handle); pstorage_block_identifier_get(&handle,2,&m_block_device_name_store_handle); // Create the timer. This will be called before a Flash activity is requested to avoid forever hanging. create_timer(); }
/**@brief Function for application main entry. */ int main(void) { SEGGER_RTT_WriteString(0, "\033[2JTutorial Start.\n\n"); uint32_t err_code; bool erase_bonds; // Initialize. timers_init(); buttons_leds_init(&erase_bonds); ble_stack_init(); device_manager_init(erase_bonds); gap_params_init(); services_init(); advertising_init(); conn_params_init(); // Start execution. application_timers_start(); err_code = ble_advertising_start(BLE_ADV_MODE_FAST); APP_ERROR_CHECK(err_code); // Enter main loop. for (;;) { power_manage(); } }
static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length) { SEGGER_RTT_WriteString(0, "received data \n"); newData = true; memset(txt_data,0,sizeof(txt_data)); for (uint32_t i = 0; i < length; i++) { //m_tx_data[i] = p_data[i]; txt_data[i] = p_data[i]; SEGGER_RTT_printf(0,"%c", p_data[i]); while(app_uart_put(p_data[i]) != NRF_SUCCESS); } SEGGER_RTT_printf(0, "to send: %s\n", txt_data); SEGGER_RTT_WriteString(0, "\n"); while(app_uart_put('\n') != NRF_SUCCESS); }
/**@brief Function for application main entry. */ int main(void) { uint32_t err_code; bool erase_bonds; app_trace_init(); // Initialize. timers_init(); buttons_leds_init(&erase_bonds); ble_stack_init(); device_manager_init(erase_bonds); gap_params_init(); advertising_init(); services_init(); conn_params_init(); // Start execution. application_timers_start(); APPL_LOG("Start Advertising \r\n"); printf("Dhavaltest\r\n"); SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n"); err_code = ble_advertising_start(BLE_ADV_MODE_FAST); APP_ERROR_CHECK(err_code); // Enter main loop. for (;;) { power_manage(); } }
/** * \callgraph * \brief call back from Ladybug_Flash.c to let us know if the flash write was successful (or not) * @param err_code 0 if successful */ void did_flash_write(uint32_t err_code) { if (err_code == 0) { SEGGER_RTT_WriteString(0,"...Flash write SUCCESS!"); } else { APP_ERROR_HANDLER(err_code); } }
/** * \callgraph * \brief Called by the system when the timer goes off. If the timer goes off, this means the Flash activity didn't complete. The caller * is notified by calling the caller's callback with an error code. * @param p_context */ static void timeout_handler(void * p_context) { SEGGER_RTT_WriteString (0, "--> in timeout handler\n"); // UNUSED_PARAMETER(p_context); // Call back the caller with an error uint32_t err_code = LADYBUG_ERROR_FLASH_ACTION_NOT_COMPLETED; m_flash_return(err_code); }
/**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler. * * @details This function is called from the scheduler in the main loop after a BLE stack * event has been received. * * @param[in] p_ble_evt Bluetooth stack event. */ static void ble_evt_dispatch(ble_evt_t * p_ble_evt) { SEGGER_RTT_WriteString(0,"\n--> IN ble_evt_dispatch\n"); SEGGER_RTT_printf(0,"connection handle: %d\n",p_ble_evt->evt.gap_evt.conn_handle); on_ble_evt(p_ble_evt); ble_conn_params_on_ble_evt(p_ble_evt); ladybug_BLE_on_ble_evt(&m_lbl, p_ble_evt); }
/********************************************************************* * * main */ void main(void) { SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n"); SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); do { r = SEGGER_RTT_WaitKey(); SEGGER_RTT_Write(0, &r, 1); r++; } while (1); }
/** * \callgraph * \brief Start the timer before calling into pstorage asking for a flash event. */ void start_timer() { SEGGER_RTT_WriteString (0, "--> in start_timer\n"); uint32_t err_code; static const uint32_t wait_time_for_flash_event_to_complete_ms = 5000; ///< Wait 5 seconds before timing out from waiting for a flash event to complete static const uint32_t app_timer_prescaler = 0; ///< Counter overflows after 512s when prescaler = 0 uint32_t timer_ticks = APP_TIMER_TICKS(wait_time_for_flash_event_to_complete_ms, app_timer_prescaler); // Start application timers. err_code = app_timer_start(m_timer_id, timer_ticks, NULL); APP_ERROR_CHECK(err_code); }
/**@brief Update the game, given a location to place the disc */ void addToColumn(uint8_t col) { uint8_t currColor = p1_turn ? RED : BLUE, row; if(discs[col] < HEIGHT) { //insert the disc row = discs[col]; discs[col]++; game[row][col] = currColor; char temp_[24]; sprintf(temp_, "\nDisc added at %d, %d\n", col, row); SEGGER_RTT_WriteString(0, temp_); //Send data to Bluetooth connection char temp[14]; uint8_t send[14]; sprintf(temp, "Received %d %d", col, row); uint8_t i = 0; while(temp[i] != '\0') { //Accounts for 1 or 2 digit numbers send[i] = temp[i]; i++; } uint32_t err_code = ble_nus_string_send(&m_nus, send, i); if(err_code != NRF_SUCCESS) APP_ERROR_CHECK(err_code); //check if game is over if(checkWin(row, col)) { switch(p1_turn) { case true: SEGGER_RTT_WriteString(0, "Player 1 Wins!\n"); break; default: SEGGER_RTT_WriteString(0, "Player 2 Wins!\n"); break; } } p1_turn = !p1_turn; } else SEGGER_RTT_WriteString(0, "\nNo more moves may be made on this column\n"); }
/**@brief Function for initializing the game variables during startup or reset */ void game_init(void) { memset(discs, 0, sizeof discs); memset(p1_home, 0, sizeof p1_home); p1_home[0] = RED; memset(game, 0, sizeof(game[0][0]) * WIDTH * HEIGHT); p1_disc_col = 0; p1_turn = true; //Print instructions SEGGER_RTT_WriteString(0, "\nConnect Four BLE instructions:\n a - Move disc left\n d - Move disc right\n s - Insert disc\n h - back to first slot\n R or C - Reset game\n"); }
/**@snippet [Handling the data received over BLE] */ static void nus_data_handler(ble_nus_t * p_nus, uint8_t * p_data, uint16_t length) { //Copy uint8_t array to string array then use sscanf char temp[length+1]; for(int i = 0; i < length; i++) temp[i] = p_data[i]; temp[length] = '\0'; //Parse row number unsigned int num; sscanf(temp, "%u", &num); SEGGER_RTT_printf(0, "\nPlayer 2 dropped disc at column %u\n", num); //Check player status and input if(p1_turn) SEGGER_RTT_WriteString(0, "But it's not their turn yet!\n"); else if(num < 0 || num >= WIDTH) SEGGER_RTT_WriteString(0, "That's not a valid column!\n"); else addToColumn(num); }
/**@brief Function for responding to keyboard input. SEGGER_RTT_GetKey does not block and will return a negative value if there is no input. Checks if a bluetooth device is connected and if it is the player's turn before proceeding with the down key press. */ void moveDisc(int8_t whichInput) { //Respond to keystroke switch(whichInput) { case LEFT: if(p1_disc_col > 0) { p1_home[p1_disc_col--] = 0; p1_home[p1_disc_col] = RED; } break; case RIGHT: if(p1_disc_col < WIDTH-1) { p1_home[p1_disc_col++] = 0; p1_home[p1_disc_col] = RED; } break; case HOME: if(p1_disc_col != 0) { p1_home[p1_disc_col] = 0; p1_disc_col = 0; p1_home[p1_disc_col] = RED; } break; case DOWN: //Update discs then game array if(!isConnected) SEGGER_RTT_WriteString(0, "\nNot connected with another player yet!\n"); else if(!p1_turn) SEGGER_RTT_WriteString(0, "\nUnable to place disc, not your turn yet!\n"); else addToColumn(p1_disc_col); break; case RESET: case CLEAR: SEGGER_RTT_WriteString(0, "\nResetting game\n"); game_init(); break; default: ; } }
/**@brief Function for the Application's S110 SoftDevice event handler. * * @param[in] p_ble_evt S110 SoftDevice event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: SEGGER_RTT_WriteString(0, "CONNECTED\n"); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; case BLE_GAP_EVT_DISCONNECTED: SEGGER_RTT_WriteString(0, "DISCONNECTED\n"); err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); m_conn_handle = BLE_CONN_HANDLE_INVALID; break; case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); APP_ERROR_CHECK(err_code); break; case BLE_GATTS_EVT_SYS_ATTR_MISSING: // No system attributes have been stored. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); APP_ERROR_CHECK(err_code); break; default: SEGGER_RTT_WriteString(0, "BLE IDLE...\n"); // No implementation needed. break; } }
/** * \callgraph * \brief When the Ladybug needs to store info, it calls the flash_write routine. * \details This routine assumes the flash storage to be used has been initialized by a call to flash_init. Match the handle to * flash storage to the info the caller wants to write. * \note As directed by the nRF51822 documentation, the flash storage is first cleared before a write to flash happens. * @param what_data_to_write Whether to write out plant info, calibration values, or the device name. * @param p_bytes_to_write A pointer to the bytes to be written to flash. * @param num_bytes_to_write The number of bytes to write to flash * @param did_flash_action Function caller passes in to be informed of the outcome of the Flash request. The pointer to the function must be valid. */ void ladybug_flash_write(flash_rw_t what_data_to_write, uint8_t *p_bytes_to_write,pstorage_size_t num_bytes_to_write,void(*did_flash_action)(uint32_t err_code)){ SEGGER_RTT_WriteString(0,"==> IN ladybug_flash_write\n"); // Check parameters. The what_data_to_write param is checked below in the switch statement. if (p_bytes_to_write == NULL || (did_flash_action == NULL)){ APP_ERROR_HANDLER(LADYBUG_ERROR_NULL_POINTER); } if (num_bytes_to_write <= 0){ APP_ERROR_HANDLER(LADYBUG_ERROR_NUM_BYTES_TO_WRITE); } // Set the static variable used to hold the location of the callback function to the pointer passed in by the caller. m_flash_return = did_flash_action; // Must clear the Flash block before write (or get unpredictable results). pstorage_handle_t *p_handle; switch (what_data_to_write) { case plantInfo: p_handle = &m_block_plantInfo_store_handle; break; case calibrationValues: p_handle = &m_block_calibration_store_handle; break; case deviceName: p_handle = &m_block_device_name_store_handle; break; default: APP_ERROR_HANDLER(LADYBUG_ERROR_INVALID_COMMAND); break; } //clearing the pstorage/flash sets the bytes to 0xFF // m_mypstorage_wait_flag is set to 0 within ladybug_flash_handler(). This way the system lets us know the Flash activity happened. m_mypstorage_wait_flag = 1; // There is a chance the Flash activity doesn't happen so we use a timer to prevent waiting forever. start_timer(); uint32_t err_code = pstorage_clear(p_handle, BLOCK_SIZE); while(m_mypstorage_wait_flag) { } APP_ERROR_CHECK(err_code); // The flash action happened, so turn off the timer before it goes off. stop_timer(); // Start the timer up again to timeout if writing to flash doesn't happen start_timer(); m_mypstorage_wait_flag = 1; err_code = pstorage_store(p_handle, p_bytes_to_write, num_bytes_to_write, 0); while(m_mypstorage_wait_flag) { } APP_ERROR_CHECK(err_code); stop_timer(); }
/********************************************************************* * * SEGGER_RTT_TerminalOut * * Function description * Writes a string to the given terminal * without changing the terminal for channel 0. * */ int32_t SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { char ac[2]; int32_t r; ac[0] = 0xFF; if (TerminalId < 10) { ac[1] = '0' + TerminalId; } else if (TerminalId < 16) { ac[1] = 'A' + (TerminalId - 0x0A); } else { return -1; // RTT only supports up to 16 virtual terminals. } SEGGER_RTT_Write(0, ac, 2); r = SEGGER_RTT_WriteString(0, s); if (TerminalId < 10) { ac[1] = '0' + _ActiveTerminal; } else if (TerminalId < 16) { ac[1] = 'A' + (_ActiveTerminal - 0x0A); } SEGGER_RTT_Write(0, ac, 2); return r; }
/********************************************************************* * * main */ void main(void) { int r; int CancelOp; do { _Cnt = 0; SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n"); SEGGER_RTT_WriteString(0, "Press <1> to continue in blocking mode (Application waits if necessary, no data lost)\r\n"); SEGGER_RTT_WriteString(0, "Press <2> to continue in non-blocking mode (Application does not wait, data lost if fifo full)\r\n"); do { r = SEGGER_RTT_WaitKey(); } while ((r != '1') && (r != '2')); if (r == '1') { SEGGER_RTT_WriteString(0, "\r\nSelected <1>. Configuring RTT and starting...\r\n"); SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); } else { SEGGER_RTT_WriteString(0, "\r\nSelected <2>. Configuring RTT and starting...\r\n"); SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_NO_BLOCK_SKIP); } CancelOp = 0; do { //for (_Delay = 0; _Delay < 10000; _Delay++); SEGGER_RTT_printf(0, "Count: %d. Press <Space> to get back to menu.\r\n", _Cnt++); r = SEGGER_RTT_HasKey(); if (r) { CancelOp = (SEGGER_RTT_GetKey() == ' ') ? 1 : 0; } // // Check if user selected to cancel the current operation // if (CancelOp) { SEGGER_RTT_WriteString(0, "Operation cancelled, going back to menu...\r\n"); break; } } while (1); SEGGER_RTT_GetKey(); SEGGER_RTT_WriteString(0, "\r\n"); } while (1); }
/********************************************************************* * * main */ void main(void) { SEGGER_RTT_ConfigUpBuffer(0, NULL, NULL, 0, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL); SEGGER_RTT_WriteString(0, "SEGGER Real-Time-Terminal Sample\r\n\r\n"); SEGGER_RTT_WriteString(0, "###### Testing SEGGER_printf() ######\r\n"); SEGGER_RTT_printf(0, "printf Test: %%c, 'S' : %c.\r\n", 'S'); SEGGER_RTT_printf(0, "printf Test: %%5c, 'E' : %5c.\r\n", 'E'); SEGGER_RTT_printf(0, "printf Test: %%-5c, 'G' : %-5c.\r\n", 'G'); SEGGER_RTT_printf(0, "printf Test: %%5.3c, 'G' : %-5c.\r\n", 'G'); SEGGER_RTT_printf(0, "printf Test: %%.3c, 'E' : %-5c.\r\n", 'E'); SEGGER_RTT_printf(0, "printf Test: %%c, 'R' : %c.\r\n", 'R'); SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\" : %s.\r\n", "RTT"); SEGGER_RTT_printf(0, "printf Test: %%s, \"RTT\\r\\nRocks.\" : %s.\r\n", "RTT\r\nRocks."); SEGGER_RTT_printf(0, "printf Test: %%u, 12345 : %u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%+u, 12345 : %+u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%.3u, 12345 : %.3u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%.6u, 12345 : %.6u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%6.3u, 12345 : %6.3u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%8.6u, 12345 : %8.6u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%08u, 12345 : %08u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%08.6u, 12345 : %08.6u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%0u, 12345 : %0u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%-.6u, 12345 : %-.6u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%-6.3u, 12345 : %-6.3u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%-8.6u, 12345 : %-8.6u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%-08u, 12345 : %-08u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%-08.6u, 12345 : %-08.6u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%-0u, 12345 : %-0u.\r\n", 12345); SEGGER_RTT_printf(0, "printf Test: %%u, -12345 : %u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%+u, -12345 : %+u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%.3u, -12345 : %.3u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%.6u, -12345 : %.6u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%6.3u, -12345 : %6.3u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%8.6u, -12345 : %8.6u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%08u, -12345 : %08u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%08.6u, -12345 : %08.6u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%0u, -12345 : %0u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-.6u, -12345 : %-.6u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-6.3u, -12345 : %-6.3u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-8.6u, -12345 : %-8.6u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-08u, -12345 : %-08u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-08.6u, -12345 : %-08.6u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-0u, -12345 : %-0u.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%d, -12345 : %d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%+d, -12345 : %+d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%.3d, -12345 : %.3d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%.6d, -12345 : %.6d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%6.3d, -12345 : %6.3d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%8.6d, -12345 : %8.6d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%08d, -12345 : %08d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%08.6d, -12345 : %08.6d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%0d, -12345 : %0d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-.6d, -12345 : %-.6d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-6.3d, -12345 : %-6.3d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-8.6d, -12345 : %-8.6d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-08d, -12345 : %-08d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-08.6d, -12345 : %-08.6d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%-0d, -12345 : %-0d.\r\n", -12345); SEGGER_RTT_printf(0, "printf Test: %%x, 0x1234ABC : %x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%+x, 0x1234ABC : %+x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%.3x, 0x1234ABC : %.3x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%.6x, 0x1234ABC : %.6x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%6.3x, 0x1234ABC : %6.3x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%8.6x, 0x1234ABC : %8.6x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%08x, 0x1234ABC : %08x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%08.6x, 0x1234ABC : %08.6x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%0x, 0x1234ABC : %0x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%-.6x, 0x1234ABC : %-.6x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%-6.3x, 0x1234ABC : %-6.3x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%-8.6x, 0x1234ABC : %-8.6x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%-08x, 0x1234ABC : %-08x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%-08.6x, 0x1234ABC : %-08.6x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%-0x, 0x1234ABC : %-0x.\r\n", 0x1234ABC); SEGGER_RTT_printf(0, "printf Test: %%p, &_Cnt : %p.\r\n", &_Cnt); SEGGER_RTT_WriteString(0, "###### SEGGER_printf() Tests done. ######\r\n"); do { _Cnt++; } while (1); }
/**@brief Function for the application's SoftDevice event handler. * * @param[in] p_ble_evt SoftDevice event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: isConnected = true; SEGGER_RTT_WriteString(0, "\nConnected to Bluetooth Device\n"); err_code = bsp_indication_set(BSP_INDICATE_CONNECTED); APP_ERROR_CHECK(err_code); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; // BLE_GAP_EVT_CONNECTED case BLE_GAP_EVT_DISCONNECTED: isConnected = false; SEGGER_RTT_WriteString(0, "\nDisconnected from Bluetooth Device\n"); err_code = bsp_indication_set(BSP_INDICATE_IDLE); APP_ERROR_CHECK(err_code); m_conn_handle = BLE_CONN_HANDLE_INVALID; break; // BLE_GAP_EVT_DISCONNECTED case BLE_GAP_EVT_SEC_PARAMS_REQUEST: // Pairing not supported err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); APP_ERROR_CHECK(err_code); break; // BLE_GAP_EVT_SEC_PARAMS_REQUEST case BLE_GATTS_EVT_SYS_ATTR_MISSING: // No system attributes have been stored. err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_SYS_ATTR_MISSING case BLE_GATTC_EVT_TIMEOUT: // Disconnect on GATT Client timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTC_EVT_TIMEOUT case BLE_GATTS_EVT_TIMEOUT: // Disconnect on GATT Server timeout event. err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_TIMEOUT case BLE_EVT_USER_MEM_REQUEST: err_code = sd_ble_user_mem_reply(p_ble_evt->evt.gattc_evt.conn_handle, NULL); APP_ERROR_CHECK(err_code); break; // BLE_EVT_USER_MEM_REQUEST case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: { ble_gatts_evt_rw_authorize_request_t req; ble_gatts_rw_authorize_reply_params_t auth_reply; req = p_ble_evt->evt.gatts_evt.params.authorize_request; if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID) { if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) || (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) { if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE; } else { auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ; } auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED; err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply); APP_ERROR_CHECK(err_code); } } } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST #if (NRF_SD_BLE_API_VERSION == 3) case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, NRF_BLE_MAX_MTU_SIZE); APP_ERROR_CHECK(err_code); break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST #endif default: // No implementation needed. break; } }
/** * \callgraph * \brief create a timer to be used before a call to write/read to flash in case the flash action doesn't happen it won't hang the system. */ void create_timer() { SEGGER_RTT_WriteString (0, "--> in create_timer\n"); uint32_t err_code = app_timer_create(&m_timer_id,APP_TIMER_MODE_SINGLE_SHOT, timeout_handler); APP_ERROR_CHECK(err_code); }
/**@brief Application main function. */ int main(void) { /* beginning of Initializing services for the Nordic Board */ uint32_t err_code; bool erase_bonds; //print start string to terminal uint8_t start_string[] = START_STRING; printf("%s",start_string); // Initialize timer. APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false); nrf_drv_gpiote_init(); uart_init(); //buttons_leds_init(&erase_bonds); ble_stack_init(); gap_params_init(); services_init(); advertising_init(); conn_params_init(); err_code = ble_advertising_start(BLE_ADV_MODE_FAST); APP_ERROR_CHECK(err_code); //More SPI Additions nrf_drv_spi_config_t const config = { #if (SPI0_ENABLED == 1) .sck_pin = SPIM0_SCK_PIN, .mosi_pin = SPIM0_MOSI_PIN, .miso_pin = SPIM0_MISO_PIN, .ss_pin = SPIM0_SS_PIN, #elif (SPI1_ENABLED == 1) .sck_pin = SPIM1_SCK_PIN, .mosi_pin = SPIM1_MOSI_PIN, .miso_pin = SPIM1_MISO_PIN, .ss_pin = SPIM1_SS_PIN, #elif (SPI2_ENABLED == 1) .sck_pin = SPIM2_SCK_PIN, .mosi_pin = SPIM2_MOSI_PIN, .miso_pin = SPIM2_MISO_PIN, .ss_pin = SPIM2_SS_PIN, #endif .irq_priority = APP_IRQ_PRIORITY_LOW, .orc = 0xCC, .frequency = NRF_DRV_SPI_FREQ_1M, .mode = NRF_DRV_SPI_MODE_0, .bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, }; ret_code_t err_code1 = nrf_drv_spi_init(&m_spi_master, &config, spi_master_event_handler); APP_ERROR_CHECK(err_code1); /* End of Initializing services for the Nordic Board Beginning of CC1101 initializing. */ CC1101_Init(); // Enter main loop. for (;;) { // //for setting in receive mode // RecvDataPacket(); SEGGER_RTT_WriteString(0,"RX data:"); for(uint32_t i = 0; i<8;i++){ SEGGER_RTT_printf(0,"%x",m_rx_data[i]); } SEGGER_RTT_WriteString(0,"\n"); // //for sending data that was recieved from the BTLE event // if(m_transfer_completed & newData) { m_transfer_completed = false; newData = false; SendDataPacket(txt_data, strlen((char *) txt_data) + 1);//Additional byte (5+1) is header byte nrf_delay_ms(1); } } } void CC1101_Init(void){ //sequence of SS pin on/off to indicate we are going to reset the system nrf_gpio_pin_clear(SPIM0_SS_PIN); nrf_delay_ms(1); nrf_gpio_pin_set(SPIM0_SS_PIN); nrf_delay_ms(1); nrf_gpio_pin_clear(SPIM0_SS_PIN); //strobe CC1101 reset uint8_t SRES = 0x30; SpiStrobe(SRES); nrf_delay_ms(5); //calibrate CC1101 CC1101_Calibrate(); nrf_delay_ms(1); }
/** * \callgraph * \brief Called to stop the timer from firing. */ void stop_timer() { SEGGER_RTT_WriteString (0, "--> in stop_timer\n"); uint32_t err_code = app_timer_stop(m_timer_id); APP_ERROR_CHECK(err_code); }
/**@brief Function for handling the Application's BLE Stack events. * * @param[in] p_ble_evt Bluetooth stack event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; static ble_gap_evt_auth_status_t m_auth_status; static ble_gap_master_id_t p_master_id; static ble_gap_sec_keyset_t keys_exchanged; SEGGER_RTT_WriteString(0,"\n--> IN on_ble_evt (a BLE event has come into main.c\n"); switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_CONNECTED\n"); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; break; case BLE_GAP_EVT_DISCONNECTED: SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_DISCONNECTED\n"); m_conn_handle = BLE_CONN_HANDLE_INVALID; advertising_start(); break; case BLE_GAP_EVT_SEC_PARAMS_REQUEST: SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_SEC_PARAMS_REQUEST\n"); err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, &m_sec_params,&keys_exchanged); APP_ERROR_CHECK(err_code); break; case BLE_GATTS_EVT_SYS_ATTR_MISSING: SEGGER_RTT_WriteString(0,"\n... BLE_GATTS_EVT_SYS_ATTR_MISSING\n"); err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0,BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS); APP_ERROR_CHECK(err_code); break; case BLE_GAP_EVT_AUTH_STATUS: SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_AUTH_STATUS\n"); m_auth_status = p_ble_evt->evt.gap_evt.params.auth_status; break; case BLE_GAP_EVT_SEC_INFO_REQUEST: //p_enc_info = keys_exchanged.keys_central.p_enc_key SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_SEC_INFO_REQUEST\n"); if (p_master_id.ediv == p_ble_evt->evt.gap_evt.params.sec_info_request.master_id.ediv) { err_code = sd_ble_gap_sec_info_reply(m_conn_handle, &keys_exchanged.keys_central.p_enc_key->enc_info, &keys_exchanged.keys_central.p_id_key->id_info, NULL); APP_ERROR_CHECK(err_code); p_master_id.ediv = p_ble_evt->evt.gap_evt.params.sec_info_request.master_id.ediv; } else { // No keys found for this device err_code = sd_ble_gap_sec_info_reply(m_conn_handle, NULL, NULL,NULL); APP_ERROR_CHECK(err_code); } break; case BLE_GAP_EVT_TIMEOUT: SEGGER_RTT_WriteString(0,"\n... BLE_GAP_EVT_TIMEOUT\n"); if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING) { // Go to system-off mode (this function will not return; wakeup will cause a reset) err_code = sd_power_system_off(); APP_ERROR_CHECK(err_code); } break; default: SEGGER_RTT_WriteString(0,"\n... Not handling a BLE event here.\n"); // No implementation needed. break; } }
/**@brief Function for starting advertising. * \callgraph */ void advertising_start(void) { SEGGER_RTT_WriteString(0,"--->>>advertising_start\n"); uint32_t err_code = ble_advertising_start(BLE_ADV_MODE_FAST); APP_ERROR_CHECK(err_code); }