diff --git a/CHANGELOG.md b/CHANGELOG.md index f305fc087d0..0618d5f9550 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Release vxx.x.x ### Features +* Add support for FAN 1.1 PHY mode IDs (all) and Channel plan IDs 1, 2, and 5 for North American and Brazil domains. This change enables OFDM modulation usage for mentioned frequency bands. * Wi-SUN timing parameters are selected based on Data rate and network size. * diff --git a/nanostack/ws_management_api.h b/nanostack/ws_management_api.h index 78ee0665034..9c4b85806d7 100644 --- a/nanostack/ws_management_api.h +++ b/nanostack/ws_management_api.h @@ -70,11 +70,13 @@ extern "C" { #define CHANNEL_FUNCTION_DH1CF 0x02 // Direct Hash #define CHANNEL_FUNCTION_VENDOR_DEFINED 0x03 // vendor given channel hop schedule -#define CHANNEL_SPACING_200 0x00 // 200 khz -#define CHANNEL_SPACING_400 0x01 // 400 khz -#define CHANNEL_SPACING_600 0x02 // 600 khz -#define CHANNEL_SPACING_100 0x03 // 100 khz -#define CHANNEL_SPACING_250 0x04 // 250 khz +#define CHANNEL_SPACING_200 0x00 // 200 khz +#define CHANNEL_SPACING_400 0x01 // 400 khz +#define CHANNEL_SPACING_600 0x02 // 600 khz +#define CHANNEL_SPACING_100 0x03 // 100 khz +#define CHANNEL_SPACING_250 0x04 // 250 khz +#define CHANNEL_SPACING_800 0x05 // 800 khz +#define CHANNEL_SPACING_1200 0x06 // 1200 khz /* * Network Size definitions are device amount in hundreds of devices. diff --git a/source/6LoWPAN/ws/ws_bootstrap.c b/source/6LoWPAN/ws/ws_bootstrap.c index 782bb0e3c53..a63f874a869 100644 --- a/source/6LoWPAN/ws/ws_bootstrap.c +++ b/source/6LoWPAN/ws/ws_bootstrap.c @@ -624,8 +624,8 @@ static uint8_t ws_generate_exluded_channel_list_from_active_channels(ws_excluded static void ws_fhss_configure_channel_masks(protocol_interface_info_entry_t *cur, fhss_ws_configuration_t *fhss_configuration) { - ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class); - ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class); + ws_generate_channel_list(fhss_configuration->channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id); + ws_generate_channel_list(fhss_configuration->unicast_channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id); // using bitwise AND operation for user set channel mask to remove channels not allowed in this device for (uint8_t n = 0; n < 8; n++) { fhss_configuration->unicast_channel_mask[n] &= cur->ws_info->cfg->fhss.fhss_channel_mask[n]; @@ -3133,7 +3133,7 @@ static void ws_set_asynch_channel_list(protocol_interface_info_entry_t *cur, asy uint16_t channel_number = cur->ws_info->cfg->fhss.fhss_uc_fixed_channel; async_req->channel_list.channel_mask[0 + (channel_number / 32)] = (1 << (channel_number % 32)); } else { - ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class); + ws_generate_channel_list(async_req->channel_list.channel_mask, cur->ws_info->hopping_schdule.number_of_channels, cur->ws_info->hopping_schdule.regulatory_domain, cur->ws_info->hopping_schdule.operating_class, cur->ws_info->hopping_schdule.channel_plan_id); } async_req->channel_list.channel_page = CHANNEL_PAGE_10; diff --git a/source/6LoWPAN/ws/ws_common.c b/source/6LoWPAN/ws/ws_common.c index 38a23c92a77..e2bfaeebfd6 100644 --- a/source/6LoWPAN/ws/ws_common.c +++ b/source/6LoWPAN/ws/ws_common.c @@ -53,33 +53,57 @@ uint8_t DEVICE_MIN_SENS = 174 - 93; uint16_t test_max_child_count_override = 0xffff; -int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class) +static int8_t ws_disable_channels_in_range(uint32_t *channel_mask, uint16_t number_of_channels, uint16_t range_start, uint16_t range_stop) { - uint32_t excluded_start_channel = 0xFFFFFFFF; - uint32_t excluded_end_channel = 0xFFFFFFFF; - - if (regulatory_domain == REG_DOMAIN_BZ) { - if (operating_class == 1) { - excluded_start_channel = 26; - excluded_end_channel = 64; - } else if (operating_class == 2) { - excluded_start_channel = 12; - excluded_end_channel = 32; - } else if (operating_class == 3) { - excluded_start_channel = 7; - excluded_end_channel = 21; + for (uint16_t i = 0; i < number_of_channels; i++) { + if (i >= range_start && i <= range_stop) { + channel_mask[0 + (i / 32)] &= ~(1 << (i % 32)); } } + return 0; +} +int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id) +{ // Clear channel mask for (uint8_t i = 0; i < 8; i++) { channel_mask[i] = 0; } - - // Set channel maks outside excluded channels + // Enable all channels for (uint16_t i = 0; i < number_of_channels; i++) { - if (i < excluded_start_channel || i > excluded_end_channel) { - channel_mask[0 + (i / 32)] |= (1 << (i % 32)); + channel_mask[0 + (i / 32)] |= (1 << (i % 32)); + } + // Disable unsupported channels per regional frequency bands + if (regulatory_domain == REG_DOMAIN_NA) { + if (channel_plan_id == 1) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 1, 7); + } else if (channel_plan_id == 5) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 5, 7); + } + } + if (regulatory_domain == REG_DOMAIN_BZ) { + if (channel_plan_id == 255) { + if (operating_class == 1) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 26, 64); + } else if (operating_class == 2) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 12, 32); + } else if (operating_class == 3) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 7, 21); + } + } else { + if (channel_plan_id == 1) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 1, 7); + ws_disable_channels_in_range(channel_mask, number_of_channels, 64, 64); + ws_disable_channels_in_range(channel_mask, number_of_channels, 72, 103); + ws_disable_channels_in_range(channel_mask, number_of_channels, 106, 111); + } else if (channel_plan_id == 2) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 24, 24); + ws_disable_channels_in_range(channel_mask, number_of_channels, 32, 47); + ws_disable_channels_in_range(channel_mask, number_of_channels, 52, 55); + } else if (channel_plan_id == 5) { + ws_disable_channels_in_range(channel_mask, number_of_channels, 5, 10); + ws_disable_channels_in_range(channel_mask, number_of_channels, 19, 23); + } } } return 0; @@ -109,6 +133,10 @@ uint32_t ws_decode_channel_spacing(uint8_t channel_spacing) return 400000; } else if (CHANNEL_SPACING_600 == channel_spacing) { return 600000; + } else if (CHANNEL_SPACING_800 == channel_spacing) { + return 800000; + } else if (CHANNEL_SPACING_1200 == channel_spacing) { + return 1200000; } return 0; } @@ -271,30 +299,60 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, return -1; } } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_NA) { - if (hopping_schdule->operating_class == 1) { - hopping_schdule->ch0_freq = 9022; - hopping_schdule->channel_spacing = CHANNEL_SPACING_200; - } else if (hopping_schdule->operating_class == 2) { - hopping_schdule->ch0_freq = 9024; - hopping_schdule->channel_spacing = CHANNEL_SPACING_400; - } else if (hopping_schdule->operating_class == 3) { - hopping_schdule->ch0_freq = 9026; - hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + if (hopping_schdule->channel_plan_id == 255) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->operating_class == 3) { + hopping_schdule->ch0_freq = 9026; + hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + } else { + return -1; + } } else { - return -1; + if (hopping_schdule->channel_plan_id == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->channel_plan_id == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->channel_plan_id == 5) { + hopping_schdule->ch0_freq = 9032; + hopping_schdule->channel_spacing = CHANNEL_SPACING_1200; + } else { + return -1; + } } } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_BZ) { - if (hopping_schdule->operating_class == 1) { - hopping_schdule->ch0_freq = 9022; - hopping_schdule->channel_spacing = CHANNEL_SPACING_200; - } else if (hopping_schdule->operating_class == 2) { - hopping_schdule->ch0_freq = 9024; - hopping_schdule->channel_spacing = CHANNEL_SPACING_400; - } else if (hopping_schdule->operating_class == 3) { - hopping_schdule->ch0_freq = 9026; - hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + if (hopping_schdule->channel_plan_id == 255) { + if (hopping_schdule->operating_class == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->operating_class == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->operating_class == 3) { + hopping_schdule->ch0_freq = 9026; + hopping_schdule->channel_spacing = CHANNEL_SPACING_600; + } else { + return -1; + } } else { - return -1; + if (hopping_schdule->channel_plan_id == 1) { + hopping_schdule->ch0_freq = 9022; + hopping_schdule->channel_spacing = CHANNEL_SPACING_200; + } else if (hopping_schdule->channel_plan_id == 2) { + hopping_schdule->ch0_freq = 9024; + hopping_schdule->channel_spacing = CHANNEL_SPACING_400; + } else if (hopping_schdule->channel_plan_id == 5) { + hopping_schdule->ch0_freq = 9032; + hopping_schdule->channel_spacing = CHANNEL_SPACING_1200; + } else { + return -1; + } } } else if (hopping_schdule->regulatory_domain == REG_DOMAIN_JP) { if (hopping_schdule->operating_class == 1) { @@ -322,7 +380,7 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, } else { return -1; } - hopping_schdule->number_of_channels = (uint8_t)ws_common_channel_number_calc(hopping_schdule->regulatory_domain, hopping_schdule->operating_class); + hopping_schdule->number_of_channels = (uint8_t)ws_common_channel_number_calc(hopping_schdule->regulatory_domain, hopping_schdule->operating_class, hopping_schdule->channel_plan_id); if (!hopping_schdule->number_of_channels) { return -1; } @@ -330,7 +388,7 @@ int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, return 0; } -uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class) +uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id) { if (regulatory_domain == REG_DOMAIN_KR) { if (operating_class == 1) { @@ -355,12 +413,22 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat return 10; } } else if (regulatory_domain == REG_DOMAIN_NA) { - if (operating_class == 1) { - return 129; - } else if (operating_class == 2) { - return 64; - } else if (operating_class == 3) { - return 42; + if (channel_plan_id == 255) { + if (operating_class == 1) { + return 129; + } else if (operating_class == 2) { + return 64; + } else if (operating_class == 3) { + return 42; + } + } else { + if (channel_plan_id == 1) { + return 136; + } else if (channel_plan_id == 2) { + return 64; + } else if (channel_plan_id == 5) { + return 24; + } } } else if (regulatory_domain == REG_DOMAIN_JP) { if (operating_class == 1) { @@ -371,12 +439,22 @@ uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operat return 12; } } else if (regulatory_domain == REG_DOMAIN_BZ) { - if (operating_class == 1) { - return 129; - } else if (operating_class == 2) { - return 64; - } else if (operating_class == 3) { - return 42; + if (channel_plan_id == 255) { + if (operating_class == 1) { + return 129; + } else if (operating_class == 2) { + return 64; + } else if (operating_class == 3) { + return 42; + } + } else { + if (channel_plan_id == 1) { + return 136; + } else if (channel_plan_id == 2) { + return 64; + } else if (channel_plan_id == 5) { + return 24; + } } } else if (regulatory_domain == REG_DOMAIN_WW) { if (operating_class == 1) { diff --git a/source/6LoWPAN/ws/ws_common.h b/source/6LoWPAN/ws/ws_common.h index 6a57cc793b7..a51f58c67af 100644 --- a/source/6LoWPAN/ws/ws_common.h +++ b/source/6LoWPAN/ws/ws_common.h @@ -122,7 +122,7 @@ typedef struct ws_info_s { #ifdef HAVE_WS -int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class); +int8_t ws_generate_channel_list(uint32_t *channel_mask, uint16_t number_of_channels, uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id); uint16_t ws_active_channel_count(uint32_t *channel_mask, uint16_t number_of_channels); @@ -140,7 +140,7 @@ phy_modulation_index_e ws_get_modulation_index_using_operating_mode(uint8_t oper int8_t ws_common_regulatory_domain_config(protocol_interface_info_entry_t *cur, ws_hopping_schedule_t *hopping_schdule); -uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class); +uint16_t ws_common_channel_number_calc(uint8_t regulatory_domain, uint8_t operating_class, uint8_t channel_plan_id); int8_t ws_common_allocate_and_init(protocol_interface_info_entry_t *cur); diff --git a/source/6LoWPAN/ws/ws_empty_functions.c b/source/6LoWPAN/ws/ws_empty_functions.c index 990c423df8d..17443e8469e 100644 --- a/source/6LoWPAN/ws/ws_empty_functions.c +++ b/source/6LoWPAN/ws/ws_empty_functions.c @@ -68,6 +68,24 @@ int ws_management_network_name_validate( return -1; } +int ws_management_phy_mode_id_set( + int8_t interface_id, + uint8_t phy_mode_id) +{ + (void)interface_id; + (void)phy_mode_id; + return -1; +} + +int ws_management_channel_plan_id_set( + int8_t interface_id, + uint8_t channel_plan_id) +{ + (void)interface_id; + (void)channel_plan_id; + return -1; +} + int ws_management_regulatory_domain_set( int8_t interface_id, uint8_t regulatory_domain, diff --git a/source/6LoWPAN/ws/ws_neighbor_class.c b/source/6LoWPAN/ws/ws_neighbor_class.c index 35647c1e121..ab24bf0ed83 100644 --- a/source/6LoWPAN/ws/ws_neighbor_class.c +++ b/source/6LoWPAN/ws/ws_neighbor_class.c @@ -254,7 +254,7 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t * } else { if (ws_us->channel_plan == 0) { - ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class); + ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_common_channel_number_calc(ws_us->plan.zero.regulator_domain, ws_us->plan.zero.operation_class, own_shedule->channel_plan_id); } else if (ws_us->channel_plan == 1) { ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels = ws_us->plan.one.number_of_channel; @@ -262,16 +262,16 @@ void ws_neighbor_class_neighbor_unicast_schedule_set(ws_neighbor_class_entry_t * //Handle excluded channel and generate activate channel list if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_RANGE) { - ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class); + ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id); ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); ws_neighbour_excluded_mask_by_range(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.range, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); } else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_BITMASK) { - ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class); + ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id); ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); ws_neighbour_excluded_mask_by_mask(&ws_neighbor->fhss_data.uc_channel_list, &ws_us->excluded_channels.mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); } else if (ws_us->excluded_channel_ctrl == WS_EXC_CHAN_CTRL_NONE) { if (ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels != ws_neighbor->fhss_data.uc_channel_list.channel_count) { - ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class); + ws_generate_channel_list(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels, own_shedule->regulatory_domain, own_shedule->operating_class, own_shedule->channel_plan_id); ws_neighbor->fhss_data.uc_channel_list.channel_count = ws_active_channel_count(ws_neighbor->fhss_data.uc_channel_list.channel_mask, ws_neighbor->fhss_data.uc_timing_info.unicast_number_of_channels); } }