├── .gitignore ├── README.md ├── adc ├── adc.cpp └── adc.h ├── adxl345 ├── adxl345.cpp └── adxl345.h ├── at24c ├── at24c.cpp └── at24c.h ├── common └── bit_op.h ├── dma ├── dma.cpp └── dma.h ├── dot-matrix ├── dot-char.cpp ├── dot-char.h ├── dot-font.cpp ├── dot-font.h ├── dot-matrix.cpp ├── dot-matrix.h ├── dot-string.cpp └── dot-string.h ├── ds3231 ├── ds3231.cpp └── ds3231.h ├── gpio-array ├── gpio-array.cpp └── gpio-array.h ├── gpio ├── gpio.cpp └── gpio.h ├── hd44780 ├── hd44780-basic.cpp ├── hd44780-basic.h ├── hd44780-gpio.cpp └── hd44780-gpio.h ├── i2c-soft ├── i2c-soft.cpp └── i2c-soft.h ├── i2c ├── i2c.cpp └── i2c.h ├── isl1208-i2csoft ├── isl1208-i2csoft.cpp └── isl1208-i2csoft.h ├── nrf24l01p ├── nrf24l01p.cpp └── nrf24l01p.h ├── nvic ├── nvic.cpp └── nvic.h ├── spi-soft ├── spi-soft.cpp └── spi-soft.h ├── spi ├── spi.cpp └── spi.h ├── sst25-spisoft ├── sst25-spisoft.cpp └── sst25-spisoft.h ├── st7735r ├── st7735r.cpp └── st7735r.h ├── st7920 ├── st7920-dm.cpp ├── st7920-dm.h ├── st7920.cpp └── st7920.h ├── tim ├── tim.cpp └── tim.h ├── tubes ├── iv22.cpp └── iv22.h ├── usart-rs485 ├── usart-rs485.cpp └── usart-rs485.h └── usart ├── usart.cpp └── usart.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | 6 | # Compiled Dynamic libraries 7 | *.so 8 | *.dylib 9 | 10 | # Compiled Static libraries 11 | *.lai 12 | *.la 13 | *.a 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | stm32libs 2 | ========= 3 | 4 | C++ libs based on STM32F10x_StdPeriph_Lib 5 | -------------------------------------------------------------------------------- /adc/adc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * adc.cpp 3 | * 4 | * Created on: Jul 5, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "adc.h" 9 | 10 | Adc::Adc(ADC_TypeDef *adc, uint32_t rcc_apb2periph_adcx, uint32_t rcc_pclk2_div) : 11 | _adc(adc) { 12 | RCC_APB2PeriphClockCmd(rcc_apb2periph_adcx, ENABLE); 13 | RCC_ADCCLKConfig(rcc_pclk2_div); 14 | } 15 | 16 | Adc::~Adc() { 17 | } 18 | 19 | void Adc::init(uint32_t mode, 20 | FunctionalState scan_conv_mode, 21 | FunctionalState continuous_conv_mode, 22 | uint32_t external_trig_conv, 23 | uint32_t data_align, 24 | uint8_t nbr_of_channel) { 25 | 26 | ADC_InitTypeDef adc_init_type; 27 | 28 | adc_init_type.ADC_Mode = mode; 29 | adc_init_type.ADC_ScanConvMode = scan_conv_mode; 30 | adc_init_type.ADC_ContinuousConvMode = continuous_conv_mode; 31 | adc_init_type.ADC_ExternalTrigConv = external_trig_conv; 32 | adc_init_type.ADC_DataAlign = data_align; 33 | adc_init_type.ADC_NbrOfChannel = nbr_of_channel; 34 | 35 | ADC_Init(_adc, &adc_init_type); 36 | ADC_Cmd(_adc, ENABLE); 37 | } 38 | 39 | void Adc::configChannel(uint8_t channel, uint8_t rank, uint8_t sample_time) { 40 | ADC_RegularChannelConfig(_adc, channel, rank, sample_time); 41 | } 42 | 43 | void Adc::calibrate() { 44 | while (ADC_GetResetCalibrationStatus(_adc)) 45 | ; 46 | ADC_StartCalibration(_adc); 47 | while (ADC_GetCalibrationStatus(_adc)) 48 | ; 49 | } 50 | 51 | void Adc::startSoftwareConvert(FunctionalState state) { 52 | ADC_SoftwareStartConvCmd(ADC1, state); 53 | } 54 | 55 | uint16_t Adc::getValue() { 56 | while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET) 57 | ; 58 | return ADC_GetConversionValue(ADC1); 59 | } 60 | 61 | void Adc::setDma(FunctionalState enable) { 62 | ADC_DMACmd(_adc, enable); 63 | } 64 | 65 | uint32_t Adc::getAddress() { 66 | return (uint32_t) (&(_adc->DR)); 67 | } 68 | -------------------------------------------------------------------------------- /adc/adc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * adc.h 3 | * 4 | * Created on: Jul 5, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef ADC_H_ 9 | #define ADC_H_ 10 | 11 | #include "stm32f10x_adc.h" 12 | 13 | class Adc { 14 | public: 15 | Adc(ADC_TypeDef *adc, uint32_t rcc_apb2periph_adcx, uint32_t rcc_pclk2_div = RCC_PCLK2_Div2); 16 | ~Adc(); 17 | 18 | void init(uint32_t mode = ADC_Mode_Independent, 19 | FunctionalState scan_conv_mode = DISABLE, 20 | FunctionalState continuous_conv_mode = DISABLE, 21 | uint32_t external_trig_conv = ADC_ExternalTrigConv_T1_CC1, 22 | uint32_t data_align = ADC_DataAlign_Right, 23 | uint8_t nbr_of_channel = 1); 24 | 25 | void configChannel(uint8_t channel, uint8_t rank, uint8_t sample_time = ADC_SampleTime_239Cycles5); 26 | void calibrate(); 27 | void startSoftwareConvert(FunctionalState state = ENABLE); 28 | uint16_t getValue(); 29 | void setDma(FunctionalState enable = ENABLE); 30 | uint32_t getAddress(); 31 | 32 | private: 33 | ADC_TypeDef* const _adc; 34 | }; 35 | 36 | #endif /* ADC_H_ */ 37 | -------------------------------------------------------------------------------- /adxl345/adxl345.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * adxl345.cpp 3 | * 4 | * Created on: Aug 23, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "adxl345/adxl345.h" 9 | 10 | Adxl345::Adxl345(I2c & i2c, uint8_t address) : 11 | _i2c(i2c), _address(address) { 12 | _measure_count = 0; 13 | _unit_g = 0.; 14 | _rawdata_sums[0] = _rawdata_sums[1] = _rawdata_sums[2] = 0; 15 | _bias[0] = _bias[1] = _bias[2] = 0; 16 | } 17 | 18 | Adxl345::~Adxl345() { 19 | 20 | } 21 | 22 | void Adxl345::init() { 23 | _i2c.setReg(_address, 0x2d, 0x08); 24 | _i2c.setReg(_address, 0x2c, 0x0b); 25 | _i2c.setReg(_address, 0x31, 0x09); 26 | delay(10); 27 | } 28 | 29 | void Adxl345::setOffsets(uint8_t index, uint8_t offset) { 30 | _i2c.setReg(_address, 0x1e + index, offset); 31 | } 32 | 33 | void Adxl345::measure(uint8_t index) { 34 | uint8_t data[2]; 35 | _i2c.getReg(_address, 0x32 + index + index, data, 2); 36 | _accelerations[index] = (int16_t) make16(data[1], data[0]); 37 | } 38 | 39 | void Adxl345::measureRawSums() { 40 | static uint8_t data[6]; 41 | _i2c.getReg(_address, 0x32, data, 6); 42 | for (uint8_t i = 0; i < 3; i++) 43 | _rawdata_sums[i] += (int16_t) make16(data[i + i + 1], data[i + i]); 44 | 45 | _measure_count++; 46 | } 47 | 48 | void Adxl345::calc() { 49 | for (uint8_t i = 0; i < 3; i++) { 50 | _accelerations[i] = (_rawdata_sums[i] / (float) _measure_count) 51 | * _scales[i] + _bias[i]; 52 | _rawdata_sums[i] = 0; 53 | } 54 | _measure_count = 0; 55 | } 56 | 57 | const int16_t * Adxl345::getAcceleratins() { 58 | return _accelerations; 59 | } 60 | -------------------------------------------------------------------------------- /adxl345/adxl345.h: -------------------------------------------------------------------------------- 1 | /* 2 | * adxl345.h 3 | * 4 | * Created on: Aug 23, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef ADXL345_H_ 9 | #define ADXL345_H_ 10 | 11 | #include "i2c/i2c.h" 12 | #include "stm32-template.h" 13 | #include "common/bit_op.h" 14 | 15 | #include 16 | 17 | class Adxl345 { 18 | public: 19 | Adxl345(I2c & i2c, uint8_t address = 0x53); 20 | virtual ~Adxl345(); 21 | void init(); 22 | void setOffsets(uint8_t index, uint8_t offset); 23 | void measure(uint8_t index); 24 | void measureRawSums(); 25 | void calc(); 26 | const int16_t *getAcceleratins(); 27 | 28 | private: 29 | I2c & _i2c; 30 | 31 | const uint8_t _address; 32 | int16_t _accelerations[3]; 33 | static float _scales[3]; 34 | uint16_t _measure_count; 35 | int16_t _bias[3]; 36 | int32_t _rawdata_sums[3]; 37 | 38 | float _unit_g; 39 | }; 40 | 41 | #endif /* ADXL345_H_ */ 42 | -------------------------------------------------------------------------------- /at24c/at24c.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * at24c.cpp 3 | * 4 | * Created on: Aug 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "at24c/at24c.h" 9 | 10 | At24c::At24c(I2c & i2c, uint8_t pagesize, uint8_t slave_address) : 11 | _i2c(i2c), _pagesize(pagesize), _slave_address(slave_address) { 12 | 13 | } 14 | 15 | At24c::~At24c() { 16 | 17 | } 18 | 19 | u8 At24c::write_raw(u16 reg_address, const void * buff, 20 | u16 length) { 21 | assert_param(length <= _pagesize); 22 | u8 t = _i2c.setReg(_slave_address | (reg_address >> 8), reg_address, (u8 *)buff, 23 | length); 24 | delay(6); 25 | return t; 26 | } 27 | 28 | u8 At24c::read(u16 reg_address, void * buff, u16 length) { 29 | return _i2c.getReg(_slave_address | (reg_address >> 8), reg_address, (u8 *)buff, 30 | length); 31 | } 32 | 33 | u8 At24c::write(u16 reg_address, const void * buff, 34 | u16 length) { 35 | uint8_t t = 0; 36 | for (u16 i = reg_address; i < reg_address + length;) { 37 | u16 end = (i + 8) / 8 * 8; 38 | if (end > reg_address + length) { 39 | end = reg_address + length; 40 | } 41 | t = this->write_raw(i, (u8*)buff + i - reg_address, end - i); 42 | i = end; 43 | } 44 | return t; 45 | } 46 | 47 | 48 | //uint8_t At24c::write(uint16_t reg_address, const void * buff, 49 | // uint16_t length) { 50 | // assert_param(length <= _pagesize); 51 | // return _i2c.setReg(_slave_address | (reg_address >> 8), reg_address, (uint8_t *)buff, 52 | // length); 53 | //} 54 | // 55 | //uint8_t At24c::write(uint16_t reg_address, uint8_t data) { 56 | // return this->write(reg_address, &data, 1); 57 | //} 58 | // 59 | //uint8_t At24c::read(uint16_t reg_address, void * buff, uint16_t length) { 60 | // assert_param(length <= _pagesize); 61 | // return _i2c.getReg(_slave_address | (reg_address >> 8), reg_address, (uint8_t *)buff, 62 | // length); 63 | //} 64 | -------------------------------------------------------------------------------- /at24c/at24c.h: -------------------------------------------------------------------------------- 1 | /* 2 | * at24c.h 3 | * 4 | * Created on: Aug 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef AT24C_H_ 9 | #define AT24C_H_ 10 | 11 | #include "i2c/i2c.h" 12 | #include "stm32-template.h" 13 | 14 | class At24c { 15 | public: 16 | At24c(I2c & i2c, u8 pagesize, u8 slave_address = 0x50); 17 | virtual ~At24c(); 18 | 19 | u8 write_raw(u16 reg_address, const void * buff, u16 length); 20 | u8 write(u16 reg_address, const void * buff, u16 length); 21 | u8 read(u16 reg_address, void * buff, u16 length = 1); 22 | 23 | private: 24 | I2c & _i2c; 25 | const u8 _pagesize; 26 | const u8 _slave_address; 27 | }; 28 | 29 | #endif /* AT24C_H_ */ 30 | -------------------------------------------------------------------------------- /common/bit_op.h: -------------------------------------------------------------------------------- 1 | /* 2 | * bit_op.h 3 | * 4 | * Created on: Jul 19, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef BIT_OP_H_ 9 | #define BIT_OP_H_ 10 | 11 | #define _BV(bit) (1 << (bit)) 12 | 13 | #define lowByte(w) ((uint8_t) ((w) & 0xff)) 14 | #define highByte(w) ((uint8_t) ((w) >> 8)) 15 | #define make16(h, l) (((h) << 8) | (l)) 16 | 17 | #define rawmax(a, b) ((a)>(b)?(a):(b)) 18 | #define rawmin(a, b) ((a)<(b)?(a):(b)) 19 | 20 | #define bitRead(value, bit) (((value) >> (bit)) & 0x01) 21 | #define bitSet(value, bit) ((value) |= (1UL << (bit))) 22 | #define bitClear(value, bit) ((value) &= ~(1UL << (bit))) 23 | #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) 24 | 25 | #define readLowBitInByte(value, bit) ((value) & _BV(bit)) 26 | #define setLowBitInByte(value, bit) ((value) |= _BV(bit)) 27 | #define clearLowbitInByte(value, bit) ((value) &= ~_BV(bit)) 28 | #define writeLowBitInByte(value, bit, bitvalue) (bitvalue ? setLowBitInByte(value, bit) : clearLowbitInByte(value, bit)) 29 | 30 | #define readHighBitInByte(value, bit) ((value) & (0x80 >> (bit))) 31 | #define setHighBitInByte(value, bit) ((value) |= (0x80 >> (bit))) 32 | #define clearHighBitInByte(value, bit) ((value) &= ~(0x80 >> (bit))) 33 | #define writeHighBitInByte(value, bit, bitvalue) (bitvalue ? setHighBitInByte(value, bit) : clearHighBitInByte(value, bit)) 34 | 35 | #endif /* BIT_OP_H_ */ 36 | -------------------------------------------------------------------------------- /dma/dma.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * dma.cpp 3 | * 4 | * Created on: Jun 6, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "dma.h" 9 | 10 | Dma::Dma(DMA_Channel_TypeDef * dma, uint32_t rcc_apb_periph_dmax, uint32_t flag) : 11 | _dma(dma), _flag(flag) { 12 | RCC_AHBPeriphClockCmd(rcc_apb_periph_dmax, ENABLE); 13 | } 14 | 15 | Dma::~Dma() { 16 | 17 | } 18 | 19 | void Dma::init(uint32_t peripheral_base_addr, 20 | uint32_t memory_base_addr, 21 | uint32_t direction, 22 | uint32_t buffer_size, 23 | uint32_t peripheral_increment, 24 | uint32_t memory_increment, 25 | uint32_t peripheral_data_size, 26 | uint32_t memory_data_size, 27 | uint32_t mode, 28 | uint32_t priority, 29 | uint32_t m2m) { 30 | 31 | this->setPeriphToConf(peripheral_base_addr, 32 | peripheral_data_size, 33 | peripheral_increment); 34 | 35 | this->setMemoryToConf(memory_base_addr, memory_data_size, memory_increment); 36 | 37 | this->setTransferToConf(buffer_size, direction); 38 | 39 | this->setFunctionToConf(mode, priority, m2m); 40 | 41 | this->initWithConf(); 42 | } 43 | 44 | void Dma::initWithConf(void) { 45 | DMA_DeInit(_dma); 46 | DMA_Init(_dma, &_dma_init_type); 47 | } 48 | 49 | void Dma::run() { 50 | DMA_Cmd(_dma, ENABLE); 51 | while (!DMA_GetFlagStatus(_flag)) 52 | ; 53 | DMA_Cmd(_dma, DISABLE); 54 | } 55 | 56 | void Dma::setEnable(FunctionalState enable) { 57 | DMA_Cmd(_dma, enable); 58 | } 59 | 60 | void Dma::setPeriphToConf(uint32_t base_addr, 61 | uint32_t data_size, 62 | uint32_t increment) { 63 | _dma_init_type.DMA_PeripheralBaseAddr = base_addr; 64 | _dma_init_type.DMA_PeripheralDataSize = data_size; 65 | _dma_init_type.DMA_PeripheralInc = increment; 66 | } 67 | 68 | void Dma::setMemoryToConf(uint32_t base_addr, 69 | uint32_t data_size, 70 | uint32_t increment) { 71 | _dma_init_type.DMA_MemoryBaseAddr = base_addr; 72 | _dma_init_type.DMA_MemoryDataSize = data_size; 73 | _dma_init_type.DMA_MemoryInc = increment; 74 | } 75 | 76 | void Dma::setFunctionToConf(uint32_t mode, uint32_t priority, uint32_t m2m) { 77 | _dma_init_type.DMA_Mode = mode; 78 | _dma_init_type.DMA_Priority = priority; 79 | _dma_init_type.DMA_M2M = m2m; 80 | } 81 | 82 | void Dma::setTransferToConf(uint32_t length, uint32_t direction) { 83 | _dma_init_type.DMA_BufferSize = length; 84 | _dma_init_type.DMA_DIR = direction; 85 | } 86 | -------------------------------------------------------------------------------- /dma/dma.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dma.h 3 | * 4 | * Created on: Jun 6, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef DMA_H_ 9 | #define DMA_H_ 10 | 11 | #include "stm32f10x_dma.h" 12 | 13 | class Dma { 14 | public: 15 | Dma(DMA_Channel_TypeDef * dma, uint32_t rcc_apb_periph_dmax, uint32_t flag); 16 | ~Dma(); 17 | 18 | void init(uint32_t peripheral_base_addr, 19 | uint32_t memory_base_addr, 20 | uint32_t direction = DMA_DIR_PeripheralSRC, 21 | uint32_t buffer_size = 0, 22 | uint32_t peripheral_increment = DMA_PeripheralInc_Disable, 23 | uint32_t memory_increment = DMA_MemoryInc_Disable, 24 | uint32_t peripheral_data_size = DMA_PeripheralDataSize_Byte, 25 | uint32_t memory_data_size = DMA_MemoryDataSize_Byte, 26 | uint32_t mode = DMA_Mode_Normal, 27 | uint32_t priority = DMA_Priority_Low, 28 | uint32_t m2m = DMA_M2M_Disable); 29 | 30 | void setPeriphToConf(uint32_t base_addr, 31 | uint32_t data_size = DMA_PeripheralDataSize_Byte, 32 | uint32_t increment = DMA_PeripheralInc_Disable); 33 | 34 | void setMemoryToConf(uint32_t base_addr, 35 | uint32_t data_size = DMA_MemoryDataSize_Byte, 36 | uint32_t increment = DMA_MemoryInc_Enable); 37 | 38 | void setTransferToConf(uint32_t length, 39 | uint32_t direction = DMA_DIR_PeripheralDST); 40 | 41 | void setFunctionToConf(uint32_t mode = DMA_Mode_Normal, 42 | uint32_t priority = DMA_Priority_Low, 43 | uint32_t m2m = DMA_M2M_Disable); 44 | 45 | void initWithConf(void); 46 | 47 | void run(); 48 | void setEnable(FunctionalState enable = ENABLE); 49 | 50 | private: 51 | DMA_Channel_TypeDef * const _dma; 52 | uint32_t _flag; 53 | DMA_InitTypeDef _dma_init_type; 54 | }; 55 | 56 | #endif /* DMA_H_ */ 57 | -------------------------------------------------------------------------------- /dot-matrix/dot-char.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | DotChar.cpp 3 | DotChar Class for printing characters on DotMatrix 4 | Created on: 2012-01-22 5 | Updated on: 2012-05-14 6 | 7 | library for Arduino for Dot Matrix Display, support driver by 74HC595 and 74HC138, ST7920, HD47780 8 | Author: Weihong Guan 9 | Blog: http://aguegu.net 10 | E-mail: weihong.guan@gmail.com 11 | Code license: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) 12 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 13 | 14 | source host: https://github.com/aguegu/dot-matrix 15 | */ 16 | 17 | #include "dot-char.h" 18 | 19 | DotChar::DotChar(DotMatrix & dm, const DotFont & df) : 20 | _dm(dm), _df(df) { 21 | _col = _row = _index = _indent = 0; 22 | _vertical = true; 23 | } 24 | 25 | DotChar::~DotChar() { 26 | 27 | } 28 | 29 | void DotChar::setChar(const char chr) { 30 | if (chr < _df.indent || chr >= _df.indent + _df.length) 31 | _index = _df.length; 32 | else 33 | _index = chr - _df.indent; 34 | 35 | _indent = _index * _df.width; 36 | } 37 | 38 | void DotChar::setVertical(const bool vertical) { 39 | _vertical = vertical; 40 | } 41 | 42 | void DotChar::postAt(const uint8_t col, const uint8_t row) { 43 | _col = col; 44 | _row = row; 45 | this->print(); 46 | } 47 | 48 | void DotChar::clear(const bool on) const { 49 | if (_vertical) 50 | _dm.setRect(_col, _row, _col + _df.width, _row + _df.height, on); 51 | else 52 | _dm.setRect(_row, this->getMaxRow() - _col, _row + _df.height, 53 | this->getMaxCol() - _col - _df.width, on); 54 | } 55 | 56 | uint8_t DotChar::calcFontRealWidth() const { 57 | if (_index == _df.length) 58 | return _df.width; 59 | 60 | uint8_t i = _df.width - 1; 61 | 62 | while (*(_df.pattern + _indent + i) == 0 && i--) 63 | ; 64 | 65 | return i + 1; 66 | } 67 | 68 | uint8_t DotChar::getWidth() const { 69 | return _df.width; 70 | } 71 | 72 | uint8_t DotChar::getHeight() const { 73 | return _df.height; 74 | } 75 | 76 | bool DotChar::getVertical() const { 77 | return _vertical; 78 | } 79 | 80 | uint8_t DotChar::getMaxCol() const { 81 | return _dm.countCol() - 1; 82 | } 83 | 84 | uint8_t DotChar::getMaxRow() const { 85 | return _dm.countRow() - 1; 86 | } 87 | 88 | void DotChar::print() const { 89 | if (_index == _df.length) 90 | this->clear(false); 91 | else 92 | _vertical ? printV() : printH(); 93 | } 94 | 95 | void DotChar::printH() const { 96 | for (uint8_t c = 0; c < _df.width; c++) { 97 | for (uint8_t r = 0; r < _df.height; r++) { 98 | if (bool b = bitRead(*(_df.pattern + _indent + c), r)) 99 | _dm.setDot(_row + r, _dm.countRow() - _col - 1 - c, b); 100 | } 101 | } 102 | } 103 | 104 | void DotChar::printV() const { 105 | for (uint8_t c = 0; c < _df.width && c + _col < _dm.countCol(); c++) { 106 | for (uint8_t r = 0; r < _df.height; r++) { 107 | if (bool b = bitRead(*(_df.pattern + _indent + c), r)) 108 | _dm.setDot(_col + c, _row + r, b); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /dot-matrix/dot-char.h: -------------------------------------------------------------------------------- 1 | /* 2 | DotChar.h 3 | DotChar Class for printing characters on DotMatrix 4 | Created on: 2012-01-22 5 | Updated on: 2012-05-14 6 | 7 | library for Arduino for Dot Matrix Display, support driver by 74HC595 and 74HC138, ST7920, HD47780 8 | Author: Weihong Guan 9 | Blog: http://aguegu.net 10 | E-mail: weihong.guan@gmail.com 11 | Code license: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) 12 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 13 | 14 | source host: https://github.com/aguegu/dot-matrix 15 | */ 16 | 17 | #ifndef DOT_CHAR_H_ 18 | #define DOT_CHAR_H_ 19 | 20 | #include "dot-matrix.h" 21 | #include "dot-font.h" 22 | 23 | class DotChar { 24 | public: 25 | DotChar(DotMatrix & dm, const DotFont & df); 26 | virtual ~DotChar(); 27 | 28 | void setChar(const char chr); 29 | void setVertical(const bool vertical = true); 30 | 31 | void postAt(const uint8_t col, const uint8_t row); 32 | 33 | void clear(const bool on = false) const; 34 | 35 | uint8_t calcFontRealWidth() const; 36 | uint8_t getWidth() const ; 37 | uint8_t getHeight() const ; 38 | 39 | bool getVertical() const ; 40 | 41 | uint8_t getMaxCol() const ; 42 | 43 | uint8_t getMaxRow() const ; 44 | 45 | private: 46 | DotMatrix & _dm; 47 | const DotFont & _df; 48 | 49 | uint8_t _col; 50 | uint8_t _row; 51 | uint8_t _index; 52 | uint16_t _indent; 53 | bool _vertical; 54 | 55 | void print() const ; 56 | void printH() const ; 57 | void printV() const; 58 | }; 59 | 60 | #endif /* DOT_CHAR_H_ */ 61 | -------------------------------------------------------------------------------- /dot-matrix/dot-font.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * dot-font.cpp 3 | * 4 | * Created on: Aug 16, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "dot-matrix/dot-font.h" 9 | 10 | static const uint8_t vfont_7x3_pattern[] = { 11 | 0x00, 0x00, 0x00, // Space 12 | 0x5f, 0x00, 0x00, // ! 13 | 0x03, 0x00, 0x03, // " 14 | 0x28, 0x7c, 0x28, // # 15 | 0x2e, 0x6b, 0x3a, // $ 16 | 0x64, 0x10, 0x4c, // % 17 | 0x5f, 0x75, 0x57, // & 18 | 0x03, 0x00, 0x00, // ' 19 | 20 | 0x1c, 0x22, 0x41, // ( 21 | 0x41, 0x22, 0x1c, // ) 22 | 0x0a, 0x04, 0x0a, // * 23 | 0x04, 0x0e, 0x04, // + 24 | 0x60, 0x00, 0x00, // , 25 | 0x04, 0x04, 0x04, // - 26 | 0x40, 0x00, 0x00, // . 27 | 0x60, 0x18, 0x06, // / 28 | 29 | 0x7f, 0x41, 0x7f, // 0 30 | 0x42, 0x7f, 0x40, // 1 31 | 0x7d, 0x45, 0x47, // 2 32 | 0x45, 0x45, 0x7f, // 3 33 | 0x3f, 0x20, 0x7f, // 4 34 | 0x47, 0x45, 0x7d, // 5 35 | 0x7f, 0x45, 0x7d, // 6 36 | 0x01, 0x01, 0x7f, // 7 37 | 38 | 0x7f, 0x45, 0x7f, // 8 39 | 0x5f, 0x51, 0x7f, // 9 40 | 0x50, 0x00, 0x00, // : 41 | 0x68, 0x00, 0x00, // ; 42 | 0x08, 0x14, 0x22, // < 43 | 0x14, 0x14, 0x14, // = 44 | 0x22, 0x14, 0x08, // > 45 | 0x59, 0x0f, 0x00, // ? 46 | 47 | 0x74, 0x44, 0x7c, // @ 48 | 0x7f, 0x21, 0x7f, // A 49 | 0x7f, 0x47, 0x7c, // B 50 | 0x7f, 0x41, 0x63, // C 51 | 0x7d, 0x41, 0x7f, // D 52 | 0x7f, 0x45, 0x45, // E 53 | 0x7f, 0x05, 0x05, // F 54 | 0x7f, 0x41, 0x7d, // G 55 | 0x7f, 0x04, 0x7f, // H 56 | 0x41, 0x7f, 0x41, // I 57 | 0x40, 0x41, 0x7f, // J 58 | 0x7f, 0x0a, 0x7b, // K 59 | 0x7f, 0x40, 0x40, // L 60 | 0x7f, 0x0e, 0x7f, // M 61 | 0x7f, 0x01, 0x7f, // N 62 | 0x7f, 0x41, 0x7f, // O 63 | 64 | 0x7f, 0x21, 0x3f, // P 65 | 0x3f, 0x21, 0x5f, // Q 66 | 0x7f, 0x31, 0x5f, // R 67 | 0x47, 0x45, 0x7d, // S 68 | 0x01, 0x7f, 0x01, // T 69 | 0x7F, 0x40, 0x7f, // U 70 | 0x7f, 0x20, 0x1f, // V 71 | 0x7f, 0x38, 0x7f, // W 72 | 0x7b, 0x0e, 0x7b, // X 73 | 0x07, 0x7c, 0x07, // Y 74 | 0x79, 0x45, 0x43, // Z 75 | 0x7f, 0x41, 0x00, // [ 76 | 0x06, 0x18, 0x60, // "\" 77 | 0x41, 0x7f, 0x00, // ] 78 | 0x02, 0x01, 0x02, // ^ 79 | 0x40, 0x40, 0x40, // _ 80 | 81 | 0x01, 0x02, 0x00, // ` 82 | 0x74, 0x54, 0x7c, // a 83 | 0x7f, 0x44, 0x7c, // b 84 | 0x7c, 0x44, 0x44, // c 85 | 0x7c, 0x44, 0x7f, // d 86 | 0x7c, 0x54, 0x5c, // e 87 | 0x04, 0x7f, 0x05, // f 88 | 0x5c, 0x54, 0x7c, // g 89 | 0x7f, 0x04, 0x7c, // h 90 | 0x7d, 0x00, 0x00, // i 91 | 0x40, 0x7d, 0x00, // j 92 | 0x7f, 0x10, 0x6c, // k 93 | 0x7f, 0x40, 0x00, // l 94 | 95 | 0x7c, 0x18, 0x7c, // m 96 | 0x7c, 0x04, 0x7c, // n 97 | 0x7c, 0x44, 0x7c, // o 98 | 0x7c, 0x24, 0x3c, // p 99 | 0x3c, 0x24, 0x7c, // q 100 | 0x7c, 0x04, 0x04, // r 101 | 0x5c, 0x54, 0x74, // s 102 | 0x04, 0x7e, 0x44, // t 103 | 0x7c, 0x40, 0x7c, // u 104 | 0x7c, 0x20, 0x1c, // v 105 | 0x7c, 0x30, 0x7c, // w 106 | 0x6c, 0x10, 0x6c, // x 107 | 0x5c, 0x50, 0x7c, // y 108 | 0x64, 0x54, 0x4c, // z 109 | 110 | 0x08, 0x7f, 0x41, // { 111 | 0x00, 0x7f, 0x00, // | 112 | 0x41, 0x7f, 0x08, // } 113 | 0x01, 0x03, 0x02, // ~ 114 | 0x7f, 0x7f, 0x7f, // Full Filled 115 | }; 116 | 117 | const DotFont vfont_7x3 = { 118 | 3, 7, 0x20, 0x60, vfont_7x3_pattern 119 | }; 120 | 121 | static const uint8_t vfont_5x3_pattern[] = { 122 | 0x1f, 0x11, 0x1f, //0 123 | 0x00, 0x1f, 0x00, //1 124 | 0x1d, 0x15, 0x17, //2 125 | 0x15, 0x15, 0x1f, //3 126 | 0x0f, 0x08, 0x1f, //4 127 | 0x17, 0x15, 0x1d, //5 128 | 0x1f, 0x15, 0x1d, //6 129 | 0x01, 0x01, 0x1f, //7 130 | 0x1f, 0x15, 0x1f, //8 131 | 0x17, 0x15, 0x1f, //9 132 | }; 133 | 134 | const DotFont vfont_5x3 = { 135 | 3, 5, 0x30, 10, vfont_5x3_pattern 136 | }; 137 | 138 | 139 | static const uint8_t vfont_6x3_pattern[] = { 140 | // 0-9 141 | 0x3f, 0x21, 0x3f, 142 | 0x22, 0x3f, 0x20, 143 | 0x3d, 0x25, 0x27, 144 | 0x25, 0x25, 0x3f, 145 | 146 | 0x1f, 0x10, 0x3f, 147 | 0x27, 0x25, 0x3d, 148 | 0x3f, 0x25, 0x3d, 149 | 0x01, 0x01, 0x3f, 150 | 151 | 0x3f, 0x25, 0x3f, 152 | 0x2f, 0x29, 0x3f, 153 | }; 154 | 155 | const DotFont vfont_6x3 = { 156 | 3, 6, 0x30, 10, vfont_6x3_pattern 157 | }; 158 | 159 | 160 | static const uint8_t vfont_8x3_pattern[] = { 161 | 0xff, 0x81, 0xff, //0 162 | 0x82, 0xff, 0x80, //1 163 | 0xf9, 0x89, 0x8f, //2 164 | 0x89, 0x89, 0xff, //3 165 | 0x3f, 0x20, 0xff, //4 166 | 0x8f, 0x89, 0xf9, //5 167 | 0xff, 0x89, 0xf9, //6 168 | 0x01, 0x01, 0xff, //7 169 | 0xff, 0x89, 0xff, //8 170 | 0x9f, 0x91, 0xff, //9 171 | }; 172 | 173 | const DotFont vfont_8x3 = { 174 | 3, 8, 0x30, 10, vfont_8x3_pattern 175 | }; 176 | 177 | static const uint8_t vfont_7x5_pattern[] = 178 | { 179 | 0x7f, 0x7f, 0x41, 0x7f, 0x7f, //0 180 | 0x00, 0x00, 0x7f, 0x7f, 0x00, //1 181 | 0x79, 0x79, 0x49, 0x4f, 0x4f, //2 182 | 0x49, 0x49, 0x49, 0x7f, 0x7f, //3 183 | 0x3f, 0x3f, 0x20, 0x7f, 0x7f, //4 184 | 0x4f, 0x4f, 0x49, 0x79, 0x79, //5 185 | 0x7f, 0x7f, 0x49, 0x79, 0x79, //6 186 | 0x01, 0x01, 0x01, 0x7f, 0x7f, //7 187 | 0x7f, 0x7f, 0x49, 0x7f, 0x7f, //8 188 | 0x4f, 0x4f, 0x49, 0x7f, 0x7f, //9 189 | }; 190 | 191 | const DotFont vfont_7x5= { 192 | 5, 7, 0x30, 10, vfont_7x5_pattern 193 | }; 194 | -------------------------------------------------------------------------------- /dot-matrix/dot-font.h: -------------------------------------------------------------------------------- 1 | /* 2 | * dot-font.h 3 | * 4 | * Created on: Aug 16, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef DOT_FONT_H_ 9 | #define DOT_FONT_H_ 10 | 11 | #include "stm32-template.h" 12 | 13 | struct DotFont { 14 | uint8_t width; 15 | uint8_t height; 16 | uint8_t indent; 17 | uint8_t length; 18 | const uint8_t *pattern; 19 | }; 20 | 21 | extern const DotFont vfont_7x3; 22 | extern const DotFont vfont_5x3; 23 | extern const DotFont vfont_6x3; 24 | extern const DotFont vfont_8x3; 25 | extern const DotFont vfont_7x5; 26 | 27 | 28 | #endif /* DOT_FONT_H_ */ 29 | -------------------------------------------------------------------------------- /dot-matrix/dot-matrix.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | DotMatrix.cpp 3 | DotMatrix Class for modeling on the Dot Matrix, providing methods like dot control, draw rectangle, line 4 | Created on: 2012-01-16 5 | Updated on: 2012-05-14 6 | 7 | library for Arduino for Dot Matrix Display, support driver by 74HC595 and 74HC138, ST7920, HD47780 8 | Author: Weihong Guan 9 | Blog: http://aguegu.net 10 | E-mail: weihong.guan@gmail.com 11 | Code license: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) 12 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 13 | 14 | source host: https://github.com/aguegu/dot-matrix 15 | */ 16 | 17 | #include "dot-matrix.h" 18 | 19 | DotMatrix::DotMatrix(uint8_t colCount, uint8_t rowCount) : 20 | _col_count(colCount), _row_count(rowCount), _bytes_per_row( 21 | (_col_count + 7) / 8), _bytes_length(_bytes_per_row * _row_count) 22 | { 23 | _cache = (uint8_t *) malloc(sizeof(uint8_t) * (_bytes_length + 1)); 24 | setMoveDirection(this->BYTE_IN_COL_POSI); 25 | 26 | this->clear(0x00); 27 | } 28 | 29 | DotMatrix::~DotMatrix() { 30 | free(_cache); 31 | } 32 | 33 | void DotMatrix::clear(uint8_t c) { 34 | memset(_cache, c, _bytes_length); 35 | } 36 | 37 | void DotMatrix::toogleDot(uint8_t col, uint8_t row) { 38 | this->setDot(col, row, !getDot(col, row)); 39 | } 40 | 41 | void DotMatrix::setDot(uint8_t col, uint8_t row, bool b) { 42 | uint16_t i = getIndex(col, row); 43 | 44 | writeHighBitInByte(*(_cache + i), col & 0x07, b); 45 | } 46 | 47 | void DotMatrix::setLine(uint8_t cA, 48 | uint8_t rA, 49 | uint8_t cB, 50 | uint8_t rB, 51 | bool on) { 52 | uint8_t cMin, cMax, rMin, rMax; 53 | 54 | cMin = rawmin(cA, cB); 55 | cMin = rawmax(cMin, 0); 56 | 57 | cMax = rawmax(cA, cB); 58 | cMax = rawmin(cMax, _col_count - 1); 59 | 60 | rMin = rawmin(rA, rB); 61 | rMin = rawmax(rMin, 0); 62 | 63 | rMax = rawmax(rA, rB); 64 | rMax = rawmin(rMax, _row_count - 1); 65 | 66 | if (cMax - cMin >= rMax - rMin) { 67 | for (uint8_t c = cMin; c <= cMax; c++) { 68 | int d = 32767; 69 | for (uint8_t r = rMin; r <= rMax; r++) { 70 | int k = abs((c - cA) * (rA - rB) - (r - rA) * (cA - cB)); 71 | if (d > k) 72 | d = k; 73 | } 74 | 75 | for (uint8_t r = rMin; r <= rMax; r++) { 76 | if (abs((c - cA) * (rA - rB) - (r - rA) * (cA - cB)) == d) 77 | this->setDot(c, r, on); 78 | } 79 | } 80 | } else { 81 | for (uint8_t r = rMin; r <= rMax; r++) { 82 | int d = 32767; 83 | for (uint8_t c = cMin; c <= cMax; c++) { 84 | int k = abs((c - cA) * (rA - rB) - (r - rA) * (cA - cB)); 85 | if (d > k) 86 | d = k; 87 | } 88 | 89 | for (uint8_t c = cMin; c <= cMax; c++) { 90 | if (abs((c - cA) * (rA - rB) - (r - rA) * (cA - cB)) 91 | == d) 92 | this->setDot(c, r, on); 93 | } 94 | } 95 | } 96 | } 97 | 98 | void DotMatrix::setRect(uint8_t cA, 99 | uint8_t rA, 100 | uint8_t cB, 101 | uint8_t rB, 102 | bool on) { 103 | uint8_t cMin, cMax, rMin, rMax; 104 | 105 | cMin = rawmin(cA, cB); 106 | cMin = rawmax(cMin, 0); 107 | 108 | cMax = rawmax(cA, cB); 109 | cMax = rawmin(cMax, this->_col_count - 1); 110 | 111 | rMin = rawmin(rA, rB); 112 | rMin = rawmax(rMin, 0); 113 | 114 | rMax = rawmax(rA, rB); 115 | rMax = rawmin(rMax, this->_row_count - 1); 116 | 117 | for (uint8_t c = cMin; c <= cMax; c++) 118 | for (uint8_t r = rMin; r <= rMax; r++) 119 | this->setDot(c, r, on); 120 | } 121 | 122 | uint16_t DotMatrix::getIndex(uint8_t col, uint8_t row) const { 123 | uint16_t index = row * _bytes_per_row + (col >> 3); 124 | return index < _bytes_length ? index : 0; 125 | } 126 | 127 | uint8_t DotMatrix::getDot(uint8_t col, uint8_t row) const { 128 | uint16_t i = getIndex(col, row); 129 | return readHighBitInByte(_cache[i], col & 0x07); 130 | } 131 | 132 | uint8_t * DotMatrix::output() const { 133 | return _cache; 134 | } 135 | 136 | uint8_t DotMatrix::countCol() const { 137 | return _col_count; 138 | } 139 | 140 | uint8_t DotMatrix::countRow() const { 141 | return _row_count; 142 | } 143 | 144 | uint8_t DotMatrix::countBytePerRow() const { 145 | return _bytes_per_row; 146 | } 147 | 148 | uint16_t DotMatrix::countBytes() const { 149 | return _bytes_length; 150 | } 151 | 152 | void DotMatrix::setByte(uint16_t index, uint8_t value) { 153 | if (index >= _bytes_length) 154 | return; 155 | _cache[index] = value; 156 | } 157 | 158 | void DotMatrix::putByte(uint8_t col, uint8_t row, uint8_t value) { 159 | uint16_t i = getIndex(col, row); 160 | uint8_t j = col & 0x07; 161 | _cache[i] |= value >> j; 162 | _cache[i + 1] |= value << (8 - j); 163 | } 164 | 165 | uint8_t DotMatrix::getByte(uint16_t index) { 166 | return index >= _bytes_length ? 0 : _cache[index]; 167 | } 168 | 169 | void DotMatrix::moveBitInColNega(bool recycle) { 170 | uint8_t *p = _cache; 171 | for (uint8_t r = _row_count; r--;) { 172 | bool b0 = readHighBitInByte(*p, 0); 173 | for (uint8_t i = _bytes_per_row - 1; i--;) 174 | { 175 | bool b = readHighBitInByte(*(p+1), 0); 176 | *p <<= 1; 177 | writeLowBitInByte(*p, 0, b); 178 | p++; 179 | } 180 | 181 | *p <<= 1; 182 | if (recycle) 183 | writeLowBitInByte(*p, 0, b0); 184 | 185 | p++; 186 | } 187 | } 188 | 189 | void DotMatrix::moveBitInColPosi(bool recycle) { 190 | uint8_t *p = _cache + _bytes_per_row - 1; 191 | for (uint8_t r = _row_count; r--;) { 192 | bool b0 = readLowBitInByte(*p, 0); 193 | for (uint8_t i = _bytes_per_row - 1; i--;) 194 | { 195 | bool b = readLowBitInByte(*(p-1), 0); 196 | *p >>= 1; 197 | writeHighBitInByte(*p, 0, b); 198 | p--; 199 | } 200 | 201 | *p >>= 1; 202 | if (recycle) 203 | writeHighBitInByte(*p, 0, b0); 204 | 205 | p += _bytes_per_row + _bytes_per_row - 1; 206 | } 207 | } 208 | 209 | void DotMatrix::moveBitInRowNega(bool recycle) { 210 | uint8_t pTemp[_bytes_per_row]; 211 | memcpy(pTemp, _cache, _bytes_per_row); 212 | 213 | memcpy(_cache, _cache + _bytes_per_row, _bytes_length - _bytes_per_row); 214 | 215 | recycle ? 216 | memcpy(_cache + _bytes_length - _bytes_per_row, pTemp, 217 | _bytes_per_row) : 218 | memset(_cache + _bytes_length - _bytes_per_row, 0x00, 219 | _bytes_per_row); 220 | } 221 | 222 | void DotMatrix::moveBitInRowPosi(bool recycle) { 223 | uint8_t pTemp[_bytes_per_row]; 224 | memcpy(pTemp, _cache + _bytes_length - _bytes_per_row, _bytes_per_row); 225 | 226 | memmove(_cache + _bytes_per_row, _cache, 227 | _bytes_length - _bytes_per_row); 228 | 229 | recycle ? 230 | memcpy(_cache, pTemp, _bytes_per_row) : 231 | memset(_cache, 0x00, _bytes_per_row); 232 | } 233 | 234 | void DotMatrix::moveByteInColNega(bool recycle) { 235 | uint8_t * p = _cache; 236 | for (uint8_t r = _row_count; r--;) { 237 | uint8_t temp = recycle ? *p : 0x00; 238 | memcpy(p, p + 1, _bytes_per_row - 1); 239 | 240 | p += _bytes_per_row; 241 | *(p - 1) = temp; 242 | } 243 | } 244 | 245 | void DotMatrix::moveByteInColPosi(bool recycle) { 246 | uint8_t *p = _cache; 247 | for (uint8_t r = _row_count; r--;) { 248 | uint8_t temp = recycle ? *(p + _bytes_per_row - 1) : 0x00; 249 | memmove(p + 1, p, _bytes_per_row - 1); 250 | *p = temp; 251 | p += _bytes_per_row; 252 | } 253 | } 254 | 255 | void DotMatrix::moveBitInByteNega(bool recycle) { 256 | uint8_t *p = _cache; 257 | for (uint16_t index = _bytes_length; index--; p++) { 258 | bool temp = *p & 0x80; 259 | *p <<= 1; 260 | if (recycle && temp) 261 | *p |= 0x01; 262 | } 263 | } 264 | 265 | void DotMatrix::moveBitInBytePosi(bool recycle) { 266 | uint8_t *p = _cache; 267 | for (uint16_t index = _bytes_length; index--; p++) { 268 | bool temp = *p & 0x01; 269 | *p >>= 1; 270 | if (recycle && temp) 271 | *p |= 0x80; 272 | } 273 | } 274 | 275 | void DotMatrix::setMoveDirection(Direction d) { 276 | switch (d) { 277 | case BIT_IN_COL_NEGA: 278 | _funMoveDirection = &DotMatrix::moveBitInColNega; 279 | break; 280 | case BIT_IN_COL_POSI: 281 | _funMoveDirection = &DotMatrix::moveBitInColPosi; 282 | break; 283 | case BIT_IN_ROW_NEGA: 284 | _funMoveDirection = &DotMatrix::moveBitInRowNega; 285 | break; 286 | case BIT_IN_ROW_POSI: 287 | _funMoveDirection = &DotMatrix::moveBitInRowPosi; 288 | break; 289 | case BYTE_IN_COL_NEGA: 290 | _funMoveDirection = &DotMatrix::moveByteInColNega; 291 | break; 292 | case BYTE_IN_COL_POSI: 293 | _funMoveDirection = &DotMatrix::moveByteInColPosi; 294 | break; 295 | case BIT_IN_BYTE_NEGA: 296 | _funMoveDirection = &DotMatrix::moveBitInByteNega; 297 | break; 298 | case BIT_IN_BYTE_POSI: 299 | _funMoveDirection = &DotMatrix::moveBitInBytePosi; 300 | break; 301 | } 302 | } 303 | 304 | void DotMatrix::move(bool recycle) { 305 | (this->*_funMoveDirection)(recycle); 306 | } 307 | 308 | uint8_t DotMatrix::orValue() { 309 | uint8_t c = 0x00; 310 | for (uint16_t i = _bytes_length; i--;) 311 | c |= _cache[i]; 312 | return c; 313 | } 314 | 315 | uint8_t DotMatrix::andValue() { 316 | uint8_t c = 0xff; 317 | for (uint16_t i = _bytes_length; i--;) 318 | c &= _cache[i]; 319 | return c; 320 | } 321 | -------------------------------------------------------------------------------- /dot-matrix/dot-matrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | DotMatrix.h 3 | DotMatrix Class for modeling on the Dot Matrix, providing methods like dot control, draw rectangle, line 4 | Created on: 2012-01-16 5 | 6 | library for Arduino for Dot Matrix Display, support driver by 74HC595 and 74HC138, ST7920, HD47780 7 | Author: Weihong Guan 8 | Blog: http://aguegu.net 9 | E-mail: weihong.guan@gmail.com 10 | Code license: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) 11 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 12 | 13 | source host: https://github.com/aguegu/dot-matrix 14 | */ 15 | 16 | #ifndef DOTMATRIX_H_ 17 | #define DOTMATRIX_H_ 18 | 19 | #include "stm32f10x.h" 20 | #include "common/bit_op.h" 21 | #include 22 | #include 23 | 24 | class DotMatrix { 25 | public: 26 | DotMatrix(uint8_t col_count, uint8_t row_count); 27 | virtual ~DotMatrix(); 28 | 29 | void clear(uint8_t c = 0x00); 30 | void setByte(uint16_t index, uint8_t value); 31 | void putByte(uint8_t col, uint8_t row, uint8_t value); 32 | uint8_t getByte(uint16_t index); 33 | 34 | void toogleDot(uint8_t col, uint8_t row); 35 | void setDot(uint8_t col, uint8_t row, bool b = true); 36 | uint8_t getDot(uint8_t col, uint8_t row) const; 37 | 38 | void setLine(uint8_t cA, uint8_t rA, uint8_t cB, uint8_t rB, bool on = true); 39 | void setRect(uint8_t cA, uint8_t rA, uint8_t cB, uint8_t rB, bool on = true); 40 | 41 | enum Direction { 42 | BIT_IN_COL_NEGA, 43 | BIT_IN_COL_POSI, 44 | BIT_IN_ROW_NEGA, 45 | BIT_IN_ROW_POSI, 46 | BYTE_IN_COL_NEGA, 47 | BYTE_IN_COL_POSI, 48 | BIT_IN_BYTE_NEGA, 49 | BIT_IN_BYTE_POSI 50 | }; 51 | 52 | void move(bool recycle = false); 53 | void setMoveDirection(Direction d); 54 | 55 | uint8_t * output() const; 56 | uint8_t countCol() const; 57 | uint8_t countRow() const; 58 | uint16_t countBytes() const; 59 | uint8_t countBytePerRow() const; 60 | 61 | uint8_t orValue(); 62 | uint8_t andValue(); 63 | 64 | protected: 65 | void moveBitInColNega(bool recycle); 66 | void moveBitInColPosi(bool recycle); 67 | void moveBitInRowNega(bool recycle); 68 | void moveBitInRowPosi(bool recycle); 69 | 70 | void moveByteInColNega(bool recycle); 71 | void moveByteInColPosi(bool recycle); 72 | 73 | void moveBitInByteNega(bool recycle); 74 | void moveBitInBytePosi(bool recycle); 75 | 76 | void (DotMatrix::*_funMoveDirection)(bool); 77 | 78 | private: 79 | const uint8_t _col_count; 80 | const uint8_t _row_count; 81 | const uint8_t _bytes_per_row; 82 | const uint16_t _bytes_length; 83 | 84 | uint8_t * _cache; 85 | 86 | uint16_t getIndex(uint8_t col, uint8_t row) const; 87 | }; 88 | 89 | #endif /* DOTMATRIX_H_ */ 90 | -------------------------------------------------------------------------------- /dot-matrix/dot-string.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | DotString.cpp 3 | DotString Class for string printing with DotFont 4 | Created on: 2012-01-25 5 | Updated on: 2012-05-14 6 | 7 | library for Arduino for Dot Matrix Display, support driver by 74HC595 and 74HC138, ST7920, HD47780 8 | Author: Weihong Guan 9 | Blog: http://aguegu.net 10 | E-mail: weihong.guan@gmail.com 11 | Code license: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) 12 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 13 | 14 | source host: https://github.com/aguegu/dot-matrix 15 | */ 16 | #include "dot-string.h" 17 | 18 | DotString::DotString(DotChar & dc, uint8_t length, bool smart_width) : 19 | _dc(dc) { 20 | _length = length; 21 | _smart_width = smart_width; 22 | _str = (char *) malloc(sizeof(char) * _length); 23 | } 24 | 25 | DotString::~DotString() { 26 | free(_str); 27 | } 28 | 29 | void DotString::printf(const char *__fmt, ...) { 30 | va_list ap; 31 | va_start(ap, __fmt); 32 | vsnprintf(_str, _length, __fmt, ap); 33 | va_end(ap); 34 | } 35 | 36 | void DotString::postAt(uint8_t col, uint8_t row) { 37 | uint8_t cursor; 38 | 39 | if (row > (_dc.getVertical() ? _dc.getMaxRow() : _dc.getMaxCol())) 40 | return; 41 | 42 | char *p = _str; 43 | 44 | cursor = col; 45 | while (*p) { 46 | _dc.setChar(*p++); 47 | _dc.postAt(cursor, row); 48 | cursor += 49 | _smart_width ? _dc.calcFontRealWidth() + 1 : _dc.getWidth() + 1; 50 | if (cursor > (_dc.getVertical() ? _dc.getMaxCol() : _dc.getMaxRow())) 51 | break; 52 | } 53 | } 54 | 55 | void DotString::setChar(uint8_t index, char chr) { 56 | assert_param(index < _length); 57 | *(_str + index) = chr; 58 | } 59 | 60 | char * DotString::getString() { 61 | return _str; 62 | } 63 | -------------------------------------------------------------------------------- /dot-matrix/dot-string.h: -------------------------------------------------------------------------------- 1 | /* 2 | DotString.h 3 | DotString Class for string printing with DotFont 4 | Created on: 2012-01-25 5 | Updated on: 2012-05-14 6 | 7 | library for Arduino for Dot Matrix Display, support driver by 74HC595 and 74HC138, ST7920, HD47780 8 | Author: Weihong Guan 9 | Blog: http://aguegu.net 10 | E-mail: weihong.guan@gmail.com 11 | Code license: Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0) 12 | http://creativecommons.org/licenses/by-nc-sa/3.0/ 13 | 14 | source host: https://github.com/aguegu/dot-matrix 15 | */ 16 | 17 | #ifndef DOTSTRING_H_ 18 | #define DOTSTRING_H_ 19 | 20 | #include "dot-matrix.h" 21 | #include "dot-char.h" 22 | 23 | #include 24 | 25 | class DotString { 26 | public: 27 | DotString(DotChar & dc, uint8_t length, bool smart_width = false); 28 | virtual ~DotString(); 29 | 30 | void postAt(uint8_t col, uint8_t row); 31 | void printf(const char *__fmt, ...); 32 | void setChar(uint8_t index, char chr); 33 | char * getString(); 34 | 35 | private: 36 | DotChar & _dc; 37 | char *_str; 38 | bool _smart_width; 39 | uint8_t _length; 40 | }; 41 | 42 | #endif /* DOTSTRING_H_ */ 43 | -------------------------------------------------------------------------------- /ds3231/ds3231.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ds3231.cpp 3 | * 4 | * Created on: Aug 15, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "ds3231/ds3231.h" 9 | 10 | Ds3231::Ds3231(I2c & i2c) : 11 | _i2c(i2c) { 12 | _datetime = (uint8_t *) malloc(sizeof(uint8_t) * 7); 13 | memset(_datetime, 0, 7); 14 | } 15 | 16 | Ds3231::~Ds3231() { 17 | free(_datetime); 18 | } 19 | 20 | void Ds3231::init() { 21 | _i2c.setReg(_address, 0x0e, 0x9c); 22 | _i2c.setReg(_address, 0x0f, 0x00); 23 | } 24 | 25 | uint8_t Ds3231::getHexData(uint8_t index) { 26 | return _datetime[index] & 0x7f; 27 | } 28 | 29 | uint8_t Ds3231::getDecData(uint8_t index) { 30 | return Ds3231::hex2dec(_datetime[index] & 0x7f); 31 | } 32 | 33 | uint8_t Ds3231::hex2dec(uint8_t hex) { 34 | return ((hex >> 4) * 10 + (hex & 0x0f)); 35 | } 36 | 37 | uint8_t Ds3231::dec2hex(uint8_t dec) { 38 | return (((dec / 10) << 4) + dec % 10); 39 | } 40 | 41 | void Ds3231::refresh(bool only_time) { 42 | uint8_t j = only_time ? 3 : 7; 43 | _i2c.getReg(_address, SECOND, _datetime, j); 44 | } 45 | 46 | void Ds3231::setTime(uint8_t hour, uint8_t minute, uint8_t second) { 47 | uint8_t tmp[3]; 48 | tmp[0] = dec2hex(second); 49 | tmp[1] = dec2hex(minute); 50 | tmp[2] = dec2hex(hour); 51 | _i2c.setReg(_address, SECOND, tmp, 3); 52 | } 53 | 54 | void Ds3231::setDate(uint8_t year, uint8_t month, 55 | uint8_t date, uint8_t weekday) { 56 | uint8_t tmp[4]; 57 | tmp[0] = weekday ? weekday : 7; 58 | tmp[1] = dec2hex(date); 59 | tmp[2] = dec2hex(month); 60 | tmp[3] = dec2hex(year); 61 | _i2c.setReg(_address, WEEKDAY, tmp, 4); 62 | } 63 | 64 | float Ds3231::getTemperature() { 65 | uint8_t temp[2]; 66 | _i2c.getReg(_address, 0x11, temp, 2); 67 | int t = make16(temp[0], temp[1]); 68 | return t / 256.; 69 | } 70 | 71 | -------------------------------------------------------------------------------- /ds3231/ds3231.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ds3231.h 3 | * 4 | * Created on: Aug 15, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef DS3231_H_ 9 | #define DS3231_H_ 10 | 11 | #include "i2c/i2c.h" 12 | #include "common/bit_op.h" 13 | #include 14 | #include 15 | 16 | #define SECOND 0 17 | #define MINUTE 1 18 | #define HOUR 2 19 | #define DATE 4 20 | #define MONTH 5 21 | #define WEEKDAY 3 22 | #define YEAR 6 23 | 24 | class Ds3231 { 25 | 26 | public: 27 | Ds3231(I2c & i2c); 28 | virtual ~Ds3231(); 29 | void init(); 30 | 31 | void setTime(uint8_t hour, uint8_t minute, uint8_t second); 32 | void setDate(uint8_t year, uint8_t month, uint8_t date, uint8_t weekday); 33 | 34 | uint8_t getHexData(uint8_t index); 35 | uint8_t getDecData(uint8_t index); 36 | 37 | static uint8_t hex2dec(uint8_t hex); 38 | static uint8_t dec2hex(uint8_t dec); 39 | 40 | void refresh(bool only_time = false); 41 | float getTemperature(); // update every 64 seconds 42 | 43 | private: 44 | static const uint8_t _address = 0x68; 45 | I2c & _i2c; 46 | uint8_t *_datetime; 47 | }; 48 | #endif /* DS3231_H_ */ 49 | -------------------------------------------------------------------------------- /gpio-array/gpio-array.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * gpio-array.cpp 3 | * 4 | * Created on: Sep 12, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "gpio-array.h" 9 | 10 | GpioArray::GpioArray(uint8_t length) : 11 | _length(length) { 12 | assert_param(_length <= 32); 13 | _gpios = (Gpio **) malloc(sizeof(Gpio *) * _length); 14 | for (uint8_t i = 0; i < _length; i++) 15 | _gpios[i] = NULL; 16 | } 17 | 18 | GpioArray::~GpioArray() { 19 | free(_gpios); 20 | } 21 | 22 | void GpioArray::setGpio(uint8_t index, Gpio & gpio) { 23 | assert_param(index < _length); 24 | _gpios[index] = &gpio; 25 | } 26 | 27 | void GpioArray::init(GPIOMode_TypeDef mode, GPIOSpeed_TypeDef speed) { 28 | for (uint8_t i = 0; i < _length; i++) { 29 | assert_param(_gpios[i] != NULL); 30 | _gpios[i]->init(mode, speed); 31 | } 32 | } 33 | 34 | void GpioArray::set(uint32_t val) { 35 | for (uint8_t i = 0; i < _length; i++) { 36 | assert_param(_gpios[i] != NULL); 37 | _gpios[i]->set(bitRead(val, i)); 38 | } 39 | } 40 | 41 | void GpioArray::toggle() { 42 | this->set(this->getOutput() ^ 0xffffffff); 43 | } 44 | 45 | uint32_t GpioArray::getOutput() { 46 | uint32_t val = 0; 47 | for (uint8_t i = 0; i < _length; i++) { 48 | assert_param(_gpios[i] != NULL); 49 | bitWrite(val, i, _gpios[i]->getOutput()); 50 | } 51 | return val; 52 | } 53 | 54 | uint32_t GpioArray::getInput() { 55 | uint32_t val = 0; 56 | for (uint8_t i = 0; i < _length; i++) { 57 | assert_param(_gpios[i] != NULL); 58 | bitWrite(val, i, _gpios[i]->getInput()); 59 | } 60 | return val; 61 | } 62 | -------------------------------------------------------------------------------- /gpio-array/gpio-array.h: -------------------------------------------------------------------------------- 1 | /* 2 | * gpio-array.h 3 | * 4 | * Created on: Sep 12, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef GPIO_ARRAY_H_ 9 | #define GPIO_ARRAY_H_ 10 | 11 | #include "gpio/gpio.h" 12 | #include "common/bit_op.h" 13 | #include 14 | 15 | class GpioArray { 16 | public: 17 | GpioArray(uint8_t length); 18 | ~GpioArray(); 19 | void setGpio(uint8_t index, Gpio & gpio); 20 | void init(GPIOMode_TypeDef mode = GPIO_Mode_IN_FLOATING, GPIOSpeed_TypeDef speed = GPIO_Speed_2MHz); 21 | void set(uint32_t val); 22 | void toggle(); 23 | uint32_t getOutput(); 24 | uint32_t getInput(); 25 | 26 | private: 27 | Gpio ** _gpios; 28 | const uint8_t _length; 29 | }; 30 | 31 | #endif /* GPIO_ARRAY_H_ */ 32 | -------------------------------------------------------------------------------- /gpio/gpio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Gpio.cpp 3 | * 4 | * Created on: May 24, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "gpio.h" 9 | 10 | Gpio::Gpio(uint16_t port, uint16_t pin) : 11 | _port((GPIO_TypeDef *) (GPIOA_BASE + (GPIOB_BASE - GPIOA_BASE) * (port))), 12 | _pin(1 << pin) { 13 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA << (port), ENABLE); 14 | } 15 | 16 | Gpio::~Gpio() { 17 | 18 | } 19 | 20 | void Gpio::init(GPIOMode_TypeDef mode, GPIOSpeed_TypeDef speed) { 21 | GPIO_InitTypeDef gpio_init_type; 22 | 23 | gpio_init_type.GPIO_Pin = _pin; 24 | gpio_init_type.GPIO_Mode = mode; 25 | gpio_init_type.GPIO_Speed = speed; 26 | 27 | GPIO_Init(_port, &gpio_init_type); 28 | } 29 | 30 | void Gpio::set(BitAction bit) { 31 | GPIO_WriteBit(_port, _pin, bit); 32 | } 33 | 34 | void Gpio::set(bool bit) { 35 | GPIO_WriteBit(_port, _pin, bit ? Bit_SET : Bit_RESET); 36 | } 37 | 38 | BitAction Gpio::getInput() { 39 | return (BitAction) GPIO_ReadInputDataBit(_port, _pin); 40 | } 41 | 42 | BitAction Gpio::getOutput() { 43 | return (BitAction) GPIO_ReadOutputDataBit(_port, _pin); 44 | } 45 | 46 | void Gpio::toggle() { 47 | GPIO_WriteBit(_port, _pin, 48 | (BitAction) (!GPIO_ReadOutputDataBit(_port, _pin))); 49 | } 50 | -------------------------------------------------------------------------------- /gpio/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Gpio.h 3 | * 4 | * Created on: May 24, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef GPIO_H_ 9 | #define GPIO_H_ 10 | 11 | #include "stm32f10x_gpio.h" 12 | 13 | class Gpio { 14 | public: 15 | /* PORTA: 0, PORTB: 1, PORTC: 2, ... */ 16 | Gpio(uint16_t port, uint16_t pin); 17 | ~Gpio(); 18 | void init(GPIOMode_TypeDef mode = GPIO_Mode_IN_FLOATING, GPIOSpeed_TypeDef speed = GPIO_Speed_2MHz); 19 | void set(BitAction bit); 20 | void set(bool bit); 21 | void toggle(); 22 | BitAction getInput(); 23 | BitAction getOutput(); 24 | 25 | private: 26 | GPIO_TypeDef * const _port; 27 | const uint16_t _pin; 28 | }; 29 | 30 | #endif /* GPIO_H_ */ 31 | -------------------------------------------------------------------------------- /hd44780/hd44780-basic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * hd44780-basic.cpp 3 | * 4 | * Created on: Aug 11, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "hd44780/hd44780-basic.h" 9 | 10 | const uint8_t Hd44780Basic::BAR_PATTERN[] = { 11 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 00000000 12 | 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 11000000 13 | 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x00, // 00011000 14 | 0x1f, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x00, 0x00, // 11011000 15 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, // 00000011 16 | 0x1f, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x1f, // 11000011 17 | 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x00, 0x1f, 0x1f, // 00011011 18 | 0x1f, 0x1f, 0x00, 0x1f, 0x1f, 0x00, 0x1f, 0x1f, // 11011011 19 | }; 20 | 21 | const uint8_t Hd44780Basic::ROW_INDEX_16[] = { 0x00, 0x40, 0x10, 0x50 }; 22 | 23 | const uint8_t Hd44780Basic::ROW_INDEX_20[] = { 0x00, 0x40, 0x14, 0x54 }; 24 | 25 | Hd44780Basic::Hd44780Basic(uint8_t row_count, uint8_t col_count) : 26 | _row_count(row_count), _col_count(col_count) { 27 | _cache_length = _row_count * _col_count + 1; 28 | _cache = (char *) malloc(sizeof(char) * _cache_length); 29 | this->setCache(); 30 | } 31 | 32 | Hd44780Basic::~Hd44780Basic() { 33 | free(_cache); 34 | } 35 | 36 | void Hd44780Basic::setCache(uint8_t value) { 37 | memset(_cache, value, _cache_length); 38 | } 39 | 40 | void Hd44780Basic::setCache(uint8_t index, uint8_t value) { 41 | assert_param(index < _cache_length); 42 | _cache[index] = value; 43 | } 44 | 45 | void Hd44780Basic::putString(uint8_t address, char *p, uint8_t length) const { 46 | this->setCursor(address); 47 | while (length--) 48 | transmit(true, *p++); 49 | } 50 | 51 | void Hd44780Basic::putChar(uint8_t address, char c) const { 52 | this->putString(address, &c, 1); 53 | } 54 | 55 | void Hd44780Basic::init() { 56 | this->initHardware(); 57 | 58 | this->setCGRam(BAR_PATTERN, 64); 59 | this->configureDisplay(true, false, false); 60 | } 61 | 62 | void Hd44780Basic::putCache() const { 63 | for (uint8_t r = 0; r < _row_count; r++) 64 | this->putString(*((_col_count <= 16 ? ROW_INDEX_16 : ROW_INDEX_20) + r), 65 | _cache + _col_count * r, _col_count); 66 | } 67 | 68 | void Hd44780Basic::printf(uint8_t index, const char *__fmt, ...) { 69 | assert_param(index < _cache_length); 70 | 71 | va_list ap; 72 | va_start(ap, __fmt); 73 | vsnprintf(_cache + index, _cache_length - index, __fmt, ap); 74 | va_end(ap); 75 | } 76 | 77 | void Hd44780Basic::printf(const char *__fmt, ...) { 78 | va_list ap; 79 | va_start(ap, __fmt); 80 | this->printf(0, __fmt, ap); 81 | va_end(ap); 82 | } 83 | 84 | // 0x01 85 | void Hd44780Basic::clear() const { 86 | transmit(false, 0x01); 87 | delayMicroseconds(2000); 88 | } 89 | 90 | // 0x02 91 | void Hd44780Basic::rst() const { 92 | transmit(false, 0x02); 93 | delayMicroseconds(2000); 94 | } 95 | 96 | // 0x04 97 | void Hd44780Basic::configureInput(bool ac, bool screen_move) const { 98 | uint8_t cmd = 0x04; 99 | 100 | if (ac) 101 | cmd |= 0x02; 102 | if (screen_move) 103 | cmd |= 0x01; 104 | 105 | transmit(false, cmd); 106 | } 107 | 108 | // 0x08 109 | void Hd44780Basic::configureDisplay(bool display_on, bool cursor, 110 | bool blink) const { 111 | uint8_t cmd = 0x08; 112 | if (display_on) 113 | cmd |= 0x04; 114 | if (cursor) 115 | cmd |= 0x02; 116 | if (blink) 117 | cmd |= 0x01; 118 | 119 | transmit(false, cmd); 120 | } 121 | 122 | // 0x10 123 | void Hd44780Basic::moveCursor(bool right) const { 124 | uint8_t cmd = 0x10; 125 | if (right) 126 | cmd |= 0x04; 127 | transmit(false, cmd); 128 | } 129 | 130 | // 0x11 131 | void Hd44780Basic::moveScreen(bool right) const { 132 | uint8_t cmd = 0x11; 133 | if (right) 134 | cmd |= 0x04; 135 | transmit(false, cmd); 136 | } 137 | 138 | // 0x20 139 | void Hd44780Basic::configureFunction(bool interface8, bool doubleline, 140 | bool font5x10) const { 141 | uint8_t cmd = 0x20; 142 | if (interface8) 143 | cmd |= 0x10; 144 | if (doubleline) 145 | cmd |= 0x08; 146 | if (font5x10) 147 | cmd |= 0x04; 148 | transmit(false, cmd); 149 | } 150 | 151 | void Hd44780Basic::setCGRam(uint8_t const *p, uint8_t length) const { 152 | this->configureInput(true, false); 153 | transmit(false, 0x40); 154 | 155 | while (length--) 156 | transmit(true, *p++); 157 | } 158 | 159 | void Hd44780Basic::setCursor(uint8_t address) const { 160 | transmit(false, address | 0x80); 161 | } 162 | -------------------------------------------------------------------------------- /hd44780/hd44780-basic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hd44780-basic.h 3 | * 4 | * Created on: Aug 11, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef HD44780_BASIC_H_ 9 | #define HD44780_BASIC_H_ 10 | 11 | #include "stm32-template.h" 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | class Hd44780Basic { 18 | public: 19 | Hd44780Basic(uint8_t row_count, uint8_t col_count); 20 | virtual ~Hd44780Basic(); 21 | 22 | void init(); 23 | void clear() const; 24 | void rst() const; 25 | 26 | void setCursor(uint8_t address) const; 27 | void moveCursor(bool right) const; 28 | void moveScreen(bool right) const; 29 | 30 | void configureDisplay(bool display_on = true, bool cursor = true, 31 | bool blink = true) const; 32 | void setCGRam(uint8_t const *pFont, uint8_t length) const; 33 | 34 | void putString(uint8_t address, char *p, uint8_t length) const; 35 | void putChar(uint8_t address, char c) const; 36 | void putCache() const; 37 | 38 | void setCache(uint8_t value = 0x00); 39 | void setCache(uint8_t index, uint8_t value); 40 | void printf(const char *__fmt, ...); 41 | void printf(uint8_t index, const char *__fmt, ...); 42 | 43 | protected: 44 | 45 | const uint8_t _row_count; 46 | const uint8_t _col_count; 47 | uint8_t _cache_length; 48 | char * _cache; 49 | 50 | static const uint8_t BAR_PATTERN[]; 51 | static const uint8_t ROW_INDEX_16[]; 52 | static const uint8_t ROW_INDEX_20[]; 53 | 54 | virtual void initHardware() const = 0; 55 | virtual void transmit(bool isData, uint8_t val) const = 0; 56 | 57 | void configureInput(bool ac = true, bool screen_move = false) const; 58 | void configureFunction(bool interface8 = false, bool doubleline = true, 59 | bool font5x10 = false) const; 60 | }; 61 | 62 | #endif /* HD44780_BASIC_H_ */ 63 | -------------------------------------------------------------------------------- /hd44780/hd44780-gpio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * hd44780-gpio.cpp 3 | * 4 | * Created on: Aug 11, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "hd44780/hd44780-gpio.h" 9 | 10 | Hd44780Gpio::Hd44780Gpio(Gpio & pin_rs, Gpio & pin_en, Gpio & pin_d4, 11 | Gpio & pin_d5, Gpio & pin_d6, Gpio & pin_d7, uint8_t row_count, 12 | uint8_t col_count) : 13 | Hd44780Basic(row_count, col_count), _pin_rs(pin_rs), _pin_en(pin_en), _pin_d4( 14 | pin_d4), _pin_d5(pin_d5), _pin_d6(pin_d6), _pin_d7(pin_d7) { 15 | 16 | } 17 | 18 | Hd44780Gpio::~Hd44780Gpio() { 19 | 20 | } 21 | 22 | void Hd44780Gpio::setDataPins(uint8_t c, bool high) const { 23 | if (high) 24 | c >>= 4; 25 | 26 | _pin_d4.set(c & 0x01); 27 | _pin_d5.set(c & 0x02); 28 | _pin_d6.set(c & 0x04); 29 | _pin_d7.set(c & 0x08); 30 | 31 | _pin_en.set(Bit_SET); 32 | _pin_en.set(Bit_RESET); 33 | 34 | #ifdef USE_FULL_ASSERT 35 | delayMicroseconds(0x20); 36 | #else 37 | delayMicroseconds(0x24); 38 | #endif 39 | } 40 | 41 | void Hd44780Gpio::setDataPins(uint8_t c) const { 42 | this->setDataPins(c, true); 43 | this->setDataPins(c, false); 44 | } 45 | 46 | void Hd44780Gpio::transmit(bool isData, uint8_t val) const { 47 | _pin_rs.set(isData); 48 | this->setDataPins(val); 49 | } 50 | 51 | void Hd44780Gpio::initHardware() const { 52 | 53 | _pin_rs.init(GPIO_Mode_Out_PP); 54 | _pin_en.init(GPIO_Mode_Out_PP); 55 | _pin_d4.init(GPIO_Mode_Out_PP); 56 | _pin_d5.init(GPIO_Mode_Out_PP); 57 | _pin_d6.init(GPIO_Mode_Out_PP); 58 | _pin_d7.init(GPIO_Mode_Out_PP); 59 | 60 | _pin_rs.set(Bit_RESET); 61 | _pin_en.set(Bit_RESET); 62 | 63 | delayMicroseconds(40000); 64 | 65 | this->setDataPins(0x30, true); 66 | delayMicroseconds(4500); 67 | 68 | this->setDataPins(0x30, true); 69 | delayMicroseconds(150); 70 | 71 | this->setDataPins(0x30, true); 72 | this->setDataPins(0x20, true); 73 | 74 | this->configureFunction(); 75 | this->configureDisplay(false, false, false); 76 | 77 | this->clear(); 78 | this->configureInput(); 79 | this->rst(); 80 | } 81 | 82 | -------------------------------------------------------------------------------- /hd44780/hd44780-gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | * hd44780-gpio.h 3 | * 4 | * Created on: Aug 11, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef HD44780_GPIO_H_ 9 | #define HD44780_GPIO_H_ 10 | 11 | #include "hd44780-basic.h" 12 | #include "gpio/gpio.h" 13 | 14 | class Hd44780Gpio: public Hd44780Basic { 15 | public: 16 | Hd44780Gpio(Gpio & pin_rs, Gpio & pin_en, Gpio & pin_d4, Gpio & pin_d5, 17 | Gpio & pin_d6, Gpio & pin_d7, uint8_t row_count = 4, 18 | uint8_t col_count = 16); 19 | virtual ~Hd44780Gpio(); 20 | 21 | private: 22 | Gpio & _pin_rs; 23 | Gpio & _pin_en; 24 | Gpio & _pin_d4; 25 | Gpio & _pin_d5; 26 | Gpio & _pin_d6; 27 | Gpio & _pin_d7; 28 | 29 | void setDataPins(uint8_t c, bool high) const; 30 | void setDataPins(uint8_t c) const; 31 | 32 | void transmit(bool isData, uint8_t val) const; 33 | 34 | void initHardware() const; 35 | }; 36 | 37 | #endif /* HD44780_GPIO_H_ */ 38 | -------------------------------------------------------------------------------- /i2c-soft/i2c-soft.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * i2c-soft.cpp 3 | * 4 | * Created on: Jun 9, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "i2c-soft.h" 9 | 10 | #define within(time, fun) for (t = (time); (fun) && --t;) 11 | 12 | I2cSoft::I2cSoft(Gpio &sda, Gpio &scl, uint16_t flat_timeout) : 13 | _sda(sda), _scl(scl), _FLAG_TIMEOUT(flat_timeout) { 14 | 15 | } 16 | 17 | I2cSoft::~I2cSoft() { 18 | 19 | } 20 | 21 | void I2cSoft::init() { 22 | _scl.init(GPIO_Mode_Out_OD); 23 | _scl.set(Bit_SET); 24 | } 25 | 26 | void I2cSoft::start() { 27 | _sda.set(Bit_SET); 28 | _sda.init(GPIO_Mode_Out_OD); 29 | 30 | _sda.set(Bit_RESET); 31 | _scl.set(Bit_RESET); 32 | } 33 | 34 | void I2cSoft::stop() { 35 | _sda.set(Bit_RESET); 36 | _sda.init(GPIO_Mode_Out_OD); 37 | 38 | _scl.set(Bit_SET); 39 | _sda.set(Bit_SET); 40 | } 41 | 42 | void I2cSoft::transmit(uint8_t data) { 43 | 44 | _sda.init(GPIO_Mode_Out_OD); 45 | 46 | for (uint8_t i = 0; i < 8; i++) { 47 | _sda.set(data & 0x80 ? Bit_SET : Bit_RESET); 48 | _scl.set(Bit_SET); 49 | _scl.set(Bit_RESET); 50 | data <<= 1; 51 | } 52 | } 53 | 54 | uint8_t I2cSoft::receive() { 55 | _sda.init(GPIO_Mode_IN_FLOATING); 56 | uint8_t data = 0; 57 | for (u8 i = 0; i < 8; i++) { 58 | _scl.set(Bit_SET); 59 | data <<= 1; 60 | data |= _sda.getInput() ? 0x01 : 0x00; 61 | _scl.set(Bit_RESET); 62 | } 63 | return data; 64 | } 65 | 66 | u16 I2cSoft::waitAck() { 67 | _sda.init(GPIO_Mode_IN_FLOATING); 68 | _scl.set(Bit_SET); 69 | 70 | vu16 t; 71 | within(_FLAG_TIMEOUT, _sda.getInput() == Bit_SET); 72 | 73 | _scl.set(Bit_RESET); 74 | return t; 75 | } 76 | 77 | uint8_t I2cSoft::write(uint8_t address, uint8_t *data, uint8_t length, 78 | uint8_t send_stop) { 79 | vu16 t; 80 | within(_FLAG_TIMEOUT, _sda.getInput() == Bit_RESET); 81 | if (!t) return 1; 82 | 83 | this->start(); 84 | this->transmit(address << 1); 85 | 86 | if (this->waitAck() == 0) return 2; 87 | 88 | while (length--) { 89 | this->transmit(*data++); 90 | if (this->waitAck() == 0) return 3; 91 | } 92 | 93 | if (send_stop) this->stop(); 94 | 95 | return t; 96 | } 97 | 98 | void I2cSoft::read(uint8_t address, uint8_t *data, uint8_t length, 99 | uint8_t send_stop) { 100 | this->start(); 101 | this->transmit((address << 1) | 0x01); 102 | this->waitAck(); 103 | 104 | while (length--) { 105 | *data++ = this->receive(); 106 | this->sendAck(length); 107 | } 108 | 109 | if (send_stop) this->stop(); 110 | } 111 | 112 | void I2cSoft::sendAck(uint8_t ack) { 113 | _scl.set(Bit_RESET); 114 | 115 | _sda.set(ack ? Bit_RESET : Bit_SET); 116 | _sda.init(GPIO_Mode_Out_OD); 117 | 118 | _scl.set(Bit_SET); 119 | _scl.set(Bit_RESET); 120 | } 121 | -------------------------------------------------------------------------------- /i2c-soft/i2c-soft.h: -------------------------------------------------------------------------------- 1 | /* 2 | * i2c-soft.h 3 | * 4 | * Created on: Jun 9, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef I2C_SOFT_H_ 9 | #define I2C_SOFT_H_ 10 | 11 | #include "gpio/gpio.h" 12 | 13 | class I2cSoft { 14 | public: 15 | I2cSoft(Gpio &sda, Gpio &scl, uint16_t flat_timeout = 0x100); 16 | ~I2cSoft(); 17 | void init(); 18 | 19 | void start(); 20 | void stop(); 21 | 22 | uint8_t write(uint8_t address, uint8_t *data, uint8_t length, 23 | uint8_t send_stop = true); 24 | 25 | void read(uint8_t address, uint8_t *data, uint8_t length, 26 | uint8_t send_stop = true); 27 | 28 | u16 waitAck(); 29 | void sendAck(uint8_t ack); 30 | 31 | void transmit(uint8_t data); 32 | uint8_t receive(); 33 | private: 34 | Gpio & _sda; 35 | Gpio & _scl; 36 | 37 | const uint16_t _FLAG_TIMEOUT; 38 | }; 39 | 40 | #endif /* I2C_SOFT_H_ */ 41 | -------------------------------------------------------------------------------- /i2c/i2c.cpp: -------------------------------------------------------------------------------- 1 | #include "i2c.h" 2 | 3 | #define within(time, fun) for (t = (time); (fun) && --t;) 4 | 5 | I2c::I2c(I2C_TypeDef * i2c, uint16_t flat_timeout, 6 | uint16_t long_timeout) : 7 | _i2c(i2c), _FLAG_TIMEOUT(flat_timeout), _LONG_TIMEOUT(long_timeout) { 8 | u32 t = (u32)(i2c - I2C1) << 11; 9 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 + t, ENABLE); 10 | } 11 | 12 | I2c::~I2c() { 13 | 14 | } 15 | 16 | void I2c::init(uint16_t mode, uint32_t clock_speed, uint16_t ack, 17 | uint16_t acknowledged_address, uint16_t duty_cycle) { 18 | 19 | I2C_DeInit(_i2c); 20 | 21 | I2C_InitTypeDef I2C_InitStructure; 22 | I2C_StructInit(&I2C_InitStructure); 23 | I2C_InitStructure.I2C_Mode = mode; 24 | I2C_InitStructure.I2C_DutyCycle = duty_cycle; 25 | I2C_InitStructure.I2C_OwnAddress1 = acknowledged_address; 26 | I2C_InitStructure.I2C_Ack = ack; 27 | I2C_InitStructure.I2C_ClockSpeed = clock_speed; 28 | I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; 29 | 30 | I2C_Init(_i2c, &I2C_InitStructure); 31 | I2C_Cmd(_i2c, ENABLE); 32 | } 33 | 34 | uint8_t I2c::write(uint8_t slave_address, const uint8_t* buf, uint32_t length, 35 | FunctionalState sendstop) { 36 | vu32 t = 0; 37 | 38 | if (!length) 39 | return 0; 40 | 41 | within(_LONG_TIMEOUT, I2C_GetFlagStatus(_i2c, I2C_FLAG_BUSY )); 42 | if (!t) 43 | return 0; 44 | 45 | I2C_GenerateSTART(_i2c, ENABLE); 46 | within(_FLAG_TIMEOUT, !I2C_CheckEvent(_i2c, I2C_EVENT_MASTER_MODE_SELECT )); 47 | if (!t) 48 | return 1; 49 | 50 | I2C_Send7bitAddress(_i2c, slave_address << 1, I2C_Direction_Transmitter); 51 | within(_FLAG_TIMEOUT, 52 | !I2C_CheckEvent(_i2c, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED )); 53 | if (!t) 54 | return 2; 55 | 56 | while (length--) { 57 | I2C_SendData(_i2c, *buf++); 58 | within(_FLAG_TIMEOUT, 59 | !I2C_CheckEvent(_i2c, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); 60 | if (!t) 61 | return 3; 62 | } 63 | 64 | I2C_GenerateSTOP(_i2c, sendstop); 65 | if (sendstop) { 66 | within(_LONG_TIMEOUT, I2C_GetFlagStatus(_i2c, I2C_FLAG_STOPF )); 67 | if (!t) 68 | return 4; 69 | } 70 | 71 | return 5; 72 | } 73 | 74 | uint8_t I2c::read(uint8_t slave_address, uint8_t* data, uint32_t length, 75 | FunctionalState checkbusy) { 76 | vu32 t = 0; 77 | if (!length) 78 | return 0; 79 | 80 | if (checkbusy) { 81 | within(_LONG_TIMEOUT, I2C_GetFlagStatus(_i2c, I2C_FLAG_BUSY )); 82 | if (!t) 83 | return 0; 84 | } 85 | 86 | I2C_AcknowledgeConfig(_i2c, ENABLE); 87 | I2C_NACKPositionConfig(_i2c, I2C_NACKPosition_Current); 88 | I2C_GenerateSTART(_i2c, ENABLE); 89 | 90 | within(_FLAG_TIMEOUT, !I2C_CheckEvent(_i2c, I2C_EVENT_MASTER_MODE_SELECT )); 91 | if (!t) 92 | return 1; 93 | 94 | I2C_Send7bitAddress(_i2c, slave_address << 1, I2C_Direction_Receiver); 95 | within(_FLAG_TIMEOUT, !I2C_GetFlagStatus(_i2c, I2C_FLAG_ADDR )); 96 | if (!t) 97 | return 2; 98 | 99 | if (length == 1) { 100 | I2C_AcknowledgeConfig(_i2c, DISABLE); 101 | 102 | __disable_irq(); 103 | (void) _i2c->SR2; 104 | I2C_GenerateSTOP(_i2c, ENABLE); 105 | __enable_irq(); 106 | 107 | within(_FLAG_TIMEOUT, !I2C_GetFlagStatus(_i2c, I2C_FLAG_RXNE )); 108 | if (!t) 109 | return 3; 110 | 111 | *data = I2C_ReceiveData(_i2c); 112 | } else if (length == 2) { 113 | I2C_NACKPositionConfig(_i2c, I2C_NACKPosition_Next); 114 | 115 | __disable_irq(); 116 | (void) _i2c->SR2; // Clear ADDR flag 117 | I2C_AcknowledgeConfig(_i2c, DISABLE); // Clear Ack bit 118 | __enable_irq(); 119 | 120 | within(_FLAG_TIMEOUT, !I2C_GetFlagStatus(_i2c, I2C_FLAG_BTF)); 121 | 122 | __disable_irq(); 123 | *data++ = I2C_ReceiveData(_i2c); 124 | I2C_GenerateSTOP(_i2c, ENABLE); 125 | __enable_irq(); 126 | 127 | *data++ = I2C_ReceiveData(_i2c); 128 | } else { 129 | (void) _i2c->SR2; // Clear ADDR flag 130 | while (length-- > 3) { 131 | // EV7 -- cannot guarantee 1 transfer completion time, wait for BTF 132 | // instead of RXNE 133 | within(_FLAG_TIMEOUT, !I2C_GetFlagStatus(_i2c, I2C_FLAG_BTF)); 134 | *data++ = I2C_ReceiveData(_i2c); 135 | } 136 | 137 | within(_FLAG_TIMEOUT, !I2C_GetFlagStatus(_i2c, I2C_FLAG_BTF)); 138 | 139 | // EV7_2 -- Figure 1 has an error, doesn't read N-2 ! 140 | I2C_AcknowledgeConfig(_i2c, DISABLE); // Clear Ack bit 141 | 142 | __disable_irq(); 143 | *data++ = I2C_ReceiveData(_i2c); // receive byte N-2 144 | I2C_GenerateSTOP(_i2c, ENABLE); // program stop 145 | *data++ = I2C_ReceiveData(_i2c); // receive byte N-1 146 | __enable_irq(); 147 | 148 | // wait for byte N 149 | within(_FLAG_TIMEOUT, 150 | !I2C_CheckEvent(_i2c, I2C_EVENT_MASTER_BYTE_RECEIVED )); 151 | *data++ = I2C_ReceiveData(_i2c); 152 | length = 0; 153 | } 154 | 155 | within(_FLAG_TIMEOUT, I2C_GetFlagStatus(_i2c, I2C_FLAG_STOPF)); 156 | if (!t) 157 | return 4; 158 | 159 | return 5; 160 | } 161 | 162 | uint8_t I2c::setReg(uint8_t slave_address, uint8_t reg_address, 163 | const uint8_t* buf, uint32_t length) { 164 | 165 | assert_param(length); 166 | uint8_t *p = (uint8_t *) malloc(sizeof(uint8_t) * (length + 1)); 167 | p[0] = reg_address; 168 | memcpy(p + 1, buf, length); 169 | uint8_t result = this->write(slave_address, p, length + 1); 170 | free(p); 171 | return result; 172 | } 173 | 174 | uint8_t I2c::setReg(uint8_t slave_address, uint8_t reg_address, 175 | const uint8_t value) { 176 | return this->setReg(slave_address, reg_address, &value, 1); 177 | } 178 | 179 | uint8_t I2c::getReg(uint8_t slave_address, uint8_t reg_address, uint8_t* buf, 180 | uint32_t length) { 181 | this->write(slave_address, ®_address, 1, DISABLE); 182 | return this->read(slave_address, buf, length, DISABLE); 183 | 184 | } 185 | -------------------------------------------------------------------------------- /i2c/i2c.h: -------------------------------------------------------------------------------- 1 | #ifndef I2C_H 2 | #define I2C_H 3 | 4 | #include "stm32f10x_i2c.h" 5 | #include 6 | #include 7 | 8 | class I2c { 9 | public: 10 | I2c(I2C_TypeDef * i2c, uint16_t flat_timeout = 11 | 0x100, uint16_t long_timeout = 0x400); 12 | ~I2c(); 13 | void init(uint16_t mode = I2C_Mode_I2C, uint32_t clock_speed = 100000, 14 | uint16_t ack = I2C_Ack_Enable, uint16_t acknowledged_address = 0, 15 | uint16_t duty_cycle = I2C_DutyCycle_2); 16 | 17 | uint8_t write(uint8_t slave_address, const uint8_t* buf, uint32_t length, 18 | FunctionalState sendstop = ENABLE); 19 | uint8_t read(uint8_t slave_address, uint8_t* buf, uint32_t length, 20 | FunctionalState checkbusy = ENABLE); 21 | uint8_t setReg(uint8_t slave_address, uint8_t reg_address, 22 | const uint8_t* buf, uint32_t length); 23 | uint8_t setReg(uint8_t slave_address, uint8_t reg_address, 24 | const uint8_t value); 25 | uint8_t getReg(uint8_t slave_address, uint8_t reg_address, uint8_t* buf, 26 | uint32_t length); 27 | 28 | private: 29 | I2C_TypeDef * const _i2c; 30 | const uint16_t _FLAG_TIMEOUT; 31 | const uint16_t _LONG_TIMEOUT; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /isl1208-i2csoft/isl1208-i2csoft.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * isl1208-i2csoft.cpp 3 | * 4 | * Created on: Jun 14, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "isl1208-i2csoft.h" 9 | 10 | Isl1208I2cSoft::Isl1208I2cSoft(Gpio &sda, Gpio &scl) : 11 | I2cSoft(sda, scl, 0x100) { 12 | 13 | } 14 | 15 | Isl1208I2cSoft::~Isl1208I2cSoft() { 16 | 17 | } 18 | 19 | void Isl1208I2cSoft::init() { 20 | this->I2cSoft::init(); 21 | uint8_t cmd[2] = { 0x07, 0x90 }; 22 | this->write(_ADDRESS, cmd, 2); 23 | } 24 | 25 | void Isl1208I2cSoft::refresh() { 26 | uint8_t cmd = 0; 27 | this->write(_ADDRESS, &cmd, 1); 28 | this->read(_ADDRESS, _data, 7); 29 | } 30 | 31 | uint8_t Isl1208I2cSoft::getVal(uint8_t index) { 32 | return _data[index]; 33 | } 34 | -------------------------------------------------------------------------------- /isl1208-i2csoft/isl1208-i2csoft.h: -------------------------------------------------------------------------------- 1 | /* 2 | * isl1208-i2csoft.h 3 | * 4 | * Created on: Jun 14, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef ISL1208_I2CSOFT_H_ 9 | #define ISL1208_I2CSOFT_H_ 10 | 11 | #include "i2c-soft/i2c-soft.h" 12 | 13 | class Isl1208I2cSoft: public I2cSoft { 14 | public: 15 | Isl1208I2cSoft(Gpio &sda, Gpio &scl); 16 | ~Isl1208I2cSoft(); 17 | void init(); 18 | void refresh(); 19 | uint8_t getVal(uint8_t index); 20 | private: 21 | static const uint8_t _ADDRESS = 0x6f; 22 | uint8_t _data[7]; 23 | }; 24 | 25 | #endif /* ISL1208_I2CSOFT_H_ */ 26 | -------------------------------------------------------------------------------- /nrf24l01p/nrf24l01p.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * nrf24l01.cpp 3 | * 4 | * Created on: Sep 21, 2016 5 | * Author: agu 6 | */ 7 | 8 | #include "nrf24l01p.h" 9 | 10 | Nrf24l01p::Nrf24l01p(Spi & spi, Gpio & sck, Gpio & miso, Gpio & mosi, 11 | Gpio & irq, Gpio & csn, Gpio & ce) : 12 | _spi(spi), _sck(sck), _miso(miso), _mosi(mosi), _irq( 13 | irq), _csn(csn), _ce(ce) { 14 | 15 | } 16 | 17 | void Nrf24l01p::init(u8 channel) { 18 | u8 status; 19 | 20 | _sck.init(GPIO_Mode_AF_PP, GPIO_Speed_10MHz); 21 | _mosi.init(GPIO_Mode_AF_PP, GPIO_Speed_10MHz); 22 | _miso.init(GPIO_Mode_IPU, GPIO_Speed_10MHz); 23 | 24 | _irq.init(GPIO_Mode_IPU, GPIO_Speed_2MHz); 25 | _csn.init(GPIO_Mode_Out_PP, GPIO_Speed_2MHz); 26 | _ce.init(GPIO_Mode_Out_PP, GPIO_Speed_2MHz); 27 | _spi.init(); 28 | 29 | // _spi.configDataSize(SPI_DataSize_8b); 30 | 31 | _ce.set(false); 32 | writeReg(CONFIG, 0x08); // Power Down 33 | command(FLUSH_TX); 34 | command(FLUSH_RX); 35 | writeReg(RF_CH, channel); 36 | writeReg(RF_SETUP, 0x0f); 37 | writeReg(SETUP_AW, 0x03); 38 | 39 | writeReg(FEATURE, 0x04); // dynamic payload 40 | 41 | readReg(RF_SETUP, &status, 1); 42 | printf("%02x\r\n", status); 43 | } 44 | 45 | void Nrf24l01p::writeReg(u8 addr, u8*data, u8 length) { 46 | _csn.set(false); 47 | _spi.write(0x20 + addr); 48 | _spi.write(data, length); 49 | _csn.set(true); 50 | } 51 | 52 | void Nrf24l01p::writeReg(u8 addr, u8 data) { 53 | uint8_t status; 54 | _csn.set(false); 55 | _spi.write(0x20 + addr); 56 | status = _spi.write(data); 57 | _csn.set(true); 58 | 59 | printf("write_register(%02x,%02x) %02x\r\n", addr, data, status); 60 | } 61 | 62 | void Nrf24l01p::readReg(u8 addr, u8*data, u8 length) { 63 | _csn.set(false); 64 | _spi.write(addr); 65 | _spi.readWithNop(data, length); 66 | _csn.set(true); 67 | } 68 | 69 | void Nrf24l01p::setupTx() { 70 | _ce.set(false); 71 | writeReg(CONFIG, 0x0e); // power on and ptx 72 | delay(2); 73 | } 74 | 75 | void Nrf24l01p::setupRx() { 76 | _ce.set(false); 77 | writeReg(CONFIG, 0x0f); // power on and prx 78 | _ce.set(true); 79 | } 80 | 81 | u8 Nrf24l01p::send(u8 *data, u8 length) { 82 | _csn.set(false); 83 | _spi.write(W_TX_PLOAD); 84 | _spi.write(data, length); 85 | _csn.set(true); 86 | 87 | _ce.set(true); 88 | delayMicroseconds(10); 89 | _ce.set(false); 90 | 91 | while (_irq.getInput()) 92 | ; 93 | 94 | u8 status; 95 | readReg(STATUS, &status, 1); 96 | writeReg(STATUS, status); 97 | 98 | if (status & MAX_TX) { 99 | command(FLUSH_TX); 100 | } 101 | 102 | setupRx(); 103 | 104 | return status; 105 | } 106 | 107 | u8 Nrf24l01p::sendFromSlave(u8 *data, u8 length) { 108 | setupTx(); 109 | u8 r = send(data, length); 110 | setupRx(); 111 | return r; 112 | } 113 | 114 | u8 Nrf24l01p::recv(u8 *data) { 115 | if (_irq.getInput() == false) { 116 | u8 status; 117 | readReg(STATUS, &status, 1); 118 | writeReg(STATUS, status); 119 | 120 | if (status & RX_OK) { 121 | _csn.set(false); 122 | _spi.write(R_RX_PL_WID); 123 | u8 len; 124 | _spi.readWithNop(&len, 1); 125 | _csn.set(true); 126 | 127 | if (len > 32) { 128 | return 0; 129 | } 130 | 131 | _csn.set(false); 132 | _spi.write(R_RX_PLOAD); 133 | _spi.readWithNop(data, len); 134 | _csn.set(true); 135 | command(FLUSH_RX); 136 | return len; 137 | } 138 | } 139 | return 0; 140 | } 141 | 142 | void Nrf24l01p::command(u8 cmd) { 143 | _csn.set(false); 144 | _spi.write(cmd); 145 | _csn.set(true); 146 | } 147 | 148 | void Nrf24l01p::initSlave(u8 * addr) { 149 | _ce.set(false); 150 | 151 | writeReg(TX_ADDR, addr, 5); 152 | writeReg(RX_ADDR_P0, addr, 5); 153 | 154 | writeReg(DNYPD, 0x01); 155 | writeReg(EN_AA, 0x01); 156 | writeReg(EN_RXADDR, 0x01); 157 | 158 | writeReg(SETUP_RETR, 0x3f); 159 | 160 | setupRx(); 161 | } 162 | 163 | void Nrf24l01p::initMaster(u8 * addr_msbytes, u8 * lsbytes) { 164 | _ce.set(false); 165 | u8 addr[5] = {0}; 166 | addr[0] = lsbytes[0]; 167 | memcpy(addr+1, addr_msbytes, 4); 168 | 169 | writeReg(RX_ADDR_P1, addr, 5); 170 | 171 | for (u8 i = 0; i<4 ; i++) { 172 | writeReg(RX_ADDR_P2 + i, lsbytes[i+1]); 173 | } 174 | 175 | writeReg(DNYPD, 0x3e); 176 | writeReg(EN_AA, 0x3e); 177 | writeReg(EN_RXADDR, 0x3e); 178 | 179 | writeReg(SETUP_RETR, 0x1f); 180 | } 181 | 182 | u8 Nrf24l01p::sendFromMaster(u8 * slave_addr, u8 *data, u8 length) { 183 | _ce.set(false); 184 | writeReg(TX_ADDR, slave_addr, 5); 185 | writeReg(RX_ADDR_P0, slave_addr, 5); 186 | writeReg(DNYPD, 0x01); 187 | writeReg(EN_AA, 0x01); 188 | writeReg(EN_RXADDR, 0x01); 189 | 190 | setupTx(); 191 | u8 result = send(data, length); 192 | 193 | writeReg(DNYPD, 0x3e); 194 | writeReg(EN_AA, 0x3e); 195 | writeReg(EN_RXADDR, 0x3e); 196 | setupRx(); 197 | 198 | return result; 199 | } 200 | -------------------------------------------------------------------------------- /nrf24l01p/nrf24l01p.h: -------------------------------------------------------------------------------- 1 | /* 2 | * work with nRF24L01+ only in DPL mode 3 | * Not intend to make it compatible with nRF24L01 or nRF2401 4 | */ 5 | 6 | #ifndef NRF24L01P_H_ 7 | #define NRF24L01P_H_ 8 | 9 | #include 10 | #include "gpio/gpio.h" 11 | #include "spi/spi.h" 12 | #include 13 | 14 | //读RX有效数据,1~32字节 15 | #define R_RX_PLOAD 0x61 16 | 17 | //写TX有效数据,1~32字节 18 | #define W_TX_PLOAD 0xA0 19 | 20 | //清除TX FIFO寄存器.发射模式下用 21 | #define FLUSH_TX 0xE1 22 | 23 | //清除RX FIFO寄存器.接收模式下用 24 | #define FLUSH_RX 0xE2 25 | 26 | //重新使用上一包数据,CE为高,数据包被不断发送. 27 | #define REUSE_TX_PL 0xE3 28 | 29 | #define R_RX_PL_WID 0x60 30 | 31 | //配置寄存器地址;bit0:1接收模式,0发射模式;bit1:电选择;bit2:CRC模式;bit3:CRC使能; 32 | //bit4:中断MAX_RT(达到最大重发次数中断)使能;bit5:中断TX_DS使能;bit6:中断RX_DR使能 33 | #define CONFIG 0x00 34 | 35 | //使能自动应答功能 bit0~5,对应通道0~5 36 | #define EN_AA 0x01 37 | 38 | //接收地址允许,bit0~5,对应通道0~5 39 | #define EN_RXADDR 0x02 40 | 41 | //设置地址宽度(所有数据通道):bit1,0:00,3字节;01,4字节;02,5字节; 42 | #define SETUP_AW 0x03 43 | 44 | //建立自动重发;bit3:0,自动重发计数器;bit7:4,自动重发延时 250*x+86us 45 | #define SETUP_RETR 0x04 46 | 47 | //RF通道,bit6:0,工作通道频率; 48 | #define RF_CH 0x05 49 | 50 | //RF寄存器;bit3:传输速率(0:1Mbps,1:2Mbps);bit2:1,发射功率;bit0:低噪声放大器增益 51 | #define RF_SETUP 0x06 52 | 53 | //状态寄存器;bit0:TX FIFO满标志;bit3:1,接收数据通道号(最大:6);bit4,达到最多次重发 54 | #define STATUS 0x07 55 | 56 | //bit5:数据发送完成中断;bit6:接收数据中断; 达到最大发送次数中断 57 | #define MAX_TX 0x10 58 | 59 | //TX发送完成中断 60 | #define TX_OK 0x20 61 | 62 | //接收到数据中断 63 | #define RX_OK 0x40 64 | 65 | //发送检测寄存器,bit7:4,数据包丢失计数器;bit3:0,重发计数器 66 | #define OBSERVE_TX 0x08 67 | 68 | //载波检测寄存器,bit0,载波检测; 69 | #define CD 0x09 70 | 71 | //数据通道0接收地址,最大长度5个字节,低字节在前 72 | #define RX_ADDR_P0 0x0A 73 | 74 | //数据通道1接收地址,最大长度5个字节,低字节在前 75 | #define RX_ADDR_P1 0x0B 76 | 77 | //数据通道2接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; 78 | #define RX_ADDR_P2 0x0C 79 | 80 | //数据通道3接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; 81 | #define RX_ADDR_P3 0x0D 82 | 83 | //数据通道4接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; 84 | #define RX_ADDR_P4 0x0E 85 | 86 | //数据通道5接收地址,最低字节可设置,高字节,必须同RX_ADDR_P1[39:8]相等; 87 | #define RX_ADDR_P5 0x0F 88 | 89 | //发送地址(低字节在前),ShockBurstTM模式下,RX_ADDR_P0与此地址相等 90 | #define TX_ADDR 0x10 91 | 92 | //接收数据通道0有效数据宽度(1~32字节),设置为0则非法 93 | #define RX_PW_P0 0x11 94 | 95 | //接收数据通道1有效数据宽度(1~32字节),设置为0则非法 96 | #define RX_PW_P1 0x12 97 | 98 | //接收数据通道2有效数据宽度(1~32字节),设置为0则非法 99 | #define RX_PW_P2 0x13 100 | 101 | //接收数据通道3有效数据宽度(1~32字节),设置为0则非法 102 | #define RX_PW_P3 0x14 103 | 104 | //接收数据通道4有效数据宽度(1~32字节),设置为0则非法 105 | #define RX_PW_P4 0x15 106 | 107 | //接收数据通道5有效数据宽度(1~32字节),设置为0则非法 108 | #define RX_PW_P5 0x16 109 | 110 | //FIFO状态寄存器;bit0,RX FIFO寄存器空标志;bit1,RX FIFO满标志;bit2,3,保留 111 | #define FIFO_STATUS 0x17 112 | 113 | #define DNYPD 0x1C 114 | #define FEATURE 0x1D 115 | 116 | extern void delay(u32); 117 | extern void delayMicroseconds(u32); 118 | 119 | class Nrf24l01p { 120 | public: 121 | Nrf24l01p(Spi & spi, Gpio & spi_sck, Gpio & spi_miso, Gpio & spi_mosi, 122 | Gpio & nrf_irq, Gpio & nrf_csn, Gpio & nrf_ce); 123 | void init(u8 channel = 0x34); 124 | 125 | void writeReg(u8 addr, u8*data, u8 length); 126 | void writeReg(u8 addr, u8 data); 127 | void readReg(u8 addr, u8*data, u8 length); 128 | 129 | u8 send(u8 * dt, u8 length); 130 | u8 sendFromMaster(u8 * slave_addr, u8 * dt, u8 length); 131 | u8 sendFromSlave(u8 * dt, u8 length); 132 | u8 recv(u8 *); 133 | 134 | // len(addr_msbytes) == 4, len(lsbytes) == 5, uniquess required in lsbytes 135 | void initMaster(u8 * addr_msbytes, u8 * lsbytes); 136 | void initSlave(u8 * addr); 137 | 138 | private: 139 | Spi & _spi; 140 | Gpio & _sck; 141 | Gpio & _miso; 142 | Gpio & _mosi; 143 | 144 | Gpio & _irq; 145 | Gpio & _csn; 146 | Gpio & _ce; 147 | 148 | void setupTx(); 149 | void setupRx(); 150 | void command(u8); 151 | }; 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /nvic/nvic.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * nvic.cpp 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "nvic.h" 9 | 10 | void Nvic::configureGroup(uint32_t priority_group) { 11 | NVIC_PriorityGroupConfig(priority_group ); 12 | } 13 | 14 | void Nvic::configure(uint8_t irq_channel, 15 | uint8_t preemption_priority, 16 | uint8_t sub_priority, 17 | FunctionalState cmd) { 18 | 19 | NVIC_InitTypeDef NVIC_InitStructure; 20 | NVIC_InitStructure.NVIC_IRQChannel = irq_channel; 21 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 22 | preemption_priority; 23 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = sub_priority; 24 | NVIC_InitStructure.NVIC_IRQChannelCmd = cmd; 25 | NVIC_Init(&NVIC_InitStructure); 26 | } 27 | 28 | Nvic nvic; 29 | -------------------------------------------------------------------------------- /nvic/nvic.h: -------------------------------------------------------------------------------- 1 | /* 2 | * nvic.h 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef NVIC_H_ 9 | #define NVIC_H_ 10 | 11 | #include "misc.h" 12 | 13 | class Nvic { 14 | public: 15 | 16 | static void configureGroup(uint32_t priority_group = NVIC_PriorityGroup_0); 17 | 18 | static void configure(uint8_t irq_channel, 19 | uint8_t preemption_priority, 20 | uint8_t sub_priority, 21 | FunctionalState cmd); 22 | }; 23 | 24 | extern Nvic nvic; 25 | 26 | #endif /* NVIC_H_ */ 27 | -------------------------------------------------------------------------------- /spi-soft/spi-soft.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * spi-soft.cpp 3 | * 4 | * Created on: Jun 7, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "spi-soft.h" 9 | #include "stm32-template.h" 10 | 11 | SpiSoft::SpiSoft(Gpio & mosi, Gpio & miso, Gpio & sck, Gpio & ss) : 12 | _mosi(mosi), _miso(miso), _sck(sck), _ss(ss) { 13 | 14 | } 15 | 16 | SpiSoft::~SpiSoft() { 17 | 18 | } 19 | 20 | void SpiSoft::init() { 21 | _mosi.init(GPIO_Mode_Out_PP); 22 | _miso.init(GPIO_Mode_IPD); 23 | _sck.init(GPIO_Mode_Out_PP); 24 | _ss.init(GPIO_Mode_Out_PP); 25 | 26 | _ss.set(Bit_SET); 27 | _sck.set(Bit_RESET); 28 | } 29 | 30 | void SpiSoft::transmit(const uint8_t * out, uint8_t * in, uint32_t length) { 31 | _ss.set(Bit_RESET); 32 | 33 | while (length--) 34 | *in++ = transmitByte(*out++); 35 | 36 | _ss.set(Bit_SET); 37 | } 38 | 39 | void SpiSoft::transmit(const uint8_t *out, uint32_t out_length, uint8_t * in, 40 | uint32_t in_length, uint8_t dummy_data) { 41 | _ss.set(Bit_RESET); 42 | 43 | while (out_length--) 44 | transmitByte(*out++); 45 | 46 | while (in_length--) 47 | *in++ = transmitByte(dummy_data); 48 | 49 | _ss.set(Bit_SET); 50 | } 51 | 52 | uint8_t SpiSoft::transmitByte(uint8_t out) { 53 | 54 | uint8_t c = 0x00; 55 | for (uint8_t i = 0; i < 8; i++) { 56 | 57 | c <<= 1; 58 | c |= _miso.getInput() ? 0x01 : 0x00; 59 | _mosi.set(out & 0x80 ? Bit_SET : Bit_RESET); 60 | _sck.set(Bit_SET); 61 | _sck.set(Bit_RESET); 62 | out <<= 1; 63 | } 64 | return c; 65 | } 66 | 67 | void SpiSoft::transmit(const uint8_t out, uint8_t * in, uint32_t in_length) { 68 | this->transmit(&out, 1, in, in_length); 69 | } 70 | 71 | -------------------------------------------------------------------------------- /spi-soft/spi-soft.h: -------------------------------------------------------------------------------- 1 | /* 2 | * spi-soft.h 3 | * 4 | * Created on: Jun 7, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef SPI_SOFT_H_ 9 | #define SPI_SOFT_H_ 10 | 11 | #include "gpio/gpio.h" 12 | 13 | // function as a spi master 14 | 15 | class SpiSoft { 16 | public: 17 | SpiSoft(Gpio & mosi, Gpio & miso, Gpio & sck, Gpio & ss); 18 | virtual ~SpiSoft(); 19 | void transmit(const uint8_t * out, uint8_t * in, uint32_t length); 20 | void transmit(const uint8_t *out, uint32_t out_length, uint8_t * in, 21 | uint32_t in_length, uint8_t dummy_data = 0x00); 22 | void transmit(const uint8_t out, uint8_t * in, uint32_t in_length); 23 | void init(); 24 | protected: 25 | Gpio & _mosi; 26 | Gpio & _miso; 27 | Gpio & _sck; 28 | 29 | uint8_t transmitByte(uint8_t in); 30 | Gpio & _ss; 31 | 32 | }; 33 | 34 | #endif /* SPI_SOFT_H_ */ 35 | -------------------------------------------------------------------------------- /spi/spi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * spi.cpp 3 | * 4 | * Created on: Jun 4, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "spi.h" 9 | 10 | Spi::Spi(SPI_TypeDef * spi) : 11 | _spi(spi) { 12 | switch ((u32) _spi) { 13 | case (u32) SPI1_BASE: 14 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); 15 | break; 16 | case (u32) SPI2_BASE: 17 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); 18 | break; 19 | case (u32) SPI3_BASE: 20 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE); 21 | break; 22 | } 23 | } 24 | 25 | Spi::~Spi() { 26 | 27 | } 28 | 29 | void Spi::init(uint16_t direction, uint16_t mode, uint16_t data_size, 30 | uint16_t cpol, uint16_t cpha, uint16_t nss, uint16_t baudrate_prescaler, 31 | uint16_t first_bit, uint16_t crc_polynomial) { 32 | 33 | SPI_InitTypeDef spi_init_type; 34 | 35 | spi_init_type.SPI_Direction = direction; 36 | spi_init_type.SPI_Mode = mode; 37 | spi_init_type.SPI_DataSize = data_size; 38 | spi_init_type.SPI_CPOL = cpol; 39 | spi_init_type.SPI_CPHA = cpha; 40 | spi_init_type.SPI_NSS = nss; 41 | spi_init_type.SPI_BaudRatePrescaler = baudrate_prescaler; 42 | spi_init_type.SPI_FirstBit = first_bit; 43 | spi_init_type.SPI_CRCPolynomial = crc_polynomial; 44 | 45 | SPI_Init(_spi, &spi_init_type); 46 | SPI_Cmd(_spi, ENABLE); 47 | } 48 | 49 | void Spi::configDataSize(uint16_t SPI_DataSize) { 50 | SPI_DataSizeConfig(_spi, SPI_DataSize); 51 | } 52 | 53 | void Spi::write(const u8 * out, u16 length, u8 * in) { 54 | while (length--) { 55 | u8 val = write(*out++); 56 | if (in) 57 | *in++ = val; 58 | } 59 | } 60 | 61 | void Spi::write(const u16 * out, u16 length, u16 * in) { 62 | while (length--) { 63 | u16 val = write(*out++); 64 | if (in) 65 | *in++ = val; 66 | } 67 | } 68 | 69 | u16 Spi::write(u16 val) { 70 | while (!SPI_I2S_GetFlagStatus(_spi, SPI_I2S_FLAG_TXE)) 71 | ; 72 | SPI_I2S_SendData(_spi, val); 73 | 74 | while (!SPI_I2S_GetFlagStatus(_spi, SPI_I2S_FLAG_RXNE)) 75 | ; 76 | return SPI_I2S_ReceiveData(_spi); 77 | } 78 | 79 | void Spi::readWithNop(u8 * in, u16 length) { 80 | while (length--) { 81 | *in++ = write(0xff); 82 | } 83 | } 84 | 85 | void Spi::readWithNop(u16 * in, u16 length) { 86 | while (length--) { 87 | *in++ = write(0xff); 88 | } 89 | } 90 | 91 | 92 | SPI_TypeDef * Spi::base() { 93 | return _spi; 94 | } 95 | -------------------------------------------------------------------------------- /spi/spi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * spi.h 3 | * 4 | * Created on: Jun 4, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef SPI_H_ 9 | #define SPI_H_ 10 | 11 | #include 12 | #include "stm32f10x_spi.h" 13 | 14 | class Spi { 15 | public: 16 | Spi(SPI_TypeDef * spi); 17 | void init(uint16_t direction = SPI_Direction_2Lines_FullDuplex, 18 | uint16_t mode = SPI_Mode_Master, 19 | uint16_t data_size = SPI_DataSize_8b, uint16_t cpol = SPI_CPOL_Low, 20 | uint16_t cpha = SPI_CPHA_1Edge, uint16_t _nss = SPI_NSS_Soft, 21 | uint16_t baudrate_prescaler = SPI_BaudRatePrescaler_8, 22 | uint16_t first_bit = SPI_FirstBit_MSB, uint16_t crc_polynomial = 7); 23 | ~Spi(); 24 | 25 | void write(const u8 * out, u16 length, u8 * in = NULL); 26 | void write(const u16 * out, u16 length, u16 * in = NULL); 27 | 28 | void readWithNop(u8 * in, u16 length); 29 | void readWithNop(u16 * in, u16 length); 30 | 31 | void configDataSize(u16); 32 | 33 | u16 write(u16); 34 | SPI_TypeDef * base(); 35 | private: 36 | SPI_TypeDef * const _spi; 37 | }; 38 | 39 | #endif /* SPI_H_ */ 40 | -------------------------------------------------------------------------------- /sst25-spisoft/sst25-spisoft.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * sst25-spisoft.cpp 3 | * 4 | * Created on: Jun 8, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "sst25-spisoft.h" 9 | 10 | Sst25SpiSoft::Sst25SpiSoft(Gpio & mosi, Gpio & miso, Gpio & sck, Gpio & ss) : 11 | SpiSoft(mosi, miso, sck, ss) { 12 | 13 | } 14 | 15 | Sst25SpiSoft::~Sst25SpiSoft() { 16 | 17 | } 18 | 19 | uint16_t Sst25SpiSoft::getId() { 20 | const static uint8_t out[] = { 0x90, 0x00, 0x00, 0x00 }; 21 | uint8_t in[2]; 22 | transmit(out, 4, in, 2); 23 | return in[0] << 8 | in[1]; 24 | } 25 | 26 | uint8_t Sst25SpiSoft::getStatus() { 27 | uint8_t status; 28 | transmit(0x05, &status, 1); 29 | return status; 30 | } 31 | 32 | void Sst25SpiSoft::write(uint32_t address, uint8_t data) { 33 | //this->write(address, &data, 1); 34 | uint8_t command[5] = { 0x02, (uint8_t) (address >> 16), (uint8_t) (address 35 | >> 8), (uint8_t) address, data }; 36 | this->transmit(0x06, 0, 0); 37 | this->transmit(command, 5, 0, 0); 38 | } 39 | 40 | uint8_t Sst25SpiSoft::read(uint32_t address) { 41 | uint8_t data; 42 | this->read(address, &data, 1); 43 | return data; 44 | } 45 | 46 | void Sst25SpiSoft::setStatus(uint8_t status) { 47 | this->transmit(0x06, 0, 0); 48 | this->transmit(0x50, 0, 0); 49 | uint8_t command[2] = { 0x01, status }; 50 | this->transmit(command, 2, 0, 0); 51 | } 52 | 53 | void Sst25SpiSoft::erase(EraseType type, uint32_t address) { 54 | 55 | uint8_t command[4] = { 0x20, (uint8_t) (address >> 16), (uint8_t) (address 56 | >> 8), (uint8_t) address }; 57 | 58 | this->transmit(0x06, 0, 0); 59 | 60 | if (type == Chip) 61 | this->transmit(0x60, 0, 0); 62 | else { 63 | command[0] = (uint8_t) type; 64 | this->transmit(command, 4, 0, 0); 65 | } 66 | 67 | while (isBusy()) 68 | ; 69 | } 70 | 71 | uint8_t Sst25SpiSoft::isBusy() { 72 | return this->getStatus() & 0x01; 73 | } 74 | 75 | void Sst25SpiSoft::write(uint32_t address, uint8_t *data, uint32_t length) { 76 | 77 | assert_param((length & 0x01) == 0); 78 | assert_param(length >= 2); 79 | 80 | uint8_t command[4] = { 0xad, (uint8_t) (address >> 16), (uint8_t) (address 81 | >> 8), (uint8_t) address }; 82 | 83 | uint8_t len = 4; 84 | uint8_t * p = command; 85 | 86 | // Byte-Program: 87 | // while (length--) 88 | // this->write(address++, *data++); 89 | 90 | // AAI-Word_Program 91 | this->transmit(0x70, 0, 0); 92 | this->transmit(0x06, 0, 0); 93 | 94 | while (length) { 95 | _ss.set(Bit_RESET); 96 | 97 | if (len == 255) 98 | this->transmitByte(0xad); 99 | else 100 | while (len--) 101 | this->transmitByte(*p++); 102 | 103 | this->transmitByte(*data++); 104 | this->transmitByte(*data++); 105 | 106 | _ss.set(Bit_SET); 107 | 108 | _ss.set(Bit_RESET); 109 | while (_miso.getInput() == Bit_RESET) 110 | ; 111 | _ss.set(Bit_SET); 112 | 113 | length -= 2; 114 | } 115 | 116 | this->transmit(0x04, 0, 0); 117 | this->transmit(0x80, 0, 0); 118 | } 119 | 120 | void Sst25SpiSoft::read(uint32_t address, uint8_t *data, uint32_t length) { 121 | uint8_t command[4] = { 0x03, (uint8_t) (address >> 16), (uint8_t) (address 122 | >> 8), (uint8_t) address }; 123 | this->transmit(command, 4, data, length); 124 | } 125 | 126 | -------------------------------------------------------------------------------- /sst25-spisoft/sst25-spisoft.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sst25-spisoft.h 3 | * 4 | * Created on: Jun 8, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef SST25_SPISOFT_H_ 9 | #define SST25_SPISOFT_H_ 10 | 11 | #include "spi-soft/spi-soft.h" 12 | #include "stm32-template.h" 13 | 14 | class Sst25SpiSoft: public SpiSoft { 15 | public: 16 | enum EraseType { 17 | Chip = 0x60, Sector4K = 0x20, Block32K = 0x52, Block64K = 0xd8, 18 | }; 19 | 20 | Sst25SpiSoft(Gpio & mosi, Gpio & miso, Gpio & sck, Gpio & ss); 21 | virtual ~Sst25SpiSoft(); 22 | uint16_t getId(); 23 | 24 | uint8_t getStatus(); 25 | void setStatus(uint8_t status); 26 | 27 | void write(uint32_t address, uint8_t data); 28 | uint8_t read(uint32_t address); 29 | 30 | void write(uint32_t address, uint8_t *data, uint32_t length); 31 | void read(uint32_t address, uint8_t *data, uint32_t length); 32 | 33 | void erase(EraseType type, uint32_t address = 0); 34 | uint8_t isBusy(); 35 | }; 36 | 37 | #endif /* SST25_SPISOFT_H_ */ 38 | -------------------------------------------------------------------------------- /st7735r/st7735r.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * st7735r.cpp 3 | * 4 | * Created on: Jun 4, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "st7735r.h" 9 | 10 | #define ST7735_CASET 0x2A 11 | #define ST7735_RASET 0x2B 12 | #define ST7735_MADCTL 0x36 13 | #define ST7735_RAMWR 0x2C 14 | #define ST7735_RAMRD 0x2E 15 | #define ST7735_COLMOD 0x3A 16 | 17 | #define MADCTLGRAPHICS 0x6 18 | #define MADCTLBMP 0x2 19 | 20 | #define MADVAL(x) (((x) << 5) | 8) 21 | //static uint8_t madctlcurrent = MADVAL(MADCTLGRAPHICS); 22 | 23 | const St7735r::instruction St7735r::initializers[] = { 24 | // SWRESET Software reset 25 | { 0x01, 150, 0, { 0 } }, 26 | // SLPOUT Leave sleep mode 27 | { 0x11, 150, 0, { 0 } }, 28 | // FRMCTR1, FRMCTR2 Frame Rate configuration -- Normal mode, idle 29 | // frame rate = fosc / (1 x 2 + 40) * (LINE + 2C + 2D) 30 | { 0xB1, 0, 3, { 0x01, 0x2C, 0x2D } }, 31 | { 0xB2, 0, 3, { 0x01, 0x2C, 0x2D } }, 32 | // FRMCTR3 Frame Rate configureation -- partial mode 33 | { 0xB3, 0, 6, { 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D } }, 34 | // INVCTR Display inversion (no inversion) 35 | { 0xB4, 0, 1, { 0x07 } }, 36 | // PWCTR1 Power control -4.6V, Auto mode 37 | { 0xC0, 0, 3, { 0xA2, 0x02, 0x84 } }, 38 | // PWCTR2 Power control VGH25 2.4C, VGSEL -10, VGH = 3 * AVDD 39 | { 0xC1, 0, 1, { 0xC5 } }, 40 | // PWCTR3 Power control, opamp current smal, boost frequency 41 | { 0xC2, 0, 2, { 0x0A, 0x00 } }, 42 | // PWCTR4 Power control, BLK/2, opamp current small and medium low 43 | { 0xC3, 0, 2, { 0x8A, 0x2A } }, 44 | // PWRCTR5, VMCTR1 Power control 45 | { 0xC4, 0, 2, { 0x8A, 0xEE } }, { 0xC5, 0, 1, { 0x0E } }, 46 | // INVOFF Don't invert display 47 | { 0x20, 0, 0, { 0 } }, 48 | // Memory access directions. row address/col address, bottom to top refesh (10.1.27) 49 | { ST7735_MADCTL, 0, 1, { MADVAL(MADCTLGRAPHICS) } }, 50 | // Color mode 16 bit (10.1.30 51 | { ST7735_COLMOD, 0, 1, { 0x05 } }, 52 | // // Column address set 0..127 53 | // { ST7735_CASET, 0, 4, { 0x00, 0x00, 0x00, 0x7F } }, 54 | // // Row address set 0..127 55 | // { ST7735_RASET, 0, 4, { 0x00, 0x00, 0x00, 0x7F } }, 56 | // GMCTRP1 Gamma correction 57 | { 0xE0, 0, 16, { 0x02, 0x1C, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2D, 0x29, 58 | 0x25, 0x2B, 0x39, 0x00, 0x01, 0x03, 0x10 } }, 59 | // GMCTRP2 Gamma Polarity corrction 60 | { 0xE1, 0, 16, { 0x03, 0x1d, 0x07, 0x06, 0x2E, 0x2C, 0x29, 0x2D, 0x2E, 61 | 0x2E, 0x37, 0x3F, 0x00, 0x00, 0x02, 0x10 } }, 62 | // DISPON Display on 63 | { 0x29, 100, 0, { 0 } }, 64 | // NORON Normal on 65 | { 0x13, 10, 0, { 0 } }, 66 | // End 67 | { 0, 0, 0, { 0 } } }; 68 | 69 | St7735r::St7735r(Spi & spi, Dma & dma, Gpio &pin_ss, Gpio &pin_reset, 70 | Gpio &pin_rs, uint16_t offset_x, uint16_t offset_y) : 71 | _spi(spi), _dma(dma), _pin_ss(pin_ss), _pin_reset(pin_reset), _pin_rs( 72 | pin_rs), _offset_x(offset_x), _offset_y(offset_y) { 73 | } 74 | 75 | St7735r::~St7735r() { 76 | 77 | } 78 | 79 | void St7735r::init() { 80 | 81 | _pin_ss.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 82 | _pin_reset.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 83 | _pin_rs.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 84 | 85 | _spi.init(SPI_Direction_2Lines_FullDuplex, SPI_Mode_Master, SPI_DataSize_8b, 86 | SPI_CPOL_Low, SPI_CPHA_1Edge, SPI_NSS_Soft, SPI_BaudRatePrescaler_2, 87 | SPI_FirstBit_MSB, 7); 88 | 89 | SPI_I2S_DMACmd(_spi.base(), SPI_I2S_DMAReq_Tx, ENABLE); 90 | 91 | _pin_ss.set(Bit_SET); 92 | _pin_reset.set(Bit_SET); 93 | delay(10); 94 | _pin_reset.set(Bit_RESET); 95 | delay(10); 96 | _pin_reset.set(Bit_SET); 97 | delay(10); 98 | 99 | for (const instruction * cmd = initializers; cmd->command; cmd++) { 100 | this->command(cmd->command); 101 | if (cmd->len) write8(true, cmd->data, cmd->len); 102 | if (cmd->delay) delay(cmd->delay); 103 | } 104 | 105 | _dma.setPeriphToConf((uint32_t) &(_spi.base()->DR), 106 | DMA_PeripheralDataSize_HalfWord, DMA_PeripheralInc_Disable ); 107 | _dma.setFunctionToConf(); 108 | } 109 | 110 | void St7735r::write8(bool is_data, const uint8_t * data, uint16_t length) { 111 | _pin_rs.set(is_data ? Bit_SET : Bit_RESET); 112 | _pin_ss.set(Bit_RESET); 113 | _spi.write(data, length); 114 | _pin_ss.set(Bit_SET); 115 | } 116 | 117 | void St7735r::write16(bool is_data, const uint16_t * data, uint16_t length) { 118 | 119 | SPI_DataSizeConfig(_spi.base(), SPI_DataSize_16b ); 120 | 121 | _pin_rs.set(is_data ? Bit_SET : Bit_RESET); 122 | _pin_ss.set(Bit_RESET); 123 | // _spi.write16(data, length); 124 | 125 | _dma.setMemoryToConf((uint32_t) &data, DMA_MemoryDataSize_HalfWord, 126 | DMA_MemoryInc_Enable ); 127 | _dma.setTransferToConf(length, DMA_DIR_PeripheralDST); 128 | _dma.initWithConf(); 129 | _dma.run(); 130 | 131 | _pin_ss.set(Bit_SET); 132 | } 133 | 134 | void St7735r::write16(bool is_data, const uint16_t data, uint16_t length) { 135 | 136 | SPI_DataSizeConfig(_spi.base(), SPI_DataSize_16b ); 137 | 138 | _pin_rs.set(is_data ? Bit_SET : Bit_RESET); 139 | _pin_ss.set(Bit_RESET); 140 | // while (length--) 141 | // _spi.write16(&data, 1); 142 | 143 | _dma.setMemoryToConf((uint32_t) &data, DMA_MemoryDataSize_HalfWord, 144 | DMA_MemoryInc_Disable ); 145 | _dma.setTransferToConf(length, DMA_DIR_PeripheralDST); 146 | _dma.initWithConf(); 147 | _dma.run(); 148 | 149 | _pin_ss.set(Bit_SET); 150 | } 151 | 152 | void St7735r::command(uint8_t cmd) { 153 | this->write8(0, &cmd, 1); 154 | } 155 | 156 | void St7735r::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, 157 | uint16_t y1) { 158 | 159 | command(ST7735_CASET); 160 | this->write16(true, x0 + _offset_x); 161 | this->write16(true, x1 + _offset_x); 162 | 163 | command(ST7735_RASET); 164 | this->write16(true, y0 + _offset_y); 165 | this->write16(true, y1 + _offset_y); 166 | 167 | command(ST7735_RAMWR); 168 | } 169 | -------------------------------------------------------------------------------- /st7735r/st7735r.h: -------------------------------------------------------------------------------- 1 | /* 2 | * st7735r.h 3 | * 4 | * Created on: Jun 4, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef ST7735R_H_ 9 | #define ST7735R_H_ 10 | 11 | #include "stm32-template.h" 12 | #include "spi/spi.h" 13 | #include "gpio/gpio.h" 14 | #include "dma/dma.h" 15 | 16 | class St7735r { 17 | public: 18 | St7735r(Spi & spi, Dma & dma, Gpio &pin_ss, Gpio &pin_reset, Gpio &pin_rs, uint16_t offset_x = 2, uint16_t offset_y = 3); 19 | virtual ~St7735r(); 20 | void init(); 21 | void write8(bool is_data, const uint8_t * data, uint16_t length); 22 | void write16(bool is_data, const uint16_t * data, uint16_t length); 23 | void write16(bool is_data, const uint16_t data, uint16_t length = 1); 24 | void command(uint8_t cmd); 25 | void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); 26 | 27 | typedef struct { 28 | uint8_t command; // ST7735 command byte 29 | uint8_t delay; // ms delay after 30 | uint8_t len; // length of parameter data 31 | uint8_t data[16]; // parameter data 32 | } instruction; 33 | 34 | private: 35 | Spi & _spi; 36 | Dma & _dma; 37 | Gpio & _pin_ss; 38 | Gpio & _pin_reset; 39 | Gpio & _pin_rs; 40 | 41 | const uint16_t _offset_x; 42 | const uint16_t _offset_y; 43 | static const instruction initializers[]; 44 | }; 45 | 46 | #endif /* ST7735R_H_ */ 47 | -------------------------------------------------------------------------------- /st7920/st7920-dm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * st7920-dm.cpp 3 | * 4 | * Created on: Aug 16, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "st7920-dm.h" 9 | 10 | St7920Dm::St7920Dm(Gpio & pin_rs, Gpio & pin_en, Gpio & pin_d4, Gpio & pin_d5, 11 | Gpio & pin_d6, Gpio & pin_d7) : 12 | St7920(pin_rs, pin_en, pin_d4, pin_d5, pin_d6, pin_d7), _dm(128, 64) { 13 | 14 | } 15 | 16 | St7920Dm::~St7920Dm() { 17 | 18 | } 19 | 20 | void St7920Dm::putDM() { 21 | uint8_t *ppa = _dm.output(); 22 | uint8_t *ppb = ppa + 512; 23 | 24 | for (uint8_t r = 0; r < 0x20; r++) { 25 | this->setDdRam(r); // y 26 | this->setDdRam(0x00); // x 27 | 28 | this->transmit(true, ppa, 0x10); 29 | this->transmit(true, ppb, 0x10); 30 | 31 | ppa += 0x10; 32 | ppb += 0x10; 33 | } 34 | } 35 | 36 | DotMatrix & St7920Dm::getDotMatrix() { 37 | return _dm; 38 | } 39 | -------------------------------------------------------------------------------- /st7920/st7920-dm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * st7920-dm.h 3 | * 4 | * Created on: Aug 16, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef ST7920_DM_H_ 9 | #define ST7920_DM_H_ 10 | 11 | #include "st7920.h" 12 | #include "dot-matrix/dot-matrix.h" 13 | 14 | class St7920Dm: public St7920 { 15 | public: 16 | St7920Dm(Gpio & pin_rs, Gpio & pin_en, Gpio & pin_d4, Gpio & pin_d5, 17 | Gpio & pin_d6, Gpio & pin_d7); 18 | ~St7920Dm(); 19 | 20 | void putDM(); 21 | DotMatrix & getDotMatrix(); 22 | 23 | private: 24 | DotMatrix _dm; 25 | }; 26 | 27 | #endif /* ST7920_DM_H_ */ 28 | -------------------------------------------------------------------------------- /st7920/st7920.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * st7920.cpp 3 | * 4 | * Created on: Aug 15, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "st7920.h" 9 | 10 | St7920::St7920(Gpio & pin_rs, Gpio & pin_en, Gpio & pin_d4, Gpio & pin_d5, 11 | Gpio & pin_d6, Gpio & pin_d7) : 12 | _pin_rs(pin_rs), _pin_en(pin_en), _pin_d4(pin_d4), _pin_d5(pin_d5), _pin_d6( 13 | pin_d6), _pin_d7(pin_d7) { 14 | } 15 | 16 | St7920::~St7920() { 17 | 18 | } 19 | 20 | void St7920::init() { 21 | 22 | _pin_rs.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 23 | _pin_en.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 24 | _pin_d4.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 25 | _pin_d5.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 26 | _pin_d6.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 27 | _pin_d7.init(GPIO_Mode_Out_PP, GPIO_Speed_50MHz); 28 | 29 | _pin_en.set(Bit_RESET); 30 | 31 | delayMicroseconds(50000); 32 | 33 | this->setDataPins(0x20, true); 34 | this->configureFunction(false, false); 35 | this->configureDisplay(true, false, false); 36 | this->clear(); 37 | this->configureEntry(true); 38 | 39 | this->configureFunction(false, true, true); 40 | } 41 | 42 | void St7920::clear() { 43 | this->transmit(false, 0x01); 44 | delayMicroseconds(2000); 45 | } 46 | 47 | void St7920::home() { 48 | this->transmit(false, 0x02); 49 | } 50 | 51 | void St7920::configureEntry(bool right) { 52 | uint8_t cmd = 0x04; 53 | if (right) 54 | cmd |= 0x02; 55 | this->transmit(false, cmd); 56 | } 57 | 58 | void St7920::configureDisplay(bool display, bool cursor, bool blink) { 59 | uint8_t cmd = 0x08; 60 | if (display) 61 | cmd |= 0x04; 62 | if (cursor) 63 | cmd |= 0x02; 64 | if (blink) 65 | cmd |= 0x01; 66 | this->transmit(false, cmd); 67 | } 68 | 69 | void St7920::moveCursor(bool right) { 70 | uint8_t cmd = 0x10; 71 | if (right) 72 | cmd |= 0x04; 73 | this->transmit(false, cmd); 74 | } 75 | 76 | void St7920::moveDisplay(bool right) { 77 | uint8_t cmd = 0x18; 78 | if (right) 79 | cmd |= 0x04; 80 | this->transmit(false, cmd); 81 | } 82 | 83 | void St7920::configureFunction(bool interface8, bool re, bool graphic) { 84 | uint8_t cmd = 0x20; 85 | if (interface8) 86 | cmd |= 0x10; 87 | if (re) 88 | cmd |= 0x04; 89 | if (re && graphic) 90 | cmd |= 0x02; 91 | this->transmit(false, cmd); 92 | } 93 | 94 | void St7920::setCgRam(uint8_t value) { 95 | this->transmit(true, 0x40 | value); 96 | } 97 | 98 | void St7920::setDdRam(uint8_t address) { 99 | this->transmit(false, 0x80 | address); 100 | } 101 | 102 | ///////////////////////////////////// 103 | 104 | void St7920::transmit(bool isData, uint8_t c) { 105 | _pin_rs.set(isData); 106 | setDataPins(c, true); 107 | setDataPins(c, false); 108 | } 109 | 110 | void St7920::transmit(bool isData, uint8_t *p, uint8_t length) { 111 | _pin_rs.set(isData); 112 | while (length--) { 113 | setDataPins(*p, true); 114 | setDataPins(*p++, false); 115 | } 116 | } 117 | 118 | void St7920::setDataPins(uint8_t c, bool high) { 119 | if (high) 120 | c >>= 4; 121 | 122 | _pin_d4.set(c & 0x01); 123 | _pin_d5.set(c & 0x02); 124 | _pin_d6.set(c & 0x04); 125 | _pin_d7.set(c & 0x08); 126 | 127 | _pin_en.set(Bit_SET); 128 | _pin_en.set(Bit_RESET); 129 | 130 | #ifndef USE_FULL_ASSERT 131 | delayMicroseconds(0x0c); 132 | #endif 133 | } 134 | 135 | void St7920::printWord(char *p) { 136 | while (*p) { 137 | this->transmit(true, *p++); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /st7920/st7920.h: -------------------------------------------------------------------------------- 1 | /* 2 | * st7920.h 3 | * 4 | * Created on: Aug 15, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef ST7920_H_ 9 | #define ST7920_H_ 10 | 11 | #include "stm32-template.h" 12 | //#include "gpio/gpio.h" 13 | 14 | class St7920 { 15 | 16 | public: 17 | St7920(Gpio & pin_rs, Gpio & pin_en, Gpio & pin_d4, Gpio & pin_d5, 18 | Gpio & pin_d6, Gpio & pin_d7); 19 | virtual ~St7920(); 20 | 21 | void init(); 22 | 23 | void printWord(char *); 24 | void clear(); 25 | void home(); 26 | void configureEntry(bool right = true); 27 | void configureDisplay(bool display = true, bool cursor = false, bool blink = 28 | false); 29 | void moveCursor(bool right = true); 30 | void moveDisplay(bool right = true); 31 | void configureFunction(bool interface8 = false, bool re = false, 32 | bool graphic = false); 33 | 34 | void setDdRam(uint8_t address); // Set address in Text Mode 35 | 36 | void transmit(bool isData, uint8_t c); 37 | void transmit(bool isData, uint8_t *p, uint8_t length); 38 | 39 | private: 40 | 41 | Gpio & _pin_rs; 42 | Gpio & _pin_en; 43 | Gpio & _pin_d4; 44 | Gpio & _pin_d5; 45 | Gpio & _pin_d6; 46 | Gpio & _pin_d7; 47 | 48 | void setDataPins(uint8_t c, bool high); 49 | void setCgRam(uint8_t value); 50 | }; 51 | 52 | #endif /* ST7920_H_ */ 53 | -------------------------------------------------------------------------------- /tim/tim.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * tim.cpp 3 | * 4 | * Created on: May 27, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "tim.h" 9 | 10 | Tim::Tim(TIM_TypeDef * tim, 11 | uint32_t rcc_apbx_periph) : 12 | _tim(tim) { 13 | u32 address = (u32) (_tim); 14 | if (address & 0x10000) { 15 | RCC_APB2PeriphClockCmd(rcc_apbx_periph, ENABLE); 16 | } else { 17 | RCC_APB1PeriphClockCmd(rcc_apbx_periph, ENABLE); 18 | } 19 | } 20 | 21 | Tim::~Tim() { 22 | 23 | } 24 | 25 | void Tim::init(uint32_t real_clock, 26 | uint16_t real_period, 27 | uint16_t clock_division, 28 | uint16_t counter_mode, 29 | uint8_t repition_counter) { 30 | TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; 31 | 32 | uint32_t prescaler = SystemCoreClock / real_clock - 1; 33 | assert_param(prescaler < 65536); 34 | 35 | TIM_TimeBaseStructure.TIM_Prescaler = prescaler; 36 | TIM_TimeBaseStructure.TIM_Period = real_period - 1; 37 | TIM_TimeBaseStructure.TIM_ClockDivision = clock_division; 38 | TIM_TimeBaseStructure.TIM_CounterMode = counter_mode; 39 | TIM_TimeBaseStructure.TIM_RepetitionCounter = repition_counter; 40 | 41 | TIM_TimeBaseInit(_tim, &TIM_TimeBaseStructure); 42 | TIM_Cmd(_tim, ENABLE); 43 | } 44 | 45 | void Tim::setCounter(uint16_t counter) { 46 | TIM_SetCounter(_tim, counter); 47 | } 48 | 49 | void Tim::configureIT(uint16_t it, FunctionalState enable) { 50 | TIM_ITConfig(_tim, it, enable); 51 | } 52 | 53 | void Tim::setState(FunctionalState enable) { 54 | TIM_Cmd(_tim, enable); 55 | } 56 | 57 | void Tim::configureArrPreload(FunctionalState enable) { 58 | TIM_ARRPreloadConfig(_tim, enable); 59 | } 60 | 61 | ITStatus Tim::getITStatus(uint16_t it) { 62 | return TIM_GetITStatus(_tim, it); 63 | } 64 | 65 | void Tim::clearITPendingBit(uint16_t it) { 66 | TIM_ClearITPendingBit(_tim, it); 67 | } 68 | 69 | 70 | 71 | ////////////////////////////////////////////////////////// 72 | 73 | TimOc::TimOc(TIM_TypeDef * tim, 74 | void (*tim_ocx_init)(TIM_TypeDef* TIMx, 75 | TIM_OCInitTypeDef* TIM_OCInitStruct), 76 | void (*tim_set_comparex)(TIM_TypeDef* TIMx, uint16_t compare)) : 77 | _tim(tim), _tim_ocx_init(tim_ocx_init), _tim_set_comparex( 78 | tim_set_comparex) { 79 | } 80 | 81 | TimOc::~TimOc() { 82 | 83 | } 84 | 85 | void TimOc::init(uint16_t oc_mode, 86 | uint16_t output_state, 87 | uint16_t output_nstate, 88 | uint16_t pulse, 89 | uint16_t oc_polarity, 90 | uint16_t oc_npolarity, 91 | uint16_t oc_idle_state, 92 | uint16_t oc_nidle_state) { 93 | 94 | TIM_OCInitTypeDef tim_oc_init_type; 95 | tim_oc_init_type.TIM_OCMode = oc_mode; 96 | tim_oc_init_type.TIM_OutputState = output_state; 97 | tim_oc_init_type.TIM_OutputNState = output_nstate; 98 | tim_oc_init_type.TIM_Pulse = pulse; 99 | tim_oc_init_type.TIM_OCPolarity = oc_polarity; 100 | tim_oc_init_type.TIM_OCNPolarity = oc_npolarity; 101 | tim_oc_init_type.TIM_OCIdleState = oc_idle_state; 102 | tim_oc_init_type.TIM_OCNIdleState = oc_nidle_state; 103 | 104 | (*_tim_ocx_init)(_tim, &tim_oc_init_type); 105 | } 106 | 107 | void TimOc::setCompare(uint16_t pulse) { 108 | (*_tim_set_comparex)(_tim, pulse); 109 | } 110 | 111 | ////////////////////////////////////////////////////////////// 112 | 113 | TimIc::TimIc(TIM_TypeDef * tim) : 114 | _tim(tim) { 115 | 116 | } 117 | 118 | TimIc::~TimIc() { 119 | 120 | } 121 | 122 | void TimIc::init(uint16_t channel, 123 | uint16_t ic_polarity, 124 | uint16_t ic_selection, 125 | uint16_t ic_prescaler, 126 | uint16_t ic_filter) { 127 | TIM_ICInitTypeDef tim_ic_init_type; 128 | tim_ic_init_type.TIM_Channel = channel; 129 | tim_ic_init_type.TIM_ICPolarity = ic_polarity; 130 | tim_ic_init_type.TIM_ICSelection = ic_selection; 131 | tim_ic_init_type.TIM_ICPrescaler = ic_prescaler; 132 | tim_ic_init_type.TIM_ICFilter = ic_filter; 133 | TIM_ICInit(_tim, &tim_ic_init_type); 134 | } 135 | -------------------------------------------------------------------------------- /tim/tim.h: -------------------------------------------------------------------------------- 1 | /* 2 | * tim.h 3 | * 4 | * Created on: May 27, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef TIM_H_ 9 | #define TIM_H_ 10 | 11 | #include "stm32f10x_tim.h" 12 | 13 | class Tim { 14 | public: 15 | Tim(TIM_TypeDef * tim, 16 | uint32_t rcc_apbx_periph); 17 | ~Tim(); 18 | void init(uint32_t real_clock = SystemCoreClock, 19 | uint16_t real_period = 0, 20 | uint16_t clock_division = TIM_CKD_DIV1, 21 | uint16_t counter_mode = TIM_CounterMode_Up, 22 | uint8_t repition_counter = 0x0000); 23 | void setCounter(uint16_t counter); 24 | void configureIT(uint16_t it, FunctionalState enable = ENABLE); 25 | void setState(FunctionalState enable = ENABLE); 26 | void configureArrPreload(FunctionalState enable = ENABLE); 27 | ITStatus getITStatus(uint16_t it); 28 | void clearITPendingBit(uint16_t it); 29 | private: 30 | TIM_TypeDef * const _tim; 31 | }; 32 | 33 | class TimOc { 34 | public: 35 | TimOc(TIM_TypeDef * tim, 36 | void (*tim_ocx_init)(TIM_TypeDef* TIMx, 37 | TIM_OCInitTypeDef* TIM_OCInitStruct), 38 | void (*tim_set_comparex)(TIM_TypeDef* TIMx, uint16_t compare)); 39 | ~TimOc(); 40 | 41 | void init(uint16_t oc_mode = TIM_OCMode_Timing, 42 | uint16_t output_state = TIM_OutputState_Disable, 43 | uint16_t output_nstate = TIM_OutputNState_Disable, 44 | uint16_t pulse = 0x0000, 45 | uint16_t oc_polarity = TIM_OCPolarity_High, 46 | uint16_t oc_npolarity = TIM_OCPolarity_High, 47 | uint16_t oc_idle_state = TIM_OCIdleState_Reset, 48 | uint16_t oc_nidle_state = TIM_OCNIdleState_Reset); 49 | 50 | void setCompare(uint16_t pulse); 51 | 52 | private: 53 | TIM_TypeDef * const _tim; 54 | void (*_tim_ocx_init)(TIM_TypeDef* TIMx, 55 | TIM_OCInitTypeDef* TIM_OCInitStruct); 56 | void (*_tim_set_comparex)(TIM_TypeDef* TIMx, uint16_t compare); 57 | }; 58 | 59 | class TimIc { 60 | public: 61 | TimIc(TIM_TypeDef * tim); 62 | ~TimIc(); 63 | void init(uint16_t channel = TIM_Channel_1, 64 | uint16_t ic_polarity = TIM_ICPolarity_Rising, 65 | uint16_t ic_selection = TIM_ICSelection_DirectTI, 66 | uint16_t ic_prescaler = TIM_ICPSC_DIV1, 67 | uint16_t ic_filter = 0x00); 68 | 69 | private: 70 | TIM_TypeDef * const _tim; 71 | }; 72 | 73 | #endif /* TIM_H_ */ 74 | -------------------------------------------------------------------------------- /tubes/iv22.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * iv22.cpp 3 | * 4 | * Created on: Oct 17, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "iv22.h" 9 | 10 | const uint8_t Iv22::_font[] = { 11 | // 0-9 12 | 0xb7, 0x22, 0x9b, 0xab, 0x2e, 0xad, 0xbd, 0x23, 0xbf, 0xaf, 13 | 14 | // a-z 15 | 0xbb, 0xbc, 0x98, 0xba, 0x9f, 0x1d, 0xb5, 0x3c, 0x14, 0xa2, 0x9c, 0x94, 16 | 0x37, 0x38, 0xb8, 0x1f, 0x2f, 0x18, 0x2c, 0x1c, 0xb0, 0x90, 0x0e, 0x0f, 17 | 0x2a, 0x1a, }; 18 | 19 | Iv22::Iv22(Gpio & pin_din, Gpio & pin_oe, Gpio & pin_st, Gpio & pin_sh, 20 | uint8_t section_count) : 21 | _pin_din(pin_din), _pin_oe(pin_oe), _pin_st(pin_st), _pin_sh(pin_sh), _section_count( 22 | section_count) { 23 | 24 | _buff = (uint8_t *) malloc( 25 | sizeof(uint8_t) * (section_count) * _BYTE_PER_SECTION); 26 | } 27 | 28 | Iv22::~Iv22() { 29 | free(_buff); 30 | } 31 | 32 | void Iv22::init() { 33 | _pin_din.init(GPIO_Mode_Out_PP); 34 | _pin_oe.init(GPIO_Mode_Out_PP); 35 | _pin_st.init(GPIO_Mode_Out_PP); 36 | _pin_sh.init(GPIO_Mode_Out_PP); 37 | 38 | _pin_oe.set(Bit_RESET); 39 | } 40 | 41 | void Iv22::send(uint8_t data) const { 42 | for (uint8_t i = 8; i--; data <<= 1) { 43 | _pin_din.set(data & 0x80); 44 | _pin_sh.set(Bit_SET); 45 | _pin_sh.set(Bit_RESET); 46 | } 47 | } 48 | 49 | void Iv22::display() { 50 | for (uint8_t i = 0; i < _section_count; i++) { 51 | this->send(_buff[i * _BYTE_PER_SECTION]); 52 | this->send(_buff[i * _BYTE_PER_SECTION + 1]); 53 | } 54 | 55 | _pin_st.set(Bit_SET); 56 | _pin_st.set(Bit_RESET); 57 | } 58 | 59 | void Iv22::setSection(uint8_t index, uint16_t value) { 60 | index %= _section_count; 61 | _buff[index + index] = highByte(value); 62 | _buff[index + index + 1] = lowByte(value); 63 | } 64 | 65 | void Iv22::clear(uint16_t value) { 66 | for (uint8_t i = 0; i < _section_count; i++) 67 | this->setSection(i, value); 68 | } 69 | 70 | void Iv22::setBackgroundColor(Color color) { 71 | for (uint8_t i = 0; i < _section_count; i++) { 72 | this->setBackgroundColor(i, color); 73 | } 74 | } 75 | 76 | void Iv22::setBackgroundColor(uint8_t index, Color color) { 77 | index %= _section_count; 78 | _buff[index * _BYTE_PER_SECTION] = color; 79 | } 80 | 81 | void Iv22::setPoint(uint8_t index) { 82 | index %= _section_count; 83 | _buff[index * _BYTE_PER_SECTION + 1] |= 0x40; 84 | } 85 | 86 | void Iv22::setPattern(uint8_t index, uint8_t pattern) { 87 | _buff[index * _BYTE_PER_SECTION + 1] &= 0x40; 88 | _buff[index * _BYTE_PER_SECTION + 1] |= pattern; 89 | } 90 | 91 | uint8_t Iv22::getPattern(uint8_t index) { 92 | return _buff[index * _BYTE_PER_SECTION + 1] & 0xbf; 93 | } 94 | 95 | bool Iv22::setChar(uint8_t index, char c) { 96 | index %= _section_count; 97 | 98 | bool val = displayable(c); 99 | 100 | if (val) { 101 | if (c >= '0' && c <= '9') 102 | this->setPattern(index, _font[c - '0']); 103 | else if (c >= 'A' && c <= 'Z') 104 | this->setPattern(index, _font[c - 'A' + 10]); 105 | else if (c >= 'a' && c <= 'z') 106 | this->setPattern(index, _font[c - 'a' + 10]); 107 | } 108 | 109 | return val; 110 | } 111 | 112 | void Iv22::setChar(char c) { 113 | for (uint8_t i = 0; i < _section_count; i++) 114 | this->setChar(i, c); 115 | } 116 | 117 | 118 | void Iv22::printf(const char *__fmt, ...) { 119 | uint16_t cache_length = _section_count * 2 + 1; 120 | char * cache = (char *) malloc(sizeof(char) * cache_length); 121 | 122 | va_list ap; 123 | va_start(ap, __fmt); 124 | vsnprintf(cache, cache_length, __fmt, ap); 125 | va_end(ap); 126 | 127 | uint8_t index = 0; 128 | uint8_t ptr = 0; 129 | 130 | for (uint8_t i = 0; i < _section_count; i++) 131 | _buff[i * _BYTE_PER_SECTION + 1] = 0x00; 132 | 133 | while (cache[index] && ptr < _section_count) { 134 | if (this->setChar(ptr, cache[index])) 135 | ptr++; 136 | else if (cache[index] == '.') 137 | this->setPoint(ptr ? ptr - 1 : 0); 138 | else { 139 | _buff[ptr * _BYTE_PER_SECTION + 1] = 0x00; 140 | ptr++; 141 | } 142 | 143 | index++; 144 | } 145 | 146 | if (cache[index] == '.') 147 | this->setPoint(ptr - 1); 148 | 149 | free(cache); 150 | } 151 | 152 | bool Iv22::displayable(char c) { 153 | return ((c >= '0' && c <= '9') or (c >= 'A' && c <= 'Z') 154 | or (c >= 'a' && c <= 'z')); 155 | } 156 | -------------------------------------------------------------------------------- /tubes/iv22.h: -------------------------------------------------------------------------------- 1 | /* 2 | * iv22.h 3 | * 4 | * Created on: Oct 17, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef IV22_H_ 9 | #define IV22_H_ 10 | 11 | #include "../gpio/gpio.h" 12 | #include 13 | #include "../common/bit_op.h" 14 | #include 15 | #include 16 | 17 | enum Color { 18 | White, Yellow, Magenta, Red, Cyan, Green, Blue, Black, 19 | }; 20 | 21 | class Iv22 { 22 | public: 23 | Iv22(Gpio & pin_din, Gpio & pin_oe, Gpio & pin_st, Gpio & pin_sh, 24 | uint8_t section_count); 25 | virtual ~Iv22(); 26 | 27 | void init(); 28 | void display(); 29 | 30 | void setSection(uint8_t index, uint16_t value = 0xff00); 31 | void clear(uint16_t value = 0xff00); 32 | 33 | void setBackgroundColor(Color color); 34 | void setBackgroundColor(uint8_t index, Color color); 35 | 36 | void setBrightness(uint8_t brightness = 0xff); 37 | 38 | void setPoint(uint8_t index); 39 | void setPattern(uint8_t index, uint8_t pattern); 40 | uint8_t getPattern(uint8_t index); 41 | 42 | bool setChar(uint8_t index, char c); 43 | void setChar(char c); 44 | 45 | void printf(const char *__fmt, ...); 46 | 47 | private: 48 | 49 | uint8_t *_buff; 50 | 51 | Gpio & _pin_din; // DIN 52 | Gpio & _pin_oe; // OE, pin with PWM output is recommended to enable brightness adjustment 53 | Gpio & _pin_st; // STCP 54 | Gpio & _pin_sh; // SHCP 55 | 56 | const uint8_t _section_count; 57 | static const uint8_t _BYTE_PER_SECTION = 2; 58 | 59 | void send(uint8_t data) const; 60 | bool displayable(char c); 61 | 62 | static const uint8_t _font[]; 63 | 64 | 65 | }; 66 | 67 | #endif /* IV22_H_ */ 68 | -------------------------------------------------------------------------------- /usart-rs485/usart-rs485.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * usart.cpp 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "usart-rs485.h" 9 | 10 | UsartRs485::UsartRs485(u8 sn, Gpio & de, 11 | Gpio & re, uint8_t buff_size, uint16_t time_out) : 12 | Usart(sn, buff_size), _de(de), _re(re), _time_out(time_out) { 13 | 14 | } 15 | 16 | UsartRs485::~UsartRs485() { 17 | 18 | } 19 | 20 | void UsartRs485::init(uint32_t baudrate, uint16_t word_length, 21 | uint16_t stop_bits, uint16_t parity, uint16_t mode, 22 | uint16_t hardware_flow_control) { 23 | 24 | this->Usart::init(baudrate, word_length, stop_bits, parity, mode, 25 | hardware_flow_control); 26 | 27 | _de.init(GPIO_Mode_Out_OD); 28 | _re.init(GPIO_Mode_Out_OD); 29 | 30 | _de.set(Bit_RESET); 31 | _re.set(Bit_RESET); 32 | } 33 | 34 | void UsartRs485::flush() { 35 | this->Usart::flush(); 36 | _re.set(Bit_RESET); 37 | _de.set(Bit_RESET); 38 | } 39 | 40 | void UsartRs485::onTXE() { 41 | _re.set(Bit_SET); 42 | _de.set(Bit_SET); 43 | this->Usart::onTXE(); 44 | } 45 | -------------------------------------------------------------------------------- /usart-rs485/usart-rs485.h: -------------------------------------------------------------------------------- 1 | /* 2 | * usart.h 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef USART_RS485_H_ 9 | #define USART_RS485_H_ 10 | 11 | #include "../usart/usart.h" 12 | #include "../gpio/gpio.h" 13 | 14 | #include 15 | 16 | class UsartRs485: public Usart { 17 | public: 18 | UsartRs485(u8 sn, 19 | Gpio & de, Gpio & re, 20 | uint8_t buff_size = 128, 21 | uint16_t time_out = 4); 22 | virtual ~UsartRs485(); 23 | 24 | void init(uint32_t baudrate = 9600, 25 | uint16_t word_length = USART_WordLength_8b, 26 | uint16_t stop_bits = USART_StopBits_1, 27 | uint16_t parity = USART_Parity_No, 28 | uint16_t mode = USART_Mode_Rx | USART_Mode_Tx, 29 | uint16_t hardware_flow_control = USART_HardwareFlowControl_None); 30 | 31 | void flush(); 32 | 33 | protected: 34 | void onTXE(); 35 | 36 | private: 37 | Gpio & _de; 38 | Gpio & _re; 39 | uint16_t _time_out; 40 | }; 41 | 42 | #endif /* USART_H_ */ 43 | -------------------------------------------------------------------------------- /usart/usart.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * usart.cpp 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #include "usart.h" 9 | 10 | Usart::Usart(u8 sn, u8 buff_size) : 11 | _buff_size(buff_size) { 12 | 13 | if (sn == 1) { 14 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 15 | _usart = USART1; 16 | } else { 17 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2 + (RCC_APB1Periph_USART3 - RCC_APB1Periph_USART2) * (sn - 2), ENABLE); 18 | _usart = (USART_TypeDef *) (USART2_BASE 19 | + (USART3_BASE - USART2_BASE) * (sn - 2)); 20 | } 21 | 22 | _tx_buff.index_write = 0; 23 | _tx_buff.index_read = 0; 24 | _tx_buff.buffer = (u16 *) malloc(sizeof(u16) * _buff_size); 25 | 26 | memset(_tx_buff.buffer, 0, _buff_size); 27 | 28 | _rx_buff.index_write = 0; 29 | _rx_buff.index_read = 0; 30 | _rx_buff.buffer = (u16 *) malloc(sizeof(u16) * _buff_size); 31 | 32 | memset(_rx_buff.buffer, 0, _buff_size); 33 | } 34 | 35 | Usart::~Usart() { 36 | free(_tx_buff.buffer); 37 | free(_rx_buff.buffer); 38 | } 39 | 40 | void Usart::init(uint32_t baudrate, u16 word_length, u16 stop_bits, u16 parity, 41 | u16 mode, u16 hardware_flow_control) { 42 | USART_InitTypeDef usart_init_type; 43 | usart_init_type.USART_BaudRate = baudrate; 44 | usart_init_type.USART_WordLength = word_length; 45 | usart_init_type.USART_StopBits = stop_bits; 46 | usart_init_type.USART_Parity = parity; 47 | usart_init_type.USART_Mode = mode; 48 | usart_init_type.USART_HardwareFlowControl = hardware_flow_control; 49 | 50 | USART_Init(_usart, &usart_init_type); 51 | 52 | USART_Cmd(_usart, ENABLE); 53 | USART_ITConfig(_usart, USART_IT_RXNE, ENABLE); 54 | } 55 | 56 | u8 Usart::available(void) { 57 | return (_buff_size + _rx_buff.index_write - _rx_buff.index_read) 58 | % _buff_size; 59 | } 60 | 61 | u8 Usart::cached(void) { 62 | return (_buff_size + _tx_buff.index_write - _tx_buff.index_read) 63 | % _buff_size; 64 | } 65 | 66 | int Usart::read(void) { 67 | if (_rx_buff.index_write != _rx_buff.index_read) { 68 | u16 c = _rx_buff.buffer[_rx_buff.index_read]; 69 | _rx_buff.index_read = (_rx_buff.index_read + 1) % _buff_size; 70 | return c; 71 | } 72 | return -1; 73 | } 74 | 75 | void Usart::flush() { 76 | while (_tx_buff.index_write != _tx_buff.index_read) 77 | ; 78 | 79 | while (USART_GetFlagStatus(_usart, USART_FLAG_TC) == RESET) 80 | ; 81 | } 82 | 83 | void Usart::write(u16 c) { 84 | volatile u8 i = (_tx_buff.index_write + 1) % _buff_size; 85 | while (i == _tx_buff.index_read) 86 | ; 87 | 88 | _tx_buff.buffer[_tx_buff.index_write] = c; 89 | _tx_buff.index_write = i; 90 | 91 | USART_ITConfig(_usart, USART_IT_TXE, ENABLE); 92 | } 93 | 94 | void Usart::onTXE() { 95 | 96 | USART_SendData(_usart, _tx_buff.buffer[_tx_buff.index_read]); 97 | _tx_buff.index_read = (_tx_buff.index_read + 1) % _buff_size; 98 | 99 | if (_tx_buff.index_read == _tx_buff.index_write) 100 | USART_ITConfig(_usart, USART_IT_TXE, DISABLE); 101 | } 102 | 103 | void Usart::onRXNE() { 104 | u8 i = (_rx_buff.index_write + 1) % _buff_size; 105 | 106 | // when buffer is full, next income would be ignored 107 | if (i != _rx_buff.index_read) { 108 | 109 | if (USART_GetFlagStatus(_usart, USART_FLAG_PE) 110 | || USART_GetFlagStatus(_usart, USART_FLAG_ORE) 111 | || USART_GetFlagStatus(_usart, USART_FLAG_FE) 112 | || USART_GetFlagStatus(_usart, USART_FLAG_NE)) { 113 | USART_ReceiveData(_usart); 114 | } else { 115 | _rx_buff.buffer[_rx_buff.index_write] = USART_ReceiveData(_usart); 116 | _rx_buff.index_write = i; 117 | } 118 | } 119 | } 120 | 121 | int Usart::timedRead(u8 timeout) { 122 | extern uint32_t millis; 123 | uint32_t start = millis; 124 | 125 | while (timeout) { 126 | int c = read(); 127 | if (c >= 0) 128 | return c; 129 | 130 | if (millis - start) { 131 | timeout--; 132 | start++; 133 | } 134 | } 135 | return -1; // -1 indicates timeout 136 | } 137 | 138 | void Usart::write(const u8 *p, uint32_t length) { 139 | while (length--) 140 | this->write(*p++); 141 | } 142 | 143 | int Usart::readBytes(u8 *buffer, int length, u8 timeout) { 144 | int index = 0; 145 | while (index < length) { 146 | int c = timedRead(timeout); 147 | if (c == -1) 148 | break; 149 | *buffer++ = (u8) c; 150 | index++; 151 | } 152 | return index; 153 | } 154 | 155 | // as readBytes with terminator character 156 | // terminates if length characters have been read, timeout, or if the terminator character detected 157 | // returns the number of characters placed in the buffer (0 means no valid data found) 158 | 159 | int Usart::readBytesUntil(char terminator, char *buffer, int length, u8 timeout) { 160 | 161 | int index = 0; 162 | while (index < length) { 163 | int c = timedRead(timeout); 164 | if (c == -1) 165 | return -1; 166 | if (c == terminator) 167 | break; 168 | *buffer++ = (char) c; 169 | index++; 170 | } 171 | return index; // return number of characters, not including null terminator 172 | } 173 | 174 | void Usart::ithandler() { 175 | if (USART_GetITStatus(_usart, USART_IT_TXE)) 176 | this->onTXE(); 177 | if (USART_GetITStatus(_usart, USART_IT_RXNE)) 178 | this->onRXNE(); 179 | } 180 | 181 | ITStatus Usart::getInterruptStatus(uint16_t interrupt) { 182 | return USART_GetITStatus(_usart, interrupt); 183 | } 184 | -------------------------------------------------------------------------------- /usart/usart.h: -------------------------------------------------------------------------------- 1 | /* 2 | * usart.h 3 | * 4 | * Created on: May 28, 2013 5 | * Author: agu 6 | */ 7 | 8 | #ifndef USART_H_ 9 | #define USART_H_ 10 | 11 | #include "stm32f10x_usart.h" 12 | #include 13 | #include 14 | 15 | #ifndef RING_BUFF 16 | #define RING_BUFF 17 | struct ring_buff { 18 | uint16_t *buffer; 19 | volatile uint8_t index_write; // to receive the incoming byte 20 | volatile uint8_t index_read; // to send byte 21 | }; 22 | #endif 23 | 24 | class Usart { 25 | public: 26 | Usart(u8 sn, u8 buff_size = 128); 27 | virtual ~Usart(); 28 | 29 | void init(uint32_t baudrate = 9600, 30 | u16 word_length = USART_WordLength_8b, 31 | u16 stop_bits = USART_StopBits_1, 32 | u16 parity = USART_Parity_No, 33 | u16 mode = USART_Mode_Rx | USART_Mode_Tx, 34 | u16 hardware_flow_control = USART_HardwareFlowControl_None); 35 | 36 | u8 available(void); 37 | u8 cached(void); 38 | 39 | virtual void flush(); 40 | void write(u16 c); 41 | int read(void); 42 | 43 | int timedRead(u8 timeout=4); 44 | 45 | void ithandler(); 46 | 47 | void write(const u8 * p, uint32_t length); 48 | 49 | int readBytes(u8 *buffer, int length, u8 timeout=4); 50 | int readBytesUntil(char terminator, char *buffer, int length, u8 timeout=4); 51 | 52 | void onTXE(); 53 | void onRXNE(); 54 | ITStatus getInterruptStatus(uint16_t interrupt); 55 | 56 | private: 57 | USART_TypeDef * _usart; 58 | 59 | ring_buff _tx_buff; 60 | ring_buff _rx_buff; 61 | const u8 _buff_size; 62 | }; 63 | 64 | #endif 65 | --------------------------------------------------------------------------------