示例#1
0
/**
 ****************************************************************************************
 * @brief Read single series of bytes from I2C EEPROM (for driver's internal use)
 *
 * @param[in] p    Memory address to read the series of bytes from (all in the same page)
 * @param[in] size count of bytes to read (must not cross page)
 ****************************************************************************************
 */
static void read_data_single(uint8_t **p, uint32_t address, uint32_t size)
{
    int j;
    
    i2c_send_address(address);
                
    for (j = 0; j < size; j++)
    {    
        WAIT_WHILE_I2C_FIFO_IS_FULL();              // Wait if Tx FIFO is full
        SEND_I2C_COMMAND(0x0100);                   // Set read access for <size> times
    }
    
    // Critical section
    GLOBAL_INT_DISABLE();
    
    // Get the received data
    for (j = 0; j < size; j++)                                         
    {
        WAIT_FOR_RECEIVED_BYTE();                   // Wait for received data
        **p =(0xFF & GetWord16(I2C_DATA_CMD_REG));  // Get the received byte
        (*p)++;
    }
    // End of critical section
    GLOBAL_INT_RESTORE();
}
示例#2
0
void hw_fem_stop(void)
{
    GLOBAL_INT_DISABLE();
    fem_config.started = false;

    /* Stop DCF Timers */
#if dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A
    RFCU_POWER->RF_PORT_EN_REG = 0x0;
#else
    RFCU_POWER->RF_PORT_EN_BLE_REG = 0x0;
    RFCU_POWER->RF_PORT_EN_FTDF_REG = 0x0;
#endif

    /* Set all FEM interface outputs to GPIO mode, and value 0, in order to get the minimum
     * possible power consumption from FEM
     */
#if defined(dg_configFEM_SKY66112_11_CSD_PORT) && defined(dg_configFEM_SKY66112_11_CSD_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CSD_PORT, dg_configFEM_SKY66112_11_CSD_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif

    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CTX_PORT, dg_configFEM_SKY66112_11_CTX_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);

#if defined(dg_configFEM_SKY66112_11_CHL_PORT) && defined(dg_configFEM_SKY66112_11_CHL_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CHL_PORT, dg_configFEM_SKY66112_11_CHL_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif

    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CRX_PORT, dg_configFEM_SKY66112_11_CRX_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);

#if defined(dg_configFEM_SKY66112_11_CPS_PORT) && defined(dg_configFEM_SKY66112_11_CPS_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CPS_PORT, dg_configFEM_SKY66112_11_CPS_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif

#if defined(dg_configFEM_SKY66112_11_ANTSEL_PORT) && defined(dg_configFEM_SKY66112_11_ANTSEL_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANTSEL_PORT, dg_configFEM_SKY66112_11_ANTSEL_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif

#if defined(dg_configFEM_SKY66112_11_ANT_TRIM_0_PORT) && defined(dg_configFEM_SKY66112_11_ANT_TRIM_0_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANT_TRIM_0_PORT, dg_configFEM_SKY66112_11_ANT_TRIM_0_PORT,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif

#if defined(dg_configFEM_SKY66112_11_ANT_TRIM_1_PORT) && defined(dg_configFEM_SKY66112_11_ANT_TRIM_1_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANT_TRIM_1_PORT, dg_configFEM_SKY66112_11_ANT_TRIM_1_PORT,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif

#if defined(dg_configFEM_SKY66112_11_ANT_TRIM_2_PORT) && defined(dg_configFEM_SKY66112_11_ANT_TRIM_2_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANT_TRIM_2_PORT, dg_configFEM_SKY66112_11_ANT_TRIM_2_PORT,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
#endif

    GLOBAL_INT_RESTORE();
}
示例#3
0
void hw_fem_set_txpower_ftdf(bool high)
{
#if defined(dg_configFEM_SKY66112_11_CHL_PORT) && defined(dg_configFEM_SKY66112_11_CHL_PIN)
    GLOBAL_INT_DISABLE();
    fem_config.tx_power_ftdf = high;
    set_txpower();
    GLOBAL_INT_RESTORE();
#endif
}
示例#4
0
void hw_aes_hash_disable(const bool waitOnFinish)
{
        if (waitOnFinish)
                hw_aes_hash_wait_on_inactive();

        REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN);
        GLOBAL_INT_DISABLE();
        REG_CLR_BIT(CRG_TOP, CLK_AMBA_REG, AES_CLK_ENABLE);
        GLOBAL_INT_RESTORE();
        NVIC_DisableIRQ(CRYPTO_IRQn);
}
示例#5
0
void hw_aes_hash_disable(const bool waitOnFinish)
{
        if (waitOnFinish)
                hw_aes_hash_wait_on_inactive();

        hw_aes_hash_disable_interrupt_source();
        AES_HASH->CRYPTO_CLRIRQ_REG = 1;
        GLOBAL_INT_DISABLE();
        REG_CLR_BIT(CRG_TOP, CLK_AMBA_REG, AES_CLK_ENABLE);
        GLOBAL_INT_RESTORE();
        REG_CLR_BIT(AES_HASH, CRYPTO_CTRL_REG, CRYPTO_MORE_IN);
}
示例#6
0
void hw_trng_enable(hw_trng_cb callback)
{
    if (callback != NULL)
    {
        trng_cb = callback;
        hw_trng_clear_pending();
        NVIC_EnableIRQ(TRNG_IRQn);
    }

    GLOBAL_INT_DISABLE();
    REG_SET_BIT(CRG_TOP, CLK_AMBA_REG, TRNG_CLK_ENABLE);
    GLOBAL_INT_RESTORE();
    REG_SET_BIT(TRNG, TRNG_CTRL_REG, TRNG_ENABLE);
}
示例#7
0
void hw_fem_set_rx_bypass_ftdf(bool enable)
{
#if defined(dg_configFEM_SKY66112_11_CPS_PORT) && defined(dg_configFEM_SKY66112_11_CPS_PIN)
    GLOBAL_INT_DISABLE();
    fem_config.rx_bypass_ftdf = enable;

    if (fem_config.started)
    {
        set_bypass();
    }

    GLOBAL_INT_RESTORE();
#endif
}
示例#8
0
void hw_fem_set_antenna(bool one)
{
#if defined(dg_configFEM_SKY66112_11_ANTSEL_PORT) && defined(dg_configFEM_SKY66112_11_ANTSEL_PIN)
    GLOBAL_INT_DISABLE();
    fem_config.antsel = one;

    if (fem_config.started)
    {
        /* Antenna selection */
        hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANTSEL_PORT,
                              dg_configFEM_SKY66112_11_ANTSEL_PIN,
                              HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, fem_config.antsel);
    }

    GLOBAL_INT_RESTORE();
#endif
}
示例#9
0
void hw_timer0_init(const timer0_config *cfg)
{
        /* Enable clock for peripheral */
        GLOBAL_INT_DISABLE();
        uint32_t clk_tmr_reg = CRG_TOP->CLK_TMR_REG;
        clk_tmr_reg &= ~CRG_TOP_CLK_TMR_REG_TMR0_DIV_Msk;
        clk_tmr_reg &= ~CRG_TOP_CLK_TMR_REG_TMR0_CLK_SEL_Msk;
        clk_tmr_reg |= CRG_TOP_CLK_TMR_REG_TMR0_ENABLE_Msk;
        CRG_TOP->CLK_TMR_REG = clk_tmr_reg ;
        GLOBAL_INT_RESTORE();

        /* Reset control register, i.e. disable timer */
        GP_TIMERS->TIMER0_CTRL_REG = 0x0;

        /* Disable NVIC interrupt */
        NVIC_DisableIRQ(SWTIM0_IRQn);

        intr_cb = NULL;

        hw_timer0_configure(cfg);
}
示例#10
0
/**
 ****************************************************************************************
 * @brief Writes page to I2C EEPROM.
 *
 * @param[in] address         Starting address of memory page.
 * @param[in] wr_data_ptr     Pointer to the first of bytes to be written.
 * @param[in] size            Size of the data to be written (MUST BE LESS OR EQUAL TO I2C_EEPROM_PAGE).
 *
 * @return                    Count of bytes that were actually written
 ****************************************************************************************
 */
uint16_t i2c_eeprom_write_page(uint8_t *wr_data_ptr, uint32_t address, uint16_t size)
{
	uint16_t feasible_size;
    uint16_t bytes_written = 0;

    if (address < I2C_EEPROM_SIZE)
    {
        // max possible write size without crossing page boundary
        feasible_size = I2C_EEPROM_PAGE - (address % I2C_EEPROM_PAGE);
        
        if (size < feasible_size)                                                                    
            feasible_size = size;                   // adjust limit accordingly
        
        i2c_wait_until_eeprom_ready();
        
        // Critical section
        GLOBAL_INT_DISABLE();
        
        i2c_send_address(address);
        
        do
        {
            WAIT_WHILE_I2C_FIFO_IS_FULL();          // Wait if I2c Tx FIFO is full
            SEND_I2C_COMMAND(*wr_data_ptr & 0xFF);  // Send write data
            wr_data_ptr++;
            feasible_size--;
            bytes_written++;
        } 
        while (feasible_size != 0);

        // End of critical section
        GLOBAL_INT_RESTORE();
        
        WAIT_UNTIL_I2C_FIFO_IS_EMPTY();             // Wait until Tx FIFO is empty
        WAIT_UNTIL_NO_MASTER_ACTIVITY();            // Wait until no master activity
    }
    
    return bytes_written;
}
示例#11
0
void hw_i2c_init(HW_I2C_ID id, const i2c_config *cfg)
{
        IRQn_Type irq_type = I2C_IRQn;
        int enable_loop_cnt = 0;

        if (id == HW_I2C2) {
                irq_type = I2C2_IRQn;
        }
        else if (id != HW_I2C1) {
                /* Requested ID must be one of HW_I2C1 or HW_I2C2 */
                ASSERT_ERROR(0);
        }

        struct i2c *i2c = get_i2c(id);

        memset(i2c, 0, sizeof(*i2c));

        GLOBAL_INT_DISABLE();
        uint32_t clk_per_reg_local = CRG_PER->CLK_PER_REG;
        REG_SET_FIELD(CRG_PER, CLK_PER_REG, I2C_CLK_SEL, clk_per_reg_local, 0);
        REG_SET_FIELD(CRG_PER, CLK_PER_REG, I2C_ENABLE, clk_per_reg_local, 1);
        CRG_PER->CLK_PER_REG = clk_per_reg_local;
        GLOBAL_INT_RESTORE();

        hw_i2c_disable(id);
        while (hw_i2c_get_enable_status(id) & I2C_I2C_ENABLE_STATUS_REG_IC_EN_Msk) {
                hw_cpm_delay_usec(500);
                enable_loop_cnt++;
                /* we shouldn't get stuck here, the HW I2C block should eventually be enabled */
                ASSERT_ERROR(enable_loop_cnt < I2C_ENABLE_LOOP_LIMIT);
        }

        IBA(id)->I2C_INTR_MASK_REG = 0x0000;

        hw_i2c_configure(id, cfg);

        NVIC_EnableIRQ(irq_type);
}
示例#12
0
static __RETAINED_CODE void configure_cache(void)
{
    bool flush = false;

    GLOBAL_INT_DISABLE();

    if (dg_configCACHEABLE_QSPI_AREA_LEN != -1)
    {
        uint32_t cache_len;

        /* dg_configCACHEABLE_QSPI_AREA_LEN must be 64KB-aligned */
        ASSERT_WARNING((dg_configCACHEABLE_QSPI_AREA_LEN & 0xFFFF) == 0);
        /*
         * dg_configCACHEABLE_QSPI_AREA_LEN shouldn't set any bits that do not fit in
         * CACHE_CTRL2_REG.CACHE_LEN (9 bits wide) after shifting out the lower 16 bits
         */
        ASSERT_WARNING((dg_configCACHEABLE_QSPI_AREA_LEN & 0x1FF0000)
                       == dg_configCACHEABLE_QSPI_AREA_LEN);
        /*
         * set cacheable area
         *
         * setting CACHE_CTRL2_REG.CACHE_LEN to N, actually sets the size of the cacheable
         * area to (N + 1) * 64KB
         * special cases:
         *  N == 0 --> no caching
         *  N == 1 --> 128KB are cached, i.e. no way to cache only 64KB
         */
        cache_len = dg_configCACHEABLE_QSPI_AREA_LEN >> 16;
        /* cannot cache only 64KB! */
        ASSERT_WARNING(cache_len != 1);

        if (cache_len > 1)
        {
            cache_len--;
        }

        REG_SETF(CACHE, CACHE_CTRL2_REG, CACHE_LEN, cache_len);
    }
示例#13
0
void hw_fem_set_txpower(bool high)
{
#if defined(dg_configFEM_SKY66112_11_CHL_PORT) && defined(dg_configFEM_SKY66112_11_CHL_PIN)
    GLOBAL_INT_DISABLE();
    fem_config.tx_power = high;

    if (fem_config.started)
    {
        if (high == false)
        {
            /* TX Power low. Stop DCF, set GPIO to low */
            hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CHL_PORT,
                                  dg_configFEM_SKY66112_11_CHL_PIN,
                                  HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, false);
            REG_SET_MASKED(RFCU_POWER, RF_PORT_EN_REG,
                           RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_RX_Msk |
                           RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_TX_Msk, 0);

        }
        else
        {
            /* TX Power high. Configure GPIO for DCF. Enable DCF on TX. */
            hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CHL_PORT,
                                     dg_configFEM_SKY66112_11_CHL_PIN,
                                     HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT4_DCF);
            REG_SET_MASKED(RFCU_POWER, RF_PORT_EN_REG,
                           RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_RX_Msk |
                           RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_TX_Msk,
                           RFCU_POWER_RF_PORT_EN_REG_RF_PORT4_TX_Msk);

        }
    }

    GLOBAL_INT_RESTORE();
#endif
}
示例#14
0
/**
 ****************************************************************************************
 * @brief  Enable sleep mode
 * @param[in]    mode           sleep mode
 * @param[in]    iconfig        wakeup interrupt config
 * @param[in]    callback       callback after wakeup
 * @description
 *  This function is used to set MCU into sleep mode, before enter sleep, wakeup source should be set.
 *****************************************************************************************
 */
void enter_sleep(enum SLEEP_MODE mode, uint32_t iconfig, void (*callback)(void))
{
    if (mode == SLEEP_CPU_CLK_OFF) {
        // --------------------------------------------
        // cpu clock disable
        // --------------------------------------------

        // Ensure we use deep SLEEP - SLEEPDEEP should be set
        // SCR[2] = SLEEPDEEP
        SCB->SCR |= (1UL << 2);
        // set pd state to deep gating
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_PMUENABLE, MASK_DISABLE);

        GLOBAL_INT_DISABLE();
#if SLEEP_CONFIG_EN == TRUE
        NVIC->ISER[0] = iconfig;
#endif
        // Wait For Interrupt
        __WFI();  // Enter sleep mode

        // Wakeup when interrupt is triggered
        GLOBAL_INT_RESTORE();

        // TODO
    }
    else if ((mode == SLEEP_NORMAL) || (mode == SLEEP_DEEP)) {
        
#if QN_LOW_POWER_MODE_EN==TRUE
        enter_low_power_mode(0);

        // --------------------------------------------
        // cpu clock disable
        // --------------------------------------------

        // Ensure we use deep SLEEP - SLEEPDEEP should be set
        // SCR[2] = SLEEPDEEP
        SCB->SCR |= (1UL << 2);

#else
        
        // --------------------------------------------
        // sleep or deep sleep
        // --------------------------------------------
#ifdef BLE_PRJ
        // Save configuration before power down
        save_ble_setting();
#endif

#if (defined(QN_9020_B1) && QN_PMU_VOLTAGE)
        // Switch off REF PLL power
        syscon_SetPGCR1WithMask(QN_SYSCON, SYSCON_MASK_DIS_REF_PLL, MASK_ENABLE);
#endif
        
        // switch to internal 20MHz
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_CLK_MUX, CLK_INT_20M<<SYSCON_POS_CLK_MUX);

        if(mode == SLEEP_NORMAL)
        {
#if (QN_DEEP_SLEEP_EN)
            sleep_env.deep_sleep = false;
#endif
            // power down all module in sleep except 32K and retention memory
            syscon_SetPGCR0WithMask(QN_SYSCON, sleep_env.retention_modules|0x00000001, 0x00000001);
        }
        else
        {
#if (QN_DEEP_SLEEP_EN)
            sleep_env.deep_sleep = true;
#endif
            // power down all module in deep sleep except retention memory
#if (defined(QN_9020_B2) || defined(QN_9020_B1))
            syscon_SetPGCR0WithMask(QN_SYSCON, 0xF7FFFCFF, 0xFFFFFC01|~sleep_env.retention_modules);
#elif defined(QN_9020_B0)
            syscon_SetPGCR0WithMask(QN_SYSCON, 0xFFFFFCFF, 0xFFFFFC01|~sleep_env.retention_modules);
#endif
        }

#if (defined(QN_9020_B0) && QN_PMU_VOLTAGE)
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_AHB_DIV_BYPASS|SYSCON_MASK_AHB_DIVIDER, 
                                              (0xf<<SYSCON_POS_AHB_DIVIDER));
#endif

        // Ensure we use deep SLEEP - SLEEPDEEP should be set
        // SCR[2] = SLEEPDEEP
        SCB->SCR |= (1UL << 2);
        // set pd state to sleep
#if !QN_PMU_VOLTAGE
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_DVDD12_PMU_SET|SYSCON_MASK_PMUENABLE, MASK_ENABLE);
#else
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_PMUENABLE, MASK_ENABLE);
#endif

        syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_VREG12_A|SYSCON_MASK_VREG12_D|SYSCON_MASK_DVDD12_SW_EN, 
                                              (0x0 << SYSCON_POS_VREG12_A)|(0x0 << SYSCON_POS_VREG12_D));

#endif // QN_LOW_POWER_MODE_EN==TRUE

#if SLEEP_CONFIG_EN == TRUE
        NVIC->ICPR[0] = 0x00000020;  // clear OSC_EN pending flag
        NVIC->ISER[0] = iconfig;
#endif
        // Wait For Interrupt
        __WFI();  // Enter sleep mode
        // Wakeup when sleep timer, comparator or gpio is triggered

        // Disable interrupt in the wakeup procedure.
        NVIC->ICER[0] = iconfig;

#if QN_LOW_POWER_MODE_EN==TRUE
#ifdef BLE_PRJ
        restore_from_low_power_mode(NULL);
#else
        restore_from_low_power_mode(callback);
#endif
#else

        // 1.2V
        syscon_SetIvrefX32WithMask(QN_SYSCON, SYSCON_MASK_VREG12_A|SYSCON_MASK_VREG12_D|SYSCON_MASK_DVDD12_SW_EN, 
                                              (0x1 << SYSCON_POS_VREG12_A)|(0x0 << SYSCON_POS_VREG12_D)|SYSCON_MASK_DVDD12_SW_EN);

#if (defined(QN_9020_B0) && QN_PMU_VOLTAGE)
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_AHB_DIV_BYPASS, MASK_ENABLE);
#endif
        syscon_SetPGCR2WithMask(QN_SYSCON, SYSCON_MASK_PD_STATE|SYSCON_MASK_DVDD12_PMU_SET, MASK_DISABLE);

#if SLEEP_CALLBACK_EN == TRUE
        if (callback != NULL) {
            callback();
        }
#endif

#if (defined(QN_9020_B0) && QN_PMU_VOLTAGE)
        syscon_set_ahb_clk(__AHB_CLK);
#endif

        // 16MHz/32MHz XTAL is ready
        while (!(syscon_GetBLESR(QN_SYSCON) & SYSCON_MASK_CLK_RDY))
        {
            // XTAL shall be ready before BLE wakeup
            if(check_ble_wakeup())
            {
                // In this case XTAL wakeup duration is larger than setting.
                // The parameter 'Oscillator wake-up time' in the NVDS should be revised.
#if (QN_DBG_INFO)
                set_dbg_info(QN_DBG_INFO_XTAL_WAKEUP_DURATION);
#endif
            }
        }
        syscon_SetCMDCRWithMask(QN_SYSCON, SYSCON_MASK_CLK_MUX, CLK_XTAL<<SYSCON_POS_CLK_MUX);

#endif // QN_LOW_POWER_MODE_EN==TRUE

#if ((defined(QN_9020_B2) || defined(QN_9020_B1)) && defined(BLE_PRJ))
        sleep_post_process();
#endif
    }
}
void fsm_scan_update(void)
{
    switch(current_scan_state) {
    case KEY_SCAN_INACTIVE:
        if (DEVELOPMENT_DEBUG && (systick_hit || wkup_hit)) {
            ASSERT_ERROR(0);
        }

        if (HAS_DELAYED_WAKEUP) {
            app_kbd_enable_delayed_scanning(true);
        } else {
            app_kbd_enable_scanning();
        }
        current_scan_state = KEY_SCAN_IDLE;     // Transition from KEY_SCAN_INACTIVE -> KEY_SCAN_IDLE
        break;
    case KEY_SCAN_IDLE:
        if (DEVELOPMENT_DEBUG && systick_hit) {
            ASSERT_ERROR(0);
        }

        if (wkup_hit) {
        //	dbg_puts(DBG_SCAN_LVL, "KEY_SCAN_IDLE -> Wakeup! -> KEY_SCANNING\r\n");
            scanning_substate = 0;
            GLOBAL_INT_DISABLE();
            current_scan_state = KEY_SCANNING;              // Transition from KEY_SCAN_IDLE -> KEY_SCANNING
            app_kbd_start_scanning();
            wkup_hit = false;                                   
            GLOBAL_INT_RESTORE();
        }
        break;
    case KEY_STATUS_UPD:
        if (DEVELOPMENT_DEBUG && wkup_hit) {
            ASSERT_ERROR(0);
        }

        if (systick_hit) {
            systick_hit = false;
            if (app_kbd_update_status()) {
                scanning_substate = 0;
                current_scan_state = KEY_SCANNING;          // Transition from KEY_STATUS_UPD -> KEY_SCANNING
                // scan once to save time!
                if (app_kbd_scan_matrix(&scanning_substate)) {
                    current_scan_state = KEY_STATUS_UPD;    // Transition from KEY_SCANNING -> KEY_STATUS_UPD
                }
            } else {
                GLOBAL_INT_DISABLE();
                app_kbd_enable_scanning();
                current_scan_state = KEY_SCAN_IDLE;         // Transition from KEY_STATUS_UPD -> KEY_SCAN_IDLE
                GLOBAL_INT_RESTORE();
            }
        }
        break;
    case KEY_SCANNING:
        if (DEVELOPMENT_DEBUG && wkup_hit) {
            ASSERT_ERROR(0);
        }

        if (systick_hit) {
            systick_hit = false;
            if (app_kbd_scan_matrix(&scanning_substate)) {
                current_scan_state = KEY_STATUS_UPD;        // Transition from KEY_SCANNING -> KEY_STATUS_UPD
            } // else the state remains unchanged and next time we will scan the next row
        }
        break;
    default:
            break;
    }
}
示例#16
0
void hw_fem_start(void)
{
    GLOBAL_INT_DISABLE();
    fem_config.started = true;

    uint8_t set_delay;
    uint8_t reset_delay;
    uint16_t rf_port_en;

    /******************************************************
     * Setup GPIOs
     */

    /* CSD GPIO Config */
#if defined(dg_configFEM_SKY66112_11_CSD_PORT) && defined(dg_configFEM_SKY66112_11_CSD_PIN)
# if dg_configFEM_SKY66112_11_CSD_USE_DCF == 0
    /* Manually set CSD (Enable FEM) */
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_CSD_PORT, dg_configFEM_SKY66112_11_CSD_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, true);
# else
    /* Use DCF for CSD */
    hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CSD_PORT, dg_configFEM_SKY66112_11_CSD_PIN,
                             HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT2_DCF);
# endif
#endif

    /* Timer 27 GPIO (DCF Port 0). Used for TX EN */
    hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CTX_PORT, dg_configFEM_SKY66112_11_CTX_PIN,
                             HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT0_DCF);

    /* Timer 28 (DCF Port 1). Used for RX EN */
    hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_CRX_PORT, dg_configFEM_SKY66112_11_CRX_PIN,
                             HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_PORT1_DCF);

    /* Antenna selection */
#if defined(dg_configFEM_SKY66112_11_ANTSEL_PORT) && defined(dg_configFEM_SKY66112_11_ANTSEL_PIN)
    hw_gpio_configure_pin(dg_configFEM_SKY66112_11_ANTSEL_PORT, dg_configFEM_SKY66112_11_ANTSEL_PIN,
                          HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_GPIO, fem_config.antsel);
#endif

    /******************************************************
     * Setup RF_ANT_TRIM GPIOs
     */

    /* RF_ANT_TRIM_0 Config */
#if defined(dg_configFEM_SKY66112_11_ANT_TRIM_0_PORT) && defined(dg_configFEM_SKY66112_11_ANT_TRIM_0_PIN)
    hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_ANT_TRIM_0_PORT, dg_configFEM_SKY66112_11_ANT_TRIM_0_PIN,
                             HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_RF_ANT_TRIM0);
#endif

    /* RF_ANT_TRIM_1 Config */
#if defined(dg_configFEM_SKY66112_11_ANT_TRIM_1_PORT) && defined(dg_configFEM_SKY66112_11_ANT_TRIM_1_PIN)
    hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_ANT_TRIM_1_PORT, dg_configFEM_SKY66112_11_ANT_TRIM_1_PIN,
                             HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_RF_ANT_TRIM1);
#endif

    /* RF_ANT_TRIM_2 Config */
#if defined(dg_configFEM_SKY66112_11_ANT_TRIM_2_PORT) && defined(dg_configFEM_SKY66112_11_ANT_TRIM_2_PIN)
    hw_gpio_set_pin_function(dg_configFEM_SKY66112_11_ANT_TRIM_2_PORT, dg_configFEM_SKY66112_11_ANT_TRIM_2_PIN,
                             HW_GPIO_MODE_OUTPUT, HW_GPIO_FUNC_RF_ANT_TRIM2);
#endif

    /******************************************************
     * Setup DCFs
     */

    /* assign values to the timer registers for CTX/CRX (in usec) */
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_27_REG, SET_OFFSET, dg_configFEM_SKY66112_11_TXSET_DCF);
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_27_REG, RESET_OFFSET, dg_configFEM_SKY66112_11_TXRESET_DCF);
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_28_REG, SET_OFFSET, dg_configFEM_SKY66112_11_RXSET_DCF);
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_28_REG, RESET_OFFSET, dg_configFEM_SKY66112_11_RXRESET_DCF);

    rf_port_en = 0x6; /* Start with Port 0: TX, Port 1: RX */

    /* Compute set/reset delays to use for CSD, CPS, CHL DCFs: For setting delay,
     * smaller of TXSET, RXSET, and for resetting delay, larger of TXSET, RXSET
     */
#if dg_configFEM_SKY66112_11_RXSET_DCF > dg_configFEM_SKY66112_11_TXSET_DCF
    set_delay = dg_configFEM_SKY66112_11_TXSET_DCF;
#else
    set_delay = dg_configFEM_SKY66112_11_RXSET_DCF;
#endif

#if dg_configFEM_SKY66112_11_RXRESET_DCF > dg_configFEM_SKY66112_11_TXRESET_DCF
    reset_delay = dg_configFEM_SKY66112_11_RXRESET_DCF;
#else
    reset_delay = dg_configFEM_SKY66112_11_TXRESET_DCF;
#endif

    /* CSD DCF (if enabled) configuration */
#if defined(dg_configFEM_SKY66112_11_CSD_PORT) && defined(dg_configFEM_SKY66112_11_CSD_PIN)
# if dg_configFEM_SKY66112_11_CSD_USE_DCF != 0
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_29_REG, SET_OFFSET, set_delay);
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_29_REG, RESET_OFFSET, reset_delay);

    /* enable DCF Signals for Port 2 (CSD) for both rx/tx */
    rf_port_en |= 0x30;

# endif /* dg_configFEM_SKY66112_11_CSD_USE_DCF != 0 */
#endif

    /* Set bypass (CPS) DCF timers (but don't enable yet) */
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_30_REG, SET_OFFSET, set_delay);
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_30_REG, RESET_OFFSET, reset_delay);

    /* Set TX Power (CHL) DCF timers (but don't enable yet) */
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_31_REG, SET_OFFSET, dg_configFEM_SKY66112_11_TXSET_DCF);
    REG_SETF(RFCU_POWER, RF_CNTRL_TIMER_31_REG, RESET_OFFSET, dg_configFEM_SKY66112_11_TXRESET_DCF);

    /* Enable DCFs */
#if dg_configBLACK_ORCA_IC_REV == BLACK_ORCA_IC_REV_A
    RFCU_POWER->RF_PORT_EN_REG = rf_port_en;
    hw_fem_set_txpower(fem_config.tx_power);
#else
    RFCU_POWER->RF_PORT_EN_BLE_REG = rf_port_en;
    RFCU_POWER->RF_PORT_EN_FTDF_REG = rf_port_en;

    set_txpower();
#endif
    set_bypass();

    GLOBAL_INT_RESTORE();
}
示例#17
0
void hw_trng_disable_clk(void)
{
    GLOBAL_INT_DISABLE();
    REG_CLR_BIT(CRG_TOP, CLK_AMBA_REG, TRNG_CLK_ENABLE);
    GLOBAL_INT_RESTORE();
}