AX5043 wake-on-radio


I’m trying to implement the wake-on-radio mode on our product.

We developped the standard rx/tx mode and now we want to achieve the wor mode due to power reduction.

I generated an example using AX-radiolab and tried to implement the generated code. The reception of a packet is ok but I don’t have any interrupt generated when the packet is received in wor RX.

I checked the low power oscillator and it’s running.
I checked that the wake-up timer is running.
I checked that a wake-up interrupt is generated using polling method of IRQRWAKEUPTIMER bit.

But i’m not able to generate any wor interrupt on the IRQ pin.
The initialisation is the same as the standard RX/TX mode except that I initialyze the lpo and set the rx_on_wor mode.

Here is the the code of this two function :

uint8_t ax5043_calibrate_lpo(ax5043_handle_t *ax5043){
    uint8_t reg_val;
    uint32_t i;
    reg_val = 0x00;
    ax5043_write_reg(ax5043, AX5043_LPOSCFREQ1, &reg_val, 1);
    reg_val = 0x00;
    ax5043_write_reg(ax5043, AX5043_LPOSCFREQ0, &reg_val, 1);

    reg_val = ((ax5043->config.rf_tune_param.f_xtal / 640) >> 8) & 0xFF;
    ax5043_write_reg(ax5043, AX5043_LPOSCFREQ1, &reg_val, 1);
    reg_val = ((ax5043->config.rf_tune_param.f_xtal / 640) >> 0) & 0xFF;
    ax5043_write_reg(ax5043, AX5043_LPOSCFREQ0, &reg_val, 1);

    reg_val = AX5043_PWRSTATE_SYNTH_RX;
    ax5043_write_reg(ax5043, AX5043_PWRMODE, &reg_val, 1);

    reg_val = ((ax5043->config.lpo_param.sckfiltmax) >> (8 + 1)) & 0xFF;
    ax5043_write_reg(ax5043, AX5043_LPOSCKFILT1, &reg_val, 1);

    reg_val = (ax5043->config.lpo_param.sckfiltmax >> 1) & 0xFF;
    ax5043_write_reg(ax5043, AX5043_LPOSCKFILT1, &reg_val, 1);


    reg_val = 0x25;
    ax5043_write_reg(ax5043, AX5043_LPOSCCONFIG, &reg_val, 1);
    ax5043_wait_n_lpo_cycles(ax5043, 6);

    reg_val = ((ax5043->config.lpo_param.sckfiltmax) >> (8 + 2)) & 0xFF;
    ax5043_write_reg(ax5043, AX5043_LPOSCKFILT1, &reg_val, 1);

    reg_val = (ax5043->config.lpo_param.sckfiltmax >> 2) & 0xFF;
    ax5043_write_reg(ax5043, AX5043_LPOSCKFILT1, &reg_val, 1);

    ax5043_wait_n_lpo_cycles(ax5043, 5);

    reg_val = 0x00;
    ax5043_write_reg(ax5043, AX5043_LPOSCCONFIG, &reg_val, 1);

    reg_val = AX5043_PWRSTATE_POWERDOWN;
    ax5043_write_reg(ax5043, AX5043_PWRMODE, &reg_val, 1);


uint8_t ax5043_rx_on_wor(ax5043_handle_t *ax5043) {
    uint8_t reg_val, reg_val_2;
    uint32_t wp;

        reg_val = 0x02;
        ax5043_write_reg(ax5043, AX5043_BGNDRSSIGAIN, &reg_val, 1);

        reg_val = 0x03;
        ax5043_write_reg(ax5043, AX5043_FIFOSTAT, &reg_val, 1);

        reg_val = 0x01;
        ax5043_write_reg(ax5043, AX5043_LPOSCCONFIG, &reg_val, 1);  // start LPOSC, slow mode

        reg_val = 0x00;
        ax5043_write_reg(ax5043, AX5043_RSSIREFERENCE, &reg_val, 1);  // start LPOSC, slow mode

        reg_val = AX5043_PWRSTATE_WOR_RX;
        ax5043_write_reg(ax5043, AX5043_PWRMODE, &reg_val, 1);

        reg_val = 0x01;
        ax5043_write_reg(ax5043, AX5043_IRQMASK0, &reg_val, 1); //  enable FIFO not empty

        reg_val = 0x01;
        ax5043_write_reg(ax5043, AX5043_IRQMASK1, &reg_val, 1);

        wp = 6;
        reg_val = ((wp >> 8) & 0xFF);
        ax5043_write_reg(ax5043, AX5043_WAKEUPFREQ1, &reg_val, 1);
        reg_val = ((wp >> 0) & 0xFF);
        ax5043_write_reg(ax5043, AX5043_WAKEUPFREQ0, &reg_val, 1);

        ax5043_read_reg(ax5043, AX5043_WAKEUPTIMER1, &reg_val, 1);
        ax5043_read_reg(ax5043, AX5043_WAKEUPTIMER0, &reg_val_2, 1);
        wp += ((reg_val << 8) | reg_val_2);

        reg_val = ((wp >> 8) & 0xFF);
        ax5043_write_reg(ax5043, AX5043_WAKEUP1, &reg_val, 1);
        reg_val = ((wp >> 0) & 0xFF);
        ax5043_write_reg(ax5043, AX5043_WAKEUP0, &reg_val, 1);

//        reg_val = 0x02;
//        ax5043_write_reg(ax5043, AX5043_IRQMASK1, &reg_val, 1);
//        while(1) {
//            ax5043_read_reg(ax5043, AX5043_IRQREQUEST1, &reg_val, 1);
//            if((reg_val & (1 << 1) == (1 << 1))) {
//                break;
//            }
//        }

Can someone tell me what I’m doing wrong ?

Best Regards,


Hello Fabian, try to use longer preamble (it should be twice longer than normal RX mode.)

P\S i spent more than 1 month for try to tune parameters for stable WOR on 868 MHz, and then returned back on timeslot (time menager) solution (when base station during ACK send to “point” time wich it should be sleep and waiting for start next communication.
In my case - the “point” initiate communication, base station allways time in RX mode, and after received packet, measured time for next time-window and send short ACK with sleep time for “point”

Hi Fabian,
first of all be sure to have implemented something like what we have in config.c (check the values that your AX-RadioLab project proposes):

__reentrantb void ax5043_set_registers_rxwor(void) __reentrant
	radio_write8(AX5043_REG_TMGRXAGC,                 0x0B); //time spent settling AGC
	radio_write8(AX5043_REG_TMGRXPREAMBLE1,           0x19); //time spent looking for preamble
	radio_write8(AX5043_REG_PKTMISCFLAGS,             0x03); //time for RSSI/AGC expressed in bit clock

This time registers are important to be set as they drive the state transitions within the receiver state machine (see Figure 13 on page 19 ofAX5043 Programming Manual)

In addition, note that the IRQ line toggles depending on what IRQs you have enabled. For WOR our radio driver easyax5043.c implements the following:

__reentrantb void ax5043_receiver_on_wor(void) __reentrant
	radio_write8(AX5043_REG_BGNDRSSIGAIN, 0x02);
		radio_write8(AX5043_REG_RADIOEVENTMASK0, 0x04);
	radio_write8(AX5043_REG_FIFOSTAT, 3); // clear FIFO data & flags
	radio_write8(AX5043_REG_LPOSCCONFIG, 0x01); // start LPOSC, slow mode
	radio_write8(AX5043_REG_RSSIREFERENCE, axradio_phy_rssireference);
	radio_write8(AX5043_REG_PKTSTOREFLAGS, (radio_read8(AX5043_REG_PKTSTOREFLAGS) & (uint8_t)~0x40));

	radio_write8(AX5043_REG_PWRMODE, AX5043_PWRSTATE_WOR_RX);
	axradio_trxstate = trxstate_rxwor;
		radio_write8(AX5043_REG_IRQMASK0, 0x41); //  enable FIFO not empty / radio controller irq
		radio_write8(AX5043_REG_IRQMASK0, 0x01); //  enable FIFO not empty
#if defined __ARMEL__ || defined __ARMEB__
    // power irq needed only for AX8052F143 WOR with TCXO
	if (((PALTRADIO & 0x40) && ((radio_read8(AX5043_REG_PINFUNCPWRAMP) & 0x0F) == 0x07)) || ((PALTRADIO & 0x80) && ((radio_read8(AX5043_REG_PINFUNCANTSEL) & 0x07) == 0x04))) // pass through of TCXO_EN
		// F143_WOR_TCXO
		radio_write8(AX5043_REG_IRQMASK0, radio_read8(AX5043_REG_IRQMASK0) | 0x80); // power irq (AX8052F143 WOR with TCXO)
		radio_write8(AX5043_REG_POWIRQMASK, 0x90); // interrupt when vddana ready (AX8052F143 WOR with TCXO)
#endif // defined
	radio_write8(AX5043_REG_IRQMASK1, 0x01); // xtal ready
		uint16_t wp = axradio_wor_period;
		radio_write8(AX5043_REG_WAKEUPFREQ1, ((wp >> 8) & 0xFF));
		radio_write8(AX5043_REG_WAKEUPFREQ0, ((wp >> 0) & 0xFF)); // actually wakeup period measured in LP OSC cycles
        wp += radio_read16(AX5043_REG_WAKEUPTIMER1);
		radio_write8(AX5043_REG_WAKEUP1, ((wp >> 8) & 0xFF));
		radio_write8(AX5043_REG_WAKEUP0, ((wp >> 0) & 0xFF));

So normally you will see an IRQ when FIFO not empty (AX5043_REG_IRQMASK0, 0x01). If you are not receiving anything, you won’t see an interrupt.
If you want to see an interrupt when IRQRWAKEUPTIMER you need to set the corresponding bit in IRQMASK1:

radio_write8(AX5043_REG_IRQMASK1, radio_read8(AX5043_REG_IRQMASK1) | 0x02); 

Thanks for your support Alex and georgi.

After hours on this issue I chose to implement what is needed for my application. In my case the power consumption of the uC is much higher than the power consumption of the AX5043 in normal mode. So i chose to let the ax5043 in FULLRX and FULLTX mode and put only the uC into low power mode. To do so I enabled the FIFONOTEMPTY interrupt radio_write8(AX5043_REG_IRQMASK0, 0x01);. And it’s working well.

Again thank you and good afternoon.

Best regards,


1 Like