Exemple #1
0
/**
 * @brief Sets a TAL PIB attribute
 *
 * This function is called to set the transceiver information base
 * attributes.
 *
 * @param attribute TAL infobase attribute ID
 * @param value TAL infobase attribute value to be set
 *
 * @return MAC_UNSUPPORTED_ATTRIBUTE if the TAL info base attribute is not found
 *         TAL_BUSY if the TAL is not in TAL_IDLE state. An exception is
 *         macBeaconTxTime which can be accepted by TAL even if TAL is not
 *         in TAL_IDLE state.
 *         MAC_SUCCESS if the attempt to set the PIB attribute was successful
 *         TAL_TRX_ASLEEP if trx is in SLEEP mode and access to trx is required
 */
retval_t tal_pib_set(uint8_t attribute, pib_value_t *value)
{
    /*
     * Do not allow any changes while ED or TX is done.
     * We allow changes during RX, but it's on the user's own risk.
     */
#if (MAC_SCAN_ED_REQUEST_CONFIRM == 1)
    if (tal_state == TAL_ED_RUNNING)
    {
        ASSERT("TAL is busy" == 0);
        return TAL_BUSY;
    }
#endif /* (MAC_SCAN_ED_REQUEST_CONFIRM == 1) */

    /*
     * Distinguish between PIBs that need to be changed in trx directly
     * and those that are simple variable udpates.
     * Ensure that the transceiver is not in SLEEP.
     * If it is in SLEEP, change it to TRX_OFF.
     */

    switch (attribute)
    {
        case macMaxFrameRetries:
                    /*
                     * The new PIB value is not immediately written to the
                     * transceiver. This is done on a frame-by-frame base.
                     */
                    tal_pib_MaxFrameRetries = value->pib_value_8bit;
                    break;

        case macMaxCSMABackoffs:
                    /*
                     * The new PIB value is not immediately written to the
                     * transceiver. This is done on a frame-by-frame base.
                     */
                    tal_pib_MaxCSMABackoffs = value->pib_value_8bit;
                    break;

#ifdef BEACON_SUPPORT
        case macBattLifeExt:
            tal_pib_BattLifeExt = value->pib_value_bool;
            break;

        case macBeaconOrder:
            tal_pib_BeaconOrder = value->pib_value_8bit;
            break;

        case macSuperframeOrder:
            tal_pib_SuperFrameOrder = value->pib_value_8bit;
            break;

        case macBeaconTxTime:
            tal_pib_BeaconTxTime = value->pib_value_32bit;
            break;

#endif  /* BEACON_SUPPORT */
#ifdef PROMISCUOUS_MODE
        case macPromiscuousMode:
            tal_pib_PromiscuousMode = value->pib_value_8bit;
            if (tal_pib_PromiscuousMode)
            {
                tal_trx_wakeup();

                /* Check if receive buffer is available or queue is not full. */
                if (NULL == tal_rx_buffer)
                {
                    set_trx_state(CMD_PLL_ON);
                    tal_rx_on_required = true;
                }
                else
                {
                    set_trx_state(CMD_RX_ON);
                }
            }
            else
            {
                set_trx_state(CMD_TRX_OFF);
                tal_rx_on_required = false;
            }
            break;
#endif

        default:
            /*
             * Following PIBs require access to trx.
             * Therefore trx must be at least in TRX_OFF.
             */

            if (tal_trx_status == TRX_SLEEP)
            {
                /* While trx is in SLEEP, register cannot be accessed. */
                return TAL_TRX_ASLEEP;
            }

            switch (attribute)
            {
                case macMinBE:
                    tal_pib_MinBE = value->pib_value_8bit;

#ifndef REDUCED_PARAM_CHECK
                    /*
                     * macMinBE must not be larger than macMaxBE or calculation
                     * of macMaxFrameWaitTotalTime will fail.
                     */
                    if (tal_pib_MinBE > tal_pib_MaxBE)
                    {
                        tal_pib_MinBE = tal_pib_MaxBE;
                    }
#endif  /* REDUCED_PARAM_CHECK */

                    pal_trx_bit_write(SR_MIN_BE, tal_pib_MinBE);
                    break;

                case macPANId:
                    tal_pib_PANId = value->pib_value_16bit;
                    pal_trx_reg_write(RG_PAN_ID_0, (uint8_t)tal_pib_PANId);
                    pal_trx_reg_write(RG_PAN_ID_1, (uint8_t)(tal_pib_PANId >> 8));
                    break;

                case macShortAddress:
                    tal_pib_ShortAddress = value->pib_value_16bit;
                    pal_trx_reg_write(RG_SHORT_ADDR_0, (uint8_t)tal_pib_ShortAddress);
                    pal_trx_reg_write(RG_SHORT_ADDR_1, (uint8_t)(tal_pib_ShortAddress >> 8));
                    break;

                case phyCurrentChannel:
                    if (tal_state != TAL_IDLE)
                    {
                        return TAL_BUSY;
                    }

                    if (tal_pib_CurrentPage == 5)
                    {
                        if (((uint32_t)TRX_SUPPORTED_CHANNELS_CHINA & ((uint32_t)0x01 << value->pib_value_8bit)) == false)
                        {
                            return MAC_INVALID_PARAMETER;
                        }
                    }
                    else
                    {
                        if (((uint32_t)TRX_SUPPORTED_CHANNELS & ((uint32_t)0x01 << value->pib_value_8bit)) == false)
                        {
                            return MAC_INVALID_PARAMETER;
                        }
                    }

                    {
                        uint8_t previous_channel;
                        tal_trx_status_t previous_trx_status = TRX_OFF;

                        previous_channel = tal_pib_CurrentChannel;
                        tal_pib_CurrentChannel = value->pib_value_8bit;

                        /*
                         * Set trx to "soft" off avoiding that ongoing
                         * transaction (e.g. ACK) are interrupted.
                         */
                        if (tal_trx_status != TRX_OFF)
                        {
                            previous_trx_status = RX_AACK_ON;   /* any other than TRX_OFF state */
                            do
                            {
                                /* set TRX_OFF until it could be set;
                                 * trx might be busy */
                            } while (set_trx_state(CMD_TRX_OFF) != TRX_OFF);
                        }

                        /* Check if frequency band/modulation is changed. */
                        if (tal_pib_CurrentPage == 5)
                        {
                            pal_trx_bit_write(SR_CC_NUMBER, GET_CHINA_FREQ(tal_pib_CurrentChannel));
                        }
                        else if ((tal_pib_CurrentChannel > 0) && (previous_channel > 0))
                        {
                            pal_trx_bit_write(SR_CHANNEL, tal_pib_CurrentChannel);
                        }
                        else
                        {
                            uint8_t reg_value;

                            /* Set modulation and channel */
                            apply_channel_page_configuration(tal_pib_CurrentPage);
                            limit_tx_pwr();
                            reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
                            pal_trx_reg_write(RG_PHY_TX_PWR, reg_value);
                        }

                        /* Re-store previous trx state */
                        if (previous_trx_status != TRX_OFF)
                        {
                            /* Set to default state */
                            set_trx_state(CMD_RX_AACK_ON);
                        }
                    }
                    break;

                case phyCurrentPage:
                    if (tal_state != TAL_IDLE)
                    {
                        return TAL_BUSY;
                    }
                    else
                    {
                        uint8_t page;
                        tal_trx_status_t previous_trx_status = TRX_OFF;
                        bool ret_val;
                        uint8_t reg_value;

                        /*
                         * Changing the channel, channel page or modulation
                         * requires that TRX is in TRX_OFF.
                         * Store current trx state and return to default state
                         * after channel page has been set.
                         */
                        if (tal_trx_status != TRX_OFF)
                        {
                            previous_trx_status = RX_AACK_ON;   /* any other than TRX_OFF state */
                            do
                            {
                                /* set TRX_OFF until it could be set;
                                 * trx might be busy */
                            } while (set_trx_state(CMD_TRX_OFF) != TRX_OFF);
                        }

                        page = value->pib_value_8bit;

                        ret_val = apply_channel_page_configuration(page);

                        if (previous_trx_status != TRX_OFF)
                        {
                            /* Set to default state */
                            set_trx_state(CMD_RX_AACK_ON);
                        }

                        if (ret_val)
                        {
                            tal_pib_CurrentPage = page;
                        }
                        else
                        {
                            return MAC_INVALID_PARAMETER;
                        }
                        limit_tx_pwr();
                        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
                        pal_trx_reg_write(RG_PHY_TX_PWR, reg_value);
                    }
                    break;

                case macMaxBE:
                    tal_pib_MaxBE = value->pib_value_8bit;
#ifndef REDUCED_PARAM_CHECK
                    /*
                     * macMinBE must not be larger than macMaxBE or calculation
                     * of macMaxFrameWaitTotalTime will fail.
                     */
                    if (tal_pib_MaxBE < tal_pib_MinBE)
                    {
                        tal_pib_MinBE = tal_pib_MaxBE;
                    }
#endif  /* REDUCED_PARAM_CHECK */
                    pal_trx_bit_write(SR_MAX_BE, tal_pib_MaxBE);
                    break;

                case phyTransmitPower:
                    {
                        uint8_t reg_value;

                        tal_pib_TransmitPower = value->pib_value_8bit;

                        /* Limit tal_pib_TransmitPower to max/min trx values */
                        limit_tx_pwr();
                        reg_value = convert_phyTransmitPower_to_reg_value(tal_pib_TransmitPower);
                        pal_trx_reg_write(RG_PHY_TX_PWR, reg_value);
                    }
                    break;

                case phyCCAMode:
                    tal_pib_CCAMode = value->pib_value_8bit;
                    pal_trx_bit_write(SR_CCA_MODE, tal_pib_CCAMode);
                    break;

                case macIeeeAddress:
                    {
                        uint8_t *ptr;

                        tal_pib_IeeeAddress = value->pib_value_64bit;
                        ptr = (uint8_t *)&tal_pib_IeeeAddress;

                        for (uint8_t i = 0; i < 8; i++)
                        {
                            pal_trx_reg_write((RG_IEEE_ADDR_0 + i), *ptr);
                            ptr++;
                        }
                    }
                    break;

                case mac_i_pan_coordinator:
                    tal_pib_PrivatePanCoordinator = value->pib_value_bool;
                    pal_trx_bit_write(SR_AACK_I_AM_COORD, tal_pib_PrivatePanCoordinator);
                    break;

                case macAckWaitDuration:
                    /*
                     * AT86RF212 does not support changing this value w.r.t.
                     * compliance operation.
                     */
                    return MAC_UNSUPPORTED_ATTRIBUTE;

                default:
                    return MAC_UNSUPPORTED_ATTRIBUTE;
            }

            break; /* end of 'default' from 'switch (attribute)' */
    }
    return MAC_SUCCESS;
} /* tal_pib_set() */
Exemple #2
0
/**
 * @brief Apply channel page configuartion to transceiver
 *
 * @param ch_page Channel page
 *
 * @return true if changes could be applied else false
 */
static bool apply_channel_page_configuration(uint8_t ch_page)
{
    /*
     * Before updating the transceiver a number of TAL PIB attributes need
     * to be updated depending on the channel page.
     */
    tal_pib_MaxFrameDuration = MAX_FRAME_DURATION;
    tal_pib_SHRDuration = NO_OF_SYMBOLS_PREAMBLE_SFD;
    tal_pib_SymbolsPerOctet = SYMBOLS_PER_OCTET;

    switch (ch_page)
    {
        case 0: /* BPSK */
            pal_trx_bit_write(SR_BPSK_OQPSK, BPSK_MODE);
            pal_trx_bit_write(SR_GC_TX_OFFS, BPSK_TX_OFFSET);
            if (tal_pib_CurrentChannel == 0)
            {
                pal_trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
            }
            else
            {
                pal_trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
                pal_trx_bit_write(SR_OQPSK_SUB1_RC_EN, HALF_SINE_FILTERING);
            }
            // Compliant ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, AACK_ACK_TIME_12_SYMBOLS);
            tal_pib_SupportedChannels = TRX_SUPPORTED_CHANNELS;
            pal_trx_bit_write(SR_CC_BAND, 0);
            pal_trx_bit_write(SR_CHANNEL, tal_pib_CurrentChannel);
            break;

        case 2: /* O-QPSK */
            pal_trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
            pal_trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_100_KBPS_OR_250_KBPS);
            if (tal_pib_CurrentChannel == 0)
            {
                pal_trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
            }
            else
            {
                pal_trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
                pal_trx_bit_write(SR_OQPSK_SUB1_RC_EN, HALF_SINE_FILTERING);
            }
            // Compliant ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, AACK_ACK_TIME_12_SYMBOLS);
            tal_pib_SupportedChannels = TRX_SUPPORTED_CHANNELS;
            pal_trx_bit_write(SR_CC_BAND, 0);
            pal_trx_bit_write(SR_CHANNEL, tal_pib_CurrentChannel);
            break;

        case 5: /* CHINESE_BAND, O-QPSK */
            pal_trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
            pal_trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_100_KBPS_OR_250_KBPS);
            pal_trx_bit_write(SR_OQPSK_SUB1_RC_EN, RC_0_8_FILTERING);
            pal_trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
            // Compliant ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, AACK_ACK_TIME_12_SYMBOLS);
            tal_pib_SupportedChannels = TRX_SUPPORTED_CHANNELS_CHINA;
            /* Channel Page 5 supports channels 0-3. */
            if (tal_pib_CurrentChannel > 3)
            {
                tal_pib_CurrentChannel = 0;
            }
            pal_trx_bit_write(SR_CC_BAND, 4);
            pal_trx_bit_write(SR_CC_NUMBER, GET_CHINA_FREQ(tal_pib_CurrentChannel));
            break;

#ifdef HIGH_DATA_RATE_SUPPORT
        case 16:    /* non-compliant OQPSK mode 1 */
            pal_trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
            pal_trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_200_KBPS_OR_500_KBPS);
            if (tal_pib_CurrentChannel == 0)
            {
                pal_trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
            }
            else
            {
                pal_trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
                pal_trx_bit_write(SR_OQPSK_SUB1_RC_EN, HALF_SINE_FILTERING);
            }
            // Reduced ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, AACK_ACK_TIME_2_SYMBOLS);
            tal_pib_SupportedChannels = TRX_SUPPORTED_CHANNELS;
            pal_trx_bit_write(SR_CC_BAND, 0);
            pal_trx_bit_write(SR_CHANNEL, tal_pib_CurrentChannel);
            break;

        case 17:    /* non-compliant OQPSK mode 2 */
            pal_trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
            pal_trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_400_KBPS_OR_1_MBPS);
            if (tal_pib_CurrentChannel == 0)
            {
                pal_trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
            }
            else
            {
                pal_trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
                pal_trx_bit_write(SR_OQPSK_SUB1_RC_EN, HALF_SINE_FILTERING);
            }
            // Reduced ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, AACK_ACK_TIME_2_SYMBOLS);
            tal_pib_SupportedChannels = TRX_SUPPORTED_CHANNELS;
            pal_trx_bit_write(SR_CC_BAND, 0);
            pal_trx_bit_write(SR_CHANNEL, tal_pib_CurrentChannel);
            break;

        case 18:    /* Chinese band, non-compliant mode 1 using O-QPSK 500 */
            pal_trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
            pal_trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_200_KBPS_OR_500_KBPS);
            pal_trx_bit_write(SR_OQPSK_SUB1_RC_EN, RC_0_8_FILTERING);
            pal_trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
            // Reduced ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, AACK_ACK_TIME_2_SYMBOLS);
            tal_pib_SupportedChannels = TRX_SUPPORTED_CHANNELS_CHINA;
            /* Channel Page 18 supports channels 0-3. */
            if (tal_pib_CurrentChannel > 3)
            {
                tal_pib_CurrentChannel = 0;
            }
            pal_trx_bit_write(SR_CC_BAND, 4);
            pal_trx_bit_write(SR_CC_NUMBER, GET_CHINA_FREQ(tal_pib_CurrentChannel));
            break;

        case 19:    /* Chinese band, non-compliant mode 2 using O-QPSK 1000 */
            pal_trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
            pal_trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
            pal_trx_bit_write(SR_OQPSK_DATA_RATE, ALTRATE_400_KBPS_OR_1_MBPS);
            pal_trx_bit_write(SR_OQPSK_SUB1_RC_EN, RC_0_8_FILTERING);
            pal_trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
            // Reduced ACK timing
            pal_trx_bit_write(SR_AACK_ACK_TIME, AACK_ACK_TIME_2_SYMBOLS);
            tal_pib_SupportedChannels = TRX_SUPPORTED_CHANNELS_CHINA;
            /* Channel Page 18 supports channels 0-3. */
            if (tal_pib_CurrentChannel > 3)
            {
                tal_pib_CurrentChannel = 0;
            }
            pal_trx_bit_write(SR_CC_BAND, 4);
            pal_trx_bit_write(SR_CC_NUMBER, GET_CHINA_FREQ(tal_pib_CurrentChannel));
            break;
#endif  /* #ifdef HIGH_DATA_RATE_SUPPORT */
            default:
                return false;
    }

    return true;
}
Exemple #3
0
/**
 * \brief Apply channel page configuartion to transceiver
 *
 * \param ch_page Channel page
 *
 * \return true if changes could be applied else false
 */
static bool apply_channel_page_configuration(uint8_t ch_page)
{
	/*
	 * Before updating the transceiver a number of TAL PIB attributes need
	 * to be updated depending on the channel page.
	 */
	/* \todo these configurations are not rate dependent here! But shall be!
	 **/
	tal_pib.MaxFrameDuration = MAX_FRAME_DURATION;
	tal_pib.SHRDuration = NO_OF_SYMBOLS_PREAMBLE_SFD;
	tal_pib.SymbolsPerOctet = SYMBOLS_PER_OCTET;

	switch (ch_page) {
	case 0: /* BPSK */
		trx_bit_write(SR_BPSK_OQPSK, BPSK_MODE);
		trx_bit_write(SR_GC_TX_OFFS, BPSK_TX_OFFSET);
		trx_bit_write(SR_ALT_SPECTRUM, ALT_SPECTRUM_DISABLE);
		if (tal_pib.CurrentChannel == 0) { /* BPSK20, EU */
			trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
		} else { /* BPSK40, NA */
			trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
		}

		/* Compliant ACK timing */
		trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_12_SYMBOLS);
		tal_pib.SupportedChannels = TRX_SUPPORTED_CHANNELS;
		trx_bit_write(SR_CC_BAND, 0);
		trx_bit_write(SR_CHANNEL, tal_pib.CurrentChannel);
		break;

	case 2: /* O-QPSK */
		trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
		trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
		trx_bit_write(SR_OQPSK_DATA_RATE,
				ALTRATE_100_KBPS_OR_250_KBPS);
		trx_bit_write(SR_ALT_SPECTRUM, ALT_SPECTRUM_DISABLE);
		if (tal_pib.CurrentChannel == 0) { /* OQPSK100, EU */
			trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
		} else { /* OQPSK250, NA */
			trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
		}

		/* Compliant ACK timing */
		trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_12_SYMBOLS);
		tal_pib.SupportedChannels = TRX_SUPPORTED_CHANNELS;
		trx_bit_write(SR_CC_BAND, 0);
		trx_bit_write(SR_CHANNEL, tal_pib.CurrentChannel);
		break;

	case 5: /* CHINESE_BAND, O-QPSK */
		trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
		trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
		trx_bit_write(SR_OQPSK_DATA_RATE,
				ALTRATE_100_KBPS_OR_250_KBPS);
		trx_bit_write(SR_ALT_SPECTRUM, ALT_SPECTRUM_ENABLE);
		trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
		/* Compliant ACK timing */
		trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_12_SYMBOLS);
		tal_pib.SupportedChannels = TRX_SUPPORTED_CHANNELS_CHINA;
		/* Channel Page 5 supports channels 0-3. */
		if (tal_pib.CurrentChannel > 3) {
			tal_pib.CurrentChannel = 0;
		}

		trx_bit_write(SR_CC_BAND, 4);
		trx_bit_write(SR_CC_NUMBER,
				GET_CHINA_FREQ(tal_pib.CurrentChannel));

		break;

#ifdef HIGH_DATA_RATE_SUPPORT
	case 16:    /* non-compliant OQPSK mode 1 */
		trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
		trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
		trx_bit_write(SR_ALT_SPECTRUM, ALT_SPECTRUM_DISABLE);
		trx_bit_write(SR_OQPSK_DATA_RATE,
				ALTRATE_200_KBPS_OR_500_KBPS);
		if (tal_pib.CurrentChannel == 0) { /* 200kbps, EU */
			trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
		} else { /* 500kbps, NA */
			trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
		}

		/* Reduced ACK timing */
		trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_2_SYMBOLS);
		tal_pib.SupportedChannels = TRX_SUPPORTED_CHANNELS;
		trx_bit_write(SR_CC_BAND, 0);
		trx_bit_write(SR_CHANNEL, tal_pib.CurrentChannel);
		break;

	case 17:    /* non-compliant OQPSK mode 2 */
		trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
		trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
		trx_bit_write(SR_ALT_SPECTRUM, ALT_SPECTRUM_DISABLE);
		trx_bit_write(SR_OQPSK_DATA_RATE,
				ALTRATE_400_KBPS_OR_1_MBPS);
		if (tal_pib.CurrentChannel == 0) { /* 400kbps, EU */
			trx_bit_write(SR_SUB_MODE, LOW_DATA_RATE);
		} else { /* 1000kbps, NA */
			trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
		}

		/* Reduced ACK timing */
		trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_2_SYMBOLS);
		tal_pib.SupportedChannels = TRX_SUPPORTED_CHANNELS;
		trx_bit_write(SR_CC_BAND, 0);
		trx_bit_write(SR_CHANNEL, tal_pib.CurrentChannel);
		break;

	case 18:    /* Chinese band, non-compliant mode 1 using O-QPSK 500 */
		trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
		trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
		trx_bit_write(SR_OQPSK_DATA_RATE,
				ALTRATE_200_KBPS_OR_500_KBPS);
		trx_bit_write(SR_ALT_SPECTRUM, ALT_SPECTRUM_ENABLE);
		trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
		/* Reduced ACK timing */
		trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_2_SYMBOLS);
		tal_pib.SupportedChannels = TRX_SUPPORTED_CHANNELS_CHINA;
		/* Channel Page 18 supports channels 0-3. */
		if (tal_pib.CurrentChannel > 3) {
			tal_pib.CurrentChannel = 0;
		}

		trx_bit_write(SR_CC_BAND, 4);
		trx_bit_write(SR_CC_NUMBER,
				GET_CHINA_FREQ(tal_pib.CurrentChannel));
		break;

	case 19:    /* Chinese band, non-compliant mode 2 using O-QPSK 1000 */
		trx_bit_write(SR_BPSK_OQPSK, OQPSK_MODE);
		trx_bit_write(SR_GC_TX_OFFS, OQPSK_TX_OFFSET);
		trx_bit_write(SR_OQPSK_DATA_RATE,
				ALTRATE_400_KBPS_OR_1_MBPS);
		trx_bit_write(SR_ALT_SPECTRUM, ALT_SPECTRUM_ENABLE);
		trx_bit_write(SR_SUB_MODE, HIGH_DATA_RATE);
		/* Reduced ACK timing */
		trx_bit_write(SR_AACK_ACK_TIME, ACK_TIME_2_SYMBOLS);
		tal_pib.SupportedChannels = TRX_SUPPORTED_CHANNELS_CHINA;
		/* Channel Page 18 supports channels 0-3. */
		if (tal_pib.CurrentChannel > 3) {
			tal_pib.CurrentChannel = 0;
		}

		trx_bit_write(SR_CC_BAND, 4);
		trx_bit_write(SR_CC_NUMBER,
				GET_CHINA_FREQ(tal_pib.CurrentChannel));
		break;

#endif  /* #ifdef HIGH_DATA_RATE_SUPPORT */
	default:
		return false;
	}

	return true;
}