extern void GattOnConnection(uint16 st_ucid) { uint8 dev_index = AppGetConnectedDeviceIndex(); uint8 service_changed_data[4]; service_changed_data[0] = WORD_LSB((HANDLE_GATT_SERVICE_END+1)); service_changed_data[1] = WORD_MSB((HANDLE_GATT_SERVICE_END+1)); service_changed_data[2] = WORD_LSB(ATT_HIGHEST_POSSIBLE_HANDLE); service_changed_data[3] = WORD_MSB(ATT_HIGHEST_POSSIBLE_HANDLE); if((g_gatt_data.serv_changed[dev_index]) && (g_gatt_data.serv_changed_config[dev_index] == gatt_client_config_indication)) { GattCharValueIndication(st_ucid, HANDLE_SERVICE_CHANGED, sizeof(service_changed_data), service_changed_data); /* Now that the indication has been sent, clear the flag in the NVM */ g_gatt_data.serv_changed[dev_index] = FALSE; Nvm_Write((uint16*)&(g_gatt_data.serv_changed[dev_index]), sizeof(g_gatt_data.serv_changed[dev_index]), (g_gatt_data.nvm_offset + SERV_CHANGED_SEND_IND(dev_index))); } }
extern app_time_error_code ConfigureCTSNotification(bool disable_notify) { if(g_time_serv_data.notify_configured == TRUE) { return error_success; } /* if current time service supported by the server enable * for notifications. */ if(g_time_serv_data.connected_device_services & cts_supported) { sys_status ret = sys_status_success; /* Set the value to disable notification on the client config handle */ uint8 notification_enabled[2] = { WORD_LSB(gatt_client_config_none), WORD_MSB(gatt_client_config_none)}; if(g_time_serv_data.conf_handle_ptr) { /* since it is already busy */ return error_cmd_inprogress; } /* enable the notification if disabling is set to false. normally * it will be enabled. */ if(disable_notify == FALSE) { notification_enabled[0] = WORD_LSB(gatt_client_config_notification); notification_enabled[1] = WORD_MSB(gatt_client_config_notification); } /* Start with enabling notifications on client configuration * descriptors of current time characteristic. */ g_time_serv_data.conf_handle_ptr = &g_time_serv_data.cur_time_ccd_hndl; /* Send the write request */ ret = GattWriteCharValueReq(GetConnectionID(), GATT_WRITE_REQUEST, g_time_serv_data.cur_time_ccd_hndl, sizeof(notification_enabled) /*size_value*/, notification_enabled); if(ret != sys_status_success) { g_time_serv_data.conf_handle_ptr = NULL; return error_not_ready; } } return error_success; }
/*----------------------------------------------------------------------------* * NAME * startBeaconing * * DESCRIPTION * This function is called to start beacon advertisements * * RETURNS * Nothing. * *---------------------------------------------------------------------------*/ void startBeaconing(void) { uint8 advData[BEACON_ADVERT_SIZE]; uint16 offset = 0; /* set the GAP Broadcaster role */ GapSetMode(gap_role_broadcaster, gap_mode_discover_no, gap_mode_connect_no, gap_mode_bond_no, gap_mode_security_none); /* clear the existing advertisement data */ LsStoreAdvScanData(0, NULL, ad_src_advertise); /* set the advertisement interval */ GapSetAdvInterval(BEACON_ADVERTISING_INTERVAL_MIN, BEACON_ADVERTISING_INTERVAL_MAX); /* store the manufacturing data */ advData[offset++] = AD_TYPE_MANUF; /* Apple company code, little endian */ advData[offset++] = 0x4C; advData[offset++] = 0x00; advData[offset++] = 2; /* Magic number */ advData[offset++] = 0x15; /* Length of the beacon payload */ /* Beacon UUID */ MemCopy(advData + offset, g_app_data.uuid, sizeof(g_app_data.uuid)); offset += sizeof(g_app_data.uuid); /* Beacon major */ advData[offset++] = WORD_MSB(g_app_data.major); advData[offset++] = WORD_LSB(g_app_data.major); /* Beacon minor */ advData[offset++] = WORD_MSB(g_app_data.minor); advData[offset++] = WORD_LSB(g_app_data.minor); /* Beacon TX Power */ advData[offset++] = g_app_data.txPower; /* store the advertisement data */ LsStoreAdvScanData(BEACON_ADVERT_SIZE, advData, ad_src_advertise); /* Start broadcasting */ LsStartStopAdvertise(TRUE, whitelist_disabled, ls_addr_type_random); }
int timer_set_square(unsigned long timer, unsigned long freq) { if (freq == 0) { return 1; // The frequency can't be set to 0. } if (freq > TIMER_FREQ) { return 1; // The number to put in the counter can't be lower than 1. TIMER_FREQ + 1 doesn't cause problems because the result is truncated, but if the user/programmer uses that value he's probably doing something wrong. } freq = TIMER_FREQ / freq; int BCD; if ((BCD = get_timer_BCD(timer)) == -1) { return 1; // Error obtaining the least significant bit from the status byte. } if (((BCD == TIMER_BCD) && freq > MAX_BCD_IN_WORD) || freq > MAX_BINARY_IN_WORD) { return 1; // The counter only accepts numbers with a maximum of 16 bits. } unsigned char timer_bit, timer_port; switch (timer) { case 0: timer_bit = TIMER_SEL0; timer_port = TIMER_0; break; case 1: timer_bit = TIMER_SEL1; timer_port = TIMER_1; break; case 2: timer_bit = TIMER_SEL2; timer_port = TIMER_2; break; default: return 1; } switch (get_timer_BCD(timer)) { case TIMER_BIN: if (sys_outb(TIMER_CTRL, timer_bit | TIMER_SQR_WAVE | TIMER_LSB_MSB | TIMER_BIN) == OK) { if (sys_outb(timer_port, WORD_LSB((unsigned)freq)) == OK) { return sys_outb(timer_port, WORD_MSB((unsigned)(freq))); } } return 1; case TIMER_BCD: if (sys_outb(TIMER_CTRL, timer_bit | TIMER_SQR_WAVE | TIMER_LSB_MSB | TIMER_BCD) == OK) { if (sys_outb(timer_port, WORD_LSB(binary_to_BCD((unsigned)freq))) == OK) { return sys_outb(timer_port, WORD_MSB(binary_to_BCD((unsigned)(freq)))); } } return 1; default: // -1 return 1; } }
/*----------------------------------------------------------------------------* * NAME * gattSetAdvertParams * * DESCRIPTION * This function is used to set advertisement parameters. * * PARAMETERS * p_addr [in] Bonded host address * fast_connection [in] TRUE: Fast advertisements * FALSE: Slow advertisements * * RETURNS * Nothing *----------------------------------------------------------------------------*/ static void gattSetAdvertParams(TYPED_BD_ADDR_T *p_addr, bool fast_connection) { uint8 advert_data[MAX_ADV_DATA_LEN];/* Advertisement packet */ uint16 length; /* Length of advertisement packet */ /* Advertisement interval, microseconds */ uint32 adv_interval_min; uint32 adv_interval_max; /* Tx power level value prefixed with 'Tx Power' AD Type */ /* Refer to BT4.0 specification, Vol3-part-C-Section-11.1.5 */ uint8 device_tx_power[TX_POWER_VALUE_LENGTH] = { AD_TYPE_TX_POWER }; /* Device appearance */ uint8 device_appearance[ATTR_LEN_DEVICE_APPEARANCE + 1] = { AD_TYPE_APPEARANCE, WORD_LSB(APPEARANCE_APPLICATION_VALUE), WORD_MSB(APPEARANCE_APPLICATION_VALUE) }; /* A variable to keep track of the data added to advert_data. The limit is * MAX_ADV_DATA_LEN. GAP layer will add AD Flags to advert_data which is 3 * bytes. Refer BT Spec 4.0, Vol 3, Part C, Sec 11.1.3: * * First byte is length * second byte is AD TYPE = 0x1 * Third byte is Flags description */ uint16 length_added_to_adv = 3; if(fast_connection) { adv_interval_min = FC_ADVERTISING_INTERVAL_MIN; adv_interval_max = FC_ADVERTISING_INTERVAL_MAX; } if((GapSetMode(gap_role_peripheral, gap_mode_discover_general, gap_mode_connect_undirected, gap_mode_bond_yes, gap_mode_security_unauthenticate) != ls_err_none) || (GapSetAdvInterval(adv_interval_min, adv_interval_max) != ls_err_none)) { ReportPanic(app_panic_set_advert_params); } /* Add bonded device to white list.*/ if(IsWhiteListEnabled()) { /* Initial case when advertisements are started for Bonded host for * 10 seconds. White list is configured with the Bonded host address */ if(LsAddWhiteListDevice(p_addr)!= ls_err_none) { ReportPanic(app_panic_add_whitelist); } } /* Reset existing advertising data */ if(LsStoreAdvScanData(0, NULL, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* Reset existing scan response data */ if(LsStoreAdvScanData(0, NULL, ad_src_scan_rsp) != ls_err_none) { ReportPanic(app_panic_set_scan_rsp_data); } /* Setup ADVERTISEMENT DATA */ /* Add UUID list of the services supported by the device */ length = GetSupportedUUIDServiceList(advert_data); /* One added for Length field, which will be added to Adv Data by GAP * layer */ length_added_to_adv += (length + 1); if (LsStoreAdvScanData(length, advert_data, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* One added for Length field, which will be added to Adv Data by GAP * layer */ length_added_to_adv += (sizeof(device_appearance) + 1); /* Add device appearance to the advertisements */ if (LsStoreAdvScanData(ATTR_LEN_DEVICE_APPEARANCE + 1, device_appearance, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } /* Change the Radio and Adv tx params for CONFIG mode */ /* Update the radio tx power level here */ LsSetTransmitPowerLevel(RADIO_TX_POWER_CONFIG); /* Update the adv tx power level here */ device_tx_power[TX_POWER_VALUE_LENGTH - 1] = ADV_TX_POWER_CONFIG; /* NOTE: The 2 tx params above are reset to the tx_power_mode on disconnection */ /* One added for Length field, it will be added to Adv Data by GAP layer */ length_added_to_adv += (TX_POWER_VALUE_LENGTH + 1); /* Add tx power value of device to the advertising data */ if (LsStoreAdvScanData(TX_POWER_VALUE_LENGTH, device_tx_power, ad_src_advertise) != ls_err_none) { ReportPanic(app_panic_set_advert_data); } addDeviceNameToAdvData(length_added_to_adv, 0); }
/*----------------------------------------------------------------------------* * NAME * initBeacon * * DESCRIPTION * This function initialises beacon data * * RETURNS * Nothing. * *---------------------------------------------------------------------------*/ void initBeacon(void) { /* read the config values from CsKeys */ uint16 beaconUuidMsw = CSReadUserKey(BEACON_UUID_MSW_USER_KEY_IDX); uint16 beaconMajor = CSReadUserKey(BEACON_MAJOR_USER_KEY_IDX); uint16 beaconMinor = CSReadUserKey(BEACON_MINOR_USER_KEY_IDX); uint16 txPower = CSReadUserKey(BEACON_TX_POWER_USER_KEY_IDX); /* set up beacon UUID */ if(beaconUuidMsw == BEACON_USER_KEY_DEFAULT_VALUE) { g_app_data.uuid[0] = BEACON_UUID_00; g_app_data.uuid[1] = BEACON_UUID_01; } else { g_app_data.uuid[0] = WORD_MSB(beaconUuidMsw); g_app_data.uuid[1] = WORD_LSB(beaconUuidMsw); } g_app_data.uuid[2] = BEACON_UUID_02; g_app_data.uuid[3] = BEACON_UUID_03; g_app_data.uuid[4] = BEACON_UUID_04; g_app_data.uuid[5] = BEACON_UUID_05; g_app_data.uuid[6] = BEACON_UUID_06; g_app_data.uuid[7] = BEACON_UUID_07; g_app_data.uuid[8] = BEACON_UUID_08; g_app_data.uuid[9] = BEACON_UUID_09; g_app_data.uuid[10] = BEACON_UUID_10; g_app_data.uuid[11] = BEACON_UUID_11; g_app_data.uuid[12] = BEACON_UUID_12; g_app_data.uuid[13] = BEACON_UUID_13; g_app_data.uuid[14] = BEACON_UUID_14; g_app_data.uuid[15] = BEACON_UUID_15; /* set up beacon major */ if(beaconMajor == BEACON_USER_KEY_DEFAULT_VALUE) { g_app_data.major = BEACON_DEFAULT_MAJOR; } else { g_app_data.major = beaconMajor; } /* set up beacon minor */ if(beaconMinor == BEACON_USER_KEY_DEFAULT_VALUE) { g_app_data.minor = BEACON_DEFAULT_MINOR; } else { g_app_data.minor = beaconMinor; } /* set up the TX power */ if(txPower == BEACON_USER_KEY_DEFAULT_VALUE) { g_app_data.txPower = BEACON_DEFAULT_TX_POWER; } else { g_app_data.txPower = txPower; } }