├── .gitignore ├── Makefile ├── README.md ├── board ├── board.c ├── board.h ├── gpio.c ├── gpio.h ├── lora.c ├── lora.h ├── pinName-board.h ├── rtc.c ├── rtc.h ├── spi.c ├── spi.h ├── sx1276-board.c ├── sx1276-board.h ├── timer.c ├── timer.h ├── utilities.c └── utilities.h ├── config ├── Comissioning.h ├── app_config.h └── sdk_config.h ├── crypto ├── aes.c ├── aes.h ├── cmac.c └── cmac.h ├── gcc_nrf52.ld ├── mac ├── LoRaMac-definitions.h ├── LoRaMac.c ├── LoRaMac.h ├── LoRaMacCrypto.c ├── LoRaMacCrypto.h └── LoRaMacTest.h ├── main.c └── radio ├── radio.h └── sx1276 ├── sx1276.c ├── sx1276.h ├── sx1276Regs-Fsk.h └── sx1276Regs-LoRa.h /.gitignore: -------------------------------------------------------------------------------- 1 | _build/ 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT_NAME := sx1276mb1mas 2 | TARGETS := nrf52832_xxaa 3 | OUTPUT_DIRECTORY := _build 4 | 5 | SDK_ROOT := ../.. 6 | PROJ_DIR := . 7 | 8 | $(OUTPUT_DIRECTORY)/nrf52832_xxaa.out: \ 9 | LINKER_SCRIPT := gcc_nrf52.ld 10 | 11 | ifeq ($(BUILD_VERSION),) 12 | BUILD_HOST=$(shell hostname) 13 | BUILD_DATE=$(shell date --rfc-3339='seconds') 14 | BUILD_VERSION="$(USER)@$(BUILD_HOST) $(BUILD_DATE)" 15 | endif 16 | 17 | # Source files common to all targets 18 | SRC_FILES += \ 19 | $(SDK_ROOT)/components/libraries/log/src/nrf_log_backend_serial.c \ 20 | $(SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \ 21 | $(SDK_ROOT)/components/libraries/util/app_error.c \ 22 | $(SDK_ROOT)/components/libraries/util/app_error_weak.c \ 23 | $(SDK_ROOT)/components/libraries/timer/app_timer.c \ 24 | $(SDK_ROOT)/components/libraries/util/app_util_platform.c \ 25 | $(SDK_ROOT)/components/libraries/mem_manager/mem_manager.c \ 26 | $(SDK_ROOT)/components/libraries/hardfault/hardfault_implementation.c \ 27 | $(SDK_ROOT)/components/libraries/util/nrf_assert.c \ 28 | $(SDK_ROOT)/components/libraries/strerror/nrf_strerror.c \ 29 | $(SDK_ROOT)/components/drivers_nrf/clock/nrf_drv_clock.c \ 30 | $(SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \ 31 | $(SDK_ROOT)/components/drivers_nrf/gpiote/nrf_drv_gpiote.c \ 32 | $(SDK_ROOT)/components/drivers_nrf/power/nrf_drv_power.c \ 33 | $(SDK_ROOT)/components/drivers_nrf/clock/nrf_drv_clock.c \ 34 | $(SDK_ROOT)/components/drivers_nrf/rtc/nrf_drv_rtc.c \ 35 | $(SDK_ROOT)/components/drivers_nrf/timer/nrf_drv_timer.c \ 36 | $(SDK_ROOT)/components/drivers_nrf/spi_master/nrf_drv_spi.c \ 37 | $(SDK_ROOT)/components/drivers_nrf/wdt/nrf_drv_wdt.c \ 38 | $(SDK_ROOT)/external/segger_rtt/RTT_Syscalls_GCC.c \ 39 | $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \ 40 | $(SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \ 41 | $(SDK_ROOT)/components/ble/common/ble_advdata.c \ 42 | $(SDK_ROOT)/components/ble/common/ble_conn_params.c \ 43 | $(SDK_ROOT)/components/ble/common/ble_srv_common.c \ 44 | $(SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.S \ 45 | $(SDK_ROOT)/components/toolchain/system_nrf52.c \ 46 | $(SDK_ROOT)/components/softdevice/common/softdevice_handler/softdevice_handler.c \ 47 | $(PROJ_DIR)/main.c \ 48 | $(PROJ_DIR)/board/board.c \ 49 | $(PROJ_DIR)/board/lora.c \ 50 | $(PROJ_DIR)/board/utilities.c \ 51 | $(PROJ_DIR)/board/gpio.c \ 52 | $(PROJ_DIR)/board/spi.c \ 53 | $(PROJ_DIR)/board/timer.c \ 54 | $(PROJ_DIR)/board/rtc.c \ 55 | $(PROJ_DIR)/board/sx1276-board.c \ 56 | $(PROJ_DIR)/radio/sx1276/sx1276.c \ 57 | $(PROJ_DIR)/mac/LoRaMac.c \ 58 | $(PROJ_DIR)/mac/LoRaMacCrypto.c \ 59 | $(PROJ_DIR)/crypto/aes.c \ 60 | $(PROJ_DIR)/crypto/cmac.c \ 61 | 62 | # Include folders common to all targets 63 | INC_FOLDERS += \ 64 | $(SDK_ROOT)/components/drivers_nrf/comp \ 65 | $(SDK_ROOT)/components/drivers_nrf/twi_master \ 66 | $(SDK_ROOT)/components/ble/ble_services/ble_ancs_c \ 67 | $(SDK_ROOT)/components/ble/ble_services/ble_ias_c \ 68 | $(SDK_ROOT)/components/libraries/pwm \ 69 | $(SDK_ROOT)/components/softdevice/s132/headers/nrf52 \ 70 | $(SDK_ROOT)/components/libraries/usbd/class/cdc/acm \ 71 | $(SDK_ROOT)/components/libraries/usbd/class/hid/generic \ 72 | $(SDK_ROOT)/components/libraries/usbd/class/msc \ 73 | $(SDK_ROOT)/components/libraries/usbd/class/hid \ 74 | $(SDK_ROOT)/components/libraries/log \ 75 | $(SDK_ROOT)/components/ble/ble_services/ble_gls \ 76 | $(SDK_ROOT)/components/libraries/fstorage \ 77 | $(SDK_ROOT)/components/drivers_nrf/i2s \ 78 | $(SDK_ROOT)/components/libraries/gpiote \ 79 | $(SDK_ROOT)/components/drivers_nrf/gpiote \ 80 | $(SDK_ROOT)/components/boards \ 81 | $(SDK_ROOT)/components/drivers_nrf/common \ 82 | $(SDK_ROOT)/components/ble/ble_advertising \ 83 | $(SDK_ROOT)/components/ble/ble_services/ble_bas_c \ 84 | $(SDK_ROOT)/components/ble/ble_services/ble_hrs_c \ 85 | $(SDK_ROOT)/components/libraries/queue \ 86 | $(SDK_ROOT)/components/ble/ble_dtm \ 87 | $(SDK_ROOT)/components/toolchain/cmsis/include \ 88 | $(SDK_ROOT)/components/ble/ble_services/ble_rscs_c \ 89 | $(SDK_ROOT)/components/drivers_nrf/uart \ 90 | $(SDK_ROOT)/components/ble/common \ 91 | $(SDK_ROOT)/components/ble/ble_services/ble_lls \ 92 | $(SDK_ROOT)/components/drivers_nrf/wdt \ 93 | $(SDK_ROOT)/components/libraries/bsp \ 94 | $(SDK_ROOT)/components/ble/ble_services/ble_bas \ 95 | $(SDK_ROOT)/components/libraries/experimental_section_vars \ 96 | $(SDK_ROOT)/components/softdevice/s132/headers \ 97 | $(SDK_ROOT)/components/ble/ble_services/ble_ans_c \ 98 | $(SDK_ROOT)/components/libraries/slip \ 99 | $(SDK_ROOT)/components/libraries/mem_manager \ 100 | $(SDK_ROOT)/external/segger_rtt \ 101 | $(SDK_ROOT)/components/libraries/csense_drv \ 102 | $(SDK_ROOT)/components/drivers_nrf/hal \ 103 | $(SDK_ROOT)/components/ble/ble_services/ble_nus_c \ 104 | $(SDK_ROOT)/components/drivers_nrf/rtc \ 105 | $(SDK_ROOT)/components/ble/ble_services/ble_ias \ 106 | $(SDK_ROOT)/components/libraries/usbd/class/hid/mouse \ 107 | $(SDK_ROOT)/components/libraries/ecc \ 108 | $(SDK_ROOT)/components/drivers_nrf/ppi \ 109 | $(SDK_ROOT)/components/ble/ble_services/ble_dfu \ 110 | $(SDK_ROOT)/components/drivers_nrf/twis_slave \ 111 | $(SDK_ROOT)/components \ 112 | $(SDK_ROOT)/components/libraries/scheduler \ 113 | $(SDK_ROOT)/components/ble/ble_services/ble_lbs \ 114 | $(SDK_ROOT)/components/ble/ble_services/ble_hts \ 115 | $(SDK_ROOT)/components/drivers_nrf/delay \ 116 | $(SDK_ROOT)/components/libraries/crc16 \ 117 | $(SDK_ROOT)/components/drivers_nrf/timer \ 118 | $(SDK_ROOT)/components/libraries/util \ 119 | $(SDK_ROOT)/components/drivers_nrf/pwm \ 120 | $(SDK_ROOT)/components/libraries/usbd/class/cdc \ 121 | $(SDK_ROOT)/components/libraries/csense \ 122 | $(SDK_ROOT)/components/drivers_nrf/rng \ 123 | $(SDK_ROOT)/components/libraries/low_power_pwm \ 124 | $(SDK_ROOT)/components/libraries/hardfault \ 125 | $(SDK_ROOT)/components/ble/ble_services/ble_cscs \ 126 | $(SDK_ROOT)/components/libraries/uart \ 127 | $(SDK_ROOT)/components/libraries/fifo \ 128 | $(SDK_ROOT)/components/libraries/hci \ 129 | $(SDK_ROOT)/components/libraries/usbd/class/hid/kbd \ 130 | $(SDK_ROOT)/components/drivers_nrf/spi_slave \ 131 | $(SDK_ROOT)/components/drivers_nrf/lpcomp \ 132 | $(SDK_ROOT)/components/libraries/timer \ 133 | $(SDK_ROOT)/components/drivers_nrf/power \ 134 | $(SDK_ROOT)/components/libraries/usbd/config \ 135 | $(SDK_ROOT)/components/toolchain \ 136 | $(SDK_ROOT)/components/libraries/led_softblink \ 137 | $(SDK_ROOT)/components/drivers_nrf/qdec \ 138 | $(SDK_ROOT)/components/ble/ble_services/ble_cts_c \ 139 | $(SDK_ROOT)/components/drivers_nrf/spi_master \ 140 | $(SDK_ROOT)/components/ble/ble_services/ble_nus \ 141 | $(SDK_ROOT)/components/ble/ble_services/ble_hids \ 142 | $(SDK_ROOT)/components/libraries/strerror \ 143 | $(SDK_ROOT)/components/drivers_nrf/pdm \ 144 | $(SDK_ROOT)/components/libraries/crc32 \ 145 | $(SDK_ROOT)/components/libraries/usbd/class/audio \ 146 | $(SDK_ROOT)/components/ble/peer_manager \ 147 | $(SDK_ROOT)/components/drivers_nrf/swi \ 148 | $(SDK_ROOT)/components/ble/ble_services/ble_tps \ 149 | $(SDK_ROOT)/components/ble/ble_services/ble_dis \ 150 | $(SDK_ROOT)/components/device \ 151 | $(SDK_ROOT)/components/ble/nrf_ble_qwr \ 152 | $(SDK_ROOT)/components/libraries/button \ 153 | $(SDK_ROOT)/components/libraries/usbd \ 154 | $(SDK_ROOT)/components/drivers_nrf/saadc \ 155 | $(SDK_ROOT)/components/ble/ble_services/ble_lbs_c \ 156 | $(SDK_ROOT)/components/ble/ble_racp \ 157 | $(SDK_ROOT)/components/toolchain/gcc \ 158 | $(SDK_ROOT)/components/libraries/fds \ 159 | $(SDK_ROOT)/components/libraries/twi \ 160 | $(SDK_ROOT)/components/drivers_nrf/clock \ 161 | $(SDK_ROOT)/components/ble/ble_services/ble_rscs \ 162 | $(SDK_ROOT)/components/drivers_nrf/usbd \ 163 | $(SDK_ROOT)/components/softdevice/common/softdevice_handler \ 164 | $(SDK_ROOT)/components/ble/ble_services/ble_hrs \ 165 | $(SDK_ROOT)/components/libraries/log/src \ 166 | $(PROJ_DIR)/config \ 167 | $(PROJ_DIR)/radio \ 168 | $(PROJ_DIR)/board \ 169 | $(PROJ_DIR)/mac \ 170 | $(PROJ_DIR)/crypto \ 171 | 172 | # Libraries common to all targets 173 | LIB_FILES += \ 174 | 175 | # C flags common to all targets 176 | CFLAGS += -DDEBUG 177 | CFLAGS += -DBLE_STACK_SUPPORT_REQD 178 | CFLAGS += -DCONFIG_NFCT_PINS_AS_GPIOS 179 | CFLAGS += -DCONFIG_GPIO_AS_PINRESET 180 | CFLAGS += -DNRF52 181 | CFLAGS += -DNRF52832_XXAA 182 | CFLAGS += -DNRF52_PAN_12 183 | CFLAGS += -DNRF52_PAN_15 184 | CFLAGS += -DNRF52_PAN_20 185 | CFLAGS += -DNRF52_PAN_31 186 | CFLAGS += -DNRF52_PAN_36 187 | CFLAGS += -DNRF52_PAN_51 188 | CFLAGS += -DNRF52_PAN_54 189 | CFLAGS += -DNRF52_PAN_55 190 | CFLAGS += -DNRF52_PAN_58 191 | CFLAGS += -DNRF52_PAN_64 192 | CFLAGS += -DNRF52_PAN_74 193 | CFLAGS += -DNRF_SD_BLE_API_VERSION=4 194 | CFLAGS += -DS132 195 | CFLAGS += -DSOFTDEVICE_PRESENT 196 | CFLAGS += -DSWI_DISABLE0 197 | CFLAGS += -DUSE_BAND_868 198 | CFLAGS += -mcpu=cortex-m4 199 | CFLAGS += -mthumb -mabi=aapcs 200 | CFLAGS += -Wall -Werror -O3 -g3 201 | CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 202 | # keep every function in separate section, this allows linker to discard unused ones 203 | CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing 204 | CFLAGS += -fno-builtin --short-enums 205 | ifneq ($(BUILD_VERSION),) 206 | CFLAGS += -DBUILD_VERSION=\"$(BUILD_VERSION)\" 207 | endif 208 | 209 | # C++ flags common to all targets 210 | CXXFLAGS += \ 211 | 212 | # Assembler flags common to all targets 213 | ASMFLAGS += -x assembler-with-cpp 214 | ADMFLAGS += -DDEBUG 215 | ASMFLAGS += -DBLE_STACK_SUPPORT_REQD 216 | ASMFLAGS += -DCONFIG_NFCT_PINS_AS_GPIOS 217 | ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET 218 | ASMFLAGS += -DNRF52 219 | ASMFLAGS += -DNRF52832_XXAA 220 | ASMFLAGS += -DNRF52_PAN_12 221 | ASMFLAGS += -DNRF52_PAN_15 222 | ASMFLAGS += -DNRF52_PAN_20 223 | ASMFLAGS += -DNRF52_PAN_31 224 | ASMFLAGS += -DNRF52_PAN_36 225 | ASMFLAGS += -DNRF52_PAN_51 226 | ASMFLAGS += -DNRF52_PAN_54 227 | ASMFLAGS += -DNRF52_PAN_55 228 | ASMFLAGS += -DNRF52_PAN_58 229 | ASMFLAGS += -DNRF52_PAN_64 230 | ASMFLAGS += -DNRF52_PAN_74 231 | ASMFLAGS += -DNRF_SD_BLE_API_VERSION=4 232 | ASMFLAGS += -DS132 233 | ASMFLAGS += -DSOFTDEVICE_PRESENT 234 | ASMFLAGS += -DSWI_DISABLE0 235 | 236 | # Linker flags 237 | LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT) 238 | LDFLAGS += -mcpu=cortex-m4 239 | LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 240 | # let linker to dump unused sections 241 | LDFLAGS += -Wl,--gc-sections 242 | # use newlib in nano version 243 | LDFLAGS += --specs=nano.specs -lc -lnosys 244 | 245 | 246 | .PHONY: $(TARGETS) default all clean help flash flash_softdevice 247 | 248 | # Default target - first one defined 249 | default: nrf52832_xxaa 250 | 251 | # Print all targets that can be built 252 | help: 253 | @echo Build version: $(BUILD_VERSION) 254 | @echo following targets are available: 255 | @echo nrf52832_xxaa 256 | 257 | TEMPLATE_PATH := $(SDK_ROOT)/components/toolchain/gcc 258 | 259 | include $(TEMPLATE_PATH)/Makefile.common 260 | 261 | $(foreach target, $(TARGETS), $(call define_target, $(target))) 262 | 263 | # Flash the program 264 | flash: $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex 265 | @echo Flashing: $< 266 | nrfjprog --program $< -f nrf52 --sectorerase 267 | nrfjprog --reset -f nrf52 268 | 269 | # Flash softdevice 270 | flash_softdevice: 271 | @echo Flashing: s132_nrf52_4.0.2_softdevice.hex 272 | nrfjprog --program $(SDK_ROOT)/components/softdevice/s132/hex/s132_nrf52_4.0.2_softdevice.hex -f nrf52 --sectorerase 273 | nrfjprog --reset -f nrf52 274 | 275 | erase: 276 | nrfjprog --eraseall -f nrf52 277 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LoRa MAC class A node on Nordic nRF52 2 | 3 | ## Hardware 4 | 5 | Developed and tested on [Nordic's PCA10040 DK](https://www.nordicsemi.com/eng/Products/Bluetooth-low-energy/nRF52-DK) 6 | and [Semtech's SX1276MB1MAS](https://developer.mbed.org/components/SX1276MB1xAS/) 7 | 8 | ###### Modifications 9 | 10 | Cut SB7 (LED3) and SB8 (LED4) - used for DIO4&5 11 | 12 | ## Software 13 | 14 | Built using Nordic's SDK v13.0.0 and gcc version 5.4.1 15 | Using S132 Softdevice v4.0.2 16 | 17 | Debug prints using Segger's RTT mechanism. 18 | 19 | ## Configuration 20 | 21 | Set `LORAWAN_APPLICATION_EUI` and `LORAWAN_APPLICATION_KEY` in `config/Comissioning.h` 22 | Device EUI is taken from nRF unique device ID (FICR DEVICEADDR). 23 | 24 | ## Building 25 | 26 | Modify `SDK_ROOT` in `Makefile` to point to Nordic's SDK root 27 | Make sure nrfjprog is in `PATH` 28 | run `make flash_softdevice && make flash` 29 | 30 | -------------------------------------------------------------------------------- /board/board.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | #include "nrf52.h" 3 | 4 | #define NRF_LOG_MODULE_NAME "BRD" 5 | #define NRF_LOG_LEVEL 4 6 | #include "nrf_log.h" 7 | 8 | uint32_t BoardGetRandomSeed( void ) 9 | { 10 | uint32_t seed = NRF_FICR->DEVICEID[0]; 11 | return seed; 12 | } 13 | 14 | void BoardGetUniqueId( uint8_t *id ) 15 | { 16 | uint32_t did[2]; 17 | did[0] = NRF_FICR->DEVICEID[0]; 18 | did[1] = NRF_FICR->DEVICEID[1]; 19 | memcpy(id, did, 8); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /board/board.h: -------------------------------------------------------------------------------- 1 | #ifndef _BOARD_H 2 | #define _BOARD_H 3 | #include 4 | #include 5 | #include "app_error.h" 6 | #include "nordic_common.h" 7 | 8 | #include "rtc.h" 9 | #include "gpio.h" 10 | #include "spi.h" 11 | #include "timer.h" 12 | #include "utilities.h" 13 | #include "radio.h" 14 | #include "sx1276/sx1276.h" 15 | #include "sx1276-board.h" 16 | #include "lora.h" 17 | 18 | /* SX1276MB1MAS pinout */ 19 | #define RADIO_DIO_0 P13 /* J1 pin 3 */ 20 | #define RADIO_DIO_1 P14 /* J1 pin 4 */ 21 | #define RADIO_DIO_2 P15 /* J1 pin 5 */ 22 | #define RADIO_DIO_3 P16 /* J1 pin 6 */ 23 | #define RADIO_DIO_4 P19 /* J2 pin 1 */ 24 | #define RADIO_DIO_5 P20 /* J2 pin 2 */ 25 | 26 | #define RADIO_NSS P22 /* J2 pin 3 */ 27 | #define RADIO_MOSI P23 /* J2 pin 4 */ 28 | #define RADIO_MISO P24 /* J2 pin 5 */ 29 | #define RADIO_SCK P25 /* J2 pin 6 */ 30 | 31 | #define RADIO_RESET P3 /* J4 pin 1 */ 32 | #define RADIO_ANT_SWITCH_HF P30 /* J4 pin 5 */ 33 | 34 | #define RADIO_DIO4_B P29 /* J4 pin 4 */ 35 | 36 | #define ASSERT_ERROR 0xA55EA55E 37 | 38 | #define USE_FULL_ASSERT 39 | #ifdef USE_FULL_ASSERT 40 | /** 41 | * @brief The assert_param macro is used for function's parameters check. 42 | * @param expr: If expr is false, it calls assert_failed function 43 | * which reports the name of the source file and the source 44 | * line number of the call that failed. 45 | * If expr is true, it returns no value. 46 | * @retval None 47 | */ 48 | #define assert_param(expr) ((expr) ? (void)0U : app_error_handler(ASSERT_ERROR,\ 49 | __LINE__,\ 50 | (const uint8_t *)__FILE__)) 51 | #else 52 | #define assert_param(expr) ((void)0U) 53 | #endif /* USE_FULL_ASSERT */ 54 | 55 | 56 | /*! 57 | * Returns a pseudo random seed generated using the MCU Unique ID 58 | * 59 | * \retval seed Generated pseudo random seed 60 | */ 61 | uint32_t BoardGetRandomSeed( void ); 62 | 63 | /*! 64 | * \brief Gets the board 64 bits unique ID 65 | * 66 | * \param [IN] id Pointer to an array that will contain the Unique ID 67 | */ 68 | void BoardGetUniqueId( uint8_t *id ); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /board/gpio.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | #include "nrf_drv_gpiote.h" 3 | 4 | #define NRF_LOG_MODULE_NAME "GPIO" 5 | #define NRF_LOG_LEVEL 3 6 | #include "nrf_log.h" 7 | 8 | static GpioIrqHandler* irq_handlers[32]; 9 | 10 | static void pin_event_handler(nrf_drv_gpiote_pin_t pin, 11 | nrf_gpiote_polarity_t action) 12 | { 13 | NRF_LOG_DEBUG("int %d %d 0x%x\r\n", pin, action, 14 | (uint32_t)irq_handlers[pin]); 15 | if (irq_handlers[pin]!=NULL) 16 | irq_handlers[pin](); 17 | } 18 | 19 | void GpioInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, 20 | PinTypes type, uint32_t value ) 21 | { 22 | ret_code_t err_code; 23 | obj->pin = pin; 24 | obj->mode = mode; 25 | obj->pull = type; 26 | obj->irq_mode = NO_IRQ; 27 | NRF_LOG_DEBUG("Init 0x%x %d %d %d\r\n", 28 | (uint32_t)obj, pin, mode, type); 29 | if (mode == PIN_INPUT) { 30 | nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); 31 | if (type == PIN_PULL_UP) 32 | config.pull = NRF_GPIO_PIN_PULLUP; 33 | else if (type == PIN_PULL_DOWN) 34 | config.pull = NRF_GPIO_PIN_PULLDOWN; 35 | err_code = nrf_drv_gpiote_in_init(pin, &config, pin_event_handler); 36 | } else { 37 | nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_SIMPLE(false); 38 | if (value!=0) 39 | config.init_state = true; 40 | err_code = nrf_drv_gpiote_out_init(pin, &config); 41 | } 42 | if (err_code != NRF_SUCCESS) { 43 | NRF_LOG_ERROR("GpioInit error %d\r\n", err_code); 44 | return; 45 | } 46 | obj->initialized = true; 47 | } 48 | 49 | void GpioSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, 50 | GpioIrqHandler *irqHandler ) 51 | { 52 | ret_code_t err_code; 53 | NRF_LOG_DEBUG("SetInterrupt %d %d 0x%x\r\n", obj->pin, irqMode, 54 | (uint32_t)irqHandler); 55 | 56 | if (obj->mode != PIN_INPUT) { 57 | NRF_LOG_ERROR("wrong pin state\r\n"); 58 | return; 59 | } 60 | if (obj->initialized) { 61 | nrf_drv_gpiote_in_uninit(obj->pin); 62 | obj->initialized = false; 63 | } 64 | 65 | nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true); 66 | 67 | obj->irq_mode = irqMode; 68 | if (irqMode == IRQ_RISING_EDGE) { 69 | config.sense = NRF_GPIOTE_POLARITY_LOTOHI; 70 | } else if (irqMode == IRQ_FALLING_EDGE) { 71 | config.sense = NRF_GPIOTE_POLARITY_HITOLO; 72 | } 73 | 74 | if (obj->pull == PIN_PULL_UP) { 75 | config.pull = NRF_GPIO_PIN_PULLUP; 76 | } else if (obj->pull == PIN_PULL_DOWN) { 77 | config.pull = NRF_GPIO_PIN_PULLDOWN; 78 | } 79 | 80 | err_code = nrf_drv_gpiote_in_init(obj->pin, &config, pin_event_handler); 81 | if (err_code != NRF_SUCCESS) { 82 | NRF_LOG_ERROR("GpioInit error %d\r\n", err_code); 83 | return; 84 | } 85 | irq_handlers[obj->pin] = irqHandler; 86 | nrf_drv_gpiote_in_event_enable(obj->pin, true); 87 | obj->initialized = true; 88 | } 89 | 90 | void GpioRemoveInterrupt( Gpio_t *obj ) 91 | { 92 | NRF_LOG_DEBUG("RemoveInterrupt %d\r\n", obj->pin); 93 | if (obj->mode != PIN_INPUT || obj->initialized != true) { 94 | NRF_LOG_ERROR("wrong pin state\r\n"); 95 | return; 96 | } 97 | nrf_drv_gpiote_in_event_disable(obj->pin); 98 | } 99 | 100 | void GpioWrite( Gpio_t *obj, uint32_t value ) 101 | { 102 | NRF_LOG_DEBUG("Write %d %d\r\n", obj->pin, value); 103 | if (obj->mode != PIN_OUTPUT || obj->initialized != true) { 104 | NRF_LOG_ERROR("wrong pin state\r\n"); 105 | return; 106 | } 107 | 108 | if (value) { 109 | nrf_drv_gpiote_out_set(obj->pin); 110 | } else { 111 | nrf_drv_gpiote_out_clear(obj->pin); 112 | } 113 | } 114 | 115 | void GpioToggle( Gpio_t *obj ) 116 | { 117 | NRF_LOG_DEBUG("Toggle %d %d\r\n", obj->pin); 118 | if (obj->mode != PIN_OUTPUT || obj->initialized != true) { 119 | NRF_LOG_ERROR("wrong pin state\r\n"); 120 | return; 121 | } 122 | 123 | nrf_drv_gpiote_out_toggle(obj->pin); 124 | } 125 | 126 | uint32_t GpioRead( Gpio_t *obj ) 127 | { 128 | if (obj->mode != PIN_INPUT || obj->initialized != true) { 129 | NRF_LOG_ERROR("wrong pin state\r\n"); 130 | return 0; 131 | } 132 | if (nrf_drv_gpiote_in_is_set(obj->pin)) 133 | return 1; 134 | else 135 | return 0; 136 | } 137 | 138 | void GpioDeinit( Gpio_t *obj ) 139 | { 140 | NRF_LOG_DEBUG("Deinit %d %d\r\n", obj->pin); 141 | if (obj->initialized != true) { 142 | NRF_LOG_DEBUG("wrong pin state\r\n"); 143 | return; 144 | } 145 | if (obj->mode == PIN_INPUT) { 146 | nrf_drv_gpiote_in_uninit(obj->pin); 147 | } else if (obj->mode == PIN_OUTPUT) { 148 | nrf_drv_gpiote_out_uninit(obj->pin); 149 | } 150 | obj->initialized = false; 151 | } 152 | 153 | -------------------------------------------------------------------------------- /board/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Generic GPIO driver implementation 10 | 11 | Comment: Relies on the specific board GPIO implementation as well as on 12 | IO expander driver implementation if one is available on the target 13 | board. 14 | 15 | License: Revised BSD License, see LICENSE.TXT file include in the project 16 | 17 | Maintainer: Miguel Luis and Gregory Cristian 18 | */ 19 | #ifndef __GPIO_H__ 20 | #define __GPIO_H__ 21 | 22 | #include "pinName-board.h" 23 | 24 | /*! 25 | * Board GPIO pin names 26 | */ 27 | typedef enum 28 | { 29 | MCU_PINS, 30 | 31 | // Not connected 32 | NC = (int)0xFFFFFFFF 33 | }PinNames; 34 | 35 | /*! 36 | * Operation Mode for the GPIO 37 | */ 38 | typedef enum 39 | { 40 | PIN_INPUT = 0, 41 | PIN_OUTPUT, 42 | }PinModes; 43 | 44 | /*! 45 | * Add a pull-up, a pull-down or nothing on the GPIO line 46 | */ 47 | typedef enum 48 | { 49 | PIN_NO_PULL = 0, 50 | PIN_PULL_UP, 51 | PIN_PULL_DOWN 52 | }PinTypes; 53 | 54 | /*! 55 | * Define the GPIO as Push-pull type or Open Drain 56 | */ 57 | typedef enum 58 | { 59 | PIN_PUSH_PULL = 0, 60 | PIN_OPEN_DRAIN 61 | }PinConfigs; 62 | 63 | /*! 64 | * Define the GPIO IRQ on a rising, falling or both edges 65 | */ 66 | typedef enum 67 | { 68 | NO_IRQ = 0, 69 | IRQ_RISING_EDGE, 70 | IRQ_FALLING_EDGE, 71 | IRQ_RISING_FALLING_EDGE 72 | }IrqModes; 73 | 74 | /*! 75 | * Define the IRQ priority on the GPIO 76 | */ 77 | typedef enum 78 | { 79 | IRQ_VERY_LOW_PRIORITY = 0, 80 | IRQ_LOW_PRIORITY, 81 | IRQ_MEDIUM_PRIORITY, 82 | IRQ_HIGH_PRIORITY, 83 | IRQ_VERY_HIGH_PRIORITY 84 | }IrqPriorities; 85 | 86 | /*! 87 | * Structure for the GPIO 88 | */ 89 | typedef struct 90 | { 91 | PinNames pin; 92 | PinModes mode; 93 | PinTypes pull; 94 | IrqModes irq_mode; 95 | bool initialized; 96 | }Gpio_t; 97 | 98 | /*! 99 | * GPIO IRQ handler function prototype 100 | */ 101 | typedef void( GpioIrqHandler )( void ); 102 | 103 | /*! 104 | * GPIO Expander IRQ handler function prototype 105 | */ 106 | typedef void( GpioIoeIrqHandler )( void ); 107 | 108 | /*! 109 | * \brief Initializes the given GPIO object 110 | * 111 | * \param [IN] obj Pointer to the GPIO object 112 | * \param [IN] pin Pin name ( please look in pinName-board.h file ) 113 | * \param [IN] mode Pin mode [PIN_INPUT, PIN_OUTPUT, 114 | * PIN_ALTERNATE_FCT, PIN_ANALOGIC] 115 | * \param [IN] config Pin config [PIN_PUSH_PULL, PIN_OPEN_DRAIN] 116 | * \param [IN] type Pin type [PIN_NO_PULL, PIN_PULL_UP, PIN_PULL_DOWN] 117 | * \param [IN] value Default output value at initialization 118 | */ 119 | void GpioInit( Gpio_t *obj, PinNames pin, PinModes mode, PinConfigs config, PinTypes type, uint32_t value ); 120 | 121 | /*! 122 | * \brief GPIO IRQ Initialization 123 | * 124 | * \param [IN] obj Pointer to the GPIO object 125 | * \param [IN] irqMode IRQ mode [NO_IRQ, IRQ_RISING_EDGE, 126 | * IRQ_FALLING_EDGE, IRQ_RISING_FALLING_EDGE] 127 | * \param [IN] irqPriority IRQ priority [IRQ_VERY_LOW_PRIORITY, IRQ_LOW_PRIORITY 128 | * IRQ_MEDIUM_PRIORITY, IRQ_HIGH_PRIORITY 129 | * IRQ_VERY_HIGH_PRIORITY] 130 | * \param [IN] irqHandler Callback function pointer 131 | */ 132 | void GpioSetInterrupt( Gpio_t *obj, IrqModes irqMode, IrqPriorities irqPriority, GpioIrqHandler *irqHandler ); 133 | 134 | /*! 135 | * \brief Removes the interrupt from the object 136 | * 137 | * \param [IN] obj Pointer to the GPIO object 138 | */ 139 | void GpioRemoveInterrupt( Gpio_t *obj ); 140 | 141 | /*! 142 | * \brief Writes the given value to the GPIO output 143 | * 144 | * \param [IN] obj Pointer to the GPIO object 145 | * \param [IN] value New GPIO output value 146 | */ 147 | void GpioWrite( Gpio_t *obj, uint32_t value ); 148 | 149 | /*! 150 | * \brief Toggle the value to the GPIO output 151 | * 152 | * \param [IN] obj Pointer to the GPIO object 153 | */ 154 | void GpioToggle( Gpio_t *obj ); 155 | 156 | /*! 157 | * \brief Reads the current GPIO input value 158 | * 159 | * \param [IN] obj Pointer to the GPIO object 160 | * \retval value Current GPIO input value 161 | */ 162 | uint32_t GpioRead( Gpio_t *obj ); 163 | 164 | /*! 165 | * \brief Deinitialize GPIO pin 166 | * 167 | * \param [IN] obj Pointer to the GPIO object 168 | */ 169 | void GpioDeinit( Gpio_t *obj ); 170 | 171 | #endif // __GPIO_H__ 172 | -------------------------------------------------------------------------------- /board/lora.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | #include "Comissioning.h" 3 | #include "LoRaMac.h" 4 | 5 | #define NRF_LOG_MODULE_NAME "LORA" 6 | #define NRF_LOG_LEVEL 4 7 | #include "nrf_log.h" 8 | 9 | /*! 10 | * Defines the application data transmission duty cycle. 5s, value in [ms]. 11 | */ 12 | #define APP_TX_DUTYCYCLE 60000 13 | 14 | /*! 15 | * Defines a random delay for application data transmission duty cycle. 1s, 16 | * value in [ms]. 17 | */ 18 | #define APP_TX_DUTYCYCLE_RND 1000 19 | 20 | /*! 21 | * Default datarate 22 | */ 23 | #define LORAWAN_DEFAULT_DATARATE DR_0 24 | 25 | /*! 26 | * LoRaWAN confirmed messages 27 | */ 28 | #define LORAWAN_CONFIRMED_MSG_ON false 29 | 30 | /*! 31 | * LoRaWAN Adaptive Data Rate 32 | * 33 | * \remark Please note that when ADR is enabled the end-device should be static 34 | */ 35 | #define LORAWAN_ADR_ON 1 36 | 37 | #if defined( USE_BAND_868 ) 38 | 39 | #include "LoRaMacTest.h" 40 | 41 | /*! 42 | * LoRaWAN ETSI duty cycle control enable/disable 43 | * 44 | * \remark Please note that ETSI mandates duty cycled transmissions. Use only for test purposes 45 | */ 46 | #define LORAWAN_DUTYCYCLE_ON false 47 | 48 | #define USE_SEMTECH_DEFAULT_CHANNEL_LINEUP 1 49 | 50 | #if( USE_SEMTECH_DEFAULT_CHANNEL_LINEUP == 1 ) 51 | 52 | #define LC4 { 867100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 53 | #define LC5 { 867300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 54 | #define LC6 { 867500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 55 | #define LC7 { 867700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 56 | #define LC8 { 867900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 57 | #define LC9 { 868800000, { ( ( DR_7 << 4 ) | DR_7 ) }, 2 } 58 | #define LC10 { 868300000, { ( ( DR_6 << 4 ) | DR_6 ) }, 1 } 59 | 60 | #endif 61 | 62 | #endif 63 | 64 | /*! 65 | * LoRaWAN application port 66 | */ 67 | #define LORAWAN_APP_PORT 2 68 | 69 | /*! 70 | * User application data buffer size 71 | */ 72 | #if defined( USE_BAND_433 ) || defined( USE_BAND_470 ) || defined( USE_BAND_780 ) || defined( USE_BAND_868 ) 73 | 74 | #define LORAWAN_APP_DATA_SIZE 16 75 | 76 | #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) 77 | 78 | #define LORAWAN_APP_DATA_SIZE 11 79 | 80 | #endif 81 | 82 | static uint8_t DevEui[] = LORAWAN_DEVICE_EUI; 83 | static uint8_t AppEui[] = LORAWAN_APPLICATION_EUI; 84 | static uint8_t AppKey[] = LORAWAN_APPLICATION_KEY; 85 | 86 | /*! 87 | * Application port 88 | */ 89 | static uint8_t AppPort = LORAWAN_APP_PORT; 90 | 91 | static uint8_t AppData[] = { 0xde, 0xad, 0xbe, 0xef}; 92 | static uint8_t AppDataSize = sizeof(AppData); 93 | 94 | /*! 95 | * Indicates if the node is sending confirmed or unconfirmed messages 96 | */ 97 | static uint8_t IsTxConfirmed = LORAWAN_CONFIRMED_MSG_ON; 98 | 99 | /*! 100 | * Defines the application data transmission duty cycle 101 | */ 102 | static uint32_t TxDutyCycleTime; 103 | 104 | /*! 105 | * Timer to handle the application data transmission duty cycle 106 | */ 107 | TIMER_DEF(TxNextPacketTimer); 108 | 109 | /*! 110 | * Indicates if a new packet can be sent 111 | */ 112 | static bool NextTx = true; 113 | 114 | /*! 115 | * Device states 116 | */ 117 | static enum eDeviceState 118 | { 119 | DEVICE_STATE_INIT, 120 | DEVICE_STATE_JOIN, 121 | DEVICE_STATE_SEND, 122 | DEVICE_STATE_CYCLE, 123 | DEVICE_STATE_SLEEP 124 | } DeviceState; 125 | 126 | 127 | /*! 128 | * \brief Prepares the payload of the frame 129 | */ 130 | static void PrepareTxFrame( uint8_t port ) 131 | { 132 | switch( port ) 133 | { 134 | case 2: 135 | break; 136 | default: 137 | break; 138 | } 139 | } 140 | 141 | /*! 142 | * \brief Prepares the payload of the frame 143 | * 144 | * \retval [0: frame could be send, 1: error] 145 | */ 146 | static bool SendFrame( void ) 147 | { 148 | McpsReq_t mcpsReq; 149 | LoRaMacTxInfo_t txInfo; 150 | 151 | if( LoRaMacQueryTxPossible( AppDataSize, &txInfo ) != LORAMAC_STATUS_OK ) 152 | { 153 | // Send empty frame in order to flush MAC commands 154 | mcpsReq.Type = MCPS_UNCONFIRMED; 155 | mcpsReq.Req.Unconfirmed.fBuffer = NULL; 156 | mcpsReq.Req.Unconfirmed.fBufferSize = 0; 157 | mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE; 158 | } 159 | else 160 | { 161 | if( IsTxConfirmed == false ) 162 | { 163 | mcpsReq.Type = MCPS_UNCONFIRMED; 164 | mcpsReq.Req.Unconfirmed.fPort = AppPort; 165 | mcpsReq.Req.Unconfirmed.fBuffer = AppData; 166 | mcpsReq.Req.Unconfirmed.fBufferSize = AppDataSize; 167 | mcpsReq.Req.Unconfirmed.Datarate = LORAWAN_DEFAULT_DATARATE; 168 | } 169 | else 170 | { 171 | mcpsReq.Type = MCPS_CONFIRMED; 172 | mcpsReq.Req.Confirmed.fPort = AppPort; 173 | mcpsReq.Req.Confirmed.fBuffer = AppData; 174 | mcpsReq.Req.Confirmed.fBufferSize = AppDataSize; 175 | mcpsReq.Req.Confirmed.NbTrials = 8; 176 | mcpsReq.Req.Confirmed.Datarate = LORAWAN_DEFAULT_DATARATE; 177 | } 178 | } 179 | 180 | if( LoRaMacMcpsRequest( &mcpsReq ) == LORAMAC_STATUS_OK ) 181 | { 182 | return false; 183 | } 184 | return true; 185 | } 186 | 187 | /*! 188 | * \brief Function executed on TxNextPacket Timeout event 189 | */ 190 | static void OnTxNextPacketTimerEvent( void * ctx ) 191 | { 192 | MibRequestConfirm_t mibReq; 193 | LoRaMacStatus_t status; 194 | 195 | TimerStop( &TxNextPacketTimer ); 196 | 197 | mibReq.Type = MIB_NETWORK_JOINED; 198 | status = LoRaMacMibGetRequestConfirm( &mibReq ); 199 | 200 | if( status == LORAMAC_STATUS_OK ) 201 | { 202 | if( mibReq.Param.IsNetworkJoined == true ) 203 | { 204 | DeviceState = DEVICE_STATE_SEND; 205 | NextTx = true; 206 | } 207 | else 208 | { 209 | DeviceState = DEVICE_STATE_JOIN; 210 | } 211 | } 212 | } 213 | 214 | /*! 215 | * \brief MCPS-Confirm event function 216 | * 217 | * \param [IN] mcpsConfirm - Pointer to the confirm structure, 218 | * containing confirm attributes. 219 | */ 220 | static void McpsConfirm( McpsConfirm_t *mcpsConfirm ) 221 | { 222 | if( mcpsConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) 223 | { 224 | switch( mcpsConfirm->McpsRequest ) 225 | { 226 | case MCPS_UNCONFIRMED: 227 | { 228 | // Check Datarate 229 | // Check TxPower 230 | break; 231 | } 232 | case MCPS_CONFIRMED: 233 | { 234 | // Check Datarate 235 | // Check TxPower 236 | // Check AckReceived 237 | // Check NbTrials 238 | break; 239 | } 240 | case MCPS_PROPRIETARY: 241 | { 242 | break; 243 | } 244 | default: 245 | break; 246 | } 247 | } 248 | NextTx = true; 249 | } 250 | 251 | /*! 252 | * \brief MCPS-Indication event function 253 | * 254 | * \param [IN] mcpsIndication - Pointer to the indication structure, 255 | * containing indication attributes. 256 | */ 257 | static void McpsIndication( McpsIndication_t *mcpsIndication ) 258 | { 259 | if( mcpsIndication->Status != LORAMAC_EVENT_INFO_STATUS_OK ) 260 | { 261 | return; 262 | } 263 | 264 | switch( mcpsIndication->McpsIndication ) 265 | { 266 | case MCPS_UNCONFIRMED: 267 | { 268 | break; 269 | } 270 | case MCPS_CONFIRMED: 271 | { 272 | break; 273 | } 274 | case MCPS_PROPRIETARY: 275 | { 276 | break; 277 | } 278 | case MCPS_MULTICAST: 279 | { 280 | break; 281 | } 282 | default: 283 | break; 284 | } 285 | 286 | // Check Multicast 287 | // Check Port 288 | // Check Datarate 289 | // Check FramePending 290 | // Check Buffer 291 | // Check BufferSize 292 | // Check Rssi 293 | // Check Snr 294 | // Check RxSlot 295 | if( mcpsIndication->RxData == true ) 296 | { 297 | switch( mcpsIndication->Port ) 298 | { 299 | default: 300 | break; 301 | } 302 | } 303 | } 304 | 305 | /*! 306 | * \brief MLME-Confirm event function 307 | * 308 | * \param [IN] mlmeConfirm - Pointer to the confirm structure, 309 | * containing confirm attributes. 310 | */ 311 | static void MlmeConfirm( MlmeConfirm_t *mlmeConfirm ) 312 | { 313 | switch( mlmeConfirm->MlmeRequest ) 314 | { 315 | case MLME_JOIN: 316 | { 317 | if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) 318 | { 319 | // Status is OK, node has joined the network 320 | DeviceState = DEVICE_STATE_SEND; 321 | } 322 | else 323 | { 324 | // Join was not successful. Try to join again 325 | DeviceState = DEVICE_STATE_JOIN; 326 | } 327 | break; 328 | } 329 | case MLME_LINK_CHECK: 330 | { 331 | if( mlmeConfirm->Status == LORAMAC_EVENT_INFO_STATUS_OK ) 332 | { 333 | } 334 | break; 335 | } 336 | default: 337 | break; 338 | } 339 | NextTx = true; 340 | } 341 | 342 | LoRaMacPrimitives_t LoRaMacPrimitives; 343 | LoRaMacCallback_t LoRaMacCallbacks; 344 | MibRequestConfirm_t mibReq; 345 | 346 | void lora_sm( void ) 347 | { 348 | switch( DeviceState ) 349 | { 350 | case DEVICE_STATE_INIT: 351 | { 352 | NRF_LOG_DEBUG("INIT\r\n"); 353 | LoRaMacPrimitives.MacMcpsConfirm = McpsConfirm; 354 | LoRaMacPrimitives.MacMcpsIndication = McpsIndication; 355 | LoRaMacPrimitives.MacMlmeConfirm = MlmeConfirm; 356 | // LoRaMacCallbacks.GetBatteryLevel = BoardGetBatteryLevel; 357 | LoRaMacInitialization( &LoRaMacPrimitives, &LoRaMacCallbacks ); 358 | 359 | TxNextPacketTimer.id = TxNextPacketTimer_app; 360 | TIMER_INIT( TxNextPacketTimer, OnTxNextPacketTimerEvent ); 361 | 362 | mibReq.Type = MIB_ADR; 363 | mibReq.Param.AdrEnable = LORAWAN_ADR_ON; 364 | LoRaMacMibSetRequestConfirm( &mibReq ); 365 | 366 | mibReq.Type = MIB_PUBLIC_NETWORK; 367 | mibReq.Param.EnablePublicNetwork = LORAWAN_PUBLIC_NETWORK; 368 | LoRaMacMibSetRequestConfirm( &mibReq ); 369 | 370 | LoRaMacTestSetDutyCycleOn( LORAWAN_DUTYCYCLE_ON ); 371 | 372 | LoRaMacChannelAdd( 3, ( ChannelParams_t )LC4 ); 373 | LoRaMacChannelAdd( 4, ( ChannelParams_t )LC5 ); 374 | LoRaMacChannelAdd( 5, ( ChannelParams_t )LC6 ); 375 | LoRaMacChannelAdd( 6, ( ChannelParams_t )LC7 ); 376 | LoRaMacChannelAdd( 7, ( ChannelParams_t )LC8 ); 377 | LoRaMacChannelAdd( 8, ( ChannelParams_t )LC9 ); 378 | LoRaMacChannelAdd( 9, ( ChannelParams_t )LC10 ); 379 | 380 | mibReq.Type = MIB_RX2_DEFAULT_CHANNEL; 381 | mibReq.Param.Rx2DefaultChannel = ( Rx2ChannelParams_t ){ 869525000, DR_3 }; 382 | LoRaMacMibSetRequestConfirm( &mibReq ); 383 | 384 | mibReq.Type = MIB_RX2_CHANNEL; 385 | mibReq.Param.Rx2Channel = ( Rx2ChannelParams_t ){ 869525000, DR_3 }; 386 | LoRaMacMibSetRequestConfirm( &mibReq ); 387 | DeviceState = DEVICE_STATE_JOIN; 388 | NRF_LOG_DEBUG("INIT done\r\n"); 389 | break; 390 | } 391 | case DEVICE_STATE_JOIN: 392 | { 393 | NRF_LOG_DEBUG("JOIN\r\n"); 394 | MlmeReq_t mlmeReq; 395 | 396 | // Initialize LoRaMac device unique ID 397 | BoardGetUniqueId( DevEui ); 398 | NRF_LOG_DEBUG("DevEUI:\r\n"); 399 | NRF_LOG_HEXDUMP_DEBUG(DevEui, sizeof(DevEui)); 400 | NRF_LOG_DEBUG("AppEUI:\r\n"); 401 | NRF_LOG_HEXDUMP_DEBUG(AppEui, sizeof(AppEui)); 402 | NRF_LOG_DEBUG("AppKey:\r\n"); 403 | NRF_LOG_HEXDUMP_DEBUG(AppKey, sizeof(AppKey)); 404 | 405 | mlmeReq.Type = MLME_JOIN; 406 | 407 | mlmeReq.Req.Join.DevEui = DevEui; 408 | mlmeReq.Req.Join.AppEui = AppEui; 409 | mlmeReq.Req.Join.AppKey = AppKey; 410 | mlmeReq.Req.Join.NbTrials = 3; 411 | 412 | if( NextTx == true ) 413 | { 414 | LoRaMacMlmeRequest( &mlmeReq ); 415 | } 416 | DeviceState = DEVICE_STATE_SLEEP; 417 | NRF_LOG_DEBUG("JOIN done\r\n"); 418 | break; 419 | } 420 | case DEVICE_STATE_SEND: 421 | { 422 | NRF_LOG_DEBUG("SEND\r\n"); 423 | if( NextTx == true ) 424 | { 425 | PrepareTxFrame( AppPort ); 426 | 427 | NextTx = SendFrame( ); 428 | } 429 | // Schedule next packet transmission 430 | TxDutyCycleTime = APP_TX_DUTYCYCLE + randr( -APP_TX_DUTYCYCLE_RND, APP_TX_DUTYCYCLE_RND ); 431 | DeviceState = DEVICE_STATE_CYCLE; 432 | NRF_LOG_DEBUG("SEND done\r\n"); 433 | break; 434 | } 435 | case DEVICE_STATE_CYCLE: 436 | { 437 | DeviceState = DEVICE_STATE_SLEEP; 438 | 439 | // Schedule next packet transmission 440 | TimerSetValue( &TxNextPacketTimer, TxDutyCycleTime ); 441 | TimerStart( &TxNextPacketTimer ); 442 | break; 443 | } 444 | case DEVICE_STATE_SLEEP: 445 | { 446 | // Wake up through events 447 | break; 448 | } 449 | default: 450 | { 451 | DeviceState = DEVICE_STATE_INIT; 452 | break; 453 | } 454 | } 455 | } 456 | -------------------------------------------------------------------------------- /board/lora.h: -------------------------------------------------------------------------------- 1 | #ifndef _LORA_H 2 | #define _LORA_H 3 | 4 | void lora_sm(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /board/pinName-board.h: -------------------------------------------------------------------------------- 1 | #ifndef __PIN_NAME_MCU_H__ 2 | #define __PIN_NAME_MCU_H__ 3 | 4 | /*! 5 | * nRF52 Pin Names 6 | */ 7 | #define MCU_PINS \ 8 | P0, P1, P2, P3, P4, P5, P6, P7, P8, P9,\ 9 | P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, \ 10 | P20, P21, P22, P23, P24, P25, P26, P27, P28, P29, \ 11 | P30, P31 12 | #endif // __PIN_NAME_MCU_H__ 13 | -------------------------------------------------------------------------------- /board/rtc.c: -------------------------------------------------------------------------------- 1 | #include "rtc.h" 2 | 3 | #include "app_config.h" 4 | #include "nrf_drv_rtc.h" 5 | #include "nrf_rtc.h" 6 | 7 | #define NRF_LOG_MODULE_NAME "RTC" 8 | #define NRF_LOG_LEVEL 3 9 | #include "nrf_log.h" 10 | 11 | const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2); /**< Declaring an instance of nrf_drv_rtc for RTC0. */ 12 | 13 | static uint32_t timestamp_base = 0; 14 | static rtc_wakeup_callback_t wakeup_clbk = NULL; 15 | 16 | static void rtc_handler(nrf_drv_rtc_int_type_t int_type) 17 | { 18 | if (int_type == NRF_DRV_RTC_INT_OVERFLOW) { 19 | uint32_t old_base = timestamp_base; 20 | timestamp_base += nrf_drv_rtc_max_ticks_get(&rtc)/RTC_FREQUENCY; 21 | NRF_LOG_DEBUG("overflow %d %d\r\n", 22 | old_base, timestamp_base); 23 | } 24 | if (int_type == NRF_DRV_RTC_INT_COMPARE0) { 25 | NRF_LOG_DEBUG("COMPARE0 wakeup\r\n"); 26 | if (wakeup_clbk) 27 | wakeup_clbk(); 28 | } 29 | } 30 | 31 | uint32_t rtc_get_timestamp(void) 32 | { 33 | uint32_t ticks = nrf_drv_rtc_counter_get(&rtc); 34 | uint32_t timestamp = timestamp_base + ticks/RTC_FREQUENCY; 35 | /* 36 | NRF_LOG_DEBUG("get_timestamp %d %d %d\r\n", 37 | ticks, timestamp, timestamp_base); 38 | */ 39 | return timestamp; 40 | } 41 | 42 | void rtc_update_timestamp(uint32_t timebase) 43 | { 44 | NRF_LOG_DEBUG("update_timestamp old: 0x%08x new: 0x%08x\r\n", 45 | timestamp_base, timebase); 46 | timestamp_base = timebase; 47 | } 48 | 49 | ret_code_t rtc_init(rtc_wakeup_callback_t clbk) 50 | { 51 | NRF_LOG_DEBUG("init rtc_freq: %d\r\n", RTC_FREQUENCY); 52 | ret_code_t err_code; 53 | 54 | //Initialize RTC instance 55 | nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG; 56 | config.prescaler = RTC_FREQ_TO_PRESCALER(RTC_FREQUENCY); 57 | err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler); 58 | APP_ERROR_CHECK(err_code); 59 | 60 | //Enable tick event - no interrupt, we need tick just to drive ADC 61 | nrf_drv_rtc_tick_enable(&rtc, false); 62 | nrf_drv_rtc_overflow_enable(&rtc, true); 63 | 64 | //Power on RTC instance 65 | nrf_drv_rtc_enable(&rtc); 66 | NRF_LOG_DEBUG("enabled prescaler: %d max_tics: %d\r\n", 67 | rtc_prescaler_get(rtc.p_reg), 68 | nrf_drv_rtc_max_ticks_get(&rtc)); 69 | 70 | wakeup_clbk = clbk; 71 | return err_code; 72 | } 73 | 74 | void rtc_test_overflow(void) 75 | { 76 | NRF_LOG_DEBUG("test_overflow\r\n"); 77 | nrf_rtc_task_trigger(rtc.p_reg, NRF_RTC_TASK_TRIGGER_OVERFLOW); 78 | } 79 | 80 | ret_code_t rtc_schedule_wakeup(uint32_t timeout) 81 | { 82 | NRF_LOG_DEBUG("schedule_wakeup %d\r\n", timeout); 83 | uint32_t ticks = nrf_drv_rtc_counter_get(&rtc); 84 | uint32_t timeout_ticks = timeout*RTC_FREQUENCY; 85 | uint32_t compare_val = 0; 86 | uint32_t max_ticks = nrf_drv_rtc_max_ticks_get(&rtc); 87 | if (ticks + timeout_ticks > max_ticks) { 88 | compare_val = (max_ticks - ticks) + timeout_ticks; 89 | } else { 90 | compare_val = ticks + timeout_ticks; 91 | } 92 | NRF_LOG_DEBUG("rtc_cc_set %d %d\r\n", ticks, compare_val); 93 | return nrf_drv_rtc_cc_set(&rtc, 0, compare_val, true); 94 | } 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /board/rtc.h: -------------------------------------------------------------------------------- 1 | #ifndef _RTC_H 2 | #define _RTC_H 3 | 4 | #include 5 | #include 6 | #include "app_error.h" 7 | 8 | typedef void (*rtc_wakeup_callback_t)(void); 9 | 10 | ret_code_t rtc_init(rtc_wakeup_callback_t); 11 | uint32_t rtc_get_timestamp(void); 12 | void rtc_update_timestamp(uint32_t); 13 | void rtc_test_overflow(void); 14 | ret_code_t rtc_schedule_wakeup(uint32_t); 15 | 16 | #endif /* _RTC_H */ 17 | -------------------------------------------------------------------------------- /board/spi.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | #include "nrf_drv_spi.h" 3 | 4 | #define NRF_LOG_MODULE_NAME "SPI" 5 | #define NRF_LOG_LEVEL 3 6 | #include "nrf_log.h" 7 | 8 | void SpiInit( Spi_t *obj, 9 | PinNames mosi, 10 | PinNames miso, 11 | PinNames sclk, 12 | PinNames nss ) 13 | { 14 | ret_code_t err_code; 15 | NRF_LOG_DEBUG("Init 0x%x %d %d %d %d\r\n", 16 | (uint32_t)obj, 17 | mosi, 18 | miso, 19 | sclk, 20 | nss); 21 | obj->Instance.p_registers = NRF_SPI0; 22 | obj->Instance.irq = SPI0_IRQ; 23 | obj->Instance.drv_inst_idx = SPI0_INSTANCE_INDEX; 24 | obj->Instance.use_easy_dma = SPI0_USE_EASY_DMA; 25 | 26 | obj->Config.sck_pin = sclk; 27 | obj->Config.mosi_pin = mosi; 28 | obj->Config.miso_pin = miso; 29 | obj->Config.ss_pin = nss; 30 | obj->Config.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY; 31 | obj->Config.orc = 0xFF; 32 | obj->Config.mode = NRF_DRV_SPI_MODE_0; 33 | obj->Config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST; 34 | obj->Config.frequency = NRF_DRV_SPI_FREQ_1M; 35 | err_code = nrf_drv_spi_init(&obj->Instance, &obj->Config, 36 | NULL, NULL); 37 | 38 | if (err_code != NRF_SUCCESS) { 39 | NRF_LOG_ERROR("error: %d\r\n", err_code); 40 | return; 41 | } 42 | obj->initialized = true; 43 | } 44 | 45 | void SpiDeInit( Spi_t *obj ) 46 | { 47 | NRF_LOG_DEBUG("DeInit 0x%x\r\n", (uint32_t)obj); 48 | if (obj->initialized) { 49 | nrf_drv_spi_uninit(&obj->Instance); 50 | obj->initialized = false; 51 | } 52 | } 53 | 54 | void SpiOut( Spi_t *obj, uint8_t addr, uint8_t *outData, uint8_t outLen ) 55 | { 56 | NRF_LOG_DEBUG("Out 0x%x 0x%x 0x%x %d\r\n", 57 | (uint32_t)obj, 58 | addr, 59 | (uint32_t)outData, 60 | outLen); 61 | if (obj->initialized != true) { 62 | NRF_LOG_ERROR("not initilized\r\n"); 63 | return; 64 | } 65 | 66 | uint8_t tx[outLen+1]; 67 | tx[0] = addr | 0x80; 68 | memcpy(&tx[1], outData, outLen); 69 | 70 | ret_code_t err_code = nrf_drv_spi_transfer(&obj->Instance, 71 | tx, 72 | sizeof(tx), 73 | NULL, 74 | 0); 75 | 76 | if (err_code != NRF_SUCCESS) { 77 | NRF_LOG_ERROR("error %d\r\n", err_code); 78 | } 79 | NRF_LOG_DEBUG("Sent: \r\n"); 80 | NRF_LOG_HEXDUMP_DEBUG(outData, outLen); 81 | 82 | return; 83 | } 84 | 85 | void SpiIn( Spi_t *obj, uint8_t addr, uint8_t *inData, uint8_t inLen ) 86 | { 87 | NRF_LOG_DEBUG("In 0x%x 0x%x 0x%x %d\r\n", 88 | (uint32_t)obj, 89 | addr, 90 | (uint32_t)inData, 91 | inLen); 92 | 93 | if (obj->initialized != true) { 94 | NRF_LOG_ERROR("not initilized\r\n"); 95 | return; 96 | } 97 | 98 | uint8_t tx[] = { addr & 0x7F }; 99 | uint8_t rx[inLen+1]; 100 | ret_code_t err_code = nrf_drv_spi_transfer(&obj->Instance, 101 | tx, 102 | 1, 103 | rx, 104 | inLen+1); 105 | 106 | if (err_code != NRF_SUCCESS) { 107 | NRF_LOG_ERROR("error %d\r\n", err_code); 108 | } 109 | memcpy(inData, &rx[1], inLen); 110 | NRF_LOG_DEBUG(" Received: \r\n"); 111 | NRF_LOG_HEXDUMP_DEBUG(inData, inLen); 112 | 113 | return; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /board/spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Implements the generic SPI driver 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __SPI_H__ 16 | #define __SPI_H__ 17 | 18 | #include "nrf_drv_spi.h" 19 | 20 | /*! 21 | * SPI driver structure definition 22 | */ 23 | struct Spi_handle { 24 | nrf_drv_spi_t Instance; 25 | nrf_drv_spi_config_t Config; 26 | bool initialized; 27 | }; 28 | 29 | /*! 30 | * SPI object type definition 31 | */ 32 | typedef struct Spi_handle Spi_t; 33 | 34 | /*! 35 | * \brief Initializes the SPI object and MCU peripheral 36 | * 37 | * \remark When NSS pin is software controlled set the pin name to NC otherwise 38 | * set the pin name to be used. 39 | * 40 | * \param [IN] obj SPI object 41 | * \param [IN] mosi SPI MOSI pin name to be used 42 | * \param [IN] miso SPI MISO pin name to be used 43 | * \param [IN] sclk SPI SCLK pin name to be used 44 | * \param [IN] nss SPI NSS pin name to be used 45 | */ 46 | void SpiInit( Spi_t *obj, PinNames mosi, PinNames miso, PinNames sclk, PinNames nss ); 47 | 48 | /*! 49 | * \brief De-initializes the SPI object and MCU peripheral 50 | * 51 | * \param [IN] obj SPI object 52 | */ 53 | void SpiDeInit( Spi_t *obj ); 54 | 55 | /*! 56 | * \brief Writes outData buffer to register addr 57 | * 58 | * \param [IN] obj SPI object 59 | * \param [IN] addr Register address 60 | * \param [IN] outData Bytes to be sent 61 | * \param [IN] outLen Number of bytes to be sent 62 | */ 63 | void SpiOut( Spi_t *obj, uint8_t addr, uint8_t *outData, uint8_t outLen ); 64 | 65 | /*! 66 | * \brief Read inData buffer from register addr 67 | * 68 | * \param [IN] obj SPI object 69 | * \param [IN] addr Register address 70 | * \param [OUT] inData Bytes read 71 | * \param [IN] inLen Maximum number of bytes to be read (size of buffer) 72 | */ 73 | void SpiIn( Spi_t *obj, uint8_t addr, uint8_t *inData, uint8_t inLen); 74 | 75 | #endif // __SPI_H__ 76 | -------------------------------------------------------------------------------- /board/sx1276-board.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | #include "radio.h" 3 | #include "sx1276/sx1276.h" 4 | #include "sx1276-board.h" 5 | 6 | #define NRF_LOG_MODULE_NAME "SX1276" 7 | #define NRF_LOG_LEVEL 4 8 | #include "nrf_log.h" 9 | 10 | /*! 11 | * Flag used to set the RF switch control pins in low power mode when the radio is not active. 12 | */ 13 | static bool RadioIsActive = false; 14 | 15 | /*! 16 | * Radio driver structure initialization 17 | */ 18 | const struct Radio_s Radio = 19 | { 20 | SX1276Init, 21 | SX1276GetStatus, 22 | SX1276SetModem, 23 | SX1276SetChannel, 24 | SX1276IsChannelFree, 25 | SX1276Random, 26 | SX1276SetRxConfig, 27 | SX1276SetTxConfig, 28 | SX1276CheckRfFrequency, 29 | SX1276GetTimeOnAir, 30 | SX1276Send, 31 | SX1276SetSleep, 32 | SX1276SetStby, 33 | SX1276SetRx, 34 | SX1276StartCad, 35 | SX1276SetTxContinuousWave, 36 | SX1276ReadRssi, 37 | SX1276Write, 38 | SX1276Read, 39 | SX1276WriteBuffer, 40 | SX1276ReadBuffer, 41 | SX1276SetMaxPayloadLength, 42 | SX1276SetPublicNetwork 43 | }; 44 | 45 | /*! 46 | * Antenna switch GPIO pins objects 47 | */ 48 | Gpio_t AntSwitchHf; 49 | 50 | void SX1276IoInit( void ) 51 | { 52 | NRF_LOG_DEBUG("IoInit\r\n"); 53 | SpiInit( &SX1276.Spi, RADIO_MOSI, RADIO_MISO, RADIO_SCK, RADIO_NSS ); 54 | 55 | GpioInit( &SX1276.Reset, RADIO_RESET, PIN_OUTPUT, PIN_PUSH_PULL, PIN_NO_PULL, 0 ); 56 | 57 | GpioInit( &SX1276.DIO0, RADIO_DIO_0, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 58 | GpioInit( &SX1276.DIO1, RADIO_DIO_1, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 59 | GpioInit( &SX1276.DIO2, RADIO_DIO_2, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 60 | GpioInit( &SX1276.DIO3, RADIO_DIO_3, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 61 | GpioInit( &SX1276.DIO4, RADIO_DIO_4, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 62 | GpioInit( &SX1276.DIO5, RADIO_DIO_5, PIN_INPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 63 | NRF_LOG_DEBUG("IoInit done\r\n"); 64 | } 65 | 66 | void SX1276IoIrqInit( DioIrqHandler **irqHandlers ) 67 | { 68 | NRF_LOG_DEBUG("IoIrqInit\r\n"); 69 | GpioSetInterrupt( &SX1276.DIO0, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[0] ); 70 | GpioSetInterrupt( &SX1276.DIO1, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[1] ); 71 | GpioSetInterrupt( &SX1276.DIO2, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[2] ); 72 | GpioSetInterrupt( &SX1276.DIO3, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[3] ); 73 | GpioSetInterrupt( &SX1276.DIO4, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[4] ); 74 | GpioSetInterrupt( &SX1276.DIO5, IRQ_RISING_EDGE, IRQ_HIGH_PRIORITY, irqHandlers[5] ); 75 | NRF_LOG_DEBUG("IoIrqInit done\r\n"); 76 | } 77 | 78 | void SX1276IoDeInit( void ) 79 | { 80 | NRF_LOG_DEBUG("IoDeInit\r\n"); 81 | SpiDeInit( &SX1276.Spi ); 82 | 83 | GpioDeinit( &SX1276.DIO0 ); 84 | GpioDeinit( &SX1276.DIO1 ); 85 | GpioDeinit( &SX1276.DIO2 ); 86 | GpioDeinit( &SX1276.DIO3 ); 87 | GpioDeinit( &SX1276.DIO4 ); 88 | GpioDeinit( &SX1276.DIO5 ); 89 | NRF_LOG_DEBUG("IoDeInit done\r\n"); 90 | } 91 | 92 | void SX1276SetRfTxPower( int8_t power ) 93 | { 94 | uint8_t paConfig = 0; 95 | uint8_t paDac = 0; 96 | 97 | paConfig = SX1276Read( REG_PACONFIG ); 98 | paDac = SX1276Read( REG_PADAC ); 99 | 100 | paConfig = ( paConfig & RF_PACONFIG_PASELECT_MASK ) | SX1276GetPaSelect( SX1276.Settings.Channel ); 101 | paConfig = ( paConfig & RF_PACONFIG_MAX_POWER_MASK ) | 0x70; 102 | 103 | if( ( paConfig & RF_PACONFIG_PASELECT_PABOOST ) == RF_PACONFIG_PASELECT_PABOOST ) 104 | { 105 | if( power > 17 ) 106 | { 107 | paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_ON; 108 | } 109 | else 110 | { 111 | paDac = ( paDac & RF_PADAC_20DBM_MASK ) | RF_PADAC_20DBM_OFF; 112 | } 113 | if( ( paDac & RF_PADAC_20DBM_ON ) == RF_PADAC_20DBM_ON ) 114 | { 115 | if( power < 5 ) 116 | { 117 | power = 5; 118 | } 119 | if( power > 20 ) 120 | { 121 | power = 20; 122 | } 123 | paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 5 ) & 0x0F ); 124 | } 125 | else 126 | { 127 | if( power < 2 ) 128 | { 129 | power = 2; 130 | } 131 | if( power > 17 ) 132 | { 133 | power = 17; 134 | } 135 | paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power - 2 ) & 0x0F ); 136 | } 137 | } 138 | else 139 | { 140 | if( power < -1 ) 141 | { 142 | power = -1; 143 | } 144 | if( power > 14 ) 145 | { 146 | power = 14; 147 | } 148 | paConfig = ( paConfig & RF_PACONFIG_OUTPUTPOWER_MASK ) | ( uint8_t )( ( uint16_t )( power + 1 ) & 0x0F ); 149 | } 150 | SX1276Write( REG_PACONFIG, paConfig ); 151 | SX1276Write( REG_PADAC, paDac ); 152 | } 153 | 154 | uint8_t SX1276GetPaSelect( uint32_t channel ) 155 | { 156 | if( channel < RF_MID_BAND_THRESH ) 157 | { 158 | return RF_PACONFIG_PASELECT_PABOOST; 159 | } 160 | else 161 | { 162 | return RF_PACONFIG_PASELECT_RFO; 163 | } 164 | } 165 | 166 | void SX1276SetAntSwLowPower( bool status ) 167 | { 168 | if( RadioIsActive != status ) 169 | { 170 | RadioIsActive = status; 171 | 172 | if( status == false ) 173 | { 174 | SX1276AntSwInit( ); 175 | } 176 | else 177 | { 178 | SX1276AntSwDeInit( ); 179 | } 180 | } 181 | } 182 | 183 | void SX1276AntSwInit( void ) 184 | { 185 | GpioInit( &AntSwitchHf, RADIO_ANT_SWITCH_HF, PIN_OUTPUT, PIN_PUSH_PULL, PIN_PULL_UP, 0 ); 186 | } 187 | 188 | void SX1276AntSwDeInit( void ) 189 | { 190 | GpioDeinit( &AntSwitchHf ); 191 | } 192 | 193 | void SX1276SetAntSw( uint8_t opMode ) 194 | { 195 | switch( opMode ) 196 | { 197 | case RFLR_OPMODE_TRANSMITTER: 198 | GpioWrite( &AntSwitchHf, 1 ); 199 | break; 200 | case RFLR_OPMODE_RECEIVER: 201 | case RFLR_OPMODE_RECEIVER_SINGLE: 202 | case RFLR_OPMODE_CAD: 203 | default: 204 | GpioWrite( &AntSwitchHf, 0 ); 205 | break; 206 | } 207 | } 208 | 209 | bool SX1276CheckRfFrequency( uint32_t frequency ) 210 | { 211 | // Implement check. Currently all frequencies are supported 212 | return true; 213 | } 214 | -------------------------------------------------------------------------------- /board/sx1276-board.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: SX1276 driver specific target board functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __SX1276_ARCH_H__ 16 | #define __SX1276_ARCH_H__ 17 | 18 | /*! 19 | * \brief Radio hardware registers initialization definition 20 | * 21 | * \remark Can be automatically generated by the SX1276 GUI (not yet implemented) 22 | */ 23 | #define RADIO_INIT_REGISTERS_VALUE \ 24 | { \ 25 | { MODEM_FSK , REG_LNA , 0x23 },\ 26 | { MODEM_FSK , REG_RXCONFIG , 0x1E },\ 27 | { MODEM_FSK , REG_RSSICONFIG , 0xD2 },\ 28 | { MODEM_FSK , REG_AFCFEI , 0x01 },\ 29 | { MODEM_FSK , REG_PREAMBLEDETECT , 0xAA },\ 30 | { MODEM_FSK , REG_OSC , 0x07 },\ 31 | { MODEM_FSK , REG_SYNCCONFIG , 0x12 },\ 32 | { MODEM_FSK , REG_SYNCVALUE1 , 0xC1 },\ 33 | { MODEM_FSK , REG_SYNCVALUE2 , 0x94 },\ 34 | { MODEM_FSK , REG_SYNCVALUE3 , 0xC1 },\ 35 | { MODEM_FSK , REG_PACKETCONFIG1 , 0xD8 },\ 36 | { MODEM_FSK , REG_FIFOTHRESH , 0x8F },\ 37 | { MODEM_FSK , REG_IMAGECAL , 0x02 },\ 38 | { MODEM_FSK , REG_DIOMAPPING1 , 0x00 },\ 39 | { MODEM_FSK , REG_DIOMAPPING2 , 0x30 },\ 40 | { MODEM_LORA, REG_LR_PAYLOADMAXLENGTH, 0x40 },\ 41 | } \ 42 | 43 | #define RF_MID_BAND_THRESH 525000000 44 | 45 | /*! 46 | * \brief Initializes the radio I/Os pins interface 47 | */ 48 | void SX1276IoInit( void ); 49 | 50 | /*! 51 | * \brief Initializes DIO IRQ handlers 52 | * 53 | * \param [IN] irqHandlers Array containing the IRQ callback functions 54 | */ 55 | void SX1276IoIrqInit( DioIrqHandler **irqHandlers ); 56 | 57 | /*! 58 | * \brief De-initializes the radio I/Os pins interface. 59 | * 60 | * \remark Useful when going in MCU low power modes 61 | */ 62 | void SX1276IoDeInit( void ); 63 | 64 | /*! 65 | * \brief Sets the radio output power. 66 | * 67 | * \param [IN] power Sets the RF output power 68 | */ 69 | void SX1276SetRfTxPower( int8_t power ); 70 | 71 | /*! 72 | * \brief Gets the board PA selection configuration 73 | * 74 | * \param [IN] channel Channel frequency in Hz 75 | * \retval PaSelect RegPaConfig PaSelect value 76 | */ 77 | uint8_t SX1276GetPaSelect( uint32_t channel ); 78 | 79 | /*! 80 | * \brief Set the RF Switch I/Os pins in Low Power mode 81 | * 82 | * \param [IN] status enable or disable 83 | */ 84 | void SX1276SetAntSwLowPower( bool status ); 85 | 86 | /*! 87 | * \brief Initializes the RF Switch I/Os pins interface 88 | */ 89 | void SX1276AntSwInit( void ); 90 | 91 | /*! 92 | * \brief De-initializes the RF Switch I/Os pins interface 93 | * 94 | * \remark Needed to decrease the power consumption in MCU low power modes 95 | */ 96 | void SX1276AntSwDeInit( void ); 97 | 98 | /*! 99 | * \brief Controls the antenna switch if necessary. 100 | * 101 | * \remark see errata note 102 | * 103 | * \param [IN] opMode Current radio operating mode 104 | */ 105 | void SX1276SetAntSw( uint8_t opMode ); 106 | 107 | /*! 108 | * \brief Checks if the given RF frequency is supported by the hardware 109 | * 110 | * \param [IN] frequency RF frequency to be checked 111 | * \retval isSupported [true: supported, false: unsupported] 112 | */ 113 | bool SX1276CheckRfFrequency( uint32_t frequency ); 114 | 115 | /*! 116 | * Radio hardware and global parameters 117 | */ 118 | extern SX1276_t SX1276; 119 | 120 | #endif // __SX1276_ARCH_H__ 121 | -------------------------------------------------------------------------------- /board/timer.c: -------------------------------------------------------------------------------- 1 | #include "board.h" 2 | 3 | #define NRF_LOG_MODULE_NAME "TIMER" 4 | #define NRF_LOG_LEVEL 3 5 | #include "nrf_log.h" 6 | 7 | void TimerInit( TimerEvent_t *obj, void ( *callback )( void * ) ) 8 | { 9 | NRF_LOG_DEBUG("Init 0x%x 0x%x 0x%x\r\n", 10 | (uint32_t)obj, 11 | (uint32_t)obj->id, 12 | (uint32_t)callback); 13 | if (obj->id == NULL) { 14 | NRF_LOG_ERROR("0x%x not initialized\r\n", 15 | (uint32_t)obj); 16 | return; 17 | } 18 | ret_code_t err_code = app_timer_create(&obj->id, 19 | APP_TIMER_MODE_SINGLE_SHOT, 20 | callback); 21 | if (err_code != NRF_SUCCESS) { 22 | NRF_LOG_ERROR("Init 0x%x 0x%x 0x%x error %d\r\n", 23 | (uint32_t)obj, 24 | (uint32_t)obj->id, 25 | (uint32_t)callback, 26 | err_code); 27 | } 28 | }; 29 | 30 | 31 | void TimerStart( TimerEvent_t *obj ) 32 | { 33 | NRF_LOG_DEBUG("Start 0x%x %d\r\n", 34 | (uint32_t)obj, 35 | obj->timeout); 36 | if (obj->id == NULL || obj->timeout == 0) { 37 | NRF_LOG_ERROR("0x%x wrong state\r\n", 38 | (uint32_t)obj); 39 | return; 40 | } 41 | uint32_t ticks = APP_TIMER_TICKS(obj->timeout); 42 | if (ticks < APP_TIMER_MIN_TIMEOUT_TICKS) 43 | ticks = APP_TIMER_MIN_TIMEOUT_TICKS; 44 | 45 | ret_code_t err_code = app_timer_start(obj->id, 46 | ticks, 47 | NULL); 48 | if (err_code != NRF_SUCCESS) { 49 | NRF_LOG_DEBUG("Start 0x%x %d %d error %d\r\n", 50 | (uint32_t)obj, 51 | obj->timeout, 52 | ticks, 53 | err_code); 54 | } 55 | } 56 | 57 | void TimerStop( TimerEvent_t *obj ) 58 | { 59 | NRF_LOG_DEBUG("Stop 0x%x\r\n", 60 | (uint32_t)obj); 61 | if (obj->id == NULL) { 62 | NRF_LOG_ERROR("0x%x not initialized\r\n", 63 | (uint32_t)obj); 64 | return; 65 | } 66 | ret_code_t err_code = app_timer_stop(obj->id); 67 | if (err_code != NRF_SUCCESS) { 68 | NRF_LOG_DEBUG("Stop 0x%x error %d\r\n", 69 | (uint32_t)obj, 70 | err_code); 71 | } 72 | } 73 | 74 | void TimerSetValue( TimerEvent_t *obj, uint32_t value ) 75 | { 76 | NRF_LOG_DEBUG("SetValue 0x%x %d\r\n", 77 | (uint32_t)obj, 78 | value); 79 | if (value < 10) 80 | value = 10; 81 | obj->timeout = value; 82 | } 83 | 84 | TimerTime_t TimerGetCurrentTime( void ) 85 | { 86 | return rtc_get_timestamp(); 87 | } 88 | 89 | TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ) 90 | { 91 | uint32_t ts = rtc_get_timestamp(); 92 | uint32_t elapsed = 0; 93 | if (savedTime < ts) 94 | elapsed = ts - savedTime; 95 | 96 | return elapsed; 97 | } 98 | 99 | -------------------------------------------------------------------------------- /board/timer.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Timer objects and scheduling management 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __TIMER_H__ 16 | #define __TIMER_H__ 17 | 18 | #include "app_timer.h" 19 | 20 | /*! 21 | * \brief Timer object description 22 | */ 23 | typedef struct { 24 | app_timer_id_t id; 25 | uint32_t timeout; 26 | }TimerEvent_t; 27 | 28 | typedef uint32_t TimerTime_t; 29 | 30 | #define TIMER_DEF(timer_id)\ 31 | APP_TIMER_DEF(timer_id##_app); \ 32 | static TimerEvent_t timer_id; 33 | 34 | 35 | /*! 36 | * \brief Initializes the timer object 37 | * 38 | * \remark TimerSetValue function must be called before starting the timer. 39 | * this function initializes timestamp and reload value at 0. 40 | * 41 | * \param [IN] obj Structure containing the timer object parameters 42 | * \param [IN] callback Function callback called at the end of the timeout 43 | */ 44 | void TimerInit( TimerEvent_t *obj, void ( *callback )( void *) ); 45 | 46 | #define TIMER_INIT(timer_id, clbk)\ 47 | timer_id.id = timer_id##_app; \ 48 | TimerInit(&timer_id, clbk); 49 | 50 | /*! 51 | * \brief Starts and adds the timer object to the list of timer events 52 | * 53 | * \param [IN] obj Structure containing the timer object parameters 54 | */ 55 | void TimerStart( TimerEvent_t *obj ); 56 | 57 | /*! 58 | * \brief Stops and removes the timer object from the list of timer events 59 | * 60 | * \param [IN] obj Structure containing the timer object parameters 61 | */ 62 | void TimerStop( TimerEvent_t *obj ); 63 | 64 | /*! 65 | * \brief Set timer new timeout value 66 | * 67 | * \param [IN] obj Structure containing the timer object parameters 68 | * \param [IN] value New timer timeout value 69 | */ 70 | void TimerSetValue( TimerEvent_t *obj, uint32_t value ); 71 | 72 | /*! 73 | * \brief Read the current time 74 | * 75 | * \retval time returns current time 76 | */ 77 | TimerTime_t TimerGetCurrentTime( void ); 78 | 79 | /*! 80 | * \brief Return the Time elapsed since a fix moment in Time 81 | * 82 | * \param [IN] savedTime fix moment in Time 83 | * \retval time returns elapsed time 84 | */ 85 | TimerTime_t TimerGetElapsedTime( TimerTime_t savedTime ); 86 | 87 | #endif // __TIMER_H__ 88 | -------------------------------------------------------------------------------- /board/utilities.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Helper functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #include 16 | #include 17 | #include "board.h" 18 | #include "utilities.h" 19 | #include "nrf_delay.h" 20 | 21 | /*! 22 | * Redefinition of rand() and srand() standard C functions. 23 | * These functions are redefined in order to get the same behavior across 24 | * different compiler toolchains implementations. 25 | */ 26 | // Standard random functions redefinition start 27 | #define RAND_LOCAL_MAX 2147483647L 28 | 29 | static uint32_t next = 1; 30 | 31 | int32_t rand1( void ) 32 | { 33 | return ( ( next = next * 1103515245L + 12345L ) % RAND_LOCAL_MAX ); 34 | } 35 | 36 | void srand1( uint32_t seed ) 37 | { 38 | next = seed; 39 | } 40 | // Standard random functions redefinition end 41 | 42 | int32_t randr( int32_t min, int32_t max ) 43 | { 44 | return ( int32_t )rand1( ) % ( max - min + 1 ) + min; 45 | } 46 | 47 | void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ) 48 | { 49 | while( size-- ) 50 | { 51 | *dst++ = *src++; 52 | } 53 | } 54 | 55 | void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ) 56 | { 57 | dst = dst + ( size - 1 ); 58 | while( size-- ) 59 | { 60 | *dst-- = *src++; 61 | } 62 | } 63 | 64 | void memset1( uint8_t *dst, uint8_t value, uint16_t size ) 65 | { 66 | while( size-- ) 67 | { 68 | *dst++ = value; 69 | } 70 | } 71 | 72 | int8_t Nibble2HexChar( uint8_t a ) 73 | { 74 | if( a < 10 ) 75 | { 76 | return '0' + a; 77 | } 78 | else if( a < 16 ) 79 | { 80 | return 'A' + ( a - 10 ); 81 | } 82 | else 83 | { 84 | return '?'; 85 | } 86 | } 87 | void Delay( float s ) 88 | { 89 | DelayMs( s * 1000.0f); 90 | } 91 | 92 | void DelayMs( uint32_t ms ) 93 | { 94 | nrf_delay_ms(ms); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /board/utilities.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Helper functions implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __UTILITIES_H__ 16 | #define __UTILITIES_H__ 17 | 18 | #include "nordic_common.h" 19 | /*! 20 | * \brief Returns 2 raised to the power of n 21 | * 22 | * \param [IN] n power value 23 | * \retval result of raising 2 to the power n 24 | */ 25 | #define POW2( n ) ( 1 << n ) 26 | 27 | /*! 28 | * \brief Initializes the pseudo random generator initial value 29 | * 30 | * \param [IN] seed Pseudo random generator initial value 31 | */ 32 | void srand1( uint32_t seed ); 33 | 34 | /*! 35 | * \brief Computes a random number between min and max 36 | * 37 | * \param [IN] min range minimum value 38 | * \param [IN] max range maximum value 39 | * \retval random random value in range min..max 40 | */ 41 | int32_t randr( int32_t min, int32_t max ); 42 | 43 | /*! 44 | * \brief Copies size elements of src array to dst array 45 | * 46 | * \remark STM32 Standard memcpy function only works on pointers that are aligned 47 | * 48 | * \param [OUT] dst Destination array 49 | * \param [IN] src Source array 50 | * \param [IN] size Number of bytes to be copied 51 | */ 52 | void memcpy1( uint8_t *dst, const uint8_t *src, uint16_t size ); 53 | 54 | /*! 55 | * \brief Copies size elements of src array to dst array reversing the byte order 56 | * 57 | * \param [OUT] dst Destination array 58 | * \param [IN] src Source array 59 | * \param [IN] size Number of bytes to be copied 60 | */ 61 | void memcpyr( uint8_t *dst, const uint8_t *src, uint16_t size ); 62 | 63 | /*! 64 | * \brief Set size elements of dst array with value 65 | * 66 | * \remark STM32 Standard memset function only works on pointers that are aligned 67 | * 68 | * \param [OUT] dst Destination array 69 | * \param [IN] value Default value 70 | * \param [IN] size Number of bytes to be copied 71 | */ 72 | void memset1( uint8_t *dst, uint8_t value, uint16_t size ); 73 | 74 | /*! 75 | * \brief Converts a nibble to an hexadecimal character 76 | * 77 | * \param [IN] a Nibble to be converted 78 | * \retval hexChar Converted hexadecimal character 79 | */ 80 | int8_t Nibble2HexChar( uint8_t a ); 81 | 82 | /*! 83 | * Blocking delay of "s" seconds 84 | */ 85 | void Delay( float s ); 86 | 87 | /*! 88 | * Blocking delay of "ms" milliseconds 89 | */ 90 | void DelayMs( uint32_t ms ); 91 | 92 | 93 | #endif // __UTILITIES_H__ 94 | -------------------------------------------------------------------------------- /config/Comissioning.h: -------------------------------------------------------------------------------- 1 | #ifndef __LORA_COMISSIONING_H__ 2 | #define __LORA_COMISSIONING_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define LORAWAN_DEVICE_ADDRESS 0 9 | 10 | /*! 11 | * When set to 1 the application uses the Over-the-Air activation procedure 12 | * When set to 0 the application uses the Personalization activation procedure 13 | */ 14 | #define OVER_THE_AIR_ACTIVATION 1 15 | 16 | /*! 17 | * Indicates if the end-device is to be connected to a private or public network 18 | */ 19 | #define LORAWAN_PUBLIC_NETWORK 1 20 | 21 | /*! 22 | * When set to 1 DevEui is LORAWAN_DEVICE_EUI 23 | * When set to 0 DevEui is automatically generated by calling 24 | * BoardGetUniqueId function 25 | */ 26 | #define STATIC_DEVICE_EUI 0 27 | 28 | /*! 29 | * Mote device IEEE EUI (big endian) 30 | * 31 | * \remark see STATIC_DEVICE_EUI comments 32 | */ 33 | #define LORAWAN_DEVICE_EUI { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 } 34 | 35 | 36 | /*! 37 | * Application IEEE EUI (big endian) 38 | */ 39 | #define LORAWAN_APPLICATION_EUI { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7 } 40 | 41 | /*! 42 | * AES encryption/decryption cipher application key 43 | */ 44 | #define LORAWAN_APPLICATION_KEY { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF } 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif 49 | 50 | #endif /* __LORA_COMISSIONING_H__ */ 51 | -------------------------------------------------------------------------------- /config/app_config.h: -------------------------------------------------------------------------------- 1 | #ifndef _APP_CONFIG_H 2 | #define _APP_CONFIG_H 3 | 4 | #ifndef BUILD_VERSION 5 | #define BUILD_VERSION "development" 6 | #endif 7 | 8 | #define DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */ 9 | 10 | // Low frequency clock source to be used by the SoftDevice 11 | #define NRF_CLOCK_LFCLKSRC {.source = NRF_CLOCK_LF_SRC_XTAL, \ 12 | .rc_ctiv = 0, \ 13 | .rc_temp_ctiv = 0, \ 14 | .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM} 15 | 16 | #define RTC_FREQUENCY 100 /* Hz */ 17 | 18 | #endif /* _APP_CONFIG_H */ 19 | -------------------------------------------------------------------------------- /crypto/aes.c: -------------------------------------------------------------------------------- 1 | /* 2 | --------------------------------------------------------------------------- 3 | Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. 4 | 5 | LICENSE TERMS 6 | 7 | The redistribution and use of this software (with or without changes) 8 | is allowed without the payment of fees or royalties provided that: 9 | 10 | 1. source code distributions include the above copyright notice, this 11 | list of conditions and the following disclaimer; 12 | 13 | 2. binary distributions include the above copyright notice, this list 14 | of conditions and the following disclaimer in their documentation; 15 | 16 | 3. the name of the copyright holder is not used to endorse products 17 | built using this software without specific written permission. 18 | 19 | DISCLAIMER 20 | 21 | This software is provided 'as is' with no explicit or implied warranties 22 | in respect of its properties, including, but not limited to, correctness 23 | and/or fitness for purpose. 24 | --------------------------------------------------------------------------- 25 | Issue 09/09/2006 26 | 27 | This is an AES implementation that uses only 8-bit byte operations on the 28 | cipher state (there are options to use 32-bit types if available). 29 | 30 | The combination of mix columns and byte substitution used here is based on 31 | that developed by Karl Malbrain. His contribution is acknowledged. 32 | */ 33 | 34 | /* define if you have a fast memcpy function on your system */ 35 | #if 0 36 | # define HAVE_MEMCPY 37 | # include 38 | # if defined( _MSC_VER ) 39 | # include 40 | # pragma intrinsic( memcpy ) 41 | # endif 42 | #endif 43 | 44 | #include 45 | #include 46 | 47 | /* define if you have fast 32-bit types on your system */ 48 | #if ( __CORTEX_M != 0 ) // if Cortex is different from M0/M0+ 49 | # define HAVE_UINT_32T 50 | #endif 51 | 52 | /* define if you don't want any tables */ 53 | #if 1 54 | # define USE_TABLES 55 | #endif 56 | 57 | /* On Intel Core 2 duo VERSION_1 is faster */ 58 | 59 | /* alternative versions (test for performance on your system) */ 60 | #if 1 61 | # define VERSION_1 62 | #endif 63 | 64 | #include "aes.h" 65 | 66 | //#if defined( HAVE_UINT_32T ) 67 | // typedef unsigned long uint32_t; 68 | //#endif 69 | 70 | /* functions for finite field multiplication in the AES Galois field */ 71 | 72 | #define WPOLY 0x011b 73 | #define BPOLY 0x1b 74 | #define DPOLY 0x008d 75 | 76 | #define f1(x) (x) 77 | #define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY)) 78 | #define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY)) 79 | #define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \ 80 | ^ (((x >> 5) & 4) * WPOLY)) 81 | #define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) 82 | 83 | #define f3(x) (f2(x) ^ x) 84 | #define f9(x) (f8(x) ^ x) 85 | #define fb(x) (f8(x) ^ f2(x) ^ x) 86 | #define fd(x) (f8(x) ^ f4(x) ^ x) 87 | #define fe(x) (f8(x) ^ f4(x) ^ f2(x)) 88 | 89 | #if defined( USE_TABLES ) 90 | 91 | #define sb_data(w) { /* S Box data values */ \ 92 | w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ 93 | w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ 94 | w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ 95 | w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ 96 | w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ 97 | w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ 98 | w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ 99 | w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ 100 | w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ 101 | w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ 102 | w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ 103 | w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ 104 | w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ 105 | w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ 106 | w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ 107 | w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ 108 | w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ 109 | w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ 110 | w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ 111 | w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ 112 | w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ 113 | w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ 114 | w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ 115 | w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ 116 | w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ 117 | w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ 118 | w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ 119 | w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ 120 | w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ 121 | w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ 122 | w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ 123 | w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } 124 | 125 | #define isb_data(w) { /* inverse S Box data values */ \ 126 | w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ 127 | w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ 128 | w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ 129 | w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ 130 | w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ 131 | w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ 132 | w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ 133 | w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ 134 | w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ 135 | w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ 136 | w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ 137 | w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ 138 | w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ 139 | w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ 140 | w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ 141 | w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ 142 | w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ 143 | w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ 144 | w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ 145 | w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ 146 | w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ 147 | w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ 148 | w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ 149 | w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ 150 | w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ 151 | w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ 152 | w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ 153 | w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ 154 | w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ 155 | w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ 156 | w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ 157 | w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } 158 | 159 | #define mm_data(w) { /* basic data for forming finite field tables */ \ 160 | w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ 161 | w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ 162 | w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ 163 | w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ 164 | w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ 165 | w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ 166 | w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ 167 | w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ 168 | w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ 169 | w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ 170 | w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ 171 | w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ 172 | w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ 173 | w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ 174 | w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ 175 | w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ 176 | w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ 177 | w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ 178 | w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ 179 | w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ 180 | w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ 181 | w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ 182 | w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ 183 | w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ 184 | w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ 185 | w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ 186 | w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ 187 | w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ 188 | w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ 189 | w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ 190 | w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ 191 | w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } 192 | 193 | static const uint8_t sbox[256] = sb_data(f1); 194 | 195 | #if defined( AES_DEC_PREKEYED ) 196 | static const uint8_t isbox[256] = isb_data(f1); 197 | #endif 198 | 199 | static const uint8_t gfm2_sbox[256] = sb_data(f2); 200 | static const uint8_t gfm3_sbox[256] = sb_data(f3); 201 | 202 | #if defined( AES_DEC_PREKEYED ) 203 | static const uint8_t gfmul_9[256] = mm_data(f9); 204 | static const uint8_t gfmul_b[256] = mm_data(fb); 205 | static const uint8_t gfmul_d[256] = mm_data(fd); 206 | static const uint8_t gfmul_e[256] = mm_data(fe); 207 | #endif 208 | 209 | #define s_box(x) sbox[(x)] 210 | #if defined( AES_DEC_PREKEYED ) 211 | #define is_box(x) isbox[(x)] 212 | #endif 213 | #define gfm2_sb(x) gfm2_sbox[(x)] 214 | #define gfm3_sb(x) gfm3_sbox[(x)] 215 | #if defined( AES_DEC_PREKEYED ) 216 | #define gfm_9(x) gfmul_9[(x)] 217 | #define gfm_b(x) gfmul_b[(x)] 218 | #define gfm_d(x) gfmul_d[(x)] 219 | #define gfm_e(x) gfmul_e[(x)] 220 | #endif 221 | #else 222 | 223 | /* this is the high bit of x right shifted by 1 */ 224 | /* position. Since the starting polynomial has */ 225 | /* 9 bits (0x11b), this right shift keeps the */ 226 | /* values of all top bits within a byte */ 227 | 228 | static uint8_t hibit(const uint8_t x) 229 | { uint8_t r = (uint8_t)((x >> 1) | (x >> 2)); 230 | 231 | r |= (r >> 2); 232 | r |= (r >> 4); 233 | return (r + 1) >> 1; 234 | } 235 | 236 | /* return the inverse of the finite field element x */ 237 | 238 | static uint8_t gf_inv(const uint8_t x) 239 | { uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; 240 | 241 | if(x < 2) 242 | return x; 243 | 244 | for( ; ; ) 245 | { 246 | if(n1) 247 | while(n2 >= n1) /* divide polynomial p2 by p1 */ 248 | { 249 | n2 /= n1; /* shift smaller polynomial left */ 250 | p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ 251 | v2 ^= (v1 * n2); /* shift accumulated value and */ 252 | n2 = hibit(p2); /* add into result */ 253 | } 254 | else 255 | return v1; 256 | 257 | if(n2) /* repeat with values swapped */ 258 | while(n1 >= n2) 259 | { 260 | n1 /= n2; 261 | p1 ^= p2 * n1; 262 | v1 ^= v2 * n1; 263 | n1 = hibit(p1); 264 | } 265 | else 266 | return v2; 267 | } 268 | } 269 | 270 | /* The forward and inverse affine transformations used in the S-box */ 271 | uint8_t fwd_affine(const uint8_t x) 272 | { 273 | #if defined( HAVE_UINT_32T ) 274 | uint32_t w = x; 275 | w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); 276 | return 0x63 ^ ((w ^ (w >> 8)) & 0xff); 277 | #else 278 | return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4) 279 | ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4); 280 | #endif 281 | } 282 | 283 | uint8_t inv_affine(const uint8_t x) 284 | { 285 | #if defined( HAVE_UINT_32T ) 286 | uint32_t w = x; 287 | w = (w << 1) ^ (w << 3) ^ (w << 6); 288 | return 0x05 ^ ((w ^ (w >> 8)) & 0xff); 289 | #else 290 | return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6) 291 | ^ (x >> 7) ^ (x >> 5) ^ (x >> 2); 292 | #endif 293 | } 294 | 295 | #define s_box(x) fwd_affine(gf_inv(x)) 296 | #define is_box(x) gf_inv(inv_affine(x)) 297 | #define gfm2_sb(x) f2(s_box(x)) 298 | #define gfm3_sb(x) f3(s_box(x)) 299 | #define gfm_9(x) f9(x) 300 | #define gfm_b(x) fb(x) 301 | #define gfm_d(x) fd(x) 302 | #define gfm_e(x) fe(x) 303 | 304 | #endif 305 | 306 | #if defined( HAVE_MEMCPY ) 307 | # define block_copy_nn(d, s, l) memcpy(d, s, l) 308 | # define block_copy(d, s) memcpy(d, s, N_BLOCK) 309 | #else 310 | # define block_copy_nn(d, s, l) copy_block_nn(d, s, l) 311 | # define block_copy(d, s) copy_block(d, s) 312 | #endif 313 | 314 | static void copy_block( void *d, const void *s ) 315 | { 316 | #if defined( HAVE_UINT_32T ) 317 | ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0]; 318 | ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1]; 319 | ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2]; 320 | ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3]; 321 | #else 322 | ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0]; 323 | ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1]; 324 | ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2]; 325 | ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3]; 326 | ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4]; 327 | ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5]; 328 | ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6]; 329 | ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7]; 330 | ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8]; 331 | ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9]; 332 | ((uint8_t*)d)[10] = ((uint8_t*)s)[10]; 333 | ((uint8_t*)d)[11] = ((uint8_t*)s)[11]; 334 | ((uint8_t*)d)[12] = ((uint8_t*)s)[12]; 335 | ((uint8_t*)d)[13] = ((uint8_t*)s)[13]; 336 | ((uint8_t*)d)[14] = ((uint8_t*)s)[14]; 337 | ((uint8_t*)d)[15] = ((uint8_t*)s)[15]; 338 | #endif 339 | } 340 | 341 | static void copy_block_nn( uint8_t * d, const uint8_t *s, uint8_t nn ) 342 | { 343 | while( nn-- ) 344 | //*((uint8_t*)d)++ = *((uint8_t*)s)++; 345 | *d++ = *s++; 346 | } 347 | 348 | static void xor_block( void *d, const void *s ) 349 | { 350 | #if defined( HAVE_UINT_32T ) 351 | ((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0]; 352 | ((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1]; 353 | ((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2]; 354 | ((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3]; 355 | #else 356 | ((uint8_t*)d)[ 0] ^= ((uint8_t*)s)[ 0]; 357 | ((uint8_t*)d)[ 1] ^= ((uint8_t*)s)[ 1]; 358 | ((uint8_t*)d)[ 2] ^= ((uint8_t*)s)[ 2]; 359 | ((uint8_t*)d)[ 3] ^= ((uint8_t*)s)[ 3]; 360 | ((uint8_t*)d)[ 4] ^= ((uint8_t*)s)[ 4]; 361 | ((uint8_t*)d)[ 5] ^= ((uint8_t*)s)[ 5]; 362 | ((uint8_t*)d)[ 6] ^= ((uint8_t*)s)[ 6]; 363 | ((uint8_t*)d)[ 7] ^= ((uint8_t*)s)[ 7]; 364 | ((uint8_t*)d)[ 8] ^= ((uint8_t*)s)[ 8]; 365 | ((uint8_t*)d)[ 9] ^= ((uint8_t*)s)[ 9]; 366 | ((uint8_t*)d)[10] ^= ((uint8_t*)s)[10]; 367 | ((uint8_t*)d)[11] ^= ((uint8_t*)s)[11]; 368 | ((uint8_t*)d)[12] ^= ((uint8_t*)s)[12]; 369 | ((uint8_t*)d)[13] ^= ((uint8_t*)s)[13]; 370 | ((uint8_t*)d)[14] ^= ((uint8_t*)s)[14]; 371 | ((uint8_t*)d)[15] ^= ((uint8_t*)s)[15]; 372 | #endif 373 | } 374 | 375 | static void copy_and_key( void *d, const void *s, const void *k ) 376 | { 377 | #if defined( HAVE_UINT_32T ) 378 | ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0]; 379 | ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1]; 380 | ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2]; 381 | ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3]; 382 | #elif 1 383 | ((uint8_t*)d)[ 0] = ((uint8_t*)s)[ 0] ^ ((uint8_t*)k)[ 0]; 384 | ((uint8_t*)d)[ 1] = ((uint8_t*)s)[ 1] ^ ((uint8_t*)k)[ 1]; 385 | ((uint8_t*)d)[ 2] = ((uint8_t*)s)[ 2] ^ ((uint8_t*)k)[ 2]; 386 | ((uint8_t*)d)[ 3] = ((uint8_t*)s)[ 3] ^ ((uint8_t*)k)[ 3]; 387 | ((uint8_t*)d)[ 4] = ((uint8_t*)s)[ 4] ^ ((uint8_t*)k)[ 4]; 388 | ((uint8_t*)d)[ 5] = ((uint8_t*)s)[ 5] ^ ((uint8_t*)k)[ 5]; 389 | ((uint8_t*)d)[ 6] = ((uint8_t*)s)[ 6] ^ ((uint8_t*)k)[ 6]; 390 | ((uint8_t*)d)[ 7] = ((uint8_t*)s)[ 7] ^ ((uint8_t*)k)[ 7]; 391 | ((uint8_t*)d)[ 8] = ((uint8_t*)s)[ 8] ^ ((uint8_t*)k)[ 8]; 392 | ((uint8_t*)d)[ 9] = ((uint8_t*)s)[ 9] ^ ((uint8_t*)k)[ 9]; 393 | ((uint8_t*)d)[10] = ((uint8_t*)s)[10] ^ ((uint8_t*)k)[10]; 394 | ((uint8_t*)d)[11] = ((uint8_t*)s)[11] ^ ((uint8_t*)k)[11]; 395 | ((uint8_t*)d)[12] = ((uint8_t*)s)[12] ^ ((uint8_t*)k)[12]; 396 | ((uint8_t*)d)[13] = ((uint8_t*)s)[13] ^ ((uint8_t*)k)[13]; 397 | ((uint8_t*)d)[14] = ((uint8_t*)s)[14] ^ ((uint8_t*)k)[14]; 398 | ((uint8_t*)d)[15] = ((uint8_t*)s)[15] ^ ((uint8_t*)k)[15]; 399 | #else 400 | block_copy(d, s); 401 | xor_block(d, k); 402 | #endif 403 | } 404 | 405 | static void add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] ) 406 | { 407 | xor_block(d, k); 408 | } 409 | 410 | static void shift_sub_rows( uint8_t st[N_BLOCK] ) 411 | { uint8_t tt; 412 | 413 | st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]); 414 | st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]); 415 | 416 | tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]); 417 | st[ 9] = s_box(st[13]); st[13] = s_box( tt ); 418 | 419 | tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt ); 420 | tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt ); 421 | 422 | tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]); 423 | st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt ); 424 | } 425 | 426 | #if defined( AES_DEC_PREKEYED ) 427 | 428 | static void inv_shift_sub_rows( uint8_t st[N_BLOCK] ) 429 | { uint8_t tt; 430 | 431 | st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]); 432 | st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]); 433 | 434 | tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]); 435 | st[ 5] = is_box(st[1]); st[ 1] = is_box( tt ); 436 | 437 | tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt ); 438 | tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt ); 439 | 440 | tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]); 441 | st[11] = is_box(st[15]); st[15] = is_box( tt ); 442 | } 443 | 444 | #endif 445 | 446 | #if defined( VERSION_1 ) 447 | static void mix_sub_columns( uint8_t dt[N_BLOCK] ) 448 | { uint8_t st[N_BLOCK]; 449 | block_copy(st, dt); 450 | #else 451 | static void mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] ) 452 | { 453 | #endif 454 | dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]); 455 | dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]); 456 | dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]); 457 | dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]); 458 | 459 | dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]); 460 | dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]); 461 | dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]); 462 | dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]); 463 | 464 | dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]); 465 | dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]); 466 | dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]); 467 | dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]); 468 | 469 | dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]); 470 | dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]); 471 | dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]); 472 | dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]); 473 | } 474 | 475 | #if defined( AES_DEC_PREKEYED ) 476 | 477 | #if defined( VERSION_1 ) 478 | static void inv_mix_sub_columns( uint8_t dt[N_BLOCK] ) 479 | { uint8_t st[N_BLOCK]; 480 | block_copy(st, dt); 481 | #else 482 | static void inv_mix_sub_columns( uint8_t dt[N_BLOCK], uint8_t st[N_BLOCK] ) 483 | { 484 | #endif 485 | dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3])); 486 | dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3])); 487 | dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3])); 488 | dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3])); 489 | 490 | dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7])); 491 | dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7])); 492 | dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7])); 493 | dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7])); 494 | 495 | dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11])); 496 | dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11])); 497 | dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11])); 498 | dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11])); 499 | 500 | dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15])); 501 | dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15])); 502 | dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15])); 503 | dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15])); 504 | } 505 | 506 | #endif 507 | 508 | #if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) 509 | 510 | /* Set the cipher key for the pre-keyed version */ 511 | 512 | return_type aes_set_key( const uint8_t key[], length_type keylen, aes_context ctx[1] ) 513 | { 514 | uint8_t cc, rc, hi; 515 | 516 | switch( keylen ) 517 | { 518 | case 16: 519 | case 24: 520 | case 32: 521 | break; 522 | default: 523 | ctx->rnd = 0; 524 | return ( uint8_t )-1; 525 | } 526 | block_copy_nn(ctx->ksch, key, keylen); 527 | hi = (keylen + 28) << 2; 528 | ctx->rnd = (hi >> 4) - 1; 529 | for( cc = keylen, rc = 1; cc < hi; cc += 4 ) 530 | { uint8_t tt, t0, t1, t2, t3; 531 | 532 | t0 = ctx->ksch[cc - 4]; 533 | t1 = ctx->ksch[cc - 3]; 534 | t2 = ctx->ksch[cc - 2]; 535 | t3 = ctx->ksch[cc - 1]; 536 | if( cc % keylen == 0 ) 537 | { 538 | tt = t0; 539 | t0 = s_box(t1) ^ rc; 540 | t1 = s_box(t2); 541 | t2 = s_box(t3); 542 | t3 = s_box(tt); 543 | rc = f2(rc); 544 | } 545 | else if( keylen > 24 && cc % keylen == 16 ) 546 | { 547 | t0 = s_box(t0); 548 | t1 = s_box(t1); 549 | t2 = s_box(t2); 550 | t3 = s_box(t3); 551 | } 552 | tt = cc - keylen; 553 | ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; 554 | ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; 555 | ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; 556 | ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; 557 | } 558 | return 0; 559 | } 560 | 561 | #endif 562 | 563 | #if defined( AES_ENC_PREKEYED ) 564 | 565 | /* Encrypt a single block of 16 bytes */ 566 | 567 | return_type aes_encrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] ) 568 | { 569 | if( ctx->rnd ) 570 | { 571 | uint8_t s1[N_BLOCK], r; 572 | copy_and_key( s1, in, ctx->ksch ); 573 | 574 | for( r = 1 ; r < ctx->rnd ; ++r ) 575 | #if defined( VERSION_1 ) 576 | { 577 | mix_sub_columns( s1 ); 578 | add_round_key( s1, ctx->ksch + r * N_BLOCK); 579 | } 580 | #else 581 | { uint8_t s2[N_BLOCK]; 582 | mix_sub_columns( s2, s1 ); 583 | copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK); 584 | } 585 | #endif 586 | shift_sub_rows( s1 ); 587 | copy_and_key( out, s1, ctx->ksch + r * N_BLOCK ); 588 | } 589 | else 590 | return ( uint8_t )-1; 591 | return 0; 592 | } 593 | 594 | /* CBC encrypt a number of blocks (input and return an IV) */ 595 | 596 | return_type aes_cbc_encrypt( const uint8_t *in, uint8_t *out, 597 | int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] ) 598 | { 599 | 600 | while(n_block--) 601 | { 602 | xor_block(iv, in); 603 | if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) 604 | return EXIT_FAILURE; 605 | //memcpy(out, iv, N_BLOCK); 606 | block_copy(out, iv); 607 | in += N_BLOCK; 608 | out += N_BLOCK; 609 | } 610 | return EXIT_SUCCESS; 611 | } 612 | 613 | #endif 614 | 615 | #if defined( AES_DEC_PREKEYED ) 616 | 617 | /* Decrypt a single block of 16 bytes */ 618 | 619 | return_type aes_decrypt( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], const aes_context ctx[1] ) 620 | { 621 | if( ctx->rnd ) 622 | { 623 | uint8_t s1[N_BLOCK], r; 624 | copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); 625 | inv_shift_sub_rows( s1 ); 626 | 627 | for( r = ctx->rnd ; --r ; ) 628 | #if defined( VERSION_1 ) 629 | { 630 | add_round_key( s1, ctx->ksch + r * N_BLOCK ); 631 | inv_mix_sub_columns( s1 ); 632 | } 633 | #else 634 | { uint8_t s2[N_BLOCK]; 635 | copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK ); 636 | inv_mix_sub_columns( s1, s2 ); 637 | } 638 | #endif 639 | copy_and_key( out, s1, ctx->ksch ); 640 | } 641 | else 642 | return -1; 643 | return 0; 644 | } 645 | 646 | /* CBC decrypt a number of blocks (input and return an IV) */ 647 | 648 | return_type aes_cbc_decrypt( const uint8_t *in, uint8_t *out, 649 | int32_t n_block, uint8_t iv[N_BLOCK], const aes_context ctx[1] ) 650 | { 651 | while(n_block--) 652 | { uint8_t tmp[N_BLOCK]; 653 | 654 | //memcpy(tmp, in, N_BLOCK); 655 | block_copy(tmp, in); 656 | if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS) 657 | return EXIT_FAILURE; 658 | xor_block(out, iv); 659 | //memcpy(iv, tmp, N_BLOCK); 660 | block_copy(iv, tmp); 661 | in += N_BLOCK; 662 | out += N_BLOCK; 663 | } 664 | return EXIT_SUCCESS; 665 | } 666 | 667 | #endif 668 | 669 | #if defined( AES_ENC_128_OTFK ) 670 | 671 | /* The 'on the fly' encryption key update for for 128 bit keys */ 672 | 673 | static void update_encrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc ) 674 | { uint8_t cc; 675 | 676 | k[0] ^= s_box(k[13]) ^ *rc; 677 | k[1] ^= s_box(k[14]); 678 | k[2] ^= s_box(k[15]); 679 | k[3] ^= s_box(k[12]); 680 | *rc = f2( *rc ); 681 | 682 | for(cc = 4; cc < 16; cc += 4 ) 683 | { 684 | k[cc + 0] ^= k[cc - 4]; 685 | k[cc + 1] ^= k[cc - 3]; 686 | k[cc + 2] ^= k[cc - 2]; 687 | k[cc + 3] ^= k[cc - 1]; 688 | } 689 | } 690 | 691 | /* Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ 692 | 693 | void aes_encrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], 694 | const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] ) 695 | { uint8_t s1[N_BLOCK], r, rc = 1; 696 | 697 | if(o_key != key) 698 | block_copy( o_key, key ); 699 | copy_and_key( s1, in, o_key ); 700 | 701 | for( r = 1 ; r < 10 ; ++r ) 702 | #if defined( VERSION_1 ) 703 | { 704 | mix_sub_columns( s1 ); 705 | update_encrypt_key_128( o_key, &rc ); 706 | add_round_key( s1, o_key ); 707 | } 708 | #else 709 | { uint8_t s2[N_BLOCK]; 710 | mix_sub_columns( s2, s1 ); 711 | update_encrypt_key_128( o_key, &rc ); 712 | copy_and_key( s1, s2, o_key ); 713 | } 714 | #endif 715 | 716 | shift_sub_rows( s1 ); 717 | update_encrypt_key_128( o_key, &rc ); 718 | copy_and_key( out, s1, o_key ); 719 | } 720 | 721 | #endif 722 | 723 | #if defined( AES_DEC_128_OTFK ) 724 | 725 | /* The 'on the fly' decryption key update for for 128 bit keys */ 726 | 727 | static void update_decrypt_key_128( uint8_t k[N_BLOCK], uint8_t *rc ) 728 | { uint8_t cc; 729 | 730 | for( cc = 12; cc > 0; cc -= 4 ) 731 | { 732 | k[cc + 0] ^= k[cc - 4]; 733 | k[cc + 1] ^= k[cc - 3]; 734 | k[cc + 2] ^= k[cc - 2]; 735 | k[cc + 3] ^= k[cc - 1]; 736 | } 737 | *rc = d2(*rc); 738 | k[0] ^= s_box(k[13]) ^ *rc; 739 | k[1] ^= s_box(k[14]); 740 | k[2] ^= s_box(k[15]); 741 | k[3] ^= s_box(k[12]); 742 | } 743 | 744 | /* Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */ 745 | 746 | void aes_decrypt_128( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], 747 | const uint8_t key[N_BLOCK], uint8_t o_key[N_BLOCK] ) 748 | { 749 | uint8_t s1[N_BLOCK], r, rc = 0x6c; 750 | if(o_key != key) 751 | block_copy( o_key, key ); 752 | 753 | copy_and_key( s1, in, o_key ); 754 | inv_shift_sub_rows( s1 ); 755 | 756 | for( r = 10 ; --r ; ) 757 | #if defined( VERSION_1 ) 758 | { 759 | update_decrypt_key_128( o_key, &rc ); 760 | add_round_key( s1, o_key ); 761 | inv_mix_sub_columns( s1 ); 762 | } 763 | #else 764 | { uint8_t s2[N_BLOCK]; 765 | update_decrypt_key_128( o_key, &rc ); 766 | copy_and_key( s2, s1, o_key ); 767 | inv_mix_sub_columns( s1, s2 ); 768 | } 769 | #endif 770 | update_decrypt_key_128( o_key, &rc ); 771 | copy_and_key( out, s1, o_key ); 772 | } 773 | 774 | #endif 775 | 776 | #if defined( AES_ENC_256_OTFK ) 777 | 778 | /* The 'on the fly' encryption key update for for 256 bit keys */ 779 | 780 | static void update_encrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc ) 781 | { uint8_t cc; 782 | 783 | k[0] ^= s_box(k[29]) ^ *rc; 784 | k[1] ^= s_box(k[30]); 785 | k[2] ^= s_box(k[31]); 786 | k[3] ^= s_box(k[28]); 787 | *rc = f2( *rc ); 788 | 789 | for(cc = 4; cc < 16; cc += 4) 790 | { 791 | k[cc + 0] ^= k[cc - 4]; 792 | k[cc + 1] ^= k[cc - 3]; 793 | k[cc + 2] ^= k[cc - 2]; 794 | k[cc + 3] ^= k[cc - 1]; 795 | } 796 | 797 | k[16] ^= s_box(k[12]); 798 | k[17] ^= s_box(k[13]); 799 | k[18] ^= s_box(k[14]); 800 | k[19] ^= s_box(k[15]); 801 | 802 | for( cc = 20; cc < 32; cc += 4 ) 803 | { 804 | k[cc + 0] ^= k[cc - 4]; 805 | k[cc + 1] ^= k[cc - 3]; 806 | k[cc + 2] ^= k[cc - 2]; 807 | k[cc + 3] ^= k[cc - 1]; 808 | } 809 | } 810 | 811 | /* Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */ 812 | 813 | void aes_encrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], 814 | const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] ) 815 | { 816 | uint8_t s1[N_BLOCK], r, rc = 1; 817 | if(o_key != key) 818 | { 819 | block_copy( o_key, key ); 820 | block_copy( o_key + 16, key + 16 ); 821 | } 822 | copy_and_key( s1, in, o_key ); 823 | 824 | for( r = 1 ; r < 14 ; ++r ) 825 | #if defined( VERSION_1 ) 826 | { 827 | mix_sub_columns(s1); 828 | if( r & 1 ) 829 | add_round_key( s1, o_key + 16 ); 830 | else 831 | { 832 | update_encrypt_key_256( o_key, &rc ); 833 | add_round_key( s1, o_key ); 834 | } 835 | } 836 | #else 837 | { uint8_t s2[N_BLOCK]; 838 | mix_sub_columns( s2, s1 ); 839 | if( r & 1 ) 840 | copy_and_key( s1, s2, o_key + 16 ); 841 | else 842 | { 843 | update_encrypt_key_256( o_key, &rc ); 844 | copy_and_key( s1, s2, o_key ); 845 | } 846 | } 847 | #endif 848 | 849 | shift_sub_rows( s1 ); 850 | update_encrypt_key_256( o_key, &rc ); 851 | copy_and_key( out, s1, o_key ); 852 | } 853 | 854 | #endif 855 | 856 | #if defined( AES_DEC_256_OTFK ) 857 | 858 | /* The 'on the fly' encryption key update for for 256 bit keys */ 859 | 860 | static void update_decrypt_key_256( uint8_t k[2 * N_BLOCK], uint8_t *rc ) 861 | { uint8_t cc; 862 | 863 | for(cc = 28; cc > 16; cc -= 4) 864 | { 865 | k[cc + 0] ^= k[cc - 4]; 866 | k[cc + 1] ^= k[cc - 3]; 867 | k[cc + 2] ^= k[cc - 2]; 868 | k[cc + 3] ^= k[cc - 1]; 869 | } 870 | 871 | k[16] ^= s_box(k[12]); 872 | k[17] ^= s_box(k[13]); 873 | k[18] ^= s_box(k[14]); 874 | k[19] ^= s_box(k[15]); 875 | 876 | for(cc = 12; cc > 0; cc -= 4) 877 | { 878 | k[cc + 0] ^= k[cc - 4]; 879 | k[cc + 1] ^= k[cc - 3]; 880 | k[cc + 2] ^= k[cc - 2]; 881 | k[cc + 3] ^= k[cc - 1]; 882 | } 883 | 884 | *rc = d2(*rc); 885 | k[0] ^= s_box(k[29]) ^ *rc; 886 | k[1] ^= s_box(k[30]); 887 | k[2] ^= s_box(k[31]); 888 | k[3] ^= s_box(k[28]); 889 | } 890 | 891 | /* Decrypt a single block of 16 bytes with 'on the fly' 892 | 256 bit keying 893 | */ 894 | void aes_decrypt_256( const uint8_t in[N_BLOCK], uint8_t out[N_BLOCK], 895 | const uint8_t key[2 * N_BLOCK], uint8_t o_key[2 * N_BLOCK] ) 896 | { 897 | uint8_t s1[N_BLOCK], r, rc = 0x80; 898 | 899 | if(o_key != key) 900 | { 901 | block_copy( o_key, key ); 902 | block_copy( o_key + 16, key + 16 ); 903 | } 904 | 905 | copy_and_key( s1, in, o_key ); 906 | inv_shift_sub_rows( s1 ); 907 | 908 | for( r = 14 ; --r ; ) 909 | #if defined( VERSION_1 ) 910 | { 911 | if( ( r & 1 ) ) 912 | { 913 | update_decrypt_key_256( o_key, &rc ); 914 | add_round_key( s1, o_key + 16 ); 915 | } 916 | else 917 | add_round_key( s1, o_key ); 918 | inv_mix_sub_columns( s1 ); 919 | } 920 | #else 921 | { uint8_t s2[N_BLOCK]; 922 | if( ( r & 1 ) ) 923 | { 924 | update_decrypt_key_256( o_key, &rc ); 925 | copy_and_key( s2, s1, o_key + 16 ); 926 | } 927 | else 928 | copy_and_key( s2, s1, o_key ); 929 | inv_mix_sub_columns( s1, s2 ); 930 | } 931 | #endif 932 | copy_and_key( out, s1, o_key ); 933 | } 934 | 935 | #endif 936 | -------------------------------------------------------------------------------- /crypto/aes.h: -------------------------------------------------------------------------------- 1 | /* 2 | --------------------------------------------------------------------------- 3 | Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. 4 | 5 | LICENSE TERMS 6 | 7 | The redistribution and use of this software (with or without changes) 8 | is allowed without the payment of fees or royalties provided that: 9 | 10 | 1. source code distributions include the above copyright notice, this 11 | list of conditions and the following disclaimer; 12 | 13 | 2. binary distributions include the above copyright notice, this list 14 | of conditions and the following disclaimer in their documentation; 15 | 16 | 3. the name of the copyright holder is not used to endorse products 17 | built using this software without specific written permission. 18 | 19 | DISCLAIMER 20 | 21 | This software is provided 'as is' with no explicit or implied warranties 22 | in respect of its properties, including, but not limited to, correctness 23 | and/or fitness for purpose. 24 | --------------------------------------------------------------------------- 25 | Issue 09/09/2006 26 | 27 | This is an AES implementation that uses only 8-bit byte operations on the 28 | cipher state. 29 | */ 30 | 31 | #ifndef AES_H 32 | #define AES_H 33 | 34 | #if 1 35 | # define AES_ENC_PREKEYED /* AES encryption with a precomputed key schedule */ 36 | #endif 37 | #if 0 38 | # define AES_DEC_PREKEYED /* AES decryption with a precomputed key schedule */ 39 | #endif 40 | #if 0 41 | # define AES_ENC_128_OTFK /* AES encryption with 'on the fly' 128 bit keying */ 42 | #endif 43 | #if 0 44 | # define AES_DEC_128_OTFK /* AES decryption with 'on the fly' 128 bit keying */ 45 | #endif 46 | #if 0 47 | # define AES_ENC_256_OTFK /* AES encryption with 'on the fly' 256 bit keying */ 48 | #endif 49 | #if 0 50 | # define AES_DEC_256_OTFK /* AES decryption with 'on the fly' 256 bit keying */ 51 | #endif 52 | 53 | #define N_ROW 4 54 | #define N_COL 4 55 | #define N_BLOCK (N_ROW * N_COL) 56 | #define N_MAX_ROUNDS 14 57 | 58 | typedef uint8_t return_type; 59 | 60 | /* Warning: The key length for 256 bit keys overflows a byte 61 | (see comment below) 62 | */ 63 | 64 | typedef uint8_t length_type; 65 | 66 | typedef struct 67 | { uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; 68 | uint8_t rnd; 69 | } aes_context; 70 | 71 | /* The following calls are for a precomputed key schedule 72 | 73 | NOTE: If the length_type used for the key length is an 74 | unsigned 8-bit character, a key length of 256 bits must 75 | be entered as a length in bytes (valid inputs are hence 76 | 128, 192, 16, 24 and 32). 77 | */ 78 | 79 | #if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED ) 80 | 81 | return_type aes_set_key( const uint8_t key[], 82 | length_type keylen, 83 | aes_context ctx[1] ); 84 | #endif 85 | 86 | #if defined( AES_ENC_PREKEYED ) 87 | 88 | return_type aes_encrypt( const uint8_t in[N_BLOCK], 89 | uint8_t out[N_BLOCK], 90 | const aes_context ctx[1] ); 91 | 92 | return_type aes_cbc_encrypt( const uint8_t *in, 93 | uint8_t *out, 94 | int32_t n_block, 95 | uint8_t iv[N_BLOCK], 96 | const aes_context ctx[1] ); 97 | #endif 98 | 99 | #if defined( AES_DEC_PREKEYED ) 100 | 101 | return_type aes_decrypt( const uint8_t in[N_BLOCK], 102 | uint8_t out[N_BLOCK], 103 | const aes_context ctx[1] ); 104 | 105 | return_type aes_cbc_decrypt( const uint8_t *in, 106 | uint8_t *out, 107 | int32_t n_block, 108 | uint8_t iv[N_BLOCK], 109 | const aes_context ctx[1] ); 110 | #endif 111 | 112 | /* The following calls are for 'on the fly' keying. In this case the 113 | encryption and decryption keys are different. 114 | 115 | The encryption subroutines take a key in an array of bytes in 116 | key[L] where L is 16, 24 or 32 bytes for key lengths of 128, 117 | 192, and 256 bits respectively. They then encrypts the input 118 | data, in[] with this key and put the reult in the output array 119 | out[]. In addition, the second key array, o_key[L], is used 120 | to output the key that is needed by the decryption subroutine 121 | to reverse the encryption operation. The two key arrays can 122 | be the same array but in this case the original key will be 123 | overwritten. 124 | 125 | In the same way, the decryption subroutines output keys that 126 | can be used to reverse their effect when used for encryption. 127 | 128 | Only 128 and 256 bit keys are supported in these 'on the fly' 129 | modes. 130 | */ 131 | 132 | #if defined( AES_ENC_128_OTFK ) 133 | void aes_encrypt_128( const uint8_t in[N_BLOCK], 134 | uint8_t out[N_BLOCK], 135 | const uint8_t key[N_BLOCK], 136 | uint8_t o_key[N_BLOCK] ); 137 | #endif 138 | 139 | #if defined( AES_DEC_128_OTFK ) 140 | void aes_decrypt_128( const uint8_t in[N_BLOCK], 141 | uint8_t out[N_BLOCK], 142 | const uint8_t key[N_BLOCK], 143 | uint8_t o_key[N_BLOCK] ); 144 | #endif 145 | 146 | #if defined( AES_ENC_256_OTFK ) 147 | void aes_encrypt_256( const uint8_t in[N_BLOCK], 148 | uint8_t out[N_BLOCK], 149 | const uint8_t key[2 * N_BLOCK], 150 | uint8_t o_key[2 * N_BLOCK] ); 151 | #endif 152 | 153 | #if defined( AES_DEC_256_OTFK ) 154 | void aes_decrypt_256( const uint8_t in[N_BLOCK], 155 | uint8_t out[N_BLOCK], 156 | const uint8_t key[2 * N_BLOCK], 157 | uint8_t o_key[2 * N_BLOCK] ); 158 | #endif 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /crypto/cmac.c: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | Copyright (C) 2009 Lander Casado, Philippas Tsigas 3 | 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files 8 | (the "Software"), to deal with the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimers. Redistributions in 16 | binary form must reproduce the above copyright notice, this list of 17 | conditions and the following disclaimers in the documentation and/or 18 | other materials provided with the distribution. 19 | 20 | In no event shall the authors or copyright holders be liable for any special, 21 | incidental, indirect or consequential damages of any kind, or any damages 22 | whatsoever resulting from loss of use, data or profits, whether or not 23 | advised of the possibility of damage, and on any theory of liability, 24 | arising out of or in connection with the use or performance of this software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 27 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 32 | DEALINGS WITH THE SOFTWARE 33 | 34 | *****************************************************************************/ 35 | //#include 36 | //#include 37 | #include 38 | #include "aes.h" 39 | #include "cmac.h" 40 | #include "utilities.h" 41 | 42 | #define LSHIFT(v, r) do { \ 43 | int32_t i; \ 44 | for (i = 0; i < 15; i++) \ 45 | (r)[i] = (v)[i] << 1 | (v)[i + 1] >> 7; \ 46 | (r)[15] = (v)[15] << 1; \ 47 | } while (0) 48 | 49 | #define XOR(v, r) do { \ 50 | int32_t i; \ 51 | for (i = 0; i < 16; i++) \ 52 | { \ 53 | (r)[i] = (r)[i] ^ (v)[i]; \ 54 | } \ 55 | } while (0) \ 56 | 57 | 58 | void AES_CMAC_Init(AES_CMAC_CTX *ctx) 59 | { 60 | memset1(ctx->X, 0, sizeof ctx->X); 61 | ctx->M_n = 0; 62 | memset1(ctx->rijndael.ksch, '\0', 240); 63 | } 64 | 65 | void AES_CMAC_SetKey(AES_CMAC_CTX *ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]) 66 | { 67 | //rijndael_set_key_enc_only(&ctx->rijndael, key, 128); 68 | aes_set_key( key, AES_CMAC_KEY_LENGTH, &ctx->rijndael); 69 | } 70 | 71 | void AES_CMAC_Update(AES_CMAC_CTX *ctx, const uint8_t *data, uint32_t len) 72 | { 73 | uint32_t mlen; 74 | uint8_t in[16]; 75 | 76 | if (ctx->M_n > 0) { 77 | mlen = MIN(16 - ctx->M_n, len); 78 | memcpy1(ctx->M_last + ctx->M_n, data, mlen); 79 | ctx->M_n += mlen; 80 | if (ctx->M_n < 16 || len == mlen) 81 | return; 82 | XOR(ctx->M_last, ctx->X); 83 | //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); 84 | aes_encrypt( ctx->X, ctx->X, &ctx->rijndael); 85 | data += mlen; 86 | len -= mlen; 87 | } 88 | while (len > 16) { /* not last block */ 89 | 90 | XOR(data, ctx->X); 91 | //rijndael_encrypt(&ctx->rijndael, ctx->X, ctx->X); 92 | 93 | memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten 94 | aes_encrypt( in, in, &ctx->rijndael); 95 | memcpy1(&ctx->X[0], in, 16); 96 | 97 | data += 16; 98 | len -= 16; 99 | } 100 | /* potential last block, save it */ 101 | memcpy1(ctx->M_last, data, len); 102 | ctx->M_n = len; 103 | } 104 | 105 | void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX *ctx) 106 | { 107 | uint8_t K[16]; 108 | uint8_t in[16]; 109 | /* generate subkey K1 */ 110 | memset1(K, '\0', 16); 111 | 112 | //rijndael_encrypt(&ctx->rijndael, K, K); 113 | 114 | aes_encrypt( K, K, &ctx->rijndael); 115 | 116 | if (K[0] & 0x80) { 117 | LSHIFT(K, K); 118 | K[15] ^= 0x87; 119 | } else 120 | LSHIFT(K, K); 121 | 122 | 123 | if (ctx->M_n == 16) { 124 | /* last block was a complete block */ 125 | XOR(K, ctx->M_last); 126 | 127 | } else { 128 | /* generate subkey K2 */ 129 | if (K[0] & 0x80) { 130 | LSHIFT(K, K); 131 | K[15] ^= 0x87; 132 | } else 133 | LSHIFT(K, K); 134 | 135 | /* padding(M_last) */ 136 | ctx->M_last[ctx->M_n] = 0x80; 137 | while (++ctx->M_n < 16) 138 | ctx->M_last[ctx->M_n] = 0; 139 | 140 | XOR(K, ctx->M_last); 141 | 142 | 143 | } 144 | XOR(ctx->M_last, ctx->X); 145 | 146 | //rijndael_encrypt(&ctx->rijndael, ctx->X, digest); 147 | 148 | memcpy1(in, &ctx->X[0], 16); //Bestela ez du ondo iten 149 | aes_encrypt(in, digest, &ctx->rijndael); 150 | memset1(K, 0, sizeof K); 151 | 152 | } 153 | 154 | -------------------------------------------------------------------------------- /crypto/cmac.h: -------------------------------------------------------------------------------- 1 | /************************************************************************** 2 | Copyright (C) 2009 Lander Casado, Philippas Tsigas 3 | 4 | All rights reserved. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining 7 | a copy of this software and associated documentation files 8 | (the "Software"), to deal with the Software without restriction, including 9 | without limitation the rights to use, copy, modify, merge, publish, 10 | distribute, sublicense, and/or sell copies of the Software, and to 11 | permit persons to whom the Software is furnished to do so, subject to 12 | the following conditions: 13 | 14 | Redistributions of source code must retain the above copyright notice, 15 | this list of conditions and the following disclaimers. Redistributions in 16 | binary form must reproduce the above copyright notice, this list of 17 | conditions and the following disclaimers in the documentation and/or 18 | other materials provided with the distribution. 19 | 20 | In no event shall the authors or copyright holders be liable for any special, 21 | incidental, indirect or consequential damages of any kind, or any damages 22 | whatsoever resulting from loss of use, data or profits, whether or not 23 | advised of the possibility of damage, and on any theory of liability, 24 | arising out of or in connection with the use or performance of this software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 27 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 31 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 32 | DEALINGS WITH THE SOFTWARE 33 | 34 | *****************************************************************************/ 35 | 36 | #ifndef _CMAC_H_ 37 | #define _CMAC_H_ 38 | 39 | #include "aes.h" 40 | 41 | #define AES_CMAC_KEY_LENGTH 16 42 | #define AES_CMAC_DIGEST_LENGTH 16 43 | 44 | typedef struct _AES_CMAC_CTX { 45 | aes_context rijndael; 46 | uint8_t X[16]; 47 | uint8_t M_last[16]; 48 | uint32_t M_n; 49 | } AES_CMAC_CTX; 50 | 51 | //#include 52 | 53 | //__BEGIN_DECLS 54 | void AES_CMAC_Init(AES_CMAC_CTX * ctx); 55 | void AES_CMAC_SetKey(AES_CMAC_CTX * ctx, const uint8_t key[AES_CMAC_KEY_LENGTH]); 56 | void AES_CMAC_Update(AES_CMAC_CTX * ctx, const uint8_t * data, uint32_t len); 57 | // __attribute__((__bounded__(__string__,2,3))); 58 | void AES_CMAC_Final(uint8_t digest[AES_CMAC_DIGEST_LENGTH], AES_CMAC_CTX * ctx); 59 | // __attribute__((__bounded__(__minbytes__,1,AES_CMAC_DIGEST_LENGTH))); 60 | //__END_DECLS 61 | 62 | #endif /* _CMAC_H_ */ 63 | 64 | -------------------------------------------------------------------------------- /gcc_nrf52.ld: -------------------------------------------------------------------------------- 1 | /* Linker script to configure memory regions. */ 2 | 3 | SEARCH_DIR(.) 4 | GROUP(-lgcc -lc -lnosys) 5 | 6 | MEMORY 7 | { 8 | FLASH (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000 9 | RAM (rwx) : ORIGIN = 0x20001b38, LENGTH = 0xe4c8 10 | } 11 | 12 | SECTIONS 13 | { 14 | .fs_data : 15 | { 16 | PROVIDE(__start_fs_data = .); 17 | KEEP(*(.fs_data)) 18 | PROVIDE(__stop_fs_data = .); 19 | } > RAM 20 | } INSERT AFTER .data; 21 | 22 | SECTIONS 23 | { 24 | .pwr_mgmt_data : 25 | { 26 | PROVIDE(__start_pwr_mgmt_data = .); 27 | KEEP(*(SORT(.pwr_mgmt_data*))) 28 | PROVIDE(__stop_pwr_mgmt_data = .); 29 | } > FLASH 30 | } INSERT AFTER .text 31 | 32 | INCLUDE "nrf5x_common.ld" 33 | -------------------------------------------------------------------------------- /mac/LoRaMac-definitions.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: LoRa MAC layer global definitions 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __LORAMAC_BOARD_H__ 16 | #define __LORAMAC_BOARD_H__ 17 | 18 | /*! 19 | * Returns individual channel mask 20 | * 21 | * \param[IN] channelIndex Channel index 1 based 22 | * \retval channelMask 23 | */ 24 | #define LC( channelIndex ) ( uint16_t )( 1 << ( channelIndex - 1 ) ) 25 | 26 | #if defined( USE_BAND_433 ) 27 | 28 | /*! 29 | * LoRaMac maximum number of channels 30 | */ 31 | #define LORA_MAX_NB_CHANNELS 16 32 | 33 | /*! 34 | * Minimal datarate that can be used by the node 35 | */ 36 | #define LORAMAC_TX_MIN_DATARATE DR_0 37 | 38 | /*! 39 | * Maximal datarate that can be used by the node 40 | */ 41 | #define LORAMAC_TX_MAX_DATARATE DR_7 42 | 43 | /*! 44 | * Minimal datarate that can be used by the node 45 | */ 46 | #define LORAMAC_RX_MIN_DATARATE DR_0 47 | 48 | /*! 49 | * Maximal datarate that can be used by the node 50 | */ 51 | #define LORAMAC_RX_MAX_DATARATE DR_7 52 | 53 | /*! 54 | * Default datarate used by the node 55 | */ 56 | #define LORAMAC_DEFAULT_DATARATE DR_0 57 | 58 | /*! 59 | * Minimal Rx1 receive datarate offset 60 | */ 61 | #define LORAMAC_MIN_RX1_DR_OFFSET 0 62 | 63 | /*! 64 | * Maximal Rx1 receive datarate offset 65 | */ 66 | #define LORAMAC_MAX_RX1_DR_OFFSET 5 67 | 68 | /*! 69 | * Minimal Tx output power that can be used by the node 70 | */ 71 | #define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM 72 | 73 | /*! 74 | * Maximal Tx output power that can be used by the node 75 | */ 76 | #define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM 77 | 78 | /*! 79 | * Default Tx output power used by the node 80 | */ 81 | #define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM 82 | 83 | /*! 84 | * LoRaMac TxPower definition 85 | */ 86 | #define TX_POWER_10_DBM 0 87 | #define TX_POWER_07_DBM 1 88 | #define TX_POWER_04_DBM 2 89 | #define TX_POWER_01_DBM 3 90 | #define TX_POWER_M2_DBM 4 91 | #define TX_POWER_M5_DBM 5 92 | 93 | /*! 94 | * LoRaMac datarates definition 95 | */ 96 | #define DR_0 0 // SF12 - BW125 97 | #define DR_1 1 // SF11 - BW125 98 | #define DR_2 2 // SF10 - BW125 99 | #define DR_3 3 // SF9 - BW125 100 | #define DR_4 4 // SF8 - BW125 101 | #define DR_5 5 // SF7 - BW125 102 | #define DR_6 6 // SF7 - BW250 103 | #define DR_7 7 // FSK 104 | 105 | /*! 106 | * Verification of default datarate 107 | */ 108 | #if ( LORAMAC_DEFAULT_DATARATE > DR_5 ) 109 | #error "A default DR higher than DR_5 may lead to connectivity loss." 110 | #endif 111 | 112 | /*! 113 | * Second reception window channel definition. 114 | */ 115 | // Channel = { Frequency [Hz], Datarate } 116 | #define RX_WND_2_CHANNEL { 434665000, DR_0 } 117 | 118 | /*! 119 | * LoRaMac maximum number of bands 120 | */ 121 | #define LORA_MAX_NB_BANDS 1 122 | 123 | // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } 124 | #define BAND0 { 100, TX_POWER_10_DBM, 0, 0 } // 1.0 % 125 | 126 | /*! 127 | * LoRaMac default channels 128 | */ 129 | // Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } 130 | #define LC1 { 433175000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 131 | #define LC2 { 433375000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 132 | #define LC3 { 433575000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 133 | 134 | /*! 135 | * LoRaMac channels which are allowed for the join procedure 136 | */ 137 | #define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) ) 138 | 139 | #elif defined( USE_BAND_470 ) 140 | 141 | /*! 142 | * LoRaMac maximum number of channels 143 | */ 144 | #define LORA_MAX_NB_CHANNELS 96 145 | 146 | /*! 147 | * Minimal datarate that can be used by the node 148 | */ 149 | #define LORAMAC_TX_MIN_DATARATE DR_0 150 | 151 | /*! 152 | * Maximal datarate that can be used by the node 153 | */ 154 | #define LORAMAC_TX_MAX_DATARATE DR_5 155 | 156 | /*! 157 | * Minimal datarate that can be used by the node 158 | */ 159 | #define LORAMAC_RX_MIN_DATARATE DR_0 160 | 161 | /*! 162 | * Maximal datarate that can be used by the node 163 | */ 164 | #define LORAMAC_RX_MAX_DATARATE DR_5 165 | 166 | /*! 167 | * Default datarate used by the node 168 | */ 169 | #define LORAMAC_DEFAULT_DATARATE DR_0 170 | 171 | /*! 172 | * Minimal Rx1 receive datarate offset 173 | */ 174 | #define LORAMAC_MIN_RX1_DR_OFFSET 0 175 | 176 | /*! 177 | * Maximal Rx1 receive datarate offset 178 | */ 179 | #define LORAMAC_MAX_RX1_DR_OFFSET 3 180 | 181 | /*! 182 | * Minimal Tx output power that can be used by the node 183 | */ 184 | #define LORAMAC_MIN_TX_POWER TX_POWER_2_DBM 185 | 186 | /*! 187 | * Maximal Tx output power that can be used by the node 188 | */ 189 | #define LORAMAC_MAX_TX_POWER TX_POWER_17_DBM 190 | 191 | /*! 192 | * Default Tx output power used by the node 193 | */ 194 | #define LORAMAC_DEFAULT_TX_POWER TX_POWER_14_DBM 195 | 196 | /*! 197 | * LoRaMac TxPower definition 198 | */ 199 | #define TX_POWER_17_DBM 0 200 | #define TX_POWER_16_DBM 1 201 | #define TX_POWER_14_DBM 2 202 | #define TX_POWER_12_DBM 3 203 | #define TX_POWER_10_DBM 4 204 | #define TX_POWER_7_DBM 5 205 | #define TX_POWER_5_DBM 6 206 | #define TX_POWER_2_DBM 7 207 | 208 | 209 | /*! 210 | * LoRaMac datarates definition 211 | */ 212 | #define DR_0 0 // SF12 - BW125 | 213 | #define DR_1 1 // SF11 - BW125 | 214 | #define DR_2 2 // SF10 - BW125 | 215 | #define DR_3 3 // SF9 - BW125 | 216 | #define DR_4 4 // SF8 - BW125 | 217 | #define DR_5 5 // SF7 - BW125 | 218 | 219 | /*! 220 | * Second reception window channel definition. 221 | */ 222 | // Channel = { Frequency [Hz], Datarate } 223 | #define RX_WND_2_CHANNEL { 505300000, DR_0 } 224 | 225 | /*! 226 | * LoRaMac maximum number of bands 227 | */ 228 | #define LORA_MAX_NB_BANDS 1 229 | 230 | // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } 231 | #define BAND0 { 1, TX_POWER_17_DBM, 0, 0 } // 100.0 % 232 | 233 | #elif defined( USE_BAND_780 ) 234 | 235 | /*! 236 | * LoRaMac maximum number of channels 237 | */ 238 | #define LORA_MAX_NB_CHANNELS 16 239 | 240 | /*! 241 | * Minimal datarate that can be used by the node 242 | */ 243 | #define LORAMAC_TX_MIN_DATARATE DR_0 244 | 245 | /*! 246 | * Maximal datarate that can be used by the node 247 | */ 248 | #define LORAMAC_TX_MAX_DATARATE DR_7 249 | 250 | /*! 251 | * Minimal datarate that can be used by the node 252 | */ 253 | #define LORAMAC_RX_MIN_DATARATE DR_0 254 | 255 | /*! 256 | * Maximal datarate that can be used by the node 257 | */ 258 | #define LORAMAC_RX_MAX_DATARATE DR_7 259 | 260 | /*! 261 | * Default datarate used by the node 262 | */ 263 | #define LORAMAC_DEFAULT_DATARATE DR_0 264 | 265 | /*! 266 | * Minimal Rx1 receive datarate offset 267 | */ 268 | #define LORAMAC_MIN_RX1_DR_OFFSET 0 269 | 270 | /*! 271 | * Maximal Rx1 receive datarate offset 272 | */ 273 | #define LORAMAC_MAX_RX1_DR_OFFSET 5 274 | 275 | /*! 276 | * Minimal Tx output power that can be used by the node 277 | */ 278 | #define LORAMAC_MIN_TX_POWER TX_POWER_M5_DBM 279 | 280 | /*! 281 | * Maximal Tx output power that can be used by the node 282 | */ 283 | #define LORAMAC_MAX_TX_POWER TX_POWER_10_DBM 284 | 285 | /*! 286 | * Default Tx output power used by the node 287 | */ 288 | #define LORAMAC_DEFAULT_TX_POWER TX_POWER_10_DBM 289 | 290 | /*! 291 | * LoRaMac TxPower definition 292 | */ 293 | #define TX_POWER_10_DBM 0 294 | #define TX_POWER_07_DBM 1 295 | #define TX_POWER_04_DBM 2 296 | #define TX_POWER_01_DBM 3 297 | #define TX_POWER_M2_DBM 4 298 | #define TX_POWER_M5_DBM 5 299 | 300 | /*! 301 | * LoRaMac datarates definition 302 | */ 303 | #define DR_0 0 // SF12 - BW125 304 | #define DR_1 1 // SF11 - BW125 305 | #define DR_2 2 // SF10 - BW125 306 | #define DR_3 3 // SF9 - BW125 307 | #define DR_4 4 // SF8 - BW125 308 | #define DR_5 5 // SF7 - BW125 309 | #define DR_6 6 // SF7 - BW250 310 | #define DR_7 7 // FSK 311 | 312 | /*! 313 | * Verification of default datarate 314 | */ 315 | #if ( LORAMAC_DEFAULT_DATARATE > DR_5 ) 316 | #error "A default DR higher than DR_5 may lead to connectivity loss." 317 | #endif 318 | 319 | /*! 320 | * Second reception window channel definition. 321 | */ 322 | // Channel = { Frequency [Hz], Datarate } 323 | #define RX_WND_2_CHANNEL { 786000000, DR_0 } 324 | 325 | /*! 326 | * LoRaMac maximum number of bands 327 | */ 328 | #define LORA_MAX_NB_BANDS 1 329 | 330 | // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } 331 | #define BAND0 { 100, TX_POWER_10_DBM, 0, 0 } // 1.0 % 332 | 333 | /*! 334 | * LoRaMac default channels 335 | */ 336 | // Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } 337 | #define LC1 { 779500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 338 | #define LC2 { 779700000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 339 | #define LC3 { 779900000, { ( ( DR_5 << 4 ) | DR_0 ) }, 0 } 340 | 341 | /*! 342 | * LoRaMac channels which are allowed for the join procedure 343 | */ 344 | #define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) ) 345 | 346 | #elif defined( USE_BAND_868 ) 347 | 348 | /*! 349 | * LoRaMac maximum number of channels 350 | */ 351 | #define LORA_MAX_NB_CHANNELS 16 352 | 353 | /*! 354 | * Minimal datarate that can be used by the node 355 | */ 356 | #define LORAMAC_TX_MIN_DATARATE DR_0 357 | 358 | /*! 359 | * Maximal datarate that can be used by the node 360 | */ 361 | #define LORAMAC_TX_MAX_DATARATE DR_7 362 | 363 | /*! 364 | * Minimal datarate that can be used by the node 365 | */ 366 | #define LORAMAC_RX_MIN_DATARATE DR_0 367 | 368 | /*! 369 | * Maximal datarate that can be used by the node 370 | */ 371 | #define LORAMAC_RX_MAX_DATARATE DR_7 372 | 373 | /*! 374 | * Default datarate used by the node 375 | */ 376 | #define LORAMAC_DEFAULT_DATARATE DR_0 377 | 378 | /*! 379 | * Minimal Rx1 receive datarate offset 380 | */ 381 | #define LORAMAC_MIN_RX1_DR_OFFSET 0 382 | 383 | /*! 384 | * Maximal Rx1 receive datarate offset 385 | */ 386 | #define LORAMAC_MAX_RX1_DR_OFFSET 5 387 | 388 | /*! 389 | * Minimal Tx output power that can be used by the node 390 | */ 391 | #define LORAMAC_MIN_TX_POWER TX_POWER_02_DBM 392 | 393 | /*! 394 | * Maximal Tx output power that can be used by the node 395 | */ 396 | #define LORAMAC_MAX_TX_POWER TX_POWER_20_DBM 397 | 398 | /*! 399 | * Default Tx output power used by the node 400 | */ 401 | #define LORAMAC_DEFAULT_TX_POWER TX_POWER_14_DBM 402 | 403 | /*! 404 | * LoRaMac TxPower definition 405 | */ 406 | #define TX_POWER_20_DBM 0 407 | #define TX_POWER_14_DBM 1 408 | #define TX_POWER_11_DBM 2 409 | #define TX_POWER_08_DBM 3 410 | #define TX_POWER_05_DBM 4 411 | #define TX_POWER_02_DBM 5 412 | 413 | /*! 414 | * LoRaMac datarates definition 415 | */ 416 | #define DR_0 0 // SF12 - BW125 417 | #define DR_1 1 // SF11 - BW125 418 | #define DR_2 2 // SF10 - BW125 419 | #define DR_3 3 // SF9 - BW125 420 | #define DR_4 4 // SF8 - BW125 421 | #define DR_5 5 // SF7 - BW125 422 | #define DR_6 6 // SF7 - BW250 423 | #define DR_7 7 // FSK 424 | 425 | /*! 426 | * Verification of default datarate 427 | */ 428 | #if ( LORAMAC_DEFAULT_DATARATE > DR_5 ) 429 | #error "A default DR higher than DR_5 may lead to connectivity loss." 430 | #endif 431 | 432 | /*! 433 | * Second reception window channel definition. 434 | */ 435 | // Channel = { Frequency [Hz], Datarate } 436 | #define RX_WND_2_CHANNEL { 869525000, DR_0 } 437 | 438 | /*! 439 | * LoRaMac maximum number of bands 440 | */ 441 | #define LORA_MAX_NB_BANDS 5 442 | 443 | /*! 444 | * LoRaMac EU868 default bands 445 | */ 446 | typedef enum 447 | { 448 | BAND_G1_0, 449 | BAND_G1_1, 450 | BAND_G1_2, 451 | BAND_G1_3, 452 | BAND_G1_4, 453 | }BandId_t; 454 | 455 | // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } 456 | #define BAND0 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % 457 | #define BAND1 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % 458 | #define BAND2 { 1000, TX_POWER_14_DBM, 0, 0 } // 0.1 % 459 | #define BAND3 { 10 , TX_POWER_14_DBM, 0, 0 } // 10.0 % 460 | #define BAND4 { 100 , TX_POWER_14_DBM, 0, 0 } // 1.0 % 461 | 462 | /*! 463 | * LoRaMac default channels 464 | */ 465 | // Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } 466 | #define LC1 { 868100000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } 467 | #define LC2 { 868300000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } 468 | #define LC3 { 868500000, { ( ( DR_5 << 4 ) | DR_0 ) }, 1 } 469 | 470 | /*! 471 | * LoRaMac channels which are allowed for the join procedure 472 | */ 473 | #define JOIN_CHANNELS ( uint16_t )( LC( 1 ) | LC( 2 ) | LC( 3 ) ) 474 | 475 | #elif defined( USE_BAND_915 ) || defined( USE_BAND_915_HYBRID ) 476 | 477 | /*! 478 | * LoRaMac maximum number of channels 479 | */ 480 | #define LORA_MAX_NB_CHANNELS 72 481 | 482 | /*! 483 | * Minimal datarate that can be used by the node 484 | */ 485 | #define LORAMAC_TX_MIN_DATARATE DR_0 486 | 487 | /*! 488 | * Maximal datarate that can be used by the node 489 | */ 490 | #define LORAMAC_TX_MAX_DATARATE DR_4 491 | 492 | /*! 493 | * Minimal datarate that can be used by the node 494 | */ 495 | #define LORAMAC_RX_MIN_DATARATE DR_8 496 | 497 | /*! 498 | * Maximal datarate that can be used by the node 499 | */ 500 | #define LORAMAC_RX_MAX_DATARATE DR_13 501 | 502 | /*! 503 | * Default datarate used by the node 504 | */ 505 | #define LORAMAC_DEFAULT_DATARATE DR_0 506 | 507 | /*! 508 | * Minimal Rx1 receive datarate offset 509 | */ 510 | #define LORAMAC_MIN_RX1_DR_OFFSET 0 511 | 512 | /*! 513 | * Maximal Rx1 receive datarate offset 514 | */ 515 | #define LORAMAC_MAX_RX1_DR_OFFSET 3 516 | 517 | /*! 518 | * Minimal Tx output power that can be used by the node 519 | */ 520 | #define LORAMAC_MIN_TX_POWER TX_POWER_10_DBM 521 | 522 | /*! 523 | * Maximal Tx output power that can be used by the node 524 | */ 525 | #define LORAMAC_MAX_TX_POWER TX_POWER_30_DBM 526 | 527 | /*! 528 | * Default Tx output power used by the node 529 | */ 530 | #define LORAMAC_DEFAULT_TX_POWER TX_POWER_20_DBM 531 | 532 | /*! 533 | * LoRaMac TxPower definition 534 | */ 535 | #define TX_POWER_30_DBM 0 536 | #define TX_POWER_28_DBM 1 537 | #define TX_POWER_26_DBM 2 538 | #define TX_POWER_24_DBM 3 539 | #define TX_POWER_22_DBM 4 540 | #define TX_POWER_20_DBM 5 541 | #define TX_POWER_18_DBM 6 542 | #define TX_POWER_16_DBM 7 543 | #define TX_POWER_14_DBM 8 544 | #define TX_POWER_12_DBM 9 545 | #define TX_POWER_10_DBM 10 546 | 547 | /*! 548 | * LoRaMac datarates definition 549 | */ 550 | #define DR_0 0 // SF10 - BW125 | 551 | #define DR_1 1 // SF9 - BW125 | 552 | #define DR_2 2 // SF8 - BW125 +-> Up link 553 | #define DR_3 3 // SF7 - BW125 | 554 | #define DR_4 4 // SF8 - BW500 | 555 | #define DR_5 5 // RFU 556 | #define DR_6 6 // RFU 557 | #define DR_7 7 // RFU 558 | #define DR_8 8 // SF12 - BW500 | 559 | #define DR_9 9 // SF11 - BW500 | 560 | #define DR_10 10 // SF10 - BW500 | 561 | #define DR_11 11 // SF9 - BW500 | 562 | #define DR_12 12 // SF8 - BW500 +-> Down link 563 | #define DR_13 13 // SF7 - BW500 | 564 | #define DR_14 14 // RFU | 565 | #define DR_15 15 // RFU | 566 | 567 | /*! 568 | * Second reception window channel definition. 569 | */ 570 | // Channel = { Frequency [Hz], Datarate } 571 | #define RX_WND_2_CHANNEL { 923300000, DR_8 } 572 | 573 | /*! 574 | * LoRaMac maximum number of bands 575 | */ 576 | #define LORA_MAX_NB_BANDS 1 577 | 578 | // Band = { DutyCycle, TxMaxPower, LastTxDoneTime, TimeOff } 579 | #define BAND0 { 1, TX_POWER_20_DBM, 0, 0 } // 100.0 % 580 | 581 | /*! 582 | * LoRaMac default channels 583 | */ 584 | // Channel = { Frequency [Hz], { ( ( DrMax << 4 ) | DrMin ) }, Band } 585 | /* 586 | * US band channels are initialized using a loop in LoRaMacInit function 587 | * \code 588 | * // 125 kHz channels 589 | * for( uint8_t i = 0; i < LORA_MAX_NB_CHANNELS - 8; i++ ) 590 | * { 591 | * Channels[i].Frequency = 902.3e6 + i * 200e3; 592 | * Channels[i].DrRange.Value = ( DR_3 << 4 ) | DR_0; 593 | * Channels[i].Band = 0; 594 | * } 595 | * // 500 kHz channels 596 | * for( uint8_t i = LORA_MAX_NB_CHANNELS - 8; i < LORA_MAX_NB_CHANNELS; i++ ) 597 | * { 598 | * Channels[i].Frequency = 903.0e6 + ( i - ( LORA_MAX_NB_CHANNELS - 8 ) ) * 1.6e6; 599 | * Channels[i].DrRange.Value = ( DR_4 << 4 ) | DR_4; 600 | * Channels[i].Band = 0; 601 | * } 602 | * \endcode 603 | */ 604 | #else 605 | #error "Please define a frequency band in the compiler options." 606 | #endif 607 | 608 | #endif // __LORAMAC_BOARD_H__ 609 | -------------------------------------------------------------------------------- /mac/LoRaMacCrypto.c: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | ___ _____ _ ___ _ _____ ___ ___ ___ ___ 9 | / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 10 | \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 11 | |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 12 | embedded.connectivity.solutions=============== 13 | 14 | Description: LoRa MAC layer implementation 15 | 16 | License: Revised BSD License, see LICENSE.TXT file include in the project 17 | 18 | Maintainer: Miguel Luis ( Semtech ), Gregory Cristian ( Semtech ) and Daniel Jäckle ( STACKFORCE ) 19 | */ 20 | #include 21 | #include 22 | #include "utilities.h" 23 | 24 | #include "aes.h" 25 | #include "cmac.h" 26 | 27 | #include "LoRaMacCrypto.h" 28 | 29 | /*! 30 | * CMAC/AES Message Integrity Code (MIC) Block B0 size 31 | */ 32 | #define LORAMAC_MIC_BLOCK_B0_SIZE 16 33 | 34 | /*! 35 | * MIC field computation initial data 36 | */ 37 | static uint8_t MicBlockB0[] = { 0x49, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 39 | }; 40 | 41 | /*! 42 | * Contains the computed MIC field. 43 | * 44 | * \remark Only the 4 first bytes are used 45 | */ 46 | static uint8_t Mic[16]; 47 | 48 | /*! 49 | * Encryption aBlock and sBlock 50 | */ 51 | static uint8_t aBlock[] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 52 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 53 | }; 54 | static uint8_t sBlock[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 55 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 56 | }; 57 | 58 | /*! 59 | * AES computation context variable 60 | */ 61 | static aes_context AesContext; 62 | 63 | /*! 64 | * CMAC computation context variable 65 | */ 66 | static AES_CMAC_CTX AesCmacCtx[1]; 67 | 68 | /*! 69 | * \brief Computes the LoRaMAC frame MIC field 70 | * 71 | * \param [IN] buffer Data buffer 72 | * \param [IN] size Data buffer size 73 | * \param [IN] key AES key to be used 74 | * \param [IN] address Frame address 75 | * \param [IN] dir Frame direction [0: uplink, 1: downlink] 76 | * \param [IN] sequenceCounter Frame sequence counter 77 | * \param [OUT] mic Computed MIC field 78 | */ 79 | void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic ) 80 | { 81 | MicBlockB0[5] = dir; 82 | 83 | MicBlockB0[6] = ( address ) & 0xFF; 84 | MicBlockB0[7] = ( address >> 8 ) & 0xFF; 85 | MicBlockB0[8] = ( address >> 16 ) & 0xFF; 86 | MicBlockB0[9] = ( address >> 24 ) & 0xFF; 87 | 88 | MicBlockB0[10] = ( sequenceCounter ) & 0xFF; 89 | MicBlockB0[11] = ( sequenceCounter >> 8 ) & 0xFF; 90 | MicBlockB0[12] = ( sequenceCounter >> 16 ) & 0xFF; 91 | MicBlockB0[13] = ( sequenceCounter >> 24 ) & 0xFF; 92 | 93 | MicBlockB0[15] = size & 0xFF; 94 | 95 | AES_CMAC_Init( AesCmacCtx ); 96 | 97 | AES_CMAC_SetKey( AesCmacCtx, key ); 98 | 99 | AES_CMAC_Update( AesCmacCtx, MicBlockB0, LORAMAC_MIC_BLOCK_B0_SIZE ); 100 | 101 | AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF ); 102 | 103 | AES_CMAC_Final( Mic, AesCmacCtx ); 104 | 105 | *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); 106 | } 107 | 108 | void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ) 109 | { 110 | uint16_t i; 111 | uint8_t bufferIndex = 0; 112 | uint16_t ctr = 1; 113 | 114 | memset1( AesContext.ksch, '\0', 240 ); 115 | aes_set_key( key, 16, &AesContext ); 116 | 117 | aBlock[5] = dir; 118 | 119 | aBlock[6] = ( address ) & 0xFF; 120 | aBlock[7] = ( address >> 8 ) & 0xFF; 121 | aBlock[8] = ( address >> 16 ) & 0xFF; 122 | aBlock[9] = ( address >> 24 ) & 0xFF; 123 | 124 | aBlock[10] = ( sequenceCounter ) & 0xFF; 125 | aBlock[11] = ( sequenceCounter >> 8 ) & 0xFF; 126 | aBlock[12] = ( sequenceCounter >> 16 ) & 0xFF; 127 | aBlock[13] = ( sequenceCounter >> 24 ) & 0xFF; 128 | 129 | while( size >= 16 ) 130 | { 131 | aBlock[15] = ( ( ctr ) & 0xFF ); 132 | ctr++; 133 | aes_encrypt( aBlock, sBlock, &AesContext ); 134 | for( i = 0; i < 16; i++ ) 135 | { 136 | encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i]; 137 | } 138 | size -= 16; 139 | bufferIndex += 16; 140 | } 141 | 142 | if( size > 0 ) 143 | { 144 | aBlock[15] = ( ( ctr ) & 0xFF ); 145 | aes_encrypt( aBlock, sBlock, &AesContext ); 146 | for( i = 0; i < size; i++ ) 147 | { 148 | encBuffer[bufferIndex + i] = buffer[bufferIndex + i] ^ sBlock[i]; 149 | } 150 | } 151 | } 152 | 153 | void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ) 154 | { 155 | LoRaMacPayloadEncrypt( buffer, size, key, address, dir, sequenceCounter, decBuffer ); 156 | } 157 | 158 | void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ) 159 | { 160 | AES_CMAC_Init( AesCmacCtx ); 161 | 162 | AES_CMAC_SetKey( AesCmacCtx, key ); 163 | 164 | AES_CMAC_Update( AesCmacCtx, buffer, size & 0xFF ); 165 | 166 | AES_CMAC_Final( Mic, AesCmacCtx ); 167 | 168 | *mic = ( uint32_t )( ( uint32_t )Mic[3] << 24 | ( uint32_t )Mic[2] << 16 | ( uint32_t )Mic[1] << 8 | ( uint32_t )Mic[0] ); 169 | } 170 | 171 | void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ) 172 | { 173 | memset1( AesContext.ksch, '\0', 240 ); 174 | aes_set_key( key, 16, &AesContext ); 175 | aes_encrypt( buffer, decBuffer, &AesContext ); 176 | // Check if optional CFList is included 177 | if( size >= 16 ) 178 | { 179 | aes_encrypt( buffer + 16, decBuffer + 16, &AesContext ); 180 | } 181 | } 182 | 183 | void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ) 184 | { 185 | uint8_t nonce[16]; 186 | uint8_t *pDevNonce = ( uint8_t * )&devNonce; 187 | 188 | memset1( AesContext.ksch, '\0', 240 ); 189 | aes_set_key( key, 16, &AesContext ); 190 | 191 | memset1( nonce, 0, sizeof( nonce ) ); 192 | nonce[0] = 0x01; 193 | memcpy1( nonce + 1, appNonce, 6 ); 194 | memcpy1( nonce + 7, pDevNonce, 2 ); 195 | aes_encrypt( nonce, nwkSKey, &AesContext ); 196 | 197 | memset1( nonce, 0, sizeof( nonce ) ); 198 | nonce[0] = 0x02; 199 | memcpy1( nonce + 1, appNonce, 6 ); 200 | memcpy1( nonce + 7, pDevNonce, 2 ); 201 | aes_encrypt( nonce, appSKey, &AesContext ); 202 | } 203 | -------------------------------------------------------------------------------- /mac/LoRaMacCrypto.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file LoRaMacCrypto.h 3 | * 4 | * \brief LoRa MAC layer cryptography implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013 Semtech 16 | * 17 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 18 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 19 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 20 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 21 | * embedded.connectivity.solutions=============== 22 | * 23 | * \endcode 24 | * 25 | * \author Miguel Luis ( Semtech ) 26 | * 27 | * \author Gregory Cristian ( Semtech ) 28 | * 29 | * \author Daniel Jäckle ( STACKFORCE ) 30 | * 31 | * \defgroup LORAMAC_CRYPTO LoRa MAC layer cryptography implementation 32 | * This module covers the implementation of cryptographic functions 33 | * of the LoRaMAC layer. 34 | * \{ 35 | */ 36 | #ifndef __LORAMAC_CRYPTO_H__ 37 | #define __LORAMAC_CRYPTO_H__ 38 | 39 | /*! 40 | * Computes the LoRaMAC frame MIC field 41 | * 42 | * \param [IN] buffer - Data buffer 43 | * \param [IN] size - Data buffer size 44 | * \param [IN] key - AES key to be used 45 | * \param [IN] address - Frame address 46 | * \param [IN] dir - Frame direction [0: uplink, 1: downlink] 47 | * \param [IN] sequenceCounter - Frame sequence counter 48 | * \param [OUT] mic - Computed MIC field 49 | */ 50 | void LoRaMacComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint32_t *mic ); 51 | 52 | /*! 53 | * Computes the LoRaMAC payload encryption 54 | * 55 | * \param [IN] buffer - Data buffer 56 | * \param [IN] size - Data buffer size 57 | * \param [IN] key - AES key to be used 58 | * \param [IN] address - Frame address 59 | * \param [IN] dir - Frame direction [0: uplink, 1: downlink] 60 | * \param [IN] sequenceCounter - Frame sequence counter 61 | * \param [OUT] encBuffer - Encrypted buffer 62 | */ 63 | void LoRaMacPayloadEncrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *encBuffer ); 64 | 65 | /*! 66 | * Computes the LoRaMAC payload decryption 67 | * 68 | * \param [IN] buffer - Data buffer 69 | * \param [IN] size - Data buffer size 70 | * \param [IN] key - AES key to be used 71 | * \param [IN] address - Frame address 72 | * \param [IN] dir - Frame direction [0: uplink, 1: downlink] 73 | * \param [IN] sequenceCounter - Frame sequence counter 74 | * \param [OUT] decBuffer - Decrypted buffer 75 | */ 76 | void LoRaMacPayloadDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t address, uint8_t dir, uint32_t sequenceCounter, uint8_t *decBuffer ); 77 | 78 | /*! 79 | * Computes the LoRaMAC Join Request frame MIC field 80 | * 81 | * \param [IN] buffer - Data buffer 82 | * \param [IN] size - Data buffer size 83 | * \param [IN] key - AES key to be used 84 | * \param [OUT] mic - Computed MIC field 85 | */ 86 | void LoRaMacJoinComputeMic( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint32_t *mic ); 87 | 88 | /*! 89 | * Computes the LoRaMAC join frame decryption 90 | * 91 | * \param [IN] buffer - Data buffer 92 | * \param [IN] size - Data buffer size 93 | * \param [IN] key - AES key to be used 94 | * \param [OUT] decBuffer - Decrypted buffer 95 | */ 96 | void LoRaMacJoinDecrypt( const uint8_t *buffer, uint16_t size, const uint8_t *key, uint8_t *decBuffer ); 97 | 98 | /*! 99 | * Computes the LoRaMAC join frame decryption 100 | * 101 | * \param [IN] key - AES key to be used 102 | * \param [IN] appNonce - Application nonce 103 | * \param [IN] devNonce - Device nonce 104 | * \param [OUT] nwkSKey - Network session key 105 | * \param [OUT] appSKey - Application session key 106 | */ 107 | void LoRaMacJoinComputeSKeys( const uint8_t *key, const uint8_t *appNonce, uint16_t devNonce, uint8_t *nwkSKey, uint8_t *appSKey ); 108 | 109 | /*! \} defgroup LORAMAC */ 110 | 111 | #endif // __LORAMAC_CRYPTO_H__ 112 | -------------------------------------------------------------------------------- /mac/LoRaMacTest.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file LoRaMacTest.h 3 | * 4 | * \brief LoRa MAC layer test function implementation 5 | * 6 | * \copyright Revised BSD License, see section \ref LICENSE. 7 | * 8 | * \code 9 | * ______ _ 10 | * / _____) _ | | 11 | * ( (____ _____ ____ _| |_ _____ ____| |__ 12 | * \____ \| ___ | (_ _) ___ |/ ___) _ \ 13 | * _____) ) ____| | | || |_| ____( (___| | | | 14 | * (______/|_____)_|_|_| \__)_____)\____)_| |_| 15 | * (C)2013 Semtech 16 | * 17 | * ___ _____ _ ___ _ _____ ___ ___ ___ ___ 18 | * / __|_ _/_\ / __| |/ / __/ _ \| _ \/ __| __| 19 | * \__ \ | |/ _ \ (__| ' <| _| (_) | / (__| _| 20 | * |___/ |_/_/ \_\___|_|\_\_| \___/|_|_\\___|___| 21 | * embedded.connectivity.solutions=============== 22 | * 23 | * \endcode 24 | * 25 | * \author Miguel Luis ( Semtech ) 26 | * 27 | * \author Gregory Cristian ( Semtech ) 28 | * 29 | * \author Daniel Jäckle ( STACKFORCE ) 30 | * 31 | * \defgroup LORAMACTEST LoRa MAC layer test function implementation 32 | * This module specifies the API implementation of test function of the LoRaMAC layer. 33 | * The functions in this file are only for testing purposes only. 34 | * \{ 35 | */ 36 | #ifndef __LORAMACTEST_H__ 37 | #define __LORAMACTEST_H__ 38 | 39 | /*! 40 | * \brief Enabled or disables the reception windows 41 | * 42 | * \details This is a test function. It shall be used for testing purposes only. 43 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 44 | * 45 | * \param [IN] enable - Enabled or disables the reception windows 46 | */ 47 | void LoRaMacTestRxWindowsOn( bool enable ); 48 | 49 | /*! 50 | * \brief Enables the MIC field test 51 | * 52 | * \details This is a test function. It shall be used for testing purposes only. 53 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 54 | * 55 | * \param [IN] txPacketCounter - Fixed Tx packet counter value 56 | */ 57 | void LoRaMacTestSetMic( uint16_t txPacketCounter ); 58 | 59 | /*! 60 | * \brief Enabled or disables the duty cycle 61 | * 62 | * \details This is a test function. It shall be used for testing purposes only. 63 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 64 | * 65 | * \param [IN] enable - Enabled or disables the duty cycle 66 | */ 67 | void LoRaMacTestSetDutyCycleOn( bool enable ); 68 | 69 | /*! 70 | * \brief Sets the channel index 71 | * 72 | * \details This is a test function. It shall be used for testing purposes only. 73 | * Changing this attribute may lead to a non-conformance LoRaMac operation. 74 | * 75 | * \param [IN] channel - Channel index 76 | */ 77 | void LoRaMacTestSetChannel( uint8_t channel ); 78 | 79 | /*! \} defgroup LORAMACTEST */ 80 | 81 | #endif // __LORAMACTEST_H__ 82 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "app_config.h" 4 | #include "app_timer.h" 5 | 6 | #include "nrf_drv_gpiote.h" 7 | #include "nrf_drv_wdt.h" 8 | #include "nrf_delay.h" 9 | #include "nrf_sdm.h" 10 | #include "softdevice_handler.h" 11 | #include "mem_manager.h" 12 | #include "board.h" 13 | 14 | #define NRF_LOG_MODULE_NAME "APP" 15 | #define NRF_LOG_LEVEL 4 16 | #include "nrf_log.h" 17 | #include "nrf_log_ctrl.h" 18 | 19 | TIMER_DEF(main_sm_timer); 20 | static char build_version[] = BUILD_VERSION; 21 | static nrf_drv_wdt_channel_id m_channel_id; 22 | static void main_sm_timer_callback(void *ctx); 23 | 24 | /** 25 | * @brief Assert callback. 26 | * 27 | * @param[in] id Fault identifier. See @ref NRF_FAULT_IDS. 28 | * @param[in] pc The program counter of the instruction that triggered the fault, or 0 if 29 | * unavailable. 30 | * @param[in] info Optional additional information regarding the fault. Refer to each fault 31 | * identifier for details. 32 | */ 33 | void wdt_init(void); 34 | void app_error_fault_handler(uint32_t id, uint32_t pc, uint32_t info) 35 | { 36 | error_info_t *error_info = (error_info_t*)info; 37 | NRF_LOG_ERROR("code: %d %s:%d\r\n", error_info->err_code, 38 | (uint32_t)error_info->p_file_name, 39 | error_info->line_num); 40 | NRF_LOG_FLUSH(); 41 | wdt_init(); 42 | while (1) {}; 43 | } 44 | 45 | /**@brief Callback function for asserts in the SoftDevice. 46 | * 47 | * @details This function will be called in case of an assert in the SoftDevice. 48 | * 49 | * @warning This handler is an example only and does not fit a final product. You need to analyze 50 | * how your product is supposed to react in case of Assert. 51 | * @warning On assert from the SoftDevice, the system can only recover on reset. 52 | * 53 | * @param[in] line_num Line number of the failing ASSERT call. 54 | * @param[in] file_name File name of the failing ASSERT call. 55 | */ 56 | void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name) 57 | { 58 | app_error_handler(DEAD_BEEF, line_num, p_file_name); 59 | } 60 | 61 | /**@brief Function for initializing logging. */ 62 | void log_init(void) 63 | { 64 | ret_code_t err_code = NRF_LOG_INIT(NULL); 65 | APP_ERROR_CHECK(err_code); 66 | } 67 | 68 | /**@brief Function for initializing timers. */ 69 | void timers_init(void) 70 | { 71 | ret_code_t err_code = app_timer_init(); 72 | APP_ERROR_CHECK(err_code); 73 | TIMER_INIT(main_sm_timer, main_sm_timer_callback); 74 | } 75 | 76 | /**@brief Function for initializing GPIOTE. */ 77 | void gpiote_init(void) 78 | { 79 | ret_code_t err_code = nrf_drv_gpiote_init(); 80 | APP_ERROR_CHECK(err_code); 81 | } 82 | 83 | /**@brief Function for initializing MEMORY MANAGER. */ 84 | void mem_mgr_init(void) 85 | { 86 | ret_code_t err_code = nrf_mem_init(); 87 | APP_ERROR_CHECK(err_code); 88 | } 89 | 90 | /**@brief Function for initializing Softdevice. */ 91 | void sd_init(void) 92 | { 93 | ret_code_t err_code; 94 | nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC; 95 | 96 | // Initialize the SoftDevice handler module. 97 | SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL); 98 | 99 | // Fetch the starting address of the application ram. This is needed by the upcoming SoftDevice calls. 100 | uint32_t ram_start = 0; 101 | err_code = softdevice_app_ram_start_get(&ram_start); 102 | APP_ERROR_CHECK(err_code); 103 | 104 | // Overwrite some of the default configurations for the BLE stack. 105 | ble_cfg_t ble_cfg; 106 | 107 | // Configure the number of custom UUIDS. 108 | memset(&ble_cfg, 0, sizeof(ble_cfg)); 109 | ble_cfg.common_cfg.vs_uuid_cfg.vs_uuid_count = 0; 110 | err_code = sd_ble_cfg_set(BLE_COMMON_CFG_VS_UUID, &ble_cfg, ram_start); 111 | APP_ERROR_CHECK(err_code); 112 | 113 | // Configure the maximum number of connections. 114 | memset(&ble_cfg, 0, sizeof(ble_cfg)); 115 | ble_cfg.gap_cfg.role_count_cfg.periph_role_count = BLE_GAP_ROLE_COUNT_PERIPH_DEFAULT; 116 | ble_cfg.gap_cfg.role_count_cfg.central_role_count = 0; 117 | ble_cfg.gap_cfg.role_count_cfg.central_sec_count = 0; 118 | err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_cfg, ram_start); 119 | APP_ERROR_CHECK(err_code); 120 | 121 | memset(&ble_cfg, 0, sizeof(ble_cfg)); 122 | ble_cfg.gatts_cfg.attr_tab_size.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_MIN; 123 | err_code = sd_ble_cfg_set(BLE_GATTS_CFG_ATTR_TAB_SIZE, &ble_cfg, ram_start); 124 | APP_ERROR_CHECK(err_code); 125 | 126 | // Enable BLE stack. 127 | err_code = softdevice_enable(&ram_start); 128 | APP_ERROR_CHECK(err_code); 129 | } 130 | 131 | void wdt_event_handler(void) 132 | { 133 | //NOTE: The max amount of time we can spend in WDT interrupt is two cycles of 32768[Hz] clock - after that, reset occurs 134 | } 135 | 136 | void wdt_init(void) 137 | { 138 | nrf_drv_wdt_config_t config = NRF_DRV_WDT_DEAFULT_CONFIG; 139 | ret_code_t err_code = nrf_drv_wdt_init(&config, wdt_event_handler); 140 | APP_ERROR_CHECK(err_code); 141 | err_code = nrf_drv_wdt_channel_alloc(&m_channel_id); 142 | APP_ERROR_CHECK(err_code); 143 | nrf_drv_wdt_enable(); 144 | } 145 | 146 | #define FPU_EXCEPTION_MASK 0x0000009F //!< FPU exception mask used to clear exceptions in FPSCR register. 147 | 148 | /**@brief Function for doing power management. */ 149 | void power_manage(void) 150 | { 151 | __set_FPSCR(__get_FPSCR() & ~(FPU_EXCEPTION_MASK)); 152 | (void) __get_FPSCR(); 153 | NVIC_ClearPendingIRQ(FPU_IRQn); 154 | ret_code_t err_code = sd_app_evt_wait(); 155 | APP_ERROR_CHECK(err_code); 156 | } 157 | 158 | static void main_sm_timer_callback(void *ctx) 159 | { 160 | NRF_LOG_DEBUG("sm_timer_callback\r\n"); 161 | } 162 | 163 | int main(void) 164 | { 165 | /* Initialize */ 166 | log_init(); 167 | NRF_LOG_INFO("Version: %s\r\n", (uint32_t)build_version); 168 | NRF_LOG_INFO("HW init start\r\n"); 169 | timers_init(); 170 | gpiote_init(); 171 | mem_mgr_init(); 172 | rtc_init(NULL); 173 | sd_init(); 174 | NRF_LOG_INFO("HW init done\r\n"); 175 | #if 0 176 | TimerSetValue(&main_sm_timer, 1000); 177 | TimerStart(&main_sm_timer); 178 | 179 | 180 | while(1){NRF_LOG_PROCESS();}; 181 | #endif 182 | 183 | 184 | SX1276IoInit(); 185 | /* Enter main loop */ 186 | for (;;) { 187 | while(NRF_LOG_PROCESS()){}; 188 | lora_sm(); 189 | } 190 | } 191 | 192 | -------------------------------------------------------------------------------- /radio/radio.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Generic radio driver definition 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __RADIO_H__ 16 | #define __RADIO_H__ 17 | 18 | /*! 19 | * Radio driver supported modems 20 | */ 21 | typedef enum 22 | { 23 | MODEM_FSK = 0, 24 | MODEM_LORA, 25 | }RadioModems_t; 26 | 27 | /*! 28 | * Radio driver internal state machine states definition 29 | */ 30 | typedef enum 31 | { 32 | RF_IDLE = 0, 33 | RF_RX_RUNNING, 34 | RF_TX_RUNNING, 35 | RF_CAD, 36 | }RadioState_t; 37 | 38 | /*! 39 | * \brief Radio driver callback functions 40 | */ 41 | typedef struct 42 | { 43 | /*! 44 | * \brief Tx Done callback prototype. 45 | */ 46 | void ( *TxDone )( void ); 47 | /*! 48 | * \brief Tx Timeout callback prototype. 49 | */ 50 | void ( *TxTimeout )( void ); 51 | /*! 52 | * \brief Rx Done callback prototype. 53 | * 54 | * \param [IN] payload Received buffer pointer 55 | * \param [IN] size Received buffer size 56 | * \param [IN] rssi RSSI value computed while receiving the frame [dBm] 57 | * \param [IN] snr Raw SNR value given by the radio hardware 58 | * FSK : N/A ( set to 0 ) 59 | * LoRa: SNR value in dB 60 | */ 61 | void ( *RxDone )( uint8_t *payload, uint16_t size, int16_t rssi, int8_t snr ); 62 | /*! 63 | * \brief Rx Timeout callback prototype. 64 | */ 65 | void ( *RxTimeout )( void ); 66 | /*! 67 | * \brief Rx Error callback prototype. 68 | */ 69 | void ( *RxError )( void ); 70 | /*! 71 | * \brief FHSS Change Channel callback prototype. 72 | * 73 | * \param [IN] currentChannel Index number of the current channel 74 | */ 75 | void ( *FhssChangeChannel )( uint8_t currentChannel ); 76 | 77 | /*! 78 | * \brief CAD Done callback prototype. 79 | * 80 | * \param [IN] channelDetected Channel Activity detected during the CAD 81 | */ 82 | void ( *CadDone ) ( bool channelActivityDetected ); 83 | }RadioEvents_t; 84 | 85 | /*! 86 | * \brief Radio driver definition 87 | */ 88 | struct Radio_s 89 | { 90 | /*! 91 | * \brief Initializes the radio 92 | * 93 | * \param [IN] events Structure containing the driver callback functions 94 | */ 95 | void ( *Init )( RadioEvents_t *events ); 96 | /*! 97 | * Return current radio status 98 | * 99 | * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] 100 | */ 101 | RadioState_t ( *GetStatus )( void ); 102 | /*! 103 | * \brief Configures the radio with the given modem 104 | * 105 | * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] 106 | */ 107 | void ( *SetModem )( RadioModems_t modem ); 108 | /*! 109 | * \brief Sets the channel frequency 110 | * 111 | * \param [IN] freq Channel RF frequency 112 | */ 113 | void ( *SetChannel )( uint32_t freq ); 114 | /*! 115 | * \brief Sets the channels configuration 116 | * 117 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 118 | * \param [IN] freq Channel RF frequency 119 | * \param [IN] rssiThresh RSSI threshold 120 | * 121 | * \retval isFree [true: Channel is free, false: Channel is not free] 122 | */ 123 | bool ( *IsChannelFree )( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ); 124 | /*! 125 | * \brief Generates a 32 bits random value based on the RSSI readings 126 | * 127 | * \remark This function sets the radio in LoRa modem mode and disables 128 | * all interrupts. 129 | * After calling this function either Radio.SetRxConfig or 130 | * Radio.SetTxConfig functions must be called. 131 | * 132 | * \retval randomValue 32 bits random value 133 | */ 134 | uint32_t ( *Random )( void ); 135 | /*! 136 | * \brief Sets the reception parameters 137 | * 138 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 139 | * \param [IN] bandwidth Sets the bandwidth 140 | * FSK : >= 2600 and <= 250000 Hz 141 | * LoRa: [0: 125 kHz, 1: 250 kHz, 142 | * 2: 500 kHz, 3: Reserved] 143 | * \param [IN] datarate Sets the Datarate 144 | * FSK : 600..300000 bits/s 145 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 146 | * 10: 1024, 11: 2048, 12: 4096 chips] 147 | * \param [IN] coderate Sets the coding rate (LoRa only) 148 | * FSK : N/A ( set to 0 ) 149 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 150 | * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) 151 | * FSK : >= 2600 and <= 250000 Hz 152 | * LoRa: N/A ( set to 0 ) 153 | * \param [IN] preambleLen Sets the Preamble length 154 | * FSK : Number of bytes 155 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 156 | * \param [IN] symbTimeout Sets the RxSingle timeout value 157 | * FSK : timeout in number of bytes 158 | * LoRa: timeout in symbols 159 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 160 | * \param [IN] payloadLen Sets payload length when fixed length is used 161 | * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] 162 | * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping 163 | * FSK : N/A ( set to 0 ) 164 | * LoRa: [0: OFF, 1: ON] 165 | * \param [IN] HopPeriod Number of symbols between each hop 166 | * FSK : N/A ( set to 0 ) 167 | * LoRa: Number of symbols 168 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 169 | * FSK : N/A ( set to 0 ) 170 | * LoRa: [0: not inverted, 1: inverted] 171 | * \param [IN] rxContinuous Sets the reception in continuous mode 172 | * [false: single mode, true: continuous mode] 173 | */ 174 | void ( *SetRxConfig )( RadioModems_t modem, uint32_t bandwidth, 175 | uint32_t datarate, uint8_t coderate, 176 | uint32_t bandwidthAfc, uint16_t preambleLen, 177 | uint16_t symbTimeout, bool fixLen, 178 | uint8_t payloadLen, 179 | bool crcOn, bool FreqHopOn, uint8_t HopPeriod, 180 | bool iqInverted, bool rxContinuous ); 181 | /*! 182 | * \brief Sets the transmission parameters 183 | * 184 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 185 | * \param [IN] power Sets the output power [dBm] 186 | * \param [IN] fdev Sets the frequency deviation (FSK only) 187 | * FSK : [Hz] 188 | * LoRa: 0 189 | * \param [IN] bandwidth Sets the bandwidth (LoRa only) 190 | * FSK : 0 191 | * LoRa: [0: 125 kHz, 1: 250 kHz, 192 | * 2: 500 kHz, 3: Reserved] 193 | * \param [IN] datarate Sets the Datarate 194 | * FSK : 600..300000 bits/s 195 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 196 | * 10: 1024, 11: 2048, 12: 4096 chips] 197 | * \param [IN] coderate Sets the coding rate (LoRa only) 198 | * FSK : N/A ( set to 0 ) 199 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 200 | * \param [IN] preambleLen Sets the preamble length 201 | * FSK : Number of bytes 202 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 203 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 204 | * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] 205 | * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping 206 | * FSK : N/A ( set to 0 ) 207 | * LoRa: [0: OFF, 1: ON] 208 | * \param [IN] HopPeriod Number of symbols between each hop 209 | * FSK : N/A ( set to 0 ) 210 | * LoRa: Number of symbols 211 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 212 | * FSK : N/A ( set to 0 ) 213 | * LoRa: [0: not inverted, 1: inverted] 214 | * \param [IN] timeout Transmission timeout [ms] 215 | */ 216 | void ( *SetTxConfig )( RadioModems_t modem, int8_t power, uint32_t fdev, 217 | uint32_t bandwidth, uint32_t datarate, 218 | uint8_t coderate, uint16_t preambleLen, 219 | bool fixLen, bool crcOn, bool FreqHopOn, 220 | uint8_t HopPeriod, bool iqInverted, uint32_t timeout ); 221 | /*! 222 | * \brief Checks if the given RF frequency is supported by the hardware 223 | * 224 | * \param [IN] frequency RF frequency to be checked 225 | * \retval isSupported [true: supported, false: unsupported] 226 | */ 227 | bool ( *CheckRfFrequency )( uint32_t frequency ); 228 | /*! 229 | * \brief Computes the packet time on air in ms for the given payload 230 | * 231 | * \Remark Can only be called once SetRxConfig or SetTxConfig have been called 232 | * 233 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 234 | * \param [IN] pktLen Packet payload length 235 | * 236 | * \retval airTime Computed airTime (ms) for the given packet payload length 237 | */ 238 | uint32_t ( *TimeOnAir )( RadioModems_t modem, uint8_t pktLen ); 239 | /*! 240 | * \brief Sends the buffer of size. Prepares the packet to be sent and sets 241 | * the radio in transmission 242 | * 243 | * \param [IN]: buffer Buffer pointer 244 | * \param [IN]: size Buffer size 245 | */ 246 | void ( *Send )( uint8_t *buffer, uint8_t size ); 247 | /*! 248 | * \brief Sets the radio in sleep mode 249 | */ 250 | void ( *Sleep )( void ); 251 | /*! 252 | * \brief Sets the radio in standby mode 253 | */ 254 | void ( *Standby )( void ); 255 | /*! 256 | * \brief Sets the radio in reception mode for the given time 257 | * \param [IN] timeout Reception timeout [ms] 258 | * [0: continuous, others timeout] 259 | */ 260 | void ( *Rx )( uint32_t timeout ); 261 | /*! 262 | * \brief Start a Channel Activity Detection 263 | */ 264 | void ( *StartCad )( void ); 265 | /*! 266 | * \brief Sets the radio in continuous wave transmission mode 267 | * 268 | * \param [IN]: freq Channel RF frequency 269 | * \param [IN]: power Sets the output power [dBm] 270 | * \param [IN]: time Transmission mode timeout [s] 271 | */ 272 | void ( *SetTxContinuousWave )( uint32_t freq, int8_t power, uint16_t time ); 273 | /*! 274 | * \brief Reads the current RSSI value 275 | * 276 | * \retval rssiValue Current RSSI value in [dBm] 277 | */ 278 | int16_t ( *Rssi )( RadioModems_t modem ); 279 | /*! 280 | * \brief Writes the radio register at the specified address 281 | * 282 | * \param [IN]: addr Register address 283 | * \param [IN]: data New register value 284 | */ 285 | void ( *Write )( uint8_t addr, uint8_t data ); 286 | /*! 287 | * \brief Reads the radio register at the specified address 288 | * 289 | * \param [IN]: addr Register address 290 | * \retval data Register value 291 | */ 292 | uint8_t ( *Read )( uint8_t addr ); 293 | /*! 294 | * \brief Writes multiple radio registers starting at address 295 | * 296 | * \param [IN] addr First Radio register address 297 | * \param [IN] buffer Buffer containing the new register's values 298 | * \param [IN] size Number of registers to be written 299 | */ 300 | void ( *WriteBuffer )( uint8_t addr, uint8_t *buffer, uint8_t size ); 301 | /*! 302 | * \brief Reads multiple radio registers starting at address 303 | * 304 | * \param [IN] addr First Radio register address 305 | * \param [OUT] buffer Buffer where to copy the registers data 306 | * \param [IN] size Number of registers to be read 307 | */ 308 | void ( *ReadBuffer )( uint8_t addr, uint8_t *buffer, uint8_t size ); 309 | /*! 310 | * \brief Sets the maximum payload length. 311 | * 312 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 313 | * \param [IN] max Maximum payload length in bytes 314 | */ 315 | void ( *SetMaxPayloadLength )( RadioModems_t modem, uint8_t max ); 316 | /*! 317 | * \brief Sets the network to public or private. Updates the sync byte. 318 | * 319 | * \remark Applies to LoRa modem only 320 | * 321 | * \param [IN] enable if true, it enables a public network 322 | */ 323 | void ( *SetPublicNetwork )( bool enable ); 324 | }; 325 | 326 | /*! 327 | * \brief Radio driver 328 | * 329 | * \remark This variable is defined and initialized in the specific radio 330 | * board implementation 331 | */ 332 | extern const struct Radio_s Radio; 333 | 334 | #endif // __RADIO_H__ 335 | -------------------------------------------------------------------------------- /radio/sx1276/sx1276.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: Generic SX1276 driver implementation 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __SX1276_H__ 16 | #define __SX1276_H__ 17 | 18 | #include "sx1276Regs-Fsk.h" 19 | #include "sx1276Regs-LoRa.h" 20 | 21 | /*! 22 | * Radio wake-up time from sleep 23 | */ 24 | #define RADIO_WAKEUP_TIME 1 // [ms] 25 | 26 | /*! 27 | * Sync word for Private LoRa networks 28 | */ 29 | #define LORA_MAC_PRIVATE_SYNCWORD 0x12 30 | 31 | /*! 32 | * Sync word for Public LoRa networks 33 | */ 34 | #define LORA_MAC_PUBLIC_SYNCWORD 0x34 35 | 36 | /*! 37 | * Radio FSK modem parameters 38 | */ 39 | typedef struct 40 | { 41 | int8_t Power; 42 | uint32_t Fdev; 43 | uint32_t Bandwidth; 44 | uint32_t BandwidthAfc; 45 | uint32_t Datarate; 46 | uint16_t PreambleLen; 47 | bool FixLen; 48 | uint8_t PayloadLen; 49 | bool CrcOn; 50 | bool IqInverted; 51 | bool RxContinuous; 52 | uint32_t TxTimeout; 53 | uint32_t RxSingleTimeout; 54 | }RadioFskSettings_t; 55 | 56 | /*! 57 | * Radio FSK packet handler state 58 | */ 59 | typedef struct 60 | { 61 | uint8_t PreambleDetected; 62 | uint8_t SyncWordDetected; 63 | int8_t RssiValue; 64 | int32_t AfcValue; 65 | uint8_t RxGain; 66 | uint16_t Size; 67 | uint16_t NbBytes; 68 | uint8_t FifoThresh; 69 | uint8_t ChunkSize; 70 | }RadioFskPacketHandler_t; 71 | 72 | /*! 73 | * Radio LoRa modem parameters 74 | */ 75 | typedef struct 76 | { 77 | int8_t Power; 78 | uint32_t Bandwidth; 79 | uint32_t Datarate; 80 | bool LowDatarateOptimize; 81 | uint8_t Coderate; 82 | uint16_t PreambleLen; 83 | bool FixLen; 84 | uint8_t PayloadLen; 85 | bool CrcOn; 86 | bool FreqHopOn; 87 | uint8_t HopPeriod; 88 | bool IqInverted; 89 | bool RxContinuous; 90 | uint32_t TxTimeout; 91 | bool PublicNetwork; 92 | }RadioLoRaSettings_t; 93 | 94 | /*! 95 | * Radio LoRa packet handler state 96 | */ 97 | typedef struct 98 | { 99 | int8_t SnrValue; 100 | int16_t RssiValue; 101 | uint8_t Size; 102 | }RadioLoRaPacketHandler_t; 103 | 104 | /*! 105 | * Radio Settings 106 | */ 107 | typedef struct 108 | { 109 | RadioState_t State; 110 | RadioModems_t Modem; 111 | uint32_t Channel; 112 | RadioFskSettings_t Fsk; 113 | RadioFskPacketHandler_t FskPacketHandler; 114 | RadioLoRaSettings_t LoRa; 115 | RadioLoRaPacketHandler_t LoRaPacketHandler; 116 | }RadioSettings_t; 117 | 118 | /*! 119 | * Radio hardware and global parameters 120 | */ 121 | typedef struct SX1276_s 122 | { 123 | Gpio_t Reset; 124 | Gpio_t DIO0; 125 | Gpio_t DIO1; 126 | Gpio_t DIO2; 127 | Gpio_t DIO3; 128 | Gpio_t DIO4; 129 | Gpio_t DIO5; 130 | Spi_t Spi; 131 | RadioSettings_t Settings; 132 | }SX1276_t; 133 | 134 | /*! 135 | * Hardware IO IRQ callback function definition 136 | */ 137 | typedef void ( DioIrqHandler )( void ); 138 | 139 | /*! 140 | * SX1276 definitions 141 | */ 142 | #define XTAL_FREQ 32000000 143 | #define FREQ_STEP 61.03515625 144 | 145 | #define RX_BUFFER_SIZE 256 146 | 147 | /*! 148 | * ============================================================================ 149 | * Public functions prototypes 150 | * ============================================================================ 151 | */ 152 | 153 | /*! 154 | * \brief Initializes the radio 155 | * 156 | * \param [IN] events Structure containing the driver callback functions 157 | */ 158 | void SX1276Init( RadioEvents_t *events ); 159 | 160 | /*! 161 | * Return current radio status 162 | * 163 | * \param status Radio status.[RF_IDLE, RF_RX_RUNNING, RF_TX_RUNNING] 164 | */ 165 | RadioState_t SX1276GetStatus( void ); 166 | 167 | /*! 168 | * \brief Configures the radio with the given modem 169 | * 170 | * \param [IN] modem Modem to be used [0: FSK, 1: LoRa] 171 | */ 172 | void SX1276SetModem( RadioModems_t modem ); 173 | 174 | /*! 175 | * \brief Sets the channel configuration 176 | * 177 | * \param [IN] freq Channel RF frequency 178 | */ 179 | void SX1276SetChannel( uint32_t freq ); 180 | 181 | /*! 182 | * \brief Sets the channels configuration 183 | * 184 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 185 | * \param [IN] freq Channel RF frequency 186 | * \param [IN] rssiThresh RSSI threshold 187 | * 188 | * \retval isFree [true: Channel is free, false: Channel is not free] 189 | */ 190 | bool SX1276IsChannelFree( RadioModems_t modem, uint32_t freq, int16_t rssiThresh ); 191 | 192 | /*! 193 | * \brief Generates a 32 bits random value based on the RSSI readings 194 | * 195 | * \remark This function sets the radio in LoRa modem mode and disables 196 | * all interrupts. 197 | * After calling this function either SX1276SetRxConfig or 198 | * SX1276SetTxConfig functions must be called. 199 | * 200 | * \retval randomValue 32 bits random value 201 | */ 202 | uint32_t SX1276Random( void ); 203 | 204 | /*! 205 | * \brief Sets the reception parameters 206 | * 207 | * \remark When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported 208 | * 209 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 210 | * \param [IN] bandwidth Sets the bandwidth 211 | * FSK : >= 2600 and <= 250000 Hz 212 | * LoRa: [0: 125 kHz, 1: 250 kHz, 213 | * 2: 500 kHz, 3: Reserved] 214 | * \param [IN] datarate Sets the Datarate 215 | * FSK : 600..300000 bits/s 216 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 217 | * 10: 1024, 11: 2048, 12: 4096 chips] 218 | * \param [IN] coderate Sets the coding rate (LoRa only) 219 | * FSK : N/A ( set to 0 ) 220 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 221 | * \param [IN] bandwidthAfc Sets the AFC Bandwidth (FSK only) 222 | * FSK : >= 2600 and <= 250000 Hz 223 | * LoRa: N/A ( set to 0 ) 224 | * \param [IN] preambleLen Sets the Preamble length 225 | * FSK : Number of bytes 226 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 227 | * \param [IN] symbTimeout Sets the RxSingle timeout value 228 | * FSK : timeout number of bytes 229 | * LoRa: timeout in symbols 230 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 231 | * \param [IN] payloadLen Sets payload length when fixed length is used 232 | * \param [IN] crcOn Enables/Disables the CRC [0: OFF, 1: ON] 233 | * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping 234 | * FSK : N/A ( set to 0 ) 235 | * LoRa: [0: OFF, 1: ON] 236 | * \param [IN] HopPeriod Number of symbols between each hop 237 | * FSK : N/A ( set to 0 ) 238 | * LoRa: Number of symbols 239 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 240 | * FSK : N/A ( set to 0 ) 241 | * LoRa: [0: not inverted, 1: inverted] 242 | * \param [IN] rxContinuous Sets the reception in continuous mode 243 | * [false: single mode, true: continuous mode] 244 | */ 245 | void SX1276SetRxConfig( RadioModems_t modem, uint32_t bandwidth, 246 | uint32_t datarate, uint8_t coderate, 247 | uint32_t bandwidthAfc, uint16_t preambleLen, 248 | uint16_t symbTimeout, bool fixLen, 249 | uint8_t payloadLen, 250 | bool crcOn, bool FreqHopOn, uint8_t HopPeriod, 251 | bool iqInverted, bool rxContinuous ); 252 | 253 | /*! 254 | * \brief Sets the transmission parameters 255 | * 256 | * \remark When using LoRa modem only bandwidths 125, 250 and 500 kHz are supported 257 | * 258 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 259 | * \param [IN] power Sets the output power [dBm] 260 | * \param [IN] fdev Sets the frequency deviation (FSK only) 261 | * FSK : [Hz] 262 | * LoRa: 0 263 | * \param [IN] bandwidth Sets the bandwidth (LoRa only) 264 | * FSK : 0 265 | * LoRa: [0: 125 kHz, 1: 250 kHz, 266 | * 2: 500 kHz, 3: Reserved] 267 | * \param [IN] datarate Sets the Datarate 268 | * FSK : 600..300000 bits/s 269 | * LoRa: [6: 64, 7: 128, 8: 256, 9: 512, 270 | * 10: 1024, 11: 2048, 12: 4096 chips] 271 | * \param [IN] coderate Sets the coding rate (LoRa only) 272 | * FSK : N/A ( set to 0 ) 273 | * LoRa: [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8] 274 | * \param [IN] preambleLen Sets the preamble length 275 | * FSK : Number of bytes 276 | * LoRa: Length in symbols (the hardware adds 4 more symbols) 277 | * \param [IN] fixLen Fixed length packets [0: variable, 1: fixed] 278 | * \param [IN] crcOn Enables disables the CRC [0: OFF, 1: ON] 279 | * \param [IN] FreqHopOn Enables disables the intra-packet frequency hopping 280 | * FSK : N/A ( set to 0 ) 281 | * LoRa: [0: OFF, 1: ON] 282 | * \param [IN] HopPeriod Number of symbols between each hop 283 | * FSK : N/A ( set to 0 ) 284 | * LoRa: Number of symbols 285 | * \param [IN] iqInverted Inverts IQ signals (LoRa only) 286 | * FSK : N/A ( set to 0 ) 287 | * LoRa: [0: not inverted, 1: inverted] 288 | * \param [IN] timeout Transmission timeout [ms] 289 | */ 290 | void SX1276SetTxConfig( RadioModems_t modem, int8_t power, uint32_t fdev, 291 | uint32_t bandwidth, uint32_t datarate, 292 | uint8_t coderate, uint16_t preambleLen, 293 | bool fixLen, bool crcOn, bool FreqHopOn, 294 | uint8_t HopPeriod, bool iqInverted, uint32_t timeout ); 295 | 296 | /*! 297 | * \brief Computes the packet time on air in ms for the given payload 298 | * 299 | * \Remark Can only be called once SetRxConfig or SetTxConfig have been called 300 | * 301 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 302 | * \param [IN] pktLen Packet payload length 303 | * 304 | * \retval airTime Computed airTime (ms) for the given packet payload length 305 | */ 306 | uint32_t SX1276GetTimeOnAir( RadioModems_t modem, uint8_t pktLen ); 307 | 308 | /*! 309 | * \brief Sends the buffer of size. Prepares the packet to be sent and sets 310 | * the radio in transmission 311 | * 312 | * \param [IN]: buffer Buffer pointer 313 | * \param [IN]: size Buffer size 314 | */ 315 | void SX1276Send( uint8_t *buffer, uint8_t size ); 316 | 317 | /*! 318 | * \brief Sets the radio in sleep mode 319 | */ 320 | void SX1276SetSleep( void ); 321 | 322 | /*! 323 | * \brief Sets the radio in standby mode 324 | */ 325 | void SX1276SetStby( void ); 326 | 327 | /*! 328 | * \brief Sets the radio in reception mode for the given time 329 | * \param [IN] timeout Reception timeout [ms] [0: continuous, others timeout] 330 | */ 331 | void SX1276SetRx( uint32_t timeout ); 332 | 333 | /*! 334 | * \brief Start a Channel Activity Detection 335 | */ 336 | void SX1276StartCad( void ); 337 | 338 | /*! 339 | * \brief Sets the radio in continuous wave transmission mode 340 | * 341 | * \param [IN]: freq Channel RF frequency 342 | * \param [IN]: power Sets the output power [dBm] 343 | * \param [IN]: time Transmission mode timeout [s] 344 | */ 345 | void SX1276SetTxContinuousWave( uint32_t freq, int8_t power, uint16_t time ); 346 | 347 | /*! 348 | * \brief Reads the current RSSI value 349 | * 350 | * \retval rssiValue Current RSSI value in [dBm] 351 | */ 352 | int16_t SX1276ReadRssi( RadioModems_t modem ); 353 | 354 | /*! 355 | * \brief Writes the radio register at the specified address 356 | * 357 | * \param [IN]: addr Register address 358 | * \param [IN]: data New register value 359 | */ 360 | void SX1276Write( uint8_t addr, uint8_t data ); 361 | 362 | /*! 363 | * \brief Reads the radio register at the specified address 364 | * 365 | * \param [IN]: addr Register address 366 | * \retval data Register value 367 | */ 368 | uint8_t SX1276Read( uint8_t addr ); 369 | 370 | /*! 371 | * \brief Writes multiple radio registers starting at address 372 | * 373 | * \param [IN] addr First Radio register address 374 | * \param [IN] buffer Buffer containing the new register's values 375 | * \param [IN] size Number of registers to be written 376 | */ 377 | void SX1276WriteBuffer( uint8_t addr, uint8_t *buffer, uint8_t size ); 378 | 379 | /*! 380 | * \brief Reads multiple radio registers starting at address 381 | * 382 | * \param [IN] addr First Radio register address 383 | * \param [OUT] buffer Buffer where to copy the registers data 384 | * \param [IN] size Number of registers to be read 385 | */ 386 | void SX1276ReadBuffer( uint8_t addr, uint8_t *buffer, uint8_t size ); 387 | 388 | /*! 389 | * \brief Sets the maximum payload length. 390 | * 391 | * \param [IN] modem Radio modem to be used [0: FSK, 1: LoRa] 392 | * \param [IN] max Maximum payload length in bytes 393 | */ 394 | void SX1276SetMaxPayloadLength( RadioModems_t modem, uint8_t max ); 395 | 396 | /*! 397 | * \brief Sets the network to public or private. Updates the sync byte. 398 | * 399 | * \remark Applies to LoRa modem only 400 | * 401 | * \param [IN] enable if true, it enables a public network 402 | */ 403 | void SX1276SetPublicNetwork( bool enable ); 404 | 405 | #endif // __SX1276_H__ 406 | -------------------------------------------------------------------------------- /radio/sx1276/sx1276Regs-LoRa.h: -------------------------------------------------------------------------------- 1 | /* 2 | / _____) _ | | 3 | ( (____ _____ ____ _| |_ _____ ____| |__ 4 | \____ \| ___ | (_ _) ___ |/ ___) _ \ 5 | _____) ) ____| | | || |_| ____( (___| | | | 6 | (______/|_____)_|_|_| \__)_____)\____)_| |_| 7 | (C)2013 Semtech 8 | 9 | Description: SX1276 LoRa modem registers and bits definitions 10 | 11 | License: Revised BSD License, see LICENSE.TXT file include in the project 12 | 13 | Maintainer: Miguel Luis and Gregory Cristian 14 | */ 15 | #ifndef __SX1276_REGS_LORA_H__ 16 | #define __SX1276_REGS_LORA_H__ 17 | 18 | /*! 19 | * ============================================================================ 20 | * SX1276 Internal registers Address 21 | * ============================================================================ 22 | */ 23 | #define REG_LR_FIFO 0x00 24 | // Common settings 25 | #define REG_LR_OPMODE 0x01 26 | #define REG_LR_FRFMSB 0x06 27 | #define REG_LR_FRFMID 0x07 28 | #define REG_LR_FRFLSB 0x08 29 | // Tx settings 30 | #define REG_LR_PACONFIG 0x09 31 | #define REG_LR_PARAMP 0x0A 32 | #define REG_LR_OCP 0x0B 33 | // Rx settings 34 | #define REG_LR_LNA 0x0C 35 | // LoRa registers 36 | #define REG_LR_FIFOADDRPTR 0x0D 37 | #define REG_LR_FIFOTXBASEADDR 0x0E 38 | #define REG_LR_FIFORXBASEADDR 0x0F 39 | #define REG_LR_FIFORXCURRENTADDR 0x10 40 | #define REG_LR_IRQFLAGSMASK 0x11 41 | #define REG_LR_IRQFLAGS 0x12 42 | #define REG_LR_RXNBBYTES 0x13 43 | #define REG_LR_RXHEADERCNTVALUEMSB 0x14 44 | #define REG_LR_RXHEADERCNTVALUELSB 0x15 45 | #define REG_LR_RXPACKETCNTVALUEMSB 0x16 46 | #define REG_LR_RXPACKETCNTVALUELSB 0x17 47 | #define REG_LR_MODEMSTAT 0x18 48 | #define REG_LR_PKTSNRVALUE 0x19 49 | #define REG_LR_PKTRSSIVALUE 0x1A 50 | #define REG_LR_RSSIVALUE 0x1B 51 | #define REG_LR_HOPCHANNEL 0x1C 52 | #define REG_LR_MODEMCONFIG1 0x1D 53 | #define REG_LR_MODEMCONFIG2 0x1E 54 | #define REG_LR_SYMBTIMEOUTLSB 0x1F 55 | #define REG_LR_PREAMBLEMSB 0x20 56 | #define REG_LR_PREAMBLELSB 0x21 57 | #define REG_LR_PAYLOADLENGTH 0x22 58 | #define REG_LR_PAYLOADMAXLENGTH 0x23 59 | #define REG_LR_HOPPERIOD 0x24 60 | #define REG_LR_FIFORXBYTEADDR 0x25 61 | #define REG_LR_MODEMCONFIG3 0x26 62 | #define REG_LR_FEIMSB 0x28 63 | #define REG_LR_FEIMID 0x29 64 | #define REG_LR_FEILSB 0x2A 65 | #define REG_LR_RSSIWIDEBAND 0x2C 66 | #define REG_LR_TEST2F 0x2F 67 | #define REG_LR_TEST30 0x30 68 | #define REG_LR_DETECTOPTIMIZE 0x31 69 | #define REG_LR_INVERTIQ 0x33 70 | #define REG_LR_TEST36 0x36 71 | #define REG_LR_DETECTIONTHRESHOLD 0x37 72 | #define REG_LR_SYNCWORD 0x39 73 | #define REG_LR_TEST3A 0x3A 74 | #define REG_LR_INVERTIQ2 0x3B 75 | 76 | // end of documented register in datasheet 77 | // I/O settings 78 | #define REG_LR_DIOMAPPING1 0x40 79 | #define REG_LR_DIOMAPPING2 0x41 80 | // Version 81 | #define REG_LR_VERSION 0x42 82 | // Additional settings 83 | #define REG_LR_PLLHOP 0x44 84 | #define REG_LR_TCXO 0x4B 85 | #define REG_LR_PADAC 0x4D 86 | #define REG_LR_FORMERTEMP 0x5B 87 | #define REG_LR_BITRATEFRAC 0x5D 88 | #define REG_LR_AGCREF 0x61 89 | #define REG_LR_AGCTHRESH1 0x62 90 | #define REG_LR_AGCTHRESH2 0x63 91 | #define REG_LR_AGCTHRESH3 0x64 92 | #define REG_LR_PLL 0x70 93 | 94 | /*! 95 | * ============================================================================ 96 | * SX1276 LoRa bits control definition 97 | * ============================================================================ 98 | */ 99 | 100 | /*! 101 | * RegFifo 102 | */ 103 | 104 | /*! 105 | * RegOpMode 106 | */ 107 | #define RFLR_OPMODE_LONGRANGEMODE_MASK 0x7F 108 | #define RFLR_OPMODE_LONGRANGEMODE_OFF 0x00 // Default 109 | #define RFLR_OPMODE_LONGRANGEMODE_ON 0x80 110 | 111 | #define RFLR_OPMODE_ACCESSSHAREDREG_MASK 0xBF 112 | #define RFLR_OPMODE_ACCESSSHAREDREG_ENABLE 0x40 113 | #define RFLR_OPMODE_ACCESSSHAREDREG_DISABLE 0x00 // Default 114 | 115 | #define RFLR_OPMODE_FREQMODE_ACCESS_MASK 0xF7 116 | #define RFLR_OPMODE_FREQMODE_ACCESS_LF 0x08 // Default 117 | #define RFLR_OPMODE_FREQMODE_ACCESS_HF 0x00 118 | 119 | #define RFLR_OPMODE_MASK 0xF8 120 | #define RFLR_OPMODE_SLEEP 0x00 121 | #define RFLR_OPMODE_STANDBY 0x01 // Default 122 | #define RFLR_OPMODE_SYNTHESIZER_TX 0x02 123 | #define RFLR_OPMODE_TRANSMITTER 0x03 124 | #define RFLR_OPMODE_SYNTHESIZER_RX 0x04 125 | #define RFLR_OPMODE_RECEIVER 0x05 126 | // LoRa specific modes 127 | #define RFLR_OPMODE_RECEIVER_SINGLE 0x06 128 | #define RFLR_OPMODE_CAD 0x07 129 | 130 | /*! 131 | * RegFrf (MHz) 132 | */ 133 | #define RFLR_FRFMSB_434_MHZ 0x6C // Default 134 | #define RFLR_FRFMID_434_MHZ 0x80 // Default 135 | #define RFLR_FRFLSB_434_MHZ 0x00 // Default 136 | 137 | /*! 138 | * RegPaConfig 139 | */ 140 | #define RFLR_PACONFIG_PASELECT_MASK 0x7F 141 | #define RFLR_PACONFIG_PASELECT_PABOOST 0x80 142 | #define RFLR_PACONFIG_PASELECT_RFO 0x00 // Default 143 | 144 | #define RFLR_PACONFIG_MAX_POWER_MASK 0x8F 145 | 146 | #define RFLR_PACONFIG_OUTPUTPOWER_MASK 0xF0 147 | 148 | /*! 149 | * RegPaRamp 150 | */ 151 | #define RFLR_PARAMP_TXBANDFORCE_MASK 0xEF 152 | #define RFLR_PARAMP_TXBANDFORCE_BAND_SEL 0x10 153 | #define RFLR_PARAMP_TXBANDFORCE_AUTO 0x00 // Default 154 | 155 | #define RFLR_PARAMP_MASK 0xF0 156 | #define RFLR_PARAMP_3400_US 0x00 157 | #define RFLR_PARAMP_2000_US 0x01 158 | #define RFLR_PARAMP_1000_US 0x02 159 | #define RFLR_PARAMP_0500_US 0x03 160 | #define RFLR_PARAMP_0250_US 0x04 161 | #define RFLR_PARAMP_0125_US 0x05 162 | #define RFLR_PARAMP_0100_US 0x06 163 | #define RFLR_PARAMP_0062_US 0x07 164 | #define RFLR_PARAMP_0050_US 0x08 165 | #define RFLR_PARAMP_0040_US 0x09 // Default 166 | #define RFLR_PARAMP_0031_US 0x0A 167 | #define RFLR_PARAMP_0025_US 0x0B 168 | #define RFLR_PARAMP_0020_US 0x0C 169 | #define RFLR_PARAMP_0015_US 0x0D 170 | #define RFLR_PARAMP_0012_US 0x0E 171 | #define RFLR_PARAMP_0010_US 0x0F 172 | 173 | /*! 174 | * RegOcp 175 | */ 176 | #define RFLR_OCP_MASK 0xDF 177 | #define RFLR_OCP_ON 0x20 // Default 178 | #define RFLR_OCP_OFF 0x00 179 | 180 | #define RFLR_OCP_TRIM_MASK 0xE0 181 | #define RFLR_OCP_TRIM_045_MA 0x00 182 | #define RFLR_OCP_TRIM_050_MA 0x01 183 | #define RFLR_OCP_TRIM_055_MA 0x02 184 | #define RFLR_OCP_TRIM_060_MA 0x03 185 | #define RFLR_OCP_TRIM_065_MA 0x04 186 | #define RFLR_OCP_TRIM_070_MA 0x05 187 | #define RFLR_OCP_TRIM_075_MA 0x06 188 | #define RFLR_OCP_TRIM_080_MA 0x07 189 | #define RFLR_OCP_TRIM_085_MA 0x08 190 | #define RFLR_OCP_TRIM_090_MA 0x09 191 | #define RFLR_OCP_TRIM_095_MA 0x0A 192 | #define RFLR_OCP_TRIM_100_MA 0x0B // Default 193 | #define RFLR_OCP_TRIM_105_MA 0x0C 194 | #define RFLR_OCP_TRIM_110_MA 0x0D 195 | #define RFLR_OCP_TRIM_115_MA 0x0E 196 | #define RFLR_OCP_TRIM_120_MA 0x0F 197 | #define RFLR_OCP_TRIM_130_MA 0x10 198 | #define RFLR_OCP_TRIM_140_MA 0x11 199 | #define RFLR_OCP_TRIM_150_MA 0x12 200 | #define RFLR_OCP_TRIM_160_MA 0x13 201 | #define RFLR_OCP_TRIM_170_MA 0x14 202 | #define RFLR_OCP_TRIM_180_MA 0x15 203 | #define RFLR_OCP_TRIM_190_MA 0x16 204 | #define RFLR_OCP_TRIM_200_MA 0x17 205 | #define RFLR_OCP_TRIM_210_MA 0x18 206 | #define RFLR_OCP_TRIM_220_MA 0x19 207 | #define RFLR_OCP_TRIM_230_MA 0x1A 208 | #define RFLR_OCP_TRIM_240_MA 0x1B 209 | 210 | /*! 211 | * RegLna 212 | */ 213 | #define RFLR_LNA_GAIN_MASK 0x1F 214 | #define RFLR_LNA_GAIN_G1 0x20 // Default 215 | #define RFLR_LNA_GAIN_G2 0x40 216 | #define RFLR_LNA_GAIN_G3 0x60 217 | #define RFLR_LNA_GAIN_G4 0x80 218 | #define RFLR_LNA_GAIN_G5 0xA0 219 | #define RFLR_LNA_GAIN_G6 0xC0 220 | 221 | #define RFLR_LNA_BOOST_LF_MASK 0xE7 222 | #define RFLR_LNA_BOOST_LF_DEFAULT 0x00 // Default 223 | 224 | #define RFLR_LNA_BOOST_HF_MASK 0xFC 225 | #define RFLR_LNA_BOOST_HF_OFF 0x00 // Default 226 | #define RFLR_LNA_BOOST_HF_ON 0x03 227 | 228 | /*! 229 | * RegFifoAddrPtr 230 | */ 231 | #define RFLR_FIFOADDRPTR 0x00 // Default 232 | 233 | /*! 234 | * RegFifoTxBaseAddr 235 | */ 236 | #define RFLR_FIFOTXBASEADDR 0x80 // Default 237 | 238 | /*! 239 | * RegFifoTxBaseAddr 240 | */ 241 | #define RFLR_FIFORXBASEADDR 0x00 // Default 242 | 243 | /*! 244 | * RegFifoRxCurrentAddr (Read Only) 245 | */ 246 | 247 | /*! 248 | * RegIrqFlagsMask 249 | */ 250 | #define RFLR_IRQFLAGS_RXTIMEOUT_MASK 0x80 251 | #define RFLR_IRQFLAGS_RXDONE_MASK 0x40 252 | #define RFLR_IRQFLAGS_PAYLOADCRCERROR_MASK 0x20 253 | #define RFLR_IRQFLAGS_VALIDHEADER_MASK 0x10 254 | #define RFLR_IRQFLAGS_TXDONE_MASK 0x08 255 | #define RFLR_IRQFLAGS_CADDONE_MASK 0x04 256 | #define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL_MASK 0x02 257 | #define RFLR_IRQFLAGS_CADDETECTED_MASK 0x01 258 | 259 | /*! 260 | * RegIrqFlags 261 | */ 262 | #define RFLR_IRQFLAGS_RXTIMEOUT 0x80 263 | #define RFLR_IRQFLAGS_RXDONE 0x40 264 | #define RFLR_IRQFLAGS_PAYLOADCRCERROR 0x20 265 | #define RFLR_IRQFLAGS_VALIDHEADER 0x10 266 | #define RFLR_IRQFLAGS_TXDONE 0x08 267 | #define RFLR_IRQFLAGS_CADDONE 0x04 268 | #define RFLR_IRQFLAGS_FHSSCHANGEDCHANNEL 0x02 269 | #define RFLR_IRQFLAGS_CADDETECTED 0x01 270 | 271 | /*! 272 | * RegFifoRxNbBytes (Read Only) 273 | */ 274 | 275 | /*! 276 | * RegRxHeaderCntValueMsb (Read Only) 277 | */ 278 | 279 | /*! 280 | * RegRxHeaderCntValueLsb (Read Only) 281 | */ 282 | 283 | /*! 284 | * RegRxPacketCntValueMsb (Read Only) 285 | */ 286 | 287 | /*! 288 | * RegRxPacketCntValueLsb (Read Only) 289 | */ 290 | 291 | /*! 292 | * RegModemStat (Read Only) 293 | */ 294 | #define RFLR_MODEMSTAT_RX_CR_MASK 0x1F 295 | #define RFLR_MODEMSTAT_MODEM_STATUS_MASK 0xE0 296 | 297 | /*! 298 | * RegPktSnrValue (Read Only) 299 | */ 300 | 301 | /*! 302 | * RegPktRssiValue (Read Only) 303 | */ 304 | 305 | /*! 306 | * RegRssiValue (Read Only) 307 | */ 308 | 309 | /*! 310 | * RegHopChannel (Read Only) 311 | */ 312 | #define RFLR_HOPCHANNEL_PLL_LOCK_TIMEOUT_MASK 0x7F 313 | #define RFLR_HOPCHANNEL_PLL_LOCK_FAIL 0x80 314 | #define RFLR_HOPCHANNEL_PLL_LOCK_SUCCEED 0x00 // Default 315 | 316 | #define RFLR_HOPCHANNEL_CRCONPAYLOAD_MASK 0xBF 317 | #define RFLR_HOPCHANNEL_CRCONPAYLOAD_ON 0x40 318 | #define RFLR_HOPCHANNEL_CRCONPAYLOAD_OFF 0x00 // Default 319 | 320 | #define RFLR_HOPCHANNEL_CHANNEL_MASK 0x3F 321 | 322 | /*! 323 | * RegModemConfig1 324 | */ 325 | #define RFLR_MODEMCONFIG1_BW_MASK 0x0F 326 | #define RFLR_MODEMCONFIG1_BW_7_81_KHZ 0x00 327 | #define RFLR_MODEMCONFIG1_BW_10_41_KHZ 0x10 328 | #define RFLR_MODEMCONFIG1_BW_15_62_KHZ 0x20 329 | #define RFLR_MODEMCONFIG1_BW_20_83_KHZ 0x30 330 | #define RFLR_MODEMCONFIG1_BW_31_25_KHZ 0x40 331 | #define RFLR_MODEMCONFIG1_BW_41_66_KHZ 0x50 332 | #define RFLR_MODEMCONFIG1_BW_62_50_KHZ 0x60 333 | #define RFLR_MODEMCONFIG1_BW_125_KHZ 0x70 // Default 334 | #define RFLR_MODEMCONFIG1_BW_250_KHZ 0x80 335 | #define RFLR_MODEMCONFIG1_BW_500_KHZ 0x90 336 | 337 | #define RFLR_MODEMCONFIG1_CODINGRATE_MASK 0xF1 338 | #define RFLR_MODEMCONFIG1_CODINGRATE_4_5 0x02 339 | #define RFLR_MODEMCONFIG1_CODINGRATE_4_6 0x04 // Default 340 | #define RFLR_MODEMCONFIG1_CODINGRATE_4_7 0x06 341 | #define RFLR_MODEMCONFIG1_CODINGRATE_4_8 0x08 342 | 343 | #define RFLR_MODEMCONFIG1_IMPLICITHEADER_MASK 0xFE 344 | #define RFLR_MODEMCONFIG1_IMPLICITHEADER_ON 0x01 345 | #define RFLR_MODEMCONFIG1_IMPLICITHEADER_OFF 0x00 // Default 346 | 347 | /*! 348 | * RegModemConfig2 349 | */ 350 | #define RFLR_MODEMCONFIG2_SF_MASK 0x0F 351 | #define RFLR_MODEMCONFIG2_SF_6 0x60 352 | #define RFLR_MODEMCONFIG2_SF_7 0x70 // Default 353 | #define RFLR_MODEMCONFIG2_SF_8 0x80 354 | #define RFLR_MODEMCONFIG2_SF_9 0x90 355 | #define RFLR_MODEMCONFIG2_SF_10 0xA0 356 | #define RFLR_MODEMCONFIG2_SF_11 0xB0 357 | #define RFLR_MODEMCONFIG2_SF_12 0xC0 358 | 359 | #define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_MASK 0xF7 360 | #define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_ON 0x08 361 | #define RFLR_MODEMCONFIG2_TXCONTINUOUSMODE_OFF 0x00 362 | 363 | #define RFLR_MODEMCONFIG2_RXPAYLOADCRC_MASK 0xFB 364 | #define RFLR_MODEMCONFIG2_RXPAYLOADCRC_ON 0x04 365 | #define RFLR_MODEMCONFIG2_RXPAYLOADCRC_OFF 0x00 // Default 366 | 367 | #define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB_MASK 0xFC 368 | #define RFLR_MODEMCONFIG2_SYMBTIMEOUTMSB 0x00 // Default 369 | 370 | /*! 371 | * RegSymbTimeoutLsb 372 | */ 373 | #define RFLR_SYMBTIMEOUTLSB_SYMBTIMEOUT 0x64 // Default 374 | 375 | /*! 376 | * RegPreambleLengthMsb 377 | */ 378 | #define RFLR_PREAMBLELENGTHMSB 0x00 // Default 379 | 380 | /*! 381 | * RegPreambleLengthLsb 382 | */ 383 | #define RFLR_PREAMBLELENGTHLSB 0x08 // Default 384 | 385 | /*! 386 | * RegPayloadLength 387 | */ 388 | #define RFLR_PAYLOADLENGTH 0x0E // Default 389 | 390 | /*! 391 | * RegPayloadMaxLength 392 | */ 393 | #define RFLR_PAYLOADMAXLENGTH 0xFF // Default 394 | 395 | /*! 396 | * RegHopPeriod 397 | */ 398 | #define RFLR_HOPPERIOD_FREQFOPPINGPERIOD 0x00 // Default 399 | 400 | /*! 401 | * RegFifoRxByteAddr (Read Only) 402 | */ 403 | 404 | /*! 405 | * RegModemConfig3 406 | */ 407 | #define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_MASK 0xF7 408 | #define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_ON 0x08 409 | #define RFLR_MODEMCONFIG3_LOWDATARATEOPTIMIZE_OFF 0x00 // Default 410 | 411 | #define RFLR_MODEMCONFIG3_AGCAUTO_MASK 0xFB 412 | #define RFLR_MODEMCONFIG3_AGCAUTO_ON 0x04 // Default 413 | #define RFLR_MODEMCONFIG3_AGCAUTO_OFF 0x00 414 | 415 | /*! 416 | * RegFeiMsb (Read Only) 417 | */ 418 | 419 | /*! 420 | * RegFeiMid (Read Only) 421 | */ 422 | 423 | /*! 424 | * RegFeiLsb (Read Only) 425 | */ 426 | 427 | /*! 428 | * RegRssiWideband (Read Only) 429 | */ 430 | 431 | /*! 432 | * RegDetectOptimize 433 | */ 434 | #define RFLR_DETECTIONOPTIMIZE_MASK 0xF8 435 | #define RFLR_DETECTIONOPTIMIZE_SF7_TO_SF12 0x03 // Default 436 | #define RFLR_DETECTIONOPTIMIZE_SF6 0x05 437 | 438 | /*! 439 | * RegInvertIQ 440 | */ 441 | #define RFLR_INVERTIQ_RX_MASK 0xBF 442 | #define RFLR_INVERTIQ_RX_OFF 0x00 443 | #define RFLR_INVERTIQ_RX_ON 0x40 444 | #define RFLR_INVERTIQ_TX_MASK 0xFE 445 | #define RFLR_INVERTIQ_TX_OFF 0x01 446 | #define RFLR_INVERTIQ_TX_ON 0x00 447 | 448 | /*! 449 | * RegDetectionThreshold 450 | */ 451 | #define RFLR_DETECTIONTHRESH_SF7_TO_SF12 0x0A // Default 452 | #define RFLR_DETECTIONTHRESH_SF6 0x0C 453 | 454 | /*! 455 | * RegInvertIQ2 456 | */ 457 | #define RFLR_INVERTIQ2_ON 0x19 458 | #define RFLR_INVERTIQ2_OFF 0x1D 459 | 460 | /*! 461 | * RegDioMapping1 462 | */ 463 | #define RFLR_DIOMAPPING1_DIO0_MASK 0x3F 464 | #define RFLR_DIOMAPPING1_DIO0_00 0x00 // Default 465 | #define RFLR_DIOMAPPING1_DIO0_01 0x40 466 | #define RFLR_DIOMAPPING1_DIO0_10 0x80 467 | #define RFLR_DIOMAPPING1_DIO0_11 0xC0 468 | 469 | #define RFLR_DIOMAPPING1_DIO1_MASK 0xCF 470 | #define RFLR_DIOMAPPING1_DIO1_00 0x00 // Default 471 | #define RFLR_DIOMAPPING1_DIO1_01 0x10 472 | #define RFLR_DIOMAPPING1_DIO1_10 0x20 473 | #define RFLR_DIOMAPPING1_DIO1_11 0x30 474 | 475 | #define RFLR_DIOMAPPING1_DIO2_MASK 0xF3 476 | #define RFLR_DIOMAPPING1_DIO2_00 0x00 // Default 477 | #define RFLR_DIOMAPPING1_DIO2_01 0x04 478 | #define RFLR_DIOMAPPING1_DIO2_10 0x08 479 | #define RFLR_DIOMAPPING1_DIO2_11 0x0C 480 | 481 | #define RFLR_DIOMAPPING1_DIO3_MASK 0xFC 482 | #define RFLR_DIOMAPPING1_DIO3_00 0x00 // Default 483 | #define RFLR_DIOMAPPING1_DIO3_01 0x01 484 | #define RFLR_DIOMAPPING1_DIO3_10 0x02 485 | #define RFLR_DIOMAPPING1_DIO3_11 0x03 486 | 487 | /*! 488 | * RegDioMapping2 489 | */ 490 | #define RFLR_DIOMAPPING2_DIO4_MASK 0x3F 491 | #define RFLR_DIOMAPPING2_DIO4_00 0x00 // Default 492 | #define RFLR_DIOMAPPING2_DIO4_01 0x40 493 | #define RFLR_DIOMAPPING2_DIO4_10 0x80 494 | #define RFLR_DIOMAPPING2_DIO4_11 0xC0 495 | 496 | #define RFLR_DIOMAPPING2_DIO5_MASK 0xCF 497 | #define RFLR_DIOMAPPING2_DIO5_00 0x00 // Default 498 | #define RFLR_DIOMAPPING2_DIO5_01 0x10 499 | #define RFLR_DIOMAPPING2_DIO5_10 0x20 500 | #define RFLR_DIOMAPPING2_DIO5_11 0x30 501 | 502 | #define RFLR_DIOMAPPING2_MAP_MASK 0xFE 503 | #define RFLR_DIOMAPPING2_MAP_PREAMBLEDETECT 0x01 504 | #define RFLR_DIOMAPPING2_MAP_RSSI 0x00 // Default 505 | 506 | /*! 507 | * RegVersion (Read Only) 508 | */ 509 | 510 | /*! 511 | * RegPllHop 512 | */ 513 | #define RFLR_PLLHOP_FASTHOP_MASK 0x7F 514 | #define RFLR_PLLHOP_FASTHOP_ON 0x80 515 | #define RFLR_PLLHOP_FASTHOP_OFF 0x00 // Default 516 | 517 | /*! 518 | * RegTcxo 519 | */ 520 | #define RFLR_TCXO_TCXOINPUT_MASK 0xEF 521 | #define RFLR_TCXO_TCXOINPUT_ON 0x10 522 | #define RFLR_TCXO_TCXOINPUT_OFF 0x00 // Default 523 | 524 | /*! 525 | * RegPaDac 526 | */ 527 | #define RFLR_PADAC_20DBM_MASK 0xF8 528 | #define RFLR_PADAC_20DBM_ON 0x07 529 | #define RFLR_PADAC_20DBM_OFF 0x04 // Default 530 | 531 | /*! 532 | * RegFormerTemp 533 | */ 534 | 535 | /*! 536 | * RegBitrateFrac 537 | */ 538 | #define RF_BITRATEFRAC_MASK 0xF0 539 | 540 | /*! 541 | * RegAgcRef 542 | */ 543 | 544 | /*! 545 | * RegAgcThresh1 546 | */ 547 | 548 | /*! 549 | * RegAgcThresh2 550 | */ 551 | 552 | /*! 553 | * RegAgcThresh3 554 | */ 555 | 556 | /*! 557 | * RegPll 558 | */ 559 | #define RF_PLL_BANDWIDTH_MASK 0x3F 560 | #define RF_PLL_BANDWIDTH_75 0x00 561 | #define RF_PLL_BANDWIDTH_150 0x40 562 | #define RF_PLL_BANDWIDTH_225 0x80 563 | #define RF_PLL_BANDWIDTH_300 0xC0 // Default 564 | 565 | #endif // __SX1276_REGS_LORA_H__ 566 | --------------------------------------------------------------------------------