├── .gitignore ├── AUTHORS ├── LICENSE ├── Makefile.paths ├── Makefile.rules ├── Makefile.rules.avr ├── Makefile.rules.efm32 ├── Makefile.rules.efm32-libefm ├── Makefile.rules.i686-linux-gnu ├── Makefile.rules.msp430 ├── Makefile.rules.msp430-llvm ├── Makefile.rules.msp430-llvm-c ├── Makefile.rules.stm32 ├── Makefile.rules.tm4 ├── README ├── docs ├── FAQ ├── coding_conventions.txt ├── contributing.txt ├── data_model.markdown ├── getting_started.markdown ├── irq_handling.txt └── new_target.txt ├── examples ├── 1wire.cpp ├── Makefile ├── adc.cpp ├── blink.cpp ├── blink_bus.cpp ├── blink_c.c ├── blink_c_api.cpp ├── blink_c_api.h ├── blink_dynamic.cpp ├── blink_dynapin.cpp ├── blink_sleep.cpp ├── blink_static.cpp ├── blink_ticks.cpp ├── blink_timer.cpp ├── flash.cpp ├── hw_config_avr.hpp ├── hw_config_msp430.hpp ├── hw_config_stm32.hpp ├── hw_config_tm4.hpp ├── hw_config_tutorial │ ├── blink1.cpp │ ├── blink2.cpp │ ├── blink3.cpp │ └── hw_config_avr.hpp ├── i2c_24cxx.cpp ├── irq_dispatch.cpp ├── irq_dispatch_simple.cpp ├── lcd.cpp ├── lcd_nokia.cpp ├── msp430_parse_tlv.cpp ├── perf_counter.cpp ├── spi.cpp ├── timer_irq.cpp ├── timer_irq_dispatch.cpp ├── uart_echo.cpp ├── uart_echo_async.cpp ├── uart_echo_buffered.cpp ├── uart_echo_irq.cpp └── uart_printf.cpp ├── include ├── 1wire.hpp ├── adc.hpp ├── algo │ └── nearptr.hpp ├── avr │ ├── cpu_avr.hpp │ ├── delay_avr.hpp │ ├── delay_static_avr.hpp │ ├── gpio_avr.hpp │ ├── timer_avr.hpp │ └── uart_avr.hpp ├── bits.hpp ├── board.hpp ├── board_arduino.hpp ├── board_base.hpp ├── board_efm32gg_stk3700.hpp ├── board_launchpad_msp430.hpp ├── board_launchpad_stellaris.hpp ├── board_stm32vldiscovery.hpp ├── byteptr.hpp ├── clock.hpp ├── compat │ └── arduino.hpp ├── console.hpp ├── cortex-m │ ├── cpu_cortexm.hpp │ ├── delay_cortexm.hpp │ ├── delay_static_cortexm.hpp │ ├── includes_cortexm.hpp │ ├── irq_dispatch_cortexm.hpp │ ├── timer_cortexm_cyccnt.hpp │ └── timer_cortexm_systick.hpp ├── cpu.hpp ├── cpu_base.hpp ├── delay.hpp ├── delay_static.hpp ├── delay_time.hpp ├── device │ ├── charset_6x8.cpp │ ├── hd44780.hpp │ ├── pcd8544.cpp │ └── pcd8544.hpp ├── efm32 │ ├── cpu_efm32.hpp │ ├── gpio_efm32.hpp │ └── includes_efm32.hpp ├── flash.hpp ├── gpio.hpp ├── gpio_base.hpp ├── i2c.hpp ├── irq_dispatch.hpp ├── irq_dispatch_base.hpp ├── lpc │ └── lpc800_bootrom.hpp ├── meta.hpp ├── msp430 │ ├── adc_msp430.hpp │ ├── clock_msp430.hpp │ ├── cpu_msp430.hpp │ ├── delay_msp430.hpp │ ├── delay_static_msp430.hpp │ ├── flash_msp430.hpp │ ├── gpio_msp430.hpp │ ├── gpiodyn_msp430.hpp │ ├── irq_dispatch_msp430.hpp │ ├── sleep_msp430.hpp │ ├── spi_msp430.hpp │ ├── timer_irq_dispatch_msp430.hpp │ ├── timer_msp430.hpp │ ├── uart_msp430.hpp │ └── watchdog_msp430.hpp ├── nrf51 │ └── gpio_nrf51.hpp ├── parallel_bus.hpp ├── posix │ ├── sleep_posix.hpp │ └── timer_posix.hpp ├── progmem.hpp ├── protocol │ ├── avr_isp.hpp │ └── usb.hpp ├── rtos │ ├── buffered_uart.hpp │ ├── circular.hpp │ ├── perf_counter.hpp │ ├── perf_counter_acu.hpp │ ├── ticks.hpp │ └── virt_timer.hpp ├── signal.hpp ├── sleep.hpp ├── sleep_impl.hpp ├── spi.hpp ├── spi_base.hpp ├── spi_command.hpp ├── stm32 │ ├── cpu_stm32.hpp │ ├── gpio_stm32.hpp │ └── includes_stm32.hpp ├── timer.hpp ├── timer_base.hpp ├── timer_irq_dispatch.hpp ├── tm4 │ ├── cpu_tm4.hpp │ ├── gpio_tm4.hpp │ ├── includes_tm4.hpp │ └── uart_tm4.hpp ├── types.hpp ├── uart.hpp ├── uart_base.hpp └── watchdog.hpp ├── scripts └── msp430_rate.py └── tests ├── Makefile ├── asm_pattern_match.py ├── circular.cpp ├── nearptr.cpp ├── sub_mod.cpp ├── test_2_same_delays.cpp ├── test_2_same_delays.pattern ├── test_delay_in_loop.cpp ├── test_delay_in_loop.pattern ├── test_delay_single.cpp ├── test_delay_single.pattern └── test_static_delay.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | bin-*/ 3 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Paul Sokolovsky 2 | Core library and other files unless explicitly stated otherwise. 3 | 4 | Carlos Rodrigues 5 | Author of Arduino PCD8544 library, on which PCD8544 is based. 6 | -------------------------------------------------------------------------------- /Makefile.paths: -------------------------------------------------------------------------------- 1 | # Makefile specifying paths to various 3rd-party components 2 | LIBPERIPHA_PATH = $(PTL_PATH)/../libperipha 3 | CORTEX_STARTUP_PATH = $(PTL_PATH)/../cortex-uni-startup 4 | -------------------------------------------------------------------------------- /Makefile.rules: -------------------------------------------------------------------------------- 1 | PTL_PATH ?= . 2 | 3 | ifeq ($(TARGET),) 4 | $(error You need to define target: $(MAKE) TARGET=(msp430|avr|stm32|...)) 5 | endif 6 | 7 | TARGETDIR = bin-$(TARGET) 8 | 9 | include $(PTL_PATH)/Makefile.paths 10 | include $(PTL_PATH)/Makefile.rules.$(TARGET) 11 | 12 | GCC_PATH ?= 13 | CROSS_COMPILE ?= $(TARGET)- 14 | GCC_VER ?= 15 | CC = $(GCC_PATH)$(CROSS_COMPILE)gcc$(GCC_VER) 16 | CXX = $(GCC_PATH)$(CROSS_COMPILE)g++$(GCC_VER) 17 | OBJDUMP ?= $(GCC_PATH)$(CROSS_COMPILE)objdump 18 | OBJCOPY ?= $(GCC_PATH)$(CROSS_COMPILE)objcopy 19 | 20 | HW_CONFIG ?= \"hw_config_$(TARGET).hpp\" 21 | 22 | CFLAGS ?= -O1 -g -Wreturn-type -ffunction-sections -fdata-sections -DHW_CONFIG=$(HW_CONFIG) 23 | ALL_INCLUDE = -I$(PTL_PATH)/include/ $(TARGET_INCLUDE) $(INCLUDE) 24 | TARGET_CFLAGS ?= $(TARGET_FLAGS) 25 | TARGET_LDFLAGS ?= $(TARGET_FLAGS) 26 | ALL_CFLAGS = $(ALL_INCLUDE) $(TARGET_CFLAGS) $(CFLAGS) 27 | ALL_CXXFLAGS = $(ALL_CFLAGS) -fno-exceptions 28 | LDFLAGS = $(TARGET_LDFLAGS) -Wl,--gc-sections -Wl,-Map=$@.map,--cref 29 | 30 | 31 | .PRECIOUS: $(TARGETDIR)/%.o 32 | 33 | ifneq ($(OVERRIDE_RULES),1) 34 | $(TARGETDIR)/%.o: %.cpp 35 | mkdir -p $(TARGETDIR) 36 | $(CXX) $(ALL_CXXFLAGS) -c $^ -o $@ 37 | 38 | $(TARGETDIR)/%.o: %.c 39 | mkdir -p $(TARGETDIR) 40 | $(CC) $(ALL_CXXFLAGS) -c $^ -o $@ 41 | endif 42 | 43 | $(TARGETDIR)/%.s: %.cpp 44 | mkdir -p $(TARGETDIR) 45 | $(CXX) $(ALL_CXXFLAGS) -S $^ -o $@ 46 | 47 | $(TARGETDIR)/%.s: %.c 48 | mkdir -p $(TARGETDIR) 49 | $(CXX) $(ALL_CXXFLAGS) -S $^ -o $@ 50 | 51 | disasm-%: $(TARGETDIR)/% 52 | $(OBJDUMP) -dSt --demangle $^ >$^.disasm 53 | 54 | all: 55 | 56 | clean: 57 | rm -f $(TARGETDIR)/*.o 58 | -------------------------------------------------------------------------------- /Makefile.rules.avr: -------------------------------------------------------------------------------- 1 | MCU = atmega168 2 | TARGET_FLAGS = -mmcu=$(MCU) 3 | 4 | 5 | .PRECIOUS: $(TARGETDIR)/%.hex 6 | 7 | $(TARGETDIR)/%.hex: $(TARGETDIR)/% 8 | $(OBJCOPY) -O ihex -R .eeprom $^ $@ 9 | $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex $^ $^.eep || exit 0 10 | 11 | deploy-%: $(TARGETDIR)/%.hex 12 | avrdude -p m328p -c arduino -P/dev/ttyUSB0 -b57600 -D -Uflash:w:$^ 13 | -------------------------------------------------------------------------------- /Makefile.rules.efm32: -------------------------------------------------------------------------------- 1 | CMSIS_PATH = /home/pfalcon/projects-3rdparty/CMSIS/EFM/ 2 | # CMSIS includes consist of two sets: "core", supplied by ARM, 3 | # and "device", supplied by silicon vendor. 4 | CMSIS_CORE_INCLUDE = -I$(LIBPERIPHA_PATH)/arm/cortex-m/arm-cmsis/CMSIS/Include 5 | CMSIS_DEVICE_INCLUDE = -I$(CMSIS_PATH)/Device/EnergyMicro/EFM32GG/Include 6 | 7 | JLINK_TOOL = /home/pfalcon/projects-3rdparty/efm32/JLink_Linux_V462a/StartJLinkExe.sh 8 | 9 | STARTUP = $(CORTEX_STARTUP_PATH)/startup.c 10 | # No need to specify full path to linker script, will be searched in -L 11 | LINKSCRIPT = efm32/efm32-biggest.ld 12 | 13 | DEVICE_INCLUDE = -I$(LIBPERIPHA_PATH) $(CMSIS_CORE_INCLUDE) $(CMSIS_DEVICE_INCLUDE) -DCORTEX_M3 14 | 15 | CROSS_COMPILE = arm-none-eabi- 16 | #GCC_VER = -4.4 17 | TARGET_INCLUDE = $(DEVICE_INCLUDE) -I$(CORTEX_STARTUP_PATH) 18 | TARGET_FLAGS = -mthumb -mcpu=cortex-m3 -DNO_SYSTEMINIT -D__EFM32__ -DEFM32 19 | TARGET_CFLAGS = $(TARGET_FLAGS) 20 | TARGET_LDFLAGS = $(TARGET_CFLAGS) $(TARGET_INCLUDE) --static -nostdlib -nostartfiles -T$(LINKSCRIPT) \ 21 | -Wl,--build-id=none $(CMSIS_SYSTEM) $(STARTUP) 22 | LDLIBS = -L$(CORTEX_STARTUP_PATH) -lgcc 23 | 24 | 25 | .PRECIOUS: $(TARGETDIR)/%.bin 26 | 27 | $(TARGETDIR)/%.bin: $(TARGETDIR)/% 28 | $(OBJCOPY) -O binary $^ $@ 29 | 30 | deploy-%: $(TARGETDIR)/%.bin 31 | echo "exec device = EFM32GG990F1024" >$(TARGETDIR)/jlink.script 32 | echo "loadbin $^, 0" >>$(TARGETDIR)/jlink.script 33 | echo "r" >>$(TARGETDIR)/jlink.script 34 | echo "go" >>$(TARGETDIR)/jlink.script 35 | echo "q" >>$(TARGETDIR)/jlink.script 36 | # Exits with rc=1 even on success 37 | $(JLINK_TOOL) $(TARGETDIR)/jlink.script || true 38 | -------------------------------------------------------------------------------- /Makefile.rules.efm32-libefm: -------------------------------------------------------------------------------- 1 | LIBEFM_PATH = /home/pfalcon/projects-3rdparty/efm32 2 | #CROSS_COMPILE = arm-linux-gnueabi- 3 | #GCC_VER = -4.4 4 | CROSS_COMPILE = ~/toolchain/arm-2010.09/bin/arm-none-eabi- 5 | GCC_VER = 6 | TARGET_INCLUDE = -I$(LIBEFM_PATH)/CMSIS/Include \ 7 | -I$(LIBEFM_PATH)/Device/EnergyMicro/EFM32GG/Include \ 8 | -I$(LIBEFM_PATH)/emlib/inc \ 9 | -I$(LIBEFM_PATH)/kits/common/bsp \ 10 | -I$(LIBEFM_PATH)/EFM32GG_STK3700/config 11 | TARGET_FLAGS = -mthumb -mcpu=cortex-m3 -mfix-cortex-m3-ldrd 12 | TARGET_CFLAGS = $(TARGET_FLAGS) -D__EFM32__ -DEFM32GG990F1024 13 | #TARGET_LDFLAGS = $(TARGET_FLAGS) --static -nostdlib -nostartfiles -Tstm32/f1/stm32f100x6.ld \ 14 | # -Wl,--build-id=none 15 | TARGET_LDFLAGS = -Xlinker -Map=lst/blink.map $(TARGET_FLAGS) \ 16 | --static -nostdlib -nostartfiles -Wl,--build-id=none \ 17 | -T$(LIBEFM_PATH)/Device/EnergyMicro/EFM32GG/Source/G++/efm32gg.ld \ 18 | $(LIBEFM_PATH)/Device/EnergyMicro/EFM32GG/Source/G++/startup_efm32gg.s 19 | LDLIBS = -Wl,--start-group -lgcc -lc -lcs3 -lcs3unhosted -Wl,--end-group 20 | 21 | .PRECIOUS: $(TARGETDIR)/%.bin 22 | 23 | $(TARGETDIR)/%.bin: $(TARGETDIR)/% 24 | $(OBJCOPY) -O binary $^ $@ 25 | 26 | deploy-%: $(TARGETDIR)/%.bin 27 | st-flash write $^ 0x8000000 28 | -------------------------------------------------------------------------------- /Makefile.rules.i686-linux-gnu: -------------------------------------------------------------------------------- 1 | OBJDUMP = objdump 2 | #TARGET_CFLAGS = -S 3 | GCC_VER = -4.8 4 | TARGET_CFLAGS = -std=c++11 5 | -------------------------------------------------------------------------------- /Makefile.rules.msp430: -------------------------------------------------------------------------------- 1 | #GCC_PATH = /opt/mspgcc-4.7/bin/ 2 | 3 | MCU = msp430g2553 4 | TARGET_FLAGS = -mmcu=$(MCU) 5 | # Can select specific device if multiple connected at the same time, 6 | # format "-s " or "-U ", see mspdebug --help 7 | DEVICE_SELECT ?= 8 | 9 | 10 | deploy-%: $(TARGETDIR)/% 11 | mspdebug $(DEVICE_SELECT) rf2500 "prog $^" 12 | -------------------------------------------------------------------------------- /Makefile.rules.msp430-llvm: -------------------------------------------------------------------------------- 1 | LLVM_PATH = /home/pfalcon/projects-3rdparty/llvm-3.0.src/Debug/bin 2 | OPT = $(LLVM_PATH)/opt 3 | LLC = $(LLVM_PATH)/llc 4 | CROSS_COMPILE = msp430- 5 | 6 | MCU = msp430g2553 7 | TARGET_FLAGS = -mmcu=$(MCU) 8 | # Can select specific device if multiple connected at the same time, 9 | # format "-s " or "-U ", see mspdebug --help 10 | DEVICE_SELECT ?= 11 | 12 | CLANGFLAGS = -ccc-host-triple msp430 -D__MSP430G2553__ -I/usr/msp430/include -m32 -emit-llvm 13 | OPTFLAGS = -std-compile-opts -strip-debug -disable-simplify-libcalls 14 | LLCFLAGS = -march=msp430 15 | 16 | OVERRIDE_RULES = 1 17 | 18 | $(TARGETDIR)/%.o: %.cpp 19 | mkdir -p $(TARGETDIR) 20 | clang $(ALL_CXXFLAGS) $(CLANGFLAGS) -S -c $^ -o $@.ll 21 | $(OPT) $(OPTFLAGS) -S $@.ll -f -o $@.opt.ll 22 | 23 | $(LLC) $(LLCFLAGS) $@.opt.ll -o $@.opt.s_ 24 | 25 | awk '/.globl\tmain/ { print "\t.section\t.init9,\"ax\",@progbits"; } \ 26 | { print }' $@.opt.s_ > $@.opt.s 27 | msp430-as $@.opt.s -o $@ 28 | 29 | deploy-%: $(TARGETDIR)/% 30 | mspdebug $(DEVICE_SELECT) rf2500 "prog $^" 31 | -------------------------------------------------------------------------------- /Makefile.rules.msp430-llvm-c: -------------------------------------------------------------------------------- 1 | LLVM_PATH = /home/pfalcon/projects-3rdparty/llvm-3.0.src/Debug/bin 2 | OPT = $(LLVM_PATH)/opt 3 | LLC = $(LLVM_PATH)/llc 4 | CROSS_COMPILE = msp430- 5 | 6 | MCU = msp430g2553 7 | TARGET_FLAGS = -mmcu=$(MCU) 8 | # Can select specific device if multiple connected at the same time, 9 | # format "-s " or "-U ", see mspdebug --help 10 | DEVICE_SELECT ?= 11 | 12 | CLANGFLAGS = -ccc-host-triple msp430 -D__MSP430G2553__ -I/usr/msp430/include -m32 -emit-llvm 13 | OPTFLAGS = -std-compile-opts -strip-debug -disable-simplify-libcalls 14 | LLCFLAGS = -march=msp430 15 | 16 | OVERRIDE_RULES = 1 17 | 18 | $(TARGETDIR)/%.o: %.cpp 19 | mkdir -p $(TARGETDIR) 20 | clang $(ALL_CXXFLAGS) $(CLANGFLAGS) -S -c $^ -o $@.ll 21 | $(OPT) $(OPTFLAGS) -S $@.ll -f -o $@.opt.ll 22 | 23 | $(LLC) -march=c $@.opt.ll -o $@.cbackend.c 24 | clang $(ALL_CXXFLAGS) $(CLANGFLAGS) -S -c $@.cbackend.c -o $@.cbackend.ll 25 | $(OPT) $(OPTFLAGS) $@.cbackend.ll -f -S -o $@.cbackend.opt.ll 26 | $(LLC) $(LLCFLAGS) $@.cbackend.opt.ll -o $@.opt.s_ 27 | 28 | awk '/.globl\tmain/ { print "\t.section\t.init9,\"ax\",@progbits"; } \ 29 | { print }' $@.opt.s_ > $@.opt.s 30 | msp430-as $@.opt.s -o $@ 31 | 32 | deploy-%: $(TARGETDIR)/% 33 | mspdebug $(DEVICE_SELECT) rf2500 "prog $^" 34 | -------------------------------------------------------------------------------- /Makefile.rules.stm32: -------------------------------------------------------------------------------- 1 | CMSIS_PATH = /home/pfalcon/projects-3rdparty/CMSIS/STM/CMSIS/CM3 2 | # CMSIS includes consist of two sets: "core", supplied by ARM, 3 | # and "device", supplied by silicon vendor. 4 | CMSIS_CORE_INCLUDE = -I$(LIBPERIPHA_PATH)/arm/cortex-m/arm-cmsis/CMSIS/Include 5 | CMSIS_DEVICE_INCLUDE = -I$(CMSIS_PATH)/DeviceSupport/ST/STM32F10x 6 | #CMSIS_STARTUP = $(CMSIS_PATH)/DeviceSupport/ST/STM32F10x/startup/gcc_ride7/startup_stm32f10x_md_vl.s 7 | #CMSIS_SYSTEM = $(CMSIS_PATH)/DeviceSupport/ST/STM32F10x/system_stm32f10x.c 8 | 9 | STARTUP = $(CORTEX_STARTUP_PATH)/startup.c 10 | # No need to specify full path to linker script, will be searched in -L 11 | LINKSCRIPT = stm32/stm32-smallest.ld 12 | 13 | #DEVICE_INCLUDE = $(CMSIS_CORE_INCLUDE) $(CMSIS_DEVICE_INCLUDE) 14 | DEVICE_INCLUDE = -I$(LIBPERIPHA_PATH) $(CMSIS_CORE_INCLUDE) -DLIBPERIPHA -DCORTEX_M3 15 | 16 | CROSS_COMPILE = arm-none-eabi- 17 | #GCC_VER = -4.4 18 | TARGET_INCLUDE = $(DEVICE_INCLUDE) -I$(CORTEX_STARTUP_PATH) 19 | TARGET_FLAGS = -mthumb -mcpu=cortex-m3 -DNO_SYSTEMINIT -D__STM32__ -DSTM32F1 -DSTM32F10X_MD_VL 20 | TARGET_CFLAGS = $(TARGET_FLAGS) 21 | TARGET_LDFLAGS = $(TARGET_CFLAGS) $(TARGET_INCLUDE) --static -nostdlib -nostartfiles -T$(LINKSCRIPT) \ 22 | -Wl,--build-id=none $(CMSIS_SYSTEM) $(STARTUP) 23 | LDLIBS = -L$(CORTEX_STARTUP_PATH) -lgcc 24 | 25 | 26 | .PRECIOUS: $(TARGETDIR)/%.bin 27 | 28 | $(TARGETDIR)/%.bin: $(TARGETDIR)/% 29 | $(OBJCOPY) -O binary $^ $@ 30 | 31 | deploy-%: $(TARGETDIR)/%.bin 32 | st-flash write $^ 0x8000000 33 | -------------------------------------------------------------------------------- /Makefile.rules.tm4: -------------------------------------------------------------------------------- 1 | CMSIS_CORE_INCLUDE = -I$(LIBPERIPHA_PATH)/arm/cortex-m/arm-cmsis/CMSIS/Include 2 | STARTUP = $(CORTEX_STARTUP_PATH)/startup.c 3 | # No need to specify full path to linker script, will be searched in -L 4 | LINKSCRIPT = tm4/lm4f120h5qr.ld 5 | 6 | DEVICE_INCLUDE = -I$(LIBPERIPHA_PATH) $(CMSIS_CORE_INCLUDE) -DLIBPERIPHA -DCORTEX_M3 7 | 8 | CROSS_COMPILE = arm-none-eabi- 9 | #GCC_VER = -4.4 10 | TARGET_INCLUDE = $(DEVICE_INCLUDE) -I$(CORTEX_STARTUP_PATH) 11 | TARGET_FLAGS = -mthumb -mcpu=cortex-m3 -DNO_SYSTEMINIT -D__LM4__ -D__TM4__ 12 | TARGET_CFLAGS = $(TARGET_FLAGS) 13 | TARGET_LDFLAGS = $(TARGET_CFLAGS) $(TARGET_INCLUDE) --static -nostdlib -nostartfiles -T$(LINKSCRIPT) \ 14 | -Wl,--build-id=none $(CMSIS_SYSTEM) $(STARTUP) 15 | LDLIBS = -L$(CORTEX_STARTUP_PATH) -lgcc 16 | 17 | 18 | .PRECIOUS: $(TARGETDIR)/%.bin 19 | 20 | $(TARGETDIR)/%.bin: $(TARGETDIR)/% 21 | $(OBJCOPY) -O binary $^ $@ 22 | 23 | deploy-%: $(TARGETDIR)/%.bin 24 | lm4flash $^ 25 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Peripheral Template Library 2 | =========================== 3 | 4 | Peripheral Template Library is a project to develop an efficient 5 | cross-platform library for microcontrollers. It provides 6 | consistent API to control basic blocks of any microcontroller - 7 | GPIO, timers, clocks, ADC, etc., then provides API/implementation of 8 | standard protocols to access peripheral devices, like SPI, I2C, UART, 9 | 1-Wire, etc. 10 | 11 | To achieve high-level efficiency, PTL is built using (C++) templated static 12 | types, allowing to apply aggressive compile-time optimizations, 13 | achieving the efficiency level of the C code purposedly written for 14 | specific MCU. Using templates also allows to provide optimized protocol 15 | implementations utilizing specialized MCU hardware blocks like SPI/I2C 16 | controllers (default implementations provided use bitbanging over GPIO). 17 | 18 | The library is currently achieving inital code stabilization, though APIs 19 | are still not stable, there're lot of refactoring to do, and there may be 20 | some non-ideal C++ code around. 21 | 22 | Current targets supported (together with example boards) are: 23 | 24 | * TI MSP430 25 | * MSP430 Launchpad 26 | * Atmel AVR 27 | * Arduino Duemilanove 28 | * ARM Cortex-M 29 | * ST STM32 30 | * STM32VLDISCOVERY 31 | * Energy Micro EFM32 32 | * EFM32GG-STK3700 33 | * TI Tiva C TM4 (former Stellaris LM4) 34 | * Stellaris/Tiva Launchpad 35 | 36 | Note that different targets have different level of hardware support. 37 | 38 | For setup instructions, refer to docs/getting_started.markdown 39 | (https://github.com/pfalcon/PeripheralTemplateLibrary/blob/master/docs/getting_started.markdown 40 | online). More documentation is available in docs/ directory. 41 | 42 | The Peripheral Template Library is licensed under GNU Lesser General Public 43 | License (LGPL), version 3 or later. Please review detailed terms in the 44 | included LICENSE file. 45 | 46 | Author: Paul Sokolovsky {pfalcon at users.sourceforge.net} 47 | -------------------------------------------------------------------------------- /docs/FAQ: -------------------------------------------------------------------------------- 1 | Q: 2 | I have in my program: 3 | 4 | timer::delay(20000); 5 | 6 | And get following compiler error on it: 7 | 8 | blink_timer.cpp:15:27: error: call of overloaded ‘delay(int)’ is ambiguous 9 | 10 | A: 11 | First of all, delay value is by definition unsigned - you can't turn back 12 | time. PTL is also highly optimized library, for example for 8/16 bit MCUs, 13 | it usually provides two delay implementation - separately for 16 bit and 14 | 32 bit delay values. Last final note is that integer constants in C/C++ 15 | are by default signed. And that last fact actually leads to ambiguities. 16 | For example, consider call like "timer::delay(65535)". You may think that 17 | it would use optimized 16 bit implementation, as 65535 fits perfectly 18 | in 16 bit. But actually, that's not the case, because for *signed* 19 | 16 bit integer value range is [-32768, 32767]. So, 65535 doesn't have 20 | type "integer", but instead "long", and for it "heavy" 32 bit 21 | implementation will be selected. Instead of silently allowing such 22 | hardly expected behavior, it was decided to explicitly remind programmer 23 | to use unsigned values for delays. So, just use "U" suffix (recommended), 24 | or explicitly cast value to uint type: 25 | 26 | timer::delay(20000U); 27 | timer::delay((uint16_t)20000); 28 | -------------------------------------------------------------------------------- /docs/coding_conventions.txt: -------------------------------------------------------------------------------- 1 | PTL tries to stick to C++03 whenever possible, and not use C++11 features. 2 | That's because many embedded targets did not yet upgrade to recent versions 3 | of gcc (4.7+). 4 | 5 | So, following (very useful) C++11 features are avoided for now: 6 | 7 | * Variadic templates 8 | * constexpr 9 | * Static assertions 10 | * etc. 11 | 12 | It's expected that these restrictions will be lifted once newer gcc versions 13 | are better leveraged in embedded community. 14 | 15 | 16 | -------------------------------------------------------------------------------- /docs/contributing.txt: -------------------------------------------------------------------------------- 1 | Peripheral Template Library is currently licensed under the terms of LGPLv3, 2 | though it's considered to either add linking exception clause or switch to 3 | BSD-like license. To facilitate such change in the future, only BSD/MIT 4 | licensed third-party code is merged, and contributors are asked to license 5 | their patches under dual LGPL3/BSD license (or alternatively, just under BSD 6 | license). 7 | 8 | The rationale of this request is that, if such licensing change is carried 9 | out in the future, all contributors will need to be contacted to ask their 10 | permissions to relicense, with possible complications that some contributors 11 | won't respond, or will be against such change. So, instead I'm asking all 12 | potential contributors about BSD licensing right away. I hope this makes 13 | sense and reasonably fair. 14 | 15 | If you have suggestions regarding licensing, please feel free to bring them 16 | up. 17 | -------------------------------------------------------------------------------- /docs/irq_handling.txt: -------------------------------------------------------------------------------- 1 | Interrupt handling is too idiosyncratic across various MCUs. As a basic 2 | example, in different MCUs peripheral blocks of similar function (timers, 3 | UARTs, etc.) may have different number of IRQs and their exact semantics. 4 | More specific example, MSP430 has separate serial interface interrupts for 5 | RX and TX, but each of them is shared by different serial interface units. 6 | For timers, MSP430 has a dedicated IRQ for one of compare channels. Another 7 | IRQ is used for all other timer events - other compare channels, timer 8 | overflow. Most IRQs in MSP430 are auto-acknowledged, but this second timer 9 | IRQ requires explicit acknowledgement. Etc., etc. 10 | 11 | So, while PTL allows to specify handlers for such MCU-specific IRQs, such 12 | approach is obviously not portable (but it is the most efficient approach 13 | of course). 14 | 15 | To achieve better cross-platform support, there are 3 other approches: 16 | 17 | 1. Asynchronous approach with main loop. This approach doesn't use 18 | interrupt handlers explicitly at all. Instead, interrupt/ready flags 19 | are manually checked in a main loop with dispatching to appropriate 20 | handlers/code. 21 | 22 | 2. Proxy low-level handler approach. MCU-specific IRQ handler would 23 | dispatch to abstracted, semantically orthoginal user handlers. For example, 24 | in timer example above, there would be separate PTL handlers for each 25 | of compare events and timer overflow, and default implementation of 26 | MSP430 IRQ handlers dispatching to them. This approach also has overhead, 27 | but at least it is constant (with the previous approach, it would be 28 | proportional to number of events to handle). Other drawback though is that 29 | simple low-level IRQ handler implementation will have extra checks even 30 | for events not used in the code. For example, if we're interested in 31 | timer overflow only, it makes no sense to dispatch on compare events. 32 | This issue might be solved using templates though. 33 | 34 | 3. Mix of the 2 approaches above: make default IRQ handlers produce 35 | "event number", then main loop to dispatch on the last event. This may 36 | allow to do constant-time dispatch (at the price of program memory storing 37 | code pointers). 38 | 39 | 40 | For half-way approach towards p.2, see timer_irq_dispatch_msp430.hpp . This 41 | allows to define IRQ handlers for all events support by particular MCU, and 42 | as efficiently as possible to dispatch to them, but not be concerned with 43 | mapping of specific IRQ vectors to IRQ handlers (including one-to-many cases, 44 | IRQ acknowledgement, etc). 45 | -------------------------------------------------------------------------------- /docs/new_target.txt: -------------------------------------------------------------------------------- 1 | Adding new target 2 | ================= 3 | 4 | To add new target, following areas should be covered: 5 | 6 | 1. CPU initialization (in most cases this is simple or null). 7 | 2. GPIO 8 | 3. Timer 9 | 10 | With this, it should be possible to use most of bitbanging 11 | protocols, if CPU provides enough speed. For more fine-grained 12 | bitbang protocol support, following is useful: 13 | 14 | 4. StaticDelay 15 | 16 | Having hardware UART is quite helpful for debugging and host 17 | communication overall. 18 | 19 | 5. Hardware UART 20 | 21 | Further hardware features can be added on-demand depending on 22 | particular application. 23 | -------------------------------------------------------------------------------- /examples/1wire.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include <1wire.hpp> 10 | 11 | using namespace PTL; 12 | 13 | #define READ_ROM 0x33 14 | #define SKIP_ROM 0xCC 15 | #define READ_POWER_SUPPLY 0xB4 16 | #define CONVERT_T 0x44 17 | #define READ_SCRATCHPAD 0xBE 18 | 19 | typedef TimeDelay<8 MHZ, StaticDelay> delayer; 20 | typedef UART<8 MHZ, 9600, Pin, Pin, timer> uart; 21 | typedef OneWire< Pin, timer > onewire; 22 | typedef Console con; 23 | 24 | uint8_t crc8(uint8_t *buf, int len); 25 | 26 | void read_scratchpad(const char *msg, uint8_t *buf) 27 | { 28 | bool res = onewire::reset(); 29 | con::putstr("Presence: "); 30 | con::puthex8(res); 31 | con::newline(); 32 | 33 | onewire::write(SKIP_ROM); 34 | onewire::write(READ_SCRATCHPAD); 35 | onewire::read_block(buf, 9); 36 | con::putstr(msg); 37 | con::puthex8(buf, 9); 38 | con::putc(' '); 39 | 40 | uint8_t crc = crc8(buf, 9); 41 | con::puthex8(crc); 42 | con::newline(); 43 | } 44 | 45 | int main() 46 | { 47 | cpu::init(cpu::FREQ_8MHZ); 48 | timer::free_run(); 49 | uart::init(); 50 | onewire::init(); 51 | 52 | while (1) { 53 | uint8_t buf[9]; 54 | uart::read(); 55 | 56 | bool res = onewire::reset(); 57 | con::putstr("Initial presence: "); 58 | con::puthex8(res); 59 | con::newline(); 60 | 61 | onewire::write(SKIP_ROM); 62 | onewire::write(READ_POWER_SUPPLY); 63 | uint8_t b = onewire::read(); 64 | con::putstr("Power status: "); 65 | con::puthex8(b); 66 | con::newline(); 67 | 68 | onewire::reset(); 69 | onewire::write(READ_ROM); 70 | onewire::read_block(buf, 8); 71 | con::putstr("Address: "); 72 | con::puthex8(buf, 8); 73 | con::putc(' '); 74 | con::puthex8(crc8(buf, 8)); 75 | con::newline(); 76 | 77 | read_scratchpad("Before measurement: ", buf); 78 | 79 | onewire::reset(); 80 | onewire::write(SKIP_ROM); 81 | onewire::write(CONVERT_T); 82 | onewire::bus_power(); 83 | delayer::delay_ms(800); 84 | 85 | read_scratchpad("After measurement: ", buf); 86 | con::newline(); 87 | } 88 | } 89 | 90 | // Based on http://en.wikipedia.org/wiki/Computation_of_CRC#Parallel_computation_without_table 91 | uint8_t crc8(uint8_t *buf, int len) 92 | { 93 | uint8_t c = 0; 94 | for (int i = len; len; len--) { 95 | uint8_t d = *buf++, e, f, r; 96 | e = c ^ d; 97 | f = e ^ (e << 3) ^ (e << 4) ^ (e << 6); 98 | r = f ^ (f >> 4) ^ (f >> 5); 99 | c = r; 100 | } 101 | return c; 102 | } 103 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | PTL_PATH = .. 2 | include $(PTL_PATH)/Makefile.rules 3 | 4 | ALL = blink blink_static blink_dynamic blink_timer blink_ticks \ 5 | blink_sleep blink_bus blink_dynapin blink_c \ 6 | uart_echo uart_echo_irq uart_echo_async uart_echo_buffered \ 7 | uart_printf \ 8 | spi i2c_24cxx 1wire adc \ 9 | timer_irq timer_irq_dispatch irq_dispatch irq_dispatch_simple \ 10 | flash \ 11 | perf_counter lcd lcd_nokia \ 12 | msp430_parse_tlv 13 | 14 | .PHONY: $(ALL) 15 | 16 | all: $(ALL) 17 | 18 | blink: $(TARGETDIR)/blink 19 | blink_static: $(TARGETDIR)/blink_static 20 | blink_dynamic: $(TARGETDIR)/blink_dynamic 21 | blink_timer: $(TARGETDIR)/blink_timer 22 | blink_ticks: $(TARGETDIR)/blink_ticks 23 | blink_sleep: $(TARGETDIR)/blink_sleep 24 | blink_bus: $(TARGETDIR)/blink_bus 25 | blink_dynapin: $(TARGETDIR)/blink_dynapin 26 | blink_c: $(TARGETDIR)/blink_c 27 | uart_echo: $(TARGETDIR)/uart_echo 28 | uart_echo_irq: $(TARGETDIR)/uart_echo_irq 29 | uart_echo_async: $(TARGETDIR)/uart_echo_async 30 | uart_echo_buffered: $(TARGETDIR)/uart_echo_buffered 31 | uart_printf: $(TARGETDIR)/uart_printf 32 | spi: $(TARGETDIR)/spi 33 | i2c_24cxx: $(TARGETDIR)/i2c_24cxx 34 | 1wire: $(TARGETDIR)/1wire 35 | adc: $(TARGETDIR)/adc 36 | timer_irq: $(TARGETDIR)/timer_irq 37 | timer_irq_dispatch: $(TARGETDIR)/timer_irq_dispatch 38 | irq_dispatch_simple: $(TARGETDIR)/irq_dispatch_simple 39 | irq_dispatch: $(TARGETDIR)/irq_dispatch 40 | flash: $(TARGETDIR)/flash 41 | perf_counter: $(TARGETDIR)/perf_counter 42 | lcd: $(TARGETDIR)/lcd 43 | lcd_nokia: $(TARGETDIR)/lcd_nokia 44 | msp430_parse_tlv: $(TARGETDIR)/msp430_parse_tlv 45 | 46 | $(TARGETDIR)/blink: $(TARGETDIR)/blink.o 47 | $(TARGETDIR)/blink.o: blink.cpp 48 | 49 | $(TARGETDIR)/blink_static: $(TARGETDIR)/blink_static.o 50 | $(TARGETDIR)/blink_static.o: blink_static.cpp 51 | 52 | $(TARGETDIR)/blink_dynamic: $(TARGETDIR)/blink_dynamic.o 53 | $(TARGETDIR)/blink_dynamic.o: blink_dynamic.cpp 54 | 55 | $(TARGETDIR)/blink_timer: $(TARGETDIR)/blink_timer.o 56 | $(TARGETDIR)/blink_timer.o: blink_timer.cpp 57 | 58 | $(TARGETDIR)/blink_ticks: $(TARGETDIR)/blink_ticks.o 59 | $(TARGETDIR)/blink_ticks.o: blink_ticks.cpp 60 | 61 | $(TARGETDIR)/blink_bus: $(TARGETDIR)/blink_bus.o 62 | $(TARGETDIR)/blink_bus.o: blink_bus.cpp 63 | 64 | $(TARGETDIR)/blink_c: $(TARGETDIR)/blink_c.o $(TARGETDIR)/blink_c_api.o 65 | 66 | $(TARGETDIR)/uart_echo: $(TARGETDIR)/uart_echo.o 67 | $(TARGETDIR)/uart_echo.o: uart_echo.cpp 68 | 69 | $(TARGETDIR)/spi: $(TARGETDIR)/spi.o 70 | $(TARGETDIR)/spi.o: spi.cpp 71 | 72 | $(TARGETDIR)/i2c_24cxx: $(TARGETDIR)/i2c_24cxx.o 73 | $(TARGETDIR)/i2c_24cxx.o: i2c_24cxx.cpp 74 | 75 | $(TARGETDIR)/1wire: $(TARGETDIR)/1wire.o 76 | $(TARGETDIR)/1wire.o: 1wire.cpp 77 | 78 | $(TARGETDIR)/adc: $(TARGETDIR)/adc.o 79 | $(TARGETDIR)/adc.o: adc.cpp 80 | 81 | $(TARGETDIR)/lcd: $(TARGETDIR)/lcd.o 82 | $(TARGETDIR)/lcd.o: lcd.cpp 83 | 84 | $(TARGETDIR)/irq_dispatch: $(TARGETDIR)/irq_dispatch.o 85 | $(TARGETDIR)/irq_dispatch_simple: $(TARGETDIR)/irq_dispatch_simple.o 86 | -------------------------------------------------------------------------------- /examples/adc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace PTL; 10 | 11 | typedef UART<1 MHZ, 9600, Pin, Pin, timer> uart; 12 | typedef Console con; 13 | typedef ADC adc; 14 | 15 | int main() 16 | { 17 | cpu::init(cpu::DEFAULT); 18 | timer::free_run(); 19 | uart::init(); 20 | adc::unlock(); 21 | adc::config(); 22 | while (1) { 23 | uart::read(); 24 | adc::width value = adc::easy_sample(adc::VCC_HALF); 25 | con::putdec(value); 26 | con::newline(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/blink.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace PTL; 8 | 9 | typedef TimeDelay delayer; 10 | 11 | int main() 12 | { 13 | cpu::init(cpu::DEFAULT); 14 | board::LED::port::enable(); 15 | board::LED::output(); 16 | while (true) { 17 | board::LED::high(); 18 | delayer::delay_ms(500); 19 | board::LED::low(); 20 | delayer::delay_ms(500); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/blink_bus.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | using namespace PTL; 8 | 9 | typedef StaticDelay delayer; 10 | typedef ParBus leds; 11 | 12 | int main() 13 | { 14 | cpu::init(cpu::DEFAULT); 15 | leds::enable(); 16 | leds::output(); 17 | int i = 0; 18 | while (true) { 19 | leds::write(i++ % 4); 20 | delayer::delay(3000000U); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/blink_c.c: -------------------------------------------------------------------------------- 1 | #include "blink_c_api.h" 2 | 3 | int main() 4 | { 5 | init(); 6 | while (1) { 7 | led_high(); 8 | delay(100000U); 9 | led_low(); 10 | delay(100000U); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/blink_c_api.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "blink_c_api.h" 6 | 7 | using namespace PTL; 8 | 9 | typedef Delay delayer; 10 | 11 | void led_high() 12 | { 13 | board::LED::high(); 14 | } 15 | 16 | void led_low() 17 | { 18 | board::LED::low(); 19 | } 20 | 21 | void delay(uint32_t val) 22 | { 23 | delayer::delay(val); 24 | } 25 | 26 | void init() 27 | { 28 | cpu::init(cpu::DEFAULT); 29 | board::LED::port::enable(); 30 | board::LED::output(); 31 | } 32 | -------------------------------------------------------------------------------- /examples/blink_c_api.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | void init(); 8 | void led_high(); 9 | void led_low(); 10 | void delay(uint32_t val); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /examples/blink_dynamic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace PTL; 7 | 8 | typedef Delay delayer; 9 | 10 | int main() 11 | { 12 | cpu::init(cpu::DEFAULT); 13 | board::LED::port::enable(); 14 | board::LED::output(); 15 | while (true) { 16 | board::LED::high(); 17 | delayer::delay(100000U); 18 | board::LED::low(); 19 | delayer::delay(100000U); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/blink_dynapin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace PTL; 9 | 10 | typedef TimeDelay delayer; 11 | 12 | //DynaPin_Store led_spec = {board::LED::port::base, board::LED::bit::value}; 13 | DynaPin_Store led_spec(board::LED::port::no, board::LED::bit::shift); 14 | typedef DynaPin dynaLED; 15 | 16 | int main() 17 | { 18 | cpu::init(cpu::DEFAULT); 19 | dynaLED::port::enable(); 20 | dynaLED::output(); 21 | while (true) { 22 | dynaLED::high(); 23 | delayer::delay_ms(500); 24 | dynaLED::low(); 25 | delayer::delay_ms(500); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/blink_sleep.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace PTL; 9 | 10 | int main() 11 | { 12 | cpu::init(cpu::DEFAULT); 13 | ACLK::source(); 14 | board::LED::port::enable(); 15 | board::LED::output(); 16 | while (true) { 17 | board::LED::toggle(); 18 | Sleep::sleep(Watchdog::INTERVAL_512); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/blink_static.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace PTL; 7 | 8 | typedef StaticDelay delayer; 9 | typedef board::LED led; 10 | 11 | 12 | int main() 13 | { 14 | cpu::init(cpu::DEFAULT); 15 | led::port::enable(); 16 | led::output(); 17 | while (true) { 18 | led::high(); 19 | delayer::delay(1000000U); 20 | led::low(); 21 | delayer::delay(1000000U); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/blink_ticks.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace PTL; 9 | 10 | typedef Ticks<> delayer; 11 | typedef board::LED led; 12 | 13 | // For Ticks to actually work, we must route hardware timer 14 | // interrupts to it 15 | IRQ_DISPATCH(delayer::timer_handlers); 16 | 17 | int main() 18 | { 19 | cpu::init(cpu::DEFAULT); 20 | led::port::enable(); 21 | led::output(); 22 | timer::free_run(); 23 | timer::enable_irq(); 24 | cpu::enable_irq(); 25 | while (true) { 26 | led::low(); 27 | delayer::delay(10); 28 | led::high(); 29 | delayer::delay(10); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/blink_timer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace PTL; 7 | 8 | typedef timer delayer; 9 | typedef board::LED led; 10 | 11 | int main() 12 | { 13 | cpu::init(cpu::DEFAULT); 14 | led::port::enable(); 15 | led::output(); 16 | timer::free_run(); 17 | while (true) { 18 | led::high(); 19 | delayer::delay(1000000U); 20 | led::low(); 21 | delayer::delay(1000000U); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/flash.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace PTL; 10 | 11 | typedef UART<1 MHZ, 9600, Pin, Pin, timer> uart; 12 | //typedef UART<1 MHZ, 9600, USCI> uart; 13 | typedef Console con; 14 | 15 | int main() 16 | { 17 | cpu::init(cpu::DEFAULT); 18 | timer::free_run(); 19 | uart::init(); 20 | 21 | Flash::init(); 22 | 23 | uart::read(); 24 | 25 | con::putstr("Current value: "); 26 | con::puthex16(*(uint16_t*)FLASH_SEGMENT_D); 27 | con::newline(); 28 | 29 | Flash::erase((uint16_t*)FLASH_SEGMENT_D); 30 | con::putstr("After erase: "); 31 | con::puthex16(*(uint16_t*)FLASH_SEGMENT_D); 32 | con::newline(); 33 | 34 | con::putstr("After write: "); 35 | Flash::write16((uint16_t*)FLASH_SEGMENT_D, 0x1234); 36 | con::puthex16(*(uint16_t*)FLASH_SEGMENT_D); 37 | con::newline(); 38 | } 39 | -------------------------------------------------------------------------------- /examples/hw_config_avr.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace PTL; 4 | 5 | typedef board::uart hwuart; 6 | typedef hwuart uart; 7 | 8 | typedef ParBus hd44780_data; 9 | typedef Signal hd44780_en_sig; 10 | typedef Signal hd44780_regsel_sig; 11 | 12 | typedef board::D3 pcd8544_sclk; 13 | typedef board::D4 pcd8544_sdin; 14 | typedef board::D5 pcd8544_dc; 15 | typedef board::D6 pcd8544_reset; 16 | typedef board::D7 pcd8544_sce; 17 | -------------------------------------------------------------------------------- /examples/hw_config_msp430.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace PTL; 7 | 8 | //#define LAUNCHPAD_MSP430_VER_1_4 9 | 10 | #ifndef LAUNCHPAD_MSP430_VER_1_4 11 | 12 | /* MSP430 Launchpad hw. rev. 1.5 has different (swapped) pin assignments for 13 | "software" and "hardware" UART. This is rooted in the fact that hwrev. 1.4 14 | had "software" assignment, but later released chips with hardware UART 15 | had them swapped. TI decided to keep compatibility with "software" UART 16 | of 1.4, by providing jumpers allowing to swap pins. Obviously, that means 17 | that you need to switch jumpers each time to go from hardware to software 18 | UART and back, which is quite inconvinient. So, PTL abandons TI's "software" 19 | UART assignment, and instead uses just same pins as hardware UART. 20 | Bottom line: put jumpers in hardware UART position (perpindicular to other 21 | jumpers) and forget about it (while you're working with PTL). See below for 22 | 1.4 support. 23 | More info: http://pfalcon-oe.blogspot.com/2012/07/ti-launchpad-14-vs-15-pin-swappery.html 24 | */ 25 | typedef UART<1 MHZ, 9600, USCI_A> hwuart; 26 | //typedef UART uart; 27 | typedef UART<1 MHZ, 9600, USCI_A> uart; 28 | 29 | /* At this time, only USCI-based hardware SPI is supported, USI still needs 30 | wrapping. Note that USCI vs USI SPI pins have the same swapping issue as UART 31 | above (great work, TI!) */ 32 | typedef SPI spi; 33 | 34 | #else 35 | 36 | /* MSP430 Launchpad hw. rev. 1.4 doesn't have hardware UART support at all, 37 | and bitbang UART has to use swapped RXD/TXD pins. */ 38 | typedef UART, Pin, timer> uart; 39 | 40 | #endif 41 | 42 | typedef ParBus< Pin, Pin, Pin, Pin > hd44780_data; 43 | typedef Signal< Pin > hd44780_en_sig; 44 | typedef Signal< Pin > hd44780_regsel_sig; 45 | 46 | typedef Pin pcd8544_sclk; 47 | typedef Pin pcd8544_sdin; 48 | typedef Pin pcd8544_dc; 49 | typedef Pin pcd8544_reset; 50 | typedef Pin pcd8544_sce; 51 | -------------------------------------------------------------------------------- /examples/hw_config_stm32.hpp: -------------------------------------------------------------------------------- 1 | using namespace PTL; 2 | -------------------------------------------------------------------------------- /examples/hw_config_tm4.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace PTL; 4 | 5 | typedef UART<16 MHZ, 115200, UART0_> hwuart; 6 | typedef hwuart uart; 7 | -------------------------------------------------------------------------------- /examples/hw_config_tutorial/blink1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | * Simplest blink application - we use typedef to define delayer, 9 | * because it's too long to repeat, but use board::LED directly, 10 | * because it's, well, easy and obvious. 11 | * 12 | * However, if we'll want to blink another LED (board:LED2, or 13 | * custom one), we'll need to replace board::LED in several places. 14 | * So, let's proceed to blink2. 15 | */ 16 | 17 | typedef TimeDelay delayer; 18 | 19 | int main() 20 | { 21 | cpu::init(cpu::DEFAULT); 22 | board::LED::port::enable(); 23 | board::LED::output(); 24 | while (true) { 25 | board::LED::high(); 26 | delayer::delay_ms(500); 27 | board::LED::low(); 28 | delayer::delay_ms(500); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/hw_config_tutorial/blink2.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | * Here, we (type)define led blink once at the beginning of the 9 | * program, so it's easy to redefine it to board::LED2, 10 | * Pin or whatever. 11 | * 12 | * However, what if our application is not such simple, consists 13 | * of many modules, or targetted several completely different boards? 14 | * Proceed to blink3. 15 | */ 16 | 17 | typedef TimeDelay delayer; 18 | typedef board::LED led; 19 | 20 | int main() 21 | { 22 | cpu::init(cpu::DEFAULT); 23 | led::port::enable(); 24 | led::output(); 25 | while (true) { 26 | led::high(); 27 | delayer::delay_ms(500); 28 | led::low(); 29 | delayer::delay_ms(500); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /examples/hw_config_tutorial/blink3.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | * Here, we just include special hardware config file, as 9 | * defined by PTL build system. All hardware-related definitions 10 | * are localized to it, and there's separate config file per 11 | * hardware target or subtarget. This means that source code 12 | * of your application does not need to be changed for particular 13 | * hardware setup, and you can add and change new hardware 14 | * setups without affecting other. Hardware config is essentially 15 | * just that - configuration file, so configuration of your 16 | * application for particular hardware target is essentially 17 | * data driven (syntax used in hardware config file is of course 18 | * C++, but that means that it's familiar and expressive). 19 | * 20 | * HW_CONFIG by default expands to "hw_config_$(TARGET).hpp", 21 | * i.e. build system by default assumes that if you have different 22 | * boards, then tehy have different architectures. You can easily 23 | * make it more finegrained though, just define it in your Makefile 24 | * to some other pattern e.g.: 25 | * 26 | * HW_CONFIG = \"hw_config_$(BOARD).hpp\" 27 | * 28 | * And build like: 29 | * 30 | * make TARGET=avr BOARD=arduino my-app 31 | * make TARGET=avr BOARD=custom-v2 my-app 32 | * 33 | */ 34 | 35 | #include HW_CONFIG 36 | 37 | int main() 38 | { 39 | cpu::init(cpu::DEFAULT); 40 | led::port::enable(); 41 | led::output(); 42 | while (true) { 43 | led::high(); 44 | delayer::delay_ms(500); 45 | led::low(); 46 | delayer::delay_ms(500); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/hw_config_tutorial/hw_config_avr.hpp: -------------------------------------------------------------------------------- 1 | typedef TimeDelay delayer; 2 | typedef board::LED led; 3 | -------------------------------------------------------------------------------- /examples/i2c_24cxx.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace PTL; 10 | 11 | typedef UART<1 MHZ, 9600, Pin, Pin, timer> uart; 12 | typedef I2C< Pin, Pin, timer, 10 > i2c; 13 | 14 | int main() 15 | { 16 | cpu::init(cpu::DEFAULT); 17 | timer::free_run(); 18 | uart::init(); 19 | i2c::init(); 20 | while (1) { 21 | uart::read(); 22 | i2c::start(); 23 | bool ack1 = i2c::write(0xa0); 24 | bool ack2 = i2c::write(0); 25 | bool ack3 = i2c::write(0x66); 26 | i2c::stop(); 27 | Console::puthex8(ack1); 28 | Console::puthex8(ack2); 29 | Console::puthex8(ack3); 30 | Console::newline(); 31 | 32 | i2c::start(); 33 | ack1 = i2c::write(0xa0); 34 | ack2 = i2c::write(0); 35 | i2c::restart(); 36 | ack3 = i2c::write(0xa1); 37 | uint8_t b1 = i2c::read(true); 38 | uint8_t b2 = i2c::read(false); 39 | i2c::stop(); 40 | 41 | Console::puthex8(ack3); 42 | Console::newline(); 43 | Console::puthex8(b1); 44 | Console::puthex8(b2); 45 | Console::newline(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/irq_dispatch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include HW_CONFIG 10 | 11 | class mytimer : public timer 12 | { 13 | public: 14 | static void irq_reset() 15 | { 16 | board::LED::toggle(); 17 | } 18 | }; 19 | 20 | class myuart : public uart 21 | { 22 | public: 23 | static void irq_rx() 24 | { 25 | board::LED::toggle(); 26 | } 27 | }; 28 | 29 | class myspi : public spi 30 | { 31 | public: 32 | static void irq_rx() 33 | { 34 | board::LED2::toggle(); 35 | } 36 | }; 37 | 38 | IRQ_DISPATCH(mytimer, myuart, myspi); 39 | 40 | int main() 41 | { 42 | cpu::init(cpu::DEFAULT); 43 | board::LED::port::enable(); 44 | board::LED::output(); 45 | mytimer::free_run(); 46 | mytimer::enable_irq(); 47 | cpu::enable_irq(); 48 | while (true); 49 | } 50 | -------------------------------------------------------------------------------- /examples/irq_dispatch_simple.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include HW_CONFIG 8 | 9 | class mytimer : public timer 10 | { 11 | public: 12 | static void irq_reset() 13 | { 14 | board::LED::toggle(); 15 | } 16 | }; 17 | 18 | IRQ_DISPATCH(mytimer); 19 | 20 | int main() 21 | { 22 | cpu::init(cpu::DEFAULT); 23 | board::LED::port::enable(); 24 | board::LED::output(); 25 | mytimer::free_run(); 26 | mytimer::enable_irq(); 27 | cpu::enable_irq(); 28 | while (true); 29 | } 30 | -------------------------------------------------------------------------------- /examples/lcd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include HW_CONFIG 11 | 12 | typedef TimeDelay delayer; 13 | typedef HD44780 lcd; 14 | typedef Console lcd_con; 15 | 16 | int main() 17 | { 18 | cpu::init(cpu::DEFAULT); 19 | board::LED::port::enable(); 20 | board::LED::output(); 21 | lcd::init(); 22 | lcd_con::putstr("Hello, World!"); 23 | unsigned c = 0; 24 | while (true) { 25 | lcd::set_pos(0, 1); 26 | lcd_con::putdec(c++); 27 | delayer::delay_ms(1000); 28 | board::LED::toggle(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /examples/lcd_nokia.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include HW_CONFIG 11 | 12 | typedef TimeDelay delayer; 13 | typedef PCD8544 Lcd; 14 | Lcd lcd; 15 | typedef Console< WriterWrapper > lcd_con; 16 | 17 | int main() 18 | { 19 | cpu::init(cpu::DEFAULT); 20 | board::LED::port::enable(); 21 | board::LED::output(); 22 | lcd.begin(); 23 | lcd.setCursor(0, 0); 24 | lcd_con::putstr("Hello, \nWorld!123456"); 25 | } 26 | -------------------------------------------------------------------------------- /examples/msp430_parse_tlv.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifndef TAG_EMPTY 10 | #define TAG_EMPTY 0xfe 11 | #define TAG_DCO_30 0x01 12 | #define TAG_ADC12_1 0x08 13 | #define TAG_ADC10_1 0x10 14 | #endif 15 | 16 | typedef UART<1 MHZ, 9600, Pin, Pin, timer> uart; 17 | typedef Console con; 18 | 19 | 20 | void show_word(const char *descr, uint8_t *p) 21 | { 22 | con::putc(' '); 23 | con::putstr(descr); 24 | con::putc(' '); 25 | con::puthex16(*(uint16_t*)p); 26 | con::newline(); 27 | } 28 | 29 | int main() 30 | { 31 | cpu::init(cpu::DEFAULT); 32 | timer::free_run(); 33 | uart::init(); 34 | 35 | while (1) { 36 | uart::read(); 37 | for (uint8_t *p = (uint8_t*)0x10c2; p < (uint8_t*)0x1100;) { 38 | uint8_t tag = *p++; 39 | switch (tag) { 40 | case TAG_EMPTY: 41 | con::putstr("TAG_EMPTY"); 42 | break; 43 | case TAG_DCO_30: 44 | con::putstr("TAG_DCO_30"); 45 | break; 46 | case TAG_ADC12_1: 47 | con::putstr("TAG_ADC12_1"); 48 | break; 49 | case TAG_ADC10_1: 50 | con::putstr("TAG_ADC10_1"); 51 | break; 52 | } 53 | uint8_t len = *p++; 54 | con::putc(' '); 55 | con::puthex8(len); 56 | con::newline(); 57 | 58 | switch (tag) { 59 | case TAG_ADC10_1: 60 | show_word("CAL_ADC_GAIN_FACTOR", p); p += 2; 61 | show_word("CAL_ADC_OFFSET", p); p += 2; 62 | show_word("CAL_ADC_15VREF_FACTOR", p); p += 2; 63 | show_word("CAL_ADC_15T30", p); p += 2; 64 | show_word("CAL_ADC_15T85", p); p += 2; 65 | show_word("CAL_ADC_25VREF_FACTOR", p); p += 2; 66 | show_word("CAL_ADC_25T30", p); p += 2; 67 | show_word("CAL_ADC_25T85", p); p += 2; 68 | break; 69 | default: 70 | p += len; 71 | break; 72 | } 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /examples/perf_counter.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include HW_CONFIG 11 | 12 | using namespace PTL; 13 | 14 | typedef Console con; 15 | 16 | PerfCounter counter; 17 | PerfCounterAcu accu; 18 | 19 | 20 | int main() 21 | { 22 | cpu::init(cpu::DEFAULT); 23 | timer::free_run(); 24 | uart::init(); 25 | 26 | while (1) { 27 | uart::read(); 28 | 29 | counter.start(); 30 | counter.stop(); 31 | con::putstr("Measuring 0 commands: "); 32 | con::putdec(counter.value()); 33 | con::newline(); 34 | 35 | counter.start(); 36 | asm("nop"); 37 | counter.stop(); 38 | con::putstr("Measuring NOP: "); 39 | con::putdec(counter.value()); 40 | con::newline(); 41 | 42 | counter.start(); 43 | StaticDelay::delay(1000); 44 | counter.stop(); 45 | con::putstr("Measuring StaticDelay::delay(1000): "); 46 | con::putdec(counter.value()); 47 | con::newline(); 48 | 49 | accu.start(); 50 | StaticDelay::delay(10000); 51 | accu.update(); 52 | con::putstr("PerfAcu after delay(10000): "); 53 | con::putdec(accu.value()); 54 | con::newline(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /examples/spi.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | using namespace PTL; 10 | 11 | typedef UART<1 MHZ, 9600, Pin, Pin, timer> uart; 12 | typedef SPI< Pin, Pin, Pin > spi; 13 | 14 | typedef Pin CS; 15 | 16 | int main() 17 | { 18 | cpu::init(cpu::DEFAULT); 19 | timer::free_run(); 20 | uart::init(); 21 | spi::init(); 22 | CS::output(); 23 | CS::high(); 24 | while (1) { 25 | uart::read(); 26 | CS::low(); 27 | uint8_t b = spi::transfer(0xff); 28 | CS::high(); 29 | Console::puthex8(b); 30 | Console::newline(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/timer_irq.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | using namespace PTL; 7 | 8 | namespace PTL { 9 | 10 | template <> 11 | void timer::irq_handler() 12 | { 13 | // Ack IRQ 14 | timer::irq_status(); 15 | board::LED::toggle(); 16 | } 17 | 18 | } 19 | 20 | int main() 21 | { 22 | cpu::init(cpu::DEFAULT); 23 | board::LED::port::enable(); 24 | board::LED::output(); 25 | board::LED::high(); 26 | timer::free_run(); 27 | timer::enable_irq(); 28 | cpu::enable_irq(); 29 | while (true); 30 | } 31 | -------------------------------------------------------------------------------- /examples/timer_irq_dispatch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct TimerIrqs : public TimerIrqsBase { 8 | static void overflow() 9 | { 10 | board::LED::toggle(); 11 | } 12 | }; 13 | 14 | IRQ_DISPATCH(timer, TimerIrqs); 15 | 16 | int main() 17 | { 18 | cpu::init(cpu::DEFAULT); 19 | board::LED::port::enable(); 20 | board::LED::output(); 21 | board::LED::high(); 22 | timer::free_run(); 23 | timer::enable_irq(); 24 | cpu::enable_irq(); 25 | while (true); 26 | } 27 | -------------------------------------------------------------------------------- /examples/uart_echo.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include HW_CONFIG 8 | 9 | int main() 10 | { 11 | cpu::init(cpu::DEFAULT); 12 | timer::free_run(); 13 | uart::init(); 14 | 15 | while (true) { 16 | uint8_t b = uart::read(); 17 | uart::write(b); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/uart_echo_async.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef UART<1 MHZ, 9600, USCI> uart; 7 | 8 | int main() 9 | { 10 | cpu::init(cpu::DEFAULT); 11 | uart::init(); 12 | 13 | while (true) { 14 | if (uart::read_ready()) { 15 | uint8_t b = uart::read_async(); 16 | // This is known to be short 17 | while (!uart::write_ready()); 18 | uart::write_async(b); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /examples/uart_echo_buffered.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include HW_CONFIG 11 | 12 | typedef BufferedUart buart; 13 | 14 | IRQ_DISPATCH(buart::uart_handlers); 15 | 16 | int main() 17 | { 18 | cpu::init(cpu::DEFAULT); 19 | board::LED::output(); 20 | board::LED::low(); 21 | buart::init(); 22 | cpu::enable_irq(); 23 | 24 | while (true) { 25 | // We have time to process only 3 incoming chars, ... 26 | for (int i = 0; i < 3; i++) { 27 | uint8_t b = buart::read(); 28 | board::LED::toggle(); 29 | buart::write(b); 30 | } 31 | // ..., and then we're busy with very important task 32 | // The whole idea is that even if we don't process incoming 33 | // chars regularly, they are not lost, but buffered in 34 | // background. 35 | StaticDelay::delay(500000U); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /examples/uart_echo_irq.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include HW_CONFIG 7 | 8 | namespace PTL { 9 | 10 | template <> 11 | void uart::uart_rx_irq_handler() 12 | { 13 | uart::write_async(uart::read_async()); 14 | board::LED::toggle(); 15 | } 16 | 17 | } 18 | 19 | int main() 20 | { 21 | cpu::init(cpu::DEFAULT); 22 | board::LED::output(); 23 | board::LED::low(); 24 | hwuart::init(); 25 | hwuart::enable_rx_irq(); 26 | cpu::enable_irq(); 27 | 28 | while (true); 29 | } 30 | -------------------------------------------------------------------------------- /examples/uart_printf.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | typedef UART uart; 9 | //typedef UART<1 MHZ, 9600, USCI> uart; 10 | typedef Console con; 11 | 12 | int main() 13 | { 14 | cpu::init(cpu::DEFAULT); 15 | timer::free_run(); 16 | uart::init(); 17 | 18 | while (true) { 19 | uint8_t b = uart::read(); 20 | con::printf("%d %u %x\n", 50000u, 50000u, 0xaa55u); 21 | con::printf("%ld %lx\n", 123456789l, 0xaa551234l); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /include/adc.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #if defined(__MSP430__) 20 | #include 21 | #else 22 | #error Unknown platform in adc.hpp 23 | #endif 24 | -------------------------------------------------------------------------------- /include/algo/nearptr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _NEAR_PTR_HPP 20 | #define _NEAR_PTR_HPP 21 | // As C++ doesn't support overloading templates by parameters, we should name 22 | // all templates differently. Also, "const char *" template parameter cannot 23 | // be cast to int. So, we have 3 templates with the same implementation, 24 | // difgering only in type of base template parameter. 25 | 26 | #define IMPL(name) \ 27 | public: \ 28 | storage_t off; \ 29 | name() { off = 0; } \ 30 | name(T *p) { off = ((int)p - (int)base) >> align; } \ 31 | T& operator*() const { return *(T*)((int)base + (off << align)); } \ 32 | operator T*() const { return (T*)((int)base + (off << align)); } 33 | 34 | // NearPtr against absolute base. This is what would be used on 35 | // MCU platform. 36 | // Params: 37 | // base - base of the memoty region within which pointer will point 38 | // storage_t - size of pointer value (uint8_t, uint16_t, etc.); can be 39 | // signed type too if needed 40 | // T - type to point to 41 | // align - alignment of pointer, as power of 2 42 | // For example, 16-bit NearPtr with alignment of 16 can address 1MB of memory 43 | template class AbsNearPtr 44 | { 45 | IMPL(AbsNearPtr) 46 | }; 47 | 48 | // NearPtr against statically allocated array (note: must have external 49 | // linkage, i.e. defined globally w/o static keyword). 50 | template class ArrayNearPtr 51 | { 52 | IMPL(ArrayNearPtr) 53 | }; 54 | 55 | // NearPtr against dynamic base store in a variable, for example, received 56 | // from malloc(). 57 | template class VarNearPtr 58 | { 59 | IMPL(VarNearPtr) 60 | }; 61 | 62 | #if 0 63 | // Example usage: 64 | 65 | const int base1 = 0x20000000; 66 | char base2[256] = "foobar"; 67 | char *base3 = (char*)malloc(256); 68 | 69 | template using Ptr1 = AbsNearPtr; 70 | template using Ptr2 = ArrayNearPtr; 71 | template using Ptr3 = VarNearPtr; 72 | 73 | Ptr2 p = &base2[3]; 74 | printf("%c", *p); // Produces "b" 75 | #endif 76 | 77 | #endif // _NEAR_PTR_HPP 78 | -------------------------------------------------------------------------------- /include/avr/cpu_avr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _CPU_AVR_HPP 20 | #define _CPU_AVR_HPP 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | class AVRCPU {}; 29 | 30 | // Various blocks of MCU 31 | class USART0 {}; 32 | 33 | template <> 34 | class CPU : public ICPU 35 | { 36 | public: 37 | static void init(int flags) 38 | { 39 | // Disable hwuart enabled by Arduino bootloader 40 | _R8(UCSR0B) = 0; 41 | #if 0 42 | switch (flags) { 43 | case DEFAULT: 44 | wdt_disable(); 45 | break; 46 | } 47 | #endif 48 | } 49 | 50 | static void enable_irq() { sei(); } 51 | static void disable_irq() { cli(); } 52 | }; 53 | 54 | typedef CPU cpu; 55 | 56 | } // namespace 57 | 58 | #endif //_CPU_AVR_HPP 59 | -------------------------------------------------------------------------------- /include/avr/delay_avr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | namespace PTL { 20 | 21 | class Delay 22 | { 23 | public: 24 | typedef uint32_t width; 25 | 26 | static void delay(width cycles) 27 | { 28 | uint32_t d = cycles / 6; 29 | asm( 30 | "ldi r24, %0 \n" 31 | "ldi r25, %1 \n" 32 | "ldi r26, %2 \n" 33 | "ldi r27, %3 \n" 34 | "1: \n" 35 | "subi r24, 1 \n" //1 36 | "sbci r25, 0 \n" //1 37 | "sbci r26, 0 \n" //1 38 | "sbci r27, 0 \n" //1 39 | "brcc 1b \n" //2 40 | : : "M" (d & 0xff), "M" ((d >> 8) & 0xff), "M" ((d >> 16) & 0xff), "M" ((d >> 24) & 0xff) : "r24", "r25", "r26", "r27" 41 | ); 42 | } 43 | }; 44 | 45 | } // namespace 46 | -------------------------------------------------------------------------------- /include/avr/delay_static_avr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | 21 | namespace PTL { 22 | 23 | #ifdef __NO_INLINE__ 24 | #error Optimization must be enabled, to support inline functions 25 | #endif 26 | 27 | #ifdef __OPTIMIZE_SIZE__ 28 | #error avr-gcc 4.5 -Os breaks this header, use other optimization level 29 | #endif 30 | 31 | // TODO: This is not yet cycle-perfect 32 | ALWAYS_INLINE static void __delay_cycles2(unsigned long delay) 33 | { 34 | if (__builtin_constant_p(delay)) { 35 | if (delay <= 262140U) { 36 | uint16_t d = delay >> 2; 37 | asm( 38 | "ldi r24, %0 \n" 39 | "ldi r25, %1 \n" 40 | "1: \n" 41 | #ifdef AVR_HAS_SBIW 42 | "sbiw r24, 1 \n" //2 43 | #else 44 | "subi r24, 1 \n" //1 45 | "sbci r25, 0 \n" //1 46 | #endif 47 | "brcc 1b \n" 48 | : : "M" (d & 0xff), "M" ((d >> 8) & 0xff) : "r24", "r25" 49 | ); 50 | } else { 51 | uint32_t d = delay / 6; 52 | asm( 53 | "ldi r24, %0 \n" 54 | "ldi r25, %1 \n" 55 | "ldi r26, %2 \n" 56 | "ldi r27, %3 \n" 57 | "1: \n" 58 | "subi r24, 1 \n" //1 59 | "sbci r25, 0 \n" //1 60 | "sbci r26, 0 \n" //1 61 | "sbci r27, 0 \n" //1 62 | "brcc 1b \n" //2 63 | : : "M" (d & 0xff), "M" ((d >> 8) & 0xff), "M" ((d >> 16) & 0xff), "M" ((d >> 24) & 0xff) : "r24", "r25", "r26", "r27" 64 | ); 65 | } 66 | } 67 | } 68 | 69 | 70 | class StaticDelay 71 | { 72 | public: 73 | ALWAYS_INLINE static void delay(long cycles) 74 | { 75 | __delay_cycles2(cycles); 76 | } 77 | }; 78 | 79 | } // namespace 80 | -------------------------------------------------------------------------------- /include/avr/gpio_avr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _GPIO_AVR_HPP 20 | #define _GPIO_AVR_HPP 21 | 22 | #include 23 | #include 24 | // Make register defines be just integer addresses 25 | #define _SFR_ASM_COMPAT 1 26 | #include 27 | 28 | namespace PTL { 29 | 30 | template 31 | class Port : public IPort 32 | { 33 | public: 34 | static const int in_reg = in_reg_; 35 | static const int out_reg = out_reg_; 36 | static const int dir_reg = dir_reg_; 37 | }; 38 | 39 | #ifdef PINA 40 | typedef Port PA; 41 | #endif 42 | #ifdef PINB 43 | typedef Port PB; 44 | #endif 45 | #ifdef PINC 46 | typedef Port PC; 47 | #endif 48 | #ifdef PIND 49 | typedef Port PD; 50 | #endif 51 | 52 | template 53 | class Pin : public PortPin< Pin, port, bit > 54 | { 55 | public: 56 | static uint8_t value() 57 | { 58 | return _REG8(port::in_reg) & bit::value; 59 | } 60 | static void high() 61 | { 62 | _REG8(port::out_reg) |= bit::value; 63 | } 64 | static void low() 65 | { 66 | _REG8(port::out_reg) &= ~bit::value; 67 | } 68 | static void toggle() 69 | { 70 | _REG8(port::out_reg) ^= bit::value; 71 | } 72 | static void output() 73 | { 74 | _REG8(port::dir_reg) |= bit::value; 75 | } 76 | static void input() 77 | { 78 | _REG8(port::dir_reg) &= ~bit::value; 79 | } 80 | }; 81 | 82 | } // namespace 83 | 84 | #endif //_GPIO_AVR_HPP 85 | -------------------------------------------------------------------------------- /include/avr/timer_avr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TIMER_AVR_HPP 20 | #define _TIMER_AVR_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | class Timer1 : public ITimer 28 | { 29 | public: 30 | static width value() { return _R16(TCNT1); } 31 | static void free_run() 32 | { 33 | _R8(TCCR1A) = 0; 34 | _R8(TCCR1B) = _BV(CS10); 35 | } 36 | 37 | }; 38 | 39 | typedef Timer1 timer; 40 | 41 | } // namespace 42 | 43 | #endif // _TIMER_AVR_HPP 44 | -------------------------------------------------------------------------------- /include/avr/uart_avr.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _UART_AVR_HPP 20 | #define _UART_AVR_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | #define DIVISOR(freq, baud, div) ((freq) / (div * (baud)) - 1) 27 | 28 | template 29 | class UART 30 | { 31 | public: 32 | static void init() 33 | { 34 | _R8(UCSR0C) = _BV(UCSZ01) | _BV(UCSZ00); 35 | if (DIVISOR(freq, baud, 16) > 15) { 36 | _R8(UCSR0A) = 0; 37 | _R16(UBRR0) = DIVISOR(freq, baud, 16); 38 | } else { 39 | _R8(UCSR0A) = _BV(U2X0); 40 | _R16(UBRR0) = DIVISOR(freq, baud, 8); 41 | } 42 | _R8(UCSR0B) = _BV(TXEN0) | _BV(RXEN0); 43 | } 44 | 45 | static uint8_t read() 46 | { 47 | while (!(_R8(UCSR0A) & _BV(RXC0))); 48 | return _R8(UDR0); 49 | } 50 | 51 | static void write(uint8_t b) 52 | { 53 | _R8(UDR0) = b; 54 | while (!(_R8(UCSR0A) & _BV(UDRE0))); 55 | } 56 | 57 | static uint8_t read_async() 58 | { 59 | return _R8(UDR0); 60 | } 61 | 62 | static void write_async(uint8_t b) 63 | { 64 | _R8(UDR0) = b; 65 | } 66 | 67 | static bool read_ready() 68 | { 69 | return _R8(UCSR0A) & _BV(RXC0); 70 | } 71 | 72 | static bool write_ready() 73 | { 74 | return _R8(UCSR0A) & _BV(UDRE0); 75 | } 76 | 77 | static void enable_rx_irq() { _R8(UCSR0B) |= _BV(RXCIE0); } 78 | static void disable_rx_irq() { _R8(UCSR0B) &= ~_BV(RXCIE0); } 79 | static void enable_tx_irq() { _R8(UCSR0B) |= _BV(UDRIE0); } 80 | static void disable_tx_irq() { _R8(UCSR0B) &= ~_BV(UDRIE0); } 81 | 82 | // static interrupt(USCIAB0RX_VECTOR) irq_handler_rx(); 83 | // static interrupt(USCIAB0TX_VECTOR) irq_handler_tx(); 84 | }; 85 | 86 | } // namespace 87 | 88 | #endif //_UART_AVR_HPP 89 | -------------------------------------------------------------------------------- /include/bits.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _BITS_HPP 20 | #define _BITS_HPP 21 | 22 | namespace PTL { 23 | 24 | template 25 | class Bit 26 | { 27 | public: 28 | static const int value = 1 << bit; 29 | static const int shift = bit; 30 | }; 31 | 32 | typedef Bit<0> Bit0; 33 | typedef Bit<1> Bit1; 34 | typedef Bit<2> Bit2; 35 | typedef Bit<3> Bit3; 36 | typedef Bit<4> Bit4; 37 | typedef Bit<5> Bit5; 38 | typedef Bit<6> Bit6; 39 | typedef Bit<7> Bit7; 40 | typedef Bit<8> Bit8; 41 | typedef Bit<9> Bit9; 42 | typedef Bit<10> Bit10; 43 | typedef Bit<11> Bit11; 44 | typedef Bit<12> Bit12; 45 | typedef Bit<13> Bit13; 46 | typedef Bit<14> Bit14; 47 | typedef Bit<15> Bit15; 48 | 49 | // Bitfield manipulation helpers, these assume value and mask already shifted 50 | // to correspond to physical bit positions. 51 | #define GET_BITFIELD(lval, mask) ((lval) & (mask)) 52 | #define SET_BITFIELD(lval, mask, field_val) (lval = (((lval) & (mask)) | (field_val))) 53 | 54 | } // namespace 55 | 56 | #endif //_BITS_HPP 57 | -------------------------------------------------------------------------------- /include/board.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | // TODO: Selecting board based on CPU is very rough 20 | #if defined(__MSP430__) 21 | #include 22 | #elif defined(__AVR__) 23 | #include 24 | #elif defined(__STM32__) 25 | #include 26 | #elif defined(__EFM32__) 27 | #include 28 | #elif defined(__LM4__) 29 | #include 30 | #else 31 | #error Unknown platform in board.hpp 32 | #endif 33 | -------------------------------------------------------------------------------- /include/board_arduino.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | class Arduino {}; 28 | 29 | template <> 30 | class Board 31 | { 32 | public: 33 | static const long freq = 16 MHZ; 34 | 35 | // "digital pin 13" 36 | typedef Pin LED; 37 | // "digital pin 0" 38 | typedef Pin pin_uart_rx; 39 | // "digital pin 1" 40 | typedef Pin pin_uart_tx; 41 | //typedef UART uart; 42 | typedef UART uart; 43 | 44 | // Arduino pin naming 45 | typedef Pin D0; 46 | typedef Pin D1; 47 | typedef Pin D2; 48 | typedef Pin D3; 49 | typedef Pin D4; 50 | typedef Pin D5; 51 | typedef Pin D6; 52 | typedef Pin D7; 53 | 54 | typedef Pin D8; 55 | typedef Pin D9; 56 | typedef Pin D10; 57 | typedef Pin D11; 58 | typedef Pin D12; 59 | typedef Pin D13; 60 | 61 | typedef Pin A0; 62 | typedef Pin A1; 63 | typedef Pin A2; 64 | typedef Pin A3; 65 | typedef Pin A4; 66 | typedef Pin A5; 67 | }; 68 | 69 | typedef Board board; 70 | 71 | } // namespace 72 | -------------------------------------------------------------------------------- /include/board_base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _BOARD_BASE_HPP 20 | #define _BOARD_BASE_HPP 21 | 22 | namespace PTL { 23 | 24 | template 25 | class Board 26 | { 27 | }; 28 | 29 | } // namespace 30 | 31 | #endif // _BOARD_BASE_HPP 32 | -------------------------------------------------------------------------------- /include/board_efm32gg_stk3700.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #include 21 | #include 22 | 23 | namespace PTL { 24 | 25 | class EFM32GGSTK3700 {}; 26 | 27 | template <> 28 | class Board 29 | { 30 | public: 31 | typedef Pin LED; 32 | typedef Pin LED2; 33 | static const long freq = 48 MHZ; 34 | }; 35 | 36 | typedef Board board; 37 | 38 | } // namespace 39 | -------------------------------------------------------------------------------- /include/board_launchpad_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _BOARD_LAUNCHPAD_MSP430_HPP 20 | #define _BOARD_LAUNCHPAD_MSP430_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | class MSP430Launchpad {}; 29 | 30 | template <> 31 | class Board 32 | { 33 | public: 34 | // Left, red LED 35 | typedef Pin LED; 36 | // Right, green LED, conflicts with SPI, I2C 37 | typedef Pin LED2; 38 | // This is HWUART pin mapping. On 1.5, jumpers should be 39 | // put in perpindicular position wrt other jumpers. Not 40 | // compatible with Launchpad 1.4, where tx & rx should be 41 | // swapped. 42 | typedef Pin pin_uart_tx; 43 | typedef Pin pin_uart_rx; 44 | static const long freq = 1 MHZ; 45 | }; 46 | 47 | typedef Board board; 48 | 49 | } // namespace 50 | 51 | #endif // _BOARD_LAUNCHPAD_MSP430_HPP 52 | -------------------------------------------------------------------------------- /include/board_launchpad_stellaris.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _BOARD_LAUNCHPAD_STELLARIS_HPP 20 | #define _BOARD_LAUNCHPAD_STELLARIS_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | class StellarisLaunchpad {}; 29 | 30 | template <> 31 | class Board 32 | { 33 | public: 34 | // Red color of RGB LED 35 | typedef Pin LED; 36 | // Blue color of RGB LED 37 | typedef Pin LED2; 38 | // Green color of RGB LED 39 | typedef Pin LED3; 40 | 41 | // Precision Oscillator (PIOSC): On-chip resource providing 42 | // a 16 MHz ±1% frequency at room temperature 43 | static const long freq = 16 MHZ; 44 | }; 45 | 46 | typedef Board board; 47 | 48 | } // namespace 49 | 50 | #endif // _BOARD_LAUNCHPAD_STELLARIS_HPP 51 | -------------------------------------------------------------------------------- /include/board_stm32vldiscovery.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #include 21 | #include 22 | 23 | namespace PTL { 24 | 25 | class STM32VLDiscovery {}; 26 | 27 | template <> 28 | class Board 29 | { 30 | public: 31 | // Right, blue LED 32 | typedef Pin LED; 33 | // Left, green LED 34 | typedef Pin LED2; 35 | static const long freq = 8 MHZ; 36 | }; 37 | 38 | typedef Board board; 39 | 40 | } // namespace 41 | -------------------------------------------------------------------------------- /include/byteptr.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace PTL { 4 | 5 | class byteptr 6 | { 7 | public: 8 | static uint16_t _uint16_t(const void *p) 9 | { 10 | const uint8_t *t = (uint8_t*)p; 11 | return (t[1] << 8) | t[0]; 12 | } 13 | 14 | static void _uint16_t(void *p, uint16_t val) 15 | { 16 | uint8_t *t = (uint8_t*)p; 17 | t[0] = val; 18 | t[1] = val >> 8; 19 | } 20 | 21 | static uint32_t _uint32_t(const void *p) 22 | { 23 | const uint8_t *t = (uint8_t*)p; 24 | return ((uint32_t)t[3] << 24) | ((uint32_t)t[2] << 16) | (t[1] << 8) | t[0]; 25 | } 26 | 27 | static void _uint32_t(void *p, uint32_t val) 28 | { 29 | uint8_t *t = (uint8_t*)p; 30 | t[0] = val; 31 | t[1] = val >> 8; 32 | t[2] = val >> 16; 33 | t[3] = val >> 24; 34 | } 35 | }; 36 | 37 | } // namespace 38 | -------------------------------------------------------------------------------- /include/clock.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #define KHZ *1000 21 | #define MHZ *1000000 22 | 23 | #if defined(__MSP430__) 24 | #include 25 | #else 26 | //#error Unknown platform in clock.hpp 27 | #endif 28 | -------------------------------------------------------------------------------- /include/compat/arduino.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | /* Arduino compatibility header, which allows to compile arduino code 21 | minimal code logic changes (but no so minimal declarations changes). */ 22 | 23 | #define ARDUINO 101 24 | 25 | #define LOW 0 26 | #define HIGH 1 27 | #define INPUT 0 28 | #define OUTPUT 1 29 | #define LSBFIRST 0 30 | #define MSBFIRST 1 31 | 32 | #define digitalWrite(pin, val) pin::set(val) 33 | 34 | template 35 | inline void _pinMode() 36 | { 37 | if (mode == OUTPUT) 38 | pin::output(); 39 | else 40 | pin::input(); 41 | } 42 | #define pinMode(pin, mode) _pinMode() 43 | 44 | template 45 | void _shiftOut(uint8_t b) 46 | { 47 | if (msbfirst == MSBFIRST) { 48 | // from SPI::write 49 | for (uint8_t i = 8; i; i--) { 50 | if (b & 0x80) 51 | pin_data::high(); 52 | else 53 | pin_data::low(); 54 | 55 | pin_clk::high(); 56 | 57 | b <<= 1; 58 | 59 | pin_clk::low(); 60 | } 61 | } else { 62 | for (uint8_t i = 8; i; i--) { 63 | if (b & 0x01) 64 | pin_data::high(); 65 | else 66 | pin_data::low(); 67 | 68 | pin_clk::high(); 69 | 70 | b >>= 1; 71 | 72 | pin_clk::low(); 73 | } 74 | } 75 | } 76 | #define shiftOut(pin_data, pin_clk, msbfirst, data) _shiftOut(data) 77 | 78 | #define delay(n) delayer::delay_ms(n) 79 | -------------------------------------------------------------------------------- /include/cortex-m/cpu_cortexm.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _CPU_CORTEXM_HPP 20 | #define _CPU_CORTEXM_HPP 21 | 22 | #include 23 | #include 24 | // Declare Cortex-M IRQ handlers 25 | #include 26 | 27 | namespace PTL { 28 | 29 | class CortexMCPU {}; 30 | 31 | // Various blocks of MCU 32 | enum { CORTEXM_NONE, CORTEXM_SYSTICK }; 33 | 34 | template <> 35 | class CPU : public ICPU 36 | { 37 | public: 38 | static void init(int flags) 39 | { 40 | // CMSIS: The Startup File startup_.s is executed 41 | // after reset and calls SystemInit(). 42 | } 43 | 44 | static void enable_irq() { __enable_irq(); } 45 | static void disable_irq() { __disable_irq(); } 46 | }; 47 | 48 | } // namespace 49 | 50 | #endif // _CPU_CORTEXM_HPP 51 | -------------------------------------------------------------------------------- /include/cortex-m/delay_cortexm.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace PTL { 4 | 5 | class Delay 6 | { 7 | public: 8 | typedef uint32_t width; 9 | 10 | static void delay(width cycles) 11 | { 12 | // call to here: 1 cycle 13 | #define ADJUST (1/*delay arg load*/ + 1/*call*/ + 1/*ret*/) 14 | cycles = ((cycles - ADJUST) + 2) / 3; 15 | asm __volatile__ ( 16 | "1: \n" 17 | "subs %[value], #1 \n" //1 18 | "bne 1b \n" // 2 19 | : [value] "+r" (cycles) : 20 | ); 21 | } 22 | }; 23 | 24 | } // namespace 25 | -------------------------------------------------------------------------------- /include/cortex-m/delay_static_cortexm.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #include 21 | 22 | namespace PTL { 23 | 24 | inline void __delay_cycles2(uint32_t cycles) 25 | { 26 | if (cycles == 0) { 27 | ; 28 | } else if (cycles == 1) { 29 | asm("add r0, #0"); // don't set flags! 30 | // Data operations | 32 | 1 31 | } else if (cycles == 2) { 32 | // Single branch won't work here, because if next 33 | // instr is unaligned 32bit one, branch will take 3 cycles 34 | asm("add r0, #0"); // don't set flags! 35 | asm("add r0, #0"); // don't set flags! 36 | } else if (cycles == 3) { 37 | asm("b 1f \n"); // Branches 16 1+P 38 | asm("1: \n"); 39 | asm("add r0, #0"); 40 | // TRM p.18-5 Taken branches with an immediate are normally 1 cycle of pipeline reload (2 cycles total). 41 | } else { 42 | uint32_t loop_count = ((cycles - 1) + 2) / 3; 43 | asm __volatile__ ( 44 | // Following 2 commands are rendered by gcc, and just typical 45 | // Compiler may preload the value to another registers and then 46 | // just do mov rA, rB - that typically happens when using same 47 | // delay value in close statements or when doing loop invariant 48 | // lifting. 49 | //"movw %[value], #low \n" //1 50 | //"movt %[value], #high \n" //1 51 | // or 52 | //"mov %[value], %another_reg \n" //1 53 | 54 | "1: \n" 55 | "subs %[value], #1 \n" //1 56 | "bne 1b \n" // 2 57 | : [value] "+r" (loop_count) : 58 | ); 59 | // 2 + 3*(N-1) + (1-2) == 3*N (+1) 60 | } 61 | } 62 | 63 | class StaticDelay 64 | { 65 | public: 66 | ALWAYS_INLINE static void delay(long cycles) 67 | { 68 | __delay_cycles2(cycles); 69 | } 70 | }; 71 | 72 | } // namespace 73 | -------------------------------------------------------------------------------- /include/cortex-m/includes_cortexm.hpp: -------------------------------------------------------------------------------- 1 | // TODO: make target MCU dependent 2 | #ifdef LIBPERIPHA 3 | //#include 4 | #if defined(CORTEX_M0) 5 | #include 6 | #elif defined(CORTEX_M0PLUS) 7 | #include 8 | #elif defined(CORTEX_M3) 9 | #include 10 | #elif defined(CORTEX_M4) 11 | #include 12 | #else 13 | #error Unknown Cortex-M Core 14 | #endif 15 | #else 16 | // Assume that complete vendor CMSIS is used 17 | //#error Undefined 18 | #endif 19 | -------------------------------------------------------------------------------- /include/cortex-m/irq_dispatch_cortexm.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _IRQ_DISPATCH_CORTEXM_HPP 20 | #define _IRQ_DISPATCH_CORTEXM_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | /** 27 | ** Device-specific classes and macros for interrupt dispatching 28 | **/ 29 | 30 | /* Implementation of function which will dispatch harware IRQ to all 31 | blocks which have corresponding PTL handler. 32 | What to change: name, condition, implementation. */ 33 | IRQ_DISPATCH_HELPER(do_systick, block::block_type == CORTEXM_SYSTICK) 34 | { 35 | block::irq_reset(); 36 | } 37 | 38 | /* Class which encapsulates all hardware -> PTL dispatchers. Mostly 39 | used to allow variable list of blocks to dispatch to. */ 40 | template 41 | class IrqDispatch 42 | { 43 | public: 44 | HANDLER(SysTick_, do_systick); 45 | }; 46 | 47 | /* Dispatch IRQ from MCU and compiler specific "IRQ vector" function. This 48 | is expected to be fully optimized out by inlining. 49 | What to change: name/attributes of function defined. */ 50 | #define CALL_HANDLER(dispatcher, vector) \ 51 | void vector##Handler() \ 52 | { \ 53 | dispatcher::vector##Handler(); \ 54 | } 55 | 56 | /* Macros to dispatch from MCU/compiler specific "IRQ vector function" 57 | to IrqDispatch class. The latter should be passed in as a param. */ 58 | #define IRQ_DISPATCH(blocks...) \ 59 | template class IrqDispatch; \ 60 | typedef IrqDispatch _irq_dispatch; \ 61 | CALL_HANDLER(_irq_dispatch, SysTick_); 62 | 63 | 64 | } // namespace 65 | 66 | #endif // _IRQ_DISPATCH_CORTEXM_HPP 67 | -------------------------------------------------------------------------------- /include/cortex-m/timer_cortexm_cyccnt.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TIMER_CORTEXM_SYSTICK_HPP 20 | #define _TIMER_CORTEXM_SYSTICK_HPP 21 | 22 | #include 23 | 24 | // TODO: WIP, untested 25 | 26 | namespace PTL { 27 | 28 | class CCycCnt : public ITimer 29 | { 30 | public: 31 | typedef uint32_t width; 32 | 33 | static width value() { return DWT->CYCCNT; } 34 | static void free_run() 35 | { 36 | // p.11-19 Cortex-M3 r2p0 TechRefMan 37 | // The TRCENA bit of the Debug Exception and Monitor Control Register must be set 38 | // before you can use the DWT. 39 | CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA; 40 | if (DWT->CTRL == 0 || (DWT->CTRL & DWT_CTRL_NOCYCCNT)) { 41 | abort(); 42 | } 43 | DWT->CTRL |= DWT_CTRL_CYCCNTENA; 44 | } 45 | }; 46 | 47 | } // namespace 48 | 49 | #endif // _TIMER_CORTEXM_SYSTICK_HPP 50 | -------------------------------------------------------------------------------- /include/cortex-m/timer_cortexm_systick.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TIMER_CORTEXM_SYSTICK_HPP 20 | #define _TIMER_CORTEXM_SYSTICK_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | class CSysTick : public ITimer 29 | { 30 | public: 31 | const static int block_type = CORTEXM_SYSTICK; 32 | typedef uint32_t width; 33 | 34 | static width value() { return SysTick->VAL; } 35 | static void free_run() 36 | { 37 | SysTick->LOAD = 0xffffff; 38 | // Set CLKSOURCE to get same clock as CPU core. In case CLKSOURCE 39 | // is unset, the clock used is implementation-dependent. 40 | SysTick->CTRL |= SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; 41 | } 42 | 43 | static void enable_irq() { SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk; } 44 | static void disable_irq() { SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk; } 45 | 46 | static void irq_reset() {} 47 | }; 48 | 49 | typedef CSysTick timer; 50 | 51 | } // namespace 52 | 53 | #endif // _TIMER_CORTEXM_SYSTICK_HPP 54 | -------------------------------------------------------------------------------- /include/cpu.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #if defined(__MSP430__) 20 | #include 21 | #elif defined(__AVR__) 22 | #include 23 | #elif defined(__STM32__) 24 | #include 25 | #elif defined(__EFM32__) 26 | #include 27 | #elif defined(__TM4__) 28 | #include 29 | #elif defined(__thumb__) || defined(__thumb2__) 30 | #include 31 | namespace PTL { 32 | typedef CPU cpu; 33 | } // namespace 34 | #else 35 | #error Unknown platform in cpu.hpp 36 | #endif 37 | -------------------------------------------------------------------------------- /include/cpu_base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _CPU_BASE_HPP 20 | #define _CPU_BASE_HPP 21 | 22 | namespace PTL { 23 | 24 | class ICPU 25 | { 26 | public: 27 | static const int DEFAULT = 0; 28 | static const int FREQ_8MHZ = 1; 29 | }; 30 | 31 | template 32 | class CPU : public ICPU 33 | { 34 | }; 35 | 36 | } // namespace 37 | 38 | #endif //_CPU_BASE_HPP 39 | -------------------------------------------------------------------------------- /include/delay.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #if defined(__MSP430__) 20 | #include 21 | #elif defined(__AVR__) 22 | #include 23 | #elif defined(__thumb__) || defined(__thumb2__) 24 | #include 25 | #else 26 | #error Unknown platform in delay.hpp 27 | #endif 28 | -------------------------------------------------------------------------------- /include/delay_static.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #if defined(__MSP430__) 20 | #include 21 | #elif defined(__AVR__) 22 | #include 23 | #elif defined(__thumb__) || defined(__thumb2__) 24 | #include 25 | #else 26 | #error Unknown platform in delay_static.hpp 27 | #endif 28 | -------------------------------------------------------------------------------- /include/delay_time.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | namespace PTL { 21 | 22 | template 23 | class TimeDelay 24 | { 25 | public: 26 | inline static void delay_us(unsigned us) 27 | { 28 | cycle_delayer::delay((uint32_t)((unsigned long long)freq * us / 1000000UL)); 29 | } 30 | 31 | inline static void delay_ms(unsigned ms) 32 | { 33 | cycle_delayer::delay((uint32_t)((unsigned long long)freq * ms / 1000UL)); 34 | } 35 | }; 36 | 37 | } // namespace 38 | -------------------------------------------------------------------------------- /include/efm32/cpu_efm32.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | 21 | namespace PTL { 22 | 23 | class EFM32CPU {}; 24 | 25 | template <> 26 | class CPU : public CPU 27 | { 28 | }; 29 | 30 | typedef CPU cpu; 31 | 32 | } // namespace 33 | -------------------------------------------------------------------------------- /include/efm32/gpio_efm32.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _GPIO_EFM32_HPP 20 | #define _GPIO_EFM32_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | template 28 | class Port : public IPort 29 | { 30 | public: 31 | static const int port_no = port_no_; 32 | 33 | static void enable() { 34 | CMU->HFPERCLKDIV |= CMU_HFPERCLKDIV_HFPERCLKEN; 35 | CMU->HFPERCLKEN0 |= CMU_HFPERCLKEN0_GPIO; 36 | // CMU_ClockEnable(cmuClock_HFPER, true); 37 | // CMU_ClockEnable(cmuClock_GPIO, true); 38 | } 39 | }; 40 | 41 | typedef Port<0, uint16_t> PA; 42 | typedef Port<1, uint16_t> PB; 43 | typedef Port<2, uint16_t> PC; 44 | typedef Port<3, uint16_t> PD; 45 | typedef Port<4, uint16_t> PE; 46 | typedef Port<5, uint16_t> PF; 47 | 48 | template 49 | class Pin : public PortPin< Pin, port, bit > 50 | { 51 | static void set_mode(int mode) 52 | { 53 | volatile uint32_t *reg; 54 | if (bit::shift < 8) 55 | reg = &GPIO->P[port::port_no].MODEL; 56 | else 57 | reg = &GPIO->P[port::port_no].MODEH; 58 | 59 | uint32_t mask = 0xf << ((bit::shift % 8) * 4); 60 | uint32_t val = mode << ((bit::shift % 8) * 4); 61 | *reg = (*reg & ~mask) | val; 62 | } 63 | 64 | public: 65 | static typename port::width value() 66 | { 67 | return GPIO->P[port::port_no].DIN & bit::value; 68 | } 69 | static void high() 70 | { 71 | GPIO->P[port::port_no].DOUTSET = bit::value; 72 | } 73 | static void low() 74 | { 75 | GPIO->P[port::port_no].DOUTCLR = bit::value; 76 | } 77 | 78 | static void output() 79 | { 80 | set_mode(_GPIO_P_MODEL_MODE0_PUSHPULL); 81 | } 82 | static void input() 83 | { 84 | set_mode(_GPIO_P_MODEL_MODE0_INPUT); 85 | } 86 | }; 87 | 88 | } // namespace 89 | 90 | #endif //_GPIO_EFM32_HPP 91 | -------------------------------------------------------------------------------- /include/efm32/includes_efm32.hpp: -------------------------------------------------------------------------------- 1 | // TODO: make target MCU dependent 2 | #include 3 | -------------------------------------------------------------------------------- /include/flash.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #if defined(__MSP430__) 20 | #include 21 | #else 22 | #error Unknown platform in flash.hpp 23 | #endif 24 | -------------------------------------------------------------------------------- /include/gpio.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifdef __MSP430__ 20 | #include 21 | #elif defined( __AVR__) 22 | #include 23 | #elif defined( __STM32__) 24 | #include 25 | #elif defined( __EFM32__) 26 | #include 27 | #elif defined( __LM4__) 28 | #include 29 | #else 30 | #error Unknown platform in gpio.hpp 31 | #endif 32 | -------------------------------------------------------------------------------- /include/gpio_base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _GPIO_BASE_HPP 20 | #define _GPIO_BASE_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace PTL { 28 | 29 | // Pin is abstraction of basic I/O signal 30 | template 31 | class IPin 32 | { 33 | public: 34 | typedef width_ width; 35 | 36 | static void enable(); 37 | static void output(); 38 | static void input(); 39 | static width value(); 40 | static void high(); 41 | static void low(); 42 | static void toggle(); 43 | static void set(bool8 val) 44 | { 45 | if (val) 46 | pin_impl::high(); 47 | else 48 | pin_impl::low(); 49 | } 50 | static void pulloff(); 51 | static void pullup(); 52 | static void pulldown(); 53 | }; 54 | 55 | // Port is a collection of related pins 56 | // no_ is thru-numbered relative port number (0 - very first GPIO port, etc.) 57 | // Used mostly for defining numbering for dynapins. 58 | template 59 | class IPort 60 | { 61 | public: 62 | typedef width_ width; 63 | static const int no = no_; 64 | 65 | // Enable port for access (power on, set up clocks, etc.) 66 | static void enable() {} 67 | // Disable port (power off) 68 | static void disable() {} 69 | 70 | static width value(); 71 | static void set(width val); 72 | static void set_masked(width val, width mask) { set(value() & mask); } 73 | }; 74 | 75 | // Pin which belongs to a (static) port 76 | // Most GPIO pins in MCUs are grouped into ports, 77 | // and this class captures pin's port and bit position 78 | // within port. But note that all pins don't have 79 | // to use this class (when there's no underlying "port", 80 | // if such port is not static) and can use IPin directly. 81 | template 82 | class PortPin: public IPin 83 | { 84 | public: 85 | typedef port_ port; 86 | typedef bit_ bit; 87 | 88 | static void enable() { port::enable(); } 89 | }; 90 | 91 | // Non-existent pin, can be used when a pin in some design is optional. 92 | // All access will be optimized out by compiler. Typical example 93 | // is a LED - boards which have it, can define it to a specific pin, 94 | // and boards which lack - to NullPin, and code will still compile 95 | // (though indication obviously won't be present in second case). 96 | class NullPin : public IPin 97 | { 98 | public: 99 | typedef class NullPort {} port; 100 | ALWAYS_INLINE static void output() {} 101 | ALWAYS_INLINE static void high() {} 102 | ALWAYS_INLINE static void low() {} 103 | ALWAYS_INLINE static void toggle() {} 104 | ALWAYS_INLINE static void set(bool8 val) {} 105 | }; 106 | 107 | } // namespace 108 | 109 | #endif //_GPIO_BASE_HPP 110 | -------------------------------------------------------------------------------- /include/i2c.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | namespace PTL { 21 | 22 | // Based on http://en.wikipedia.org/wiki/I%C2%B2C 23 | 24 | template 25 | class I2C 26 | { 27 | public: 28 | static void init() 29 | { 30 | sda_high(); 31 | scl_high(); 32 | } 33 | 34 | static void sda_high() 35 | { 36 | sda::input(); 37 | sda::pullup(); 38 | } 39 | static void sda_low() 40 | { 41 | sda::output(); 42 | sda::low(); 43 | } 44 | 45 | static void scl_high() 46 | { 47 | scl::input(); 48 | scl::pullup(); 49 | } 50 | static void scl_low() 51 | { 52 | scl::output(); 53 | scl::low(); 54 | } 55 | 56 | static void delay() 57 | { 58 | delayer::delay(delay_); 59 | } 60 | 61 | 62 | 63 | static void start() 64 | { 65 | sda_low(); 66 | delay(); 67 | scl_low(); 68 | delay(); 69 | } 70 | 71 | static void restart() 72 | { 73 | sda_high(); 74 | delay(); 75 | scl_high(); 76 | delay(); 77 | start(); 78 | } 79 | 80 | static void stop() 81 | { 82 | sda_low(); 83 | scl_high(); 84 | delay(); 85 | sda_high(); 86 | delay(); 87 | } 88 | 89 | static typename sda::port::width read_bit() 90 | { 91 | sda_high(); 92 | scl_high(); 93 | delay(); 94 | typename sda::port::width ack = sda::value(); 95 | scl_low(); 96 | return ack; 97 | } 98 | 99 | static void write_bit(uint8_t val) 100 | { 101 | if (val) 102 | sda_high(); 103 | else 104 | sda_low(); 105 | delay(); 106 | scl_high(); 107 | delay(); // Rather should sense scl for clock stretching 108 | scl_low(); 109 | } 110 | 111 | static typename sda::port::width write(uint8_t b) 112 | { 113 | for (int i = 8; i--;) { 114 | write_bit(b & 0x80); 115 | b <<= 1; 116 | } 117 | return read_bit(); 118 | } 119 | 120 | static uint8_t read(bool ack = true) 121 | { 122 | uint8_t b = 0; 123 | for (int i = 8; i--;) { 124 | b <<= 1; 125 | if (read_bit()) 126 | b |= 1; 127 | } 128 | write_bit(!ack); 129 | return b; 130 | } 131 | }; 132 | 133 | } // namespace 134 | -------------------------------------------------------------------------------- /include/irq_dispatch.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifdef __MSP430__ 20 | #include 21 | #elif defined(__ARM_ARCH_7M__) 22 | #include 23 | #else 24 | #error Unknown platform in irq_dispatch.hpp 25 | #endif 26 | -------------------------------------------------------------------------------- /include/irq_dispatch_base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _IRQ_DISPATCH_BASE_HPP 20 | #define _IRQ_DISPATCH_BASE_HPP 21 | 22 | namespace PTL { 23 | 24 | /** 25 | ** Device-independent helper macros/classes for interrupt dispatching 26 | **/ 27 | 28 | /* Null MCU device block, used as a placeholder. */ 29 | class NullBlock 30 | { 31 | public: 32 | const static int block_type = 0; 33 | }; 34 | 35 | /* 36 | * We want to declare a function whose body will be executed only 37 | * when (static) condition is true. We have to use metaprog conditionals 38 | * here, because if condition is false, func body may not compile at all 39 | * (for example because class it opeartes on lacks specific methods). 40 | * So, we use 2 complementary implementations of func: one with empty 41 | * body for case of condition == false, and one with the given body 42 | * in case it's true. All is wrapped with macros for readability. 43 | */ 44 | 45 | #define IRQ_DISPATCH_HELPER(func_name, cond) \ 46 | template \ 47 | inline void func_name(uint8_t val = 0, typename meta::enable_if<(!(cond))>::type* = 0) {} \ 48 | \ 49 | template \ 50 | inline void func_name(uint8_t val = 0, typename meta::enable_if<(cond)>::type* = 0) \ 51 | 52 | /* Apply templated function to list of template args. Note: this and other similar 53 | funcs depend on particular number of arguments passed and must be updated to 54 | pass more. */ 55 | #define APPLY_TO_ALL(func, b1, b2, b3) { func(); func(); func(); } 56 | /* Apply templated function to list of template args, also passing (runtime) argument 57 | to a function. */ 58 | #define APPLY_TO_ALL_ARG(func, arg, b1, b2, b3) { func(arg); func(arg); func(arg); } 59 | 60 | /* Define handler function for particular hardware IRQ. */ 61 | #define HANDLER(vector, dispatch_func) \ 62 | static void vector##Handler() \ 63 | { \ 64 | APPLY_TO_ALL(dispatch_func, b1, b2, b3); \ 65 | } 66 | 67 | /* Define handler function for particular hardware IRQ, caching value 68 | of a register allowing to demux multiplexed IRQs. This cached value 69 | is passed to each PTL handler. */ 70 | #define HANDLER_CACHE_REG(vector, dispatch_func, reg) \ 71 | static void vector##Handler() \ 72 | { \ 73 | uint8_t cache = reg; \ 74 | APPLY_TO_ALL_ARG(dispatch_func, cache, b1, b2, b3); \ 75 | } 76 | 77 | } // namespace 78 | 79 | #endif // _IRQ_DISPATCH_BASE_HPP 80 | -------------------------------------------------------------------------------- /include/lpc/lpc800_bootrom.hpp: -------------------------------------------------------------------------------- 1 | #define BOOTROM 0x1fff0000 2 | #define BOOTROM_SIZE 8192 3 | // ROM In-Application Programming routine 4 | // +1 to signify this is Thumb code 5 | #define BOOTROM_IAP (BOOTROM + BOOTROM_SIZE - 16 + 1) 6 | #define BOOTROM_DEVICE_DRIVER_TABLE (BOOTROM + BOOTROM_SIZE - 8) 7 | 8 | // cmd and result can point to same area of memory (UM10601 p.269) 9 | typedef void (*IAPFuncPtr)(uint32_t *cmd, uint32_t *result); 10 | 11 | #define DEVICE_DRIVER_FUNC_TABLE(device_no) ((*(uint32_t**)BOOTROM_DEVICE_DRIVER_TABLE)[device_no]) 12 | 13 | struct LPC800_PWRD { 14 | void (*set_pll)(unsigned int cmd[4], unsigned int resp[2]); 15 | void (*set_power)(unsigned int cmd[4], unsigned int resp[2]); 16 | }; 17 | 18 | struct LPC800_DeviceDrivers { 19 | void *res0; 20 | void *res1; 21 | void *res2; 22 | struct LPC800_PWRD *PWRD; 23 | void *res4; 24 | struct LPC800_I2CD *I2CD; 25 | void *res6; 26 | void *res7; 27 | void *res8; 28 | struct LPC800_USARTD *USARTD; 29 | }; 30 | 31 | #define DeviceDrivers (*(struct LPC800_DeviceDrivers**)BOOTROM_DEVICE_DRIVER_TABLE) 32 | 33 | // Example usage: 34 | //DeviceDrivers->PWRD->set_power(); 35 | -------------------------------------------------------------------------------- /include/meta.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | // C++ metaprogramming helper 21 | 22 | #include 23 | 24 | namespace meta { 25 | 26 | // enable_if 27 | template 28 | struct enable_if {}; 29 | template 30 | struct enable_if { typedef T type; }; 31 | 32 | // signed_t 33 | template struct signed_t {}; 34 | template <> struct signed_t { typedef int8_t type; }; 35 | template <> struct signed_t { typedef int16_t type; }; 36 | template <> struct signed_t { typedef int32_t type; }; 37 | template <> struct signed_t { typedef int64_t type; }; 38 | 39 | }; 40 | -------------------------------------------------------------------------------- /include/msp430/cpu_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _CPU_MSP430_HPP 20 | #define _CPU_MSP430_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | class MSP430CPU {}; 29 | 30 | // Various blocks of CPU 31 | 32 | enum { MSP430_NONE, MSP430_TIMER, MSP430_USART, MSP430_USI, MSP430_USCI }; 33 | 34 | // All implementation of MSP430 blocks support should inherit from this class. 35 | class MSP430Block 36 | { 37 | public: 38 | const static int block_type = MSP430_NONE; 39 | }; 40 | 41 | /* 42 | * MSP430 serial communications implementation is pretty twisted thing. 43 | * Let's start with saying that MSP430 series has 3 different serial 44 | * comminication controllers: USART, USI, USCI. So, below we define 45 | * empty ID classes to specialize protocol implementation against. 46 | */ 47 | 48 | // USART is contoller in "original" MSP430 series, doesn't seem to be 49 | // available in "value line". 50 | struct USART {}; 51 | // USI & USCI are "value line" novelties. 52 | // USI doesn't support UART and otherwise "lower profiler" than USCI. 53 | struct USI {}; 54 | // USCI consists of two blocks: USCI_A & USCI_B. They appear to always 55 | // come together, i.e. there doesn't seem to be a chip model with only 56 | // USCI_A or USCI_B (though, with TI engineers and marketologists, you 57 | // can only keep fingers crossed). USCI_A capable of doing UART and SPI, 58 | // USCI_B - SPI and I2C. 59 | struct USCI_A { const static int no = 'A'; }; 60 | struct USCI_B { const static int no = 'B'; }; 61 | 62 | 63 | template <> 64 | class CPU : public ICPU 65 | { 66 | public: 67 | static void init(int flags) 68 | { 69 | // Disable watchdog 70 | WDTCTL = WDTPW | WDTHOLD; 71 | switch (flags) { 72 | case DEFAULT: 73 | // Use precalibrated 1MHz frequency 74 | BCSCTL1 = CALBC1_1MHZ; 75 | DCOCTL = CALDCO_1MHZ; 76 | break; 77 | case FREQ_8MHZ: 78 | BCSCTL1 = CALBC1_8MHZ; 79 | DCOCTL = CALDCO_8MHZ; 80 | break; 81 | } 82 | } 83 | 84 | static void enable_irq() { eint(); } 85 | static void disable_irq() { dint(); } 86 | }; 87 | 88 | typedef CPU cpu; 89 | 90 | } // namespace 91 | 92 | #endif //_CPU_MSP430_HPP 93 | -------------------------------------------------------------------------------- /include/msp430/delay_msp430.hpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | namespace PTL { 4 | 5 | class Delay 6 | { 7 | public: 8 | typedef uint32_t width; 9 | 10 | static void delay(width cycles) 11 | { 12 | // call to here: 5 cycles 13 | // - 4 below because we do post-check, so with 0 we do 1 iteration 14 | cycles -= 5 + 3 + 5 + 3 - 4; // 3 clocks 15 | cycles >>= 2; // 5 instructions, 5 cycles 16 | asm( 17 | "mov %A0, r14 \n" 18 | "mov %B0, r15 \n" 19 | "1: \n" 20 | "sub #1, r14 \n" // 1 cycle 21 | "subc #0, r15 \n" // 1 cycle 22 | "jc 1b \n" // 2 cycles, msp430 has weird C flag value for subtracts 23 | : : "ir" (cycles) : "r14", "r15" 24 | ); 25 | // ret: 3 cycles 26 | } 27 | }; 28 | 29 | } // namespace 30 | -------------------------------------------------------------------------------- /include/msp430/flash_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | #include 21 | 22 | namespace PTL { 23 | 24 | // 1MHz / 3 = 333KHz 25 | #define FLASH_CLOCK_DIV 3 26 | 27 | #define FLASH_SEGMENT_D 0x1000 28 | 29 | class Flash 30 | { 31 | public: 32 | static void init() 33 | { 34 | // MCLK should be 1MHz 35 | FCTL2 = FWKEY | FSSEL_1 | (FLASH_CLOCK_DIV - 1); 36 | } 37 | 38 | static void erase(void *block) 39 | { 40 | // Watchdog should be disabled 41 | // Reset LOCK and other status bits 42 | FCTL3 = FWKEY; 43 | FCTL1 = FWKEY | ERASE; 44 | *(uint8_t*)block = 0; 45 | FCTL1 = FWKEY; 46 | FCTL3 = FWKEY | LOCK; 47 | } 48 | 49 | static void write8(uint8_t *addr, uint8_t val) 50 | { 51 | // Reset LOCK and other status bits 52 | FCTL3 = FWKEY; 53 | FCTL1 = FWKEY | WRT; 54 | *addr = val; 55 | FCTL1 = FWKEY; 56 | FCTL3 = FWKEY | LOCK; 57 | } 58 | 59 | static void write16(uint16_t *addr, uint16_t val) 60 | { 61 | // Reset LOCK and other status bits 62 | FCTL3 = FWKEY; 63 | FCTL1 = FWKEY | WRT; 64 | *addr = val; 65 | FCTL1 = FWKEY; 66 | FCTL3 = FWKEY | LOCK; 67 | } 68 | }; 69 | 70 | } // namespace 71 | -------------------------------------------------------------------------------- /include/msp430/gpio_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _GPIO_MSP430_HPP 20 | #define _GPIO_MSP430_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | template 29 | class Port : public IPort 30 | { 31 | public: 32 | static const int base = in_reg_; 33 | static const int in_reg = in_reg_; 34 | static const int out_reg = out_reg_; 35 | static const int dir_reg = dir_reg_; 36 | static const int resistor_reg = resistor_reg_; 37 | }; 38 | 39 | typedef Port P1; 40 | typedef Port P2; 41 | typedef Port P3; 42 | 43 | template 44 | class Pin : public PortPin< Pin, port, bit > 45 | { 46 | public: 47 | static typename port::width value() 48 | { 49 | return _REG8(port::in_reg) & bit::value; 50 | } 51 | static void high() 52 | { 53 | _REG8(port::out_reg) |= bit::value; 54 | } 55 | static void low() 56 | { 57 | _REG8(port::out_reg) &= ~bit::value; 58 | } 59 | static void toggle() 60 | { 61 | _REG8(port::out_reg) ^= bit::value; 62 | } 63 | static void output() 64 | { 65 | _REG8(port::dir_reg) |= bit::value; 66 | } 67 | static void input() 68 | { 69 | _REG8(port::dir_reg) &= ~bit::value; 70 | } 71 | static void pulloff() 72 | { 73 | _REG8(port::resistor_reg) &= ~bit::value; 74 | } 75 | static void pullup() 76 | { 77 | _REG8(port::resistor_reg) |= bit::value; 78 | _REG8(port::out_reg) |= bit::value; 79 | } 80 | static void pulldown() 81 | { 82 | _REG8(port::resistor_reg) |= bit::value; 83 | _REG8(port::out_reg) &= ~bit::value; 84 | } 85 | }; 86 | 87 | } // namespace 88 | 89 | #endif //_GPIO_MSP430_HPP 90 | -------------------------------------------------------------------------------- /include/msp430/spi_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _SPI_MSP430_HPP 20 | #define _SPI_MSP430_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | // Hardware USCI SPI pins (P1) 28 | #define SCLK BIT5 29 | #define SDI BIT7 30 | #define SDO BIT6 31 | 32 | template <> 33 | class SPI : public ISPI, public SPIBlockXfer< SPI >, public MSP430Block 34 | { 35 | public: 36 | typedef USCI_B usci; 37 | const static int block_type = MSP430_USCI; 38 | 39 | static void init() 40 | { 41 | UCB0CTL1 = UCSWRST; 42 | 43 | // SMCLK 44 | UCB0CTL1 = UCSWRST | UCSSEL_2; 45 | 46 | // Suitable polarity mode, master, 3-wire SPI, synchronous op 47 | UCB0CTL0 = UCCKPH | UCMSB | UCMST | UCMODE_0 | UCSYNC; 48 | 49 | // SPI clock = SMCLK / 1 50 | UCB0BR0 = 1; 51 | UCB0BR1 = 0; 52 | 53 | // Set SPI altfuncs for pins 54 | P1SEL |= SCLK | SDI | SDO; 55 | P1SEL2 |= SCLK | SDI | SDO; 56 | // Per MSP430 manual, direction of SCLK/MOSI/MISO is controlled 57 | // by USCI module itself 58 | UCB0CTL1 &= ~UCSWRST; 59 | } 60 | 61 | static void disable() 62 | { 63 | UCB0CTL1 = UCSWRST; 64 | // Unset SPI altfuncs, back to GPIO mode 65 | P1SEL &= ~(SCLK | SDI | SDO); 66 | P1SEL2 &= ~(SCLK | SDI | SDO); 67 | } 68 | 69 | #define NOP() asm("nop") 70 | #define NOP8() { NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); } 71 | 72 | static uint8_t transfer(uint8_t b) 73 | { 74 | UCB0TXBUF = b; 75 | // We know that transfer takes 8 cycles, so instead of (long) loop, 76 | // just use 8 nop's. 77 | // while (!(IFG2 & UCB0RXIFG)); 78 | NOP8(); 79 | return UCB0RXBUF; 80 | } 81 | 82 | static void write(uint8_t b) { transfer(b); } 83 | 84 | static void irq_rx() {} 85 | static void irq_tx() {} 86 | }; 87 | 88 | } // namespace 89 | 90 | #endif //_SPI_MSP430_HPP 91 | -------------------------------------------------------------------------------- /include/msp430/timer_irq_dispatch_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TIMER_MSP430_DISPATCH_HPP 20 | #define _TIMER_MSP430_DISPATCH_HPP 21 | 22 | #include 23 | // interrupt(X) define. TODO: get rid of? 24 | #include 25 | 26 | namespace PTL { 27 | 28 | // We use approach of grouping IRQ handlers into struct TimerIrqsBase 29 | // because this allows easier method inlining for pre-C+11 compiers, 30 | // and (arguably?) less tricky (but multi-level) empty handler usage. 31 | struct TimerIrqsBase { 32 | // Empty, unused methods expected to be eliminated with --gc-sections 33 | static void overflow() {} 34 | static void cc0() {} 35 | static void cc1() {} 36 | static void cc2() {} 37 | }; 38 | 39 | template 40 | class TimerIrqDispatch 41 | { 42 | 43 | public: 44 | ALWAYS_INLINE static void handle_main() { 45 | // Reading status also acks IRQ 46 | switch (timer::irq_status()) { 47 | // 1. MSP headers define TAIV bits per-timer, but they are actually 48 | // the same for all timers (hopefully for all MCUs!) 49 | // 2. Method calls below are expected to be inlined, and if 50 | // one is empry, entire branch to be dead-code elimated. 51 | case TA0IV_TAIFG: 52 | irq_handlers::overflow(); 53 | break; 54 | case TA0IV_TACCR1: 55 | irq_handlers::cc1(); 56 | break; 57 | case TA0IV_TACCR2: 58 | irq_handlers::cc2(); 59 | break; 60 | } 61 | } 62 | 63 | ALWAYS_INLINE static void handle_cc0() { 64 | irq_handlers::cc0(); 65 | } 66 | 67 | // The idea would be to *define* *Timer's* irq_handler*() here (as a friend 68 | // method). Unfortunately that's not supported by C++. So, we'll define 69 | // irq handlers as ours, at least Timer::irq_no_* allows us to avoid duplication 70 | // and abstract it a bit. 71 | 72 | // Unfortunately, this doesn't work with gcc 4.5 either 73 | 74 | #if 0 75 | static interrupt(Timer::irq_no_main) irq_handler() 76 | { 77 | handle_main(); 78 | } 79 | 80 | static interrupt(Timer::irq_no_cc0) irq_handler_cc0() 81 | } 82 | if (cc0) cc0(); 83 | } 84 | #endif 85 | }; 86 | 87 | // Can't get around using macros - see above 88 | // But now that we need to use macros, let's hide TimerIrqDispatch 89 | // instantiation there too. 90 | #define IRQ_DISPATCH(timer, irq_handlers) \ 91 | template <> \ 92 | void timer::irq_handler() \ 93 | { TimerIrqDispatch::handle_main(); } \ 94 | template <> \ 95 | void timer::irq_handler_cc0() \ 96 | { TimerIrqDispatch::handle_cc0(); } 97 | 98 | } // namespace 99 | 100 | #endif // _TIMER_MSP430_DISPATCH_HPP 101 | -------------------------------------------------------------------------------- /include/msp430/timer_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TIMER_MSP430_HPP 20 | #define _TIMER_MSP430_HPP 21 | 22 | #include 23 | #include 24 | // interrupt(X) define. TODO: get rid of? 25 | #include 26 | #include 27 | 28 | namespace PTL { 29 | 30 | template 31 | class Timer : public ITimer< Timer, COUNT_UP, uint16_t > 32 | { 33 | public: 34 | const static int block_type = MSP430_TIMER; 35 | typedef uint16_t width; 36 | 37 | static const int ctrl_reg = ctrl_reg_; 38 | static const int val_reg = val_reg_; 39 | static const int intr_reg = intr_reg_; 40 | // TODO: refactor into common clock infra 41 | enum ClockDivider { DIV_1 = ID_0, DIV_2 = ID_1, DIV_4 = ID_2, DIV_8 = ID_3 }; 42 | 43 | static width value() { return *(volatile width*)val_reg; } 44 | static void free_run(ClockDivider div = DIV_1) 45 | { 46 | // SMCLK, continuous mode 47 | _REG16(ctrl_reg) = TASSEL_2 | MC_2 | div; 48 | } 49 | 50 | static void enable_irq() { *(volatile uint16_t*)ctrl_reg |= TAIE; } 51 | static void disable_irq() { *(volatile uint16_t*)ctrl_reg &= ~TAIE; } 52 | static uint16_t irq_status() { return *(volatile uint16_t*)intr_reg; } 53 | // __attribute__((interrupt(TIMER0_A1_VECTOR))) static void irq_handler(); 54 | static interrupt(TIMER0_A1_VECTOR) irq_handler(); 55 | static interrupt(TIMER0_A0_VECTOR) irq_handler_cc0(); 56 | 57 | static void irq_reset() {} 58 | static void irq_capture_compare0() {} 59 | static void irq_capture_compare1() {} 60 | static void irq_capture_compare2() {} 61 | }; 62 | 63 | 64 | typedef Timer Timer0_A; 65 | #ifdef TA1CTL_ 66 | typedef Timer Timer1_A; 67 | #endif 68 | typedef Timer0_A timer; 69 | 70 | } // namespace 71 | 72 | #endif // _TIMER_MSP430_HPP 73 | -------------------------------------------------------------------------------- /include/msp430/uart_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _UART_MSP430_HPP 20 | #define _UART_MSP430_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | template 27 | class UART : public MSP430Block 28 | { 29 | public: 30 | typedef USCI_A usci; 31 | const static int block_type = MSP430_USCI; 32 | 33 | static void init() 34 | { 35 | /* 36 | slau144i.pdf 15.3.1 p.424 37 | The recommended USCI initialization/re-configuration process is: 38 | 1. Set UCSWRST (BIS.B #UCSWRST,&UCAxCTL1) 39 | 2. Initialize all USCI registers with UCSWRST = 1 (including UCAxCTL1) 40 | 3. Configure ports. 41 | 4. Clear UCSWRST via software (BIC.B #UCSWRST,&UCAxCTL1) 42 | 5. Enable interrupts (optional) via UCAxRXIE and/or UCAxTXIE 43 | */ 44 | UCA0CTL1 |= UCSWRST; 45 | UCA0CTL0 = UCMODE_0; 46 | UCA0CTL1 = UCSSEL_2 | UCSWRST; 47 | UCA0BR0 = (freq / baud) & 0xff; 48 | UCA0BR1 = (freq / baud) >> 8; 49 | //uint8_t mod = (freq * 8 / baud) - (freq / baud * 8); 50 | // Proper rounding 51 | uint8_t mod = ((freq * 8 * 2 / baud) - (freq / baud * 8 * 2) + 1) / 2; 52 | UCA0MCTL = mod << 1; 53 | P1SEL |= BIT1 | BIT2; 54 | P1SEL2 |= BIT1 | BIT2; 55 | P1DIR &= ~BIT1; 56 | P1DIR |= BIT2; 57 | UCA0CTL1 &= ~UCSWRST; 58 | } 59 | 60 | static uint8_t read() 61 | { 62 | while (!(IFG2 & UCA0RXIFG)); 63 | return UCA0RXBUF; 64 | } 65 | 66 | static void write(uint8_t b) 67 | { 68 | UCA0TXBUF = b; 69 | while (!(IFG2 & UCA0TXIFG)); 70 | } 71 | 72 | static uint8_t read_async() 73 | { 74 | return UCA0RXBUF; 75 | } 76 | 77 | static void write_async(uint8_t b) 78 | { 79 | UCA0TXBUF = b; 80 | } 81 | 82 | static bool read_ready() 83 | { 84 | return IFG2 & UCA0RXIFG; 85 | } 86 | 87 | static bool write_ready() 88 | { 89 | return IFG2 & UCA0TXIFG; 90 | } 91 | 92 | static void enable_rx_irq() { IE2 |= UCA0RXIE; } 93 | static void disable_rx_irq() { IE2 &= ~UCA0RXIE; } 94 | static void enable_tx_irq() { IE2 |= UCA0TXIE; } 95 | static void disable_tx_irq() { IE2 &= ~UCA0TXIE; } 96 | 97 | static interrupt(USCIAB0RX_VECTOR) uart_rx_irq_handler(); 98 | static interrupt(USCIAB0TX_VECTOR) uart_tx_irq_handler(); 99 | 100 | static void irq_rx() {} 101 | static void irq_tx() {} 102 | }; 103 | 104 | } // namespace 105 | 106 | #endif //_UART_MSP430_HPP 107 | -------------------------------------------------------------------------------- /include/msp430/watchdog_msp430.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _WATCHDOG_MSP430_HPP 20 | #define _WATCHDOG_MSP430_HPP 21 | 22 | namespace PTL { 23 | 24 | class Watchdog 25 | { 26 | public: 27 | const static uint16_t SMCLK = 0; 28 | const static uint16_t ACLK = WDTSSEL; 29 | 30 | const static uint16_t INTERVAL_32768 = 0; 31 | const static uint16_t INTERVAL_8192 = 1; 32 | const static uint16_t INTERVAL_512 = 2; 33 | const static uint16_t INTERVAL_64 = 3; 34 | 35 | template 36 | static void enable_watchdog(uint16_t interval) 37 | { 38 | // slau144i 10.2.3 p.352 "The WDT+ should be halted before changing 39 | // the clock source to avoid a possible incorrect interval." 40 | disable(); 41 | WDTCTL = WDTPW | WDTCNTCL | clock::as_watchdog_clock() | interval; 42 | } 43 | 44 | template 45 | static void set_interval(uint16_t interval) 46 | { 47 | // Warning: 48 | // slau144i 10.2.3 p.352 "The WDT+ should be halted before changing 49 | // the clock source to avoid a possible incorrect interval." 50 | WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | clock::as_watchdog_clock() | interval; 51 | } 52 | 53 | template 54 | static void enable_interval(uint16_t interval) 55 | { 56 | // slau144i 10.2.3 p.352 "The WDT+ should be halted before changing 57 | // the clock source to avoid a possible incorrect interval." 58 | disable(); 59 | set_interval(interval); 60 | } 61 | 62 | static void disable() { WDTCTL = WDTPW | WDTHOLD; } 63 | static void reset() { WDTCTL = WDTPW | ((WDTCTL & 0xff) | WDTCNTCL); } 64 | static void enable_irq() { IE1 |= WDTIE; } 65 | static void disable_irq() { IE1 &= ~WDTIE; } 66 | }; 67 | 68 | } // namespace 69 | 70 | #endif //_WATCHDOG_MSP430_HPP 71 | -------------------------------------------------------------------------------- /include/nrf51/gpio_nrf51.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _GPIO_NRF51_HPP 20 | #define _GPIO_NRF51_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | #undef FVAL 29 | #define FVAL(field, val) field##_##MASK, field##_##val 30 | 31 | template 32 | class Port : public IPort 33 | { 34 | public: 35 | static const int base = base_; 36 | 37 | static GPIO_Type *ptr() { return (GPIO_Type*)base; } 38 | 39 | static void enable() { 40 | // Doesn't seem to be a need to enable (single in MCU) port explicitly? 41 | } 42 | }; 43 | 44 | typedef Port P0; 45 | 46 | template 47 | class Pin : public PortPin< Pin, port, bit > 48 | { 49 | public: 50 | static typename port::width value() 51 | { 52 | return port::ptr()->IN & bit::value; 53 | } 54 | static void high() 55 | { 56 | port::ptr()->OUTSET = bit::value; 57 | } 58 | static void low() 59 | { 60 | port::ptr()->OUTCLR = bit::value; 61 | } 62 | static void toggle() 63 | { 64 | port::ptr()->OUT ^= bit::value; 65 | } 66 | 67 | static void output() 68 | { 69 | // nRF51 refman 13.1 p.56: "Pin direction can be configured both in 70 | // the DIR register as well as through the individual PIN_CNF[n] 71 | // registers. A change in one register will automatically be 72 | // reflected in the other register. 73 | port::ptr()->DIRSET = bit::value; 74 | // nRF51 refman 13.1 p.55: "The input buffer of a GPIO pin can be 75 | // disconnected from the pin to enable power savings when the pin is 76 | // not used as an input. Inputs must be connected in order to get a 77 | // valid input value in the IN register and for the sense mechanism 78 | // to get access to the pin. 79 | SET_BITFIELD(port::ptr()->PIN_CNF[bit::shift], FVAL(GPIO_PIN_CNF_INPUT, DISCONNECT)); 80 | } 81 | static void input() 82 | { 83 | // See output() comments 84 | SET_BITFIELD(port::ptr()->PIN_CNF[bit::shift], FVAL(GPIO_PIN_CNF_INPUT, CONNECT)); 85 | port::ptr()->DIRCLR = bit::value; 86 | } 87 | 88 | static void pulloff() 89 | { 90 | volatile uint32_t *reg = &port::ptr()->PIN_CNF[bit::shift]; 91 | SET_BITFIELD(*reg, FVAL(GPIO_PIN_CNF_PULL, DISABLED)); 92 | } 93 | static void pullup() 94 | { 95 | volatile uint32_t *reg = &port::ptr()->PIN_CNF[bit::shift]; 96 | SET_BITFIELD(*reg, FVAL(GPIO_PIN_CNF_PULL, PULLUP)); 97 | } 98 | static void pulldown() 99 | { 100 | volatile uint32_t *reg = &port::ptr()->PIN_CNF[bit::shift]; 101 | SET_BITFIELD(*reg, FVAL(GPIO_PIN_CNF_PULL, PULLDOWN)); 102 | } 103 | }; 104 | 105 | } // namespace 106 | 107 | #endif //_GPIO_NRF51_HPP 108 | -------------------------------------------------------------------------------- /include/parallel_bus.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _PARALLEL_BUS_HPP 20 | #define _PARALLEL_BUS_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | // Parallel bus made of individual GPIO signals 27 | // Widths 1-8 are supported, if wider bus required, just use this class 28 | // several times. (Note that wide bus constructed from arbitrary GPIOs 29 | // would be pretty inefficient, better to base it on ordered range of 30 | // GPIOs and Port class - ParBusAligned below). 31 | 32 | template 40 | class ParBus; 41 | 42 | // "Empty" partial specialization to stop recursion 43 | template <> 44 | class ParBus 46 | { 47 | public: 48 | static void write(uint8_t v) {} 49 | static uint8_t read() { return 0; } 50 | 51 | static void enable() {} 52 | static void input() {} 53 | static void output() {} 54 | }; 55 | 56 | // Recursive template definition 57 | template 58 | class ParBus : public ParBus 59 | { 60 | typedef ParBus rest; 61 | public: 62 | typedef uint8_t width; 63 | 64 | static void write(uint8_t v) { 65 | bit0::set(v & 0x01); 66 | rest::write(v >> 1); 67 | } 68 | 69 | static uint8_t read() { 70 | return (bool)bit0::value() | rest::read(); 71 | } 72 | 73 | static void enable() { 74 | bit0::port::enable(); 75 | rest::enable(); 76 | } 77 | 78 | static void input() { 79 | bit0::input(); 80 | rest::input(); 81 | } 82 | 83 | static void output() { 84 | bit0::output(); 85 | rest::output(); 86 | } 87 | }; 88 | 89 | // Parallel bus which is aligned to properly ordered subrange 90 | // of port pins 91 | // TODO: incomplete 92 | template 93 | class ParBusAligned 94 | { 95 | // static_assert(lsb::port == msb::port); 96 | public: 97 | typedef width_ width; 98 | 99 | protected: 100 | const static int bus_width = msb::bit::shift - lsb::bit::shift + 1; 101 | const static width bus_mask = (1 << bus_width) - 1; 102 | 103 | public: 104 | static void enable() { 105 | lsb::port::enable(); 106 | } 107 | 108 | static void write(width v) { 109 | lsb::port::set_masked(v << lsb::bit::shift, bus_mask << lsb::bit::shift); 110 | } 111 | 112 | static width read() { 113 | return (lsb::port::value() >> lsb::bit::shift) & bus_mask; 114 | } 115 | }; 116 | 117 | } // namespace 118 | 119 | #endif // _PARALLEL_BUS_HPP 120 | -------------------------------------------------------------------------------- /include/posix/sleep_posix.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _SLEEP_MSP430_HPP 20 | #define _SLEEP_MSP430_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | class Sleep 28 | { 29 | public: 30 | static void sleep(uint32_t interval) 31 | { 32 | usleep(interval); 33 | } 34 | 35 | static void powerdown() 36 | { 37 | fprintf(stderr, "System powered down\n"); 38 | exit(99); 39 | } 40 | }; 41 | 42 | } // namespace 43 | 44 | #endif //_SLEEP_MSP430_HPP 45 | -------------------------------------------------------------------------------- /include/posix/timer_posix.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TIMER_POSIX_HPP 20 | #define _TIMER_POSIX_HPP 21 | 22 | #include 23 | 24 | #include 25 | 26 | namespace PTL { 27 | 28 | class Timer : public ITimer 29 | { 30 | public: 31 | 32 | static width value() 33 | { 34 | struct timeval t; 35 | gettimeofday(&t, NULL); 36 | return t.tv_sec * 1000000 + t.tv_usec; 37 | } 38 | 39 | static void free_run() 40 | { 41 | // Always running 42 | } 43 | }; 44 | 45 | typedef Timer timer; 46 | 47 | } // namespace 48 | 49 | #endif // _TIMER_POSIX_HPP 50 | -------------------------------------------------------------------------------- /include/progmem.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifdef __AVR__ 20 | 21 | #include 22 | 23 | #define progmem PROGMEM 24 | #define memcpy_progmem memcpy_P 25 | 26 | #else 27 | 28 | // Normal Von Neumann architecture, code space accessible 29 | // from data space 30 | 31 | #define progmem 32 | #define memcpy_progmem memcpy 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /include/protocol/avr_isp.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2014 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #include 21 | #include 22 | 23 | // TODO: WIP, untested 24 | 25 | namespace PTL { 26 | 27 | template 28 | class AVR_ISP 29 | { 30 | public: 31 | static void init() 32 | { 33 | reset_sig::output(); 34 | reset_sig::deassert(); 35 | } 36 | 37 | static void start() 38 | { 39 | reset_sig::assert(); 40 | //AVR910 41 | delayer::delay_ms(20); 42 | } 43 | 44 | static void send_cmd(uint16_t cmd, uint8_t b2, uint8_t b3) 45 | { 46 | spi::transfer(cmd >> 8); 47 | spi::transfer(cmd & 0xff); 48 | spi::transfer(b2); 49 | return spi::transfer(b3); 50 | } 51 | 52 | static void enable_program() 53 | { 54 | if (send_cmd(CMD_Program_Enable, 0x55, 0xaa) != 0x55) 55 | return false; 56 | return true; 57 | } 58 | 59 | static void read_flash(uint16_t addr) 60 | { 61 | uint16_t cmd = addr & 1 ? CMD_Read_Flash_High : CMD_Read_Flash_Low; 62 | addr >>= 1; 63 | return send_cmd(cmd | (addr >> 8), addr & 0xff, 0); 64 | } 65 | }; 66 | 67 | } // namespace 68 | -------------------------------------------------------------------------------- /include/protocol/usb.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2014 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | 20 | // TODO: WIP, untested 21 | 22 | namespace PTL { 23 | 24 | template <> 25 | class USB 26 | { 27 | PID _next_data = PID_DATA0; 28 | public: 29 | static void xact_in(); 30 | static void xact_out(usb_addr_t addr, usb_endp_t endpoint, uint8_t *data, uint16_t len) 31 | { 32 | send_token(PID_OUT, addr, endpoint); 33 | send_data(next_data(), data, len); 34 | recv_handshake(); 35 | } 36 | static void xact_setup(); 37 | 38 | PID next_data() 39 | { 40 | PID r = _next_data; 41 | if (_next_data == PID_DATA0) 42 | _next_data == PID_DATA1; 43 | else 44 | _next_data == PID_DATA0; 45 | } 46 | }; 47 | 48 | } // namespace 49 | -------------------------------------------------------------------------------- /include/rtos/buffered_uart.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #include 21 | 22 | namespace PTL { 23 | 24 | template class buffer = PTL::CircularBuffer> 26 | class BufferedUart 27 | { 28 | public: 29 | 30 | static buffer read_buf; 31 | static buffer write_buf; 32 | 33 | class uart_handlers : public uart 34 | { 35 | public: 36 | static void irq_rx() 37 | { 38 | if (read_buf.full()) 39 | overrun(); 40 | else 41 | read_buf.push(uart::read_async()); 42 | } 43 | static void irq_tx() 44 | { 45 | // assert(!store.write_buf.empty()); 46 | uint8_t c = write_buf.pop(); 47 | uart::write_async(c); 48 | // If there's nothing more to send, disable TX IRQ 49 | // (really "TX Buffer Empty IRQ") 50 | if (write_buf.empty()) 51 | uart::disable_tx_irq(); 52 | } 53 | }; 54 | 55 | public: 56 | static void init() 57 | { 58 | uart::init(); 59 | // We always should expect to receive something 60 | uart::enable_rx_irq(); 61 | // but in the beginning, there's nothing to send - 62 | // interrupts will be enabled on first char to send 63 | uart::disable_tx_irq(); 64 | } 65 | static uint8_t read() 66 | { 67 | while (read_buf.empty()); 68 | uart::disable_rx_irq(); 69 | uint8_t c = read_buf.pop(); 70 | uart::enable_rx_irq(); 71 | return c; 72 | } 73 | static void write(uint8_t c) 74 | { 75 | while (write_buf.full()); 76 | uart::disable_tx_irq(); 77 | write_buf.push(c); 78 | // We added new char, so there's something to send - enable TX IRQ 79 | uart::enable_tx_irq(); 80 | } 81 | 82 | // Override 83 | static void overrun() 84 | { 85 | } 86 | 87 | }; 88 | 89 | // Explicit instantiation of static fields 90 | template class buffer> 91 | buffer BufferedUart::read_buf; 92 | template class buffer> 93 | buffer BufferedUart::write_buf; 94 | 95 | } // namespace 96 | -------------------------------------------------------------------------------- /include/rtos/circular.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | namespace PTL { 20 | 21 | 22 | // Note: only methods marked "volatile" are thread/interrupt safe 23 | // All other methods should be called only from critical section 24 | // (e.g., with interrupts disabled). 25 | template 26 | class CircularBuffer 27 | { 28 | elem buf[max_size_]; 29 | elem *head, *tail; 30 | uint8_t _size; 31 | public: 32 | CircularBuffer() : head(buf), tail(buf), _size(0) {} 33 | 34 | /* std:queue compliant methods */ 35 | 36 | int size() const 37 | { 38 | return _size; 39 | } 40 | 41 | bool empty() const volatile 42 | { 43 | return _size == 0; 44 | } 45 | 46 | void push(elem e) 47 | { 48 | *tail++ = e; 49 | if (tail >= buf + max_size_) 50 | tail = buf; 51 | _size++; 52 | } 53 | 54 | elem pop() 55 | { 56 | elem e = *head++; 57 | if (head >= buf + max_size_) 58 | head = buf; 59 | _size--; 60 | return e; 61 | } 62 | 63 | elem front() const volatile 64 | { 65 | return *head; 66 | } 67 | 68 | // No back, sorry 69 | //elem back() const; 70 | 71 | /* extended methods */ 72 | 73 | int free_size() const 74 | { 75 | return max_size_ - _size; 76 | } 77 | 78 | bool full() const volatile 79 | { 80 | return _size == max_size_; 81 | } 82 | 83 | bool has_free_size(unsigned size) 84 | { 85 | return free_size() >= size; 86 | } 87 | 88 | void push(const elem *p, uint8_t len) 89 | { 90 | while (len--) { 91 | push(*p++); 92 | } 93 | } 94 | 95 | bool push_checked(elem b) 96 | { 97 | if (full()) 98 | return false; 99 | push(b); 100 | return true; 101 | } 102 | 103 | elem pop_checked() 104 | { 105 | if (empty()) 106 | return 0; 107 | return pop(); 108 | } 109 | 110 | /* Read/write interface */ 111 | void write(elem b) { push_checked(b); } 112 | // Checking that buffer contains enough elements is on the caller 113 | elem read() { return pop(); } 114 | }; 115 | 116 | } // namespace 117 | -------------------------------------------------------------------------------- /include/rtos/perf_counter.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _PERF_COUNTER_HPP 20 | #define _PERF_COUNTER_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | #ifdef __MSP430__ 27 | #define PERF_COUNTER_CORRECTION 6 28 | #else 29 | #define PERF_COUNTER_CORRECTION 0 30 | #endif 31 | 32 | template 33 | class PerfCounter 34 | { 35 | typename timer::width counter; 36 | public: 37 | void start() { counter = timer::value(); } 38 | 39 | typename timer::width elapsed() 40 | { return timer::elapsed(timer::value(), counter) - PERF_COUNTER_CORRECTION; } 41 | 42 | typename timer::width stop() 43 | { return counter = elapsed(); } 44 | typename timer::width value() { return counter; } 45 | }; 46 | 47 | typedef PerfCounter Perf; 48 | 49 | } // namespace 50 | 51 | #endif //_PERF_COUNTER_HPP 52 | -------------------------------------------------------------------------------- /include/rtos/perf_counter_acu.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _PERF_COUNTER_ACU_HPP 20 | #define _PERF_COUNTER_ACU_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | template 27 | class PerfCounterAcu 28 | { 29 | public: 30 | typedef width_ width; 31 | 32 | private: 33 | width counter; 34 | typename timer::width last_val; 35 | 36 | public: 37 | PerfCounterAcu() : counter(0) {} 38 | void reset() { counter = 0; } 39 | void start() { last_val = timer::value(); } 40 | void update() 41 | { 42 | typename timer::width t = timer::value(); 43 | counter += timer::elapsed(t, last_val); 44 | last_val = t; 45 | } 46 | width value() { return counter; } 47 | width elapsed() { update(); return value(); } 48 | }; 49 | 50 | typedef PerfCounterAcu PerfAcu; 51 | 52 | } // namespace 53 | 54 | #endif //_PERF_COUNTER_ACU_HPP 55 | -------------------------------------------------------------------------------- /include/rtos/ticks.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TIMER_TICK_HPP 20 | #define _TIMER_TICK_HPP 21 | #include 22 | 23 | namespace PTL { 24 | 25 | template 26 | class Ticks : public ITimer< Ticks, COUNT_UP, width > 27 | { 28 | protected: 29 | volatile static width ticks; 30 | public: 31 | static void reset() { ticks = 0; } 32 | static void inc() { ticks++; } 33 | static width value() { return ticks; } 34 | 35 | class timer_handlers : public timer { 36 | public: 37 | static void irq_reset() 38 | { 39 | Ticks::inc(); 40 | } 41 | }; 42 | }; 43 | 44 | // Explicit instantiation of static class variable - will be a COMMON symbol 45 | // http://sourceware.org/binutils/docs/as/Comm.html#Comm 46 | template volatile width Ticks::ticks; 47 | 48 | // Client must bind Ticks::Irqs to a specific timer object using IRQ_DISPATCH: 49 | //IRQ_DISPATCH(timer, Ticks<>::Irqs); 50 | 51 | } // namespace 52 | 53 | #endif // _TIMER_TICK_HPP 54 | -------------------------------------------------------------------------------- /include/rtos/virt_timer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _VIRT_TIMER_HPP 20 | #define _VIRT_TIMER_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | template 27 | class VirtTimer 28 | { 29 | typename timer::width start; 30 | typename timer::width period; 31 | public: 32 | void start(typename timer::width period) { start = timer::value(); this->period = period; } 33 | bool expired() 34 | { return timer::elapsed(timer::value(), start) > period; } 35 | }; 36 | 37 | } // namespace 38 | 39 | #endif //_VIRT_TIMER_HPP 40 | -------------------------------------------------------------------------------- /include/signal.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _SIGNAL_HPP 20 | #define _SIGNAL_HPP 21 | 22 | namespace PTL { 23 | 24 | template 25 | class Signal 26 | { 27 | public: 28 | typedef typename pin::port port; 29 | 30 | static void output() { pin::output(); } 31 | static void input() { pin::input(); } 32 | static void assert() { pin::high(); } 33 | static void deassert() { pin::low(); } 34 | static void toggle() { pin::toggle(); } 35 | static bool value() { return pin::value(); } 36 | static bool is_asserted() { return value(); } 37 | }; 38 | 39 | template 40 | class InvertedSignal 41 | { 42 | public: 43 | typedef typename pin::port port; 44 | 45 | static void output() { pin::output(); } 46 | static void input() { pin::input(); } 47 | static void assert() { pin::low(); } 48 | static void deassert() { pin::high(); } 49 | static void toggle() { pin::toggle(); } 50 | static bool value() { return !pin::value(); } 51 | static bool is_asserted() { return value(); } 52 | }; 53 | 54 | } // namespace 55 | 56 | #endif //_SIGNAL_HPP 57 | 58 | -------------------------------------------------------------------------------- /include/sleep.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifdef __MSP430__ 20 | #include 21 | #elif defined(__linux__) 22 | #include 23 | #else 24 | #error Unknown platform in sleep.hpp 25 | #endif 26 | -------------------------------------------------------------------------------- /include/sleep_impl.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | 21 | #ifdef __MSP430__ 22 | namespace PTL { 23 | 24 | uint32_t Sleep::_interval; 25 | 26 | } // namespace 27 | #endif 28 | -------------------------------------------------------------------------------- /include/spi.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #ifdef __MSP430__ 21 | #include 22 | #endif 23 | -------------------------------------------------------------------------------- /include/spi_command.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _SPI_COMMAND_HPP 20 | #define _SPI_COMMAND_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | template 28 | class SPICommandMixIn 29 | { 30 | public: 31 | static void init() 32 | { 33 | cs::output(); 34 | cs::deassert(); 35 | } 36 | 37 | static uint8_t spi_command(uint8_t cmd) 38 | { 39 | uint8_t val; 40 | cs::assert(); 41 | val = spi::transfer(cmd); 42 | cs::deassert(); 43 | return val; 44 | } 45 | 46 | static uint8_t spi_command_read(uint8_t cmd) 47 | { 48 | uint8_t val; 49 | cs::assert(); 50 | spi::transfer(cmd); 51 | val = spi::transfer(0xFF); 52 | cs::deassert(); 53 | return val; 54 | } 55 | 56 | static void spi_command_write(uint8_t cmd, uint8_t val) 57 | { 58 | cs::assert(); 59 | spi::transfer(cmd); 60 | spi::transfer(val); 61 | cs::deassert(); 62 | } 63 | 64 | static void spi_command_read_block(uint8_t cmd, uint8_t *buf, uint8_t len) 65 | { 66 | cs::assert(); 67 | spi::transfer(cmd); 68 | spi::read_block(buf, len); 69 | cs::deassert(); 70 | } 71 | 72 | static void spi_command_write_block(uint8_t cmd, const uint8_t *buf, uint8_t len) 73 | { 74 | cs::assert(); 75 | spi::transfer(cmd); 76 | spi::write_block(buf, len); 77 | cs::deassert(); 78 | } 79 | }; 80 | 81 | } // namespace 82 | 83 | #endif //_SPI_COMMAND_HPP 84 | -------------------------------------------------------------------------------- /include/stm32/cpu_stm32.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | 21 | namespace PTL { 22 | 23 | class STM32CPU {}; 24 | 25 | template <> 26 | class CPU : public CPU 27 | { 28 | }; 29 | 30 | typedef CPU cpu; 31 | 32 | } // namespace 33 | -------------------------------------------------------------------------------- /include/stm32/gpio_stm32.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _GPIO_STM32_HPP 20 | #define _GPIO_STM32_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | template 28 | class Port : public IPort 29 | { 30 | public: 31 | static const int base = base_; 32 | 33 | static GPIO_TypeDef *ptr() { return (GPIO_TypeDef*)base; } 34 | 35 | static void enable() { 36 | switch (base) { 37 | case GPIOA_BASE: 38 | RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; 39 | break; 40 | case GPIOB_BASE: 41 | RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; 42 | break; 43 | case GPIOC_BASE: 44 | RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; 45 | break; 46 | case GPIOD_BASE: 47 | RCC->APB2ENR |= RCC_APB2ENR_IOPDEN; 48 | break; 49 | } 50 | } 51 | }; 52 | 53 | typedef Port PA; 54 | typedef Port PB; 55 | typedef Port PC; 56 | typedef Port PD; 57 | 58 | template 59 | class Pin : public PortPin< Pin, port, bit > 60 | { 61 | static void set_mode(int mode) 62 | { 63 | volatile uint32_t *reg; 64 | if (bit::shift < 8) 65 | reg = &port::ptr()->CRL; 66 | else 67 | reg = &port::ptr()->CRH; 68 | uint32_t mask = 0xf << ((bit::shift % 8) * 4); 69 | uint32_t val = mode << ((bit::shift % 8) * 4); 70 | *reg = (*reg & ~mask) | val; 71 | } 72 | 73 | public: 74 | static typename port::width value() 75 | { 76 | return port::ptr()->IDR & bit::value; 77 | } 78 | static void high() 79 | { 80 | port::ptr()->BSRR = bit::value; 81 | } 82 | static void low() 83 | { 84 | port::ptr()->BRR = bit::value; 85 | } 86 | static void toggle() 87 | { 88 | port::ptr()->ODR ^= bit::value; 89 | } 90 | 91 | static void output() 92 | { 93 | set_mode(0x02); 94 | } 95 | static void input() 96 | { 97 | set_mode(0x04); 98 | } 99 | }; 100 | 101 | } // namespace 102 | 103 | #endif //_GPIO_STM32_HPP 104 | -------------------------------------------------------------------------------- /include/stm32/includes_stm32.hpp: -------------------------------------------------------------------------------- 1 | // TODO: make target MCU dependent 2 | #ifdef LIBPERIPHA 3 | #include 4 | #include 5 | #else 6 | #include 7 | #endif 8 | -------------------------------------------------------------------------------- /include/timer.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifdef __MSP430__ 20 | #include 21 | #elif defined( __AVR__) 22 | #include 23 | #elif defined(__ARM_ARCH_7M__) 24 | #include 25 | #elif defined(__linux__) 26 | #include 27 | #else 28 | #error Unknown platform in timer.hpp 29 | #endif 30 | -------------------------------------------------------------------------------- /include/timer_irq_dispatch.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifdef __MSP430__ 20 | #include 21 | #else 22 | #error Unknown platform in timer_dispatch.hpp 23 | #endif 24 | -------------------------------------------------------------------------------- /include/tm4/cpu_tm4.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #pragma once 20 | #include 21 | 22 | namespace PTL { 23 | 24 | class TM4CPU {}; 25 | 26 | enum { TM4_UART }; 27 | 28 | template <> 29 | class CPU : public CPU 30 | { 31 | }; 32 | 33 | typedef CPU cpu; 34 | 35 | } // namespace 36 | -------------------------------------------------------------------------------- /include/tm4/gpio_tm4.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _GPIO_LM4_HPP 20 | #define _GPIO_LM4_HPP 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | namespace PTL { 27 | 28 | template 29 | class Port : public IPort 30 | { 31 | public: 32 | static const int base = base_; 33 | 34 | static GPIO_Type *ptr() { return (GPIO_Type*)base; } 35 | 36 | static void enable() { 37 | switch (base) { 38 | case GPIOA_BASE: 39 | SYSCTL->RCGCGPIO |= Bit0::value; 40 | break; 41 | case GPIOB_BASE: 42 | SYSCTL->RCGCGPIO |= Bit1::value; 43 | break; 44 | case GPIOC_BASE: 45 | SYSCTL->RCGCGPIO |= Bit2::value; 46 | break; 47 | case GPIOD_BASE: 48 | SYSCTL->RCGCGPIO |= Bit3::value; 49 | break; 50 | case GPIOE_BASE: 51 | SYSCTL->RCGCGPIO |= Bit4::value; 52 | break; 53 | case GPIOF_BASE: 54 | SYSCTL->RCGCGPIO |= Bit5::value; 55 | break; 56 | } 57 | } 58 | }; 59 | 60 | typedef Port PA; 61 | typedef Port PB; 62 | typedef Port PC; 63 | typedef Port PD; 64 | typedef Port PE; 65 | typedef Port PF; 66 | 67 | template 68 | class Pin : public PortPin< Pin, port, bit > 69 | { 70 | public: 71 | static typename port::width value() 72 | { 73 | return port::ptr()->DATA & bit::value; 74 | } 75 | static void high() 76 | { 77 | (&port::ptr()->DATA_START)[bit::value] = 0xff; 78 | } 79 | static void low() 80 | { 81 | (&port::ptr()->DATA_START)[bit::value] = 0x00; 82 | } 83 | static void toggle() 84 | { 85 | port::ptr()->DATA ^= bit::value; 86 | } 87 | 88 | static void output() 89 | { 90 | port::ptr()->DIR |= bit::value; 91 | enable(); 92 | } 93 | static void input() 94 | { 95 | port::ptr()->DIR &= ~bit::value; 96 | enable(); 97 | } 98 | static void enable() 99 | { 100 | port::ptr()->DEN |= bit::value; 101 | } 102 | static void disable() 103 | { 104 | port::ptr()->DEN &= ~bit::value; 105 | } 106 | 107 | static void altfunc(uint32_t func) 108 | { 109 | port::ptr()->AFSEL |= bit::value; 110 | uint32_t mask = 0xf << (bit::shift * 4); 111 | port::ptr()->PCTL = (port::ptr()->PCTL & ~mask) | (func << (bit::shift * 4)); 112 | } 113 | }; 114 | 115 | } // namespace 116 | 117 | #endif //_GPIO_LM4_HPP 118 | -------------------------------------------------------------------------------- /include/tm4/includes_tm4.hpp: -------------------------------------------------------------------------------- 1 | // TODO: make target MCU dependent 2 | #ifdef LIBPERIPHA 3 | #include 4 | #include 5 | #include 6 | #else 7 | #error Untested 8 | #endif 9 | -------------------------------------------------------------------------------- /include/tm4/uart_tm4.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012-2013 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _UART_LM4_HPP 20 | #define _UART_LM4_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | class UART0_ {}; 28 | 29 | #define FRACT_PART(x) ((x) - ((long)(x))) 30 | 31 | 32 | template 33 | class UART 34 | { 35 | typedef Pin rxpin; 36 | typedef Pin txpin; 37 | 38 | public: 39 | const static int block_type = TM4_UART; 40 | 41 | static void init() 42 | { 43 | SYSCTL->RCGCUART |= Bit0::value; 44 | txpin::port::enable(); 45 | // Both pins always belong to same port 46 | //rxpin::port::enable(); 47 | rxpin::altfunc(1); 48 | txpin::altfunc(1); 49 | // No need to set pin direction, just enable 50 | rxpin::enable(); 51 | txpin::enable(); 52 | // 16 assumes UART->CR & HSE == 0 53 | UART0->CR &= ~UART_CR_UARTEN; 54 | UART0->IBRD = freq / (16 * baud); 55 | UART0->FBRD = int(FRACT_PART((double)freq / (16 * baud)) * 64 + 0.5); 56 | UART0->LCRH = UART_LCRH_WLEN_8; 57 | UART0->CC = UART_CC_CS_PIOSC; 58 | UART0->CR |= UART_CR_UARTEN | UART_CR_RXE | UART_CR_TXE; 59 | } 60 | 61 | static uint8_t read() 62 | { 63 | while (UART0->FR & UART_FR_RXFE); 64 | return UART0->DR; 65 | } 66 | 67 | static void write(uint8_t b) 68 | { 69 | UART0->DR = b; 70 | while (UART0->FR & UART_FR_TXFF); 71 | } 72 | 73 | static uint8_t read_async() 74 | { 75 | return UART0->DR; 76 | } 77 | 78 | static void write_async(uint8_t b) 79 | { 80 | UART0->DR = b; 81 | } 82 | 83 | static bool read_ready() 84 | { 85 | return !(UART0->FR & UART_FR_RXFE); 86 | } 87 | 88 | static bool write_ready() 89 | { 90 | return !(UART0->FR & UART_FR_TXFF); 91 | } 92 | 93 | }; 94 | 95 | } // namespace 96 | 97 | #endif //_UART_LM4_HPP 98 | -------------------------------------------------------------------------------- /include/types.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _TYPES_HPP 20 | #define _TYPES_HPP 21 | 22 | #include 23 | 24 | namespace PTL { 25 | 26 | typedef uint8_t bool8; 27 | 28 | class None {}; 29 | 30 | typedef void (*IrqHandler)(); 31 | 32 | // Helpers to access iomem registers 33 | #define _REG8(addr) (*(volatile uint8_t*)(addr)) 34 | #define _REG16(addr) (*(volatile uint16_t*)(addr)) 35 | #define _REG32(addr) (*(volatile uint32_t*)(addr)) 36 | // AVR compat. TODO: get rid of these? 37 | #ifndef _R8 38 | #define _R8(addr) _REG8(addr) 39 | #define _R16(addr) _REG16(addr) 40 | #define _R32(addr) _REG32(addr) 41 | #endif 42 | 43 | #define ALWAYS_INLINE __attribute__((__always_inline__)) inline 44 | #define NOINLINE __attribute__((noinline)) 45 | 46 | } // namespace 47 | 48 | #endif //_TYPES_HPP 49 | -------------------------------------------------------------------------------- /include/uart.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #include 20 | #ifdef __MSP430__ 21 | #include 22 | #elif defined(__AVR__) 23 | #include 24 | #elif defined( __LM4__) 25 | #include 26 | #endif 27 | -------------------------------------------------------------------------------- /include/uart_base.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifndef _UART_HPP 20 | #define _UART_HPP 21 | 22 | #include 23 | #include 24 | 25 | namespace PTL { 26 | 27 | template 28 | class UART 29 | { 30 | static const int bit_time = freq / baud; 31 | 32 | public: 33 | static void init() 34 | { 35 | tx::output(); 36 | tx::high(); 37 | rx::input(); 38 | } 39 | static uint8_t read(); 40 | static void write(uint8_t b); 41 | }; 42 | 43 | template 44 | void UART::write(uint8_t val) 45 | { 46 | typename timer::width start; 47 | uint8_t bit_count = 8; 48 | 49 | // We fix initial transfer start time, 50 | // and reference all times against it, to 51 | // avoid accumulating error. 52 | start = timer::value(); 53 | 54 | // Start bit 55 | tx::low(); 56 | timer::delay_since(start, bit_time); 57 | 58 | // Data bits, LSB first 59 | do { 60 | if (val & 1) 61 | tx::high(); 62 | else 63 | tx::low(); 64 | start += bit_time; 65 | timer::delay_since(start, bit_time); 66 | val >>= 1; 67 | } while (--bit_count); 68 | 69 | // Stop bit 70 | tx::high(); 71 | start += bit_time; 72 | timer::delay_since(start, bit_time); 73 | } 74 | 75 | template 76 | uint8_t UART::read() 77 | { 78 | typename timer::width start; 79 | uint8_t bit_count = 8; 80 | typename rx::port::width val; 81 | uint8_t b = 0; 82 | 83 | // Wait for start bit (low) 84 | while (rx::value()); 85 | 86 | // We'll use absolute time reference, the same as for write() 87 | start = timer::value(); 88 | // We'll sample bit values in the middle of period 89 | timer::delay_since(start, bit_time / 2); 90 | start += bit_time / 2; 91 | // We're at the middle of start bit now 92 | 93 | do { 94 | timer::delay_since(start, bit_time); 95 | val = rx::value(); 96 | b >>= 1; 97 | if (val) 98 | b |= 0x80; 99 | start += bit_time; 100 | } while (--bit_count); 101 | 102 | return b; 103 | } 104 | 105 | } // namespace 106 | 107 | #endif //_UART_HPP 108 | -------------------------------------------------------------------------------- /include/watchdog.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the Peripheral Template Library project. 3 | * 4 | * Copyright (c) 2012 Paul Sokolovsky 5 | * 6 | * This library is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Lesser General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public License 17 | * along with this library. If not, see . 18 | */ 19 | #ifdef __MSP430__ 20 | #include 21 | #else 22 | #error Unknown platform in watchdog.hpp 23 | #endif 24 | -------------------------------------------------------------------------------- /scripts/msp430_rate.py: -------------------------------------------------------------------------------- 1 | def calc(freq, baud): 2 | return ((freq * 8 * 2 / baud) - (freq / baud * 8 * 2) + 1) / 2 3 | 4 | #for baud in (9600, 19200, 38400, 56000, 115200, 128000, 256000): 5 | 6 | MOD = [0, 0x02, 0x22, 0x2a, 0xaa, 0xae, 0xee, 0xfe] 7 | 8 | 9 | for baud in (256000,): 10 | div = 1000000 / baud 11 | mod = calc(1000000, baud) + 0 12 | print baud, mod 13 | t_ideal = 1.0 / baud 14 | print "ideal bit length (s):", t_ideal 15 | bit = 1 16 | err = 0.0 17 | while bit != 0x100: 18 | t = (div + int(bool(MOD[mod] & bit))) / 1000000.0 19 | print t, t - t_ideal 20 | err += t - t_ideal 21 | bit <<= 1 22 | 23 | print err / t_ideal * 100 24 | -------------------------------------------------------------------------------- /tests/Makefile: -------------------------------------------------------------------------------- 1 | PTL_PATH = .. 2 | include $(PTL_PATH)/Makefile.rules 3 | 4 | ALL = sub_mod circular nearptr 5 | 6 | .PHONY: $(ALL) 7 | .PRECIOUS: $(TARGETDIR)/%.o 8 | 9 | all: $(ALL) 10 | 11 | sub_mod: $(TARGETDIR)/sub_mod 12 | circular: $(TARGETDIR)/circular 13 | nearptr: $(TARGETDIR)/nearptr 14 | -------------------------------------------------------------------------------- /tests/asm_pattern_match.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import sys 3 | import re 4 | 5 | 6 | lines = [] 7 | 8 | asm_fname = sys.argv[1] 9 | pat_fname = sys.argv[2] 10 | 11 | with open(asm_fname) as f: 12 | in_func = False 13 | for l in f: 14 | l = l.strip() 15 | if not l: 16 | continue 17 | if l == ".cfi_endproc": 18 | in_func = False 19 | if in_func: 20 | if re.match(r".L\d+:", l): 21 | pass 22 | elif l[0] in ["@", "."]: 23 | continue 24 | # print l 25 | lines.append(l) 26 | elif "%function" in l: 27 | in_func = True 28 | 29 | pattern = [l.rstrip() for l in open(pat_fname).readlines()] 30 | captures = {} 31 | for l in lines[1:]: 32 | l = re.sub(r"[\t ]", " ", l) 33 | p = "" 34 | if pattern: 35 | p = pattern.pop(0) 36 | # print l, "|", p 37 | m = re.match(p, l) 38 | c = m.groupdict() 39 | for k, v in c.iteritems(): 40 | if k in captures and captures[k] != v: 41 | print "FAIL:", asm_fname 42 | sys.exit(1) 43 | captures.update(c) 44 | 45 | # Differently named capture regs should represent different underlying regs 46 | if len(set(captures.values())) != len(captures): 47 | print "FAIL:", asm_fname 48 | sys.exit(1) 49 | 50 | print "OK:", asm_fname 51 | -------------------------------------------------------------------------------- /tests/circular.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #if 1 4 | #include 5 | #else 6 | void assert(int) {} 7 | #endif 8 | 9 | using namespace PTL; 10 | 11 | #define SIZE 10 12 | 13 | CircularBuffer buf; 14 | 15 | int main() 16 | { 17 | assert(buf.empty()); 18 | assert(buf.size() == 0); 19 | assert(buf.free_size() == SIZE); 20 | buf.push('a'); 21 | assert(!buf.empty()); 22 | assert(buf.size() == 1); 23 | buf.push((uint8_t*)"abcd", 4); 24 | assert(buf.size() == 5); 25 | assert(buf.pop() == 'a'); 26 | assert(buf.pop() == 'a'); 27 | assert(buf.pop() == 'b'); 28 | assert(buf.pop() == 'c'); 29 | assert(buf.pop() == 'd'); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /tests/nearptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | const int base1 = 0x20000000; 7 | char base2[256] = "foobar"; 8 | char *base3 = (char*)malloc(256); 9 | 10 | //template using Ptr = AbsNearPtr; 11 | template using Ptr = ArrayNearPtr; 12 | //template using Ptr = VarNearPtr; 13 | 14 | void func(Ptr p) 15 | { 16 | assert(sizeof(p) == 2); 17 | assert((char*)p == base2 + 3); 18 | assert(*p == 'b'); 19 | assert(p[1] == 'a'); 20 | } 21 | 22 | int main() 23 | { 24 | Ptr p = &base2[3]; 25 | assert(sizeof(p) == 2); 26 | // Pass into a function to avoid inlining optimizations 27 | func(p); 28 | } 29 | -------------------------------------------------------------------------------- /tests/sub_mod.cpp: -------------------------------------------------------------------------------- 1 | // Test modular (2^N) arithmetics 2 | #include 3 | #include 4 | 5 | using namespace PTL; 6 | 7 | class Dummy {}; 8 | 9 | uint32_t v0x10 = 0x10; 10 | uint32_t v0x20 = 0x20; 11 | uint32_t v0xffffff = 0xffffff; 12 | 13 | int main() 14 | { 15 | typedef ITimer test_timer; 16 | assert((test_timer::sub_mod(0x20, 0x10) == 0x10)); 17 | assert((test_timer::sub_mod(0x10, 0xffffff) == 0x11)); 18 | assert((test_timer::sub_mod(0x10, 0x20) == 0xfffff0)); 19 | 20 | assert((test_timer::sub_mod(v0x20, v0x10) == 0x10)); 21 | assert((test_timer::sub_mod(v0x10, v0xffffff) == 0x11)); 22 | assert((test_timer::sub_mod(v0x10, v0x20) == 0xfffff0)); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /tests/test_2_same_delays.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace PTL; 4 | 5 | extern "C" { 6 | 7 | void test_2_same_delays() 8 | { 9 | StaticDelay::delay(1000000U); 10 | StaticDelay::delay(1000000U); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /tests/test_2_same_delays.pattern: -------------------------------------------------------------------------------- 1 | movw (?Pr\d+), #\d+ 2 | movt (?Pr\d+), \d+ 3 | mov (?Pr\d+), (?Pr\d+) 4 | 1: 5 | subs (?Pr\d+), #1 6 | bne 1b 7 | 1: 8 | subs (?Pr\d+), #1 9 | bne 1b 10 | bx lr 11 | -------------------------------------------------------------------------------- /tests/test_delay_in_loop.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace PTL; 4 | 5 | extern "C" { 6 | 7 | void test_delay_in_loop() 8 | { 9 | while (1) { 10 | StaticDelay::delay(1000000U); 11 | } 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /tests/test_delay_in_loop.pattern: -------------------------------------------------------------------------------- 1 | movw (?Pr\d+), #\d+ 2 | movt (?Pr\d+), \d+ 3 | .L2: 4 | mov (?Pr\d+), (?Pr\d+) 5 | 1: 6 | subs (?Pr\d+), #1 7 | bne 1b 8 | b .L2 9 | -------------------------------------------------------------------------------- /tests/test_delay_single.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace PTL; 4 | 5 | extern "C" { 6 | 7 | void test_single_delay() 8 | { 9 | StaticDelay::delay(1000000U); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /tests/test_delay_single.pattern: -------------------------------------------------------------------------------- 1 | movw (?Pr\d+), #\d+ 2 | movt (?Pr\d+), \d+ 3 | 1: 4 | subs (?Pr\d+), #1 5 | bne 1b 6 | bx lr 7 | -------------------------------------------------------------------------------- /tests/test_static_delay.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | function test_case () { 5 | make -B TARGET=stm32 bin-stm32/$1.s 6 | python asm_pattern_match.py bin-stm32/$1.s $1.pattern 7 | echo "===" 8 | } 9 | 10 | test_case test_delay_single 11 | test_case test_2_same_delays 12 | test_case test_delay_in_loop 13 | --------------------------------------------------------------------------------