void act_linearAct_Process(void) { if (Timer_Expired(act_linearAct_TIMER_report)) { linearAct_sendPosition(0); } #if (USE_STIMULI == 1) if (Timer_Expired(act_linearAct_TIMER_stimuli)) { gpio_toggle_pin(STIMULI); } #endif }
/** * @brief Writes data to a serial interface. * @param data1 : 1st buffer * @param data2 : 2nd buffer * @param n_bytes1: number of bytes in 1st buffer * @param n_bytes2: number of bytes in 2nd buffer * @retval None */ void Hal_Write_Serial(const void *data1, const void *data2, int32_t n_bytes1, int32_t n_bytes2) { struct timer t; Timer_Set(&t, CLOCK_SECOND / 10); #ifdef PRINT_CSV_FORMAT PRINT_CSV("00:00:00.000"); for (int i = 0; i < n_bytes1; i++) { PRINT_CSV(" %02x", ((uint8_t *) data1)[i]); } for (int i = 0; i < n_bytes2; i++) { PRINT_CSV(" %02x", ((uint8_t *) data2)[i]); } PRINT_CSV("\n"); #endif while (1) { if (BlueNRG_SPI_Write (&SpiHandle, (uint8_t *) data1, (uint8_t *) data2, n_bytes1, n_bytes2) == 0) break; if (Timer_Expired(&t)) { break; } } }
void tst_CoreLED_Process(void) { /// Stuff that needs doing is done here if (Timer_Expired(tst_CoreLED_Blink_TIMER)) { gpio_toggle_pin(tst_CoreLED_PIN); } }
/** * @brief Enable notification * @param None * @retval None */ void enableNotification(void) { uint8_t client_char_conf_data[] = {0x01, 0x00}; // Enable notifications struct timer t; Timer_Set(&t, CLOCK_SECOND*10); while(aci_gatt_write_charac_descriptor(connection_handle, tx_handle+2, 2, client_char_conf_data)==BLE_STATUS_NOT_ALLOWED){ /* Radio is busy */ if(Timer_Expired(&t)) break; } notification_enabled = TRUE; }
void act_output_Process(void) { #if act_output_USEEEPROM==1 if (Timer_Expired(act_output_STORE_VALUE_TIMEOUT)) { uint8_t index = 0; #ifdef act_output_CH0 eeprom_write_byte_crc(EEDATA.ch0, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH1 eeprom_write_byte_crc(EEDATA.ch1, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH2 eeprom_write_byte_crc(EEDATA.ch2, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH3 eeprom_write_byte_crc(EEDATA.ch3, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH4 eeprom_write_byte_crc(EEDATA.ch4, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH5 eeprom_write_byte_crc(EEDATA.ch5, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH6 eeprom_write_byte_crc(EEDATA.ch6, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH7 eeprom_write_byte_crc(EEDATA.ch7, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH8 eeprom_write_byte_crc(EEDATA.ch8, chnValue[index], WITHOUT_CRC); index++; #endif #ifdef act_output_CH9 eeprom_write_byte_crc(EEDATA.ch9, chnValue[index], WITHOUT_CRC); index++; #endif EEDATA_UPDATE_CRC; } #endif }
/* Enable notification */ static void enableNotification(void) { uint8_t client_char_conf_data[] = {0x01, 0x00}; // Enable notifications struct timer t; Timer_Set(&t, CLOCK_SECOND*10); while(aci_gatt_write_charac_descriptor(connection_handle, notify_read_handle+2, 2, client_char_conf_data)==BLE_STATUS_NOT_ALLOWED) { /* Radio is busy */ if(Timer_Expired(&t)) break; } host_notification_enabled = TRUE; HAL_Delay(100); ble_host_on_connect(); printf("notification enable\n\r"); }
void sns_rfid_Process(void) { uint8_t version; uint32_t id; if( 0 == rfid_fetch( &version, &id ) ) { if( !sns_rfid_got_card ) { sns_rfid_got_card = 1; sns_rfid_card.id = id; sns_rfid_card.version = version; // Card arrived sns_rfid_HandleCardEvent(1); } Timer_SetTimeout(sns_rfid_CARD_LEFT_TIMER, sns_rfid_CARD_LEFT_TIME, TimerTypeOneShot, 0); } if ( Timer_Expired(sns_rfid_CARD_LEFT_TIMER) ) { sns_rfid_got_card = 0; // Card left sns_rfid_HandleCardEvent(0); } }
void sns_counter_Process(void) { #if sns_counter_USEEEPROM==1 if (StoreInEEPROM == 1) { StoreInEEPROM = 0; eeprom_write_dword_crc(EEDATA32.Count[0], (uint32_t)(Count[0]), WITH_CRC); } #endif #ifdef sns_counter_SEND_TIMER if (Timer_Expired(sns_counter_SEND_TIMER)) { #ifdef sns_counter_CH0 sns_counter_send_counter(0); #endif #ifdef sns_counter_CH1 sns_counter_send_counter(1); #endif #ifdef sns_counter_CH2 sns_counter_send_counter(2); #endif #ifdef sns_counter_CH3 sns_counter_send_counter(3); #endif #ifdef sns_counter_CH4 sns_counter_send_counter(4); #endif #ifdef sns_counter_CH5 sns_counter_send_counter(5); #endif #ifdef sns_counter_CH6 sns_counter_send_counter(6); #endif #ifdef sns_counter_CH7 sns_counter_send_counter(7); #endif } #endif }
int hci_send_req(struct hci_request *r, BOOL async) { uint8_t *ptr; uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); hci_event_pckt *event_pckt; hci_uart_pckt *hci_hdr; int to = DEFAULT_TIMEOUT; struct timer t; tHciDataPacket * hciReadPacket = NULL; tListNode hciTempQueue; list_init_head(&hciTempQueue); hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam); if(async){ goto done; } /* Minimum timeout is 1. */ if(to == 0) to = 1; Timer_Set(&t, to); while(1) { evt_cmd_complete *cc; evt_cmd_status *cs; evt_le_meta_event *me; int len; #if ENABLE_MICRO_SLEEP while(1){ ATOMIC_SECTION_BEGIN(); if(Timer_Expired(&t)){ ATOMIC_SECTION_END(); goto failed; } if(!HCI_Queue_Empty()){ ATOMIC_SECTION_END(); break; } Enter_Sleep_Mode(); ATOMIC_SECTION_END(); } #else while(1){ if(Timer_Expired(&t)){ goto failed; } if(!HCI_Queue_Empty()){ break; } } #endif /* Extract packet from HCI event queue. */ Disable_SPI_IRQ(); list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket); hci_hdr = (void *)hciReadPacket->dataBuff; if(hci_hdr->type != HCI_EVENT_PKT){ list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); // See comment below Enable_SPI_IRQ(); continue; } event_pckt = (void *) (hci_hdr->data); ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE); len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE); switch (event_pckt->evt) { case EVT_CMD_STATUS: cs = (void *) ptr; if (cs->opcode != opcode) goto failed; if (r->event != EVT_CMD_STATUS) { if (cs->status) { goto failed; } break; } r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_CMD_COMPLETE: cc = (void *) ptr; if (cc->opcode != opcode) goto failed; ptr += EVT_CMD_COMPLETE_SIZE; len -= EVT_CMD_COMPLETE_SIZE; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_LE_META_EVENT: me = (void *) ptr; if (me->subevent != r->event) break; len -= 1; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, me->data, r->rlen); goto done; case EVT_HARDWARE_ERROR: goto failed; default: break; } /* In the meantime there could be other events from the controller. In this case, insert the packet in a different queue. These packets will be inserted back in the main queue just before exiting from send_req(). */ list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); /* Be sure there is at list one packet in the pool to process the expected event. */ if(list_is_empty(&hciReadPktPool)){ pListNode tmp_node; list_remove_head(&hciReadPktRxQueue, &tmp_node); list_insert_tail(&hciReadPktPool, tmp_node); } Enable_SPI_IRQ(); } failed: move_list(&hciReadPktRxQueue, &hciTempQueue); Enable_SPI_IRQ(); return -1; done: // Insert the packet back into the pool. list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); move_list(&hciReadPktRxQueue, &hciTempQueue); Enable_SPI_IRQ(); return 0; }
void sns_flower_Process(void) { static uint8_t measureState=0; static uint16_t results[6]; static uint16_t resultsInv[6]; uint16_t temp; static uint8_t flowerChannelToSend = 0; if (Timer_Expired(sns_flower_WAIT_TIMER)) { gpio_set_out(sns_flower_highSide_PIN); gpio_set_out(sns_flower_lowSide_PIN); gpio_set_pin(sns_flower_highSide_PIN); gpio_clr_pin(sns_flower_lowSide_PIN); measureState=0; Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_MEASUREMENT_PERIOD_MS , TimerTypeOneShot, 0); } if (Timer_Expired(sns_flower_MEASUREMENT_TIMER)) { StdCan_Msg_t txMsg; StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS); StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER); txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_VOLTAGECURRENT; txMsg.Header.ModuleId = sns_flower_ID; txMsg.Length = 3; switch (measureState) { case 0: #ifdef sns_flower0AD results[0] = ADC_Get(sns_flower0AD); #endif #ifdef sns_flower1AD results[1] = ADC_Get(sns_flower1AD); #endif #ifdef sns_flower2AD results[2] = ADC_Get(sns_flower2AD); #endif #ifdef sns_flower3AD results[3] = ADC_Get(sns_flower3AD); #endif #ifdef sns_flower4AD results[4] = ADC_Get(sns_flower4AD); #endif #ifdef sns_flower5AD results[5] = ADC_Get(sns_flower5AD); #endif gpio_clr_pin(sns_flower_highSide_PIN); gpio_set_pin(sns_flower_lowSide_PIN); measureState=1; Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_MEASUREMENT_PERIOD_MS , TimerTypeOneShot, 0); break; case 1: #ifdef sns_flower0AD resultsInv[0] = 1023-ADC_Get(sns_flower0AD); #endif #ifdef sns_flower1AD resultsInv[1] = 1023-ADC_Get(sns_flower1AD); #endif #ifdef sns_flower2AD resultsInv[2] = 1023-ADC_Get(sns_flower2AD); #endif #ifdef sns_flower3AD resultsInv[3] = 1023-ADC_Get(sns_flower3AD); #endif #ifdef sns_flower4AD resultsInv[4] = 1023-ADC_Get(sns_flower4AD); #endif #ifdef sns_flower5AD resultsInv[5] = 1023-ADC_Get(sns_flower5AD); #endif gpio_clr_pin(sns_flower_highSide_PIN); gpio_clr_pin(sns_flower_lowSide_PIN); gpio_set_in(sns_flower_highSide_PIN); gpio_set_in(sns_flower_lowSide_PIN); measureState=2; flowerChannelToSend=0; Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_MEASUREMENT_PERIOD_MS , TimerTypeOneShot, 0); break; case 2: switch(flowerChannelToSend) { case 0: #ifdef sns_flower0AD txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT; txMsg.Data[0] = 0; temp = (uint16_t)((float)(results[0]+resultsInv[0])*4.888); txMsg.Data[1] = (temp>>8)&0xff; txMsg.Data[2] = (temp)&0xff; while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {} flowerChannelToSend = 1; # if !(defined(sns_flower1AD) || defined(sns_flower2AD) || defined(sns_flower3AD) || defined(sns_flower4AD) || defined(sns_flower5AD)) flowerChannelToSend = 0; measureState=0; # endif break; #endif case 1: #ifdef sns_flower1AD txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT; txMsg.Data[0] = 1; temp = (uint16_t)((float)(results[1]+resultsInv[1])*4.888); txMsg.Data[1] = (temp>>8)&0xff; txMsg.Data[2] = (temp)&0xff; while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {} flowerChannelToSend = 2; # if !(defined(sns_flower2AD) || defined(sns_flower3AD) || defined(sns_flower4AD) || defined(sns_flower5AD)) flowerChannelToSend = 0; measureState=0; # endif break; #endif case 2: #ifdef sns_flower2AD txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT; txMsg.Data[0] = 2; temp = (uint16_t)((float)(results[2]+resultsInv[2])*4.888); txMsg.Data[1] = (temp>>8)&0xff; txMsg.Data[2] = (temp)&0xff; while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {} flowerChannelToSend = 3; #if !(defined(sns_flower3AD) || defined(sns_flower4AD) || defined(sns_flower5AD)) flowerChannelToSend = 0; measureState=0; #endif break; #endif case 3: #ifdef sns_flower3AD txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT; txMsg.Data[0] = 3; temp = (uint16_t)((float)(results[3]+resultsInv[3])*4.888); txMsg.Data[1] = (temp>>8)&0xff; txMsg.Data[2] = (temp)&0xff; while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {} flowerChannelToSend = 4; #if !( defined(sns_flower4AD) || defined(sns_flower5AD)) flowerChannelToSend = 0; measureState=0; #endif break; #endif case 4: #ifdef sns_flower4AD txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT; txMsg.Data[0] = 4; temp = (uint16_t)((float)(results[4]+resultsInv[4])*4.888); txMsg.Data[1] = (temp>>8)&0xff; txMsg.Data[2] = (temp)&0xff; while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {} flowerChannelToSend = 5; #if !(defined(sns_flower5AD)) flowerChannelToSend = 0; measureState=0; #endif break; #endif case 5: #ifdef sns_flower5AD txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PERCENT; txMsg.Data[0] = 5; temp = (uint16_t)((float)(results[5]+resultsInv[5])*4.888); txMsg.Data[1] = (temp>>8)&0xff; txMsg.Data[2] = (temp)&0xff; while (StdCan_Put(&txMsg) != StdCan_Ret_OK) {} flowerChannelToSend = 0; measureState=0; break; #endif default: measureState=0; break; } if (measureState != 0) { Timer_SetTimeout(sns_flower_MEASUREMENT_TIMER, sns_flower_CAN_MSG_PAUS_MS , TimerTypeOneShot, 0); } break; } } }
void sns_irTransmit_Process(void) { if (sns_irTransmit_state == sns_irTransmit_STATE_IDLE) { } else if (sns_irTransmit_state == sns_irTransmit_STATE_START_TRANSMIT) { if (expandProtocol(sns_irTransmit_txbuffer, &sns_irTransmit_length, &sns_irTransmit_proto) == IR_OK) { if (IrTransceiver_Transmit(sns_irTransmit_txbuffer, sns_irTransmit_length, sns_irTransmit_proto.modfreq) == IR_OK) { sns_irTransmit_state = sns_irTransmit_STATE_TRANSMITTING; } else { sns_irTransmit_state = sns_irTransmit_STATE_IDLE; } } else { sns_irTransmit_state = sns_irTransmit_STATE_IDLE; } } else if (sns_irTransmit_state == sns_irTransmit_STATE_TRANSMITTING){ //polla om den är klar, om klar gå till sns_irTransmit_STATE_START_PAUSE if (IrTransceiver_Transmit_Poll() != IR_NOT_FINISHED) { sns_irTransmit_state = sns_irTransmit_STATE_START_PAUSE; } } else if (sns_irTransmit_state == sns_irTransmit_STATE_START_PAUSE) { if (sns_irTransmit_repeatCount < sns_irTransmit_proto.repeats) { sns_irTransmit_repeatCount++; } Timer_SetTimeout(sns_irTransmit_REPEAT_TIMER, sns_irTransmit_proto.timeout, TimerTypeOneShot, 0); if (sns_irTransmit_proto.framecnt != 255) { sns_irTransmit_proto.framecnt++; } sns_irTransmit_state = sns_irTransmit_STATE_PAUSING; } else if (sns_irTransmit_state == sns_irTransmit_STATE_PAUSING) { //när timeout har gått (timebase) så gå till sns_irTransmit_STATE_START_TRANSMIT if (Timer_Expired(sns_irTransmit_REPEAT_TIMER)) { sns_irTransmit_state = sns_irTransmit_STATE_START_TRANSMIT; } if (sns_irTransmit_stop == 1 && sns_irTransmit_repeatCount >= sns_irTransmit_proto.repeats) { sns_irTransmit_state = sns_irTransmit_STATE_STOP; } } else if (sns_irTransmit_state == sns_irTransmit_STATE_STOP) { sns_irTransmit_stop = 0; sns_irTransmit_proto.timeout = 0; sns_irTransmit_proto.framecnt = 0; sns_irTransmit_repeatCount = 0; sns_irTransmit_state = sns_irTransmit_STATE_IDLE; } }
int main( void ) { // Enable interrupts as early as possible sei(); Timer_Init(); // Set as outputs and stop rotor DDRD |= (1 << PD1)|(1 << PD2); PORTD &= ~((1 << PD1)|(1 << PD2)); // Setup ADC initAdcFeedback(); Can_Message_t txMsg; txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID); txMsg.DataLength = 4; txMsg.RemoteFlag = 0; txMsg.ExtendedFlag = 1; txMsg.Data.words[0] = APP_TYPE; txMsg.Data.words[1] = APP_VERSION; // Set up callback for CAN reception BIOS_CanCallback = &can_receive; // Send CAN_NMT_APP_START BIOS_CanSend(&txMsg); // Read calibration value from eeprom azimuthCalibration = eeprom_read_word( CALIBRATE_AZIMUTH ); // Timer for reading position feedback Timer_SetTimeout(0, 100, TimerTypeFreeRunning, 0); Timer_SetTimeout(1, 1000, TimerTypeFreeRunning, 0); sendStatus( STATUS ); while (1) { if (Timer_Expired(0)) { // Periodicly read antennas position readFeedback(); } if (Timer_Expired(1)) { sendStatus(STATUS); } if (rxMsgFull) { switch (rxMsg.Id){ case MSG_CAL_SET: // Set calibration value if( 2 == rxMsg.DataLength ){ calibration( SET, rxMsg.Data.words[0] ); } break; case MSG_CAL_GET: // Get calibration value if( 0 == rxMsg.DataLength ){ txMsg.Id = MSG_CAL_RET; txMsg.DataLength = 2; txMsg.Data.words[0] = calibration( GET, 0 ); BIOS_CanSend(&txMsg); } break; case MSG_ABS: // Start turning to absolute position if( 2 == rxMsg.DataLength ){ } break; case MSG_REL: // Start turning to relative position if( 2 == rxMsg.DataLength ){ } break; case MSG_START: // Start turning if( 1 == rxMsg.DataLength ){ // First data byte decides direction controlRelay( rxMsg.Data.bytes[0] ); } break; case MSG_STOP: // Stop turning //if( 1 == rxMsg.DataLength ){ controlRelay( ROTATE_STOP ); //} break; case MSG_STATUS: // Get position if( 0 == rxMsg.DataLength ){ sendStatus(STATUS); } break; default: break; } rxMsgFull = 0; // } } return 0; }
void act_protectedOutput_Process() { #if act_protectedOutput_EEPROM_ENABLED == 1 if (Timer_Expired(act_protectedOutput_STORE_VALUE_TIMEOUT)) { #if act_protectedOutput_CH_COUNT >= 1 eeprom_write_byte_crc(EEDATA.ch0, chTargetState[0], WITHOUT_CRC); #endif #if act_protectedOutput_CH_COUNT >= 2 eeprom_write_byte_crc(EEDATA.ch1, chTargetState[1], WITHOUT_CRC); #endif #if act_protectedOutput_CH_COUNT >= 3 eeprom_write_byte_crc(EEDATA.ch2, chTargetState[2], WITHOUT_CRC); #endif #if act_protectedOutput_CH_COUNT >= 4 eeprom_write_byte_crc(EEDATA.ch3, chTargetState[3], WITHOUT_CRC); #endif EEDATA_UPDATE_CRC; } #endif // shall we retry to set target output state? if (Timer_Expired(act_protectedOutput_RETRY_TIMER)) { // read DIAG pin again and update outputs accordingly readDiagPin(); #if act_protectedOutput_FORCED_RETRIES == 1 // forced retry to set output states, regardless of DIAG updateOutput(1); // read DIAG pin again and hope we have a better flag readDiagPin(); #else // if DIAG allows it, retry to set the output states updateOutput(0); #endif if (diagState == DIAG_ASSERTED) { // if DIAG was still asserted, initiate another timer run Timer_SetTimeout(act_protectedOutput_RETRY_TIMER, act_protectedOutput_RETRY_TIMER_TIME_S*1000, TimerTypeOneShot, 0); } else { // things went back to normal. report this diagReportPending = 1; } } // shall we report diag status to CAN? if (diagReportPending) { StdCan_Msg_t txMsg; StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_SNS); StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER); txMsg.Header.ModuleType = CAN_MODULE_TYPE_SNS_PROTECTEDOUTPUT; txMsg.Header.ModuleId = act_protectedOutput_ID; txMsg.Header.Command = CAN_MODULE_CMD_PHYSICAL_PINSTATUS; txMsg.Length = 2; txMsg.Data[0] = 0; //TODO: add support for more channels // we follow the standard SNS_INPUT format, but the data corresponds to the "health" rather than physical level if (diagState == DIAG_NORMAL) { txMsg.Data[1] = 1; //healthy, target output state stable } else { txMsg.Data[1] = 0; //not healthy, DIAG pin ASSERTED, not in target output state } while (StdCan_Put(&txMsg) != StdCan_Ret_OK); diagReportPending = 0; } }
/* 'to' is timeout in system clock ticks. */ int hci_send_req(struct hci_request *r) { uint8_t *ptr; uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); hci_event_pckt *event_pckt; hci_uart_pckt *hci_hdr; int try; int to = DEFAULT_TIMEOUT; new_packet = FALSE; hci_set_packet_complete_callback(new_hci_event); if (hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam) < 0) goto failed; try = 10; while (try--) { evt_cmd_complete *cc; evt_cmd_status *cs; evt_le_meta_event *me; int len; /* Minimum timeout is 1. */ if(to == 0) to = 1; if (to > 0) { struct timer t; Timer_Set(&t, to); while(1){ if(Timer_Expired(&t)){ goto failed; } if(new_packet){ break; } } } hci_hdr = (void *)hci_buffer; if(hci_hdr->type != HCI_EVENT_PKT){ new_packet = FALSE; Enable_SPI_IRQ(); continue; } event_pckt = (void *) (hci_hdr->data); ptr = hci_buffer + (1 + HCI_EVENT_HDR_SIZE); len = hci_pckt_len - (1 + HCI_EVENT_HDR_SIZE); switch (event_pckt->evt) { case EVT_CMD_STATUS: cs = (void *) ptr; if (cs->opcode != opcode) break; if (r->event != EVT_CMD_STATUS) { if (cs->status) { goto failed; } break; } r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_CMD_COMPLETE: cc = (void *) ptr; if (cc->opcode != opcode) break; ptr += EVT_CMD_COMPLETE_SIZE; len -= EVT_CMD_COMPLETE_SIZE; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_LE_META_EVENT: me = (void *) ptr; if (me->subevent != r->event) break; len -= 1; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, me->data, r->rlen); goto done; case EVT_HARDWARE_ERROR: goto failed; default: break; // In the meantime there could be other events from the controller. } new_packet = FALSE; Enable_SPI_IRQ(); } failed: hci_set_packet_complete_callback(NULL); Enable_SPI_IRQ(); return -1; done: hci_set_packet_complete_callback(NULL); Enable_SPI_IRQ(); return 0; } int hci_reset() { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_RESET; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_disconnect(uint16_t handle, uint8_t reason) { struct hci_request rq; disconnect_cp cp; uint8_t status; cp.handle = handle; cp.reason = reason; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LINK_CTL; rq.ocf = OCF_DISCONNECT; rq.cparam = &cp; rq.clen = DISCONNECT_CP_SIZE; rq.event = EVT_CMD_STATUS; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_le_read_local_version(uint8_t *hci_version, uint16_t *hci_revision, uint8_t *lmp_pal_version, uint16_t *manufacturer_name, uint16_t *lmp_pal_subversion) { struct hci_request rq; read_local_version_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_INFO_PARAM; rq.ocf = OCF_READ_LOCAL_VERSION; rq.cparam = NULL; rq.clen = 0; rq.rparam = &resp; rq.rlen = READ_LOCAL_VERSION_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return -1; } *hci_version = resp.hci_version; *hci_revision = btohs(resp.hci_revision); *lmp_pal_version = resp.lmp_pal_version; *manufacturer_name = btohs(resp.manufacturer_name); *lmp_pal_subversion = btohs(resp.lmp_pal_subversion); return 0; } int hci_le_read_buffer_size(uint16_t *pkt_len, uint8_t *max_pkt) { struct hci_request rq; le_read_buffer_size_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_READ_BUFFER_SIZE; rq.cparam = NULL; rq.clen = 0; rq.rparam = &resp; rq.rlen = LE_READ_BUFFER_SIZE_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return -1; } *pkt_len = resp.pkt_len; *max_pkt = resp.max_pkt; return 0; } int hci_le_set_advertising_parameters(uint16_t min_interval, uint16_t max_interval, uint8_t advtype, uint8_t own_bdaddr_type, uint8_t direct_bdaddr_type, tBDAddr direct_bdaddr, uint8_t chan_map, uint8_t filter) { struct hci_request rq; le_set_adv_parameters_cp adv_cp; uint8_t status; Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); adv_cp.min_interval = min_interval; adv_cp.max_interval = max_interval; adv_cp.advtype = advtype; adv_cp.own_bdaddr_type = own_bdaddr_type; adv_cp.direct_bdaddr_type = direct_bdaddr_type; Osal_MemCpy(adv_cp.direct_bdaddr,direct_bdaddr,sizeof(adv_cp.direct_bdaddr)); adv_cp.chan_map = chan_map; adv_cp.filter = filter; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADV_PARAMETERS; rq.cparam = &adv_cp; rq.clen = LE_SET_ADV_PARAMETERS_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_le_set_advertising_data(uint8_t length, const uint8_t data[]) { struct hci_request rq; le_set_adv_data_cp adv_cp; uint8_t status; Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); adv_cp.length = length; Osal_MemCpy(adv_cp.data, data, MIN(31,length)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADV_DATA; rq.cparam = &adv_cp; rq.clen = LE_SET_ADV_DATA_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_le_set_advertise_enable(uint8_t enable) { struct hci_request rq; le_set_advertise_enable_cp adv_cp; uint8_t status; Osal_MemSet(&adv_cp, 0, sizeof(adv_cp)); adv_cp.enable = enable?1:0; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_ADVERTISE_ENABLE; rq.cparam = &adv_cp; rq.clen = LE_SET_ADVERTISE_ENABLE_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_le_rand(uint8_t random_number[8]) { struct hci_request rq; le_rand_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_RAND; rq.cparam = NULL; rq.clen = 0; rq.rparam = &resp; rq.rlen = LE_RAND_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return -1; } Osal_MemCpy(random_number, resp.random, 8); return 0; } int hci_le_set_scan_resp_data(uint8_t length, const uint8_t data[]) { struct hci_request rq; le_set_scan_response_data_cp scan_resp_cp; uint8_t status; Osal_MemSet(&scan_resp_cp, 0, sizeof(scan_resp_cp)); scan_resp_cp.length = length; Osal_MemCpy(scan_resp_cp.data, data, MIN(31,length)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_SCAN_RESPONSE_DATA; rq.cparam = &scan_resp_cp; rq.clen = LE_SET_SCAN_RESPONSE_DATA_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_le_read_advertising_channel_tx_power(int8_t *tx_power_level) { struct hci_request rq; le_read_adv_channel_tx_power_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_READ_ADV_CHANNEL_TX_POWER; rq.cparam = NULL; rq.clen = 0; rq.rparam = &resp; rq.rlen = LE_RAND_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return -1; } *tx_power_level = resp.level; return 0; } int hci_le_set_random_address(tBDAddr bdaddr) { struct hci_request rq; le_set_random_address_cp set_rand_addr_cp; uint8_t status; Osal_MemSet(&set_rand_addr_cp, 0, sizeof(set_rand_addr_cp)); Osal_MemCpy(set_rand_addr_cp.bdaddr, bdaddr, sizeof(tBDAddr)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_SET_RANDOM_ADDRESS; rq.cparam = &set_rand_addr_cp; rq.clen = LE_SET_RANDOM_ADDRESS_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_read_bd_addr(tBDAddr bdaddr) { struct hci_request rq; read_bd_addr_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_INFO_PARAM; rq.ocf = OCF_READ_BD_ADDR; rq.cparam = NULL; rq.clen = 0; rq.rparam = &resp; rq.rlen = READ_BD_ADDR_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return -1; } Osal_MemCpy(bdaddr, resp.bdaddr, sizeof(tBDAddr)); return 0; } int hci_le_create_connection(uint16_t interval, uint16_t window, uint8_t initiator_filter, uint8_t peer_bdaddr_type, const tBDAddr peer_bdaddr, uint8_t own_bdaddr_type, uint16_t min_interval, uint16_t max_interval, uint16_t latency, uint16_t supervision_timeout, uint16_t min_ce_length, uint16_t max_ce_length) { struct hci_request rq; le_create_connection_cp create_cp; uint8_t status; Osal_MemSet(&create_cp, 0, sizeof(create_cp)); create_cp.interval = interval; create_cp.window = window; create_cp.initiator_filter = initiator_filter; create_cp.peer_bdaddr_type = peer_bdaddr_type; Osal_MemCpy(create_cp.peer_bdaddr, peer_bdaddr, sizeof(tBDAddr)); create_cp.own_bdaddr_type = own_bdaddr_type; create_cp.min_interval=min_interval; create_cp.max_interval=max_interval; create_cp.latency = latency; create_cp.supervision_timeout=supervision_timeout; create_cp.min_ce_length=min_ce_length; create_cp.max_ce_length=max_ce_length; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_CREATE_CONN; rq.cparam = &create_cp; rq.clen = LE_CREATE_CONN_CP_SIZE; rq.event = EVT_CMD_STATUS; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0) return -1; if (status) { return -1; } return 0; } int hci_le_encrypt(uint8_t key[16], uint8_t plaintextData[16], uint8_t encryptedData[16]) { struct hci_request rq; le_encrypt_cp params; le_encrypt_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemCpy(params.key, key, 16); Osal_MemCpy(params.plaintext, plaintextData, 16); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_ENCRYPT; rq.cparam = ¶ms; rq.clen = LE_ENCRYPT_CP_SIZE; rq.rparam = &resp; rq.rlen = LE_ENCRYPT_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } Osal_MemCpy(encryptedData, resp.encdata, 16); return 0; } int hci_le_ltk_request_reply(uint8_t key[16]) { struct hci_request rq; le_ltk_reply_cp params; le_ltk_reply_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); params.handle = 1; Osal_MemCpy(params.key, key, 16); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_LTK_REPLY; rq.cparam = ¶ms; rq.clen = LE_LTK_REPLY_CP_SIZE; rq.rparam = &resp; rq.rlen = LE_LTK_REPLY_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return -1; } return 0; } int hci_le_ltk_request_neg_reply() { struct hci_request rq; le_ltk_neg_reply_cp params; le_ltk_neg_reply_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); params.handle = 1; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_LTK_NEG_REPLY; rq.cparam = ¶ms; rq.clen = LE_LTK_NEG_REPLY_CP_SIZE; rq.rparam = &resp; rq.rlen = LE_LTK_NEG_REPLY_RP_SIZE; if (hci_send_req(&rq) < 0) return -1; if (resp.status) { return -1; } return 0; } int hci_le_read_white_list_size(uint8_t *size) { struct hci_request rq; le_read_white_list_size_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_READ_WHITE_LIST_SIZE; rq.rparam = &resp; rq.rlen = LE_READ_WHITE_LIST_SIZE_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } *size = resp.size; return 0; } int hci_le_clear_white_list() { struct hci_request rq; uint8_t status; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_CLEAR_WHITE_LIST; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0){ return -1; } if (status) { return -1; } return 0; } int hci_le_add_device_to_white_list(uint8_t bdaddr_type, tBDAddr bdaddr) { struct hci_request rq; le_add_device_to_white_list_cp params; uint8_t status; params.bdaddr_type = bdaddr_type; Osal_MemCpy(params.bdaddr, bdaddr, 6); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_ADD_DEVICE_TO_WHITE_LIST; rq.cparam = ¶ms; rq.clen = LE_ADD_DEVICE_TO_WHITE_LIST_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0){ return -1; } if (status) { return -1; } return 0; } int hci_le_remove_device_from_white_list(uint8_t bdaddr_type, tBDAddr bdaddr) { struct hci_request rq; le_remove_device_from_white_list_cp params; uint8_t status; params.bdaddr_type = bdaddr_type; Osal_MemCpy(params.bdaddr, bdaddr, 6); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_REMOVE_DEVICE_FROM_WHITE_LIST; rq.cparam = ¶ms; rq.clen = LE_REMOVE_DEVICE_FROM_WHITE_LIST_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0){ return -1; } if (status) { return -1; } return 0; } int hci_read_transmit_power_level(uint16_t *conn_handle, uint8_t type, int8_t * tx_level) { struct hci_request rq; read_transmit_power_level_cp params; read_transmit_power_level_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); params.handle = *conn_handle; params.type = type; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_HOST_CTL; rq.ocf = OCF_READ_TRANSMIT_POWER_LEVEL; rq.cparam = ¶ms; rq.clen = READ_TRANSMIT_POWER_LEVEL_CP_SIZE; rq.rparam = &resp; rq.rlen = READ_TRANSMIT_POWER_LEVEL_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } *conn_handle = resp.handle; *tx_level = resp.handle; return 0; } int hci_read_rssi(uint16_t *conn_handle, int8_t * rssi) { struct hci_request rq; read_rssi_cp params; read_rssi_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); params.handle = *conn_handle; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_STATUS_PARAM; rq.ocf = OCF_READ_RSSI; rq.cparam = ¶ms; rq.clen = READ_RSSI_CP_SIZE; rq.rparam = &resp; rq.rlen = READ_RSSI_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } *conn_handle = resp.handle; *rssi = resp.rssi; return 0; } int hci_le_read_local_supported_features(uint8_t *features) { struct hci_request rq; le_read_local_supported_features_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_READ_LOCAL_SUPPORTED_FEATURES; rq.rparam = &resp; rq.rlen = LE_READ_LOCAL_SUPPORTED_FEATURES_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } Osal_MemCpy(features, resp.features, sizeof(resp.features)); return 0; } int hci_le_read_channel_map(uint16_t conn_handle, uint8_t ch_map[5]) { struct hci_request rq; le_read_channel_map_cp params; le_read_channel_map_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); params.handle = conn_handle; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_READ_CHANNEL_MAP; rq.cparam = ¶ms; rq.clen = LE_READ_CHANNEL_MAP_CP_SIZE; rq.rparam = &resp; rq.rlen = LE_READ_CHANNEL_MAP_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } Osal_MemCpy(ch_map, resp.map, 5); return 0; } int hci_le_read_supported_states(uint8_t states[8]) { struct hci_request rq; le_read_supported_states_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_READ_SUPPORTED_STATES; rq.rparam = &resp; rq.rlen = LE_READ_SUPPORTED_STATES_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } Osal_MemCpy(states, resp.states, 8); return 0; } int hci_le_receiver_test(uint8_t frequency) { struct hci_request rq; le_receiver_test_cp params; uint8_t status; params.frequency = frequency; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_RECEIVER_TEST; rq.cparam = ¶ms; rq.clen = LE_RECEIVER_TEST_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0){ return -1; } if (status) { return -1; } return 0; } int hci_le_transmitter_test(uint8_t frequency, uint8_t length, uint8_t payload) { struct hci_request rq; le_transmitter_test_cp params; uint8_t status; params.frequency = frequency; params.length = length; params.payload = payload; Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_TRANSMITTER_TEST; rq.cparam = ¶ms; rq.clen = LE_TRANSMITTER_TEST_CP_SIZE; rq.rparam = &status; rq.rlen = 1; if (hci_send_req(&rq) < 0){ return -1; } if (status) { return -1; } return 0; } int hci_le_test_end(uint16_t *num_pkts) { struct hci_request rq; le_test_end_rp resp; Osal_MemSet(&resp, 0, sizeof(resp)); Osal_MemSet(&rq, 0, sizeof(rq)); rq.ogf = OGF_LE_CTL; rq.ocf = OCF_LE_TEST_END; rq.rparam = &resp; rq.rlen = LE_TEST_END_RP_SIZE; if (hci_send_req(&rq) < 0){ return -1; } if (resp.status) { return -1; } *num_pkts = resp.num_pkts; return 0; }