Пример #1
0
/**
 * @brief Gets the OQPSK Chiprate
 *
 *
 * @param[in]   trx_id Transceiver identifier
 * @param[in]   freq_band Frequency band
 *
 * @return     oqpsk chiprate
 */
oqpsk_chip_rate_t get_oqpsk_chip_rate(trx_id_t trx_id,
		sun_freq_band_t freq_band)
{
	uint16_t rate = 0;
	uint8_t rate_mode = 0;

	for (uint8_t i = 0; i < OQPSK_CHIP_RATE_FREQ_TABLE_ROW_SIZE; i++) {
		if (freq_band ==
				(uint16_t)PGM_READ_WORD(&
				oqpsk_chip_rate_freq_table
				[i][0])) {
			rate = (uint16_t)PGM_READ_WORD(
					&oqpsk_chip_rate_freq_table[i][1]);
			break;
		}
	}
	if (rate == 2000) {
		rate_mode = CHIP_RATE_2000;
	} else if (rate == 1000) {
		rate_mode = CHIP_RATE_1000;
	} else if (rate == 200) {
		rate_mode = CHIP_RATE_200;
	} else if (rate == 100) {
		rate_mode = CHIP_RATE_100;
	}

	return rate_mode;
}
Пример #2
0
// General Functions
uint8_t xboot_get_version(uint16_t *ver)
{
        uint8_t ret = init_api();
        uint16_t ptr;
        
        #ifdef NEED_EIND
        uint8_t saved_eind;
        #endif // NEED_EIND
        
        if (ret != XB_SUCCESS)
                return ret;
        
        if (api_version == 1)
        {
                ptr = PGM_READ_WORD(JUMP_TABLE_INDEX(0));
                if (ptr == 0 || ptr == 0xffff)
                        return XB_ERR_NOT_FOUND;
                
                #ifdef NEED_EIND
                saved_eind = EIND;
                EIND = PROGMEM_SIZE >> 17;
                #endif // NEED_EIND
                
                ret = ( (uint8_t(*)(uint16_t *)) ptr )(ver);
                
                #ifdef NEED_EIND
                EIND = saved_eind;
                #endif // NEED_EIND
                
                return ret;
        }
/**
 * @brief Obtains the message type from the buffer and calls the respective handler
 *
 * This function decodes all events/messages and calls the appropriate handler.
 *
 * @param event Pointer to the buffer header whose body part holds the message
 * type and message elemnets
 */
void dispatch_event(uint8_t *event)
{
    /*
     * A pointer to the body of the buffer is obtained from the pointer to the
     * received header.
     */
    uint8_t *buffer_body = BMM_BUFFER_POINTER((buffer_t *)event);

    /* Check is done to see if the message type is valid */
    /* Please note:
     * The macro PGM_READ_WORD is only relevant for AVR-GCC builds and
     * reads a DWord from flash, which is the start address of the function.
     *
     * How does this work for builds that are larger than 128K?
     *
     * For IAR builds this statement is fine, since PGM_READ_WORD just
     * turns to "*". The size of the function pointer is automatically
     * 3 byte for MCUs which have more than 128K flash. The the address
     * of the callback is properly derived from this location.
     *
     * AVR-GCC currently does not support function pointers larger than
     * 16 bit. This implies that functions residing in the upper 128K
     * cannot be addressed properly. Therefore this code does not work
     * in these cases.
     * In regular cases, where code is not larger than 128K, the size
     * of a function pointer is 16 bit and properly read via PGM_READ_WORD.
     *
     * Update: In order for this to work, the option -mrelax must be given 
     * on the compiler command-line that is used to link the final ELF file. 
     * (Older compilers did not implement this option for the AVR, 
     * use -Wl,--relax instead.)     */
    /* Check for regular MAC requests. */
    if (buffer_body[CMD_ID_OCTET] <= LAST_MESSAGE)
    {
        /*
         * The following statement reads the address from the dispatch table
         * of the function to be called by utilizing function pointers.
         */
        handler_t handler = (handler_t)PGM_READ_WORD(&dispatch_table[buffer_body[CMD_ID_OCTET]]);

        if (handler != NULL)
        {
            handler(event);
        }
        else
        {
            bmm_buffer_free((buffer_t *)event);
#if (DEBUG > 0)
            ASSERT("Dispatch handler unavailable" == 0);
#endif
        }
    }
#ifdef ENABLE_RTB
    else
    {
        dispatch_rtb_event(event);
    }
#endif  /* ENABLE_RTB */
}
Пример #4
0
/**
 * @brief Post processing of the vendor data response.
 *
 * @param PairingRef       Pairing reference
 * @param VendorId         Vendor ID.
 * @param nsduLength       Length of the payload.
 * @param nsdu             Actual payload
 * @param RxLinkQuality    Link quality of received packet.
 * @param RxFlags          Rx Flags.
 */
static void vendor_data_ind(uint8_t PairingRef, uint16_t VendorId,
		uint8_t nsduLength, uint8_t *nsdu, uint8_t RxLinkQuality,
		uint8_t RxFlags)
{
	uint16_t v_id = PGM_READ_WORD(&VendorIdentifier);
	if (v_id == VendorId) {
		if (node_status == POWER_SAVE) {
			printf("Leaving power save mode.\r\n");
			nlme_rx_enable_request(RX_DURATION_INFINITY,
					(FUNC_PTR)nlme_rx_enable_confirm
					);
			node_status = IDLE;
		}

		printf("Vendor data received from pairing ref %d - ",
				PairingRef);
		switch (nsdu[0]) {
		case BATTERY_STATUS_RESP:
		{
			uint16_t volt = (uint16_t)nsdu[1] |
					((uint16_t)nsdu[2] << 8);

			printf("battery status ");
			printf("%d.", volt / 1000);
			printf("%d V\r\n", volt % 1000);
		}
		break;

		case ALIVE_RESP:
			printf("Remote controller is alive\r\n");
			break;

		case FW_VERSION_RESP:
			printf("Firmware version response: %d.%d.%d\r\n",
					nsdu[1], nsdu[2], nsdu[3]);
			break;

		case RX_ON_RESP:
			printf("RX on response\r\n");
			break;

		default:
			printf("unknown command: 0x");
			for (uint8_t i = 0; i < nsduLength; i++) {
				printf("%.02X ", nsdu[i]);
			}
			printf("\r\n");
			break;
		}
	}

	/* Keep compiler happy */
	PairingRef = PairingRef;
	nsduLength = nsduLength;
	RxLinkQuality = RxLinkQuality;
	RxFlags = RxFlags;
}
Пример #5
0
/**
 * @brief Gets the symbol duration in us
 *
 * @param trx_id Transceiver identifier
 *
 * @return Duration of a symbol in us
 */
uint16_t tal_get_symbol_duration_us(trx_id_t trx_id)
{
	uint16_t ret_val = 0; /* 0: indicator for wrong parameter */

	switch (tal_pib[trx_id].phy.modulation) {
#ifdef SUPPORT_FSK
	case FSK:
		ret_val = 20; /* table 0, pg. 7 */
		break;

#endif
#ifdef SUPPORT_OFDM
	case OFDM:
		ret_val = 120;
		break;

#endif
#ifdef SUPPORT_OQPSK
	case OQPSK: /* table 183, pg. 118 */
		ret_val
			= (uint16_t)PGM_READ_WORD(&oqpsk_sym_duration_table[
					tal_pib
					[trx_id].phy.phy_mode.oqpsk.chip_rate]);
		break;

#endif
#ifdef SUPPORT_LEGACY_OQPSK
	case LEG_OQPSK:
		ret_val = 16;
		break;

#endif
	default:
		break;
	}

	return ret_val;
}
Пример #6
0
void vendor_data_ind(uint8_t PairingRef, uint16_t VendorId,
                     uint8_t nsduLength, uint8_t *nsdu, uint8_t RxLinkQuality,
                     uint8_t RxFlags)
{
    /* Check if vendor id matches.
     * Handle here only vendor data from same vendor */
    uint16_t v_id = PGM_READ_WORD(&VendorIdentifier);
    uint8_t nsduHandle = 1;
    if ((VendorId == v_id) && (RxFlags & RX_FLAG_WITH_SEC)) {
        switch (nsdu[0]) { /* vendor-specific command id */
        case BATTERY_STATUS_REQ:
        {
            uint16_t voltage = get_batmon_voltage();
            nsdu[0] = BATTERY_STATUS_RESP;
            nsdu[1] = (uint8_t)voltage; /* LSB */
            nsdu[2] = (uint8_t)(voltage >> 8); /* MSB */
            nsduLength = 3;
        }
        break;

        case ALIVE_REQ: /* Alive request */
            vendor_app_alive_req();
            /* Send alive response */
            nsdu[0] = ALIVE_RESP;
            nsduLength = 1;
            break;

        case FW_VERSION_REQ:
        {
            /* Send alive response */
            nsdu[0] = FW_VERSION_RESP;
            nsdu[1] = FW_VERSION_MAJOR; /* major version number */
            nsdu[2] = FW_VERSION_MINOR; /* minor version number */
            nsdu[3] = FW_VERSION_REV; /* revision version number */
            nsduLength = 4;
        }
        break;

        case RX_ON_REQ:
        {
            uint32_t duration = 0;

            memcpy(&duration, &nsdu[1], 3);
            if (!nlme_rx_enable_request(duration,
                                        (FUNC_PTR)nlme_rx_enable_confirm
                                       )) {
                /*
                 * RX enable could not been added to the queue.
                 * Therefore do not send response message.
                 */
                return;
            }

            /* Send response */
            nsdu[0] = RX_ON_RESP;
            nsduLength = 1;
        }
        break;

        default:
        {
            /* Send response */
            nsdu[0] = FW_DATA_RESP;
            nsdu[1] = VD_NOT_SUPPORTED_ATTRIBUTE;
            nsduLength = 2;
        }
        break;
        }

        /* Transmit response message */

        nlde_data_request(PairingRef, PROFILE_ID_ZRC, VendorId,
                          nsduLength, nsdu,
                          TXO_UNICAST | TXO_DST_ADDR_NET | TXO_ACK_REQ | TXO_SEC_REQ | TXO_MULTI_CH | TXO_CH_NOT_SPEC | TXO_VEND_SPEC,
                          nsduHandle,
                          (FUNC_PTR)vendor_data_confirm
                         );
        /* Keep compiler happy */
        RxLinkQuality = RxLinkQuality;
        RxFlags = RxFlags;
    }
}
Пример #7
0
void vendor_data_ind(uint8_t PairingRef, profile_id_t ProfileId, uint16_t VendorId,
                          uint8_t nsduLength, uint8_t *nsdu, uint8_t RxLinkQuality,
                          uint8_t RxFlags)
{
    /* Check if vendor id matches.
       Handle here only vendor data from same vendor */
    uint16_t v_id = PGM_READ_WORD(&VendorIdentifier);
    if ((VendorId == v_id) && (RxFlags & RX_FLAG_WITH_SEC))
    {
	switch (nsdu[0])    // vendor-specific command id
        {
          
#ifdef _DEBUG_INTERFACE_
        case 0x1B:  
          {
              int i;
              for (i = 0; i < nsduLength;) 
              {
                  RxHandler(nsdu[i++]); 
              }
             
               RX_index = 4;	// Next GetChar() will get the command id
          
              /* Call QDebug_Process */
              QDebug_ProcessCommands();
              return;
          }
          break;
          
#endif
          
#ifdef TFA_BAT_MON
            case BATTERY_STATUS_REQ:
                {
                    uint16_t voltage = tfa_get_batmon_voltage();
                    nsdu[0] = BATTERY_STATUS_RESP;
                    nsdu[1] = (uint8_t)voltage;    // LSB
                    nsdu[2] = (uint8_t)(voltage >> 8);    // MSB
                    nsduLength = 3;
                }
                break;
#endif
            case ALIVE_REQ:  /* Alive request */
                vendor_app_alive_req();
                /* Send alive response */
                nsdu[0] = ALIVE_RESP;
                nsduLength = 1;
                break;

            case FW_VERSION_REQ:
                {
                    /* Send alive response */
                    nsdu[0] = FW_VERSION_RESP;
                    nsdu[1] = FW_VERSION_MAJOR;    // major version number
                    nsdu[2] = FW_VERSION_MINOR;    // minor version number
                    nsdu[3] = FW_VERSION_REV;    // revision version number
                    nsduLength = 4;
                }
                break;

            case RX_ON_REQ:
                {
                    uint32_t duration = 0;

                    memcpy(&duration, &nsdu[1], 3);
                    if (!nlme_rx_enable_request(duration))
                    {
                        /*
                         * RX enable could not been added to the queue.
                         * Therefore do not send response message.
                         */
                        return;
                    }
                    /* Send response */
                    nsdu[0] = RX_ON_RESP;
                    nsduLength = 1;
                }
                break;

#ifdef FLASH_SUPPORT
            case FW_DATA_REQ:
                {
                    fw_data_frame_t *fw_frame;
                    vendor_status_t status = VD_SUCCESS;

                    fw_frame = (fw_data_frame_t *)nsdu;

                    /* Verify data chunk size */
                    uint8_t fw_data_size = nsduLength - 5;  // 5 = header len
                    if (fw_data_size > 64)
                    {
                        status = VD_UNSUPPORTED_SIZE;
                    }
                    else
                    {
                        /* Fill temporary page buffer */
                        uint16_t start_addr = (fw_frame->frame_cnt - 1) % 4;
                        flash_fill_page_buffer(start_addr * (SPM_PAGESIZE / 4), fw_data_size, &fw_frame->fw_data[0]);
                        /* Write flash page */
                        if ((fw_frame->frame_cnt % 4) == 0)
                        {
                            uint32_t page_start_addr;
                            page_start_addr = IMAGE_START_ADDR + ((uint32_t)SPM_PAGESIZE * ((fw_frame->frame_cnt / 4) - 1));
                            flash_program_page(page_start_addr);
                        }
                        else if (fw_frame->frame_cnt == fw_frame->total_num_frames)
                        {
                            uint32_t page_start_addr;
                            page_start_addr = IMAGE_START_ADDR + ((uint32_t)SPM_PAGESIZE * (fw_frame->frame_cnt / 4));
                            flash_program_page(page_start_addr);
                        }
                    }
                    /* Send response */
                    nsdu[0] = FW_DATA_RESP;
                    nsdu[1] = status;
                    nsduLength = 2;
                }
                break;
#endif  /* #ifdef FLASH_SUPPORT */

#ifdef FLASH_SUPPORT
            case FW_SWAP_REQ:
                flash_swap(IMAGE_START_ADDR, IMAGE_SIZE);
                /* Do not send response message */
                return;
#endif  /* #ifdef FLASH_SUPPORT */

            default:
                {
                    /* Send response */
                    nsdu[0] = FW_DATA_RESP;
                    nsdu[1] = VD_NOT_SUPPORTED_ATTRIBUTE;
                    nsduLength = 2;
                }
                break;
        }

        /* Transmit response message */
        nlde_data_request(PairingRef, PROFILE_ID_VENDOR_DATA, VendorId,
                        nsduLength, nsdu,
                        TXO_UNICAST | TXO_DST_ADDR_NET | TXO_ACK_REQ | TXO_SEC_REQ | TXO_MULTI_CH | TXO_CH_NOT_SPEC | TXO_VEND_SPEC);

        /* Keep compiler happy */
        UNUSED(ProfileId);
        UNUSED(RxLinkQuality);
        UNUSED(RxFlags);
    }
}
Пример #8
0
/**
 * @brief Gets PSDU data rate
 *
 * @param trx_id Transceiver identifier
 *
 * @return data rate in kbit/s
 */
float get_data_rate(trx_id_t trx_id)
{
	float rate = 0;

	switch (tal_pib[trx_id].phy.modulation) {
#ifdef SUPPORT_FSK
	case FSK:
		rate = 10 *
				(uint8_t)PGM_READ_BYTE(&fsk_data_rate_table[
					tal_pib[trx_id
					].phy.phy_mode.fsk.data_rate]);
		if (tal_pib[trx_id].phy.phy_mode.fsk.mod_type == F4FSK) {
			rate *= 2;
		}

		if (tal_pib[trx_id].FSKFECEnabled) {
			rate /= 2;
		}
		break;

#endif
#ifdef SUPPORT_OFDM
	case OFDM:
		rate
			= (uint16_t)PGM_READ_WORD(&ofdm_data_rate_table[tal_pib[
					trx_id
				].OFDMMCS] \
				[tal_pib[trx_id].phy.phy_mode.ofdm.option]);            /* optoin
		                                                                         * -
		                                                                         * 1 */
		break;

#endif
#ifdef SUPPORT_OQPSK
	case OQPSK:
	{
		uint16_t chip_rate = oqpsk_get_chip_rate(trx_id);
		uint8_t spread = oqpsk_spreading(
				tal_pib[trx_id].phy.phy_mode.oqpsk.chip_rate,
				tal_pib[trx_id].OQPSKRateMode);
		rate = (float)chip_rate / (float)spread / (float)2;
	}
	break;

#endif
#ifdef SUPPORT_LEGACY_OQPSK
	case LEG_OQPSK:
		rate = 250;
		if (tal_pib[trx_id].HighRateEnabled) {
			if (tal_pib[trx_id].phy.phy_mode.leg_oqpsk.chip_rate ==
					CHIP_RATE_1000) {
				rate *= 2;
			} else {
				rate *= 4;
			}
		}
		break;
#endif

	default:
		break;
	}

	return rate;
}