├── .gitignore ├── Makefile ├── README.md ├── STM32F103C_MINI ├── board.c ├── board.h └── board.mk ├── STM32F103x8.ld ├── aes ├── aes.mk ├── inc │ ├── aes.h │ ├── aes_user_options.h │ └── util.h └── src │ ├── aes_add_round_key.c │ ├── aes_decrypt_cbc.c │ ├── aes_decrypt_cfb.c │ ├── aes_decrypt_ecb.c │ ├── aes_decrypt_ofb.c │ ├── aes_encrypt_cbc.c │ ├── aes_encrypt_cfb.c │ ├── aes_encrypt_ecb.c │ ├── aes_encrypt_ofb.c │ ├── aes_get_rcon.c │ ├── aes_get_sbox.c │ ├── aes_get_sbox_inv.c │ ├── aes_included_galois_multiplication.c │ ├── aes_initialize.c │ ├── aes_key_expansion.c │ ├── aes_mix_columns.c │ ├── aes_mix_columns_inv.c │ ├── aes_rot_word.c │ ├── aes_shift_rows.c │ ├── aes_shift_rows_inv.c │ ├── aes_src.h │ ├── aes_sub_bytes.c │ ├── aes_sub_bytes_inv.c │ └── aes_sub_word.c ├── aes_secret.sample.h ├── am2302.c ├── am2302.h ├── bh1750.c ├── bh1750.h ├── build ├── rsensor.bin └── rsensor.elf ├── chconf.h ├── devices.txt ├── ds1820b.c ├── ds1820b.h ├── halconf.h ├── main.c ├── main.h ├── mcuconf.h ├── nrf24l01.c ├── nrf24l01.h ├── nrf_spi.c ├── nrf_spi.h ├── oneWire.c ├── oneWire.h ├── owtemp.c ├── owtemp.h ├── sensors.c ├── sensors.h ├── stm32f103c_mini.txt └── util ├── floatp10.c ├── itoa.c ├── printfs.c ├── printfs.h └── utoa.c /.gitignore: -------------------------------------------------------------------------------- 1 | .dep 2 | .settings 3 | .cproject 4 | .project 5 | build/lst 6 | build/obj 7 | build/rsensor.hex 8 | build/rsensor.dmp 9 | build/rsensor.map 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | # Build global options 3 | # NOTE: Can be overridden externally. 4 | # 5 | 6 | # Compiler options here. 7 | ifeq ($(USE_OPT),) 8 | USE_OPT = -O2 -std=gnu99 -ggdb -fomit-frame-pointer -falign-functions=16 9 | endif 10 | 11 | # C specific options here (added to USE_OPT). 12 | ifeq ($(USE_COPT),) 13 | USE_COPT = 14 | endif 15 | 16 | # C++ specific options here (added to USE_OPT). 17 | ifeq ($(USE_CPPOPT),) 18 | USE_CPPOPT = -fno-rtti 19 | endif 20 | 21 | # Enable this if you want the linker to remove unused code and data 22 | ifeq ($(USE_LINK_GC),) 23 | USE_LINK_GC = yes 24 | endif 25 | 26 | # If enabled, this option allows to compile the application in THUMB mode. 27 | ifeq ($(USE_THUMB),) 28 | USE_THUMB = yes 29 | endif 30 | 31 | # Enable this if you want to see the full log while compiling. 32 | ifeq ($(USE_VERBOSE_COMPILE),) 33 | USE_VERBOSE_COMPILE = yes 34 | endif 35 | 36 | # 37 | # Build global options 38 | ############################################################################## 39 | 40 | ############################################################################## 41 | # Architecture or project specific options 42 | # 43 | 44 | # Enable this if you really want to use the STM FWLib. 45 | ifeq ($(USE_FWLIB),) 46 | USE_FWLIB = no 47 | endif 48 | 49 | # 50 | # Architecture or project specific options 51 | ############################################################################## 52 | 53 | ############################################################################## 54 | # Project, sources and paths 55 | # 56 | 57 | # Define project name here 58 | PROJECT = rsensor 59 | 60 | # Imported source files and paths 61 | CHIBIOS = ../chibios/ChibiOS_2.6.5 62 | include STM32F103C_MINI/board.mk 63 | include $(CHIBIOS)/os/hal/platforms/STM32F1xx/platform.mk 64 | include $(CHIBIOS)/os/hal/hal.mk 65 | include $(CHIBIOS)/os/ports/GCC/ARMCMx/STM32F1xx/port.mk 66 | include $(CHIBIOS)/os/kernel/kernel.mk 67 | include aes/aes.mk 68 | 69 | # Define linker script file here 70 | LDSCRIPT= STM32F103x8.ld 71 | 72 | # C sources that can be compiled in ARM or THUMB mode depending on the global 73 | # setting. 74 | CSRC = $(PORTSRC) \ 75 | $(KERNSRC) \ 76 | $(HALSRC) \ 77 | $(PLATFORMSRC) \ 78 | $(BOARDSRC) \ 79 | $(CHIBIOS)/os/various/shell.c \ 80 | $(CHIBIOS)/os/various/syscalls.c \ 81 | $(CHIBIOS)/os/various/chrtclib.c \ 82 | $(CHIBIOS)/os/various/chprintf.c \ 83 | owtemp.c ds1820b.c oneWire.c \ 84 | $(AESSRC) \ 85 | am2302.c \ 86 | bh1750.c \ 87 | nrf24l01.c nrf_spi.c \ 88 | main.c 89 | 90 | # sensors.c \ 91 | 92 | # C++ sources that can be compiled in ARM or THUMB mode depending on the global 93 | # setting. 94 | CPPSRC = 95 | 96 | # C sources to be compiled in ARM mode regardless of the global setting. 97 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 98 | # option that results in lower performance and larger code size. 99 | ACSRC = 100 | 101 | # C++ sources to be compiled in ARM mode regardless of the global setting. 102 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 103 | # option that results in lower performance and larger code size. 104 | ACPPSRC = 105 | 106 | # C sources to be compiled in THUMB mode regardless of the global setting. 107 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 108 | # option that results in lower performance and larger code size. 109 | TCSRC = 110 | 111 | # C sources to be compiled in THUMB mode regardless of the global setting. 112 | # NOTE: Mixing ARM and THUMB mode enables the -mthumb-interwork compiler 113 | # option that results in lower performance and larger code size. 114 | TCPPSRC = 115 | 116 | # List ASM source files here 117 | ASMSRC = $(PORTASM) 118 | 119 | INCDIR = $(PORTINC) $(KERNINC) \ 120 | $(HALINC) $(PLATFORMINC) $(BOARDINC) \ 121 | $(CHIBIOS)/os/various $(AESINC) 122 | 123 | # 124 | # Project, sources and paths 125 | ############################################################################## 126 | 127 | ############################################################################## 128 | # Compiler settings 129 | # 130 | 131 | MCU = cortex-m3 132 | 133 | #TRGT = arm-elf- 134 | TRGT = arm-none-eabi- 135 | CC = $(TRGT)gcc 136 | CPPC = $(TRGT)g++ 137 | # Enable loading with g++ only if you need C++ runtime support. 138 | # NOTE: You can use C++ even without C++ support if you are careful. C++ 139 | # runtime support makes code size explode. 140 | LD = $(TRGT)gcc 141 | #LD = $(TRGT)g++ 142 | CP = $(TRGT)objcopy 143 | AS = $(TRGT)gcc -x assembler-with-cpp 144 | OD = $(TRGT)objdump 145 | HEX = $(CP) -O ihex 146 | BIN = $(CP) -O binary 147 | 148 | # ARM-specific options here 149 | AOPT = 150 | 151 | # THUMB-specific options here 152 | TOPT = -mthumb -DTHUMB 153 | 154 | # Define C warning options here 155 | CWARN = -Wall -Wextra -Wstrict-prototypes 156 | 157 | # Define C++ warning options here 158 | CPPWARN = -Wall -Wextra 159 | 160 | # 161 | # Compiler settings 162 | ############################################################################## 163 | 164 | ############################################################################## 165 | # Start of default section 166 | # 167 | 168 | # List all default C defines here, like -D_DEBUG=1 169 | #DDEFS = -DSTDOUT_SD=SD1 -DSTDIN_SD=SD1 170 | DDEFS = 171 | 172 | # List all default ASM defines here, like -D_DEBUG=1 173 | DADEFS = 174 | 175 | # List all default directories to look for include files here 176 | DINCDIR = 177 | 178 | # List the default directory to look for the libraries here 179 | DLIBDIR = 180 | 181 | # List all default libraries here 182 | DLIBS = 183 | 184 | # 185 | # End of default section 186 | ############################################################################## 187 | 188 | ############################################################################## 189 | # Start of user section 190 | # 191 | 192 | # List all user C define here, like -D_DEBUG=1 193 | UDEFS = 194 | 195 | # Define ASM defines here 196 | UADEFS = 197 | 198 | # List all user directories here 199 | UINCDIR = 200 | 201 | # List the user directory to look for the libraries here 202 | ULIBDIR = 203 | 204 | # List all user libraries here 205 | ULIBS = 206 | 207 | # 208 | # End of user defines 209 | ############################################################################## 210 | 211 | ifeq ($(USE_FWLIB),yes) 212 | include $(CHIBIOS)/ext/stm32lib/stm32lib.mk 213 | CSRC += $(STM32SRC) 214 | INCDIR += $(STM32INC) 215 | USE_OPT += -DUSE_STDPERIPH_DRIVER 216 | endif 217 | 218 | include $(CHIBIOS)/os/ports/GCC/ARMCMx/rules.mk 219 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndruPol/remote-sensor/59614bfc98fa650fa8272af7875d21d7f5ca32bf/README.md -------------------------------------------------------------------------------- /STM32F103C_MINI/board.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #include "ch.h" 18 | #include "hal.h" 19 | 20 | /** 21 | * @brief PAL setup. 22 | * @details Digital I/O ports static configuration as defined in @p board.h. 23 | * This variable is used by the HAL when initializing the PAL driver. 24 | */ 25 | #if HAL_USE_PAL || defined(__DOXYGEN__) 26 | const PALConfig pal_default_config = 27 | { 28 | {VAL_GPIOAODR, VAL_GPIOACRL, VAL_GPIOACRH}, 29 | {VAL_GPIOBODR, VAL_GPIOBCRL, VAL_GPIOBCRH}, 30 | {VAL_GPIOCODR, VAL_GPIOCCRL, VAL_GPIOCCRH}, 31 | }; 32 | #endif 33 | 34 | /* 35 | * Early initialization code. 36 | * This initialization must be performed just after stack setup and before 37 | * any other initialization. 38 | */ 39 | void __early_init(void) { 40 | 41 | stm32_clock_init(); 42 | } 43 | 44 | #if HAL_USE_MMC_SPI 45 | /* Board-related functions related to the MMC_SPI driver.*/ 46 | bool_t mmc_lld_is_card_inserted(MMCDriver *mmcp) { 47 | 48 | (void)mmcp; 49 | // return palReadPad(GPIOB, GPIOB_MMCCP); 50 | return TRUE; 51 | } 52 | 53 | bool_t mmc_lld_is_write_protected(MMCDriver *mmcp) { 54 | 55 | (void)mmcp; 56 | // return !palReadPad(GPIOC, GPIOC_MMCWP); 57 | return FALSE; 58 | } 59 | #endif 60 | 61 | /* 62 | * Board-specific initialization code. 63 | */ 64 | void boardInit(void) { 65 | } 66 | -------------------------------------------------------------------------------- /STM32F103C_MINI/board.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #ifndef _BOARD_H_ 18 | #define _BOARD_H_ 19 | 20 | /* 21 | * Setup for the STM32F103C-MINNI proto board. 22 | */ 23 | 24 | /* 25 | * Board identifier. 26 | */ 27 | #define BOARD_STM32F103C_MINNI 28 | #define BOARD_NAME "STM32F103C-MINNI" 29 | 30 | /* 31 | * Board frequencies. 32 | */ 33 | #define STM32_LSECLK 32768 34 | #define STM32_HSECLK 8000000 35 | 36 | /* 37 | * MCU type, supported types are defined in ./os/hal/platforms/hal_lld.h. 38 | */ 39 | #define STM32F10X_MD 40 | 41 | /* 42 | * IO pins assignments. 43 | */ 44 | #define GPIOA_PIN0 0 45 | #define GPIOA_PIN1 1 46 | #define GPIOA_PIN2 2 47 | #define GPIOA_PIN3 3 48 | #define GPIOA_PIN4 4 49 | #define GPIOA_PIN5 5 50 | #define GPIOA_PIN6 6 51 | #define GPIOA_PIN7 7 52 | #define GPIOA_PIN8 8 53 | #define GPIOA_USART1_TX 9 54 | #define GPIOA_USART1_RX 10 55 | #define GPIOA_USB_DM 11 56 | #define GPIOA_USB_DP 12 57 | #define GPIOA_JTMS 13 58 | #define GPIOA_JTCK 14 59 | #define GPIOA_JTDI 15 60 | 61 | 62 | #define GPIOB_PIN0 0 63 | #define GPIOB_PIN1 1 64 | #define GPIOB_BOOT1 2 65 | #define GPIOB_JTDO 3 66 | #define GPIOB_JNTRST 4 67 | #define GPIOB_PIN5 5 68 | #define GPIOB_PIN6 6 69 | #define GPIOB_PIN7 7 70 | #define GPIOB_PIN8 8 71 | #define GPIOB_PIN9 9 72 | #define GPIOB_PIN10 10 73 | #define GPIOB_PIN11 11 74 | #define GPIOB_PIN12 12 75 | #define GPIOB_PIN13 13 76 | #define GPIOB_PIN14 14 77 | #define GPIOB_PIN15 15 78 | 79 | /* 80 | * I/O ports initial setup, this configuration is established soon after reset 81 | * in the initialization code. 82 | * 83 | * The digits have the following meaning: 84 | * 0 - Analog input. 85 | * 1 - Push Pull output 10MHz. 86 | * 2 - Push Pull output 2MHz. 87 | * 3 - Push Pull output 50MHz. 88 | * 4 - Digital input. 89 | * 5 - Open Drain output 10MHz. 90 | * 6 - Open Drain output 2MHz. 91 | * 7 - Open Drain output 50MHz. 92 | * 8 - Digital input with PullUp or PullDown resistor depending on ODR. 93 | * 9 - Alternate Push Pull output 10MHz. 94 | * A - Alternate Push Pull output 2MHz. 95 | * B - Alternate Push Pull output 50MHz. 96 | * C - Reserved. 97 | * D - Alternate Open Drain output 10MHz. 98 | * E - Alternate Open Drain output 2MHz. 99 | * F - Alternate Open Drain output 50MHz. 100 | * Please refer to the STM32 Reference Manual for details. 101 | */ 102 | 103 | /* 104 | * Port A setup. 105 | * Everything input with pull-up except: 106 | * PA9 - Alternate output (USART1 TX). 107 | * PA10 - Normal input (USART1 RX). 108 | * PA11 - Normal input (USB DM). 109 | * PA12 - Normal input (USB DP). 110 | */ 111 | #define VAL_GPIOACRL 0x88888888 /* PA7...PA0 */ 112 | #define VAL_GPIOACRH 0x888444B8 /* PA15...PA8 */ 113 | #define VAL_GPIOAODR 0xFFFFFFFF 114 | 115 | /* 116 | * Port B setup. 117 | * Everything input with pull-up except: 118 | */ 119 | #define VAL_GPIOBCRL 0x88888888 /* PB7...PB0 */ 120 | #define VAL_GPIOBCRH 0x88888888 /* PB15...PB8 */ 121 | #define VAL_GPIOBODR 0xFFFFFFFF 122 | 123 | /* 124 | * Port C setup. 125 | * Everything input with pull-up except: 126 | */ 127 | #define VAL_GPIOCCRL 0x88888888 /* PC7...PC0 */ 128 | #define VAL_GPIOCCRH 0x88888888 /* PC15...PC8 */ 129 | #define VAL_GPIOCODR 0xFFFFFFFF 130 | 131 | /* 132 | * USB bus activation macro, required by the USB driver. 133 | */ 134 | //#define usb_lld_connect_bus(usbp) palClearPad(GPIOC, GPIOC_USB_DISC) 135 | #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_INPUT); 136 | 137 | /* 138 | * USB bus de-activation macro, required by the USB driver. 139 | */ 140 | #define usb_lld_disconnect_bus(usbp) { \ 141 | palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL); \ 142 | palClearPad(GPIOA, GPIOA_USB_DP); \ 143 | } 144 | 145 | #if !defined(_FROM_ASM_) 146 | #ifdef __cplusplus 147 | extern "C" { 148 | #endif 149 | void boardInit(void); 150 | #ifdef __cplusplus 151 | } 152 | #endif 153 | #endif /* _FROM_ASM_ */ 154 | 155 | #endif /* _BOARD_H_ */ 156 | -------------------------------------------------------------------------------- /STM32F103C_MINI/board.mk: -------------------------------------------------------------------------------- 1 | # List of all the board related files. 2 | BOARDSRC = STM32F103C_MINI/board.c 3 | 4 | # Required include directories 5 | BOARDINC = STM32F103C_MINI 6 | -------------------------------------------------------------------------------- /STM32F103x8.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 3 | 2011,2012,2013 Giovanni Di Sirio. 4 | 5 | This file is part of ChibiOS/RT. 6 | 7 | ChibiOS/RT is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | ChibiOS/RT is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | 20 | --- 21 | 22 | A special exception to the GPL can be applied should you wish to distribute 23 | a combined work that includes ChibiOS/RT, without being obliged to provide 24 | the source code for any proprietary components. See the file exception.txt 25 | for full details of how and when the exception can be applied. 26 | */ 27 | 28 | /* 29 | * ST32F103x8 memory setup. 30 | */ 31 | __main_stack_size__ = 0x0800; 32 | __process_stack_size__ = 0x0400; 33 | 34 | MEMORY 35 | { 36 | flash : org = 0x08000000, len = 64k 37 | ram : org = 0x20000000, len = 20k 38 | } 39 | 40 | __ram_start__ = ORIGIN(ram); 41 | __ram_size__ = LENGTH(ram); 42 | __ram_end__ = __ram_start__ + __ram_size__; 43 | 44 | ENTRY(ResetHandler) 45 | 46 | SECTIONS 47 | { 48 | . = 0; 49 | _text = .; 50 | 51 | startup : ALIGN(16) SUBALIGN(16) 52 | { 53 | KEEP(*(vectors)) 54 | } > flash 55 | 56 | constructors : ALIGN(4) SUBALIGN(4) 57 | { 58 | PROVIDE(__init_array_start = .); 59 | KEEP(*(SORT(.init_array.*))) 60 | KEEP(*(.init_array)) 61 | PROVIDE(__init_array_end = .); 62 | } > flash 63 | 64 | destructors : ALIGN(4) SUBALIGN(4) 65 | { 66 | PROVIDE(__fini_array_start = .); 67 | KEEP(*(.fini_array)) 68 | KEEP(*(SORT(.fini_array.*))) 69 | PROVIDE(__fini_array_end = .); 70 | } > flash 71 | 72 | .text : ALIGN(16) SUBALIGN(16) 73 | { 74 | *(.text.startup.*) 75 | *(.text) 76 | *(.text.*) 77 | *(.rodata) 78 | *(.rodata.*) 79 | *(.glue_7t) 80 | *(.glue_7) 81 | *(.gcc*) 82 | } > flash 83 | 84 | .ARM.extab : 85 | { 86 | *(.ARM.extab* .gnu.linkonce.armextab.*) 87 | } > flash 88 | 89 | .ARM.exidx : { 90 | PROVIDE(__exidx_start = .); 91 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 92 | PROVIDE(__exidx_end = .); 93 | } > flash 94 | 95 | .eh_frame_hdr : 96 | { 97 | *(.eh_frame_hdr) 98 | } > flash 99 | 100 | .eh_frame : ONLY_IF_RO 101 | { 102 | *(.eh_frame) 103 | } > flash 104 | 105 | .textalign : ONLY_IF_RO 106 | { 107 | . = ALIGN(8); 108 | } > flash 109 | 110 | _etext = .; 111 | _textdata = _etext; 112 | 113 | .stacks : 114 | { 115 | . = ALIGN(8); 116 | __main_stack_base__ = .; 117 | . += __main_stack_size__; 118 | . = ALIGN(8); 119 | __main_stack_end__ = .; 120 | __process_stack_base__ = .; 121 | __main_thread_stack_base__ = .; 122 | . += __process_stack_size__; 123 | . = ALIGN(8); 124 | __process_stack_end__ = .; 125 | __main_thread_stack_end__ = .; 126 | } > ram 127 | 128 | .data : 129 | { 130 | . = ALIGN(4); 131 | PROVIDE(_data = .); 132 | *(.data) 133 | . = ALIGN(4); 134 | *(.data.*) 135 | . = ALIGN(4); 136 | *(.ramtext) 137 | . = ALIGN(4); 138 | PROVIDE(_edata = .); 139 | } > ram AT > flash 140 | 141 | .bss : 142 | { 143 | . = ALIGN(4); 144 | PROVIDE(_bss_start = .); 145 | *(.bss) 146 | . = ALIGN(4); 147 | *(.bss.*) 148 | . = ALIGN(4); 149 | *(COMMON) 150 | . = ALIGN(4); 151 | PROVIDE(_bss_end = .); 152 | } > ram 153 | } 154 | 155 | PROVIDE(end = .); 156 | _end = .; 157 | 158 | __heap_base__ = _end; 159 | __heap_end__ = __ram_end__; 160 | -------------------------------------------------------------------------------- /aes/aes.mk: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | 4 | AESSRC = aes/src/aes_add_round_key.c \ 5 | aes/src/aes_get_rcon.c \ 6 | aes/src/aes_get_sbox.c \ 7 | aes/src/aes_get_sbox_inv.c \ 8 | aes/src/aes_included_galois_multiplication.c \ 9 | aes/src/aes_key_expansion.c \ 10 | aes/src/aes_mix_columns.c \ 11 | aes/src/aes_mix_columns_inv.c \ 12 | aes/src/aes_rot_word.c \ 13 | aes/src/aes_sub_word.c \ 14 | aes/src/aes_shift_rows.c \ 15 | aes/src/aes_shift_rows_inv.c \ 16 | aes/src/aes_sub_bytes.c \ 17 | aes/src/aes_sub_bytes_inv.c \ 18 | aes/src/aes_initialize.c \ 19 | aes/src/aes_decrypt_ecb.c \ 20 | aes/src/aes_encrypt_ecb.c 21 | 22 | AESINC = aes/inc 23 | -------------------------------------------------------------------------------- /aes/inc/aes.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes.h 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #ifndef AES_H_ 14 | #define AES_H_ 15 | 16 | #include "util.h" 17 | #include "aes_user_options.h" 18 | 19 | 20 | /////////////////////////////////////////////////////////////////////////////// 21 | // Nb is the number of columns in the state matrix, which is always 4 with AES 22 | /////////////////////////////////////////////////////////////////////////////// 23 | #define Nb 4 24 | 25 | /////////////////////////////////////////////////// 26 | // Nk is the number of the 32-bit words in the key 27 | /////////////////////////////////////////////////// 28 | #define Nk_128 4 29 | #define Nk_192 6 30 | #define Nk_256 8 31 | 32 | /////////////////////////////////////////////////////// 33 | // Nr is the number of rounds to execute the algorithm 34 | /////////////////////////////////////////////////////// 35 | #define Nr_128 10 36 | #define Nr_192 12 37 | #define Nr_256 14 38 | 39 | 40 | //////////////////////////////////////////////////////////// 41 | // Enumeration to tell aes_initialize() how long the key is 42 | //////////////////////////////////////////////////////////// 43 | typedef enum 44 | { 45 | AES_KEY_LENGTH_128_BITS, 46 | AES_KEY_LENGTH_192_BITS, 47 | AES_KEY_LENGTH_256_BITS 48 | } aes_key_length_t; 49 | 50 | //////////////////////////////////////////////////////////// 51 | // Structure for holding data for an AES algorithm instance 52 | //////////////////////////////////////////////////////////// 53 | typedef struct 54 | { 55 | //For w, use the worst case size (i.e., that for 256 bit keys) 56 | unsigned char state[4][Nb]; 57 | unsigned char w[4][Nb * (Nr_256 + 1)]; 58 | 59 | //Nb is left out since it is always 4, there's no need to waste a byte of memory for it 60 | unsigned char Nk; 61 | unsigned char Nr; 62 | 63 | //Variable to hold initialization vector or intermediate data in CBC, CFB, and OFB modes 64 | unsigned char iv_or_intermediate_data[16]; 65 | 66 | //Variable to hold a remaining bytes of key block data used for CFB and OFB modes 67 | unsigned int rem_key_bytes; 68 | } aes_data_t; 69 | 70 | 71 | /////////////////////// 72 | // Function prototypes 73 | /////////////////////// 74 | void aes_initialize(aes_data_t * aes_data_p, aes_key_length_t aes_key_length, const unsigned char * key, const unsigned char * iv) __REENTRANT; 75 | 76 | void aes_encrypt_ecb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block) __REENTRANT; 77 | void aes_decrypt_ecb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block) __REENTRANT; 78 | 79 | #if (AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES != 0) 80 | void aes_encrypt_cbc(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block) __REENTRANT; 81 | void aes_decrypt_cbc(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block) __REENTRANT; 82 | 83 | void aes_encrypt_cfb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block, unsigned int len) __REENTRANT; 84 | void aes_decrypt_cfb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block, unsigned int len) __REENTRANT; 85 | 86 | void aes_encrypt_ofb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block, unsigned int len) __REENTRANT; 87 | void aes_decrypt_ofb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block, unsigned int len) __REENTRANT; 88 | #endif 89 | 90 | #endif /* AES_H_ */ 91 | -------------------------------------------------------------------------------- /aes/inc/aes_user_options.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_user_options.h 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #ifndef AES_USER_OPTIONS_H_ 14 | #define AES_USER_OPTIONS_H_ 15 | 16 | ///////////////////////////////////////////////////////////// 17 | // User options (recompile library if these are changed) 18 | ///////////////////////////////////////////////////////////// 19 | #define AES_FORCE_TABLES_INTO_CODE_MEMORY_WITH_SDCC 0 //Force the sbox, sbox_inv, and rcon tables into code memory using the __code keyword (only for SDCC) 20 | #define AES_FORCE_FUNCTIONS_AS_REENTRANT_WITH_SDCC 0 //Force the aes_*_encrypt() and aes_*_decrypt() functions to be compiled as __reentrant 21 | #define AES_USE_USER_DEFINED_GALOIS_MULTIPLY_FUNCTION 0 //Use section below to define an alternate Galois multiplier function than the one used in the library 22 | #define AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES 0 //Allow the use of CBC, CFB, and OFB modes of operation in addition to ECB 23 | 24 | 25 | /////////////////////////////////////////////////////////// 26 | // Definition for a user-defined Galois multiplier 27 | /////////////////////////////////////////////////////////// 28 | #if (AES_USE_USER_DEFINED_GALOIS_MULTIPLY_FUNCTION != 0) 29 | //You must provide an alternate Galois multiply function that follows the following form (inlining the function is optional): 30 | // [inline] unsigned char galois_multiply_function(unsigned char a, unsigned char b) 31 | // where a and b are the multiplier/muliplicand and the return value is the Galois product. 32 | extern inline unsigned char enc_dec_accel_galois_multiply(unsigned char a, unsigned char b); //Extern function or include the header file for the function here 33 | 34 | #define aes_user_defined_galois_multiplication(a, b) enc_dec_accel_galois_multiply(a, b) //Change the name of the second function to your own 35 | #endif 36 | 37 | 38 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 39 | // Definition of __REENTRANT (use AES_FORCE_CRYPT_FUNCTIONS_REENTRANT_WITH_SDCC above to change...do not modify section below this comment!) 40 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 41 | #if (AES_FORCE_FUNCTIONS_AS_REENTRANT_WITH_SDCC != 0) 42 | #define __REENTRANT __reentrant 43 | #else 44 | #define __REENTRANT 45 | #endif 46 | 47 | 48 | #endif /* AES_USER_OPTIONS_H_ */ 49 | -------------------------------------------------------------------------------- /aes/inc/util.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: util.h 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #ifndef UTIL_H_ 14 | #define UTIL_H_ 15 | 16 | 17 | 18 | 19 | 20 | /////////////////////// 21 | // Function prototypes 22 | /////////////////////// 23 | void util_xor_arrays(const unsigned char * input_block_a, const unsigned char * input_block_b, unsigned char * output_block, unsigned int len); 24 | void util_copy_array(const unsigned char * input_block, unsigned char * output_block, unsigned int len); 25 | 26 | 27 | #endif /* UTIL_H_ */ 28 | -------------------------------------------------------------------------------- /aes/src/aes_add_round_key.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_add_round_key.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_add_round_key(aes_data_t * aes_data_p, unsigned char round) 20 | // 21 | // Description: 22 | // Adds the round key at "round" in w[] to state[]. 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // unsigned char round - round of key to add 27 | // 28 | // Return value: 29 | // None 30 | // 31 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | void aes_add_round_key(aes_data_t * aes_data_p, unsigned char round) __REENTRANT 33 | { 34 | unsigned char row, col; 35 | 36 | //loop through and add the appropriate state and round bytes 37 | for(row = 0; row < 4; row++) 38 | { 39 | for(col = 0; col < Nb; col++) 40 | { 41 | aes_data_p->state[row][col] = aes_data_p->state[row][col] ^ aes_data_p->w[row][(round * 4) + col]; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /aes/src/aes_decrypt_cbc.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_decrypt_cbc.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | #if (AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES != 0) 18 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // void aes_decrypt_cbc(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block); 21 | // 22 | // Description: 23 | // Decrypts an input block of cipher text into an output block of plain text using cipher-block chaining (CBC) mode 24 | // 25 | // Parameters: 26 | // aes_data_t * aes_data_p - data structure for this instance 27 | // const unsigned char * input_cipher_text_block - cipher text to be decrypted (the first 16 bytes of this array will be decrypted) 28 | // unsigned char * output_plain_text_block - decrypted plain text (must be at least 16 bytes in length) 29 | // 30 | // Return value: 31 | // None 32 | // 33 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | void aes_decrypt_cbc(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block) __REENTRANT 35 | { 36 | //The general algorithm for CBC decryption is 37 | // 1. Decrypt the cipher text 38 | // 2. XOR the IV (first decryption) or the previous cipher text block with the output of (1) 39 | // 3. Since the cipher text must be saved in aes_data_p->iv_or_intermediate_data, copy it 40 | aes_decrypt_ecb(aes_data_p, input_cipher_text_block, output_plain_text_block); 41 | util_xor_arrays(aes_data_p->iv_or_intermediate_data, output_plain_text_block, output_plain_text_block, 16); 42 | util_copy_array(input_cipher_text_block, aes_data_p->iv_or_intermediate_data, 16); 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /aes/src/aes_decrypt_cfb.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_decrypt_cfb.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | #if (AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES != 0) 18 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // void aes_decrypt_cfb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, 21 | // unsigned char * output_plain_text_block, unsigned int len); 22 | // 23 | // Description: 24 | // Decrypts an input block of cipher text into an output block of plain text using cipher feedback (CFB) mode 25 | // 26 | // Parameters: 27 | // aes_data_t * aes_data_p - data structure for this instance 28 | // const unsigned char * input_plain_text_block - plain text to be encrypted (the first len bytes will be encrypted) 29 | // unsigned char * output_cipher_text_block - encrypted cipher text (must be at least len bytes in length) 30 | // unsigned int len - number of bytes to be encrypted (can be any valid unsigned integer value) 31 | // 32 | // Return value: 33 | // None 34 | // 35 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | void aes_decrypt_cfb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block, unsigned int len) __REENTRANT 37 | { 38 | unsigned int i; 39 | 40 | //Since CFB allows turning a block cipher into a stream cipher, we can decrypt as many bytes as we want 41 | for(i = 0; i < len; i++) 42 | { 43 | //There are no key bytes left, so encrypt the IV/intermediate data to get another key byte block 44 | if(aes_data_p->rem_key_bytes == 0) 45 | { 46 | aes_encrypt_ecb(aes_data_p, aes_data_p->iv_or_intermediate_data, aes_data_p->iv_or_intermediate_data); 47 | aes_data_p->rem_key_bytes = 16; 48 | } 49 | 50 | //The general algorithm for CFB decryption is 51 | // 1. Set the current output plain text byte to the XOR of the current key byte and the current byte from the input cipher text 52 | // 2. Copy the current input cipher text byte to the current IV/intermediate data byte 53 | // 3. Decrement the number of remaining key block bytes 54 | output_plain_text_block[i] = aes_data_p->iv_or_intermediate_data[16 - aes_data_p->rem_key_bytes] ^ input_cipher_text_block[i]; 55 | aes_data_p->iv_or_intermediate_data[16 - aes_data_p->rem_key_bytes] = input_cipher_text_block[i]; 56 | aes_data_p->rem_key_bytes--; 57 | } 58 | } 59 | #endif 60 | -------------------------------------------------------------------------------- /aes/src/aes_decrypt_ecb.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_decrypt_ecb.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_decrypt_ecb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block) 20 | // 21 | // Description: 22 | // Decrypts an input block of cipher text into an output block of plain text using electronic codebook (ECB) mode 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // const unsigned char * input_cipher_text_block - cipher text to be decrypted (the first 16 bytes of this array will be decrypted) 27 | // unsigned char * output_plain_text_block - decrypted plain text (must be at least 16 bytes in length) 28 | // 29 | // Return value: 30 | // None 31 | // 32 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | void aes_decrypt_ecb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block) __REENTRANT 34 | { 35 | unsigned char row, col, round; 36 | 37 | //start out by copying the input cipher text onto the state 38 | for(row = 0; row < 4; row++) 39 | { 40 | for(col = 0; col < Nb; col++) 41 | { 42 | aes_data_p->state[row][col] = input_cipher_text_block[row + (4 * col)]; 43 | } 44 | } 45 | 46 | //add the round key at round Nr 47 | aes_add_round_key(aes_data_p, aes_data_p->Nr); 48 | 49 | //To take this for loop all the way down to zero, the exit clause would look weird (either round < 255 or round != 255), 50 | // so we leave it out and just break when we have processed round zero. 51 | for(round = (aes_data_p->Nr - 1); ; round--) 52 | { 53 | aes_shift_rows_inv(aes_data_p); 54 | aes_sub_bytes_inv(aes_data_p); 55 | 56 | aes_add_round_key(aes_data_p, round); 57 | 58 | //we do not apply mix columns at iteration zero, but we do exit on iteration zero 59 | if(round != 0) 60 | { 61 | aes_mix_columns_inv(aes_data_p); 62 | } 63 | else 64 | { 65 | break; 66 | } 67 | } 68 | 69 | //copy the decrypted state onto the output plain text 70 | for(row = 0; row < 4; row++) 71 | { 72 | for(col = 0; col < Nb; col++) 73 | { 74 | output_plain_text_block[row + (4 * col)] = aes_data_p->state[row][col]; 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /aes/src/aes_decrypt_ofb.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_decrypt_ofb.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | #if (AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES != 0) 18 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // void aes_decrypt_ofb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, 21 | // unsigned char * output_plain_text_block, unsigned int len); 22 | // 23 | // Description: 24 | // Decrypts an input block of cipher text into an output block of plain text using output feedback (OFB) mode 25 | // 26 | // Parameters: 27 | // aes_data_t * aes_data_p - data structure for this instance 28 | // const unsigned char * input_plain_text_block - plain text to be encrypted (the first len bytes will be encrypted) 29 | // unsigned char * output_cipher_text_block - encrypted cipher text (must be at least len bytes in length) 30 | // unsigned int len - number of bytes to be encrypted (can be any valid unsigned integer value) 31 | // 32 | // Return value: 33 | // None 34 | // 35 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | void aes_decrypt_ofb(aes_data_t * aes_data_p, const unsigned char * input_cipher_text_block, unsigned char * output_plain_text_block, unsigned int len) __REENTRANT 37 | { 38 | unsigned int i; 39 | 40 | //Since OFB allows turning a block cipher into a stream cipher, we can decrypt as many bytes as we want 41 | for(i = 0; i < len; i++) 42 | { 43 | //There are no key bytes left, so encrypt the IV/intermediate data to get another key byte block 44 | if(aes_data_p->rem_key_bytes == 0) 45 | { 46 | aes_encrypt_ecb(aes_data_p, aes_data_p->iv_or_intermediate_data, aes_data_p->iv_or_intermediate_data); 47 | aes_data_p->rem_key_bytes = 16; 48 | } 49 | 50 | //The general algorithm for CFB decryption is 51 | // 1. Set the current output plain text byte to the XOR of the current key byte and the current byte from the input cipher text 52 | // 2. Decrement the number of remaining key block bytes 53 | output_plain_text_block[i] = aes_data_p->iv_or_intermediate_data[16 - aes_data_p->rem_key_bytes] ^ input_cipher_text_block[i]; 54 | aes_data_p->rem_key_bytes--; 55 | } 56 | } 57 | #endif 58 | -------------------------------------------------------------------------------- /aes/src/aes_encrypt_cbc.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_encrypt_cbc.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | #if (AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES != 0) 18 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // void aes_encrypt_cbc(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block) 21 | // 22 | // Description: 23 | // Encrypts an input block of plain text into an output block of cipher text using cipher-block chaining (CBC) mode 24 | // 25 | // Parameters: 26 | // aes_data_t * aes_data_p - data structure for this instance 27 | // const unsigned char * input_plain_text_block - plain text to be encrypted (the first 16 bytes of this array will be encrypted) 28 | // unsigned char * output_cipher_text_block - encrypted cipher text (must be at least 16 bytes in length) 29 | // 30 | // Return value: 31 | // None 32 | // 33 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | void aes_encrypt_cbc(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block) __REENTRANT 35 | { 36 | //The general algorithm for CBC encryption is 37 | // 1. XOR the IV (first decryption) or the previous cipher text block with the input plain text block 38 | // 2. Encryp the result of (1) 39 | // 3. Since the cipher text must be saved in aes_data_p->iv_or_intermediate_data, copy it 40 | util_xor_arrays(aes_data_p->iv_or_intermediate_data, input_plain_text_block, aes_data_p->iv_or_intermediate_data, 16); 41 | aes_encrypt_ecb(aes_data_p, aes_data_p->iv_or_intermediate_data, aes_data_p->iv_or_intermediate_data); 42 | util_copy_array(aes_data_p->iv_or_intermediate_data, output_cipher_text_block, 16); 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /aes/src/aes_encrypt_cfb.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_encrypt_cfb.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | #if (AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES != 0) 18 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // void aes_encrypt_cfb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, 21 | // unsigned char * output_cipher_text_block, unsigned int len) 22 | // 23 | // Description: 24 | // Encrypts an input block of plain text into an output block of cipher text using cipher feedback (CFB) mode 25 | // 26 | // Parameters: 27 | // aes_data_t * aes_data_p - data structure for this instance 28 | // const unsigned char * input_plain_text_block - plain text to be encrypted (the first len bytes will be encrypted) 29 | // unsigned char * output_cipher_text_block - encrypted cipher text (must be at least len bytes in length) 30 | // unsigned int len - number of bytes to be encrypted (can be any valid unsigned integer value) 31 | // 32 | // Return value: 33 | // None 34 | // 35 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | void aes_encrypt_cfb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block, unsigned int len) __REENTRANT 37 | { 38 | unsigned int i; 39 | 40 | //Since CFB allows turning a block cipher into a stream cipher, we can decrypt as many bytes as we want 41 | for(i = 0; i < len; i++) 42 | { 43 | //There are no key bytes left, so encrypt the IV/intermediate data to get another key byte block 44 | if(aes_data_p->rem_key_bytes == 0) 45 | { 46 | aes_encrypt_ecb(aes_data_p, aes_data_p->iv_or_intermediate_data, aes_data_p->iv_or_intermediate_data); 47 | aes_data_p->rem_key_bytes = 16; 48 | } 49 | 50 | //The general algorithm for CFB encryption is 51 | // 1. Set the current IV/intermediate data byte to itself XORed with the current input plain text byte 52 | // 2. Set the current output cipher text byte to the result of (1) 53 | // 3. Decrement the number of remaining key block bytes 54 | aes_data_p->iv_or_intermediate_data[16 - aes_data_p->rem_key_bytes] ^= input_plain_text_block[i]; 55 | output_cipher_text_block[i] = aes_data_p->iv_or_intermediate_data[16 - aes_data_p->rem_key_bytes]; 56 | aes_data_p->rem_key_bytes--; 57 | } 58 | } 59 | #endif 60 | -------------------------------------------------------------------------------- /aes/src/aes_encrypt_ecb.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_encrypt_ecb.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_encrypt_ecb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block) 20 | // 21 | // Description: 22 | // Encrypts an input block of plain text into an output block of cipher text using electronic codebook (ECB) mode 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // const unsigned char * input_plain_text_block - plain text to be encrypted (the first 16 bytes of this array will be encrypted) 27 | // unsigned char * output_cipher_text_block - encrypted cipher text (must be at least 16 bytes in length) 28 | // 29 | // Return value: 30 | // None 31 | // 32 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | void aes_encrypt_ecb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block) __REENTRANT 34 | { 35 | unsigned char row, col, round; 36 | 37 | //start out by copying the input plain text onto the state 38 | for(row = 0; row < 4; row++) 39 | { 40 | for(col = 0; col < Nb; col++) 41 | { 42 | aes_data_p->state[row][col] = input_plain_text_block[row + (4 * col)]; 43 | } 44 | } 45 | 46 | //add the round key at round 0 47 | aes_add_round_key(aes_data_p, 0); 48 | 49 | //Rather than having round only count up to Nr - 1 and then calling the functions (less aes_mix_columns()) again outside 50 | // the for() loop, I am counting all the way up to Nr, but not calling aes_mix_columns on the last iteration. 51 | for(round = 1; round <= aes_data_p->Nr; round++) 52 | { 53 | aes_sub_bytes(aes_data_p); 54 | aes_shift_rows(aes_data_p); 55 | 56 | //don't apply mix columns on the last iteration 57 | if(round <= (aes_data_p->Nr - 1)) 58 | { 59 | aes_mix_columns(aes_data_p); 60 | } 61 | 62 | aes_add_round_key(aes_data_p, round); 63 | } 64 | 65 | //copy the encrypted state onto the output cipher text 66 | for(row = 0; row < 4; row++) 67 | { 68 | for(col = 0; col < Nb; col++) 69 | { 70 | output_cipher_text_block[row + (4 * col)] = aes_data_p->state[row][col]; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /aes/src/aes_encrypt_ofb.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_encrypt_ofb.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | #if (AES_ALLOW_NON_ECB_BLOCK_CIPHER_MODES != 0) 18 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // void aes_encrypt_ofb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, 21 | // unsigned char * output_cipher_text_block, unsigned int len) 22 | // 23 | // Description: 24 | // Encrypts an input block of plain text into an output block of cipher text using output feedback (OFB) mode 25 | // 26 | // Parameters: 27 | // aes_data_t * aes_data_p - data structure for this instance 28 | // const unsigned char * input_plain_text_block - plain text to be encrypted (the first len bytes will be encrypted) 29 | // unsigned char * output_cipher_text_block - encrypted cipher text (must be at least len bytes in length) 30 | // unsigned int len - number of bytes to be encrypted (can be any valid unsigned integer value) 31 | // 32 | // Return value: 33 | // None 34 | // 35 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | void aes_encrypt_ofb(aes_data_t * aes_data_p, const unsigned char * input_plain_text_block, unsigned char * output_cipher_text_block, unsigned int len) __REENTRANT 37 | { 38 | unsigned int i; 39 | 40 | //Since OFB allows turning a block cipher into a stream cipher, we can encrypt as many bytes as we want 41 | for(i = 0; i < len; i++) 42 | { 43 | //There are no key bytes left, so encrypt the IV/intermediate data to get another key byte block 44 | if(aes_data_p->rem_key_bytes == 0) 45 | { 46 | aes_encrypt_ecb(aes_data_p, aes_data_p->iv_or_intermediate_data, aes_data_p->iv_or_intermediate_data); 47 | aes_data_p->rem_key_bytes = 16; 48 | } 49 | 50 | //The general algorithm for CFB encryption is 51 | // 1. Set the current IV/intermediate data byte to itself XORed with the current input plain text byte 52 | // 3. Decrement the number of remaining key block bytes 53 | output_cipher_text_block[i] = aes_data_p->iv_or_intermediate_data[16 - aes_data_p->rem_key_bytes] ^ input_plain_text_block[i]; 54 | aes_data_p->rem_key_bytes--; 55 | } 56 | } 57 | #endif 58 | -------------------------------------------------------------------------------- /aes/src/aes_get_rcon.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_get_rcon.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // unsigned char aes_get_rcon(unsigned char index) 20 | // 21 | // Description: 22 | // Gets the specified rcon value 23 | // 24 | // Parameters: 25 | // unsigned char index - index into the rcon array 26 | // 27 | // Return value: 28 | // The specified rcon value 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | unsigned char aes_get_rcon(unsigned char index) __REENTRANT 32 | { 33 | //array to hold rcon values..."CODE" is only defined if using SDCC and forcing tables into code memory 34 | CODE static const unsigned char rcon[255] = 35 | { 36 | // 0 1 2 3 4 5 6 7 8 9 a b c d e f 37 | 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, //0 38 | 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, //1 39 | 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, //2 40 | 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, //3 41 | 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, //4 42 | 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, //5 43 | 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, //6 44 | 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, //7 45 | 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, //8 46 | 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, //9 47 | 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, //a 48 | 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, //b 49 | 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, //c 50 | 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, //d 51 | 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, //e 52 | 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb //f 53 | }; 54 | 55 | //the array only has 255 entries, so guard against going out of bounds 56 | if(index == 255) 57 | { 58 | return 0; 59 | } 60 | else 61 | { 62 | return rcon[index]; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /aes/src/aes_get_sbox.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_get_sbox.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // unsigned char aes_get_sbox(unsigned char index) 20 | // 21 | // Description: 22 | // Gets the specified sbox value 23 | // 24 | // Parameters: 25 | // unsigned char index - index into the sbox array 26 | // 27 | // Return value: 28 | // The specified sbox value 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | unsigned char aes_get_sbox(unsigned char index) __REENTRANT 32 | { 33 | //array to hold sbox values..."CODE" is only defined if using SDCC and forcing tables into code memory 34 | CODE static const unsigned char sbox[256] = 35 | { 36 | // 0 1 2 3 4 5 6 7 8 9 a b c d e f 37 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 38 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 39 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 40 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 41 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 42 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 43 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 44 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 45 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 46 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 47 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //a 48 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //b 49 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //c 50 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //d 51 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //e 52 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 //f 53 | }; 54 | 55 | return sbox[index]; 56 | } 57 | -------------------------------------------------------------------------------- /aes/src/aes_get_sbox_inv.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_get_sbox_inv.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // unsigned char aes_get_sbox_inv(unsigned char index) 20 | // 21 | // Description: 22 | // Gets the specified sbox_inv value 23 | // 24 | // Parameters: 25 | // unsigned char index - index into the sbox_inv array 26 | // 27 | // Return value: 28 | // The specified sbox_inv value 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | unsigned char aes_get_sbox_inv(unsigned char index) __REENTRANT 32 | { 33 | //array to hold sbox_inv values..."CODE" is only defined if using SDCC and forcing tables into code memory 34 | CODE static const unsigned char sbox_inv[256] = 35 | { 36 | // 0 1 2 3 4 5 6 7 8 9 a b c d e f 37 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, //0 38 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, //1 39 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, //2 40 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, //3 41 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, //4 42 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, //5 43 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, //6 44 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, //7 45 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, //8 46 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, //9 47 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, //a 48 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, //b 49 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, //c 50 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, //d 51 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, //d 52 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d //f 53 | }; 54 | 55 | return sbox_inv[index]; 56 | } 57 | -------------------------------------------------------------------------------- /aes/src/aes_included_galois_multiplication.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_included_galois_multiplication.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // unsigned char aes_included_galois_multiplication(unsigned char a, unsigned char b) 20 | // 21 | // Description: 22 | // Executes a Galois multiplication over the field GF(2^8). 23 | // 24 | // Parameters: 25 | // unsigned char a - Multiplier in Galois multiplication 26 | // unsigned char b - Multiplicand in Galois multiplication 27 | // 28 | // Return value: 29 | // Galois multiplication of a and b over the field GF(2^8) 30 | // 31 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | unsigned char aes_included_galois_multiplication(unsigned char a, unsigned char b) __REENTRANT 33 | { 34 | unsigned char p = 0; 35 | unsigned char counter; 36 | unsigned char hi_bit_set; 37 | 38 | for(counter = 0; counter < 8; counter++) 39 | { 40 | if((b & 1) == 1) 41 | { 42 | p ^= a; 43 | } 44 | 45 | hi_bit_set = (a & 0x80); 46 | a <<= 1; 47 | 48 | if(hi_bit_set == 0x80) 49 | { 50 | a ^= 0x1b; 51 | } 52 | 53 | b >>= 1; 54 | } 55 | 56 | return p; 57 | } 58 | -------------------------------------------------------------------------------- /aes/src/aes_initialize.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_initialize.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | #include 16 | 17 | 18 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | // 20 | // void aes_initialize(aes_data_t * aes_data_p, aes_key_length_t aes_key_length, const unsigned char * key, const unsigned char * iv) 21 | // 22 | // Description: 23 | // Initialize aes_data_p. This function only needs to be called before using aes_data_p the first time and then at any time the 24 | // key or key length is changed. 25 | // 26 | // Parameters: 27 | // aes_data_t * aes_data_p - data structure for this instance 28 | // aes_key_length_t aes_key_length - enumeration entry for the number of bits in the key 29 | // const unsigned char * key - key to use for encryption/decryption 30 | // const unsigned char * iv - only used with non-ECB modes, this is the initialization vector for encryption/decryption (set to 31 | // NULL to not use) 32 | // 33 | // Return value: 34 | // Galois multiplication of a and b over the field GF(2^8) 35 | // 36 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 37 | void aes_initialize(aes_data_t * aes_data_p, aes_key_length_t aes_key_length, const unsigned char * key, const unsigned char * iv) __REENTRANT 38 | { 39 | unsigned char i; 40 | 41 | //set up the constants to allow all 3 key lengths. Nb is not set here since it's always 4 for AES. 42 | if(aes_key_length == AES_KEY_LENGTH_128_BITS) 43 | { 44 | aes_data_p->Nk = Nk_128; 45 | aes_data_p->Nr = Nr_128; 46 | } 47 | else if(aes_key_length == AES_KEY_LENGTH_192_BITS) 48 | { 49 | aes_data_p->Nk = Nk_192; 50 | aes_data_p->Nr = Nr_192; 51 | } 52 | else 53 | { 54 | //default to 256 bit key length 55 | aes_data_p->Nk = Nk_256; 56 | aes_data_p->Nr = Nr_256; 57 | } 58 | 59 | //run the key expansion algorithm 60 | aes_key_expansion(aes_data_p, key); 61 | 62 | //Set up the initialization vector if provided 63 | if(iv != NULL) 64 | { 65 | for(i = 0; i < 16; i++) 66 | { 67 | aes_data_p->iv_or_intermediate_data[i] = iv[i]; 68 | } 69 | } 70 | 71 | aes_data_p->rem_key_bytes = 0; 72 | } 73 | -------------------------------------------------------------------------------- /aes/src/aes_key_expansion.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_key_expansion.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_key_expansion(aes_data_t * aes_data_p, unsigned char * key) 20 | // 21 | // Description: 22 | // Runs the key expansion algorithm 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // const unsigned char * key - key to use for encryption/decryption 27 | // 28 | // Return value: 29 | // None 30 | // 31 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | void aes_key_expansion(aes_data_t * aes_data_p, unsigned char * key) __REENTRANT 33 | { 34 | unsigned char col; 35 | unsigned char temp[4]; 36 | 37 | //the first round key is the key itself 38 | for(col = 0; col < aes_data_p->Nk; col++) 39 | { 40 | aes_data_p->w[0][col] = key[(4 * col)]; 41 | aes_data_p->w[1][col] = key[(4 * col) + 1]; 42 | aes_data_p->w[2][col] = key[(4 * col) + 2]; 43 | aes_data_p->w[3][col] = key[(4 * col) + 3]; 44 | } 45 | 46 | //subsequent rounds are derived from the previous round's key 47 | while (col < (Nb * (aes_data_p->Nr + 1))) 48 | { 49 | //copy the previous column 50 | temp[0] = aes_data_p->w[0][col - 1]; 51 | temp[1] = aes_data_p->w[1][col - 1]; 52 | temp[2] = aes_data_p->w[2][col - 1]; 53 | temp[3] = aes_data_p->w[3][col - 1]; 54 | 55 | //calculate the key adder 56 | if((col % aes_data_p->Nk) == 0) 57 | { 58 | aes_rot_word(temp); 59 | aes_sub_word(temp); 60 | 61 | //Only the zeroth entry has an item in rcon, the other three are 0's. 62 | //A value XOR'ed with 0 is itself, so we only need to XOR the zeroth entry. 63 | temp[0] = temp[0] ^ aes_get_rcon(col / aes_data_p->Nk); 64 | } 65 | else if((aes_data_p->Nk > 6) && ((col % aes_data_p->Nk) == 4)) 66 | { 67 | aes_sub_word(temp); 68 | } 69 | 70 | //add the calculated word to the corresponding word in the previous round key to get the current key 71 | aes_data_p->w[0][col] = aes_data_p->w[0][col - aes_data_p->Nk] ^ temp[0]; 72 | aes_data_p->w[1][col] = aes_data_p->w[1][col - aes_data_p->Nk] ^ temp[1]; 73 | aes_data_p->w[2][col] = aes_data_p->w[2][col - aes_data_p->Nk] ^ temp[2]; 74 | aes_data_p->w[3][col] = aes_data_p->w[3][col - aes_data_p->Nk] ^ temp[3]; 75 | 76 | col++; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /aes/src/aes_mix_columns.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_mix_columns.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_mix_columns(aes_data_t * aes_data_p) 20 | // 21 | // Description: 22 | // Runs the mix columns algorithm 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_mix_columns(aes_data_t * aes_data_p) __REENTRANT 32 | { 33 | unsigned char temp[4]; 34 | unsigned char col; 35 | 36 | //go through each column and calculate the Galois multiplication 37 | for (col = 0; col < Nb; col++) 38 | { 39 | temp[0] = aes_data_p->state[0][col]; 40 | temp[1] = aes_data_p->state[1][col]; 41 | temp[2] = aes_data_p->state[2][col]; 42 | temp[3] = aes_data_p->state[3][col]; 43 | 44 | aes_data_p->state[0][col] = aes_galois_multiplication(temp[0], 2) ^ 45 | aes_galois_multiplication(temp[3], 1) ^ 46 | aes_galois_multiplication(temp[2], 1) ^ 47 | aes_galois_multiplication(temp[1], 3); 48 | 49 | aes_data_p->state[1][col] = aes_galois_multiplication(temp[1], 2) ^ 50 | aes_galois_multiplication(temp[0], 1) ^ 51 | aes_galois_multiplication(temp[3], 1) ^ 52 | aes_galois_multiplication(temp[2], 3); 53 | 54 | aes_data_p->state[2][col] = aes_galois_multiplication(temp[2], 2) ^ 55 | aes_galois_multiplication(temp[1], 1) ^ 56 | aes_galois_multiplication(temp[0], 1) ^ 57 | aes_galois_multiplication(temp[3], 3); 58 | 59 | aes_data_p->state[3][col] = aes_galois_multiplication(temp[3], 2) ^ 60 | aes_galois_multiplication(temp[2], 1) ^ 61 | aes_galois_multiplication(temp[1], 1) ^ 62 | aes_galois_multiplication(temp[0], 3); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /aes/src/aes_mix_columns_inv.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_mix_columns_inv.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_mix_columns_inv(aes_data_t * aes_data_p) 20 | // 21 | // Description: 22 | // Runs the inverted mix columns algorithm 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_mix_columns_inv(aes_data_t * aes_data_p) __REENTRANT 32 | { 33 | unsigned char temp[4]; 34 | unsigned char col; 35 | 36 | //go through each column and calculate the Galois multiplication 37 | for (col = 0; col < Nb; col++) 38 | { 39 | temp[0] = aes_data_p->state[0][col]; 40 | temp[1] = aes_data_p->state[1][col]; 41 | temp[2] = aes_data_p->state[2][col]; 42 | temp[3] = aes_data_p->state[3][col]; 43 | 44 | aes_data_p->state[0][col] = aes_galois_multiplication(temp[0], 14) ^ 45 | aes_galois_multiplication(temp[3], 9) ^ 46 | aes_galois_multiplication(temp[2], 13) ^ 47 | aes_galois_multiplication(temp[1], 11); 48 | 49 | aes_data_p->state[1][col] = aes_galois_multiplication(temp[1], 14) ^ 50 | aes_galois_multiplication(temp[0], 9) ^ 51 | aes_galois_multiplication(temp[3], 13) ^ 52 | aes_galois_multiplication(temp[2], 11); 53 | 54 | aes_data_p->state[2][col] = aes_galois_multiplication(temp[2], 14) ^ 55 | aes_galois_multiplication(temp[1], 9) ^ 56 | aes_galois_multiplication(temp[0], 13) ^ 57 | aes_galois_multiplication(temp[3], 11); 58 | 59 | aes_data_p->state[3][col] = aes_galois_multiplication(temp[3], 14) ^ 60 | aes_galois_multiplication(temp[2], 9) ^ 61 | aes_galois_multiplication(temp[1], 13) ^ 62 | aes_galois_multiplication(temp[0], 11); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /aes/src/aes_rot_word.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_rot_word.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_rot_word(unsigned char * word) 20 | // 21 | // Description: 22 | // Rotates a word one byte to the left 23 | // 24 | // Parameters: 25 | // unsigned char * word - pointer to the 4-byte word to rotate 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_rot_word(unsigned char * word) __REENTRANT 32 | { 33 | unsigned char temp; 34 | 35 | //rotate word one byte to the left 36 | temp = word[0]; 37 | word[0] = word[1]; 38 | word[1] = word[2]; 39 | word[2] = word[3]; 40 | word[3] = temp; 41 | } 42 | -------------------------------------------------------------------------------- /aes/src/aes_shift_rows.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_shift_rows.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_shift_rows_inv(aes_data_t * aes_data_p) 20 | // 21 | // Description: 22 | // Shifts each row in the state by that row number of bytes to the left 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_shift_rows(aes_data_t * aes_data_p) __REENTRANT 32 | { 33 | unsigned char temp; 34 | 35 | //row 0 does not get rotated 36 | 37 | //rotate row 1 left by 1 column 38 | temp = aes_data_p->state[1][0]; 39 | aes_data_p->state[1][0] = aes_data_p->state[1][1]; 40 | aes_data_p->state[1][1] = aes_data_p->state[1][2]; 41 | aes_data_p->state[1][2] = aes_data_p->state[1][3]; 42 | aes_data_p->state[1][3] = temp; 43 | 44 | //rotate row 2 left by 2 columns by switching items 0 and 2 and 1 and 3 45 | temp = aes_data_p->state[2][0]; 46 | aes_data_p->state[2][0] = aes_data_p->state[2][2]; 47 | aes_data_p->state[2][2] = temp; 48 | temp = aes_data_p->state[2][1]; 49 | aes_data_p->state[2][1] = aes_data_p->state[2][3]; 50 | aes_data_p->state[2][3] = temp; 51 | 52 | //rotate row 3 left by 3 columns 53 | temp = aes_data_p->state[3][0]; 54 | aes_data_p->state[3][0] = aes_data_p->state[3][3]; 55 | aes_data_p->state[3][3] = aes_data_p->state[3][2]; 56 | aes_data_p->state[3][2] = aes_data_p->state[3][1]; 57 | aes_data_p->state[3][1] = temp; 58 | } 59 | -------------------------------------------------------------------------------- /aes/src/aes_shift_rows_inv.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_shift_rows_inv.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_shift_rows_inv(aes_data_t * aes_data_p) 20 | // 21 | // Description: 22 | // Shifts each row in the state by that row number of bytes to the right 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_shift_rows_inv(aes_data_t * aes_data_p) __REENTRANT 32 | { 33 | unsigned char temp; 34 | 35 | //row 0 does not get rotated 36 | 37 | //rotate row 1 right by 1 column 38 | temp = aes_data_p->state[1][0]; 39 | aes_data_p->state[1][0] = aes_data_p->state[1][3]; 40 | aes_data_p->state[1][3] = aes_data_p->state[1][2]; 41 | aes_data_p->state[1][2] = aes_data_p->state[1][1]; 42 | aes_data_p->state[1][1] = temp; 43 | 44 | //rotate row 2 right by 2 columns by switching items 0 and 2 and 1 and 3 45 | temp = aes_data_p->state[2][0]; 46 | aes_data_p->state[2][0] = aes_data_p->state[2][2]; 47 | aes_data_p->state[2][2] = temp; 48 | temp = aes_data_p->state[2][1]; 49 | aes_data_p->state[2][1] = aes_data_p->state[2][3]; 50 | aes_data_p->state[2][3] = temp; 51 | 52 | //rotate row 3 right by 3 columns 53 | temp = aes_data_p->state[3][0]; 54 | aes_data_p->state[3][0] = aes_data_p->state[3][1]; 55 | aes_data_p->state[3][1] = aes_data_p->state[3][2]; 56 | aes_data_p->state[3][2] = aes_data_p->state[3][3]; 57 | aes_data_p->state[3][3] = temp; 58 | } 59 | -------------------------------------------------------------------------------- /aes/src/aes_src.h: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_src.h 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #ifndef AES_SRC_H_ 14 | #define AES_SRC_H_ 15 | 16 | #include "aes.h" 17 | #include "aes_user_options.h" 18 | 19 | 20 | //////////////////////////////////////////////////////////////////////////////////////////////// 21 | // If the user is using SDCC and wants to force tables into code memory, use the __code keyword 22 | //////////////////////////////////////////////////////////////////////////////////////////////// 23 | #if (AES_FORCE_TABLES_INTO_CODE_MEMORY_WITH_SDCC != 0) 24 | #define CODE __code 25 | #else 26 | #define CODE 27 | #endif 28 | 29 | 30 | ////////////////////////////////////////////////////////////////////////////////////////////////// 31 | // If the user has defined their own multiplier, set it up here. Otherwise, use the built-in one. 32 | ////////////////////////////////////////////////////////////////////////////////////////////////// 33 | #if (AES_USE_USER_DEFINED_GALOIS_MULTIPLY_FUNCTION != 0) 34 | #define aes_galois_multiplication(a, b) aes_user_defined_galois_multiplication(a, b) 35 | #else 36 | #define aes_galois_multiplication(a, b) aes_included_galois_multiplication(a, b) 37 | #endif 38 | 39 | 40 | /////////////////////// 41 | // Function prototypes 42 | /////////////////////// 43 | unsigned char aes_get_sbox(unsigned char index) __REENTRANT; 44 | unsigned char aes_get_sbox_inv(unsigned char index) __REENTRANT; 45 | unsigned char aes_get_rcon(unsigned char index) __REENTRANT; 46 | void aes_rot_word(unsigned char * word) __REENTRANT; 47 | void aes_sub_word(unsigned char * word) __REENTRANT; 48 | void aes_shift_rows(aes_data_t * aes_data_p) __REENTRANT; 49 | void aes_shift_rows_inv(aes_data_t * aes_data_p) __REENTRANT; 50 | void aes_sub_bytes(aes_data_t * aes_data_p) __REENTRANT; 51 | void aes_sub_bytes_inv(aes_data_t * aes_data_p) __REENTRANT; 52 | void aes_add_round_key(aes_data_t * aes_data_p, unsigned char round) __REENTRANT; 53 | unsigned char aes_included_galois_multiplication(unsigned char a, unsigned char b) __REENTRANT; 54 | void aes_mix_columns(aes_data_t * aes_data_p) __REENTRANT; 55 | void aes_mix_columns_inv(aes_data_t * aes_data_p) __REENTRANT; 56 | void aes_key_expansion(aes_data_t * aes_data_p, unsigned char * key) __REENTRANT; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /aes/src/aes_sub_bytes.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_sub_bytes.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_sub_bytes(aes_data_t * aes_data_p) 20 | // 21 | // Description: 22 | // Substitutes the values in the state array with corresponding values from the sbox array 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_sub_bytes(aes_data_t * aes_data_p) __REENTRANT 32 | { 33 | int row, col; 34 | 35 | //substitute each byte in the state array with its corresponding entry in sbox[] 36 | for(row = 0; row < 4; row++) 37 | { 38 | for(col = 0; col < Nb; col++) 39 | { 40 | aes_data_p->state[row][col] = aes_get_sbox(aes_data_p->state[row][col]); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /aes/src/aes_sub_bytes_inv.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_sub_bytes_inv.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_sub_bytes_inv(aes_data_t * aes_data_p) 20 | // 21 | // Description: 22 | // Substitutes the values in the state array with corresponding values from the sbox_inv array 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_sub_bytes_inv(aes_data_t * aes_data_p) __REENTRANT 32 | { 33 | int row, col; 34 | 35 | //substitute each byte in the state array with its corresponding entry in sbox_inv[] 36 | for(row = 0; row < 4; row++) 37 | { 38 | for(col = 0; col < Nb; col++) 39 | { 40 | aes_data_p->state[row][col] = aes_get_sbox_inv(aes_data_p->state[row][col]); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /aes/src/aes_sub_word.c: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////////////// 2 | // 3 | // File: aes_sub_word.c 4 | // 5 | // Copyright S. Brennen Ball, 2010 6 | // 7 | // The author provides no guarantees, warantees, or promises, implied or 8 | // otherwise. By using this software you agree to indemnify the author 9 | // of any damages incurred by using it. 10 | // 11 | ///////////////////////////////////////////////////////////////////////////// 12 | 13 | #include "aes.h" 14 | #include "aes_src.h" 15 | 16 | 17 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | // 19 | // void aes_sub_word(aes_data_t * aes_data_p) 20 | // 21 | // Description: 22 | // Substitutes the values in a word with corresponding values from the sbox array 23 | // 24 | // Parameters: 25 | // aes_data_t * aes_data_p - data structure for this instance 26 | // 27 | // Return value: 28 | // None 29 | // 30 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | void aes_sub_word(unsigned char * word) __REENTRANT 32 | { 33 | //substitute each byte of "word" with its corresponding entry in sbox[] 34 | word[0] = aes_get_sbox(word[0]); 35 | word[1] = aes_get_sbox(word[1]); 36 | word[2] = aes_get_sbox(word[2]); 37 | word[3] = aes_get_sbox(word[3]); 38 | } 39 | -------------------------------------------------------------------------------- /aes_secret.sample.h: -------------------------------------------------------------------------------- 1 | /* 2 | aes_secret.h - aes encryption key 3 | */ 4 | 5 | static const unsigned char aes_key[16] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0x10}; -------------------------------------------------------------------------------- /am2302.c: -------------------------------------------------------------------------------- 1 | /* 2 | * DHT21/DHT22 driver 3 | */ 4 | 5 | #include "ch.h" 6 | #include "hal.h" 7 | 8 | #include "am2302.h" 9 | 10 | #define DHT_BIT_TIMEOUT_US (80 * 4) /* one bit timeout */ 11 | #define DHT_START_PULSE_MS 18 12 | #define DHT_IRQ_TIMEOUT_MS 2 /* irq timeout */ 13 | #define DHT_PKT_SIZE 5 14 | #define DHT_PKT_TIMEOUT_MS 10 15 | 16 | #define DHT_CHANNEL1_GPIO GPIOA /* channel 1 GPIO */ 17 | #define DHT_CHANNEL2_GPIO GPIOB /* channel 2 GPIO */ 18 | #define DHT_CHANNEL1_PIN 15 /* channel 1 PIN */ 19 | #define DHT_CHANNEL2_PIN 3 /* channel 2 PIN */ 20 | #define DHT_CHANNEL1 ICU_CHANNEL_1 21 | #define DHT_CHANNEL2 ICU_CHANNEL_2 22 | 23 | #define ERROR_DIV 2 24 | #define PERIOD_OK(x, l, h) \ 25 | ((x)->low >= ((l) - (l) / ERROR_DIV) && \ 26 | (x)->low < ((l) + (l) / ERROR_DIV) && \ 27 | ((x)->period - (x)->low) >= ((h) - (h) / ERROR_DIV) && \ 28 | ((x)->period - (x)->low) < ((h) + (h) / ERROR_DIV)) 29 | /*-----------------------------------------------------------------------------*/ 30 | 31 | typedef struct _icu_capture_t icu_capture_t; 32 | struct _icu_capture_t { 33 | uint16_t period; 34 | uint16_t low; 35 | }; 36 | 37 | typedef struct _dht_read_t dht_read_t; 38 | struct _dht_read_t { 39 | uint8_t channel; /* in */ 40 | dht_error_t error; /* out */ 41 | uint8_t data[DHT_PKT_SIZE]; /* out */ 42 | }; 43 | 44 | static BinarySemaphore icusem, cb_sem; 45 | static volatile icu_capture_t icu_data; 46 | 47 | static void icuwidthcb(ICUDriver *icup) { 48 | icu_data.low = icuGetWidth(icup); 49 | } 50 | 51 | static void icuperiodcb(ICUDriver *icup) { 52 | icu_data.period = icuGetPeriod(icup); 53 | chBSemSignalI(&cb_sem); 54 | } 55 | 56 | static void icuoverflowcb(ICUDriver *icup) { 57 | (void)icup; 58 | icu_data.period = 0; 59 | chBSemSignalI(&cb_sem); 60 | } 61 | 62 | static ICUConfig icucfgch1 = { 63 | ICU_INPUT_ACTIVE_LOW, 64 | 1000000, /* 1mHz ICU clock frequency. */ 65 | icuwidthcb, 66 | icuperiodcb, 67 | icuoverflowcb, 68 | DHT_CHANNEL1, 69 | 0 70 | }; 71 | 72 | static ICUConfig icucfgch2 = { 73 | ICU_INPUT_ACTIVE_LOW, 74 | 1000000, /* 1mHz ICU clock frequency. */ 75 | icuwidthcb, 76 | icuperiodcb, 77 | icuoverflowcb, 78 | DHT_CHANNEL2, 79 | 0 80 | }; 81 | 82 | /* 83 | * AM2302 read thread. 84 | */ 85 | static Thread *DHTThread_p; 86 | static WORKING_AREA(waDHTThread, 128); 87 | __attribute__((noreturn)) 88 | static msg_t DHTThread(void *arg) { 89 | 90 | (void)arg; 91 | chRegSetThreadName("DHTThd"); 92 | 93 | chBSemInit(&cb_sem, TRUE); 94 | while (TRUE) { 95 | /* wait for read request */ 96 | dht_read_t *req; 97 | Thread *tp; 98 | tp = chMsgWait(); 99 | req = (dht_read_t *) chMsgGet(tp); 100 | chMsgRelease(tp, (msg_t) req); 101 | 102 | AFIO->MAPR |= AFIO_MAPR_TIM2_REMAP_NOREMAP; 103 | 104 | // set DHT pin low on 2ms 105 | if (req->channel == 1){ 106 | palSetPadMode(DHT_CHANNEL1_GPIO, DHT_CHANNEL1_PIN, PAL_MODE_OUTPUT_OPENDRAIN); 107 | palClearPad(DHT_CHANNEL1_GPIO, DHT_CHANNEL1_PIN); 108 | } 109 | else if (req->channel == 2){ 110 | palSetPadMode(DHT_CHANNEL2_GPIO, DHT_CHANNEL2_PIN, PAL_MODE_OUTPUT_OPENDRAIN); 111 | palClearPad(DHT_CHANNEL2_GPIO, DHT_CHANNEL2_PIN); 112 | } 113 | chThdSleepMilliseconds(DHT_START_PULSE_MS); 114 | 115 | AFIO->MAPR |= AFIO_MAPR_TIM2_REMAP_FULLREMAP; 116 | 117 | if (req->channel == 1){ 118 | icuStart(&ICUD2, &icucfgch1); 119 | } 120 | else if (req->channel == 2){ 121 | icuStart(&ICUD2, &icucfgch2); 122 | } 123 | 124 | if (req->channel == 1){ 125 | palSetPadMode(DHT_CHANNEL1_GPIO, DHT_CHANNEL1_PIN, PAL_MODE_INPUT); 126 | } 127 | else if (req->channel == 2){ 128 | palSetPadMode(DHT_CHANNEL2_GPIO, DHT_CHANNEL2_PIN, PAL_MODE_INPUT); 129 | } 130 | icuEnable(&ICUD2); 131 | 132 | /* skip first falling edge */ 133 | int i; 134 | // IRQ timeout or receive timeout 135 | if(chBSemWaitTimeout(&cb_sem, MS2ST(DHT_IRQ_TIMEOUT_MS)) == RDY_TIMEOUT) { 136 | req->error = DHT_IRQ_TIMEOUT; 137 | goto reply; 138 | } 139 | if(!icu_data.period) { 140 | req->error = DHT_TIMEOUT; 141 | goto reply; 142 | } 143 | 144 | /* start sequence received */ 145 | if(!PERIOD_OK(&icu_data, 80, 80)) { 146 | req->error = DHT_DECODE_ERROR; 147 | goto reply; 148 | } 149 | 150 | for(i = 0; i < DHT_PKT_SIZE; i++) { 151 | unsigned int mask = 0x80; 152 | uint8_t byte = 0; 153 | while(mask) { 154 | if(chBSemWaitTimeout(&cb_sem, MS2ST(DHT_IRQ_TIMEOUT_MS)) == RDY_TIMEOUT) { 155 | req->error = DHT_IRQ_TIMEOUT; 156 | goto reply; 157 | } 158 | if(!icu_data.period) { 159 | req->error = DHT_TIMEOUT; 160 | goto reply; 161 | } 162 | 163 | /* next bit received */ 164 | if(PERIOD_OK(&icu_data, 50, 70)) { 165 | byte |= mask; /* 1 */ 166 | } else if(!PERIOD_OK(&icu_data, 50, 27)) { 167 | req->error = DHT_DECODE_ERROR; 168 | goto reply; 169 | } 170 | 171 | mask >>= 1; 172 | } 173 | req->data[i] = byte; 174 | } 175 | req->error = DHT_NO_ERROR; 176 | 177 | reply: 178 | icuDisable(&ICUD2); 179 | icuStop(&ICUD2); 180 | chBSemSignal(&icusem); 181 | } 182 | } 183 | 184 | dht_error_t dht_read(uint8_t channel, int *temperature, int *humidity) { 185 | dht_read_t rd; 186 | dht_read_t *rd_p = &rd; 187 | 188 | rd.channel = channel; 189 | 190 | chBSemWait(&icusem); /* to be sure */ 191 | 192 | chMsgSend(DHTThread_p, (msg_t) rd_p); 193 | 194 | /* wait for reply */ 195 | if(chBSemWaitTimeout(&icusem, MS2ST(DHT_PKT_TIMEOUT_MS)) == RDY_TIMEOUT) { 196 | chBSemReset(&icusem, FALSE); 197 | return DHT_RCV_TIMEOUT; 198 | } 199 | chBSemReset(&icusem, FALSE); 200 | 201 | if(rd.error != DHT_NO_ERROR) { 202 | return rd.error; 203 | } 204 | 205 | /* compute checksum */ 206 | unsigned int sum = 0; 207 | uint8_t i; 208 | for(i = 0; i < DHT_PKT_SIZE - 1; i++) sum += rd.data[i]; 209 | if((sum & 0xff) != rd.data[i]) { 210 | return DHT_CHECKSUM_ERROR; 211 | } 212 | 213 | if (rd.data[1] == 0 && rd.data[3] == 0) { // DHT11 214 | *humidity = ((unsigned int)rd.data[0]); 215 | *temperature = ((unsigned int)rd.data[2]); 216 | } 217 | else { // DHT21/22 218 | /* read 16 bit humidity value */ 219 | *humidity = ((unsigned int)rd.data[0] << 8) | 220 | (unsigned int)rd.data[1]; 221 | 222 | /* read 16 bit temperature value */ 223 | int val = ((unsigned int)rd.data[2] << 8) | 224 | (unsigned int)rd.data[3]; 225 | *temperature = val & 0x8000 ? -(val & ~0x8000) : val; 226 | } 227 | return DHT_NO_ERROR; 228 | } 229 | 230 | void dht_init(void){ 231 | AFIO->MAPR |= AFIO_MAPR_SWJ_CFG_JTAGDISABLE; 232 | 233 | chBSemInit(&icusem, FALSE); 234 | DHTThread_p = chThdCreateStatic(waDHTThread, sizeof(waDHTThread), DHT_PRIO, DHTThread, NULL); 235 | } 236 | -------------------------------------------------------------------------------- /am2302.h: -------------------------------------------------------------------------------- 1 | #ifndef _AM2302_H_ 2 | #define _AM2302_H_ 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #define DHT_COLLECTION_PERIOD_MS 2000UL 8 | #define DHT_PRIO (NORMALPRIO+1) 9 | 10 | typedef enum { 11 | DHT_UNKNOWN, 12 | DHT_NO_ERROR, 13 | DHT_IRQ_TIMEOUT, 14 | DHT_TIMEOUT, 15 | DHT_RCV_TIMEOUT, 16 | DHT_DECODE_ERROR, 17 | DHT_CHECKSUM_ERROR, 18 | } dht_error_t; 19 | 20 | /*-----------------------------------------------------------------------------*/ 21 | void dht_init(void); 22 | /* temperature in 1/10 deg C, humidity in 1/10 % */ 23 | dht_error_t dht_read(uint8_t channel, int *temperature, int *humidity); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | #endif 29 | -------------------------------------------------------------------------------- /bh1750.c: -------------------------------------------------------------------------------- 1 | /* 2 | * bh1750.c 3 | */ 4 | 5 | #include "ch.h" 6 | #include "hal.h" 7 | 8 | #include "bh1750.h" 9 | 10 | #define I2CD_BH1750 I2CD1 11 | 12 | #define BH1750_ADDR 0x23 // device address 13 | #define BH1750_PWR_DOWN 0x0 // No active state. 14 | #define BH1750_CONT_HMODE 0x10 // Continuously H-Resolution Mode 15 | #define BH1750_DELAY 200 // wait results (datasheet says max. 180ms) 16 | #define BH1750_TIMEOUT_MS 10 // i2c transmit timeout 17 | 18 | static const I2CConfig i2cfg = { OPMODE_I2C, 100000, STD_DUTY_CYCLE, }; 19 | 20 | // read data 21 | bh1750_error_t bh1750_read(int16_t *value) { 22 | static uint8_t txbuf[2] = {0}, rxbuf[2] = {0}; 23 | 24 | bh1750_error_t err = BH1750_NO_ERROR; 25 | 26 | i2cStart(&I2CD_BH1750, &i2cfg); 27 | i2cAcquireBus(&I2CD_BH1750); 28 | txbuf[0] = BH1750_CONT_HMODE; 29 | if (i2cMasterTransmitTimeout(&I2CD_BH1750, BH1750_ADDR, txbuf, 1, rxbuf, 0, MS2ST(BH1750_TIMEOUT_MS)) != RDY_OK){ 30 | err = BH1750_TIMEOUT; 31 | goto error; 32 | } 33 | chThdSleepMilliseconds(BH1750_DELAY); 34 | txbuf[0] = BH1750_PWR_DOWN; 35 | if (i2cMasterTransmitTimeout(&I2CD_BH1750, BH1750_ADDR, txbuf, 1, rxbuf, 2, MS2ST(BH1750_TIMEOUT_MS)) != RDY_OK){ 36 | err = BH1750_TIMEOUT; 37 | } 38 | 39 | error: 40 | i2cReleaseBus(&I2CD_BH1750); 41 | i2cStop(&I2CD_BH1750); 42 | 43 | if (err != BH1750_NO_ERROR){ 44 | return err; 45 | } 46 | 47 | *value = ((rxbuf[0] << 8) + rxbuf[1])/1.2; 48 | return BH1750_NO_ERROR; 49 | } 50 | 51 | void bh1750_init(void) { 52 | // Start the i2c driver 53 | palSetPadMode(GPIOB, GPIOB_PIN6, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); 54 | palSetPadMode(GPIOB, GPIOB_PIN7, PAL_MODE_STM32_ALTERNATE_OPENDRAIN); 55 | } 56 | -------------------------------------------------------------------------------- /bh1750.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bh1750.h 3 | */ 4 | 5 | #ifndef BH1750_H_ 6 | #define BH1750_H_ 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #include "ch.h" 12 | #include "hal.h" 13 | 14 | typedef enum { 15 | BH1750_NO_ERROR, 16 | BH1750_ERROR, 17 | BH1750_TIMEOUT, 18 | } bh1750_error_t; 19 | 20 | typedef struct _bh1750_read_t bh1750_read_t; 21 | struct _bh1750_read_t { 22 | bh1750_error_t error; /* out */ 23 | uint16_t value; /* out */ 24 | }; 25 | 26 | void bh1750_init(void); 27 | bh1750_error_t bh1750_read(int16_t *value); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | #endif /* BH1750_H_ */ 33 | -------------------------------------------------------------------------------- /build/rsensor.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndruPol/remote-sensor/59614bfc98fa650fa8272af7875d21d7f5ca32bf/build/rsensor.bin -------------------------------------------------------------------------------- /build/rsensor.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AndruPol/remote-sensor/59614bfc98fa650fa8272af7875d21d7f5ca32bf/build/rsensor.elf -------------------------------------------------------------------------------- /chconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file templates/chconf.h 19 | * @brief Configuration file template. 20 | * @details A copy of this file must be placed in each project directory, it 21 | * contains the application specific kernel settings. 22 | * 23 | * @addtogroup config 24 | * @details Kernel related settings and hooks. 25 | * @{ 26 | */ 27 | 28 | #ifndef _CHCONF_H_ 29 | #define _CHCONF_H_ 30 | 31 | /*===========================================================================*/ 32 | /** 33 | * @name Kernel parameters and options 34 | * @{ 35 | */ 36 | /*===========================================================================*/ 37 | 38 | /** 39 | * @brief System tick frequency. 40 | * @details Frequency of the system timer that drives the system ticks. This 41 | * setting also defines the system tick time unit. 42 | */ 43 | #if !defined(CH_FREQUENCY) || defined(__DOXYGEN__) 44 | #define CH_FREQUENCY 1000 45 | #endif 46 | 47 | /** 48 | * @brief Round robin interval. 49 | * @details This constant is the number of system ticks allowed for the 50 | * threads before preemption occurs. Setting this value to zero 51 | * disables the preemption for threads with equal priority and the 52 | * round robin becomes cooperative. Note that higher priority 53 | * threads can still preempt, the kernel is always preemptive. 54 | * 55 | * @note Disabling the round robin preemption makes the kernel more compact 56 | * and generally faster. 57 | */ 58 | #if !defined(CH_TIME_QUANTUM) || defined(__DOXYGEN__) 59 | #define CH_TIME_QUANTUM 20 60 | #endif 61 | 62 | /** 63 | * @brief Managed RAM size. 64 | * @details Size of the RAM area to be managed by the OS. If set to zero 65 | * then the whole available RAM is used. The core memory is made 66 | * available to the heap allocator and/or can be used directly through 67 | * the simplified core memory allocator. 68 | * 69 | * @note In order to let the OS manage the whole RAM the linker script must 70 | * provide the @p __heap_base__ and @p __heap_end__ symbols. 71 | * @note Requires @p CH_USE_MEMCORE. 72 | */ 73 | #if !defined(CH_MEMCORE_SIZE) || defined(__DOXYGEN__) 74 | #define CH_MEMCORE_SIZE 0 75 | #endif 76 | 77 | /** 78 | * @brief Idle thread automatic spawn suppression. 79 | * @details When this option is activated the function @p chSysInit() 80 | * does not spawn the idle thread automatically. The application has 81 | * then the responsibility to do one of the following: 82 | * - Spawn a custom idle thread at priority @p IDLEPRIO. 83 | * - Change the main() thread priority to @p IDLEPRIO then enter 84 | * an endless loop. In this scenario the @p main() thread acts as 85 | * the idle thread. 86 | * . 87 | * @note Unless an idle thread is spawned the @p main() thread must not 88 | * enter a sleep state. 89 | */ 90 | #if !defined(CH_NO_IDLE_THREAD) || defined(__DOXYGEN__) 91 | #define CH_NO_IDLE_THREAD FALSE 92 | #endif 93 | 94 | /** @} */ 95 | 96 | /*===========================================================================*/ 97 | /** 98 | * @name Performance options 99 | * @{ 100 | */ 101 | /*===========================================================================*/ 102 | 103 | /** 104 | * @brief OS optimization. 105 | * @details If enabled then time efficient rather than space efficient code 106 | * is used when two possible implementations exist. 107 | * 108 | * @note This is not related to the compiler optimization options. 109 | * @note The default is @p TRUE. 110 | */ 111 | #if !defined(CH_OPTIMIZE_SPEED) || defined(__DOXYGEN__) 112 | #define CH_OPTIMIZE_SPEED TRUE 113 | #endif 114 | 115 | /** @} */ 116 | 117 | /*===========================================================================*/ 118 | /** 119 | * @name Subsystem options 120 | * @{ 121 | */ 122 | /*===========================================================================*/ 123 | 124 | /** 125 | * @brief Threads registry APIs. 126 | * @details If enabled then the registry APIs are included in the kernel. 127 | * 128 | * @note The default is @p TRUE. 129 | */ 130 | #if !defined(CH_USE_REGISTRY) || defined(__DOXYGEN__) 131 | #define CH_USE_REGISTRY TRUE 132 | #endif 133 | 134 | /** 135 | * @brief Threads synchronization APIs. 136 | * @details If enabled then the @p chThdWait() function is included in 137 | * the kernel. 138 | * 139 | * @note The default is @p TRUE. 140 | */ 141 | #if !defined(CH_USE_WAITEXIT) || defined(__DOXYGEN__) 142 | #define CH_USE_WAITEXIT TRUE 143 | #endif 144 | 145 | /** 146 | * @brief Semaphores APIs. 147 | * @details If enabled then the Semaphores APIs are included in the kernel. 148 | * 149 | * @note The default is @p TRUE. 150 | */ 151 | #if !defined(CH_USE_SEMAPHORES) || defined(__DOXYGEN__) 152 | #define CH_USE_SEMAPHORES TRUE 153 | #endif 154 | 155 | /** 156 | * @brief Semaphores queuing mode. 157 | * @details If enabled then the threads are enqueued on semaphores by 158 | * priority rather than in FIFO order. 159 | * 160 | * @note The default is @p FALSE. Enable this if you have special requirements. 161 | * @note Requires @p CH_USE_SEMAPHORES. 162 | */ 163 | #if !defined(CH_USE_SEMAPHORES_PRIORITY) || defined(__DOXYGEN__) 164 | #define CH_USE_SEMAPHORES_PRIORITY FALSE 165 | #endif 166 | 167 | /** 168 | * @brief Atomic semaphore API. 169 | * @details If enabled then the semaphores the @p chSemSignalWait() API 170 | * is included in the kernel. 171 | * 172 | * @note The default is @p TRUE. 173 | * @note Requires @p CH_USE_SEMAPHORES. 174 | */ 175 | #if !defined(CH_USE_SEMSW) || defined(__DOXYGEN__) 176 | #define CH_USE_SEMSW TRUE 177 | #endif 178 | 179 | /** 180 | * @brief Mutexes APIs. 181 | * @details If enabled then the mutexes APIs are included in the kernel. 182 | * 183 | * @note The default is @p TRUE. 184 | */ 185 | #if !defined(CH_USE_MUTEXES) || defined(__DOXYGEN__) 186 | #define CH_USE_MUTEXES TRUE 187 | #endif 188 | 189 | /** 190 | * @brief Conditional Variables APIs. 191 | * @details If enabled then the conditional variables APIs are included 192 | * in the kernel. 193 | * 194 | * @note The default is @p TRUE. 195 | * @note Requires @p CH_USE_MUTEXES. 196 | */ 197 | #if !defined(CH_USE_CONDVARS) || defined(__DOXYGEN__) 198 | #define CH_USE_CONDVARS TRUE 199 | #endif 200 | 201 | /** 202 | * @brief Conditional Variables APIs with timeout. 203 | * @details If enabled then the conditional variables APIs with timeout 204 | * specification are included in the kernel. 205 | * 206 | * @note The default is @p TRUE. 207 | * @note Requires @p CH_USE_CONDVARS. 208 | */ 209 | #if !defined(CH_USE_CONDVARS_TIMEOUT) || defined(__DOXYGEN__) 210 | #define CH_USE_CONDVARS_TIMEOUT TRUE 211 | #endif 212 | 213 | /** 214 | * @brief Events Flags APIs. 215 | * @details If enabled then the event flags APIs are included in the kernel. 216 | * 217 | * @note The default is @p TRUE. 218 | */ 219 | #if !defined(CH_USE_EVENTS) || defined(__DOXYGEN__) 220 | #define CH_USE_EVENTS TRUE 221 | #endif 222 | 223 | /** 224 | * @brief Events Flags APIs with timeout. 225 | * @details If enabled then the events APIs with timeout specification 226 | * are included in the kernel. 227 | * 228 | * @note The default is @p TRUE. 229 | * @note Requires @p CH_USE_EVENTS. 230 | */ 231 | #if !defined(CH_USE_EVENTS_TIMEOUT) || defined(__DOXYGEN__) 232 | #define CH_USE_EVENTS_TIMEOUT TRUE 233 | #endif 234 | 235 | /** 236 | * @brief Synchronous Messages APIs. 237 | * @details If enabled then the synchronous messages APIs are included 238 | * in the kernel. 239 | * 240 | * @note The default is @p TRUE. 241 | */ 242 | #if !defined(CH_USE_MESSAGES) || defined(__DOXYGEN__) 243 | #define CH_USE_MESSAGES TRUE 244 | #endif 245 | 246 | /** 247 | * @brief Synchronous Messages queuing mode. 248 | * @details If enabled then messages are served by priority rather than in 249 | * FIFO order. 250 | * 251 | * @note The default is @p FALSE. Enable this if you have special requirements. 252 | * @note Requires @p CH_USE_MESSAGES. 253 | */ 254 | #if !defined(CH_USE_MESSAGES_PRIORITY) || defined(__DOXYGEN__) 255 | #define CH_USE_MESSAGES_PRIORITY FALSE 256 | #endif 257 | 258 | /** 259 | * @brief Mailboxes APIs. 260 | * @details If enabled then the asynchronous messages (mailboxes) APIs are 261 | * included in the kernel. 262 | * 263 | * @note The default is @p TRUE. 264 | * @note Requires @p CH_USE_SEMAPHORES. 265 | */ 266 | #if !defined(CH_USE_MAILBOXES) || defined(__DOXYGEN__) 267 | #define CH_USE_MAILBOXES TRUE 268 | #endif 269 | 270 | /** 271 | * @brief I/O Queues APIs. 272 | * @details If enabled then the I/O queues APIs are included in the kernel. 273 | * 274 | * @note The default is @p TRUE. 275 | */ 276 | #if !defined(CH_USE_QUEUES) || defined(__DOXYGEN__) 277 | #define CH_USE_QUEUES TRUE 278 | #endif 279 | 280 | /** 281 | * @brief Core Memory Manager APIs. 282 | * @details If enabled then the core memory manager APIs are included 283 | * in the kernel. 284 | * 285 | * @note The default is @p TRUE. 286 | */ 287 | #if !defined(CH_USE_MEMCORE) || defined(__DOXYGEN__) 288 | #define CH_USE_MEMCORE TRUE 289 | #endif 290 | 291 | /** 292 | * @brief Heap Allocator APIs. 293 | * @details If enabled then the memory heap allocator APIs are included 294 | * in the kernel. 295 | * 296 | * @note The default is @p TRUE. 297 | * @note Requires @p CH_USE_MEMCORE and either @p CH_USE_MUTEXES or 298 | * @p CH_USE_SEMAPHORES. 299 | * @note Mutexes are recommended. 300 | */ 301 | #if !defined(CH_USE_HEAP) || defined(__DOXYGEN__) 302 | #define CH_USE_HEAP TRUE 303 | #endif 304 | 305 | /** 306 | * @brief C-runtime allocator. 307 | * @details If enabled the the heap allocator APIs just wrap the C-runtime 308 | * @p malloc() and @p free() functions. 309 | * 310 | * @note The default is @p FALSE. 311 | * @note Requires @p CH_USE_HEAP. 312 | * @note The C-runtime may or may not require @p CH_USE_MEMCORE, see the 313 | * appropriate documentation. 314 | */ 315 | #if !defined(CH_USE_MALLOC_HEAP) || defined(__DOXYGEN__) 316 | #define CH_USE_MALLOC_HEAP FALSE 317 | #endif 318 | 319 | /** 320 | * @brief Memory Pools Allocator APIs. 321 | * @details If enabled then the memory pools allocator APIs are included 322 | * in the kernel. 323 | * 324 | * @note The default is @p TRUE. 325 | */ 326 | #if !defined(CH_USE_MEMPOOLS) || defined(__DOXYGEN__) 327 | #define CH_USE_MEMPOOLS TRUE 328 | #endif 329 | 330 | /** 331 | * @brief Dynamic Threads APIs. 332 | * @details If enabled then the dynamic threads creation APIs are included 333 | * in the kernel. 334 | * 335 | * @note The default is @p TRUE. 336 | * @note Requires @p CH_USE_WAITEXIT. 337 | * @note Requires @p CH_USE_HEAP and/or @p CH_USE_MEMPOOLS. 338 | */ 339 | #if !defined(CH_USE_DYNAMIC) || defined(__DOXYGEN__) 340 | #define CH_USE_DYNAMIC TRUE 341 | #endif 342 | 343 | /** @} */ 344 | 345 | /*===========================================================================*/ 346 | /** 347 | * @name Debug options 348 | * @{ 349 | */ 350 | /*===========================================================================*/ 351 | 352 | /** 353 | * @brief Debug option, system state check. 354 | * @details If enabled the correct call protocol for system APIs is checked 355 | * at runtime. 356 | * 357 | * @note The default is @p FALSE. 358 | */ 359 | #if !defined(CH_DBG_SYSTEM_STATE_CHECK) || defined(__DOXYGEN__) 360 | #define CH_DBG_SYSTEM_STATE_CHECK FALSE 361 | #endif 362 | 363 | /** 364 | * @brief Debug option, parameters checks. 365 | * @details If enabled then the checks on the API functions input 366 | * parameters are activated. 367 | * 368 | * @note The default is @p FALSE. 369 | */ 370 | #if !defined(CH_DBG_ENABLE_CHECKS) || defined(__DOXYGEN__) 371 | #define CH_DBG_ENABLE_CHECKS FALSE 372 | #endif 373 | 374 | /** 375 | * @brief Debug option, consistency checks. 376 | * @details If enabled then all the assertions in the kernel code are 377 | * activated. This includes consistency checks inside the kernel, 378 | * runtime anomalies and port-defined checks. 379 | * 380 | * @note The default is @p FALSE. 381 | */ 382 | #if !defined(CH_DBG_ENABLE_ASSERTS) || defined(__DOXYGEN__) 383 | #define CH_DBG_ENABLE_ASSERTS FALSE 384 | #endif 385 | 386 | /** 387 | * @brief Debug option, trace buffer. 388 | * @details If enabled then the context switch circular trace buffer is 389 | * activated. 390 | * 391 | * @note The default is @p FALSE. 392 | */ 393 | #if !defined(CH_DBG_ENABLE_TRACE) || defined(__DOXYGEN__) 394 | #define CH_DBG_ENABLE_TRACE FALSE 395 | #endif 396 | 397 | /** 398 | * @brief Debug option, stack checks. 399 | * @details If enabled then a runtime stack check is performed. 400 | * 401 | * @note The default is @p FALSE. 402 | * @note The stack check is performed in a architecture/port dependent way. 403 | * It may not be implemented or some ports. 404 | * @note The default failure mode is to halt the system with the global 405 | * @p panic_msg variable set to @p NULL. 406 | */ 407 | #if !defined(CH_DBG_ENABLE_STACK_CHECK) || defined(__DOXYGEN__) 408 | #define CH_DBG_ENABLE_STACK_CHECK FALSE 409 | #endif 410 | 411 | /** 412 | * @brief Debug option, stacks initialization. 413 | * @details If enabled then the threads working area is filled with a byte 414 | * value when a thread is created. This can be useful for the 415 | * runtime measurement of the used stack. 416 | * 417 | * @note The default is @p FALSE. 418 | */ 419 | #if !defined(CH_DBG_FILL_THREADS) || defined(__DOXYGEN__) 420 | #define CH_DBG_FILL_THREADS FALSE 421 | #endif 422 | 423 | /** 424 | * @brief Debug option, threads profiling. 425 | * @details If enabled then a field is added to the @p Thread structure that 426 | * counts the system ticks occurred while executing the thread. 427 | * 428 | * @note The default is @p TRUE. 429 | * @note This debug option is defaulted to TRUE because it is required by 430 | * some test cases into the test suite. 431 | */ 432 | #if !defined(CH_DBG_THREADS_PROFILING) || defined(__DOXYGEN__) 433 | #define CH_DBG_THREADS_PROFILING FALSE 434 | #endif 435 | 436 | /** @} */ 437 | 438 | /*===========================================================================*/ 439 | /** 440 | * @name Kernel hooks 441 | * @{ 442 | */ 443 | /*===========================================================================*/ 444 | 445 | /** 446 | * @brief Threads descriptor structure extension. 447 | * @details User fields added to the end of the @p Thread structure. 448 | */ 449 | #if !defined(THREAD_EXT_FIELDS) || defined(__DOXYGEN__) 450 | #define THREAD_EXT_FIELDS \ 451 | /* Add threads custom fields here.*/ 452 | #endif 453 | 454 | /** 455 | * @brief Threads initialization hook. 456 | * @details User initialization code added to the @p chThdInit() API. 457 | * 458 | * @note It is invoked from within @p chThdInit() and implicitly from all 459 | * the threads creation APIs. 460 | */ 461 | #if !defined(THREAD_EXT_INIT_HOOK) || defined(__DOXYGEN__) 462 | #define THREAD_EXT_INIT_HOOK(tp) { \ 463 | /* Add threads initialization code here.*/ \ 464 | } 465 | #endif 466 | 467 | /** 468 | * @brief Threads finalization hook. 469 | * @details User finalization code added to the @p chThdExit() API. 470 | * 471 | * @note It is inserted into lock zone. 472 | * @note It is also invoked when the threads simply return in order to 473 | * terminate. 474 | */ 475 | #if !defined(THREAD_EXT_EXIT_HOOK) || defined(__DOXYGEN__) 476 | #define THREAD_EXT_EXIT_HOOK(tp) { \ 477 | /* Add threads finalization code here.*/ \ 478 | } 479 | #endif 480 | 481 | /** 482 | * @brief Context switch hook. 483 | * @details This hook is invoked just before switching between threads. 484 | */ 485 | #if !defined(THREAD_CONTEXT_SWITCH_HOOK) || defined(__DOXYGEN__) 486 | #define THREAD_CONTEXT_SWITCH_HOOK(ntp, otp) { \ 487 | /* System halt code here.*/ \ 488 | } 489 | #endif 490 | 491 | /** 492 | * @brief Idle Loop hook. 493 | * @details This hook is continuously invoked by the idle thread loop. 494 | */ 495 | #if !defined(IDLE_LOOP_HOOK) || defined(__DOXYGEN__) 496 | #define IDLE_LOOP_HOOK() { \ 497 | /* Idle loop code here.*/ \ 498 | } 499 | #endif 500 | 501 | /** 502 | * @brief System tick event hook. 503 | * @details This hook is invoked in the system tick handler immediately 504 | * after processing the virtual timers queue. 505 | */ 506 | #if !defined(SYSTEM_TICK_EVENT_HOOK) || defined(__DOXYGEN__) 507 | #define SYSTEM_TICK_EVENT_HOOK() { \ 508 | /* System tick event code here.*/ \ 509 | } 510 | #endif 511 | 512 | /** 513 | * @brief System halt hook. 514 | * @details This hook is invoked in case to a system halting error before 515 | * the system is halted. 516 | */ 517 | #if !defined(SYSTEM_HALT_HOOK) || defined(__DOXYGEN__) 518 | #define SYSTEM_HALT_HOOK() { \ 519 | /* System halt code here.*/ \ 520 | } 521 | #endif 522 | 523 | /** @} */ 524 | 525 | /*===========================================================================*/ 526 | /* Port-specific settings (override port settings defaulted in chcore.h). */ 527 | /*===========================================================================*/ 528 | #define PORT_INT_REQUIRED_STACK 32 529 | #define CHPRINTF_USE_FLOAT 1 530 | 531 | #endif /* _CHCONF_H_ */ 532 | 533 | /** @} */ 534 | -------------------------------------------------------------------------------- /devices.txt: -------------------------------------------------------------------------------- 1 | Unit VDD_min VDD_typ VDD_max,V I_min I_max, mA 2 | STM32F103C8T6 2 3.3 3.6 0.035 50/28(48Mhz) 3 | NRF24L01 1.9 3 3.6 0.001 11.8 4 | BH1750 2.4 3 3.6 ? 0.19 5 | DHT22/AM2303 3.3 5 5.5 1 2.1 6 | DHT21/HM2301 3.3 5 5.5 1 2.1 7 | DS1820B 3 5.5 1 >=4 8 | BMP085 1.8 2.5 3.6 0.0001 1 9 | -------------------------------------------------------------------------------- /ds1820b.c: -------------------------------------------------------------------------------- 1 | #include "ch.h" 2 | #include "hal.h" 3 | #include "oneWire.h" 4 | #include "ds1820b.h" 5 | #include "math.h" 6 | 7 | 8 | void ds1820BInit (OneWireDriver* drv, const OneWireRomAddress *address, 9 | const uint8_t precBits) 10 | { 11 | uint8_t initVal[] = {0x4e, 0x00, 0xff, 0x1f}; 12 | 13 | if (precBits <= 9) { 14 | initVal[3] |= 0; 15 | } else if (precBits == 10) { 16 | initVal[3] |= 0b00100000; 17 | } else if (precBits == 11) { 18 | initVal[3] |= 0b01000000; 19 | } else { // prec bit >= 12 20 | initVal[3] |= 0b01100000; 21 | } 22 | 23 | oneWireReset (drv); 24 | if (address == NULL) { 25 | oneWireSendByte (drv, 0xcc); 26 | } else { 27 | oneWireSendByte (drv, 0x55); 28 | oneWireSend (drv, address->addr, 8); 29 | } 30 | 31 | oneWireSend (drv, initVal, sizeof(initVal)); 32 | } 33 | 34 | float ds1820BGetTemp (OneWireDriver* drv, const OneWireRomAddress *address) 35 | { 36 | uint8_t ram[9]; 37 | 38 | oneWireAcquireBus (drv); 39 | oneWireReset (drv); 40 | if (address == NULL) { 41 | oneWireSendByte (drv, 0xcc); 42 | } else { 43 | oneWireSendByte (drv, 0x55); 44 | oneWireSend (drv, address->addr, 8); 45 | } 46 | 47 | oneWireSendByte (drv, 0x44); 48 | chThdSleepMilliseconds(100); // minimum conv time when 9 bit 49 | while (oneWireReceiveBit(drv) == FALSE) { 50 | chThdSleepMilliseconds(10); // waint until conversion is done 51 | } 52 | 53 | oneWireReset (drv); 54 | if (address == NULL) { 55 | oneWireSendByte (drv, 0xcc); 56 | } else { 57 | oneWireSendByte (drv, 0x55); 58 | oneWireSend (drv, address->addr, 8); 59 | } 60 | 61 | oneWireSendByte (drv, 0xbe); 62 | oneWireReceive (drv, ram, sizeof(ram)); 63 | // uint8_t crc = oneWireCrc8(ram, 8); 64 | uint8_t crc = owCrc8(ram, 8); 65 | if (crc != ram[8]) { 66 | oneWireRealeaseBus (); 67 | return (nanf("")); 68 | } 69 | 70 | 71 | const int16_t rawTmp = (ram[1] << 8) | (ram [0]); 72 | oneWireRealeaseBus (); 73 | return (rawTmp * 0.0625f); 74 | } 75 | 76 | 77 | void ds1820BAskTemp (OneWireDriver* drv, const OneWireRomAddress *address) 78 | { 79 | oneWireAcquireBus (drv); 80 | oneWireReset (drv); 81 | if (address == NULL) { 82 | oneWireSendByte (drv, 0xcc); 83 | } else { 84 | oneWireSendByte (drv, 0x55); 85 | oneWireSend (drv, address->addr, 8); 86 | } 87 | oneWireSendByte (drv, 0x44); 88 | oneWireRealeaseBus (); 89 | } 90 | 91 | 92 | float ds1820BGGetTempFromRam (OneWireDriver* drv, const OneWireRomAddress *address) 93 | { 94 | uint8_t ram[9]; 95 | 96 | oneWireAcquireBus (drv); 97 | 98 | oneWireReset (drv); 99 | if (address == NULL) { 100 | oneWireSendByte (drv, 0xcc); 101 | } else { 102 | oneWireSendByte (drv, 0x55); 103 | oneWireSend (drv, address->addr, 8); 104 | } 105 | 106 | oneWireSendByte (drv, 0xbe); 107 | oneWireReceive (drv, ram, sizeof(ram)); 108 | // uint8_t crc = oneWireCrc8(ram, 8); 109 | uint8_t crc = owCrc8(ram, 8); 110 | if (crc != ram[8]) { 111 | oneWireRealeaseBus (); 112 | return (nanf("")); 113 | } 114 | 115 | oneWireRealeaseBus (); 116 | const int16_t rawTmp = (ram[1] << 8) | (ram [0]); 117 | return (rawTmp * 0.0625f); 118 | } 119 | 120 | -------------------------------------------------------------------------------- /ds1820b.h: -------------------------------------------------------------------------------- 1 | #ifndef __DS_1820_B_H__ 2 | #define __DS_1820_B_H__ 3 | 4 | #include "oneWire.h" 5 | 6 | 7 | /* 8 | initialise and configure sensors 9 | */ 10 | void ds1820BInit (OneWireDriver* drv, const OneWireRomAddress *address, 11 | const uint8_t precBits); 12 | 13 | 14 | /* 15 | ask conversion, wait for the conversion to be done, then return value, 16 | could be the simplest way to acquire data when there is only one sensor 17 | */ 18 | float ds1820BGetTemp (OneWireDriver* drv, const OneWireRomAddress *address); 19 | 20 | 21 | /* 22 | separate ask conversion command and get values. 23 | this is the fastest way to acquire data when there is a lot of sensors : 24 | 1/ ask conversion for all sensors 25 | 2/ wait time accordingly to precision (see datasheet) 26 | 3/ get the temperature for all sensors 27 | */ 28 | void ds1820BAskTemp (OneWireDriver* drv, const OneWireRomAddress *address); 29 | float ds1820BGGetTempFromRam (OneWireDriver* drv, const OneWireRomAddress *address); 30 | 31 | #endif //__DS_1820_B_H__ 32 | -------------------------------------------------------------------------------- /halconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | /** 18 | * @file templates/halconf.h 19 | * @brief HAL configuration header. 20 | * @details HAL configuration file, this file allows to enable or disable the 21 | * various device drivers from your application. You may also use 22 | * this file in order to override the device drivers default settings. 23 | * 24 | * @addtogroup HAL_CONF 25 | * @{ 26 | */ 27 | 28 | #ifndef _HALCONF_H_ 29 | #define _HALCONF_H_ 30 | 31 | #include "mcuconf.h" 32 | 33 | /** 34 | * @brief Enables the TM subsystem. 35 | */ 36 | #if !defined(HAL_USE_TM) || defined(__DOXYGEN__) 37 | #define HAL_USE_TM FALSE 38 | #endif 39 | 40 | /** 41 | * @brief Enables the PAL subsystem. 42 | */ 43 | #if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) 44 | #define HAL_USE_PAL TRUE 45 | #endif 46 | 47 | /** 48 | * @brief Enables the ADC subsystem. 49 | */ 50 | #if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) 51 | #define HAL_USE_ADC FALSE 52 | #endif 53 | 54 | /** 55 | * @brief Enables the CAN subsystem. 56 | */ 57 | #if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) 58 | #define HAL_USE_CAN FALSE 59 | #endif 60 | 61 | /** 62 | * @brief Enables the EXT subsystem. 63 | */ 64 | #if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) 65 | #define HAL_USE_EXT TRUE 66 | #endif 67 | 68 | /** 69 | * @brief Enables the GPT subsystem. 70 | */ 71 | #if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) 72 | #define HAL_USE_GPT FALSE 73 | #endif 74 | 75 | /** 76 | * @brief Enables the I2C subsystem. 77 | */ 78 | #if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) 79 | #define HAL_USE_I2C TRUE 80 | #endif 81 | 82 | /** 83 | * @brief Enables the ICU subsystem. 84 | */ 85 | #if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) 86 | #define HAL_USE_ICU TRUE 87 | #endif 88 | 89 | /** 90 | * @brief Enables the MAC subsystem. 91 | */ 92 | #if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) 93 | #define HAL_USE_MAC FALSE 94 | #endif 95 | 96 | /** 97 | * @brief Enables the MMC_SPI subsystem. 98 | */ 99 | #if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) 100 | #define HAL_USE_MMC_SPI FALSE 101 | #endif 102 | 103 | /** 104 | * @brief Enables the PWM subsystem. 105 | */ 106 | #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) 107 | #define HAL_USE_PWM FALSE 108 | #endif 109 | 110 | /** 111 | * @brief Enables the RTC subsystem. 112 | */ 113 | #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) 114 | #define HAL_USE_RTC TRUE 115 | #endif 116 | 117 | /** 118 | * @brief Enables the SDC subsystem. 119 | */ 120 | #if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) 121 | #define HAL_USE_SDC FALSE 122 | #endif 123 | 124 | /** 125 | * @brief Enables the SERIAL subsystem. 126 | */ 127 | #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) 128 | #define HAL_USE_SERIAL TRUE 129 | #endif 130 | 131 | /** 132 | * @brief Enables the SERIAL over USB subsystem. 133 | */ 134 | #if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) 135 | #define HAL_USE_SERIAL_USB FALSE 136 | #endif 137 | 138 | /** 139 | * @brief Enables the SPI subsystem. 140 | */ 141 | #if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) 142 | #define HAL_USE_SPI TRUE 143 | #endif 144 | 145 | /** 146 | * @brief Enables the UART subsystem. 147 | */ 148 | #if !defined(HAL_USE_UART) || defined(__DOXYGEN__) 149 | #define HAL_USE_UART TRUE 150 | #endif 151 | 152 | /** 153 | * @brief Enables the USB subsystem. 154 | */ 155 | #if !defined(HAL_USE_USB) || defined(__DOXYGEN__) 156 | #define HAL_USE_USB FALSE 157 | #endif 158 | 159 | /*===========================================================================*/ 160 | /* ADC driver related settings. */ 161 | /*===========================================================================*/ 162 | 163 | /** 164 | * @brief Enables synchronous APIs. 165 | * @note Disabling this option saves both code and data space. 166 | */ 167 | #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) 168 | #define ADC_USE_WAIT TRUE 169 | #endif 170 | 171 | /** 172 | * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. 173 | * @note Disabling this option saves both code and data space. 174 | */ 175 | #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 176 | #define ADC_USE_MUTUAL_EXCLUSION TRUE 177 | #endif 178 | 179 | /*===========================================================================*/ 180 | /* CAN driver related settings. */ 181 | /*===========================================================================*/ 182 | 183 | /** 184 | * @brief Sleep mode related APIs inclusion switch. 185 | */ 186 | #if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) 187 | #define CAN_USE_SLEEP_MODE TRUE 188 | #endif 189 | 190 | /*===========================================================================*/ 191 | /* I2C driver related settings. */ 192 | /*===========================================================================*/ 193 | 194 | /** 195 | * @brief Enables the mutual exclusion APIs on the I2C bus. 196 | */ 197 | #if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 198 | #define I2C_USE_MUTUAL_EXCLUSION TRUE 199 | #endif 200 | 201 | /*===========================================================================*/ 202 | /* MAC driver related settings. */ 203 | /*===========================================================================*/ 204 | 205 | /** 206 | * @brief Enables an event sources for incoming packets. 207 | */ 208 | #if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) 209 | #define MAC_USE_ZERO_COPY FALSE 210 | #endif 211 | 212 | /** 213 | * @brief Enables an event sources for incoming packets. 214 | */ 215 | #if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) 216 | #define MAC_USE_EVENTS TRUE 217 | #endif 218 | 219 | /*===========================================================================*/ 220 | /* MMC_SPI driver related settings. */ 221 | /*===========================================================================*/ 222 | 223 | /** 224 | * @brief Delays insertions. 225 | * @details If enabled this options inserts delays into the MMC waiting 226 | * routines releasing some extra CPU time for the threads with 227 | * lower priority, this may slow down the driver a bit however. 228 | * This option is recommended also if the SPI driver does not 229 | * use a DMA channel and heavily loads the CPU. 230 | */ 231 | #if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) 232 | #define MMC_NICE_WAITING TRUE 233 | #endif 234 | 235 | /*===========================================================================*/ 236 | /* SDC driver related settings. */ 237 | /*===========================================================================*/ 238 | 239 | /** 240 | * @brief Number of initialization attempts before rejecting the card. 241 | * @note Attempts are performed at 10mS intervals. 242 | */ 243 | #if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) 244 | #define SDC_INIT_RETRY 100 245 | #endif 246 | 247 | /** 248 | * @brief Include support for MMC cards. 249 | * @note MMC support is not yet implemented so this option must be kept 250 | * at @p FALSE. 251 | */ 252 | #if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) 253 | #define SDC_MMC_SUPPORT FALSE 254 | #endif 255 | 256 | /** 257 | * @brief Delays insertions. 258 | * @details If enabled this options inserts delays into the MMC waiting 259 | * routines releasing some extra CPU time for the threads with 260 | * lower priority, this may slow down the driver a bit however. 261 | */ 262 | #if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) 263 | #define SDC_NICE_WAITING TRUE 264 | #endif 265 | 266 | /*===========================================================================*/ 267 | /* SERIAL driver related settings. */ 268 | /*===========================================================================*/ 269 | 270 | /** 271 | * @brief Default bit rate. 272 | * @details Configuration parameter, this is the baud rate selected for the 273 | * default configuration. 274 | */ 275 | #if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) 276 | #define SERIAL_DEFAULT_BITRATE 38400 277 | #endif 278 | 279 | /** 280 | * @brief Serial buffers size. 281 | * @details Configuration parameter, you can change the depth of the queue 282 | * buffers depending on the requirements of your application. 283 | * @note The default is 64 bytes for both the transmission and receive 284 | * buffers. 285 | */ 286 | #if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) 287 | #define SERIAL_BUFFERS_SIZE 16 288 | #endif 289 | 290 | /*===========================================================================*/ 291 | /* SPI driver related settings. */ 292 | /*===========================================================================*/ 293 | 294 | /** 295 | * @brief Enables synchronous APIs. 296 | * @note Disabling this option saves both code and data space. 297 | */ 298 | #if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) 299 | #define SPI_USE_WAIT TRUE 300 | #endif 301 | 302 | /** 303 | * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. 304 | * @note Disabling this option saves both code and data space. 305 | */ 306 | #if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) 307 | #define SPI_USE_MUTUAL_EXCLUSION TRUE 308 | #endif 309 | 310 | #endif /* _HALCONF_H_ */ 311 | 312 | /** @} */ 313 | -------------------------------------------------------------------------------- /main.h: -------------------------------------------------------------------------------- 1 | /* 2 | * main.h 3 | * 4 | * Created on: 16.08.2013 5 | * Author: pae 6 | */ 7 | 8 | #ifndef MAIN_H_ 9 | #define MAIN_H_ 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | #define FIRMWARE "0.4" // версия прошивки 15 | #define SLEEPTIME 720 // время режима пониженного энергопотребления, сек 16 | #define SENSORID 0 // this sensor ID 17 | 18 | typedef enum { 19 | SENSOR_INFO = 0, // not implemented 20 | SENSOR_DATA, 21 | SENSOR_ERROR 22 | } msgtype_t; 23 | 24 | typedef enum { 25 | DS1820 = 0, 26 | BH1750, 27 | DHT, 28 | BMP085, 29 | ADC 30 | } sensortype_t; 31 | 32 | typedef enum { 33 | TEMPERATURE = 0, 34 | HUMIDITY, 35 | PRESSURE, 36 | LIGHT, 37 | VOLTAGE 38 | } valuetype_t; 39 | 40 | // описание формата посылки 41 | #define MSGLEN 16 42 | typedef struct MESSAGE MESSAGE_T; 43 | struct MESSAGE{ 44 | msgtype_t msgType; // тип сообщения: 0 - инфо, 1 - значение датчика, 2 - ошибка 45 | uint8_t sensorID; // board ID 46 | sensortype_t sensorType; // тип датчика: 0 - DS1820, 1 - BH1750, 2 - DHT21/22 сенсор, 3 - BMP085, 4 - ADC 47 | valuetype_t valueType; // тип значения: 0 - temperature, 1 - humidity, 2 - pressure, 3 - light, 4 - voltage 48 | uint8_t owkey[8]; // идентификатор датчика DS1820, номер датчика DHT в owkey[0] 49 | union { // значение датчика 50 | float fValue; 51 | int32_t iValue; 52 | uint8_t cValue[4]; 53 | } data; 54 | }; 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | #endif /* MAIN_H_ */ 61 | -------------------------------------------------------------------------------- /mcuconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006-2013 Giovanni Di Sirio 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | #define STM32F103_MCUCONF 18 | 19 | /* 20 | * STM32F103 drivers configuration. 21 | * The following settings override the default settings present in 22 | * the various device driver implementation headers. 23 | * Note that the settings for each driver only have effect if the whole 24 | * driver is enabled in halconf.h. 25 | * 26 | * IRQ priorities: 27 | * 15...0 Lowest...Highest. 28 | * 29 | * DMA priorities: 30 | * 0...3 Lowest...Highest. 31 | */ 32 | 33 | /* 34 | * HAL driver system settings. 35 | */ 36 | #define STM32_NO_INIT FALSE 37 | #define STM32_HSI_ENABLED FALSE 38 | #define STM32_LSI_ENABLED TRUE 39 | #define STM32_HSE_ENABLED TRUE 40 | #define STM32_LSE_ENABLED TRUE 41 | #define STM32_SW STM32_SW_PLL 42 | #define STM32_PLLSRC STM32_PLLSRC_HSE 43 | #define STM32_PLLXTPRE STM32_PLLXTPRE_DIV1 44 | #define STM32_PLLMUL_VALUE 3 45 | #define STM32_HPRE STM32_HPRE_DIV1 46 | #define STM32_PPRE1 STM32_PPRE1_DIV2 47 | #define STM32_PPRE2 STM32_PPRE2_DIV2 48 | #define STM32_ADCPRE STM32_ADCPRE_DIV4 49 | #define STM32_USB_CLOCK_REQUIRED FALSE 50 | #define STM32_USBPRE STM32_USBPRE_DIV1P5 51 | #define STM32_MCOSEL STM32_MCOSEL_NOCLOCK 52 | #define STM32_RTCSEL STM32_RTCSEL_LSE 53 | #define STM32_PVD_ENABLE FALSE 54 | #define STM32_PLS STM32_PLS_LEV0 55 | 56 | /* 57 | * ADC driver system settings. 58 | */ 59 | #define STM32_ADC_USE_ADC1 FALSE 60 | #define STM32_ADC_ADC1_DMA_PRIORITY 2 61 | #define STM32_ADC_ADC1_IRQ_PRIORITY 6 62 | 63 | /* 64 | * CAN driver system settings. 65 | */ 66 | #define STM32_CAN_USE_CAN1 FALSE 67 | #define STM32_CAN_CAN1_IRQ_PRIORITY 11 68 | 69 | /* 70 | * EXT driver system settings. 71 | */ 72 | #define STM32_EXT_EXTI0_IRQ_PRIORITY 6 73 | #define STM32_EXT_EXTI1_IRQ_PRIORITY 6 74 | #define STM32_EXT_EXTI2_IRQ_PRIORITY 6 75 | #define STM32_EXT_EXTI3_IRQ_PRIORITY 6 76 | #define STM32_EXT_EXTI4_IRQ_PRIORITY 6 77 | #define STM32_EXT_EXTI5_9_IRQ_PRIORITY 6 78 | #define STM32_EXT_EXTI10_15_IRQ_PRIORITY 6 79 | #define STM32_EXT_EXTI16_IRQ_PRIORITY 6 80 | #define STM32_EXT_EXTI17_IRQ_PRIORITY 6 81 | #define STM32_EXT_EXTI18_IRQ_PRIORITY 6 82 | #define STM32_EXT_EXTI19_IRQ_PRIORITY 6 83 | 84 | /* 85 | * GPT driver system settings. 86 | */ 87 | #define STM32_GPT_USE_TIM1 FALSE 88 | #define STM32_GPT_USE_TIM2 FALSE 89 | #define STM32_GPT_USE_TIM3 FALSE 90 | #define STM32_GPT_USE_TIM4 FALSE 91 | #define STM32_GPT_USE_TIM5 FALSE 92 | #define STM32_GPT_USE_TIM8 FALSE 93 | #define STM32_GPT_TIM1_IRQ_PRIORITY 7 94 | #define STM32_GPT_TIM2_IRQ_PRIORITY 7 95 | #define STM32_GPT_TIM3_IRQ_PRIORITY 7 96 | #define STM32_GPT_TIM4_IRQ_PRIORITY 7 97 | #define STM32_GPT_TIM5_IRQ_PRIORITY 7 98 | #define STM32_GPT_TIM8_IRQ_PRIORITY 7 99 | 100 | /* 101 | * I2C driver system settings. 102 | */ 103 | #define STM32_I2C_USE_I2C1 TRUE 104 | #define STM32_I2C_USE_I2C2 FALSE 105 | #define STM32_I2C_I2C1_IRQ_PRIORITY 5 106 | #define STM32_I2C_I2C2_IRQ_PRIORITY 5 107 | #define STM32_I2C_I2C1_DMA_PRIORITY 3 108 | #define STM32_I2C_I2C2_DMA_PRIORITY 3 109 | #define STM32_I2C_I2C1_DMA_ERROR_HOOK() chSysHalt() 110 | #define STM32_I2C_I2C2_DMA_ERROR_HOOK() chSysHalt() 111 | 112 | /* 113 | * ICU driver system settings. 114 | */ 115 | #define STM32_ICU_USE_TIM1 FALSE 116 | #define STM32_ICU_USE_TIM2 TRUE 117 | #define STM32_ICU_USE_TIM3 FALSE 118 | #define STM32_ICU_USE_TIM4 FALSE 119 | #define STM32_ICU_USE_TIM5 FALSE 120 | #define STM32_ICU_USE_TIM8 FALSE 121 | #define STM32_ICU_TIM1_IRQ_PRIORITY 7 122 | #define STM32_ICU_TIM2_IRQ_PRIORITY 7 123 | #define STM32_ICU_TIM3_IRQ_PRIORITY 7 124 | #define STM32_ICU_TIM4_IRQ_PRIORITY 7 125 | #define STM32_ICU_TIM5_IRQ_PRIORITY 7 126 | #define STM32_ICU_TIM8_IRQ_PRIORITY 7 127 | 128 | /* 129 | * PWM driver system settings. 130 | */ 131 | #define STM32_PWM_USE_ADVANCED FALSE 132 | #define STM32_PWM_USE_TIM1 FALSE 133 | #define STM32_PWM_USE_TIM2 FALSE 134 | #define STM32_PWM_USE_TIM3 FALSE 135 | #define STM32_PWM_USE_TIM4 FALSE 136 | #define STM32_PWM_USE_TIM5 FALSE 137 | #define STM32_PWM_USE_TIM8 FALSE 138 | #define STM32_PWM_TIM1_IRQ_PRIORITY 7 139 | #define STM32_PWM_TIM2_IRQ_PRIORITY 7 140 | #define STM32_PWM_TIM3_IRQ_PRIORITY 7 141 | #define STM32_PWM_TIM4_IRQ_PRIORITY 7 142 | #define STM32_PWM_TIM5_IRQ_PRIORITY 7 143 | #define STM32_PWM_TIM8_IRQ_PRIORITY 7 144 | 145 | /* 146 | * RTC driver system settings. 147 | */ 148 | #define STM32_RTC_IRQ_PRIORITY 15 149 | 150 | /* 151 | * SERIAL driver system settings. 152 | */ 153 | #define STM32_SERIAL_USE_USART1 FALSE 154 | #define STM32_SERIAL_USE_USART2 TRUE 155 | #define STM32_SERIAL_USE_USART3 FALSE 156 | #define STM32_SERIAL_USE_UART4 FALSE 157 | #define STM32_SERIAL_USE_UART5 FALSE 158 | #define STM32_SERIAL_USART1_PRIORITY 12 159 | #define STM32_SERIAL_USART2_PRIORITY 12 160 | #define STM32_SERIAL_USART3_PRIORITY 12 161 | #define STM32_SERIAL_UART4_PRIORITY 12 162 | #define STM32_SERIAL_UART5_PRIORITY 12 163 | 164 | /* 165 | * SPI driver system settings. 166 | */ 167 | #define STM32_SPI_USE_SPI1 TRUE 168 | #define STM32_SPI_USE_SPI2 FALSE 169 | #define STM32_SPI_USE_SPI3 FALSE 170 | #define STM32_SPI_SPI1_DMA_PRIORITY 1 171 | #define STM32_SPI_SPI2_DMA_PRIORITY 1 172 | #define STM32_SPI_SPI3_DMA_PRIORITY 1 173 | #define STM32_SPI_SPI1_IRQ_PRIORITY 10 174 | #define STM32_SPI_SPI2_IRQ_PRIORITY 10 175 | #define STM32_SPI_SPI3_IRQ_PRIORITY 10 176 | #define STM32_SPI_DMA_ERROR_HOOK(spip) chSysHalt() 177 | 178 | /* 179 | * UART driver system settings. 180 | */ 181 | #define STM32_UART_USE_USART1 TRUE 182 | #define STM32_UART_USE_USART2 FALSE 183 | #define STM32_UART_USE_USART3 FALSE 184 | #define STM32_UART_USART1_IRQ_PRIORITY 12 185 | #define STM32_UART_USART2_IRQ_PRIORITY 12 186 | #define STM32_UART_USART3_IRQ_PRIORITY 12 187 | #define STM32_UART_USART1_DMA_PRIORITY 0 188 | #define STM32_UART_USART2_DMA_PRIORITY 0 189 | #define STM32_UART_USART3_DMA_PRIORITY 0 190 | #define STM32_UART_DMA_ERROR_HOOK(uartp) chSysHalt() 191 | 192 | /* 193 | * USB driver system settings. 194 | */ 195 | #define STM32_USB_USE_USB1 FALSE 196 | #define STM32_USB_LOW_POWER_ON_SUSPEND TRUE 197 | #define STM32_USB_USB1_HP_IRQ_PRIORITY 13 198 | #define STM32_USB_USB1_LP_IRQ_PRIORITY 14 199 | 200 | -------------------------------------------------------------------------------- /nrf24l01.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 3 | 2011,2012 Giovanni Di Sirio. 4 | 5 | This file is part of ChibiOS/RT. 6 | 7 | ChibiOS/RT is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | ChibiOS/RT is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | 20 | --- 21 | 22 | A special exception to the GPL can be applied should you wish to distribute 23 | a combined work that includes ChibiOS/RT, without being obliged to provide 24 | the source code for any proprietary components. See the file exception.txt 25 | for full details of how and when the exception can be applied. 26 | */ 27 | 28 | #define CHANNEL 0 29 | 30 | /* 31 | * The number of bytes the NRF24L01 RX FIFO is going to hold 32 | * This can be 32 bytes MAX 33 | */ 34 | #define NRF_FIFO_BYTES 16 35 | 36 | /* 37 | * Define IRQ an CE PORT/PAD 38 | * Make sure to setup the IRQ pad with the EXT driver as well 39 | */ 40 | #define NRF_PORT_CE_IRQ GPIOB 41 | #define NRF_PORT_IRQ 9 42 | #define NRF_PORT_CE 8 43 | 44 | /** 45 | * @name NRF status flags 46 | * @{ 47 | */ 48 | #define NRF_TX_NO_ERROR 0 /**< @brief No pending conditions. */ 49 | #define NRF_TX_OVERRUN_ERROR 2 /**< @brief Overflow happened. */ 50 | #define NRF_TRANSMIT_ERROR 4 /**< @brief Transmission error. */ 51 | /** @} */ 52 | 53 | /** 54 | * @brief Driver state machine possible states. 55 | */ 56 | typedef enum { 57 | NRF_UNINIT = 0, /**< Not initialized. */ 58 | NRF_STOP = 1, /**< Stopped. */ 59 | NRF_READY = 2 /**< Ready. */ 60 | } nrfstate_t; 61 | 62 | /** 63 | * @brief Transmitter state machine states. 64 | */ 65 | typedef enum { 66 | NRF_TX_IDLE = 0, /**< Not transmitting. */ 67 | NRF_TX_ACTIVE = 1, /**< Transmitting. */ 68 | NRF_TX_COMPLETE = 2 /**< Buffer complete. */ 69 | } nrftxstate_t; 70 | 71 | /** 72 | * @brief Receiver state machine states. 73 | */ 74 | typedef enum { 75 | NRF_RX_IDLE = 0, /**< Not receiving. */ 76 | NRF_RX_ACTIVE = 1, /**< Receiving. */ 77 | NRF_RX_COMPLETE = 2 /**< Buffer complete. */ 78 | } nrfrxstate_t; 79 | 80 | /** 81 | * @brief NRF driver condition flags type. 82 | */ 83 | typedef uint8_t nrfflags_t; 84 | 85 | typedef struct _NRFD NRFD; 86 | struct _NRFD { 87 | /** 88 | * @brief Driver state. 89 | */ 90 | volatile nrfstate_t state; 91 | /** 92 | * @brief Transmitter state. 93 | */ 94 | volatile nrftxstate_t txstate; 95 | /** 96 | * @brief Receiver state. 97 | */ 98 | volatile nrfrxstate_t rxstate; 99 | /** 100 | * @brief NRF driver condition flags type. 101 | */ 102 | volatile nrfflags_t flags; 103 | /* 104 | * Binary semaphore, to lock access to the send and receive queue of the NRF24L01 105 | */ 106 | BinarySemaphore NRFSemIRQ; 107 | BinarySemaphore NRFSemRX; 108 | BinarySemaphore NRFSemTX; 109 | }; 110 | 111 | extern NRFD nrf; 112 | 113 | /* 114 | * Initialize the NRF24L01 Wifi chip. 115 | */ 116 | void NRFInit(void); 117 | 118 | /* 119 | * Set channel 120 | * Frequency is F0= 2400 + RF_CH [MHz] 121 | */ 122 | void NRFSetChannel(uint8_t chan); 123 | 124 | /* 125 | * Handle the IRQ signal, unlock the Semaphores or set flags. 126 | */ 127 | void NRFHandleIrq(void); 128 | 129 | /* 130 | * NRF24L01 test 131 | */ 132 | void NRFtest(void); 133 | 134 | /* 135 | * Function to send data 136 | * This functions blocks until data is available 137 | * The send output buffer needs to be NRF_FIFO_BYTES(32) bytes wide 138 | */ 139 | bool_t NRFSendData(uint8_t *inBuf); 140 | 141 | /* 142 | * Routine to unlock IRQ handling. 143 | */ 144 | void NRFReportIRQ(void); 145 | 146 | /* 147 | * Test if there is a carrier signal active on the channel 148 | * When present return true 149 | */ 150 | uint8_t NRFCarrier(void); 151 | 152 | /* 153 | * Function to receive data from FIFO 154 | * This functions blocks until data is available 155 | * The output buffer needs to be NRF_FIFO_BYTES(32) bytes wide 156 | */ 157 | void NRFReceiveData(uint8_t *pipeNr, uint8_t *outBuf); 158 | 159 | /* 160 | * Set the address to the receiver pipe 161 | * Normaly pipe is used to receive the ack packets by shockburst 162 | * Use pipe 1 as the first data receive pipe 163 | * @Arguments 164 | * pipe Pipe number to set the address to 165 | * addr_size The size of the address in bytes 166 | * addr Byte array holding the addr, LSB first 167 | */ 168 | void NRFSetRecvAddr(uint8_t pipe, uint8_t addr[], uint8_t addrSize); 169 | 170 | 171 | /* 172 | * Set the address to the receiver pipe 173 | * The receive address of pipe 0 is set as well, to enable auto ACK handling 174 | * @Arguments 175 | * pipe Pipe number to set the address to 176 | * addr_size The size of the address in bytes 177 | * addr Byte array holding the address, LSB first 178 | */ 179 | void NRFSetSendAddr(uint8_t addr[], uint8_t addrSize); 180 | 181 | void NRFPWRDown(void); 182 | void NRFPWRUp(void); 183 | void NRFGetAddrs(uint8_t *txaddr, uint8_t *rxaddr); 184 | uint8_t NRFChannelScan(uint8_t chan); 185 | 186 | /* 187 | * NRF thread 188 | */ 189 | #define NRF_WA_SIZE 256 190 | extern WORKING_AREA(NRFThreadWA, NRF_WA_SIZE); 191 | extern msg_t NRFThread(void *arg); 192 | -------------------------------------------------------------------------------- /nrf_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 3 | 2011,2012 Giovanni Di Sirio. 4 | 5 | This file is part of ChibiOS/RT. 6 | 7 | ChibiOS/RT is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | ChibiOS/RT is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | 20 | --- 21 | 22 | A special exception to the GPL can be applied should you wish to distribute 23 | a combined work that includes ChibiOS/RT, without being obliged to provide 24 | the source code for any proprietary components. See the file exception.txt 25 | for full details of how and when the exception can be applied. 26 | */ 27 | 28 | #include "ch.h" 29 | #include "hal.h" 30 | 31 | #include "nrf_spi.h" 32 | 33 | #include 34 | 35 | /* 36 | * SPI speed definitions. 37 | */ 38 | #define SPI_DIV2 0 39 | #define SPI_DIV4 (SPI_CR1_BR_0) 40 | #define SPI_DIV8 (SPI_CR1_BR_1) 41 | #define SPI_DIV16 (SPI_CR1_BR_1 | SPI_CR1_BR_0) 42 | #define SPI_DIV32 (SPI_CR1_BR_2) 43 | #define SPI_DIV64 (SPI_CR1_BR_2 | SPI_CR1_BR_0) 44 | 45 | #define HIGHSPEED_SPI_DIV SPI_DIV2 46 | 47 | /* 48 | * Mutex to lock output buffer 49 | */ 50 | static Mutex SPIMtx; /* Mutex */ 51 | 52 | /* 53 | * SPI configuration structure. 54 | */ 55 | static const SPIConfig hs_spicfg = {NULL, GPIOA, GPIOA_PIN4, SPI_DIV2}; 56 | 57 | /* 58 | * Initialize the SPI interface 59 | */ 60 | void SPIInit(void) 61 | { 62 | /* 63 | * SPI1 I/O pins setup. 64 | */ 65 | palSetPadMode(GPIOA, GPIOA_PIN5, PAL_MODE_STM32_ALTERNATE_PUSHPULL); /* SCK. */ 66 | palSetPadMode(GPIOA, GPIOA_PIN6, PAL_MODE_STM32_ALTERNATE_PUSHPULL); /* MISO.*/ 67 | palSetPadMode(GPIOA, GPIOA_PIN7, PAL_MODE_STM32_ALTERNATE_PUSHPULL); /* MOSI.*/ 68 | palSetPadMode(GPIOA, GPIOA_PIN4, PAL_MODE_OUTPUT_PUSHPULL); 69 | palSetPad(GPIOA, GPIOA_PIN4); 70 | 71 | /* 72 | * Initialize Mutex 73 | */ 74 | chMtxInit(&SPIMtx); /* Mutex initialization before use */ 75 | } 76 | 77 | /* 78 | * SPI bus exchange routine 79 | */ 80 | int SPIExchangeData(SPIDriver *spip, uint8_t *tx, uint8_t *rx, size_t size) { 81 | chMtxLock(&SPIMtx); 82 | 83 | /* 84 | * Do exchange between device and MCU. 85 | */ 86 | spiAcquireBus(spip); /* Acquire ownership of the bus. */ 87 | spiStart(spip, &hs_spicfg); /* Setup transfer parameters. */ 88 | spiSelect(spip); /* Slave Select assertion. */ 89 | spiExchange(spip, size, tx, rx); /* Atomic transfer operations. */ 90 | spiUnselect(spip); /* Slave Select de-assertion. */ 91 | spiReleaseBus(spip); /* Ownership release. */ 92 | 93 | chMtxUnlock(); 94 | 95 | return 0; 96 | } 97 | 98 | /* 99 | * SPI bus send routine 100 | */ 101 | int SPISendData(SPIDriver *spip, uint8_t *tx, size_t size) { 102 | 103 | chMtxLock(&SPIMtx); 104 | 105 | /* 106 | * Do exchange between device and MCU. 107 | */ 108 | spiAcquireBus(spip); /* Acquire ownership of the bus. */ 109 | spiStart(spip, &hs_spicfg); /* Setup transfer parameters. */ 110 | spiSelect(spip); /* Slave Select assertion. */ 111 | spiSend(spip, size, tx); /* Send command */ 112 | spiUnselect(spip); /* Slave Select de-assertion. */ 113 | spiReleaseBus(spip); /* Ownership release. */ 114 | 115 | chMtxUnlock(); 116 | 117 | return 0; 118 | } 119 | 120 | /* 121 | * SPI bus receive routine 122 | */ 123 | int SPIReceiveData(SPIDriver *spip, uint8_t *rx, size_t size) { 124 | 125 | chMtxLock(&SPIMtx); 126 | 127 | /* 128 | * Do exchange between device and MCU. 129 | */ 130 | spiAcquireBus(spip); /* Acquire ownership of the bus. */ 131 | spiStart(spip, &hs_spicfg); /* Setup transfer parameters. */ 132 | spiSelect(spip); /* Slave Select assertion. */ 133 | spiReceive(spip, size, rx); 134 | spiUnselect(spip); /* Slave Select de-assertion. */ 135 | spiReleaseBus(spip); /* Ownership release. */ 136 | 137 | chMtxUnlock(); 138 | 139 | return 0; 140 | } 141 | -------------------------------------------------------------------------------- /nrf_spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, 3 | 2011,2012 Giovanni Di Sirio. 4 | 5 | This file is part of ChibiOS/RT. 6 | 7 | ChibiOS/RT is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | ChibiOS/RT is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | 20 | --- 21 | 22 | A special exception to the GPL can be applied should you wish to distribute 23 | a combined work that includes ChibiOS/RT, without being obliged to provide 24 | the source code for any proprietary components. See the file exception.txt 25 | for full details of how and when the exception can be applied. 26 | */ 27 | 28 | /* 29 | * Initialize the SPI interface 30 | */ 31 | void SPIInit(void); 32 | 33 | /* 34 | * SPI bus exchange routine 35 | */ 36 | int SPIExchangeData(SPIDriver *spip, uint8_t *tx, uint8_t *rx, size_t size); 37 | 38 | /* 39 | * SPI bus send routine 40 | */ 41 | int SPISendData(SPIDriver *spip, uint8_t *tx, size_t size); 42 | 43 | /* 44 | * SPI bus receive routine 45 | */ 46 | int SPIReceiveData(SPIDriver *spip, uint8_t *rx, size_t size); 47 | 48 | -------------------------------------------------------------------------------- /oneWire.c: -------------------------------------------------------------------------------- 1 | 2 | #include "ch.h" 3 | #include "hal.h" 4 | #include "oneWire.h" 5 | #include "string.h" 6 | 7 | #define OW_TIMEOUT_MS 10 // break timeout 8 | 9 | static struct UsartDictionnary { 10 | OneWireDriver *drv[1]; 11 | UARTDriver *uart[1]; 12 | } usartDict = { .drv = {NULL}, 13 | .uart = {NULL} 14 | }; 15 | 16 | 17 | 18 | static void oneWireSerialMode (OneWireDriver* drv, SerialMode sm); 19 | static uint8_t oneWireUnpack (uint8_t buffer[8]); 20 | static void oneWirePack (uint8_t cmd, uint8_t buffer[8]); 21 | static uint8_t oneWireNext(OneWireDriver* drv, uint8_t *romBytes, 22 | bool_t conditional); 23 | static uint8_t oneWireFirst(OneWireDriver* drv, uint8_t *romBytes, 24 | bool_t conditional); 25 | static void usartDictionnaryAddPair (OneWireDriver* drv, UARTDriver *uart); 26 | static OneWireDriver* usartDictionnaryGetDriverByUart (UARTDriver *uart); 27 | 28 | 29 | // USART CALLBACK 30 | static void txBufferEmpty(UARTDriver *uartp) ; 31 | static void rxErr(UARTDriver *uartp, uartflags_t e); 32 | static void rxEnd(UARTDriver *uartp); 33 | //static void rxChar(UARTDriver *uartp, uint16_t c); 34 | 35 | 36 | 37 | static const UARTConfig uartCfgReset = { 38 | NULL, 39 | txBufferEmpty, 40 | rxEnd, 41 | NULL, // rxChar, 42 | rxErr, 43 | 9600, 44 | 0, 45 | 0, 46 | USART_CR3_HDSEL // half duplex mode 47 | }; 48 | 49 | static const UARTConfig uartCfgTransfert = { 50 | NULL, 51 | txBufferEmpty, 52 | rxEnd, 53 | NULL, //rxChar, 54 | rxErr, 55 | 115200, 56 | 0, 57 | 0, 58 | USART_CR3_HDSEL // half duplex mode 59 | }; 60 | 61 | static const uint8_t dscrc_table[] = { 62 | 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, 63 | 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, 64 | 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, 65 | 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, 66 | 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, 67 | 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, 68 | 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, 69 | 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, 70 | 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, 71 | 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, 72 | 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, 73 | 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, 74 | 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, 75 | 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, 76 | 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, 77 | 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; 78 | 79 | 80 | static const uint8_t owBufferWrite[] = { 81 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 82 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 83 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 84 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 85 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 86 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 87 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 88 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 89 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 90 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 91 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 92 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 93 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 94 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 95 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 96 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 97 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 98 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 99 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 100 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 101 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 102 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 103 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 104 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 105 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 106 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 107 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 108 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 109 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 110 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 111 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 112 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 113 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 114 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 115 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 116 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 117 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 118 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 119 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 120 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 121 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 122 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 123 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 124 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 125 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 126 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 127 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 128 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 129 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 130 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 131 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,0xff, 0xff, 132 | 0xff, 0xff 133 | }; 134 | 135 | 136 | void oneWireInit (OneWireDriver* drv, const OneWireConfig *cfg) 137 | { 138 | memcpy (&(drv->config), cfg, sizeof (OneWireConfig)); 139 | oneWireSerialMode (drv, ModeGpioIn); 140 | chBSemInit (&(drv->semSent), TRUE); 141 | chBSemInit (&(drv->semReceive), TRUE); 142 | chMtxInit (&(drv->acquireLock)); 143 | drv->lastDiscrep = 0; 144 | drv->doneFlag = FALSE; 145 | usartDictionnaryAddPair (drv, cfg->uartd); 146 | } 147 | 148 | #define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0])) 149 | 150 | 151 | bool_t oneWireReset (OneWireDriver* drv) 152 | { 153 | uint8_t owPresence; 154 | const uint8_t resetByte = 0xf0; 155 | 156 | oneWireSerialMode (drv, ModeSerialReset); 157 | 158 | chBSemReset(&(drv->semSent), TRUE); 159 | chBSemReset(&(drv->semReceive), TRUE); 160 | uartStartReceive (drv->config.uartd, 1 , (void *) &owPresence); 161 | uartStartSend (drv->config.uartd, 1, &resetByte); 162 | if (chBSemWaitTimeout(&(drv->semSent), MS2ST(OW_TIMEOUT_MS)) == RDY_TIMEOUT){ 163 | return FALSE; 164 | } 165 | if (chBSemWaitTimeout(&(drv->semReceive), MS2ST(OW_TIMEOUT_MS)) == RDY_TIMEOUT){ 166 | return FALSE; 167 | } 168 | 169 | oneWireSerialMode (drv, ModeSerialTransfert); 170 | 171 | return (owPresence != resetByte); 172 | } 173 | 174 | 175 | void oneWireSendByte (OneWireDriver* drv, uint8_t command) 176 | { 177 | oneWireSend (drv, &command, 1); 178 | } 179 | 180 | uint8_t oneWireReceiveByte (OneWireDriver* drv) 181 | { 182 | uint8_t buf; 183 | oneWireReceive (drv, &buf, 1); 184 | 185 | return buf; 186 | } 187 | 188 | 189 | void oneWireSendBit (OneWireDriver* drv, bool_t bit) 190 | { 191 | uint8_t bitBuf; 192 | bitBuf = bit ? 0xff : 0x00; 193 | 194 | chBSemReset(&(drv->semSent), TRUE); 195 | uartStartSend (drv->config.uartd, 1, &bitBuf); 196 | chBSemWait (&(drv->semSent)); 197 | 198 | } 199 | 200 | 201 | 202 | bool_t oneWireSend (OneWireDriver* drv, const uint8_t *command, uint8_t len) 203 | { 204 | const uint32_t owLen = len*8; 205 | uint8_t cmdBuf[owLen]; 206 | 207 | for (uint32_t i=0; isemSent), TRUE); 212 | uartStartSend (drv->config.uartd, owLen, &cmdBuf); 213 | if (chBSemWaitTimeout(&(drv->semSent), MS2ST(OW_TIMEOUT_MS)) == RDY_TIMEOUT){ 214 | return FALSE; 215 | } 216 | 217 | return TRUE; 218 | } 219 | 220 | bool_t oneWireReceive (OneWireDriver* drv, uint8_t *buffer, uint8_t len) 221 | { 222 | const uint32_t owLen = len*8; 223 | uint8_t owBufferRead[owLen]; 224 | 225 | if (owLen > sizeof (owBufferWrite)) { 226 | return FALSE; 227 | } 228 | chBSemReset(&(drv->semReceive), TRUE); 229 | uartStartReceive (drv->config.uartd, owLen , (void *) owBufferRead); 230 | chBSemReset(&(drv->semSent), TRUE); 231 | uartStartSend (drv->config.uartd, owLen, (void *) owBufferWrite); 232 | if (chBSemWaitTimeout(&(drv->semSent), MS2ST(OW_TIMEOUT_MS)) == RDY_TIMEOUT){ 233 | return FALSE; 234 | } 235 | if (chBSemWaitTimeout(&(drv->semReceive), MS2ST(OW_TIMEOUT_MS)) == RDY_TIMEOUT){ 236 | return FALSE; 237 | } 238 | 239 | for (uint32_t i=0; isemReceive), TRUE); 252 | uartStartReceive (drv->config.uartd, 1 , (void *) &rec); 253 | chBSemReset(&(drv->semSent), TRUE); 254 | uartStartSend (drv->config.uartd, 1, (void *) owBufferWrite); 255 | if (chBSemWaitTimeout(&(drv->semSent), MS2ST(OW_TIMEOUT_MS)) == RDY_TIMEOUT){ 256 | return FALSE; 257 | } 258 | if (chBSemWaitTimeout(&(drv->semReceive), MS2ST(OW_TIMEOUT_MS)) == RDY_TIMEOUT){ 259 | return FALSE; 260 | } 261 | 262 | return (rec == 0xff); 263 | } 264 | 265 | bool_t oneWireReadRom (OneWireDriver* drv, OneWireRomAddress *rom) 266 | { 267 | oneWireReset (drv); 268 | oneWireSendByte (drv, 0x33); 269 | oneWireReceive (drv, rom->addr, sizeof (rom->addr)); 270 | // uint8_t crc = oneWireCrc8(rom->addr, 7); 271 | uint8_t crc = owCrc8(rom->addr, 7); 272 | if (crc != rom->addr[7]) { 273 | return FALSE; 274 | } else { 275 | return TRUE; 276 | } 277 | } 278 | 279 | 280 | 281 | 282 | uint8_t oneWireSearchRom (OneWireDriver* drv, bool_t conditional, 283 | OneWireRomAddress *addrs, uint8_t len) 284 | { 285 | uint8_t m, cont = 0; 286 | uint8_t romBytes[8] = {0,0,0,0,0,0,0,0}; 287 | 288 | oneWireAcquireBus (drv); 289 | if(oneWireReset(drv)) { 290 | if(oneWireFirst(drv, romBytes, conditional)) { 291 | // Begins when at least one part found 292 | uint8_t numROMs = 0; 293 | do { 294 | cont++; 295 | for (m=0;m<8;m++) { 296 | addrs[numROMs].addr[m] = romBytes[m]; 297 | } 298 | numROMs++; // Continues until no additional 299 | } while ((numROMs < len) && oneWireNext(drv, romBytes, conditional)); 300 | 301 | while (numROMs < len) { 302 | for (m=0;m<8;m++) { 303 | addrs[numROMs].addr[m] = 0; 304 | } 305 | numROMs++; 306 | } 307 | } 308 | } 309 | oneWireRealeaseBus (); 310 | return cont; 311 | } 312 | 313 | 314 | /*uint8_t oneWireCrc8( uint8_t *addr, uint8_t len) 315 | { 316 | uint8_t crc = 0; 317 | 318 | while (len--) { 319 | crc = dscrc_table[crc ^ *addr++]; 320 | } 321 | return crc; 322 | }*/ 323 | 324 | uint8_t crcDS(uint8_t inp, uint8_t crc) { 325 | inp ^= crc; 326 | crc = 0; 327 | if(inp & 0x1) crc ^= 0x5e; 328 | if(inp & 0x2) crc ^= 0xbc; 329 | if(inp & 0x4) crc ^= 0x61; 330 | if(inp & 0x8) crc ^= 0xc2; 331 | if(inp & 0x10) crc ^= 0x9d; 332 | if(inp & 0x20) crc ^= 0x23; 333 | if(inp & 0x40) crc ^= 0x46; 334 | if(inp & 0x80) crc ^= 0x8c; 335 | return crc; 336 | } 337 | 338 | uint8_t owCrc8(uint8_t *addr, uint8_t len) { 339 | uint8_t crc = 0; 340 | while (len--) { 341 | crc = crcDS(*addr++, crc); 342 | } 343 | return crc; 344 | } 345 | 346 | void oneWireAcquireBus (OneWireDriver* drv) 347 | { 348 | chMtxLock (&(drv->acquireLock)); 349 | } 350 | 351 | void oneWireRealeaseBus (void) 352 | { 353 | chMtxUnlock (); 354 | } 355 | 356 | /* 357 | # _ __ _ _ 358 | # | '_ \ (_) | | 359 | # | |_) | _ __ _ __ __ __ _ | |_ ___ 360 | # | .__/ | '__| | | \ \ / / / _` | | __| / _ \ 361 | # | | | | | | \ V / | (_| | \ |_ | __/ 362 | # |_| |_| |_| \_/ \__,_| \__| \___| 363 | */ 364 | 365 | 366 | static void oneWirePack (uint8_t cmd, uint8_t buffer[8]) 367 | { 368 | for (uint32_t i=0; i<8; i++) { 369 | buffer[i] = (cmd & (1 << i)) ? 0xff : 0x00; 370 | } 371 | } 372 | 373 | static uint8_t oneWireUnpack (uint8_t buffer[8]) 374 | { 375 | uint8_t res = 0; 376 | 377 | for (uint32_t i=0; i<8; i++) { 378 | if (buffer[i] == 0xff) { 379 | res |= (1 << i); 380 | } 381 | } 382 | 383 | return res; 384 | } 385 | 386 | static void oneWireSerialMode (OneWireDriver* drv, SerialMode sm) 387 | { 388 | /* for STM32F4DISCOVERY 389 | * const uint32_t modeTx = 390 | PAL_MODE_ALTERNATE(drv->config.dqAlternate) | PAL_STM32_OTYPE_OPENDRAIN 391 | | PAL_MODE_INPUT_PULLUP | PAL_STM32_OSPEED_HIGHEST | PAL_STM32_MODE_ALTERNATE; 392 | */ 393 | // for STM32F103 394 | const uint32_t modeTx = PAL_MODE_STM32_ALTERNATE_OPENDRAIN; 395 | 396 | if (sm == drv->currentSm) 397 | return; 398 | 399 | switch (sm) { 400 | case ModeGpioIn: 401 | uartStop (drv->config.uartd); 402 | palSetPadMode (drv->config.dqPort, drv->config.dqPad, PAL_MODE_INPUT_PULLUP); 403 | break; 404 | 405 | case ModeSerialReset: 406 | // uartStop (drv->config.uartd); 407 | uartStart(drv->config.uartd, &uartCfgReset); 408 | 409 | palSetPadMode (drv->config.dqPort, drv->config.dqPad, modeTx); 410 | break; 411 | 412 | case ModeSerialTransfert: 413 | // uartStop (drv->config.uartd); 414 | uartStart(drv->config.uartd, &uartCfgTransfert); 415 | 416 | palSetPadMode (drv->config.dqPort, drv->config.dqPad, modeTx); 417 | break; 418 | } 419 | drv->currentSm = sm; 420 | } 421 | 422 | 423 | 424 | static void txBufferEmpty(UARTDriver *uartp) 425 | { 426 | (void) uartp; 427 | OneWireDriver *drv = usartDictionnaryGetDriverByUart (uartp); 428 | if (drv != NULL) { 429 | chSysLockFromIsr(); 430 | chBSemSignalI(&(drv->semSent)); 431 | chSysUnlockFromIsr(); 432 | } 433 | } 434 | 435 | static void rxErr(UARTDriver *uartp, uartflags_t e) 436 | { 437 | (void) uartp; 438 | (void) e; 439 | } 440 | 441 | 442 | static void rxEnd(UARTDriver *uartp) 443 | { 444 | (void) uartp; 445 | OneWireDriver *drv = usartDictionnaryGetDriverByUart (uartp); 446 | if (drv != NULL) { 447 | chSysLockFromIsr(); 448 | chBSemSignalI(&(drv->semReceive)); 449 | chSysUnlockFromIsr(); 450 | } 451 | } 452 | 453 | /* static void rxChar(UARTDriver *uartp, uint16_t c) */ 454 | /* { */ 455 | /* (void) uartp; */ 456 | /* (void) c; */ 457 | /* } */ 458 | 459 | 460 | static uint8_t oneWireFirst (OneWireDriver* drv, uint8_t *romBytes, 461 | bool_t conditional) 462 | { 463 | drv->lastDiscrep = 0; 464 | drv->doneFlag = FALSE; 465 | // Call Next and return it's return value; 466 | return oneWireNext(drv, romBytes, conditional); 467 | } 468 | 469 | 470 | 471 | static uint8_t oneWireNext (OneWireDriver* drv, uint8_t *romBytes, 472 | bool_t conditional) 473 | { 474 | uint8_t m = 1; // ROM Bit index 475 | uint8_t n = 0; // ROM Byte index 476 | uint8_t k = 1; // Bit mask 477 | uint8_t x = 0; 478 | uint8_t discrepMarker = 0; 479 | uint8_t g=0; // Output bit 480 | uint8_t nxt=0; // Return value 481 | short flag=0; 482 | static uint8_t dowcrc; 483 | 484 | nxt = FALSE; // Reset next flag to false 485 | dowcrc = 0; // Reset the dowcrc 486 | flag = !oneWireReset(drv); 487 | 488 | if (flag||drv->doneFlag) // If no parts return false 489 | { 490 | drv->lastDiscrep = 0; // Reset the search 491 | return FALSE; 492 | } 493 | 494 | // Send SearchROM or Conditional Search Rom command 495 | oneWireSendByte(drv, conditional ? 0xEC : 0xF0); 496 | do 497 | { 498 | x = 0; 499 | if (oneWireReceiveBit(drv) == 1) 500 | x = 2; 501 | if (oneWireReceiveBit(drv) == 1) 502 | x |= 1; // And it's complement 503 | if (x == 3) // There are no devices on the one wire bus 504 | break; 505 | else 506 | { 507 | if (x > 0) // All devices coupled have 0 or 1 508 | g = x >> 1; // Bit write value for search 509 | 510 | // If this discrepancy is before the last discrepancy on a previous 511 | // Next then pick the same as last time. 512 | else 513 | { 514 | if (m < drv->lastDiscrep) 515 | g = ((romBytes[n] & k) > 0); 516 | // If equal to last pick 1 517 | else 518 | g = (m == drv->lastDiscrep); // If not then pick 0 519 | 520 | // If 0 was picked then record position with mask k 521 | if (g == 0) discrepMarker = m; 522 | } 523 | 524 | // Isolate bit in ROM[n] with mask k 525 | if (g == 1) romBytes[n] |= k; 526 | else romBytes[n] &= ~k; 527 | 528 | oneWireSendBit(drv, g); // ROM search write 529 | 530 | m++; // Increment bit counter m 531 | k = k << 1; // and shift the bit mask k 532 | // If the mask is 0 then go to new ROM 533 | if (k == 0) 534 | { // Byte n and reset mask 535 | // dowcrc = dscrc_table[dowcrc ^ romBytes[n]]; // Accumulate the crc 536 | dowcrc = crcDS(romBytes[n], dowcrc); 537 | n++; 538 | k++; 539 | } 540 | } 541 | } while (n < 8); // Loop through until through all ROM bytes 0-7 542 | 543 | if (m < (65||dowcrc)) // If search was unsuccessful then 544 | drv->lastDiscrep = 0; // reset the last Discrepancy to zero 545 | else // Search was successful, so set lastDiscrep, lastOne, nxt 546 | { 547 | drv->lastDiscrep = discrepMarker; 548 | drv->doneFlag = (drv->lastDiscrep == 0); 549 | nxt = TRUE; // Indicates search not yet complete, more parts remain 550 | } 551 | 552 | return nxt; 553 | } 554 | 555 | static void usartDictionnaryAddPair (OneWireDriver* drv, UARTDriver *uart) 556 | { 557 | uint8_t i = 0; 558 | 559 | while (i++ < ARRAY_LEN (usartDict.drv)) { 560 | if (usartDict.drv[i] == drv) { 561 | usartDict.uart[i] = uart; 562 | return; 563 | } 564 | } 565 | 566 | i = 0; 567 | while (i < ARRAY_LEN (usartDict.drv) && (usartDict.drv[i] != NULL)) { 568 | i++; 569 | } 570 | 571 | if (i < ARRAY_LEN (usartDict.drv)) { 572 | usartDict.drv[i] = drv; 573 | usartDict.uart[i] = uart; 574 | } 575 | } 576 | 577 | static OneWireDriver* usartDictionnaryGetDriverByUart (UARTDriver *uart) 578 | { 579 | uint8_t i = 0; 580 | while ((i < ARRAY_LEN (usartDict.drv) && usartDict.uart[i] != uart)) { 581 | i++; 582 | } 583 | if (i < ARRAY_LEN (usartDict.drv)) { 584 | return usartDict.drv[i]; 585 | } else { 586 | return NULL; 587 | } 588 | } 589 | -------------------------------------------------------------------------------- /oneWire.h: -------------------------------------------------------------------------------- 1 | #ifndef __ONE_WIRE_H__ 2 | #define __ONE_WIRE_H__ 3 | #include "ch.h" 4 | #include "hal.h" 5 | 6 | /* 7 | This is a library for OneWire Master bus http://en.wikipedia.org/wiki/1-Wire 8 | based on advices found on dallas documentation : 9 | http://www.maximintegrated.com/app-notes/index.mvp/id/214 10 | this library use an usart to avoid to consume cpu cycle in bit banging 11 | 12 | the library is synchronous, but when waiting it yield the processor to chibios. 13 | 14 | Alexandre Bustico 15 | alexandre.bustico@enac.fr 16 | 17 | TODO : envoyer les 0xff depuis la flash pour economiser de la stack 18 | port discovery 19 | temperature en asynchrone sur plusieurs capteurs 20 | 21 | 22 | */ 23 | 24 | 25 | struct OneWireDriver; 26 | typedef struct OneWireDriver OneWireDriver; 27 | 28 | typedef struct { 29 | uint8_t addr[8]; 30 | } OneWireRomAddress; 31 | 32 | typedef struct { 33 | ioportid_t dqPort; // the port for the data IO 34 | uint8_t dqPad; // pad for the data IO, shloud be the tx of an usart 35 | uint8_t dqAlternate; // alternate function, see stm32 ref manuel to find it 36 | UARTDriver *uartd; // Chibios Uart Driver used as oneWire interface 37 | } OneWireConfig; 38 | 39 | 40 | 41 | /* 42 | create OneWireDriver object, initialise UART 43 | */ 44 | void oneWireInit (OneWireDriver* drv, const OneWireConfig *cfg); 45 | 46 | /* 47 | send a reset condition on the OneWire bus to reinitialise all 48 | slave on this bus 49 | */ 50 | bool_t oneWireReset (OneWireDriver* drv); 51 | 52 | 53 | /* 54 | basic io : send/receive bit, byte, buffers 55 | since every OneWire Bit involve uart byte, 56 | oneWireSend need to reserve len*8 bytes on the stack 57 | oneWireReceive need to reserve len*8*2 bytes on the stack 58 | So Stack size should be calculated according to this if you send receive 59 | big bunch of bytes. 60 | */ 61 | bool_t oneWireReceiveBit (OneWireDriver* drv); 62 | void oneWireSendBit (OneWireDriver* drv, bool_t bit); 63 | void oneWireSendByte (OneWireDriver* drv, uint8_t command); 64 | uint8_t oneWireReceiveByte (OneWireDriver* drv); 65 | bool_t oneWireSend (OneWireDriver* drv, const uint8_t *command, uint8_t len); 66 | bool_t oneWireReceive (OneWireDriver* drv, uint8_t *buffer, uint8_t len); 67 | 68 | /* 69 | get rom address of the slave when there is just ONE slave connected 70 | otherwise (multiple slaves connected), use oneWireSearchRom 71 | */ 72 | bool_t oneWireReadRom (OneWireDriver* drv, OneWireRomAddress *addr); 73 | 74 | 75 | /* 76 | get all rom address when multiple slave are connected 77 | depending on conditional value, get All the 78 | slave or just the slave which are in alarm state (cf conditional search) 79 | it's your responsability to give a pointer on an sufficently large 80 | array for all the slave, otherwise you will miss some slave. 81 | */ 82 | uint8_t oneWireSearchRom (OneWireDriver* drv, bool_t conditional, 83 | OneWireRomAddress *addrs, uint8_t len); 84 | 85 | 86 | /* 87 | crc helper function implementing crc8 used bu oneWire slave, to ensure that 88 | the data received are valid 89 | */ 90 | //uint8_t oneWireCrc8( uint8_t *addr, uint8_t len); 91 | 92 | uint8_t owCrc8( uint8_t *addr, uint8_t len); 93 | 94 | /* 95 | If more than one thread would communicate with different slaves, 96 | call to oneWire function should be pritected by these functions 97 | */ 98 | void oneWireAcquireBus (OneWireDriver* drv); 99 | void oneWireRealeaseBus (void); 100 | 101 | 102 | /* 103 | This is private data, for internal library state only 104 | */ 105 | 106 | // Private Data Daclaration 107 | typedef enum {ModeGpioIn, ModeSerialReset, ModeSerialTransfert} SerialMode; 108 | 109 | struct OneWireDriver { 110 | OneWireConfig config; 111 | SerialMode currentSm; 112 | Mutex acquireLock; 113 | BinarySemaphore semSent; 114 | BinarySemaphore semReceive; 115 | uint8_t lastDiscrep ; 116 | bool_t doneFlag ; 117 | }; 118 | 119 | 120 | #endif //__ONE_WIRE_H__ 121 | -------------------------------------------------------------------------------- /owtemp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * owtemp.c - 1-Wire temperature sensor DS1820B driver 3 | * 4 | * Created on: 28.03.2013 5 | * Author: A.Polyakov 6 | */ 7 | 8 | #include "ch.h" 9 | #include "hal.h" 10 | 11 | #include "owtemp.h" 12 | #include "oneWire.h" 13 | #include "ds1820b.h" 14 | 15 | #include 16 | #include 17 | 18 | //#define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0])) 19 | #define OWSCAN_TIMEOUT_MS 250 // задержка сканирования датчиков температуры (мсек) 20 | #define OWTEMPCONV 190 // задержка конвертирования (мсек) для датчиков температуры DS1820B 21 | #define OWTEMPPREC 10 // точность преобразования для датчиков температуры 22 | 23 | static OneWireRomAddress romAddr[OWDEVICES]; 24 | 25 | // признак инициализации oneWire 26 | extern bool_t ow_initialized; 27 | 28 | extern OneWireDriver owDrv; 29 | extern const OneWireConfig owCfg; 30 | extern BinarySemaphore owsem; 31 | 32 | ow_temp_read_t ow_temp_read; // возвращает значения температуры и признак ошибки 33 | static BinarySemaphore owtempsem; 34 | 35 | /* 36 | * Процесс сканирования температурных датчиков DS1820B 37 | */ 38 | static Thread *OWTempThread_p; 39 | static WORKING_AREA(waOWTempThread, 256); 40 | __attribute__((noreturn)) 41 | static msg_t OWTempThread(void *arg) { 42 | (void)arg; 43 | chRegSetThreadName("owTempThd"); 44 | while (TRUE) { 45 | ow_temp_read_t *req; 46 | Thread *tp; 47 | 48 | tp = chMsgWait(); 49 | req = (ow_temp_read_t *) chMsgGet(tp); 50 | chMsgRelease(tp, (msg_t) req); 51 | 52 | req->error = OW_TEMP_NO_ERROR; 53 | 54 | chBSemWait(&owsem); 55 | oneWireSearchRom (&owDrv, FALSE, romAddr, OWDEVICES); 56 | bool_t ow_found = FALSE; 57 | for (uint8_t i=0; iowtemp[i].key[0] = 0x00; 70 | if (romAddr[i].addr[0] == 0x28) { 71 | memcpy(&req->owtemp[i].key,&romAddr[i],8); 72 | req->owtemp[i].value = ds1820BGGetTempFromRam(&owDrv, &(romAddr[i])); 73 | } 74 | } 75 | chBSemSignal(&owsem); 76 | } 77 | else { 78 | req->error = OW_TEMP_NOT_FOUND; 79 | } 80 | 81 | chBSemSignal(&owtempsem); 82 | }//while 83 | } 84 | 85 | // получает значения с температурных датчиков DS1820B 86 | ow_temp_error_t owtemp_read(void) { 87 | ow_temp_read_t *ow_temp_read_p = &ow_temp_read; 88 | 89 | chBSemWait(&owtempsem); /* to be sure */ 90 | 91 | chMsgSend(OWTempThread_p, (msg_t) ow_temp_read_p); 92 | 93 | /* wait for reply */ 94 | if(chBSemWaitTimeout(&owtempsem, MS2ST(OWSCAN_TIMEOUT_MS)) == RDY_TIMEOUT) { 95 | chBSemReset(&owtempsem, FALSE); 96 | ow_temp_read.error = OW_TEMP_TIMEOUT; 97 | return OW_TEMP_TIMEOUT; 98 | } 99 | chBSemReset(&owtempsem, FALSE); 100 | return ow_temp_read.error; 101 | } 102 | 103 | // создает процесс опроса датчиков DS1820B 104 | void ow_temp_init(void){ 105 | chBSemInit(&owtempsem, FALSE); 106 | oneWireInit(&owDrv,&owCfg); 107 | // Создаем процесс опроса датчиков 1-wire 108 | OWTempThread_p = chThdCreateStatic(waOWTempThread, sizeof(waOWTempThread), OWTEMP_PRIO, OWTempThread, NULL); 109 | } 110 | -------------------------------------------------------------------------------- /owtemp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * owtemp.h 3 | */ 4 | #ifndef OWTEMP_H_ 5 | #define OWTEMP_H_ 6 | 7 | #define OWDEVICES 6 // max 1-wire devices on bus 8 | #define OWTEMP_PRIO NORMALPRIO+1 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif 13 | 14 | typedef struct _ow_temp_t ow_temp_t; // описание датчика температуры DS1820B 15 | struct _ow_temp_t { 16 | uint8_t key[8]; // идентификатор датчика DS1820B 17 | float value; // значение датчика 18 | }; 19 | 20 | typedef enum { 21 | OW_TEMP_UNKNOWN, 22 | OW_TEMP_NO_ERROR, 23 | OW_TEMP_NOT_FOUND, 24 | OW_TEMP_TIMEOUT, 25 | } ow_temp_error_t; 26 | 27 | typedef struct _ow_temp_read_t ow_temp_read_t; 28 | struct _ow_temp_read_t { 29 | ow_temp_error_t error; 30 | ow_temp_t owtemp[OWDEVICES]; /* out */ 31 | }; 32 | 33 | extern ow_temp_read_t ow_temp_read; 34 | 35 | void ow_temp_init(void); 36 | ow_temp_error_t owtemp_read(void); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | #endif /* OWTEMP_H_ */ 42 | -------------------------------------------------------------------------------- /sensors.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sensors.c 3 | * 4 | * Created on: 01.04.2013 5 | * Author: pae 6 | */ 7 | 8 | /* 9 | * BOARD STM32F103C_MINNI MCU STM32F103C8T6 10 | * 11 | * PERIPHERALS MODES REMAP FUNCTIONS PINS 12 | * ADC1 IN8 0 ADC1_IN8 PB0 13 | * ADC1 IN9 0 ADC1_IN9 PB1 14 | */ 15 | 16 | #include "ch.h" 17 | #include "hal.h" 18 | 19 | #include "sensors.h" 20 | 21 | adc_read_t sensors; // описание датчиков 22 | static BinarySemaphore adcsem, adc_cbsem; // семафор управления процессом adc 23 | 24 | static adcsample_t samples[SENSORSALL]; // буфер чтения АЦП 25 | 26 | static void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n); 27 | static void adcerrcallback(ADCDriver *adcp, adcerror_t err); 28 | 29 | /* 30 | * ADC conversion group. 31 | * Mode: Linear buffer, 1 samples of 17 channels, SW triggered. 32 | * Channels: IN0-17 (239.5 cycles sampling time) 33 | */ 34 | static const ADCConversionGroup adcgrpcfg = { 35 | FALSE, //circular 36 | SENSORSALL, //number of channels 37 | adccallback, //adc callback function 38 | adcerrcallback, //error callback function 39 | /* HW dependent part.*/ 40 | 0, //cr1 41 | 0, //cr2 42 | //SMPR1 register 43 | // ADC_SMPR1_SMP_VREF(ADC_SAMPLE_239P5) | 44 | // ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_239P5) | 45 | // ADC_SMPR1_SMP_AN15(ADC_SAMPLE_239P5) | 46 | // ADC_SMPR1_SMP_AN14(ADC_SAMPLE_239P5) | 47 | // ADC_SMPR1_SMP_AN13(ADC_SAMPLE_239P5) | 48 | // ADC_SMPR1_SMP_AN12(ADC_SAMPLE_239P5) | 49 | // ADC_SMPR1_SMP_AN11(ADC_SAMPLE_239P5) | 50 | // ADC_SMPR1_SMP_AN10(ADC_SAMPLE_239P5) | 51 | 0, 52 | //SMPR2 register 53 | // ADC_SMPR2_SMP_AN9(ADC_SAMPLE_239P5) | 54 | // ADC_SMPR2_SMP_AN8(ADC_SAMPLE_239P5) | 55 | // ADC_SMPR2_SMP_AN7(ADC_SAMPLE_239P5) | 56 | // ADC_SMPR2_SMP_AN6(ADC_SAMPLE_239P5) | 57 | // ADC_SMPR2_SMP_AN5(ADC_SAMPLE_239P5) | 58 | // ADC_SMPR2_SMP_AN4(ADC_SAMPLE_239P5) | 59 | // ADC_SMPR2_SMP_AN3(ADC_SAMPLE_239P5) | 60 | // ADC_SMPR2_SMP_AN2(ADC_SAMPLE_239P5) | 61 | // ADC_SMPR2_SMP_AN1(ADC_SAMPLE_239P5) | 62 | ADC_SMPR2_SMP_AN0(ADC_SAMPLE_239P5) | 63 | 0, 64 | //SQR1 register 65 | // ADC_SQR1_SQ16_N(ADC_CHANNEL_SENSOR) | 66 | // ADC_SQR1_SQ15_N(ADC_CHANNEL_IN15) | 67 | // ADC_SQR1_SQ14_N(ADC_CHANNEL_IN14) | 68 | // ADC_SQR1_SQ13_N(ADC_CHANNEL_IN13) | 69 | ADC_SQR1_NUM_CH(SENSORSALL), 70 | //SQR2 register 71 | // ADC_SQR2_SQ12_N(ADC_CHANNEL_IN12) | 72 | // ADC_SQR2_SQ11_N(ADC_CHANNEL_IN11) | 73 | // ADC_SQR2_SQ10_N(ADC_CHANNEL_IN10) | 74 | // ADC_SQR2_SQ9_N(ADC_CHANNEL_IN9) | 75 | // ADC_SQR2_SQ8_N(ADC_CHANNEL_IN8) | 76 | // ADC_SQR2_SQ7_N(ADC_CHANNEL_IN7) | 77 | 0, 78 | //SQR3 register 79 | // ADC_SQR3_SQ6_N(ADC_CHANNEL_IN9) | 80 | // ADC_SQR3_SQ5_N(ADC_CHANNEL_IN8) | 81 | // ADC_SQR3_SQ4_N(ADC_CHANNEL_IN3) | 82 | // ADC_SQR3_SQ3_N(ADC_CHANNEL_IN9) | 83 | // ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9) | 84 | ADC_SQR3_SQ1_N(ADC_CHANNEL_IN8) | 85 | 0 86 | }; 87 | 88 | /* 89 | * ADC end conversion callback 90 | */ 91 | static void adccallback(ADCDriver *adcp, adcsample_t *buffer, size_t n) { 92 | (void) buffer; (void) n; 93 | if (adcp->state == ADC_COMPLETE){ 94 | chBSemSignal(&adc_cbsem); 95 | } 96 | } 97 | 98 | static void adcerrcallback(ADCDriver *adcp, adcerror_t err) { 99 | (void)adcp; 100 | (void)err; 101 | if (adcp->state == ADC_ERROR){ 102 | sensors.error = ADC_CONV_ERROR; 103 | chBSemSignal(&adc_cbsem); 104 | } 105 | } 106 | 107 | /* 108 | * процесс опроса датчиков АЦП 109 | */ 110 | static Thread *ADCThread_p; 111 | WORKING_AREA(waADCThread, 128); 112 | __attribute__((noreturn)) 113 | msg_t ADCThread(void *arg) { 114 | chRegSetThreadName("ADCThd"); 115 | chBSemInit(&adcsem,FALSE); 116 | chBSemInit(&adc_cbsem,TRUE); 117 | 118 | (void)arg; 119 | while (TRUE) { 120 | adc_read_t *req; 121 | Thread *tp; 122 | 123 | tp = chMsgWait(); 124 | req = (adc_read_t *) chMsgGet(tp); 125 | chMsgRelease(tp, (msg_t) req); 126 | 127 | req->error = ADC_NO_ERROR; 128 | chBSemReset(&adc_cbsem,TRUE); 129 | adcStartConversion(&ADCD1, &adcgrpcfg, samples, 1); 130 | if (chBSemWaitTimeout(&adc_cbsem, MS2ST(ADC_TIMEOUT_MS)) == RDY_TIMEOUT){ 131 | req->error = ADC_TIMEOUT; 132 | } 133 | if (req->error == ADC_NO_ERROR) { 134 | // датчик напряжения аккумулятора 135 | req->sensor[BATTSENSOR].value = samples[BATTSENSOR]; 136 | // остальные датчики 137 | for (uint8_t i = 0; i < SENSORSNUM; i++){ 138 | req->sensor[i].value = samples[i]; 139 | } 140 | } 141 | chBSemSignal(&adcsem); 142 | } 143 | } 144 | 145 | /* 146 | * Initializes the ADC driver 1. 147 | */ 148 | void sensors_init(void){ 149 | 150 | adcStart(&ADCD1, NULL); 151 | palSetPadMode(GPIOB, GPIOB_PIN0, PAL_MODE_INPUT_ANALOG); // 00: PB.00 -> ADC1 channel 8 152 | // palSetPadMode(GPIOB, GPIOB_PIN1, PAL_MODE_INPUT_ANALOG); // 01: PB.01 -> ADC1 channel 9 153 | 154 | sensors.sensor[BATTSENSOR].type = 2; 155 | for (uint8_t i = 0; i < SENSORSNUM; i++){ 156 | sensors.sensor[i].type = 0; 157 | } 158 | 159 | ADCThread_p = chThdCreateStatic(waADCThread, sizeof(waADCThread), ADC_PRIO, ADCThread, NULL); 160 | } 161 | 162 | adc_error_t sensors_read(void) { 163 | adc_read_t *adc_read_p = &sensors; 164 | 165 | chBSemWait(&adcsem); /* to be sure */ 166 | 167 | chMsgSend(ADCThread_p, (msg_t) adc_read_p); 168 | 169 | /* wait for reply */ 170 | if(chBSemWaitTimeout(&adcsem, MS2ST(ADC_TIMEOUT_MS)) == RDY_TIMEOUT) { 171 | adc_read_p->error = ADC_TIMEOUT; 172 | return ADC_TIMEOUT; 173 | } 174 | chBSemReset(&adcsem, FALSE); 175 | if (adc_read_p->error == ADC_CONV_ERROR){ 176 | return ADC_CONV_ERROR; 177 | } 178 | adc_read_p->error = ADC_NO_ERROR; 179 | return ADC_NO_ERROR; 180 | } 181 | -------------------------------------------------------------------------------- /sensors.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sensors.h 3 | */ 4 | #ifndef SENSORS_H_ 5 | #define SENSORS_H_ 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | #include "ch.h" 11 | #include "hal.h" 12 | 13 | #define SENSORSNUM 0 // число внешних датчиков 14 | #define SENSORSALL 1 // общее число датчиков 15 | #define BATTSENSOR 0 // номер датчика контроля напряжения батареи PB.00 16 | #define ADC_TIMEOUT_MS 100 // задержка опроса датчиков, мсек 17 | 18 | // значения АЦП 19 | #define BATTERYNORMA 995 // значение "норма" для батареи > 3.1V 20 | #define BATTERYLOW 500 // значение для обнаружения низкого заряда батареи < 3V 21 | 22 | typedef enum { 23 | ADC_NO_ERROR, 24 | ADC_CONV_ERROR, 25 | ADC_TIMEOUT, 26 | } adc_error_t; 27 | 28 | // описание датчика 29 | typedef struct _sensor sensor_t; 30 | struct _sensor{ 31 | uint8_t type; // тип датчика: 0 - не используется, 1 - датчик, 2 - контроль питания 32 | uint16_t value; // последнее значение считанное АЦП 33 | }; 34 | 35 | typedef struct _adc_read_t adc_read_t; 36 | struct _adc_read_t { 37 | adc_error_t error; /* out */ 38 | sensor_t sensor[SENSORSALL]; /* out */ 39 | }; 40 | 41 | #define ADC_PRIO NORMALPRIO 42 | extern adc_read_t sensors; // описание датчиков 43 | 44 | // инициализация АЦП 45 | void sensors_init(void); 46 | // чтение значений ADC 47 | adc_error_t sensors_read(void); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | #endif /* SENSORS_H_ */ 53 | -------------------------------------------------------------------------------- /stm32f103c_mini.txt: -------------------------------------------------------------------------------- 1 | Configuration stm32f103c_mini 2 | Date 08/20/2013 3 | MCU STM32F103C(8-B)Tx 4 | 5 | 6 | 7 | PERIPHERALS MODES REMAP FUNCTIONS PINS 8 | SPI1 Full-Duplex-Master_With-NSS 0 SPI1_MISO PA6 9 | SPI1 Full-Duplex-Master_With-NSS 0 SPI1_MOSI PA7 10 | SPI1 Full-Duplex-Master_With-NSS 0 SPI1_NSS PA4 11 | SPI1 Full-Duplex-Master_With-NSS 0 SPI1_SCK PA5 12 | I2C1 I2C 0 I2C1_SCL PB6 13 | I2C1 I2C 0 I2C1_SDA PB7 14 | USART1 Half-duplex(single-wire-mode) 0 USART1_TX PA9 15 | USB USB_FS 0 USB_USBDM PA11 16 | USB USB_FS 0 USB_USBDP PA12 17 | TIM2 PWM_INPUT 1 TIM2_CH1 PA15 18 | TIM2 PWM_INPUT 1 TIM2_CH2 PB3 19 | ADC1 IN2 0 ADC1_IN2 PA2 20 | ADC1 IN3 0 ADC1_IN3 PA3 21 | ADC1 IN8 0 ADC1_IN8 PB0 22 | ADC1 IN9 0 ADC1_IN9 PB1 23 | SYS Serial-Wire 0 SYS_JTCK-SWCLK PA14 24 | SYS Serial-Wire 0 SYS_JTMS-SWDIO PA13 25 | SYS SYS-OSC32 0 SYS_OSC32_IN PC14-OSC32_IN 26 | SYS SYS-OSC32 0 SYS_OSC32_OUT PC15-OSC32_OUT 27 | 28 | 29 | 30 | POS PIN FUNCTION Used 31 | 10 PA15 TIM2_CH1 AM2302 32 | 11 PB3 TIM2_CH2 AM2302 33 | 12 PA2 USART2_TX Serial console 34 | 13 PA3 USART2_RX Serial console 35 | 14 PA4 SPI1_NSS NRF24L01+ 36 | 15 PA5 SPI1_SCK NRF24L01+ 37 | 16 PA6 SPI1_MISO NRF24L01+ 38 | 17 PA7 SPI1_MOSI NRF24L01+ 39 | 18 PB0 ADC1_IN8 Battery voltage 40 | 19 PB1 ADC1_IN9 NU 41 | 25 PB12 Output_Push-Pull NU 42 | 26 PB13 Output_Push-Pull Sensors power control 43 | 27 PB14 Input_Floating Stop mode switch 44 | 28 PB15 Output_Push-Pull State LED 45 | 30 PA9 USART1_TX 1-Wire driver 46 | 42 PB6 I2C1_SCL BH1750 47 | 43 PB7 I2C1_SDA BH1750 48 | 45 PB8 Output_Push-Pull NRF24L01+ CE 49 | 46 PB9 Input_Floating NRF24L01+ IRQ 50 | -------------------------------------------------------------------------------- /util/floatp10.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | /* _floatp10() get the characteristic, mantissa and sign of a double */ 3 | /* precision floating point number such that: */ 4 | /* */ 5 | /* 1 <= mantissa < 10 */ 6 | /* - 308 <= characteristic <= 308 */ 7 | /* */ 8 | /* negative: false if positive */ 9 | /* true if negative */ 10 | /*---------------------------------------------------------------------------*/ 11 | #include 12 | #include 13 | 14 | int _floatp10(double *fnum, uint_fast8_t *negative, int prec) 15 | { 16 | int i; 17 | int fpower = 0; 18 | int ipower = 256; 19 | int rpower = 256; 20 | double fround = 0.5; 21 | 22 | static double const pfpower[] = 23 | { 24 | 1.0e+256, 25 | 1.0e+128, 26 | 1.0e+64, 27 | 1.0e+32, 28 | 1.0e+16, 29 | 1.0e+8, 30 | 1.0e+4, 31 | 1.0e+2, 32 | 1.0e+1 33 | }; 34 | 35 | static double const nfpower[] = 36 | { 37 | 1.0e-256, 38 | 1.0e-128, 39 | 1.0e-64, 40 | 1.0e-32, 41 | 1.0e-16, 42 | 1.0e-8, 43 | 1.0e-4, 44 | 1.0e-2, 45 | 1.0e-1 46 | }; 47 | 48 | *negative = *fnum < (double)0; 49 | 50 | if(*fnum != 0.0) 51 | { 52 | if(prec > 0) 53 | { 54 | if(prec < 309) 55 | { 56 | for(i = 0; i < 9; i++) 57 | { 58 | if(prec >= rpower) 59 | { 60 | fround /= pfpower[i]; 61 | prec -= rpower; 62 | } 63 | rpower >>= 1; 64 | } 65 | } 66 | else 67 | fround = (double)0; 68 | } 69 | else if(prec < 0) 70 | { 71 | if(prec > -310) 72 | { 73 | fround = (double)5; 74 | for(i = 0; i < 9; i++) 75 | { 76 | if(prec >= rpower) 77 | { 78 | fround *= pfpower[i]; 79 | prec += rpower; 80 | } 81 | rpower >>= 1; 82 | } 83 | } 84 | else 85 | fround = (double)0; 86 | } 87 | *fnum = fabs(*fnum) + fround; 88 | if(*fnum < (double)1) 89 | { 90 | for(i = 0; i < 9; i++) 91 | { 92 | if(*fnum <= nfpower[i]) 93 | { 94 | *fnum *= pfpower[i]; 95 | fpower -= ipower; 96 | } 97 | ipower >>= 1; 98 | } 99 | } 100 | else if(*fnum >= (double)10) 101 | { 102 | for(i = 0; i < 9; i++) 103 | { 104 | if(*fnum >= pfpower[i]) 105 | { 106 | *fnum /= pfpower[i]; 107 | fpower += ipower; 108 | } 109 | ipower >>= 1; 110 | } 111 | } 112 | if(*fnum < (double)1) 113 | { 114 | *fnum *= pfpower[8]; 115 | fpower--; 116 | } 117 | } 118 | return fpower; 119 | } 120 | -------------------------------------------------------------------------------- /util/itoa.c: -------------------------------------------------------------------------------- 1 | /******************************************************* 2 | * Code contributed by Chris Takahashi, * 3 | * ctakahashi (at) users (dot) sourceforge (dot) net. * 4 | * See stdlib.h for licence. * 5 | * $Date: 2005/08/31 11:39:47 $ * 6 | *******************************************************/ 7 | #include 8 | 9 | char *itoa(int num, char *str, int radix) 10 | { 11 | char sign = 0; 12 | char temp[33]; //an int can only be 32 bits long 13 | //at radix 2 (binary) the string 14 | //is at most 16 + 1 null long. 15 | int temp_loc = 0; 16 | int digit; 17 | int str_loc = 0; 18 | 19 | //save sign for radix 10 conversion 20 | if (radix == 10 && num < 0) { 21 | sign = 1; 22 | num = -num; 23 | } 24 | unsigned int Tmp = num; 25 | //construct a backward string of the number. 26 | do { 27 | digit = Tmp % radix; 28 | Tmp = Tmp / radix; 29 | if (digit < 10) 30 | temp[temp_loc++] = digit + '0'; 31 | else 32 | temp[temp_loc++] = digit - 10 + 'A'; 33 | } while (Tmp > 0); 34 | 35 | //now add the sign for radix 10 36 | if (radix == 10 && sign) { 37 | temp[temp_loc] = '-'; 38 | } else { 39 | temp_loc--; 40 | } 41 | 42 | 43 | //now reverse the string. 44 | while ( temp_loc >=0 ) {// while there are still chars 45 | str[str_loc++] = temp[temp_loc--]; 46 | } 47 | str[str_loc] = 0; // add null termination. 48 | 49 | return str; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /util/printfs.c: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------*/ 2 | /* _printfs() - print formatted data to a file or a string */ 3 | /*---------------------------------------------------------------------------*/ 4 | #include 5 | #define HUGE_VAL 1e256 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #ifdef __STDC__ 13 | #include 14 | #else 15 | #include 16 | #endif 17 | 18 | #define POS_INFINITY "inf" 19 | #define NEG_INFINITY "-inf" 20 | 21 | #define _FLOAT_ROUND_ADJUST (double)5e-15 22 | 23 | 24 | int vsprintf(char *string, const char *format, va_list ap); 25 | int sprintf(char *buffer, char const *format, ...) 26 | { 27 | int Len; 28 | va_list ap; 29 | va_start(ap, format); 30 | Len = vsprintf(buffer, format, ap); 31 | va_end(ap); 32 | return Len; 33 | } 34 | 35 | extern int _floatp10(double *fnum, uint_fast8_t *negative, int prec); 36 | 37 | // as sizeof(int) == sizeof(long), 'l' specifier ignored 38 | char *itoa(int num, char *str, int radix); 39 | char *utoa(unsigned num, char *str, int radix); 40 | 41 | int vsprintf(char *string, char const *format, va_list ap) 42 | { 43 | char *output = string; 44 | char buffer[128]; 45 | char *s; 46 | size_t width; 47 | uint_fast8_t prec; 48 | int fpower; 49 | uint_fast8_t negative; 50 | size_t padlen, zpadlen; 51 | double fnum; 52 | 53 | union 54 | { 55 | struct 56 | { 57 | uint_fast16_t left_justify:1; // %- 58 | uint_fast16_t show_sign:1; // %+ 59 | uint_fast16_t zero_padding:1; // %0 60 | uint_fast16_t pad_sign:1; // %(space) 61 | uint_fast16_t alt:1; // %# 62 | uint_fast16_t uppercase:1; // %E%G%X / %e %g %x 63 | // uint_fast16_t long_val:1; // %l 64 | 65 | uint_fast16_t precision:1; // format string has precision field 66 | }; 67 | uint_fast16_t raw; 68 | } flags; 69 | 70 | for(; *format; format++) 71 | { 72 | if(*format != '%') 73 | { 74 | *output++ = *format; 75 | } 76 | else 77 | { 78 | flags.raw = 0; 79 | width = 0; 80 | prec = 0; 81 | padlen = 0; 82 | zpadlen = 0; 83 | s = buffer; 84 | 85 | while(*++format) 86 | { 87 | switch(*format) 88 | { 89 | case '-': 90 | flags.left_justify = 1; 91 | continue; 92 | case '+': 93 | flags.show_sign = 1; 94 | continue; 95 | case '0': 96 | flags.zero_padding = 1; 97 | continue; 98 | case ' ': 99 | flags.pad_sign = 1; 100 | continue; 101 | case '#': 102 | flags.alt = 1; 103 | continue; 104 | default: 105 | break; 106 | } 107 | break; 108 | } 109 | if(*format == '*') 110 | { 111 | width = va_arg(ap, int); 112 | format++; 113 | } 114 | else 115 | { 116 | while(isdigit(*format)) 117 | { 118 | width = (width * 10) + (*format - '0'); 119 | format++; 120 | } 121 | } 122 | if(*format == '.') 123 | { 124 | format++; 125 | if(*format == '*') 126 | { 127 | prec = va_arg(ap, unsigned int); 128 | flags.precision = 1; 129 | format++; 130 | } 131 | else 132 | { 133 | while(isdigit(*format)) 134 | { 135 | flags.precision = 1; 136 | prec = (prec * 10) + (*format - '0'); 137 | format++; 138 | } 139 | } 140 | } 141 | if(*format == 'l') 142 | { 143 | // flags.long_val = 1; 144 | format++; 145 | } 146 | if(strchr("feEgG", *format)) 147 | { 148 | if(fnum == HUGE_VAL) 149 | { 150 | strcpy(s, POS_INFINITY); 151 | flags.zero_padding = 0; 152 | flags.precision = 0; 153 | goto overflow; 154 | } 155 | else if(fnum == -HUGE_VAL) 156 | { 157 | strcpy(s, NEG_INFINITY); 158 | flags.zero_padding = 0; 159 | flags.precision = 0; 160 | goto overflow; 161 | } 162 | } 163 | switch(*format) 164 | { 165 | case 'c': 166 | *output++ = (char)va_arg(ap, int); 167 | continue; 168 | case 'd': 169 | case 'i': 170 | // if(flags.long_val) 171 | // ltoa(va_arg(ap, long), buffer, 10); 172 | // else 173 | itoa(va_arg(ap, int), buffer, 10); 174 | flags.alt = 0; 175 | break; 176 | case 'G': 177 | flags.uppercase = 1; 178 | case 'g': 179 | fnum = va_arg(ap, double); 180 | if(!flags.precision) 181 | prec = 6; 182 | { 183 | double sfnum = fnum; 184 | fpower = _floatp10(&sfnum, &negative, -999); 185 | sfnum = fnum; 186 | fpower = _floatp10(&sfnum, &negative, prec - fpower); 187 | if((fnum != 0.0) && ((fpower < -4) || (fpower >= (int)prec))) 188 | { 189 | fnum = sfnum; 190 | goto format_Ee; 191 | } 192 | } 193 | prec -= (fpower + 1); 194 | if((int)prec <= 0) 195 | prec = 1; 196 | goto format_f; 197 | 198 | case 'E': 199 | flags.uppercase = 1; 200 | case 'e': 201 | fnum = va_arg(ap, double); 202 | if(!flags.precision) 203 | prec = 6; 204 | { 205 | double sfnum = fnum; 206 | fpower = _floatp10(&sfnum, &negative, -999); 207 | fpower = _floatp10(&fnum, &negative, prec - fpower); 208 | } 209 | format_Ee: 210 | if(negative) 211 | *s++ = '-'; 212 | { 213 | int fdigit = (int)fnum; 214 | *s++ = (char)(fdigit + '0'); 215 | fnum -= (double)fdigit; 216 | } 217 | fnum *= 10.0; 218 | fnum += _FLOAT_ROUND_ADJUST; 219 | if(flags.alt || prec) 220 | { 221 | flags.precision = 0; 222 | *s++ = '.'; 223 | uint_fast8_t fprec = 0; 224 | while(prec) 225 | { 226 | if(fprec < 16) 227 | { 228 | int fdigit = (int)fnum; 229 | *s++ = (char)(fdigit + '0'); 230 | fnum -= (double)fdigit; 231 | fnum *= 10.0; 232 | fnum += _FLOAT_ROUND_ADJUST; 233 | fprec++; 234 | } 235 | else 236 | { 237 | *s++ = '0'; 238 | } 239 | prec--; 240 | } 241 | } 242 | *s = flags.uppercase ? 'E' : 'e'; 243 | if(fpower >= 0) 244 | { 245 | *s++ = '+'; 246 | } 247 | else 248 | { 249 | *s++ = '-'; 250 | fpower = -fpower; 251 | } 252 | if(fpower < 10) 253 | *s++ = '0'; 254 | itoa(fpower, s, 10); 255 | s = buffer; 256 | break; 257 | case 'f': 258 | fnum = va_arg(ap, double); 259 | if(!flags.precision) 260 | prec = 6; 261 | format_f: 262 | fpower = _floatp10(&fnum, &negative, prec); 263 | if(negative) 264 | *s++ = '-'; 265 | if(fpower < 0) 266 | { 267 | *s++ = '0'; 268 | fpower++; 269 | } 270 | else 271 | { 272 | uint_fast8_t fprec = 0; 273 | while(fpower >= 0) 274 | { 275 | if(fprec < 16) 276 | { 277 | int fdigit = (int)fnum; 278 | *s++ = (char)(fdigit + '0'); 279 | fnum -= (double)fdigit; 280 | fnum *= 10.0; 281 | fnum += _FLOAT_ROUND_ADJUST; 282 | fprec++; 283 | } 284 | else 285 | { 286 | *s++ = '0'; 287 | } 288 | fpower--; 289 | } 290 | fpower = 0; 291 | } 292 | if(flags.alt || prec) 293 | { 294 | flags.precision = 0; 295 | *s++ = '.'; 296 | uint_fast8_t fprec = 0; 297 | while(prec) 298 | { 299 | if(fpower < 0) 300 | { 301 | *s++ = '0'; 302 | fpower++; 303 | } 304 | else 305 | { 306 | if(fprec < 16) 307 | { 308 | int fdigit = (int)fnum; 309 | *s++ = (char)(fdigit + '0'); 310 | 311 | fnum -= (double)fdigit; 312 | fnum *= 10.0; 313 | fnum += _FLOAT_ROUND_ADJUST; 314 | fprec++; 315 | } 316 | else 317 | { 318 | *s++ = '0'; 319 | } 320 | } 321 | prec--; 322 | } 323 | } 324 | *s = '\0'; 325 | s = buffer; 326 | break; 327 | case 'n': 328 | *va_arg(ap, int *) = output - string; 329 | continue; 330 | 331 | case 'o': 332 | if(flags.alt) 333 | *s++ = '0'; 334 | // if(flags.long_val) 335 | // ultoa(va_arg(ap, unsigned long), s, 8); 336 | // else 337 | utoa(va_arg(ap, unsigned int), s, 8); 338 | s = buffer; 339 | break; 340 | 341 | case 'p': 342 | strupr(utoa((uintptr_t)va_arg(ap, void *), s, 16)); 343 | break; 344 | 345 | case 's': 346 | s = va_arg(ap, char *); 347 | flags.show_sign = 0; 348 | flags.zero_padding = 0; 349 | flags.pad_sign = 0; 350 | break; 351 | 352 | case 'u': 353 | // if(flags.long_val) 354 | // ultoa(va_arg(ap, unsigned long), s, 10); 355 | // else 356 | utoa(va_arg(ap, unsigned int), s, 10); 357 | break; 358 | 359 | case 'x': 360 | case 'X': 361 | s = buffer; 362 | if(flags.alt) 363 | { 364 | *s++ = '0'; 365 | *s++ = *format; 366 | } 367 | // if(flags.long_val) 368 | // ultoa(va_arg(ap, unsigned long), s, 16); 369 | // else 370 | utoa(va_arg(ap, unsigned int), s, 16); 371 | if(*format == 'X') 372 | strupr(s); 373 | s = buffer; 374 | break; 375 | default: 376 | *output++ = *format; 377 | continue; 378 | } 379 | overflow: 380 | { 381 | size_t ssize = strlen(s); 382 | size_t dsize = ssize; 383 | char schar = '\0'; 384 | size_t maxlen = -1; 385 | 386 | if(flags.left_justify) 387 | flags.zero_padding = 0; 388 | if(*format == 's') 389 | { 390 | if(flags.precision) 391 | { 392 | flags.precision = 0; 393 | maxlen = prec; 394 | } 395 | } 396 | else 397 | { 398 | if(ssize == 1 && *s == '0') 399 | { 400 | if(flags.precision && prec == 0) 401 | { 402 | *s = '\0'; 403 | ssize = 0; 404 | dsize = 0; 405 | } 406 | } 407 | if(*format == 'o' && flags.alt && prec < ssize) //???????? 408 | { 409 | flags.precision = 1; 410 | prec = ssize + 1; 411 | } 412 | if(*s == '-') 413 | { 414 | s++; 415 | schar = '-'; 416 | dsize--; 417 | } 418 | else if(flags.show_sign) 419 | { 420 | schar = '+'; 421 | ssize++; 422 | } 423 | else if(flags.pad_sign) 424 | { 425 | schar = ' '; 426 | ssize++; 427 | } 428 | } 429 | if(width > ssize) 430 | { 431 | if(flags.precision && (prec > dsize)) 432 | { 433 | padlen = width - (ssize + (prec - dsize)); 434 | } 435 | else 436 | { 437 | padlen = width - ssize; 438 | } 439 | } 440 | if(flags.precision && (prec > dsize)) 441 | { 442 | zpadlen = prec - dsize; 443 | } 444 | else if(flags.zero_padding) 445 | { 446 | zpadlen = padlen; 447 | padlen = 0; 448 | } 449 | while(!flags.left_justify && (padlen > 0)) 450 | { 451 | *output++ = ' '; 452 | padlen--; 453 | } 454 | 455 | if(schar) 456 | { 457 | *output++ = schar; 458 | } 459 | 460 | while(zpadlen > 0) 461 | { 462 | *output++ = '0'; 463 | zpadlen--; 464 | } 465 | while(*s) 466 | { 467 | if(maxlen != (size_t)-1) 468 | { 469 | if(!(maxlen--)) break; 470 | } 471 | *output++ = *s++; 472 | } 473 | 474 | while(flags.left_justify && (padlen > 0)) 475 | { 476 | *output++ = ' '; 477 | padlen--; 478 | } 479 | } 480 | } 481 | } 482 | *output = '\0'; 483 | return(output - string); 484 | } 485 | -------------------------------------------------------------------------------- /util/printfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * printfs.h 3 | * 4 | * Created on: 17.01.2014 5 | * Author: andru 6 | */ 7 | 8 | #ifndef PRINTFS_H_ 9 | #define PRINTFS_H_ 10 | 11 | int sprintf(char *buffer, char const *format, ...); 12 | 13 | #endif /* PRINTFS_H_ */ 14 | -------------------------------------------------------------------------------- /util/utoa.c: -------------------------------------------------------------------------------- 1 | /******************************************************* 2 | * Code contributed by Chris Takahashi, * 3 | * ctakahashi (at) users (dot) sourceforge (dot) net. * 4 | * See stdlib.h for licence. * 5 | * $Date: 2005/08/31 11:39:47 $ * 6 | *******************************************************/ 7 | #include 8 | 9 | char *utoa(unsigned long num, char *str, int radix) { 10 | char temp[33]; //an int can only be 16 bits long 11 | //at radix 2 (binary) the string 12 | //is at most 16 + 1 null long. 13 | int temp_loc = 0; 14 | int digit; 15 | int str_loc = 0; 16 | 17 | //construct a backward string of the number. 18 | do { 19 | digit = num % radix; 20 | num = num / radix; 21 | if (digit < 10) 22 | temp[temp_loc++] = digit + '0'; 23 | else 24 | temp[temp_loc++] = digit - 10 + 'A'; 25 | } while (num > 0); 26 | 27 | temp_loc--; 28 | 29 | 30 | //now reverse the string. 31 | while ( temp_loc >=0 ) {// while there are still chars 32 | str[str_loc++] = temp[temp_loc--]; 33 | } 34 | str[str_loc] = 0; // add null termination. 35 | 36 | return str; 37 | } 38 | 39 | --------------------------------------------------------------------------------