1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/cc26x2_cc13x2/auxiliary.c
2020-06-10 23:24:09 +02:00

93 lines
2.6 KiB
C

/*
* Copyright (C) 2020 Locha Inc
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_cc26x2_cc13x2
* @{
*
* @file
* @brief CC26x2, CC13x2 AUX functions
* @author Jean Pierre Dudey <jeandudey@hotmail.com>
* @}
*/
#include <assert.h>
#include "cpu.h"
/**
* @brief Order of operation modes
*
* This is to calculate which mode follows the other, to change step-by-step
* the mode.
*
* @{
*/
#define OPMODE_PDA_ORDER (0)
#define OPMODE_A_ORDER (1)
#define OPMODE_LP_ORDER (2)
#define OPMODE_PDLP_ORDER (3)
/** @} */
/** Array to map an operation mode to it's order when changing it */
static const uint8_t _opmode_to_order[4] = {
OPMODE_A_ORDER,
OPMODE_LP_ORDER,
OPMODE_PDA_ORDER,
OPMODE_PDLP_ORDER
};
/** Array to map an order to an operation mode, used to get the next operation
* mode. This is because we need to change the operation in ordered steps */
static const uint8_t _order_to_opmode[4] = {
AUX_SYSIF_OPMODEREQ_REQ_PDA,
AUX_SYSIF_OPMODEREQ_REQ_A,
AUX_SYSIF_OPMODEREQ_REQ_LP,
AUX_SYSIF_OPMODEREQ_REQ_PDLP
};
void aux_sysif_opmode_change(uint32_t target_opmode)
{
assert((target_opmode == AUX_SYSIF_OPMODEREQ_REQ_PDLP) ||
(target_opmode == AUX_SYSIF_OPMODEREQ_REQ_PDA) ||
(target_opmode == AUX_SYSIF_OPMODEREQ_REQ_LP) ||
(target_opmode == AUX_SYSIF_OPMODEREQ_REQ_A));
uint32_t current_opmode;
uint32_t next_mode;
/* Change AUX operation mode following hardware rules, operation mode
* change needs to be done in order, and one step at a time:
*
* PDA -> A -> LP -> PDLP
*/
do {
current_opmode = AUX_SYSIF->OPMODEREQ;
/* Wait for change ACK */
while (current_opmode != AUX_SYSIF->OPMODEACK) {}
if (current_opmode == target_opmode) {
break;
}
/* At this point we aren't in the mode we want, now we calculate which
* mode follows this and make the change to that mode, this is repeated
* in this loop until we get to the desired mode */
uint32_t current_order = _opmode_to_order[current_opmode];
if (current_order < _opmode_to_order[target_opmode]) {
next_mode = _order_to_opmode[current_order + 1];
}
else {
next_mode = _order_to_opmode[current_order - 1];
}
/* Request next mode */
AUX_SYSIF->OPMODEREQ = next_mode;
} while (current_opmode != target_opmode);
}