Merge pull request #8 from rogerclarkmelbourne/master
Synching to Roger's
This commit is contained in:
commit
266ab9f0cb
|
@ -0,0 +1,74 @@
|
|||
# GD32 Boards
|
||||
|
||||
|
||||
menu.device_variant=Variant
|
||||
menu.bootloader_version=Bootloader version
|
||||
menu.upload_method=Upload method
|
||||
menu.cpu_speed=CPU Speed(MHz)
|
||||
|
||||
|
||||
###################### Generic GD32F103C ########################################
|
||||
|
||||
genericGD32F103C.name=Generic GD32F103C series
|
||||
genericGD32F103C.build.variant=generic_GD32f103c
|
||||
genericGD32F103C.build.vect=VECT_TAB_ADDR=0x8000000
|
||||
genericGD32F103C.build.core=maple
|
||||
genericGD32F103C.build.board=GENERIC_GD32F103C
|
||||
genericGD32F103C.upload.use_1200bps_touch=false
|
||||
genericGD32F103C.upload.file_type=bin
|
||||
genericGD32F103C.upload.auto_reset=true
|
||||
genericGD32F103C.build.cpu_flags=-DMCU_STM32F103CB
|
||||
genericGD32F103C.build.f_cpu=72000000L
|
||||
|
||||
## GD32F103CB -------------------------
|
||||
genericGD32F103C.menu.device_variant.GD32F103CB=GD32F103CB (20k RAM. 128k Flash)
|
||||
genericGD32F103C.menu.device_variant.GD32F103CB.build.ldscript=ld/jtag.ld
|
||||
genericGD32F103C.menu.device_variant.GD32F103CB.upload.maximum_size=131072
|
||||
genericGD32F103C.menu.device_variant.GD32F103CB.upload.ram.maximum_size=20480
|
||||
genericGD32F103C.menu.device_variant.GD32F103CB.upload.flash.maximum_size=131072
|
||||
|
||||
|
||||
## GD32F103C8 -------------------------
|
||||
genericGD32F103C.menu.device_variant.GD32F103C8=GD32F103C8 (20k RAM. 64k Flash)
|
||||
genericGD32F103C.menu.device_variant.GD32F103C8.build.ldscript=ld/jtag_c8.ld
|
||||
genericGD32F103C.menu.device_variant.GD32F103C8.upload.maximum_size=65536
|
||||
genericGD32F103C.menu.device_variant.GD32F103C8.upload.ram.maximum_size=20480
|
||||
genericGD32F103C.menu.device_variant.GD32F103C8.upload.flash.maximum_size=65536
|
||||
|
||||
#---------------------------- UPLOAD METHODS ---------------------------
|
||||
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod=GD32duino bootloader
|
||||
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.build.ldscript=ld/bootloader_20.ld
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003
|
||||
genericGD32F103C.menu.upload_method.DFUUploadMethod.upload.altID=2
|
||||
|
||||
genericGD32F103C.menu.upload_method.serialMethod=Serial
|
||||
genericGD32F103C.menu.upload_method.serialMethod.upload.protocol=maple_serial
|
||||
genericGD32F103C.menu.upload_method.serialMethod.upload.tool=serial_upload
|
||||
|
||||
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod=STLink
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod.upload.protocol=STLink
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod.upload.tool=stlink_upload
|
||||
genericGD32F103C.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER
|
||||
|
||||
|
||||
genericGD32F103C.menu.upload_method.BMPMethod=BMP (Black Magic Probe)
|
||||
genericGD32F103C.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp
|
||||
genericGD32F103C.menu.upload_method.BMPMethod.upload.tool=bmp_upload
|
||||
genericGD32F103C.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG
|
||||
|
||||
genericGD32F103C.menu.cpu_speed.speed_120mhz=120Mhz (overdrive)
|
||||
genericGD32F103C.menu.cpu_speed.speed_120mhz.build.f_cpu=120000000L
|
||||
|
||||
genericGD32F103C.menu.cpu_speed.speed_96mhz=96Mhz (Stable)
|
||||
genericGD32F103C.menu.cpu_speed.speed_96mhz.build.f_cpu=96000000L
|
||||
|
||||
genericGD32F103C.menu.cpu_speed.speed_72mhz=72Mhz (compatibility)
|
||||
genericGD32F103C.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _WIRISH_WPROGRAM_H_
|
||||
#define _WIRISH_WPROGRAM_H_
|
||||
|
||||
#include "wirish.h"
|
||||
|
||||
void setup();
|
||||
void loop();
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif // __cplusplus
|
||||
void yield(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "variant.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,197 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/HardwareSerial.cpp
|
||||
* @brief Wirish serial port implementation.
|
||||
*/
|
||||
|
||||
#include "HardwareSerial.h"
|
||||
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/timer.h>
|
||||
#include <libmaple/usart.h>
|
||||
|
||||
#if 0
|
||||
|
||||
#define DEFINE_HWSERIAL(name, n) \
|
||||
HardwareSerial name(USART##n, \
|
||||
BOARD_USART##n##_TX_PIN, \
|
||||
BOARD_USART##n##_RX_PIN)
|
||||
|
||||
#define DEFINE_HWSERIAL_UART(name, n) \
|
||||
HardwareSerial name(UART##n, \
|
||||
BOARD_USART##n##_TX_PIN, \
|
||||
BOARD_USART##n##_RX_PIN)
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#if BOARD_HAVE_USART1
|
||||
DEFINE_HWSERIAL(Serial1, 1);
|
||||
#endif
|
||||
#if BOARD_HAVE_USART2
|
||||
DEFINE_HWSERIAL(Serial2, 2);
|
||||
#endif
|
||||
#if BOARD_HAVE_USART3
|
||||
DEFINE_HWSERIAL(Serial3, 3);
|
||||
#endif
|
||||
#if BOARD_HAVE_UART4
|
||||
DEFINE_HWSERIAL_UART(Serial4, 4);
|
||||
#endif
|
||||
#if BOARD_HAVE_UART5
|
||||
DEFINE_HWSERIAL_UART(Serial5, 5);
|
||||
#endif
|
||||
#if BOARD_HAVE_USART6
|
||||
DEFINE_HWSERIAL_UART(Serial6, 6);
|
||||
#endif
|
||||
#else
|
||||
#if BOARD_HAVE_USART1
|
||||
DEFINE_HWSERIAL(Serial, 1);
|
||||
#endif
|
||||
#if BOARD_HAVE_USART2
|
||||
DEFINE_HWSERIAL(Serial1, 2);
|
||||
#endif
|
||||
#if BOARD_HAVE_USART3
|
||||
DEFINE_HWSERIAL(Serial2, 3);
|
||||
#endif
|
||||
#if BOARD_HAVE_UART4
|
||||
DEFINE_HWSERIAL_UART(Serial3, 4);
|
||||
#endif
|
||||
#if BOARD_HAVE_UART5
|
||||
DEFINE_HWSERIAL_UART(Serial4, 5);
|
||||
#endif
|
||||
#if BOARD_HAVE_USART6
|
||||
DEFINE_HWSERIAL_UART(Serial5, 6);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
HardwareSerial::HardwareSerial(usart_dev *usart_device,
|
||||
uint8 tx_pin,
|
||||
uint8 rx_pin) {
|
||||
this->usart_device = usart_device;
|
||||
this->tx_pin = tx_pin;
|
||||
this->rx_pin = rx_pin;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up/tear down
|
||||
*/
|
||||
|
||||
#if STM32_MCU_SERIES == STM32_SERIES_F1
|
||||
/* F1 MCUs have no GPIO_AFR[HL], so turn off PWM if there's a conflict
|
||||
* on this GPIO bit. */
|
||||
static void disable_timer_if_necessary(timer_dev *dev, uint8 ch) {
|
||||
if (dev != NULL) {
|
||||
timer_set_mode(dev, ch, TIMER_DISABLED);
|
||||
}
|
||||
}
|
||||
#elif (STM32_MCU_SERIES == STM32_SERIES_F2) || \
|
||||
(STM32_MCU_SERIES == STM32_SERIES_F4)
|
||||
#define disable_timer_if_necessary(dev, ch) ((void)0)
|
||||
#else
|
||||
#warning "Unsupported STM32 series; timer conflicts are possible"
|
||||
#endif
|
||||
|
||||
void HardwareSerial::begin(uint32 baud)
|
||||
{
|
||||
begin(baud,SERIAL_8N1);
|
||||
}
|
||||
/*
|
||||
* Roger Clark.
|
||||
* Note. The config parameter is not currently used. This is a work in progress.
|
||||
* Code needs to be written to set the config of the hardware serial control register in question.
|
||||
*
|
||||
*/
|
||||
|
||||
void HardwareSerial::begin(uint32 baud, uint8_t config)
|
||||
{
|
||||
// ASSERT(baud <= this->usart_device->max_baud);// Roger Clark. Assert doesn't do anything useful, we may as well save the space in flash and ram etc
|
||||
|
||||
if (baud > this->usart_device->max_baud) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stm32_pin_info *txi = &PIN_MAP[this->tx_pin];
|
||||
const stm32_pin_info *rxi = &PIN_MAP[this->rx_pin];
|
||||
|
||||
disable_timer_if_necessary(txi->timer_device, txi->timer_channel);
|
||||
|
||||
usart_config_gpios_async(this->usart_device,
|
||||
rxi->gpio_device, rxi->gpio_bit,
|
||||
txi->gpio_device, txi->gpio_bit,
|
||||
config);
|
||||
usart_init(this->usart_device);
|
||||
usart_set_baud_rate(this->usart_device, USART_USE_PCLK, baud);
|
||||
usart_enable(this->usart_device);
|
||||
}
|
||||
|
||||
void HardwareSerial::end(void) {
|
||||
usart_disable(this->usart_device);
|
||||
}
|
||||
|
||||
/*
|
||||
* I/O
|
||||
*/
|
||||
|
||||
int HardwareSerial::read(void) {
|
||||
// Block until a byte becomes available, to save user confusion.
|
||||
while (!this->available())
|
||||
;
|
||||
return usart_getc(this->usart_device);
|
||||
}
|
||||
|
||||
int HardwareSerial::available(void) {
|
||||
return usart_data_available(this->usart_device);
|
||||
}
|
||||
|
||||
/* Roger Clark. Added function missing from LibMaple code */
|
||||
|
||||
int HardwareSerial::peek(void)
|
||||
{
|
||||
return usart_peek(this->usart_device);
|
||||
}
|
||||
|
||||
int HardwareSerial::availableForWrite(void)
|
||||
{
|
||||
/* Roger Clark.
|
||||
* Currently there isn't an output ring buffer, chars are sent straight to the hardware.
|
||||
* so just return 1, meaning that 1 char can be written
|
||||
* This will be slower than a ring buffer implementation, but it should at least work !
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t HardwareSerial::write(unsigned char ch) {
|
||||
|
||||
usart_putc(this->usart_device, ch);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void HardwareSerial::flush(void) {
|
||||
usart_reset_rx(this->usart_device);
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/HardwareSerial.h
|
||||
* @brief Wirish serial port interface.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_HARDWARESERIAL_H_
|
||||
#define _WIRISH_HARDWARESERIAL_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
|
||||
#include "Print.h"
|
||||
#include "boards.h"
|
||||
#include "Stream.h"
|
||||
/*
|
||||
* IMPORTANT:
|
||||
*
|
||||
* This class documented "by hand" (i.e., not using Doxygen) in the
|
||||
* leaflabs-docs/ repository.
|
||||
*
|
||||
* If you alter the public HardwareSerial interface, you MUST update
|
||||
* the documentation accordingly.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// Define constants and variables for buffering incoming serial data. We're
|
||||
// using a ring buffer (I think), in which head is the index of the location
|
||||
// to which to write the next incoming character and tail is the index of the
|
||||
// location from which to read.
|
||||
#if !(defined(SERIAL_TX_BUFFER_SIZE) && defined(SERIAL_RX_BUFFER_SIZE))
|
||||
#if (RAMEND < 1000)
|
||||
#define SERIAL_TX_BUFFER_SIZE 16
|
||||
#define SERIAL_RX_BUFFER_SIZE 16
|
||||
#else
|
||||
#define SERIAL_TX_BUFFER_SIZE 64
|
||||
#define SERIAL_RX_BUFFER_SIZE 64
|
||||
#endif
|
||||
#endif
|
||||
#if (SERIAL_TX_BUFFER_SIZE>256)
|
||||
typedef uint16_t tx_buffer_index_t;
|
||||
#else
|
||||
typedef uint8_t tx_buffer_index_t;
|
||||
#endif
|
||||
#if (SERIAL_RX_BUFFER_SIZE>256)
|
||||
typedef uint16_t rx_buffer_index_t;
|
||||
#else
|
||||
typedef uint8_t rx_buffer_index_t;
|
||||
#endif
|
||||
|
||||
struct usart_dev;
|
||||
|
||||
/* Roger Clark
|
||||
*
|
||||
* Added config defines from AVR
|
||||
* Note. The values will need to be changed to match STM32 USART config register values, these are just place holders.
|
||||
*/
|
||||
// Define config for Serial.begin(baud, config);
|
||||
// Note. STM32 doesn't support as many different Serial modes as AVR or SAM cores.
|
||||
|
||||
#define SERIAL_8N1 0B00000000
|
||||
#define SERIAL_8N2 0B00100000
|
||||
#define SERIAL_9N1 0B00001000
|
||||
#define SERIAL_9N2 0B00101000
|
||||
|
||||
#define SERIAL_8E1 0B00000010
|
||||
#define SERIAL_8E2 0B00100010
|
||||
#define SERIAL_9E1 0B00001010
|
||||
#define SERIAL_9E2 0B00101010
|
||||
|
||||
#define SERIAL_8O1 0B00000011
|
||||
#define SERIAL_8O2 0B00100011
|
||||
#define SERIAL_9O1 0B00001011
|
||||
#define SERIAL_9O2 0B00101011
|
||||
|
||||
|
||||
/* Roger Clark
|
||||
* Moved macros from hardwareSerial.cpp
|
||||
*/
|
||||
|
||||
#define DEFINE_HWSERIAL(name, n) \
|
||||
HardwareSerial name(USART##n, \
|
||||
BOARD_USART##n##_TX_PIN, \
|
||||
BOARD_USART##n##_RX_PIN)
|
||||
|
||||
#define DEFINE_HWSERIAL_UART(name, n) \
|
||||
HardwareSerial name(UART##n, \
|
||||
BOARD_USART##n##_TX_PIN, \
|
||||
BOARD_USART##n##_RX_PIN)
|
||||
|
||||
|
||||
/* Roger clark. Changed class inheritance from Print to Stream.
|
||||
* Also added new functions for peek() and availableForWrite()
|
||||
* Note. AvailableForWrite is only a stub function in the cpp
|
||||
*/
|
||||
class HardwareSerial : public Stream {
|
||||
|
||||
public:
|
||||
HardwareSerial(struct usart_dev *usart_device,
|
||||
uint8 tx_pin,
|
||||
uint8 rx_pin);
|
||||
|
||||
/* Set up/tear down */
|
||||
void begin(uint32 baud);
|
||||
void begin(uint32 baud,uint8_t config);
|
||||
void end();
|
||||
virtual int available(void);
|
||||
virtual int peek(void);
|
||||
virtual int read(void);
|
||||
int availableForWrite(void);
|
||||
virtual void flush(void);
|
||||
virtual size_t write(uint8_t);
|
||||
inline size_t write(unsigned long n) { return write((uint8_t)n); }
|
||||
inline size_t write(long n) { return write((uint8_t)n); }
|
||||
inline size_t write(unsigned int n) { return write((uint8_t)n); }
|
||||
inline size_t write(int n) { return write((uint8_t)n); }
|
||||
using Print::write;
|
||||
|
||||
/* Pin accessors */
|
||||
int txPin(void) { return this->tx_pin; }
|
||||
int rxPin(void) { return this->rx_pin; }
|
||||
|
||||
operator bool() { return true; }
|
||||
|
||||
/* Escape hatch into libmaple */
|
||||
/* FIXME [0.0.13] documentation */
|
||||
struct usart_dev* c_dev(void) { return this->usart_device; }
|
||||
private:
|
||||
struct usart_dev *usart_device;
|
||||
uint8 tx_pin;
|
||||
uint8 rx_pin;
|
||||
protected:
|
||||
#if 0
|
||||
volatile uint8_t * const _ubrrh;
|
||||
volatile uint8_t * const _ubrrl;
|
||||
volatile uint8_t * const _ucsra;
|
||||
volatile uint8_t * const _ucsrb;
|
||||
volatile uint8_t * const _ucsrc;
|
||||
volatile uint8_t * const _udr;
|
||||
// Has any byte been written to the UART since begin()
|
||||
bool _written;
|
||||
|
||||
volatile rx_buffer_index_t _rx_buffer_head;
|
||||
volatile rx_buffer_index_t _rx_buffer_tail;
|
||||
volatile tx_buffer_index_t _tx_buffer_head;
|
||||
volatile tx_buffer_index_t _tx_buffer_tail;
|
||||
// Don't put any members after these buffers, since only the first
|
||||
// 32 bytes of this struct can be accessed quickly using the ldd
|
||||
// instruction.
|
||||
unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE];
|
||||
unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE];
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
#if BOARD_HAVE_USART1
|
||||
extern HardwareSerial Serial1;
|
||||
#endif
|
||||
#if BOARD_HAVE_USART2
|
||||
extern HardwareSerial Serial2;
|
||||
#endif
|
||||
#if BOARD_HAVE_USART3
|
||||
extern HardwareSerial Serial3;
|
||||
#endif
|
||||
#if BOARD_HAVE_UART4
|
||||
extern HardwareSerial Serial4;
|
||||
#endif
|
||||
#if BOARD_HAVE_UART5
|
||||
extern HardwareSerial Serial5;
|
||||
#endif
|
||||
#if BOARD_HAVE_USART6
|
||||
extern HardwareSerial Serial6;
|
||||
#endif
|
||||
#else
|
||||
#if BOARD_HAVE_USART1
|
||||
extern HardwareSerial Serial;
|
||||
#endif
|
||||
#if BOARD_HAVE_USART2
|
||||
extern HardwareSerial Serial1;
|
||||
#endif
|
||||
#if BOARD_HAVE_USART3
|
||||
extern HardwareSerial Serial2;
|
||||
#endif
|
||||
#if BOARD_HAVE_UART4
|
||||
extern HardwareSerial Serial3;
|
||||
#endif
|
||||
#if BOARD_HAVE_UART5
|
||||
extern HardwareSerial Serial4;
|
||||
#endif
|
||||
#if BOARD_HAVE_USART6
|
||||
extern HardwareSerial Serial5;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,156 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Bryan Newbold.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "HardwareTimer.h"
|
||||
|
||||
#include <libmaple/rcc.h>
|
||||
#include "ext_interrupts.h" // for noInterrupts(), interrupts()
|
||||
#include "wirish_math.h"
|
||||
#include <board/board.h> // for CYCLES_PER_MICROSECOND
|
||||
|
||||
// TODO [0.1.0] Remove deprecated pieces
|
||||
|
||||
/*
|
||||
* Evil hack to infer this->dev from timerNum in the HardwareTimer
|
||||
* constructor. See:
|
||||
*
|
||||
* http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.2
|
||||
* http://yosefk.com/c++fqa/function.html#fqa-33.2
|
||||
*/
|
||||
|
||||
extern "C" {
|
||||
static timer_dev **this_devp;
|
||||
static rcc_clk_id this_id;
|
||||
static void set_this_dev(timer_dev *dev) {
|
||||
if (dev->clk_id == this_id) {
|
||||
*this_devp = dev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HardwareTimer routines
|
||||
*/
|
||||
|
||||
HardwareTimer::HardwareTimer(uint8 timerNum) {
|
||||
rcc_clk_id timerID = (rcc_clk_id)(RCC_TIMER1 + (timerNum - 1));
|
||||
this->dev = NULL;
|
||||
noInterrupts(); // Hack to ensure we're the only ones using
|
||||
// set_this_dev() and friends. TODO: use a lock.
|
||||
this_id = timerID;
|
||||
this_devp = &this->dev;
|
||||
timer_foreach(set_this_dev);
|
||||
interrupts();
|
||||
ASSERT(this->dev != NULL);
|
||||
}
|
||||
|
||||
void HardwareTimer::pause(void) {
|
||||
timer_pause(this->dev);
|
||||
}
|
||||
|
||||
void HardwareTimer::resume(void) {
|
||||
timer_resume(this->dev);
|
||||
}
|
||||
|
||||
uint32 HardwareTimer::getPrescaleFactor(void) {
|
||||
return timer_get_prescaler(this->dev) + 1;
|
||||
}
|
||||
|
||||
void HardwareTimer::setPrescaleFactor(uint32 factor) {
|
||||
timer_set_prescaler(this->dev, (uint16)(factor - 1));
|
||||
}
|
||||
|
||||
uint16 HardwareTimer::getOverflow() {
|
||||
return timer_get_reload(this->dev);
|
||||
}
|
||||
|
||||
void HardwareTimer::setOverflow(uint16 val) {
|
||||
timer_set_reload(this->dev, val);
|
||||
}
|
||||
|
||||
uint16 HardwareTimer::getCount(void) {
|
||||
return timer_get_count(this->dev);
|
||||
}
|
||||
|
||||
void HardwareTimer::setCount(uint16 val) {
|
||||
uint16 ovf = this->getOverflow();
|
||||
timer_set_count(this->dev, min(val, ovf));
|
||||
}
|
||||
|
||||
#define MAX_RELOAD ((1 << 16) - 1)
|
||||
uint16 HardwareTimer::setPeriod(uint32 microseconds) {
|
||||
// Not the best way to handle this edge case?
|
||||
if (!microseconds) {
|
||||
this->setPrescaleFactor(1);
|
||||
this->setOverflow(1);
|
||||
return this->getOverflow();
|
||||
}
|
||||
|
||||
uint32 period_cyc = microseconds * CYCLES_PER_MICROSECOND;
|
||||
uint16 prescaler = (uint16)(period_cyc / MAX_RELOAD + 1);
|
||||
uint16 overflow = (uint16)((period_cyc + (prescaler / 2)) / prescaler);
|
||||
this->setPrescaleFactor(prescaler);
|
||||
this->setOverflow(overflow);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
void HardwareTimer::setMode(int channel, timer_mode mode) {
|
||||
timer_set_mode(this->dev, (uint8)channel, (timer_mode)mode);
|
||||
}
|
||||
|
||||
uint16 HardwareTimer::getCompare(int channel) {
|
||||
return timer_get_compare(this->dev, (uint8)channel);
|
||||
}
|
||||
|
||||
void HardwareTimer::setCompare(int channel, uint16 val) {
|
||||
uint16 ovf = this->getOverflow();
|
||||
timer_set_compare(this->dev, (uint8)channel, min(val, ovf));
|
||||
}
|
||||
|
||||
void HardwareTimer::attachInterrupt(int channel, voidFuncPtr handler) {
|
||||
timer_attach_interrupt(this->dev, (uint8)channel, handler);
|
||||
}
|
||||
|
||||
void HardwareTimer::detachInterrupt(int channel) {
|
||||
timer_detach_interrupt(this->dev, (uint8)channel);
|
||||
}
|
||||
|
||||
void HardwareTimer::refresh(void) {
|
||||
timer_generate_update(this->dev);
|
||||
}
|
||||
|
||||
/* -- Deprecated predefined instances -------------------------------------- */
|
||||
|
||||
HardwareTimer Timer1(1);
|
||||
HardwareTimer Timer2(2);
|
||||
HardwareTimer Timer3(3);
|
||||
HardwareTimer Timer4(4);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
HardwareTimer Timer5(5);
|
||||
HardwareTimer Timer6(6);
|
||||
HardwareTimer Timer7(7);
|
||||
HardwareTimer Timer8(8);
|
||||
#endif
|
|
@ -0,0 +1,337 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Bryan Newbold.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Wirish timer class.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_HARDWARETIMER_H_
|
||||
#define _WIRISH_HARDWARETIMER_H_
|
||||
|
||||
// TODO [0.1.0] Remove deprecated pieces, pick a better API
|
||||
|
||||
#include <libmaple/timer.h>
|
||||
|
||||
/** Timer mode. */
|
||||
typedef timer_mode TimerMode;
|
||||
|
||||
/**
|
||||
* @brief Interface to one of the 16-bit timer peripherals.
|
||||
*/
|
||||
class HardwareTimer {
|
||||
private:
|
||||
timer_dev *dev;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new HardwareTimer instance.
|
||||
* @param timerNum number of the timer to control.
|
||||
*/
|
||||
HardwareTimer(uint8 timerNum);
|
||||
|
||||
/**
|
||||
* @brief Stop the counter, without affecting its configuration.
|
||||
*
|
||||
* @see HardwareTimer::resume()
|
||||
*/
|
||||
void pause(void);
|
||||
|
||||
/**
|
||||
* @brief Resume a paused timer, without affecting its configuration.
|
||||
*
|
||||
* The timer will resume counting and firing interrupts as
|
||||
* appropriate.
|
||||
*
|
||||
* Note that there is some function call overhead associated with
|
||||
* using this method, so using it in concert with
|
||||
* HardwareTimer::pause() is not a robust way to align multiple
|
||||
* timers to the same count value.
|
||||
*
|
||||
* @see HardwareTimer::pause()
|
||||
*/
|
||||
void resume(void);
|
||||
|
||||
/**
|
||||
* @brief Get the timer's prescale factor.
|
||||
* @return Timer prescaler, from 1 to 65,536.
|
||||
* @see HardwareTimer::setPrescaleFactor()
|
||||
*/
|
||||
uint32 getPrescaleFactor();
|
||||
|
||||
/**
|
||||
* @brief Set the timer's prescale factor.
|
||||
*
|
||||
* The new value won't take effect until the next time the counter
|
||||
* overflows. You can force the counter to reset using
|
||||
* HardwareTimer::refresh().
|
||||
*
|
||||
* @param factor The new prescale value to set, from 1 to 65,536.
|
||||
* @see HardwareTimer::refresh()
|
||||
*/
|
||||
void setPrescaleFactor(uint32 factor);
|
||||
|
||||
/**
|
||||
* @brief Get the timer overflow value.
|
||||
* @see HardwareTimer::setOverflow()
|
||||
*/
|
||||
uint16 getOverflow();
|
||||
|
||||
/**
|
||||
* @brief Set the timer overflow (or "reload") value.
|
||||
*
|
||||
* The new value won't take effect until the next time the counter
|
||||
* overflows. You can force the counter to reset using
|
||||
* HardwareTimer::refresh().
|
||||
*
|
||||
* @param val The new overflow value to set
|
||||
* @see HardwareTimer::refresh()
|
||||
*/
|
||||
void setOverflow(uint16 val);
|
||||
|
||||
/**
|
||||
* @brief Get the current timer count.
|
||||
*
|
||||
* @return The timer's current count value
|
||||
*/
|
||||
uint16 getCount(void);
|
||||
|
||||
/**
|
||||
* @brief Set the current timer count.
|
||||
*
|
||||
* @param val The new count value to set. If this value exceeds
|
||||
* the timer's overflow value, it is truncated to the
|
||||
* overflow value.
|
||||
*/
|
||||
void setCount(uint16 val);
|
||||
|
||||
/**
|
||||
* @brief Set the timer's period in microseconds.
|
||||
*
|
||||
* Configures the prescaler and overflow values to generate a timer
|
||||
* reload with a period as close to the given number of
|
||||
* microseconds as possible.
|
||||
*
|
||||
* @param microseconds The desired period of the timer. This must be
|
||||
* greater than zero.
|
||||
* @return The new overflow value.
|
||||
*/
|
||||
uint16 setPeriod(uint32 microseconds);
|
||||
|
||||
/**
|
||||
* @brief Configure a timer channel's mode.
|
||||
* @param channel Timer channel, from 1 to 4
|
||||
* @param mode Mode to set
|
||||
*/
|
||||
void setMode(int channel, timer_mode mode);
|
||||
|
||||
/**
|
||||
* @brief Get the compare value for the given channel.
|
||||
* @see HardwareTimer::setCompare()
|
||||
*/
|
||||
uint16 getCompare(int channel);
|
||||
|
||||
/**
|
||||
* @brief Set the compare value for the given channel.
|
||||
*
|
||||
* @param channel the channel whose compare to set, from 1 to 4.
|
||||
* @param compare The compare value to set. If greater than this
|
||||
* timer's overflow value, it will be truncated to
|
||||
* the overflow value.
|
||||
*
|
||||
* @see timer_mode
|
||||
* @see HardwareTimer::setMode()
|
||||
* @see HardwareTimer::attachInterrupt()
|
||||
*/
|
||||
void setCompare(int channel, uint16 compare);
|
||||
|
||||
/**
|
||||
* @brief Attach an interrupt handler to the given channel.
|
||||
*
|
||||
* This interrupt handler will be called when the timer's counter
|
||||
* reaches the given channel compare value.
|
||||
*
|
||||
* @param channel the channel to attach the ISR to, from 1 to 4.
|
||||
* @param handler The ISR to attach to the given channel.
|
||||
* @see voidFuncPtr
|
||||
*/
|
||||
void attachInterrupt(int channel, voidFuncPtr handler);
|
||||
|
||||
/**
|
||||
* @brief Remove the interrupt handler attached to the given
|
||||
* channel, if any.
|
||||
*
|
||||
* The handler will no longer be called by this timer.
|
||||
*
|
||||
* @param channel the channel whose interrupt to detach, from 1 to 4.
|
||||
* @see HardwareTimer::attachInterrupt()
|
||||
*/
|
||||
void detachInterrupt(int channel);
|
||||
|
||||
/**
|
||||
* @brief Reset the counter, and update the prescaler and overflow
|
||||
* values.
|
||||
*
|
||||
* This will reset the counter to 0 in upcounting mode (the
|
||||
* default). It will also update the timer's prescaler and
|
||||
* overflow, if you have set them up to be changed using
|
||||
* HardwareTimer::setPrescaleFactor() or
|
||||
* HardwareTimer::setOverflow().
|
||||
*
|
||||
* @see HardwareTimer::setPrescaleFactor()
|
||||
* @see HardwareTimer::setOverflow()
|
||||
*/
|
||||
void refresh(void);
|
||||
|
||||
/* Escape hatch */
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the underlying libmaple timer_dev for
|
||||
* this HardwareTimer instance.
|
||||
*/
|
||||
timer_dev* c_dev(void) { return this->dev; }
|
||||
|
||||
/* -- The rest of this file is deprecated. --------------------------------- */
|
||||
|
||||
/** @brief Deprecated; use setMode(channel, mode) instead. */
|
||||
void setChannelMode(int channel, timer_mode mode) {
|
||||
setMode(channel, mode);
|
||||
}
|
||||
|
||||
/** @brief Deprecated; use setMode(TIMER_CH1, mode) instead. */
|
||||
void setChannel1Mode(timer_mode mode) { setMode(TIMER_CH1, mode); }
|
||||
|
||||
/** @brief Deprecated; use setMode(TIMER_CH2, mode) instead. */
|
||||
void setChannel2Mode(timer_mode mode) { setMode(TIMER_CH2, mode); }
|
||||
|
||||
/** @brief Deprecated; use setMode(TIMER_CH3, mode) instead. */
|
||||
void setChannel3Mode(timer_mode mode) { setMode(TIMER_CH3, mode); }
|
||||
|
||||
/** @brief Deprecated; use setMode(TIMER_CH4, mode) instead. */
|
||||
void setChannel4Mode(timer_mode mode) { setMode(TIMER_CH4, mode); }
|
||||
|
||||
/** @brief Deprecated; use return getCompare(TIMER_CH1) instead. */
|
||||
uint16 getCompare1() { return getCompare(TIMER_CH1); }
|
||||
|
||||
/** @brief Deprecated; use return getCompare(TIMER_CH2) instead. */
|
||||
uint16 getCompare2() { return getCompare(TIMER_CH2); }
|
||||
|
||||
/** @brief Deprecated; use return getCompare(TIMER_CH3) instead. */
|
||||
uint16 getCompare3() { return getCompare(TIMER_CH3); }
|
||||
|
||||
/** @brief Deprecated; use return getCompare(TIMER_CH4) instead. */
|
||||
uint16 getCompare4() { return getCompare(TIMER_CH4); }
|
||||
|
||||
/** @brief Deprecated; use setCompare(TIMER_CH1, compare) instead. */
|
||||
void setCompare1(uint16 compare) { setCompare(TIMER_CH1, compare); }
|
||||
|
||||
/** @brief Deprecated; use setCompare(TIMER_CH2, compare) instead. */
|
||||
void setCompare2(uint16 compare) { setCompare(TIMER_CH2, compare); }
|
||||
|
||||
/** @brief Deprecated; use setCompare(TIMER_CH3, compare) instead. */
|
||||
void setCompare3(uint16 compare) { setCompare(TIMER_CH3, compare); }
|
||||
|
||||
/** @brief Deprecated; use setCompare(TIMER_CH4, compare) instead. */
|
||||
void setCompare4(uint16 compare) { setCompare(TIMER_CH4, compare); }
|
||||
|
||||
/** @brief Deprecated; use attachInterrupt(TIMER_CH1, handler) instead. */
|
||||
void attachCompare1Interrupt(voidFuncPtr handler) {
|
||||
attachInterrupt(TIMER_CH1, handler);
|
||||
}
|
||||
|
||||
/** @brief Deprecated; use attachInterrupt(TIMER_CH2, handler) instead. */
|
||||
void attachCompare2Interrupt(voidFuncPtr handler) {
|
||||
attachInterrupt(TIMER_CH2, handler);
|
||||
}
|
||||
|
||||
/** @brief Deprecated; use attachInterrupt(TIMER_CH3, handler) instead. */
|
||||
void attachCompare3Interrupt(voidFuncPtr handler) {
|
||||
attachInterrupt(TIMER_CH3, handler);
|
||||
}
|
||||
|
||||
/** @brief Deprecated; use attachInterrupt(TIMER_CH4, handler) instead. */
|
||||
void attachCompare4Interrupt(voidFuncPtr handler) {
|
||||
attachInterrupt(TIMER_CH4, handler);
|
||||
}
|
||||
|
||||
/** @brief Deprecated; use detachInterrupt(TIMER_CH1) instead. */
|
||||
void detachCompare1Interrupt(void) { detachInterrupt(TIMER_CH1); }
|
||||
|
||||
/** @brief Deprecated; use detachInterrupt(TIMER_CH2) instead. */
|
||||
void detachCompare2Interrupt(void) { detachInterrupt(TIMER_CH2); }
|
||||
|
||||
/** @brief Deprecated; use detachInterrupt(TIMER_CH3) instead. */
|
||||
void detachCompare3Interrupt(void) { detachInterrupt(TIMER_CH3); }
|
||||
|
||||
/** @brief Deprecated; use detachInterrupt(TIMER_CH4) instead. */
|
||||
void detachCompare4Interrupt(void) { detachInterrupt(TIMER_CH4); }
|
||||
|
||||
/** @brief Deprecated; use refresh() instead. */
|
||||
void generateUpdate(void) { refresh(); }
|
||||
};
|
||||
|
||||
/** @brief Deprecated; use TIMER_OUTPUT_COMPARE instead. */
|
||||
#define TIMER_OUTPUTCOMPARE TIMER_OUTPUT_COMPARE
|
||||
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer1;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer2;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer3;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer4;
|
||||
#if (STM32_MCU_SERIES == STM32_SERIES_F1) && defined(STM32_HIGH_DENSITY)
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer5;
|
||||
/**
|
||||
* @brief Deprecated.
|
||||
*
|
||||
* Pre-instantiated timer.
|
||||
*/
|
||||
extern HardwareTimer Timer8;
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* Print.cpp - Base class that provides print() and println()
|
||||
* Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA
|
||||
*
|
||||
* Modified 23 November 2006 by David A. Mellis
|
||||
* Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com>
|
||||
*/
|
||||
|
||||
#include "Print.h"
|
||||
|
||||
#include "wirish_math.h"
|
||||
#include "limits.h"
|
||||
|
||||
#ifndef LLONG_MAX
|
||||
/*
|
||||
* Note:
|
||||
*
|
||||
* At time of writing (12 April 2011), the limits.h that came with the
|
||||
* newlib we distributed didn't include LLONG_MAX. Because we're
|
||||
* staying away from using templates (see /notes/coding_standard.rst,
|
||||
* "Language Features and Compiler Extensions"), this value was
|
||||
* copy-pasted from a println() of the value
|
||||
*
|
||||
* std::numeric_limits<long long>::max().
|
||||
*/
|
||||
#define LLONG_MAX 9223372036854775807LL
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Public methods
|
||||
*/
|
||||
|
||||
size_t Print::write(const char *str) {
|
||||
size_t n = 0;
|
||||
while (*str) {
|
||||
write(*str++);
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::write(const void *buffer, uint32 size) {
|
||||
size_t n = 0;
|
||||
uint8 *ch = (uint8*)buffer;
|
||||
while (size--) {
|
||||
write(*ch++);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::print(uint8 b, int base) {
|
||||
return print((uint64)b, base);
|
||||
}
|
||||
|
||||
size_t Print::print(const String &s)
|
||||
{
|
||||
return write(s.c_str(), s.length());
|
||||
}
|
||||
|
||||
size_t Print::print(char c) {
|
||||
return write(c);
|
||||
}
|
||||
|
||||
size_t Print::print(const char str[]) {
|
||||
return write(str);
|
||||
}
|
||||
|
||||
size_t Print::print(int n, int base) {
|
||||
return print((long long)n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned int n, int base) {
|
||||
return print((unsigned long long)n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long n, int base) {
|
||||
return print((long long)n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long n, int base) {
|
||||
return print((unsigned long long)n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(long long n, int base) {
|
||||
if (base == BYTE)
|
||||
{
|
||||
return write((uint8)n);
|
||||
}
|
||||
if (n < 0) {
|
||||
print('-');
|
||||
n = -n;
|
||||
}
|
||||
return printNumber(n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(unsigned long long n, int base) {
|
||||
size_t c=0;
|
||||
if (base == BYTE) {
|
||||
c= write((uint8)n);
|
||||
} else {
|
||||
c= printNumber(n, base);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits) {
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::println(void)
|
||||
{
|
||||
size_t n = print('\r');
|
||||
n += print('\n');
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const String &s)
|
||||
{
|
||||
size_t n = print(s);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(char c) {
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const char c[]) {
|
||||
size_t n = print(c);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(uint8 b, int base) {
|
||||
size_t n = print(b, base);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(int n, int base) {
|
||||
size_t s = print(n, base);
|
||||
s += println();
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned int n, int base) {
|
||||
size_t s = print(n, base);
|
||||
s += println();
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Print::println(long n, int base) {
|
||||
size_t s = print((long long)n, base);
|
||||
s += println();
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long n, int base) {
|
||||
size_t s = print((unsigned long long)n, base);
|
||||
s += println();
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Print::println(long long n, int base) {
|
||||
size_t s = print(n, base);
|
||||
s += println();
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Print::println(unsigned long long n, int base) {
|
||||
size_t s = print(n, base);
|
||||
s += println();
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Print::println(double n, int digits) {
|
||||
size_t s = print(n, digits);
|
||||
s += println();
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifdef SUPPORTS_PRINTF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
// Work in progress to support printf.
|
||||
// Need to implement stream FILE to write individual chars to chosen serial port
|
||||
int Print::printf (__const char *__restrict __format, ...)
|
||||
{
|
||||
FILE *__restrict __stream;
|
||||
int ret_status = 0;
|
||||
|
||||
|
||||
va_list args;
|
||||
va_start(args,__format);
|
||||
ret_status = vfprintf(__stream, __format, args);
|
||||
va_end(args);
|
||||
return ret_status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Private methods
|
||||
*/
|
||||
|
||||
size_t Print::printNumber(unsigned long long n, uint8 base) {
|
||||
unsigned char buf[CHAR_BIT * sizeof(long long)];
|
||||
unsigned long i = 0;
|
||||
size_t s=0;
|
||||
if (n == 0) {
|
||||
print('0');
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (n > 0) {
|
||||
buf[i++] = n % base;
|
||||
n /= base;
|
||||
}
|
||||
|
||||
for (; i > 0; i--) {
|
||||
s += print((char)(buf[i - 1] < 10 ?
|
||||
'0' + buf[i - 1] :
|
||||
'A' + buf[i - 1] - 10));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/* According to snprintf(),
|
||||
*
|
||||
* nextafter((double)numeric_limits<long long>::max(), 0.0) ~= 9.22337e+18
|
||||
*
|
||||
* This slightly smaller value was picked semi-arbitrarily. */
|
||||
#define LARGE_DOUBLE_TRESHOLD (9.1e18)
|
||||
|
||||
/* THIS FUNCTION SHOULDN'T BE USED IF YOU NEED ACCURATE RESULTS.
|
||||
*
|
||||
* This implementation is meant to be simple and not occupy too much
|
||||
* code size. However, printing floating point values accurately is a
|
||||
* subtle task, best left to a well-tested library function.
|
||||
*
|
||||
* See Steele and White 2003 for more details:
|
||||
*
|
||||
* http://kurtstephens.com/files/p372-steele.pdf
|
||||
*/
|
||||
size_t Print::printFloat(double number, uint8 digits) {
|
||||
size_t s=0;
|
||||
// Hackish fail-fast behavior for large-magnitude doubles
|
||||
if (abs(number) >= LARGE_DOUBLE_TRESHOLD) {
|
||||
if (number < 0.0) {
|
||||
s=print('-');
|
||||
}
|
||||
s+=print("<large double>");
|
||||
return s;
|
||||
}
|
||||
|
||||
// Handle negative numbers
|
||||
if (number < 0.0) {
|
||||
s+=print('-');
|
||||
number = -number;
|
||||
}
|
||||
|
||||
// Simplistic rounding strategy so that e.g. print(1.999, 2)
|
||||
// prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for (uint8 i = 0; i < digits; i++) {
|
||||
rounding /= 10.0;
|
||||
}
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
long long int_part = (long long)number;
|
||||
double remainder = number - int_part;
|
||||
s+=print(int_part);
|
||||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits > 0) {
|
||||
s+=print(".");
|
||||
}
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits-- > 0) {
|
||||
remainder *= 10.0;
|
||||
int to_print = (int)remainder;
|
||||
s+=print(to_print);
|
||||
remainder -= to_print;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Print.h - Base class that provides print() and println()
|
||||
* Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA.
|
||||
*
|
||||
* Modified 12 April 2011 by Marti Bolivar <mbolivar@leaflabs.com>
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_PRINT_H_
|
||||
#define _WIRISH_PRINT_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include "WString.h"
|
||||
|
||||
enum {
|
||||
BYTE = 0,
|
||||
BIN = 2,
|
||||
OCT = 8,
|
||||
DEC = 10,
|
||||
HEX = 16
|
||||
};
|
||||
|
||||
class Print {
|
||||
public:
|
||||
virtual size_t write(uint8 ch) = 0;
|
||||
virtual size_t write(const char *str);
|
||||
virtual size_t write(const void *buf, uint32 len);
|
||||
|
||||
size_t print(const String &);
|
||||
size_t print(char);
|
||||
size_t print(const char[]);
|
||||
size_t print(uint8, int=DEC);
|
||||
size_t print(int, int=DEC);
|
||||
size_t print(unsigned int, int=DEC);
|
||||
size_t print(long, int=DEC);
|
||||
size_t print(unsigned long, int=DEC);
|
||||
size_t print(long long, int=DEC);
|
||||
size_t print(unsigned long long, int=DEC);
|
||||
size_t print(double, int=2);
|
||||
size_t println(void);
|
||||
size_t println(const String &s);
|
||||
size_t println(char);
|
||||
size_t println(const char[]);
|
||||
size_t println(uint8, int=DEC);
|
||||
size_t println(int, int=DEC);
|
||||
size_t println(unsigned int, int=DEC);
|
||||
size_t println(long, int=DEC);
|
||||
size_t println(unsigned long, int=DEC);
|
||||
size_t println(long long, int=DEC);
|
||||
size_t println(unsigned long long, int=DEC);
|
||||
size_t println(double, int=2);
|
||||
#ifdef SUPPORTS_PRINTF
|
||||
// Roger Clark. Work in progress to add printf support
|
||||
int printf(const char * format, ...);
|
||||
#endif
|
||||
Print() : write_error(0) {}
|
||||
|
||||
int getWriteError() { return write_error; }
|
||||
void clearWriteError() { setWriteError(0); }
|
||||
|
||||
protected:
|
||||
void setWriteError(int err = 1) { write_error = err; }
|
||||
|
||||
private:
|
||||
int write_error;
|
||||
size_t printNumber(unsigned long long, uint8);
|
||||
size_t printFloat(double, uint8);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
Stream.cpp - adds parsing methods to Stream class
|
||||
Copyright (c) 2008 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Created July 2011
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Stream.h"
|
||||
|
||||
#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait
|
||||
#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field
|
||||
|
||||
// private method to read stream with timeout
|
||||
int Stream::timedRead()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = read();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// private method to peek stream with timeout
|
||||
int Stream::timedPeek()
|
||||
{
|
||||
int c;
|
||||
_startMillis = millis();
|
||||
do {
|
||||
c = peek();
|
||||
if (c >= 0) return c;
|
||||
} while(millis() - _startMillis < _timeout);
|
||||
return -1; // -1 indicates timeout
|
||||
}
|
||||
|
||||
// returns peek of the next digit in the stream or -1 if timeout
|
||||
// discards non-numeric characters
|
||||
int Stream::peekNextDigit()
|
||||
{
|
||||
int c;
|
||||
while (1) {
|
||||
c = timedPeek();
|
||||
if (c < 0) return c; // timeout
|
||||
if (c == '-') return c;
|
||||
if (c >= '0' && c <= '9') return c;
|
||||
read(); // discard non-numeric
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait
|
||||
{
|
||||
_timeout = timeout;
|
||||
}
|
||||
|
||||
// find returns true if the target string is found
|
||||
bool Stream::find(char *target)
|
||||
{
|
||||
return findUntil(target, (char*)"");
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of given length is found
|
||||
// returns true if target string is found, false if timed out
|
||||
bool Stream::find(char *target, size_t length)
|
||||
{
|
||||
return findUntil(target, length, NULL, 0);
|
||||
}
|
||||
|
||||
// as find but search ends if the terminator string is found
|
||||
bool Stream::findUntil(char *target, char *terminator)
|
||||
{
|
||||
return findUntil(target, strlen(target), terminator, strlen(terminator));
|
||||
}
|
||||
|
||||
// reads data from the stream until the target string of the given length is found
|
||||
// search terminated if the terminator string is found
|
||||
// returns true if target string is found, false if terminated or timed out
|
||||
bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen)
|
||||
{
|
||||
size_t index = 0; // maximum target string length is 64k bytes!
|
||||
size_t termIndex = 0;
|
||||
int c;
|
||||
|
||||
if( *target == 0)
|
||||
return true; // return true if target is a null string
|
||||
while( (c = timedRead()) > 0){
|
||||
|
||||
if(c != target[index])
|
||||
index = 0; // reset index if any char does not match
|
||||
|
||||
if( c == target[index]){
|
||||
//////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1);
|
||||
if(++index >= targetLen){ // return true if all chars in the target match
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(termLen > 0 && c == terminator[termIndex]){
|
||||
if(++termIndex >= termLen)
|
||||
return false; // return false if terminate string found before target string
|
||||
}
|
||||
else
|
||||
termIndex = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// function is terminated by the first character that is not a digit.
|
||||
long Stream::parseInt()
|
||||
{
|
||||
return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout)
|
||||
}
|
||||
|
||||
// as above but a given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
long Stream::parseInt(char skipChar)
|
||||
{
|
||||
boolean isNegative = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if(c == skipChar)
|
||||
; // ignore this charactor
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if(c >= '0' && c <= '9') // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || c == skipChar );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// as parseInt but returns a floating point value
|
||||
float Stream::parseFloat()
|
||||
{
|
||||
return parseFloat(NO_SKIP_CHAR);
|
||||
}
|
||||
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
float Stream::parseFloat(char skipChar){
|
||||
boolean isNegative = false;
|
||||
boolean isFraction = false;
|
||||
long value = 0;
|
||||
int c;
|
||||
float fraction = 1.0;
|
||||
|
||||
c = peekNextDigit();
|
||||
// ignore non numeric leading characters
|
||||
if(c < 0)
|
||||
return 0; // zero returned if timeout
|
||||
|
||||
do{
|
||||
if(c == skipChar)
|
||||
; // ignore
|
||||
else if(c == '-')
|
||||
isNegative = true;
|
||||
else if (c == '.')
|
||||
isFraction = true;
|
||||
else if(c >= '0' && c <= '9') { // is c a digit?
|
||||
value = value * 10 + c - '0';
|
||||
if(isFraction)
|
||||
fraction *= 0.1;
|
||||
}
|
||||
read(); // consume the character we got with peek
|
||||
c = timedPeek();
|
||||
}
|
||||
while( (c >= '0' && c <= '9') || c == '.' || c == skipChar );
|
||||
|
||||
if(isNegative)
|
||||
value = -value;
|
||||
if(isFraction)
|
||||
return value * fraction;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
// read characters from stream into buffer
|
||||
// terminates if length characters have been read, or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer
|
||||
// the buffer is NOT null terminated.
|
||||
//
|
||||
size_t Stream::readBytes(char *buffer, size_t length)
|
||||
{
|
||||
size_t count = 0;
|
||||
while (count < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0) break;
|
||||
*buffer++ = (char)c;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// as readBytes with terminator character
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
||||
{
|
||||
if (length < 1) return 0;
|
||||
size_t index = 0;
|
||||
while (index < length) {
|
||||
int c = timedRead();
|
||||
if (c < 0 || c == terminator) break;
|
||||
*buffer++ = (char)c;
|
||||
index++;
|
||||
}
|
||||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
String Stream::readString()
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Stream::readStringUntil(char terminator)
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0 && c != terminator)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Stream.h - base class for character-based streams.
|
||||
Copyright (c) 2010 David A. Mellis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
parsing functions based on TextFinder library by Michael Margolis
|
||||
*/
|
||||
|
||||
#ifndef Stream_h
|
||||
#define Stream_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Print.h"
|
||||
|
||||
// compatability macros for testing
|
||||
/*
|
||||
#define getInt() parseInt()
|
||||
#define getInt(skipChar) parseInt(skipchar)
|
||||
#define getFloat() parseFloat()
|
||||
#define getFloat(skipChar) parseFloat(skipChar)
|
||||
#define getString( pre_string, post_string, buffer, length)
|
||||
readBytesBetween( pre_string, terminator, buffer, length)
|
||||
*/
|
||||
|
||||
class Stream : public Print
|
||||
{
|
||||
protected:
|
||||
unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read
|
||||
unsigned long _startMillis; // used for timeout measurement
|
||||
int timedRead(); // private method to read stream with timeout
|
||||
int timedPeek(); // private method to peek stream with timeout
|
||||
int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout
|
||||
|
||||
public:
|
||||
virtual int available() = 0;
|
||||
virtual int read() = 0;
|
||||
virtual int peek() = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
Stream() {_timeout=1000;}
|
||||
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
|
||||
bool find(char *target); // reads data from the stream until the target string is found
|
||||
bool find(uint8_t *target) { return find ((char *)target); }
|
||||
// returns true if target string is found, false if timed out (see setTimeout)
|
||||
|
||||
bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found
|
||||
bool find(uint8_t *target, size_t length) { return find ((char *)target, length); }
|
||||
// returns true if target string is found, false if timed out
|
||||
|
||||
bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found
|
||||
bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); }
|
||||
|
||||
bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found
|
||||
bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); }
|
||||
|
||||
|
||||
long parseInt(); // returns the first valid (long) integer value from the current position.
|
||||
// initial characters that are not digits (or the minus sign) are skipped
|
||||
// integer is terminated by the first character that is not a digit.
|
||||
|
||||
float parseFloat(); // float version of parseInt
|
||||
|
||||
size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer
|
||||
size_t readBytes( uint8_t *buffer, size_t length) { return readBytes((char *)buffer, length); }
|
||||
// terminates if length characters have been read or timeout (see setTimeout)
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character
|
||||
size_t readBytesUntil( char terminator, uint8_t *buffer, size_t length) { return readBytesUntil(terminator, (char *)buffer, length); }
|
||||
// terminates if length characters have been read, timeout, or if the terminator character detected
|
||||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
// Arduino String functions to be added here
|
||||
String readString();
|
||||
String readStringUntil(char terminator);
|
||||
|
||||
protected:
|
||||
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
||||
// as above but the given skipChar is ignored
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
|
||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,35 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _WIRISH_WPROGRAM_H_
|
||||
#define _WIRISH_WPROGRAM_H_
|
||||
|
||||
#include <wirish.h>
|
||||
|
||||
void setup();
|
||||
void loop();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,746 @@
|
|||
/*
|
||||
WString.cpp - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All rights reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "WString.h"
|
||||
#include "itoa.h"
|
||||
#include "avr/dtostrf.h"
|
||||
|
||||
/*********************************************/
|
||||
/* Constructors */
|
||||
/*********************************************/
|
||||
|
||||
String::String(const char *cstr)
|
||||
{
|
||||
init();
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
String::String(const String &value)
|
||||
{
|
||||
init();
|
||||
*this = value;
|
||||
}
|
||||
|
||||
String::String(const __FlashStringHelper *pstr)
|
||||
{
|
||||
init();
|
||||
*this = pstr;
|
||||
}
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String::String(String &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
String::String(StringSumHelper &&rval)
|
||||
{
|
||||
init();
|
||||
move(rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
String::String(char c)
|
||||
{
|
||||
init();
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned char value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned char)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(int)];
|
||||
itoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned int value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned int)];
|
||||
utoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[2 + 8 * sizeof(long)];
|
||||
ltoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(unsigned long value, unsigned char base)
|
||||
{
|
||||
init();
|
||||
char buf[1 + 8 * sizeof(unsigned long)];
|
||||
ultoa(value, buf, base);
|
||||
*this = buf;
|
||||
}
|
||||
|
||||
String::String(float value, unsigned char decimalPlaces)
|
||||
{
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::String(double value, unsigned char decimalPlaces)
|
||||
{
|
||||
init();
|
||||
char buf[33];
|
||||
*this = dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
|
||||
}
|
||||
|
||||
String::~String()
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Memory Management */
|
||||
/*********************************************/
|
||||
|
||||
inline void String::init(void)
|
||||
{
|
||||
buffer = NULL;
|
||||
capacity = 0;
|
||||
len = 0;
|
||||
}
|
||||
|
||||
void String::invalidate(void)
|
||||
{
|
||||
if (buffer) free(buffer);
|
||||
buffer = NULL;
|
||||
capacity = len = 0;
|
||||
}
|
||||
|
||||
unsigned char String::reserve(unsigned int size)
|
||||
{
|
||||
if (buffer && capacity >= size) return 1;
|
||||
if (changeBuffer(size)) {
|
||||
if (len == 0) buffer[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned char String::changeBuffer(unsigned int maxStrLen)
|
||||
{
|
||||
char *newbuffer = (char *)realloc(buffer, maxStrLen + 1);
|
||||
if (newbuffer) {
|
||||
buffer = newbuffer;
|
||||
capacity = maxStrLen;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Copy and Move */
|
||||
/*********************************************/
|
||||
|
||||
String & String::copy(const char *cstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
strcpy(buffer, cstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
|
||||
{
|
||||
if (!reserve(length)) {
|
||||
invalidate();
|
||||
return *this;
|
||||
}
|
||||
len = length;
|
||||
strcpy_P(buffer, (PGM_P)pstr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
void String::move(String &rhs)
|
||||
{
|
||||
if (buffer) {
|
||||
if (capacity >= rhs.len) {
|
||||
strcpy(buffer, rhs.buffer);
|
||||
len = rhs.len;
|
||||
rhs.len = 0;
|
||||
return;
|
||||
} else {
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
buffer = rhs.buffer;
|
||||
capacity = rhs.capacity;
|
||||
len = rhs.len;
|
||||
rhs.buffer = NULL;
|
||||
rhs.capacity = 0;
|
||||
rhs.len = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const String &rhs)
|
||||
{
|
||||
if (this == &rhs) return *this;
|
||||
|
||||
if (rhs.buffer) copy(rhs.buffer, rhs.len);
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String & String::operator = (String &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (StringSumHelper &&rval)
|
||||
{
|
||||
if (this != &rval) move(rval);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
String & String::operator = (const char *cstr)
|
||||
{
|
||||
if (cstr) copy(cstr, strlen(cstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String & String::operator = (const __FlashStringHelper *pstr)
|
||||
{
|
||||
if (pstr) copy(pstr, strlen_P((PGM_P)pstr));
|
||||
else invalidate();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* concat */
|
||||
/*********************************************/
|
||||
|
||||
unsigned char String::concat(const String &s)
|
||||
{
|
||||
return concat(s.buffer, s.len);
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr, unsigned int length)
|
||||
{
|
||||
unsigned int newlen = len + length;
|
||||
if (!cstr) return 0;
|
||||
if (length == 0) return 1;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy(buffer + len, cstr);
|
||||
len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::concat(const char *cstr)
|
||||
{
|
||||
if (!cstr) return 0;
|
||||
return concat(cstr, strlen(cstr));
|
||||
}
|
||||
|
||||
unsigned char String::concat(char c)
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = c;
|
||||
buf[1] = 0;
|
||||
return concat(buf, 1);
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned char num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned char)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(int num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(int)];
|
||||
itoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned int num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned int)];
|
||||
utoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(long num)
|
||||
{
|
||||
char buf[2 + 3 * sizeof(long)];
|
||||
ltoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(unsigned long num)
|
||||
{
|
||||
char buf[1 + 3 * sizeof(unsigned long)];
|
||||
ultoa(num, buf, 10);
|
||||
return concat(buf, strlen(buf));
|
||||
}
|
||||
|
||||
unsigned char String::concat(float num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(double num)
|
||||
{
|
||||
char buf[20];
|
||||
char* string = dtostrf(num, 4, 2, buf);
|
||||
return concat(string, strlen(string));
|
||||
}
|
||||
|
||||
unsigned char String::concat(const __FlashStringHelper * str)
|
||||
{
|
||||
if (!str) return 0;
|
||||
int length = strlen_P((const char *) str);
|
||||
if (length == 0) return 1;
|
||||
unsigned int newlen = len + length;
|
||||
if (!reserve(newlen)) return 0;
|
||||
strcpy_P(buffer + len, (const char *) str);
|
||||
len = newlen;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Concatenate */
|
||||
/*********************************************/
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs.buffer, rhs.len)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, char c)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(c)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, float num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, double num)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(num)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs)
|
||||
{
|
||||
StringSumHelper &a = const_cast<StringSumHelper&>(lhs);
|
||||
if (!a.concat(rhs)) a.invalidate();
|
||||
return a;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Comparison */
|
||||
/*********************************************/
|
||||
|
||||
int String::compareTo(const String &s) const
|
||||
{
|
||||
if (!buffer || !s.buffer) {
|
||||
if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer;
|
||||
if (buffer && len > 0) return *(unsigned char *)buffer;
|
||||
return 0;
|
||||
}
|
||||
return strcmp(buffer, s.buffer);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const String &s2) const
|
||||
{
|
||||
return (len == s2.len && compareTo(s2) == 0);
|
||||
}
|
||||
|
||||
unsigned char String::equals(const char *cstr) const
|
||||
{
|
||||
if (len == 0) return (cstr == NULL || *cstr == 0);
|
||||
if (cstr == NULL) return buffer[0] == 0;
|
||||
return strcmp(buffer, cstr) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) < 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) > 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator<=(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) <= 0;
|
||||
}
|
||||
|
||||
unsigned char String::operator>=(const String &rhs) const
|
||||
{
|
||||
return compareTo(rhs) >= 0;
|
||||
}
|
||||
|
||||
unsigned char String::equalsIgnoreCase( const String &s2 ) const
|
||||
{
|
||||
if (this == &s2) return 1;
|
||||
if (len != s2.len) return 0;
|
||||
if (len == 0) return 1;
|
||||
const char *p1 = buffer;
|
||||
const char *p2 = s2.buffer;
|
||||
while (*p1) {
|
||||
if (tolower(*p1++) != tolower(*p2++)) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2 ) const
|
||||
{
|
||||
if (len < s2.len) return 0;
|
||||
return startsWith(s2, 0);
|
||||
}
|
||||
|
||||
unsigned char String::startsWith( const String &s2, unsigned int offset ) const
|
||||
{
|
||||
if (offset > len - s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0;
|
||||
}
|
||||
|
||||
unsigned char String::endsWith( const String &s2 ) const
|
||||
{
|
||||
if ( len < s2.len || !buffer || !s2.buffer) return 0;
|
||||
return strcmp(&buffer[len - s2.len], s2.buffer) == 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Character Access */
|
||||
/*********************************************/
|
||||
|
||||
char String::charAt(unsigned int loc) const
|
||||
{
|
||||
return operator[](loc);
|
||||
}
|
||||
|
||||
void String::setCharAt(unsigned int loc, char c)
|
||||
{
|
||||
if (loc < len) buffer[loc] = c;
|
||||
}
|
||||
|
||||
char & String::operator[](unsigned int index)
|
||||
{
|
||||
static char dummy_writable_char;
|
||||
if (index >= len || !buffer) {
|
||||
dummy_writable_char = 0;
|
||||
return dummy_writable_char;
|
||||
}
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
char String::operator[]( unsigned int index ) const
|
||||
{
|
||||
if (index >= len || !buffer) return 0;
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const
|
||||
{
|
||||
if (!bufsize || !buf) return;
|
||||
if (index >= len) {
|
||||
buf[0] = 0;
|
||||
return;
|
||||
}
|
||||
unsigned int n = bufsize - 1;
|
||||
if (n > len - index) n = len - index;
|
||||
strncpy((char *)buf, buffer + index, n);
|
||||
buf[n] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Search */
|
||||
/*********************************************/
|
||||
|
||||
int String::indexOf(char c) const
|
||||
{
|
||||
return indexOf(c, 0);
|
||||
}
|
||||
|
||||
int String::indexOf( char ch, unsigned int fromIndex ) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char* temp = strchr(buffer + fromIndex, ch);
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2) const
|
||||
{
|
||||
return indexOf(s2, 0);
|
||||
}
|
||||
|
||||
int String::indexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
const char *found = strstr(buffer + fromIndex, s2.buffer);
|
||||
if (found == NULL) return -1;
|
||||
return found - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf( char theChar ) const
|
||||
{
|
||||
return lastIndexOf(theChar, len - 1);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(char ch, unsigned int fromIndex) const
|
||||
{
|
||||
if (fromIndex >= len) return -1;
|
||||
char tempchar = buffer[fromIndex + 1];
|
||||
buffer[fromIndex + 1] = '\0';
|
||||
char* temp = strrchr( buffer, ch );
|
||||
buffer[fromIndex + 1] = tempchar;
|
||||
if (temp == NULL) return -1;
|
||||
return temp - buffer;
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2) const
|
||||
{
|
||||
return lastIndexOf(s2, len - s2.len);
|
||||
}
|
||||
|
||||
int String::lastIndexOf(const String &s2, unsigned int fromIndex) const
|
||||
{
|
||||
if (s2.len == 0 || len == 0 || s2.len > len) return -1;
|
||||
if (fromIndex >= len) fromIndex = len - 1;
|
||||
int found = -1;
|
||||
for (char *p = buffer; p <= buffer + fromIndex; p++) {
|
||||
p = strstr(p, s2.buffer);
|
||||
if (!p) break;
|
||||
if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
String String::substring(unsigned int left, unsigned int right) const
|
||||
{
|
||||
if (left > right) {
|
||||
unsigned int temp = right;
|
||||
right = left;
|
||||
left = temp;
|
||||
}
|
||||
String out;
|
||||
if (left > len) return out;
|
||||
if (right > len) right = len;
|
||||
char temp = buffer[right]; // save the replaced character
|
||||
buffer[right] = '\0';
|
||||
out = buffer + left; // pointer arithmetic
|
||||
buffer[right] = temp; //restore character
|
||||
return out;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Modification */
|
||||
/*********************************************/
|
||||
|
||||
void String::replace(char find, char replace)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
if (*p == find) *p = replace;
|
||||
}
|
||||
}
|
||||
|
||||
void String::replace(const String& find, const String& replace)
|
||||
{
|
||||
if (len == 0 || find.len == 0) return;
|
||||
int diff = replace.len - find.len;
|
||||
char *readFrom = buffer;
|
||||
char *foundAt;
|
||||
if (diff == 0) {
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
memcpy(foundAt, replace.buffer, replace.len);
|
||||
readFrom = foundAt + replace.len;
|
||||
}
|
||||
} else if (diff < 0) {
|
||||
char *writeTo = buffer;
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
unsigned int n = foundAt - readFrom;
|
||||
memcpy(writeTo, readFrom, n);
|
||||
writeTo += n;
|
||||
memcpy(writeTo, replace.buffer, replace.len);
|
||||
writeTo += replace.len;
|
||||
readFrom = foundAt + find.len;
|
||||
len += diff;
|
||||
}
|
||||
strcpy(writeTo, readFrom);
|
||||
} else {
|
||||
unsigned int size = len; // compute size needed for result
|
||||
while ((foundAt = strstr(readFrom, find.buffer)) != NULL) {
|
||||
readFrom = foundAt + find.len;
|
||||
size += diff;
|
||||
}
|
||||
if (size == len) return;
|
||||
if (size > capacity && !changeBuffer(size)) return; // XXX: tell user!
|
||||
int index = len - 1;
|
||||
while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) {
|
||||
readFrom = buffer + index + find.len;
|
||||
memmove(readFrom + diff, readFrom, len - (readFrom - buffer));
|
||||
len += diff;
|
||||
buffer[len] = 0;
|
||||
memcpy(buffer + index, replace.buffer, replace.len);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index){
|
||||
if (index >= len) { return; }
|
||||
int count = len - index;
|
||||
remove(index, count);
|
||||
}
|
||||
|
||||
void String::remove(unsigned int index, unsigned int count){
|
||||
if (index >= len) { return; }
|
||||
if (count <= 0) { return; }
|
||||
if (index + count > len) { count = len - index; }
|
||||
char *writeTo = buffer + index;
|
||||
len = len - count;
|
||||
strncpy(writeTo, buffer + index + count,len - index);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
void String::toLowerCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = tolower(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::toUpperCase(void)
|
||||
{
|
||||
if (!buffer) return;
|
||||
for (char *p = buffer; *p; p++) {
|
||||
*p = toupper(*p);
|
||||
}
|
||||
}
|
||||
|
||||
void String::trim(void)
|
||||
{
|
||||
if (!buffer || len == 0) return;
|
||||
char *begin = buffer;
|
||||
while (isspace(*begin)) begin++;
|
||||
char *end = buffer + len - 1;
|
||||
while (isspace(*end) && end >= begin) end--;
|
||||
len = end + 1 - begin;
|
||||
if (begin > buffer) memcpy(buffer, begin, len);
|
||||
buffer[len] = 0;
|
||||
}
|
||||
|
||||
/*********************************************/
|
||||
/* Parsing / Conversion */
|
||||
/*********************************************/
|
||||
|
||||
long String::toInt(void) const
|
||||
{
|
||||
if (buffer) return atol(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
float String::toFloat(void) const
|
||||
{
|
||||
if (buffer) return float(atof(buffer));
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
WString.h - String library for Wiring & Arduino
|
||||
...mostly rewritten by Paul Stoffregen...
|
||||
Copyright (c) 2009-10 Hernando Barragan. All right reserved.
|
||||
Copyright 2011, Paul Stoffregen, paul@pjrc.com
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef String_class_h
|
||||
#define String_class_h
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
// When compiling programs with this class, the following gcc parameters
|
||||
// dramatically increase performance and memory (RAM) efficiency, typically
|
||||
// with little or no increase in code size.
|
||||
// -felide-constructors
|
||||
// -std=c++0x
|
||||
|
||||
class __FlashStringHelper;
|
||||
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))
|
||||
|
||||
// An inherited class for holding the result of a concatenation. These
|
||||
// result objects are assumed to be writable by subsequent concatenations.
|
||||
class StringSumHelper;
|
||||
|
||||
// The string class
|
||||
class String
|
||||
{
|
||||
// use a function pointer to allow for "if (s)" without the
|
||||
// complications of an operator bool(). for more information, see:
|
||||
// http://www.artima.com/cppsource/safebool.html
|
||||
typedef void (String::*StringIfHelperType)() const;
|
||||
void StringIfHelper() const {}
|
||||
|
||||
public:
|
||||
// constructors
|
||||
// creates a copy of the initial value.
|
||||
// if the initial value is null or invalid, or if memory allocation
|
||||
// fails, the string will be marked as invalid (i.e. "if (s)" will
|
||||
// be false).
|
||||
String(const char *cstr = "");
|
||||
String(const String &str);
|
||||
String(const __FlashStringHelper *str);
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String(String &&rval);
|
||||
String(StringSumHelper &&rval);
|
||||
#endif
|
||||
explicit String(char c);
|
||||
explicit String(unsigned char, unsigned char base=10);
|
||||
explicit String(int, unsigned char base=10);
|
||||
explicit String(unsigned int, unsigned char base=10);
|
||||
explicit String(long, unsigned char base=10);
|
||||
explicit String(unsigned long, unsigned char base=10);
|
||||
explicit String(float, unsigned char decimalPlaces=2);
|
||||
explicit String(double, unsigned char decimalPlaces=2);
|
||||
~String(void);
|
||||
|
||||
// memory management
|
||||
// return true on success, false on failure (in which case, the string
|
||||
// is left unchanged). reserve(0), if successful, will validate an
|
||||
// invalid string (i.e., "if (s)" will be true afterwards)
|
||||
unsigned char reserve(unsigned int size);
|
||||
inline unsigned int length(void) const {return len;}
|
||||
|
||||
// creates a copy of the assigned value. if the value is null or
|
||||
// invalid, or if the memory allocation fails, the string will be
|
||||
// marked as invalid ("if (s)" will be false).
|
||||
String & operator = (const String &rhs);
|
||||
String & operator = (const char *cstr);
|
||||
String & operator = (const __FlashStringHelper *str);
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
String & operator = (String &&rval);
|
||||
String & operator = (StringSumHelper &&rval);
|
||||
#endif
|
||||
|
||||
// concatenate (works w/ built-in types)
|
||||
|
||||
// returns true on success, false on failure (in which case, the string
|
||||
// is left unchanged). if the argument is null or invalid, the
|
||||
// concatenation is considered unsucessful.
|
||||
unsigned char concat(const String &str);
|
||||
unsigned char concat(const char *cstr);
|
||||
unsigned char concat(char c);
|
||||
unsigned char concat(unsigned char c);
|
||||
unsigned char concat(int num);
|
||||
unsigned char concat(unsigned int num);
|
||||
unsigned char concat(long num);
|
||||
unsigned char concat(unsigned long num);
|
||||
unsigned char concat(float num);
|
||||
unsigned char concat(double num);
|
||||
unsigned char concat(const __FlashStringHelper * str);
|
||||
|
||||
// if there's not enough memory for the concatenated value, the string
|
||||
// will be left unchanged (but this isn't signalled in any way)
|
||||
String & operator += (const String &rhs) {concat(rhs); return (*this);}
|
||||
String & operator += (const char *cstr) {concat(cstr); return (*this);}
|
||||
String & operator += (char c) {concat(c); return (*this);}
|
||||
String & operator += (unsigned char num) {concat(num); return (*this);}
|
||||
String & operator += (int num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned int num) {concat(num); return (*this);}
|
||||
String & operator += (long num) {concat(num); return (*this);}
|
||||
String & operator += (unsigned long num) {concat(num); return (*this);}
|
||||
String & operator += (float num) {concat(num); return (*this);}
|
||||
String & operator += (double num) {concat(num); return (*this);}
|
||||
String & operator += (const __FlashStringHelper *str){concat(str); return (*this);}
|
||||
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, char c);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, float num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, double num);
|
||||
friend StringSumHelper & operator + (const StringSumHelper &lhs, const __FlashStringHelper *rhs);
|
||||
|
||||
// comparison (only works w/ Strings and "strings")
|
||||
operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; }
|
||||
int compareTo(const String &s) const;
|
||||
unsigned char equals(const String &s) const;
|
||||
unsigned char equals(const char *cstr) const;
|
||||
unsigned char operator == (const String &rhs) const {return equals(rhs);}
|
||||
unsigned char operator == (const char *cstr) const {return equals(cstr);}
|
||||
unsigned char operator != (const String &rhs) const {return !equals(rhs);}
|
||||
unsigned char operator != (const char *cstr) const {return !equals(cstr);}
|
||||
unsigned char operator < (const String &rhs) const;
|
||||
unsigned char operator > (const String &rhs) const;
|
||||
unsigned char operator <= (const String &rhs) const;
|
||||
unsigned char operator >= (const String &rhs) const;
|
||||
unsigned char equalsIgnoreCase(const String &s) const;
|
||||
unsigned char startsWith( const String &prefix) const;
|
||||
unsigned char startsWith(const String &prefix, unsigned int offset) const;
|
||||
unsigned char endsWith(const String &suffix) const;
|
||||
|
||||
// character acccess
|
||||
char charAt(unsigned int index) const;
|
||||
void setCharAt(unsigned int index, char c);
|
||||
char operator [] (unsigned int index) const;
|
||||
char& operator [] (unsigned int index);
|
||||
void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const;
|
||||
void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const
|
||||
{getBytes((unsigned char *)buf, bufsize, index);}
|
||||
const char * c_str() const { return buffer; }
|
||||
|
||||
// search
|
||||
int indexOf( char ch ) const;
|
||||
int indexOf( char ch, unsigned int fromIndex ) const;
|
||||
int indexOf( const String &str ) const;
|
||||
int indexOf( const String &str, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( char ch ) const;
|
||||
int lastIndexOf( char ch, unsigned int fromIndex ) const;
|
||||
int lastIndexOf( const String &str ) const;
|
||||
int lastIndexOf( const String &str, unsigned int fromIndex ) const;
|
||||
String substring( unsigned int beginIndex ) const { return substring(beginIndex, len); };
|
||||
String substring( unsigned int beginIndex, unsigned int endIndex ) const;
|
||||
|
||||
// modification
|
||||
void replace(char find, char replace);
|
||||
void replace(const String& find, const String& replace);
|
||||
void remove(unsigned int index);
|
||||
void remove(unsigned int index, unsigned int count);
|
||||
void toLowerCase(void);
|
||||
void toUpperCase(void);
|
||||
void trim(void);
|
||||
|
||||
// parsing/conversion
|
||||
long toInt(void) const;
|
||||
float toFloat(void) const;
|
||||
|
||||
protected:
|
||||
char *buffer; // the actual char array
|
||||
unsigned int capacity; // the array length minus one (for the '\0')
|
||||
unsigned int len; // the String length (not counting the '\0')
|
||||
protected:
|
||||
void init(void);
|
||||
void invalidate(void);
|
||||
unsigned char changeBuffer(unsigned int maxStrLen);
|
||||
unsigned char concat(const char *cstr, unsigned int length);
|
||||
|
||||
// copy and move
|
||||
String & copy(const char *cstr, unsigned int length);
|
||||
String & copy(const __FlashStringHelper *pstr, unsigned int length);
|
||||
#ifdef __GXX_EXPERIMENTAL_CXX0X__
|
||||
void move(String &rhs);
|
||||
#endif
|
||||
};
|
||||
|
||||
class StringSumHelper : public String
|
||||
{
|
||||
public:
|
||||
StringSumHelper(const String &s) : String(s) {}
|
||||
StringSumHelper(const char *p) : String(p) {}
|
||||
StringSumHelper(char c) : String(c) {}
|
||||
StringSumHelper(unsigned char num) : String(num) {}
|
||||
StringSumHelper(int num) : String(num) {}
|
||||
StringSumHelper(unsigned int num) : String(num) {}
|
||||
StringSumHelper(long num) : String(num) {}
|
||||
StringSumHelper(unsigned long num) : String(num) {}
|
||||
StringSumHelper(float num) : String(num) {}
|
||||
StringSumHelper(double num) : String(num) {}
|
||||
};
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // String_class_h
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
dtostrf - Emulation for dtostrf function from avr-libc
|
||||
Copyright (c) 2013 Arduino. All rights reserved.
|
||||
Written by Cristian Maglie <c.maglie@bug.st>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
|
||||
char fmt[20];
|
||||
sprintf(fmt, "%%%d.%df", width, prec);
|
||||
sprintf(sout, fmt, val);
|
||||
return sout;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
dtostrf - Emulation for dtostrf function from avr-libc
|
||||
Copyright (c) 2013 Arduino. All rights reserved.
|
||||
Written by Cristian Maglie <c.maglie@bug.st>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *dtostrf (double val, signed char width, unsigned char prec, char *sout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
#ifndef __PGMSPACE_H_
|
||||
#define __PGMSPACE_H_ 1
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
#define PSTR(str) (str)
|
||||
|
||||
#define _SFR_BYTE(n) (n)
|
||||
|
||||
typedef void prog_void;
|
||||
typedef char prog_char;
|
||||
typedef unsigned char prog_uchar;
|
||||
typedef int8_t prog_int8_t;
|
||||
typedef uint8_t prog_uint8_t;
|
||||
typedef int16_t prog_int16_t;
|
||||
typedef uint16_t prog_uint16_t;
|
||||
typedef int32_t prog_int32_t;
|
||||
typedef uint32_t prog_uint32_t;
|
||||
|
||||
#define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
|
||||
#define strcpy_P(dest, src) strcpy((dest), (src))
|
||||
#define strcat_P(dest, src) strcat((dest), (src))
|
||||
#define strcmp_P(a, b) strcmp((a), (b))
|
||||
#define strstr_P(a, b) strstr((a), (b))
|
||||
#define strlen_P(a) strlen((a))
|
||||
#define sprintf_P(s, f, ...) sprintf((s), (f), __VA_ARGS__)
|
||||
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#define pgm_read_word(addr) (*(const unsigned short *)(addr))
|
||||
#define pgm_read_dword(addr) (*(const unsigned long *)(addr))
|
||||
#define pgm_read_float(addr) (*(const float *)(addr))
|
||||
|
||||
#define pgm_read_byte_near(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_near(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_near(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_near(addr) pgm_read_float(addr)
|
||||
#define pgm_read_byte_far(addr) pgm_read_byte(addr)
|
||||
#define pgm_read_word_far(addr) pgm_read_word(addr)
|
||||
#define pgm_read_dword_far(addr) pgm_read_dword(addr)
|
||||
#define pgm_read_float_far(addr) pgm_read_float(addr)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,579 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief BIT[n] and binary literal defines, for Arduino
|
||||
* compatibility.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_BIT_CONSTANTS_H_
|
||||
#define _WIRISH_BIT_CONSTANTS_H_
|
||||
|
||||
#define BIT0 (1 << 0)
|
||||
#define BIT1 (1 << 1)
|
||||
#define BIT2 (1 << 2)
|
||||
#define BIT3 (1 << 3)
|
||||
#define BIT4 (1 << 4)
|
||||
#define BIT5 (1 << 5)
|
||||
#define BIT6 (1 << 6)
|
||||
#define BIT7 (1 << 7)
|
||||
#define BIT8 (1 << 8)
|
||||
#define BIT9 (1 << 9)
|
||||
#define BIT10 (1 << 10)
|
||||
#define BIT11 (1 << 11)
|
||||
#define BIT12 (1 << 12)
|
||||
#define BIT13 (1 << 13)
|
||||
#define BIT14 (1 << 14)
|
||||
#define BIT15 (1 << 15)
|
||||
#define BIT16 (1 << 16)
|
||||
#define BIT17 (1 << 17)
|
||||
#define BIT18 (1 << 18)
|
||||
#define BIT19 (1 << 19)
|
||||
#define BIT20 (1 << 20)
|
||||
#define BIT21 (1 << 21)
|
||||
#define BIT22 (1 << 22)
|
||||
#define BIT23 (1 << 23)
|
||||
#define BIT24 (1 << 24)
|
||||
#define BIT25 (1 << 25)
|
||||
#define BIT26 (1 << 26)
|
||||
#define BIT27 (1 << 27)
|
||||
#define BIT28 (1 << 28)
|
||||
#define BIT29 (1 << 29)
|
||||
#define BIT30 (1 << 30)
|
||||
#define BIT31 (1 << 31)
|
||||
|
||||
#define B0 0
|
||||
#define B00 0
|
||||
#define B000 0
|
||||
#define B0000 0
|
||||
#define B00000 0
|
||||
#define B000000 0
|
||||
#define B0000000 0
|
||||
#define B00000000 0
|
||||
#define B1 1
|
||||
#define B01 1
|
||||
#define B001 1
|
||||
#define B0001 1
|
||||
#define B00001 1
|
||||
#define B000001 1
|
||||
#define B0000001 1
|
||||
#define B00000001 1
|
||||
#define B10 2
|
||||
#define B010 2
|
||||
#define B0010 2
|
||||
#define B00010 2
|
||||
#define B000010 2
|
||||
#define B0000010 2
|
||||
#define B00000010 2
|
||||
#define B11 3
|
||||
#define B011 3
|
||||
#define B0011 3
|
||||
#define B00011 3
|
||||
#define B000011 3
|
||||
#define B0000011 3
|
||||
#define B00000011 3
|
||||
#define B100 4
|
||||
#define B0100 4
|
||||
#define B00100 4
|
||||
#define B000100 4
|
||||
#define B0000100 4
|
||||
#define B00000100 4
|
||||
#define B101 5
|
||||
#define B0101 5
|
||||
#define B00101 5
|
||||
#define B000101 5
|
||||
#define B0000101 5
|
||||
#define B00000101 5
|
||||
#define B110 6
|
||||
#define B0110 6
|
||||
#define B00110 6
|
||||
#define B000110 6
|
||||
#define B0000110 6
|
||||
#define B00000110 6
|
||||
#define B111 7
|
||||
#define B0111 7
|
||||
#define B00111 7
|
||||
#define B000111 7
|
||||
#define B0000111 7
|
||||
#define B00000111 7
|
||||
#define B1000 8
|
||||
#define B01000 8
|
||||
#define B001000 8
|
||||
#define B0001000 8
|
||||
#define B00001000 8
|
||||
#define B1001 9
|
||||
#define B01001 9
|
||||
#define B001001 9
|
||||
#define B0001001 9
|
||||
#define B00001001 9
|
||||
#define B1010 10
|
||||
#define B01010 10
|
||||
#define B001010 10
|
||||
#define B0001010 10
|
||||
#define B00001010 10
|
||||
#define B1011 11
|
||||
#define B01011 11
|
||||
#define B001011 11
|
||||
#define B0001011 11
|
||||
#define B00001011 11
|
||||
#define B1100 12
|
||||
#define B01100 12
|
||||
#define B001100 12
|
||||
#define B0001100 12
|
||||
#define B00001100 12
|
||||
#define B1101 13
|
||||
#define B01101 13
|
||||
#define B001101 13
|
||||
#define B0001101 13
|
||||
#define B00001101 13
|
||||
#define B1110 14
|
||||
#define B01110 14
|
||||
#define B001110 14
|
||||
#define B0001110 14
|
||||
#define B00001110 14
|
||||
#define B1111 15
|
||||
#define B01111 15
|
||||
#define B001111 15
|
||||
#define B0001111 15
|
||||
#define B00001111 15
|
||||
#define B10000 16
|
||||
#define B010000 16
|
||||
#define B0010000 16
|
||||
#define B00010000 16
|
||||
#define B10001 17
|
||||
#define B010001 17
|
||||
#define B0010001 17
|
||||
#define B00010001 17
|
||||
#define B10010 18
|
||||
#define B010010 18
|
||||
#define B0010010 18
|
||||
#define B00010010 18
|
||||
#define B10011 19
|
||||
#define B010011 19
|
||||
#define B0010011 19
|
||||
#define B00010011 19
|
||||
#define B10100 20
|
||||
#define B010100 20
|
||||
#define B0010100 20
|
||||
#define B00010100 20
|
||||
#define B10101 21
|
||||
#define B010101 21
|
||||
#define B0010101 21
|
||||
#define B00010101 21
|
||||
#define B10110 22
|
||||
#define B010110 22
|
||||
#define B0010110 22
|
||||
#define B00010110 22
|
||||
#define B10111 23
|
||||
#define B010111 23
|
||||
#define B0010111 23
|
||||
#define B00010111 23
|
||||
#define B11000 24
|
||||
#define B011000 24
|
||||
#define B0011000 24
|
||||
#define B00011000 24
|
||||
#define B11001 25
|
||||
#define B011001 25
|
||||
#define B0011001 25
|
||||
#define B00011001 25
|
||||
#define B11010 26
|
||||
#define B011010 26
|
||||
#define B0011010 26
|
||||
#define B00011010 26
|
||||
#define B11011 27
|
||||
#define B011011 27
|
||||
#define B0011011 27
|
||||
#define B00011011 27
|
||||
#define B11100 28
|
||||
#define B011100 28
|
||||
#define B0011100 28
|
||||
#define B00011100 28
|
||||
#define B11101 29
|
||||
#define B011101 29
|
||||
#define B0011101 29
|
||||
#define B00011101 29
|
||||
#define B11110 30
|
||||
#define B011110 30
|
||||
#define B0011110 30
|
||||
#define B00011110 30
|
||||
#define B11111 31
|
||||
#define B011111 31
|
||||
#define B0011111 31
|
||||
#define B00011111 31
|
||||
#define B100000 32
|
||||
#define B0100000 32
|
||||
#define B00100000 32
|
||||
#define B100001 33
|
||||
#define B0100001 33
|
||||
#define B00100001 33
|
||||
#define B100010 34
|
||||
#define B0100010 34
|
||||
#define B00100010 34
|
||||
#define B100011 35
|
||||
#define B0100011 35
|
||||
#define B00100011 35
|
||||
#define B100100 36
|
||||
#define B0100100 36
|
||||
#define B00100100 36
|
||||
#define B100101 37
|
||||
#define B0100101 37
|
||||
#define B00100101 37
|
||||
#define B100110 38
|
||||
#define B0100110 38
|
||||
#define B00100110 38
|
||||
#define B100111 39
|
||||
#define B0100111 39
|
||||
#define B00100111 39
|
||||
#define B101000 40
|
||||
#define B0101000 40
|
||||
#define B00101000 40
|
||||
#define B101001 41
|
||||
#define B0101001 41
|
||||
#define B00101001 41
|
||||
#define B101010 42
|
||||
#define B0101010 42
|
||||
#define B00101010 42
|
||||
#define B101011 43
|
||||
#define B0101011 43
|
||||
#define B00101011 43
|
||||
#define B101100 44
|
||||
#define B0101100 44
|
||||
#define B00101100 44
|
||||
#define B101101 45
|
||||
#define B0101101 45
|
||||
#define B00101101 45
|
||||
#define B101110 46
|
||||
#define B0101110 46
|
||||
#define B00101110 46
|
||||
#define B101111 47
|
||||
#define B0101111 47
|
||||
#define B00101111 47
|
||||
#define B110000 48
|
||||
#define B0110000 48
|
||||
#define B00110000 48
|
||||
#define B110001 49
|
||||
#define B0110001 49
|
||||
#define B00110001 49
|
||||
#define B110010 50
|
||||
#define B0110010 50
|
||||
#define B00110010 50
|
||||
#define B110011 51
|
||||
#define B0110011 51
|
||||
#define B00110011 51
|
||||
#define B110100 52
|
||||
#define B0110100 52
|
||||
#define B00110100 52
|
||||
#define B110101 53
|
||||
#define B0110101 53
|
||||
#define B00110101 53
|
||||
#define B110110 54
|
||||
#define B0110110 54
|
||||
#define B00110110 54
|
||||
#define B110111 55
|
||||
#define B0110111 55
|
||||
#define B00110111 55
|
||||
#define B111000 56
|
||||
#define B0111000 56
|
||||
#define B00111000 56
|
||||
#define B111001 57
|
||||
#define B0111001 57
|
||||
#define B00111001 57
|
||||
#define B111010 58
|
||||
#define B0111010 58
|
||||
#define B00111010 58
|
||||
#define B111011 59
|
||||
#define B0111011 59
|
||||
#define B00111011 59
|
||||
#define B111100 60
|
||||
#define B0111100 60
|
||||
#define B00111100 60
|
||||
#define B111101 61
|
||||
#define B0111101 61
|
||||
#define B00111101 61
|
||||
#define B111110 62
|
||||
#define B0111110 62
|
||||
#define B00111110 62
|
||||
#define B111111 63
|
||||
#define B0111111 63
|
||||
#define B00111111 63
|
||||
#define B1000000 64
|
||||
#define B01000000 64
|
||||
#define B1000001 65
|
||||
#define B01000001 65
|
||||
#define B1000010 66
|
||||
#define B01000010 66
|
||||
#define B1000011 67
|
||||
#define B01000011 67
|
||||
#define B1000100 68
|
||||
#define B01000100 68
|
||||
#define B1000101 69
|
||||
#define B01000101 69
|
||||
#define B1000110 70
|
||||
#define B01000110 70
|
||||
#define B1000111 71
|
||||
#define B01000111 71
|
||||
#define B1001000 72
|
||||
#define B01001000 72
|
||||
#define B1001001 73
|
||||
#define B01001001 73
|
||||
#define B1001010 74
|
||||
#define B01001010 74
|
||||
#define B1001011 75
|
||||
#define B01001011 75
|
||||
#define B1001100 76
|
||||
#define B01001100 76
|
||||
#define B1001101 77
|
||||
#define B01001101 77
|
||||
#define B1001110 78
|
||||
#define B01001110 78
|
||||
#define B1001111 79
|
||||
#define B01001111 79
|
||||
#define B1010000 80
|
||||
#define B01010000 80
|
||||
#define B1010001 81
|
||||
#define B01010001 81
|
||||
#define B1010010 82
|
||||
#define B01010010 82
|
||||
#define B1010011 83
|
||||
#define B01010011 83
|
||||
#define B1010100 84
|
||||
#define B01010100 84
|
||||
#define B1010101 85
|
||||
#define B01010101 85
|
||||
#define B1010110 86
|
||||
#define B01010110 86
|
||||
#define B1010111 87
|
||||
#define B01010111 87
|
||||
#define B1011000 88
|
||||
#define B01011000 88
|
||||
#define B1011001 89
|
||||
#define B01011001 89
|
||||
#define B1011010 90
|
||||
#define B01011010 90
|
||||
#define B1011011 91
|
||||
#define B01011011 91
|
||||
#define B1011100 92
|
||||
#define B01011100 92
|
||||
#define B1011101 93
|
||||
#define B01011101 93
|
||||
#define B1011110 94
|
||||
#define B01011110 94
|
||||
#define B1011111 95
|
||||
#define B01011111 95
|
||||
#define B1100000 96
|
||||
#define B01100000 96
|
||||
#define B1100001 97
|
||||
#define B01100001 97
|
||||
#define B1100010 98
|
||||
#define B01100010 98
|
||||
#define B1100011 99
|
||||
#define B01100011 99
|
||||
#define B1100100 100
|
||||
#define B01100100 100
|
||||
#define B1100101 101
|
||||
#define B01100101 101
|
||||
#define B1100110 102
|
||||
#define B01100110 102
|
||||
#define B1100111 103
|
||||
#define B01100111 103
|
||||
#define B1101000 104
|
||||
#define B01101000 104
|
||||
#define B1101001 105
|
||||
#define B01101001 105
|
||||
#define B1101010 106
|
||||
#define B01101010 106
|
||||
#define B1101011 107
|
||||
#define B01101011 107
|
||||
#define B1101100 108
|
||||
#define B01101100 108
|
||||
#define B1101101 109
|
||||
#define B01101101 109
|
||||
#define B1101110 110
|
||||
#define B01101110 110
|
||||
#define B1101111 111
|
||||
#define B01101111 111
|
||||
#define B1110000 112
|
||||
#define B01110000 112
|
||||
#define B1110001 113
|
||||
#define B01110001 113
|
||||
#define B1110010 114
|
||||
#define B01110010 114
|
||||
#define B1110011 115
|
||||
#define B01110011 115
|
||||
#define B1110100 116
|
||||
#define B01110100 116
|
||||
#define B1110101 117
|
||||
#define B01110101 117
|
||||
#define B1110110 118
|
||||
#define B01110110 118
|
||||
#define B1110111 119
|
||||
#define B01110111 119
|
||||
#define B1111000 120
|
||||
#define B01111000 120
|
||||
#define B1111001 121
|
||||
#define B01111001 121
|
||||
#define B1111010 122
|
||||
#define B01111010 122
|
||||
#define B1111011 123
|
||||
#define B01111011 123
|
||||
#define B1111100 124
|
||||
#define B01111100 124
|
||||
#define B1111101 125
|
||||
#define B01111101 125
|
||||
#define B1111110 126
|
||||
#define B01111110 126
|
||||
#define B1111111 127
|
||||
#define B01111111 127
|
||||
#define B10000000 128
|
||||
#define B10000001 129
|
||||
#define B10000010 130
|
||||
#define B10000011 131
|
||||
#define B10000100 132
|
||||
#define B10000101 133
|
||||
#define B10000110 134
|
||||
#define B10000111 135
|
||||
#define B10001000 136
|
||||
#define B10001001 137
|
||||
#define B10001010 138
|
||||
#define B10001011 139
|
||||
#define B10001100 140
|
||||
#define B10001101 141
|
||||
#define B10001110 142
|
||||
#define B10001111 143
|
||||
#define B10010000 144
|
||||
#define B10010001 145
|
||||
#define B10010010 146
|
||||
#define B10010011 147
|
||||
#define B10010100 148
|
||||
#define B10010101 149
|
||||
#define B10010110 150
|
||||
#define B10010111 151
|
||||
#define B10011000 152
|
||||
#define B10011001 153
|
||||
#define B10011010 154
|
||||
#define B10011011 155
|
||||
#define B10011100 156
|
||||
#define B10011101 157
|
||||
#define B10011110 158
|
||||
#define B10011111 159
|
||||
#define B10100000 160
|
||||
#define B10100001 161
|
||||
#define B10100010 162
|
||||
#define B10100011 163
|
||||
#define B10100100 164
|
||||
#define B10100101 165
|
||||
#define B10100110 166
|
||||
#define B10100111 167
|
||||
#define B10101000 168
|
||||
#define B10101001 169
|
||||
#define B10101010 170
|
||||
#define B10101011 171
|
||||
#define B10101100 172
|
||||
#define B10101101 173
|
||||
#define B10101110 174
|
||||
#define B10101111 175
|
||||
#define B10110000 176
|
||||
#define B10110001 177
|
||||
#define B10110010 178
|
||||
#define B10110011 179
|
||||
#define B10110100 180
|
||||
#define B10110101 181
|
||||
#define B10110110 182
|
||||
#define B10110111 183
|
||||
#define B10111000 184
|
||||
#define B10111001 185
|
||||
#define B10111010 186
|
||||
#define B10111011 187
|
||||
#define B10111100 188
|
||||
#define B10111101 189
|
||||
#define B10111110 190
|
||||
#define B10111111 191
|
||||
#define B11000000 192
|
||||
#define B11000001 193
|
||||
#define B11000010 194
|
||||
#define B11000011 195
|
||||
#define B11000100 196
|
||||
#define B11000101 197
|
||||
#define B11000110 198
|
||||
#define B11000111 199
|
||||
#define B11001000 200
|
||||
#define B11001001 201
|
||||
#define B11001010 202
|
||||
#define B11001011 203
|
||||
#define B11001100 204
|
||||
#define B11001101 205
|
||||
#define B11001110 206
|
||||
#define B11001111 207
|
||||
#define B11010000 208
|
||||
#define B11010001 209
|
||||
#define B11010010 210
|
||||
#define B11010011 211
|
||||
#define B11010100 212
|
||||
#define B11010101 213
|
||||
#define B11010110 214
|
||||
#define B11010111 215
|
||||
#define B11011000 216
|
||||
#define B11011001 217
|
||||
#define B11011010 218
|
||||
#define B11011011 219
|
||||
#define B11011100 220
|
||||
#define B11011101 221
|
||||
#define B11011110 222
|
||||
#define B11011111 223
|
||||
#define B11100000 224
|
||||
#define B11100001 225
|
||||
#define B11100010 226
|
||||
#define B11100011 227
|
||||
#define B11100100 228
|
||||
#define B11100101 229
|
||||
#define B11100110 230
|
||||
#define B11100111 231
|
||||
#define B11101000 232
|
||||
#define B11101001 233
|
||||
#define B11101010 234
|
||||
#define B11101011 235
|
||||
#define B11101100 236
|
||||
#define B11101101 237
|
||||
#define B11101110 238
|
||||
#define B11101111 239
|
||||
#define B11110000 240
|
||||
#define B11110001 241
|
||||
#define B11110010 242
|
||||
#define B11110011 243
|
||||
#define B11110100 244
|
||||
#define B11110101 245
|
||||
#define B11110110 246
|
||||
#define B11110111 247
|
||||
#define B11111000 248
|
||||
#define B11111001 249
|
||||
#define B11111010 250
|
||||
#define B11111011 251
|
||||
#define B11111100 252
|
||||
#define B11111101 253
|
||||
#define B11111110 254
|
||||
#define B11111111 255
|
||||
|
||||
#endif /* _BIT_CONSTANTS_H_ */
|
|
@ -0,0 +1,35 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/* Note: Use of this header file is deprecated. Use bit_constants.h
|
||||
instead. */
|
||||
|
||||
#ifndef _WIRISH_BITS_H_
|
||||
#define _WIRISH_BITS_H_
|
||||
|
||||
#include <bit_constants.h>
|
||||
|
||||
#endif
|
|
@ -0,0 +1,172 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Bryan Newbold.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/boards.h
|
||||
* @author Bryan Newbold <bnewbold@leaflabs.com>,
|
||||
* Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief init() and board-specific pin information.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_BOARDS_H_
|
||||
#define _WIRISH_BOARDS_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <wirish_types.h>
|
||||
#include <board/board.h>
|
||||
|
||||
/* Set of all possible pin names; not all boards have all these (note
|
||||
* that we use the Dx convention since all of the Maple's pins are
|
||||
* "digital" pins (e.g. can be used with digitalRead() and
|
||||
* digitalWrite()), but not all of them are connected to ADCs. */
|
||||
enum {
|
||||
D0, D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15, D16,
|
||||
D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30, D31,
|
||||
D32, D33, D34, D35, D36, D37, D38, D39, D40, D41, D42, D43, D44, D45, D46,
|
||||
D47, D48, D49, D50, D51, D52, D53, D54, D55, D56, D57, D58, D59, D60, D61,
|
||||
D62, D63, D64, D65, D66, D67, D68, D69, D70, D71, D72, D73, D74, D75, D76,
|
||||
D77, D78, D79, D80, D81, D82, D83, D84, D85, D86, D87, D88, D89, D90, D91,
|
||||
D92, D93, D94, D95, D96, D97, D98, D99, D100, D101, D102, D103, D104, D105,
|
||||
D106, D107, D108, D109, D110, D111, };
|
||||
|
||||
/**
|
||||
* @brief Maps each Maple pin to a corresponding stm32_pin_info.
|
||||
* @see stm32_pin_info
|
||||
*/
|
||||
extern const stm32_pin_info PIN_MAP[];
|
||||
|
||||
/**
|
||||
* @brief Pins capable of PWM output.
|
||||
*
|
||||
* Its length is BOARD_NR_PWM_PINS.
|
||||
*/
|
||||
extern const uint8 boardPWMPins[];
|
||||
|
||||
/**
|
||||
* @brief Array of pins capable of analog input.
|
||||
*
|
||||
* Its length is BOARD_NR_ADC_PINS.
|
||||
*/
|
||||
extern const uint8 boardADCPins[];
|
||||
|
||||
/**
|
||||
* @brief Pins which are connected to external hardware.
|
||||
*
|
||||
* For example, on Maple boards, it always at least includes
|
||||
* PB1 for the LED. Its length is BOARD_NR_USED_PINS.
|
||||
*/
|
||||
extern const uint8 boardUsedPins[];
|
||||
|
||||
/**
|
||||
* @brief Generic board initialization function.
|
||||
*
|
||||
* This function is called before main(). It ensures that the clocks
|
||||
* and peripherals are configured properly for use with wirish, then
|
||||
* calls boardInit().
|
||||
*
|
||||
* @see boardInit()
|
||||
*/
|
||||
void init(void);
|
||||
|
||||
/**
|
||||
* @brief Board-specific initialization function.
|
||||
*
|
||||
* This function is called from init() after all generic board
|
||||
* initialization has been performed. Each board is required to
|
||||
* define its own.
|
||||
*
|
||||
* @see init()
|
||||
*/
|
||||
extern void boardInit(void);
|
||||
|
||||
/**
|
||||
* @brief Test if a pin is used for a special purpose on your board.
|
||||
* @param pin Pin to test
|
||||
* @return true if the given pin is in boardUsedPins, and false otherwise.
|
||||
* @see boardUsedPins
|
||||
*/
|
||||
bool boardUsesPin(uint8 pin);
|
||||
|
||||
/*
|
||||
* Derived and default board definitions
|
||||
*/
|
||||
|
||||
#define CLOCK_SPEED_MHZ CYCLES_PER_MICROSECOND
|
||||
#define CLOCK_SPEED_HZ (CLOCK_SPEED_MHZ * 1000000UL)
|
||||
|
||||
|
||||
#ifndef BOARD_BUTTON_PRESSED_LEVEL
|
||||
#define BOARD_BUTTON_PRESSED_LEVEL HIGH
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Does the board break out a USART/UART's RX and TX pins?
|
||||
*
|
||||
* BOARD_HAVE_USART(n) is nonzero iff USARTn is available (n must be
|
||||
* an integer literal, 1 through 6). Also see BOARD_HAVE_USART1, ...,
|
||||
* BOARD_HAVE_UART4 (sic), etc.
|
||||
*/
|
||||
#define BOARD_HAVE_USART(n) (defined(BOARD_USART##n##_TX_PIN) && \
|
||||
defined(BOARD_USART##n##_RX_PIN))
|
||||
/** Feature test: nonzero iff the board has USART1. */
|
||||
#define BOARD_HAVE_USART1 BOARD_HAVE_USART(1)
|
||||
/** Feature test: nonzero iff the board has USART2, 0 otherwise. */
|
||||
#define BOARD_HAVE_USART2 BOARD_HAVE_USART(2)
|
||||
/** Feature test: nonzero iff the board has USART3, 0 otherwise. */
|
||||
#define BOARD_HAVE_USART3 BOARD_HAVE_USART(3)
|
||||
/** Feature test: nonzero iff the board has UART4, 0 otherwise. */
|
||||
#define BOARD_HAVE_UART4 BOARD_HAVE_USART(4)
|
||||
/** Feature test: nonzero iff the board has UART5, 0 otherwise. */
|
||||
#define BOARD_HAVE_UART5 BOARD_HAVE_USART(5)
|
||||
/** Feature test: nonzero iff the board has USART6, 0 otherwise. */
|
||||
#define BOARD_HAVE_USART6 BOARD_HAVE_USART(6)
|
||||
|
||||
/**
|
||||
* @brief Does the board break out a SPI peripheral's pins?
|
||||
*
|
||||
* BOARD_HAVE_SPI(n) is nonzero iff SPIn is available (n must be an
|
||||
* integer literal: 1, 2, or 3). Also see BOARD_HAVE_SPI1,
|
||||
* BOARD_HAVE_SPI2, BOARD_HAVE_SPI3. */
|
||||
#define BOARD_HAVE_SPI(n) (defined(BOARD_SPI##n##_NSS_PIN) && \
|
||||
defined(BOARD_SPI##n##_SCK_PIN) && \
|
||||
defined(BOARD_SPI##n##_MISO_PIN) && \
|
||||
defined(BOARD_SPI##n##_MOSI_PIN))
|
||||
/** Feature test: nonzero iff the board has SPI1. */
|
||||
#define BOARD_HAVE_SPI1 BOARD_HAVE_SPI(1)
|
||||
/** Feature test: nonzero iff the board has SPI2. */
|
||||
#define BOARD_HAVE_SPI2 BOARD_HAVE_SPI(2)
|
||||
/** Feature test: nonzero iff the board has SPI3. */
|
||||
#define BOARD_HAVE_SPI3 BOARD_HAVE_SPI(3)
|
||||
|
||||
/**
|
||||
* @brief Feature test: nonzero iff the board has SerialUSB.
|
||||
*/
|
||||
//Roger Clark. Change so that BOARD_HAVE_SERIALUSB is always true, so that it can be controller by -DSERIAL_USB
|
||||
#define BOARD_HAVE_SERIALUSB 1
|
||||
|
||||
/*(defined(BOARD_USB_DISC_DEV) && defined(BOARD_USB_DISC_BIT))*/
|
||||
|
||||
#endif
|
|
@ -0,0 +1,71 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/boards_private.h
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Private board support header.
|
||||
*
|
||||
* This file declares chip-specific variables and functions which
|
||||
* determine how init() behaves. It is not part of the public Wirish
|
||||
* API, and can change without notice.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_BOARDS_PRIVATE_H_
|
||||
#define _WIRISH_BOARDS_PRIVATE_H_
|
||||
|
||||
#include <libmaple/rcc.h>
|
||||
#include <libmaple/adc.h>
|
||||
|
||||
/* Makes the PIN_MAP rows more human-readable. */
|
||||
#define PMAP_ROW(gpio_dev, gpio_bit, timer_dev, timer_ch, adc_dev, adc_ch) \
|
||||
{ gpio_dev, timer_dev, adc_dev, gpio_bit, timer_ch, adc_ch }
|
||||
|
||||
namespace wirish {
|
||||
namespace priv {
|
||||
|
||||
/*
|
||||
* Chip-specific initialization data
|
||||
*/
|
||||
|
||||
extern rcc_pll_cfg w_board_pll_cfg;
|
||||
extern adc_prescaler w_adc_pre;
|
||||
extern adc_smp_rate w_adc_smp;
|
||||
|
||||
/*
|
||||
* Chip-specific initialization routines and helper functions.
|
||||
*/
|
||||
|
||||
void board_reset_pll(void);
|
||||
void board_setup_clock_prescalers(void);
|
||||
void board_setup_gpio(void);
|
||||
void board_setup_usb(void);
|
||||
void series_init(void);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,6 @@
|
|||
/* We compile with nodefaultlibs, so we need to provide an error
|
||||
* handler for an empty pure virtual function */
|
||||
extern "C" void __cxa_pure_virtual(void) {
|
||||
while(1)
|
||||
;
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/ext_interrupts.cpp
|
||||
* @brief Wiring-like interface for external interrupts
|
||||
*/
|
||||
|
||||
#include "ext_interrupts.h"
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/exti.h>
|
||||
|
||||
#include "boards.h"
|
||||
|
||||
static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode);
|
||||
|
||||
void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS || !handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
exti_trigger_mode outMode = exti_out_mode(mode);
|
||||
|
||||
exti_attach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit),
|
||||
gpio_exti_port(PIN_MAP[pin].gpio_device),
|
||||
handler,
|
||||
outMode);
|
||||
}
|
||||
|
||||
void attachInterrupt(uint8 pin, voidArgumentFuncPtr handler, void *arg,
|
||||
ExtIntTriggerMode mode) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS || !handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
exti_trigger_mode outMode = exti_out_mode(mode);
|
||||
|
||||
exti_attach_callback((exti_num)(PIN_MAP[pin].gpio_bit),
|
||||
gpio_exti_port(PIN_MAP[pin].gpio_device),
|
||||
handler,
|
||||
arg,
|
||||
outMode);
|
||||
}
|
||||
|
||||
void detachInterrupt(uint8 pin) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS) {
|
||||
return;
|
||||
}
|
||||
|
||||
exti_detach_interrupt((exti_num)(PIN_MAP[pin].gpio_bit));
|
||||
}
|
||||
|
||||
static inline exti_trigger_mode exti_out_mode(ExtIntTriggerMode mode) {
|
||||
switch (mode) {
|
||||
case RISING:
|
||||
return EXTI_RISING;
|
||||
case FALLING:
|
||||
return EXTI_FALLING;
|
||||
case CHANGE:
|
||||
return EXTI_RISING_FALLING;
|
||||
}
|
||||
// Can't happen
|
||||
ASSERT(0);
|
||||
return (exti_trigger_mode)0;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/ext_interrupts.h
|
||||
* @brief Wiring-like external interrupt prototypes and types.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_EXT_INTERRUPTS_H_
|
||||
#define _WIRISH_EXT_INTERRUPTS_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <libmaple/nvic.h>
|
||||
|
||||
/**
|
||||
* The kind of transition on an external pin which should trigger an
|
||||
* interrupt.
|
||||
*/
|
||||
typedef enum ExtIntTriggerMode {
|
||||
RISING, /**< To trigger an interrupt when the pin transitions LOW
|
||||
to HIGH */
|
||||
FALLING, /**< To trigger an interrupt when the pin transitions
|
||||
HIGH to LOW */
|
||||
CHANGE /**< To trigger an interrupt when the pin transitions from
|
||||
LOW to HIGH or HIGH to LOW (i.e., when the pin
|
||||
changes). */
|
||||
} ExtIntTriggerMode;
|
||||
|
||||
/**
|
||||
* @brief Registers an interrupt handler on a pin.
|
||||
*
|
||||
* The interrupt will be triggered on a given transition on the pin,
|
||||
* as specified by the mode parameter. The handler runs in interrupt
|
||||
* context. The new handler will replace whatever handler is
|
||||
* currently registered for the pin, if any.
|
||||
*
|
||||
* @param pin Pin number
|
||||
* @param handler Function to run upon external interrupt trigger.
|
||||
* The handler should take no arguments, and have void
|
||||
* return type.
|
||||
* @param mode Type of transition to trigger on, e.g. falling, rising, etc.
|
||||
*
|
||||
* @sideeffect Registers a handler
|
||||
* @see detachInterrupt()
|
||||
*/
|
||||
void attachInterrupt(uint8 pin, voidFuncPtr handler, ExtIntTriggerMode mode);
|
||||
|
||||
/**
|
||||
* @brief Registers an interrupt handler on a pin.
|
||||
*
|
||||
* The interrupt will be triggered on a given transition on the pin,
|
||||
* as specified by the mode parameter. The handler runs in interrupt
|
||||
* context. The new handler will replace whatever handler is
|
||||
* currently registered for the pin, if any.
|
||||
*
|
||||
* @param pin Pin number
|
||||
* @param handler Static class member function to run upon external interrupt
|
||||
* trigger. The handler should take 1 argument and return void
|
||||
* @param arg Argument that the handler will be passed when it's called. One
|
||||
* use of this is to pass the specific instance of the class that
|
||||
* will handle the interrupt.
|
||||
* @param mode Type of transition to trigger on, e.g. falling, rising, etc.
|
||||
*
|
||||
* @sideeffect Registers a handler
|
||||
* @see detachInterrupt()
|
||||
*/
|
||||
void attachInterrupt(uint8 pin, voidArgumentFuncPtr handler, void *arg,
|
||||
ExtIntTriggerMode mode);
|
||||
|
||||
/**
|
||||
* @brief Disable any registered external interrupt.
|
||||
* @param pin Maple pin number
|
||||
* @sideeffect unregisters external interrupt handler
|
||||
* @see attachInterrupt()
|
||||
*/
|
||||
void detachInterrupt(uint8 pin);
|
||||
|
||||
/**
|
||||
* Re-enable interrupts.
|
||||
*
|
||||
* Call this after noInterrupts() to re-enable interrupt handling,
|
||||
* after you have finished with a timing-critical section of code.
|
||||
*
|
||||
* @see noInterrupts()
|
||||
*/
|
||||
static __always_inline void interrupts() {
|
||||
nvic_globalirq_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable interrupts.
|
||||
*
|
||||
* After calling this function, all user-programmable interrupts will
|
||||
* be disabled. You can call this function before a timing-critical
|
||||
* section of code, then call interrupts() to re-enable interrupt
|
||||
* handling.
|
||||
*
|
||||
* @see interrupts()
|
||||
*/
|
||||
static __always_inline void noInterrupts() {
|
||||
nvic_globalirq_disable();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Copyright (c) 2012 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Empty yield() hook.
|
||||
*
|
||||
* This function is intended to be used by library writers to build
|
||||
* libraries or sketches that supports cooperative threads.
|
||||
*
|
||||
* Its defined as a weak symbol and it can be redefined to implement a
|
||||
* real cooperative scheduler.
|
||||
*/
|
||||
static void __empty() {
|
||||
// Empty
|
||||
}
|
||||
void yield(void) __attribute__ ((weak, alias("__empty")));
|
|
@ -0,0 +1,163 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/io.h
|
||||
* @brief Wiring-style pin I/O interface.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_IO_H_
|
||||
#define _WIRISH_IO_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <boards.h>
|
||||
|
||||
/**
|
||||
* Specifies a GPIO pin behavior.
|
||||
* @see pinMode()
|
||||
*/
|
||||
typedef enum WiringPinMode {
|
||||
OUTPUT, /**< Basic digital output: when the pin is HIGH, the
|
||||
voltage is held at +3.3v (Vcc) and when it is LOW, it
|
||||
is pulled down to ground. */
|
||||
|
||||
OUTPUT_OPEN_DRAIN, /**< In open drain mode, the pin indicates
|
||||
"low" by accepting current flow to ground
|
||||
and "high" by providing increased
|
||||
impedance. An example use would be to
|
||||
connect a pin to a bus line (which is pulled
|
||||
up to a positive voltage by a separate
|
||||
supply through a large resistor). When the
|
||||
pin is high, not much current flows through
|
||||
to ground and the line stays at positive
|
||||
voltage; when the pin is low, the bus
|
||||
"drains" to ground with a small amount of
|
||||
current constantly flowing through the large
|
||||
resistor from the external supply. In this
|
||||
mode, no current is ever actually sourced
|
||||
from the pin. */
|
||||
|
||||
INPUT, /**< Basic digital input. The pin voltage is sampled; when
|
||||
it is closer to 3.3v (Vcc) the pin status is high, and
|
||||
when it is closer to 0v (ground) it is low. If no
|
||||
external circuit is pulling the pin voltage to high or
|
||||
low, it will tend to randomly oscillate and be very
|
||||
sensitive to noise (e.g., a breath of air across the pin
|
||||
might cause the state to flip). */
|
||||
|
||||
INPUT_ANALOG, /**< This is a special mode for when the pin will be
|
||||
used for analog (not digital) reads. Enables ADC
|
||||
conversion to be performed on the voltage at the
|
||||
pin. */
|
||||
|
||||
INPUT_PULLUP, /**< The state of the pin in this mode is reported
|
||||
the same way as with INPUT, but the pin voltage
|
||||
is gently "pulled up" towards +3.3v. This means
|
||||
the state will be high unless an external device
|
||||
is specifically pulling the pin down to ground,
|
||||
in which case the "gentle" pull up will not
|
||||
affect the state of the input. */
|
||||
|
||||
INPUT_PULLDOWN, /**< The state of the pin in this mode is reported
|
||||
the same way as with INPUT, but the pin voltage
|
||||
is gently "pulled down" towards 0v. This means
|
||||
the state will be low unless an external device
|
||||
is specifically pulling the pin up to 3.3v, in
|
||||
which case the "gentle" pull down will not
|
||||
affect the state of the input. */
|
||||
|
||||
INPUT_FLOATING, /**< Synonym for INPUT. */
|
||||
|
||||
PWM, /**< This is a special mode for when the pin will be used for
|
||||
PWM output (a special case of digital output). */
|
||||
|
||||
PWM_OPEN_DRAIN, /**< Like PWM, except that instead of alternating
|
||||
cycles of LOW and HIGH, the voltage on the pin
|
||||
consists of alternating cycles of LOW and
|
||||
floating (disconnected). */
|
||||
} WiringPinMode;
|
||||
|
||||
/**
|
||||
* Configure behavior of a GPIO pin.
|
||||
*
|
||||
* @param pin Number of pin to configure.
|
||||
* @param mode Mode corresponding to desired pin behavior.
|
||||
* @see WiringPinMode
|
||||
*/
|
||||
void pinMode(uint8 pin, WiringPinMode mode);
|
||||
|
||||
#define HIGH 0x1
|
||||
#define LOW 0x0
|
||||
|
||||
/**
|
||||
* Writes a (digital) value to a pin. The pin must have its
|
||||
* mode set to OUTPUT or OUTPUT_OPEN_DRAIN.
|
||||
*
|
||||
* @param pin Pin to write to.
|
||||
* @param value Either LOW (write a 0) or HIGH (write a 1).
|
||||
* @see pinMode()
|
||||
*/
|
||||
void digitalWrite(uint8 pin, uint8 value);
|
||||
|
||||
/**
|
||||
* Read a digital value from a pin. The pin must have its mode set to
|
||||
* one of INPUT, INPUT_PULLUP, and INPUT_PULLDOWN.
|
||||
*
|
||||
* @param pin Pin to read from.
|
||||
* @return LOW or HIGH.
|
||||
* @see pinMode()
|
||||
*/
|
||||
uint32 digitalRead(uint8 pin);
|
||||
|
||||
/**
|
||||
* Read an analog value from pin. This function blocks during ADC
|
||||
* conversion, and has 12 bits of resolution. The pin must have its
|
||||
* mode set to INPUT_ANALOG.
|
||||
*
|
||||
* @param pin Pin to read from.
|
||||
* @return Converted voltage, in the range 0--4095, (i.e. a 12-bit ADC
|
||||
* conversion).
|
||||
* @see pinMode()
|
||||
*/
|
||||
uint16 analogRead(uint8 pin);
|
||||
|
||||
/**
|
||||
* Shift out a byte of data, one bit at a time.
|
||||
*
|
||||
* This function starts at either the most significant or least
|
||||
* significant bit in a byte value, and shifts out each byte in order
|
||||
* onto a data pin. After each bit is written to the data pin, a
|
||||
* separate clock pin is pulsed to indicate that the new bit is
|
||||
* available.
|
||||
*
|
||||
* @param dataPin Pin to shift data out on
|
||||
* @param clockPin Pin to pulse after each bit is shifted out
|
||||
* @param bitOrder Either MSBFIRST (big-endian) or LSBFIRST (little-endian).
|
||||
* @param value Value to shift out
|
||||
*/
|
||||
void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,170 @@
|
|||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "itoa.h"
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif // __cplusplus
|
||||
|
||||
#if 0
|
||||
/* reverse: reverse string s in place */
|
||||
static void reverse( char s[] )
|
||||
{
|
||||
int i, j ;
|
||||
char c ;
|
||||
|
||||
for ( i = 0, j = strlen(s)-1 ; i < j ; i++, j-- )
|
||||
{
|
||||
c = s[i] ;
|
||||
s[i] = s[j] ;
|
||||
s[j] = c ;
|
||||
}
|
||||
}
|
||||
|
||||
/* itoa: convert n to characters in s */
|
||||
extern void itoa( int n, char s[] )
|
||||
{
|
||||
int i, sign ;
|
||||
|
||||
if ( (sign = n) < 0 ) /* record sign */
|
||||
{
|
||||
n = -n; /* make n positive */
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{ /* generate digits in reverse order */
|
||||
s[i++] = n % 10 + '0'; /* get next digit */
|
||||
} while ((n /= 10) > 0) ; /* delete it */
|
||||
|
||||
if (sign < 0 )
|
||||
{
|
||||
s[i++] = '-';
|
||||
}
|
||||
|
||||
s[i] = '\0';
|
||||
|
||||
reverse( s ) ;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
extern char* itoa( int value, char *string, int radix )
|
||||
{
|
||||
return ltoa( value, string, radix ) ;
|
||||
}
|
||||
|
||||
extern char* ltoa( long value, char *string, int radix )
|
||||
{
|
||||
char tmp[33];
|
||||
char *tp = tmp;
|
||||
long i;
|
||||
unsigned long v;
|
||||
int sign;
|
||||
char *sp;
|
||||
|
||||
if ( string == NULL )
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
if (radix > 36 || radix <= 1)
|
||||
{
|
||||
return 0 ;
|
||||
}
|
||||
|
||||
sign = (radix == 10 && value < 0);
|
||||
if (sign)
|
||||
{
|
||||
v = -value;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = (unsigned long)value;
|
||||
}
|
||||
|
||||
while (v || tp == tmp)
|
||||
{
|
||||
i = v % radix;
|
||||
v = v / radix;
|
||||
if (i < 10)
|
||||
*tp++ = i+'0';
|
||||
else
|
||||
*tp++ = i + 'a' - 10;
|
||||
}
|
||||
|
||||
sp = string;
|
||||
|
||||
if (sign)
|
||||
*sp++ = '-';
|
||||
while (tp > tmp)
|
||||
*sp++ = *--tp;
|
||||
*sp = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
extern char* utoa( unsigned long value, char *string, int radix )
|
||||
{
|
||||
return ultoa( value, string, radix ) ;
|
||||
}
|
||||
|
||||
extern char* ultoa( unsigned long value, char *string, int radix )
|
||||
{
|
||||
char tmp[33];
|
||||
char *tp = tmp;
|
||||
long i;
|
||||
unsigned long v = value;
|
||||
char *sp;
|
||||
|
||||
if ( string == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (radix > 36 || radix <= 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (v || tp == tmp)
|
||||
{
|
||||
i = v % radix;
|
||||
v = v / radix;
|
||||
if (i < 10)
|
||||
*tp++ = i+'0';
|
||||
else
|
||||
*tp++ = i + 'a' - 10;
|
||||
}
|
||||
|
||||
sp = string;
|
||||
|
||||
|
||||
while (tp > tmp)
|
||||
*sp++ = *--tp;
|
||||
*sp = 0;
|
||||
|
||||
return string;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
See the GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ITOA_
|
||||
#define _ITOA_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif // __cplusplus
|
||||
|
||||
#if 0
|
||||
|
||||
extern void itoa( int n, char s[] ) ;
|
||||
|
||||
#else
|
||||
|
||||
extern char* itoa( int value, char *string, int radix ) ;
|
||||
extern char* ltoa( long value, char *string, int radix ) ;
|
||||
extern char* utoa( unsigned long value, char *string, int radix ) ;
|
||||
extern char* ultoa( unsigned long value, char *string, int radix ) ;
|
||||
#endif /* 0 */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // _ITOA_
|
|
@ -0,0 +1,109 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/adc.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>,
|
||||
* Perry Hung <perry@leaflabs.com>
|
||||
* @brief Analog to digital converter routines
|
||||
*/
|
||||
|
||||
#include <libmaple/adc.h>
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/rcc.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize an ADC peripheral.
|
||||
*
|
||||
* Initializes the RCC clock line for the given peripheral. Resets
|
||||
* ADC device registers.
|
||||
*
|
||||
* @param dev ADC peripheral to initialize
|
||||
*/
|
||||
void adc_init(const adc_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set external event select for regular group
|
||||
* @param dev ADC device
|
||||
* @param event Event used to trigger the start of conversion.
|
||||
* @see adc_extsel_event
|
||||
*/
|
||||
void adc_set_extsel(const adc_dev *dev, adc_extsel_event event) {
|
||||
uint32 cr2 = dev->regs->CR2;
|
||||
cr2 &= ~ADC_CR2_EXTSEL;
|
||||
cr2 |= event;
|
||||
dev->regs->CR2 = cr2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the sample rate for all channels on an ADC device.
|
||||
*
|
||||
* Don't call this during conversion.
|
||||
*
|
||||
* @param dev adc device
|
||||
* @param smp_rate sample rate to set
|
||||
* @see adc_smp_rate
|
||||
*/
|
||||
void adc_set_sample_rate(const adc_dev *dev, adc_smp_rate smp_rate) {
|
||||
uint32 adc_smpr1_val = 0, adc_smpr2_val = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (i < 8) {
|
||||
/* ADC_SMPR1 determines sample time for channels [10,17] */
|
||||
adc_smpr1_val |= smp_rate << (i * 3);
|
||||
}
|
||||
/* ADC_SMPR2 determines sample time for channels [0,9] */
|
||||
adc_smpr2_val |= smp_rate << (i * 3);
|
||||
}
|
||||
|
||||
dev->regs->SMPR1 = adc_smpr1_val;
|
||||
dev->regs->SMPR2 = adc_smpr2_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform a single synchronous software triggered conversion on a
|
||||
* channel.
|
||||
* @param dev ADC device to use for reading.
|
||||
* @param channel channel to convert
|
||||
* @return conversion result
|
||||
*/
|
||||
uint16 adc_read(const adc_dev *dev, uint8 channel) {
|
||||
adc_reg_map *regs = dev->regs;
|
||||
|
||||
adc_set_reg_seqlen(dev, 1);
|
||||
|
||||
regs->SQR3 = channel;
|
||||
regs->CR2 |= ADC_CR2_SWSTART;
|
||||
while (!(regs->SR & ADC_SR_EOC))
|
||||
;
|
||||
|
||||
return (uint16)(regs->DR & ADC_DR_DATA);
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/adc.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>,
|
||||
* Perry Hung <perry@leaflabs.com>
|
||||
* @brief STM32F1 ADC support.
|
||||
*/
|
||||
|
||||
#include <libmaple/adc.h>
|
||||
#include <libmaple/gpio.h>
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
adc_dev adc1 = {
|
||||
.regs = ADC1_BASE,
|
||||
.clk_id = RCC_ADC1,
|
||||
};
|
||||
/** ADC1 device. */
|
||||
const adc_dev *ADC1 = &adc1;
|
||||
|
||||
adc_dev adc2 = {
|
||||
.regs = ADC2_BASE,
|
||||
.clk_id = RCC_ADC2,
|
||||
};
|
||||
/** ADC2 device. */
|
||||
const adc_dev *ADC2 = &adc2;
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
adc_dev adc3 = {
|
||||
.regs = ADC3_BASE,
|
||||
.clk_id = RCC_ADC3,
|
||||
};
|
||||
/** ADC3 device. */
|
||||
const adc_dev *ADC3 = &adc3;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* STM32F1 routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Calibrate an ADC peripheral
|
||||
*
|
||||
* Availability: STM32F1.
|
||||
*
|
||||
* @param dev adc device
|
||||
*/
|
||||
void adc_calibrate(const adc_dev *dev) {
|
||||
__io uint32 *rstcal_bit = bb_perip(&(dev->regs->CR2), 3);
|
||||
__io uint32 *cal_bit = bb_perip(&(dev->regs->CR2), 2);
|
||||
|
||||
*rstcal_bit = 1;
|
||||
while (*rstcal_bit)
|
||||
;
|
||||
|
||||
*cal_bit = 1;
|
||||
while (*cal_bit)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common routines
|
||||
*/
|
||||
|
||||
void adc_set_prescaler(adc_prescaler pre) {
|
||||
rcc_set_prescaler(RCC_PRESCALER_ADC, (uint32)pre);
|
||||
}
|
||||
|
||||
void adc_foreach(void (*fn)(const adc_dev*)) {
|
||||
fn(ADC1);
|
||||
fn(ADC2);
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
fn(ADC3);
|
||||
#endif
|
||||
}
|
||||
|
||||
void adc_config_gpio(const adc_dev *ignored, gpio_dev *gdev, uint8 bit) {
|
||||
gpio_set_mode(gdev, bit, GPIO_INPUT_ANALOG);
|
||||
}
|
||||
|
||||
void adc_enable_single_swstart(const adc_dev *dev) {
|
||||
adc_init(dev);
|
||||
adc_set_extsel(dev, ADC_SWSTART);
|
||||
adc_set_exttrig(dev, 1);
|
||||
adc_enable(dev);
|
||||
adc_calibrate(dev);
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/bkp.c
|
||||
* @brief STM32F1 Backup register support.
|
||||
*/
|
||||
|
||||
#include <libmaple/bkp.h>
|
||||
#include <libmaple/pwr.h>
|
||||
#include <libmaple/rcc.h>
|
||||
#include <libmaple/bitband.h>
|
||||
|
||||
static inline __io uint32* data_register(uint8 reg);
|
||||
|
||||
bkp_dev bkp = {
|
||||
.regs = BKP_BASE,
|
||||
};
|
||||
/** Backup device. */
|
||||
const bkp_dev *BKP = &bkp;
|
||||
|
||||
/**
|
||||
* @brief Initialize backup interface.
|
||||
*
|
||||
* Enables the power and backup interface clocks, and resets the
|
||||
* backup device.
|
||||
*/
|
||||
void bkp_init(void) {
|
||||
/* Don't call pwr_init(), or you'll reset the device. We just
|
||||
* need the clock. */
|
||||
rcc_clk_enable(RCC_PWR);
|
||||
rcc_clk_enable(RCC_BKP);
|
||||
rcc_reset_dev(RCC_BKP);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable write access to the backup registers. Backup interface must
|
||||
* be initialized for subsequent register writes to work.
|
||||
* @see bkp_init()
|
||||
*/
|
||||
void bkp_enable_writes(void) {
|
||||
*bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable write access to the backup registers.
|
||||
*/
|
||||
void bkp_disable_writes(void) {
|
||||
*bb_perip(&PWR_BASE->CR, PWR_CR_DBP_BIT) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a value from given backup data register.
|
||||
* @param reg Data register to read, from 1 to BKP_NR_DATA_REGS (10 on
|
||||
* medium-density devices, 42 on high-density devices).
|
||||
*/
|
||||
uint16 bkp_read(uint8 reg) {
|
||||
__io uint32* dr = data_register(reg);
|
||||
if (!dr) {
|
||||
ASSERT(0); /* nonexistent register */
|
||||
return 0;
|
||||
}
|
||||
return (uint16)*dr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a value to given data register.
|
||||
*
|
||||
* Write access to backup registers must be enabled.
|
||||
*
|
||||
* @param reg Data register to write, from 1 to BKP_NR_DATA_REGS (10
|
||||
* on medium-density devices, 42 on high-density devices).
|
||||
* @param val Value to write into the register.
|
||||
* @see bkp_enable_writes()
|
||||
*/
|
||||
void bkp_write(uint8 reg, uint16 val) {
|
||||
__io uint32* dr = data_register(reg);
|
||||
if (!dr) {
|
||||
ASSERT(0); /* nonexistent register */
|
||||
return;
|
||||
}
|
||||
*dr = (uint32)val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Data register memory layout is not contiguous. It's split up from
|
||||
* 1--NR_LOW_DRS, beginning at BKP_BASE->DR1, through to
|
||||
* (NR_LOW_DRS+1)--BKP_NR_DATA_REGS, beginning at BKP_BASE->DR11.
|
||||
*/
|
||||
#define NR_LOW_DRS 10
|
||||
|
||||
static inline __io uint32* data_register(uint8 reg) {
|
||||
if (reg < 1 || reg > BKP_NR_DATA_REGS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if BKP_NR_DATA_REGS == NR_LOW_DRS
|
||||
return (uint32*)BKP_BASE + reg;
|
||||
#else
|
||||
if (reg <= NR_LOW_DRS) {
|
||||
return (uint32*)BKP_BASE + reg;
|
||||
} else {
|
||||
return (uint32*)&(BKP_BASE->DR11) + (reg - NR_LOW_DRS - 1);
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Bryan Newbold.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/dac.c
|
||||
* @brief Digital to analog converter support.
|
||||
*/
|
||||
|
||||
#include <libmaple/dac.h>
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/gpio.h>
|
||||
|
||||
#if STM32_HAVE_DAC
|
||||
dac_dev dac = {
|
||||
.regs = DAC_BASE,
|
||||
};
|
||||
const dac_dev *DAC = &dac;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the digital to analog converter
|
||||
* @param dev DAC device
|
||||
* @param flags Flags:
|
||||
* DAC_CH1: Enable channel 1
|
||||
* DAC_CH2: Enable channel 2
|
||||
* @sideeffect May set PA4 or PA5 to INPUT_ANALOG
|
||||
*/
|
||||
void dac_init(const dac_dev *dev, uint32 flags) {
|
||||
/* First turn on the clock */
|
||||
rcc_clk_enable(RCC_DAC);
|
||||
rcc_reset_dev(RCC_DAC);
|
||||
|
||||
if (flags & DAC_CH1) {
|
||||
dac_enable_channel(dev, 1);
|
||||
}
|
||||
|
||||
if (flags & DAC_CH2) {
|
||||
dac_enable_channel(dev, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a 12-bit value to the DAC to output
|
||||
* @param dev DAC device
|
||||
* @param channel channel to select (1 or 2)
|
||||
* @param val value to write
|
||||
*/
|
||||
void dac_write_channel(const dac_dev *dev, uint8 channel, uint16 val) {
|
||||
switch(channel) {
|
||||
case 1:
|
||||
dev->regs->DHR12R1 = DAC_DHR12R1_DACC1DHR & val;
|
||||
break;
|
||||
case 2:
|
||||
dev->regs->DHR12R2 = DAC_DHR12R2_DACC2DHR & val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a DAC channel
|
||||
* @param dev DAC device
|
||||
* @param channel channel to enable, either 1 or 2
|
||||
* @sideeffect May change pin mode of PA4 or PA5
|
||||
*/
|
||||
void dac_enable_channel(const dac_dev *dev, uint8 channel) {
|
||||
/*
|
||||
* Setup ANALOG mode on PA4 and PA5. This mapping is consistent
|
||||
* across all supported STM32s with a DAC.
|
||||
*/
|
||||
switch (channel) {
|
||||
case 1:
|
||||
gpio_set_mode(GPIOA, 4, GPIO_MODE_ANALOG);
|
||||
dev->regs->CR |= DAC_CR_EN1;
|
||||
break;
|
||||
case 2:
|
||||
gpio_set_mode(GPIOA, 5, GPIO_MODE_ANALOG);
|
||||
dev->regs->CR |= DAC_CR_EN2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a DAC channel
|
||||
* @param dev DAC device
|
||||
* @param channel channel to disable, either 1 or 2
|
||||
*/
|
||||
void dac_disable_channel(const dac_dev *dev, uint8 channel) {
|
||||
switch (channel) {
|
||||
case 1:
|
||||
dev->regs->CR &= ~DAC_CR_EN1;
|
||||
break;
|
||||
case 2:
|
||||
dev->regs->CR &= ~DAC_CR_EN2;
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/dma.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>;
|
||||
* Original implementation by Michael Hope
|
||||
* @brief Portable DMA routines.
|
||||
*/
|
||||
|
||||
#include <libmaple/dma.h>
|
||||
#include "dma_private.h"
|
||||
#include "stm32_private.h"
|
||||
|
||||
/*
|
||||
* Convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize a DMA device.
|
||||
* @param dev Device to initialize.
|
||||
*/
|
||||
void dma_init(dma_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Private API
|
||||
*/
|
||||
|
||||
enum dma_atype _dma_addr_type(__io void *addr) {
|
||||
switch (stm32_block_purpose((void*)addr)) {
|
||||
/* Notice we're treating the code block as memory here. That's
|
||||
* correct for addresses in Flash and in [0x0, 0x7FFFFFF]
|
||||
* (provided that those addresses are aliased to Flash, SRAM, or
|
||||
* FSMC, depending on BOOT[01] and possibly SYSCFG_MEMRMP). It's
|
||||
* not correct for other addresses in the code block, but those
|
||||
* will (hopefully) just fail-fast with transfer or bus errors. If
|
||||
* lots of people get confused, it might be worth being more
|
||||
* careful here. */
|
||||
case STM32_BLOCK_CODE: /* Fall through */
|
||||
case STM32_BLOCK_SRAM: /* ... */
|
||||
case STM32_BLOCK_FSMC_1_2: /* ... */
|
||||
case STM32_BLOCK_FSMC_3_4:
|
||||
return DMA_ATYPE_MEM;
|
||||
case STM32_BLOCK_PERIPH:
|
||||
return DMA_ATYPE_PER;
|
||||
case STM32_BLOCK_FSMC_REG: /* Fall through */
|
||||
/* Is this right? I can't think of a reason to DMA into or out
|
||||
* of the FSMC registers. [mbolivar] */
|
||||
case STM32_BLOCK_UNUSED: /* ... */
|
||||
case STM32_BLOCK_CORTEX_INTERNAL: /* ... */
|
||||
return DMA_ATYPE_OTHER;
|
||||
default:
|
||||
ASSERT(0); /* Can't happen */
|
||||
return DMA_ATYPE_OTHER;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,413 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/dma.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>;
|
||||
* Original implementation by Michael Hope
|
||||
* @brief STM32F1 DMA support.
|
||||
*/
|
||||
|
||||
#include <libmaple/dma.h>
|
||||
#include <libmaple/bitband.h>
|
||||
|
||||
/* Hack to ensure inlining in dma_irq_handler() */
|
||||
#define DMA_GET_HANDLER(dev, tube) (dev->handlers[tube - 1].handler)
|
||||
#include "dma_private.h"
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
static dma_dev dma1 = {
|
||||
.regs = DMA1_BASE,
|
||||
.clk_id = RCC_DMA1,
|
||||
.handlers = {{ .handler = NULL, .irq_line = NVIC_DMA_CH1 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH2 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH3 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH4 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH5 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH6 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA_CH7 }},
|
||||
};
|
||||
/** STM32F1 DMA1 device */
|
||||
dma_dev *DMA1 = &dma1;
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
static dma_dev dma2 = {
|
||||
.regs = DMA2_BASE,
|
||||
.clk_id = RCC_DMA2,
|
||||
.handlers = {{ .handler = NULL, .irq_line = NVIC_DMA2_CH1 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH2 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH3 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 },
|
||||
{ .handler = NULL, .irq_line = NVIC_DMA2_CH_4_5 }}, /* !@#$ */
|
||||
};
|
||||
/** STM32F1 DMA2 device */
|
||||
dma_dev *DMA2 = &dma2;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Auxiliary routines
|
||||
*/
|
||||
|
||||
/* Can channel serve cfg->tube_req_src? */
|
||||
static int cfg_req_ok(dma_channel channel, dma_tube_config *cfg) {
|
||||
return (cfg->tube_req_src & 0x7) == channel;
|
||||
}
|
||||
|
||||
/* Can dev serve cfg->tube_req_src? */
|
||||
static int cfg_dev_ok(dma_dev *dev, dma_tube_config *cfg) {
|
||||
return (rcc_clk_id)(cfg->tube_req_src >> 3) == dev->clk_id;
|
||||
}
|
||||
|
||||
/* Is addr acceptable for use as DMA src/dst? */
|
||||
static int cfg_mem_ok(__io void *addr) {
|
||||
enum dma_atype atype = _dma_addr_type(addr);
|
||||
return atype == DMA_ATYPE_MEM || atype == DMA_ATYPE_PER;
|
||||
}
|
||||
|
||||
/* Is the direction implied by src->dst supported? */
|
||||
static int cfg_dir_ok(dma_tube_config *cfg) {
|
||||
/* We can't do peripheral->peripheral transfers. */
|
||||
return ((_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM) ||
|
||||
(_dma_addr_type(cfg->tube_dst) == DMA_ATYPE_MEM));
|
||||
}
|
||||
|
||||
static int preconfig_check(dma_dev *dev, dma_channel channel,
|
||||
dma_tube_config *cfg) {
|
||||
if (!cfg_req_ok(channel, cfg)) {
|
||||
return -DMA_TUBE_CFG_EREQ;
|
||||
}
|
||||
if (cfg->tube_nr_xfers > 65535) {
|
||||
return -DMA_TUBE_CFG_ENDATA;
|
||||
}
|
||||
if (!cfg_dev_ok(dev, cfg)) {
|
||||
return -DMA_TUBE_CFG_EDEV;
|
||||
}
|
||||
if (!cfg_mem_ok(cfg->tube_src)) {
|
||||
return -DMA_TUBE_CFG_ESRC;
|
||||
}
|
||||
if (!cfg_mem_ok(cfg->tube_dst)) {
|
||||
return -DMA_TUBE_CFG_EDST;
|
||||
}
|
||||
if (!cfg_dir_ok(cfg)) {
|
||||
return -DMA_TUBE_CFG_EDIR;
|
||||
}
|
||||
return DMA_TUBE_CFG_SUCCESS;
|
||||
}
|
||||
|
||||
static inline void set_ccr(dma_tube_reg_map *chregs,
|
||||
dma_xfer_size msize, int minc,
|
||||
dma_xfer_size psize, int pinc,
|
||||
uint32 other_flags) {
|
||||
chregs->CCR = ((msize << 10) | (psize << 8) |
|
||||
(minc ? DMA_CCR_MINC : 0) | (pinc ? DMA_CCR_PINC : 0) |
|
||||
other_flags);
|
||||
}
|
||||
|
||||
static inline uint32 cfg_ccr_flags(unsigned tube_flags) {
|
||||
/* DMA_CFG_SRC_INC and DMA_CFG_DST_INC are special */
|
||||
return tube_flags & ~(DMA_CFG_SRC_INC | DMA_CFG_DST_INC);
|
||||
}
|
||||
|
||||
/* Configure chregs according to cfg, where cfg->tube_dst is peripheral. */
|
||||
static int config_to_per(dma_tube_reg_map *chregs, dma_tube_config *cfg) {
|
||||
/* Check that ->tube_src is memory (if it's anything else, we
|
||||
* shouldn't have been called). */
|
||||
ASSERT(_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM);
|
||||
|
||||
set_ccr(chregs,
|
||||
cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC,
|
||||
cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC,
|
||||
(cfg_ccr_flags(cfg->tube_flags) | DMA_CCR_DIR_FROM_MEM));
|
||||
chregs->CNDTR = cfg->tube_nr_xfers;
|
||||
chregs->CMAR = (uint32)cfg->tube_src;
|
||||
chregs->CPAR = (uint32)cfg->tube_dst;
|
||||
return DMA_TUBE_CFG_SUCCESS;
|
||||
}
|
||||
|
||||
/* Configure chregs according to cfg, where cfg->tube_dst is memory. */
|
||||
static int config_to_mem(dma_tube_reg_map *chregs, dma_tube_config *cfg) {
|
||||
uint32 mem2mem;
|
||||
|
||||
if ((_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM) &&
|
||||
(cfg->tube_flags & DMA_CFG_CIRC)) {
|
||||
/* Can't do mem-to-mem and circular mode */
|
||||
return -DMA_TUBE_CFG_ECFG;
|
||||
}
|
||||
|
||||
mem2mem = (_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM ?
|
||||
DMA_CCR_MEM2MEM : 0);
|
||||
set_ccr(chregs,
|
||||
cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC,
|
||||
cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC,
|
||||
(cfg_ccr_flags(cfg->tube_flags) |
|
||||
DMA_CCR_DIR_FROM_PER |
|
||||
mem2mem));
|
||||
chregs->CNDTR = cfg->tube_nr_xfers;
|
||||
chregs->CMAR = (uint32)cfg->tube_dst;
|
||||
chregs->CPAR = (uint32)cfg->tube_src;
|
||||
return DMA_TUBE_CFG_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines
|
||||
*/
|
||||
|
||||
int dma_tube_cfg(dma_dev *dev, dma_channel channel, dma_tube_config *cfg) {
|
||||
dma_tube_reg_map *chregs;
|
||||
int ret = preconfig_check(dev, channel, cfg);
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
dma_disable(dev, channel); /* Must disable before reconfiguring */
|
||||
dma_clear_isr_bits(dev, channel); /* For sanity and consistency
|
||||
* with STM32F2. */
|
||||
|
||||
chregs = dma_tube_regs(dev, channel);
|
||||
switch (_dma_addr_type(cfg->tube_dst)) {
|
||||
case DMA_ATYPE_PER:
|
||||
ret = config_to_per(chregs, cfg);
|
||||
break;
|
||||
case DMA_ATYPE_MEM:
|
||||
ret = config_to_mem(chregs, cfg);
|
||||
break;
|
||||
default:
|
||||
/* Can't happen */
|
||||
ASSERT(0);
|
||||
return -DMA_TUBE_CFG_ECFG;
|
||||
}
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
chregs->CNDTR = cfg->tube_nr_xfers;
|
||||
return DMA_TUBE_CFG_SUCCESS;
|
||||
}
|
||||
|
||||
void dma_set_priority(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
dma_priority priority) {
|
||||
dma_channel_reg_map *channel_regs;
|
||||
uint32 ccr;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
channel_regs = dma_channel_regs(dev, channel);
|
||||
ccr = channel_regs->CCR;
|
||||
ccr &= ~DMA_CCR_PL;
|
||||
ccr |= (priority << 12);
|
||||
channel_regs->CCR = ccr;
|
||||
}
|
||||
|
||||
void dma_set_num_transfers(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
uint16 num_transfers) {
|
||||
dma_channel_reg_map *channel_regs;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
channel_regs = dma_channel_regs(dev, channel);
|
||||
channel_regs->CNDTR = num_transfers;
|
||||
}
|
||||
|
||||
void dma_attach_interrupt(dma_dev *dev, dma_channel channel,
|
||||
void (*handler)(void)) {
|
||||
DMA_GET_HANDLER(dev, channel) = handler;
|
||||
nvic_irq_enable(dev->handlers[channel - 1].irq_line);
|
||||
}
|
||||
|
||||
void dma_detach_interrupt(dma_dev *dev, dma_channel channel) {
|
||||
/* Don't use nvic_irq_disable()! Think about DMA2 channels 4 and 5. */
|
||||
dma_channel_regs(dev, channel)->CCR &= ~0xF;
|
||||
DMA_GET_HANDLER(dev, channel) = NULL;
|
||||
}
|
||||
|
||||
void dma_enable(dma_dev *dev, dma_channel channel) {
|
||||
dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel);
|
||||
bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 1);
|
||||
}
|
||||
|
||||
void dma_disable(dma_dev *dev, dma_channel channel) {
|
||||
dma_channel_reg_map *chan_regs = dma_channel_regs(dev, channel);
|
||||
bb_peri_set_bit(&chan_regs->CCR, DMA_CCR_EN_BIT, 0);
|
||||
}
|
||||
|
||||
dma_irq_cause dma_get_irq_cause(dma_dev *dev, dma_channel channel) {
|
||||
/* Grab and clear the ISR bits. */
|
||||
uint8 status_bits = dma_get_isr_bits(dev, channel);
|
||||
dma_clear_isr_bits(dev, channel);
|
||||
|
||||
/* If the channel global interrupt flag is cleared, then
|
||||
* something's very wrong. */
|
||||
ASSERT(status_bits & 0x1);
|
||||
/* If GIF is set, then some other flag should be set, barring
|
||||
* something unexpected (e.g. the user making an unforeseen IFCR
|
||||
* write). */
|
||||
ASSERT(status_bits != 0x1);
|
||||
|
||||
/* ISR flags get set even if the corresponding interrupt enable
|
||||
* bits in the channel's configuration register are cleared, so we
|
||||
* can't use a switch here.
|
||||
*
|
||||
* Don't change the order of these if statements. */
|
||||
if (status_bits & 0x8) {
|
||||
return DMA_TRANSFER_ERROR;
|
||||
} else if (status_bits & 0x2) {
|
||||
return DMA_TRANSFER_COMPLETE;
|
||||
} else if (status_bits & 0x4) {
|
||||
return DMA_TRANSFER_HALF_COMPLETE;
|
||||
}
|
||||
|
||||
/* If we get here, one of our assumptions has been violated, but
|
||||
* the debug level is too low for the above ASSERTs() to have had
|
||||
* any effect. In order to fail fast, mimic the DMA controller's
|
||||
* behavior when an error occurs. */
|
||||
dma_disable(dev, channel);
|
||||
return DMA_TRANSFER_ERROR;
|
||||
}
|
||||
|
||||
void dma_set_mem_addr(dma_dev *dev, dma_channel channel, __io void *addr) {
|
||||
dma_channel_reg_map *chan_regs;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
chan_regs = dma_channel_regs(dev, channel);
|
||||
chan_regs->CMAR = (uint32)addr;
|
||||
}
|
||||
|
||||
void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) {
|
||||
dma_channel_reg_map *chan_regs;
|
||||
|
||||
ASSERT_FAULT(!dma_is_channel_enabled(dev, channel));
|
||||
|
||||
chan_regs = dma_channel_regs(dev, channel);
|
||||
chan_regs->CPAR = (uint32)addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deprecated. Use dma_tube_cfg() instead.
|
||||
*
|
||||
* Set up a DMA transfer.
|
||||
*
|
||||
* The channel will be disabled before being reconfigured. The
|
||||
* transfer will have low priority by default. You may choose another
|
||||
* priority before the transfer begins using dma_set_priority(), as
|
||||
* well as performing any other configuration you desire. When the
|
||||
* channel is configured to your liking, enable it using dma_enable().
|
||||
*
|
||||
* @param dev DMA device.
|
||||
* @param channel DMA channel.
|
||||
* @param peripheral_address Base address of peripheral data register
|
||||
* involved in the transfer.
|
||||
* @param peripheral_size Peripheral data transfer size.
|
||||
* @param memory_address Base memory address involved in the transfer.
|
||||
* @param memory_size Memory data transfer size.
|
||||
* @param mode Logical OR of dma_mode_flags
|
||||
*
|
||||
* @see dma_tube_cfg()
|
||||
*
|
||||
* @sideeffect Disables the given DMA channel.
|
||||
* @see dma_xfer_size
|
||||
* @see dma_mode_flags
|
||||
* @see dma_set_num_transfers()
|
||||
* @see dma_set_priority()
|
||||
* @see dma_attach_interrupt()
|
||||
* @see dma_enable()
|
||||
*/
|
||||
__deprecated
|
||||
void dma_setup_transfer(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
__io void *peripheral_address,
|
||||
dma_xfer_size peripheral_size,
|
||||
__io void *memory_address,
|
||||
dma_xfer_size memory_size,
|
||||
uint32 mode) {
|
||||
dma_channel_reg_map *channel_regs = dma_channel_regs(dev, channel);
|
||||
|
||||
dma_disable(dev, channel); /* can't write to CMAR/CPAR otherwise */
|
||||
channel_regs->CCR = (memory_size << 10) | (peripheral_size << 8) | mode;
|
||||
channel_regs->CMAR = (uint32)memory_address;
|
||||
channel_regs->CPAR = (uint32)peripheral_address;
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handlers
|
||||
*/
|
||||
|
||||
void __irq_dma1_channel1(void) {
|
||||
dma_irq_handler(DMA1, DMA_CH1);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel2(void) {
|
||||
dma_irq_handler(DMA1, DMA_CH2);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel3(void) {
|
||||
dma_irq_handler(DMA1, DMA_CH3);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel4(void) {
|
||||
dma_irq_handler(DMA1, DMA_CH4);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel5(void) {
|
||||
dma_irq_handler(DMA1, DMA_CH5);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel6(void) {
|
||||
dma_irq_handler(DMA1, DMA_CH6);
|
||||
}
|
||||
|
||||
void __irq_dma1_channel7(void) {
|
||||
dma_irq_handler(DMA1, DMA_CH7);
|
||||
}
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
void __irq_dma2_channel1(void) {
|
||||
dma_irq_handler(DMA2, DMA_CH1);
|
||||
}
|
||||
|
||||
void __irq_dma2_channel2(void) {
|
||||
dma_irq_handler(DMA2, DMA_CH2);
|
||||
}
|
||||
|
||||
void __irq_dma2_channel3(void) {
|
||||
dma_irq_handler(DMA2, DMA_CH3);
|
||||
}
|
||||
|
||||
void __irq_dma2_channel4_5(void) {
|
||||
if ((DMA2_BASE->CCR4 & DMA_CCR_EN) && (DMA2_BASE->ISR & DMA_ISR_GIF4)) {
|
||||
dma_irq_handler(DMA2, DMA_CH4);
|
||||
}
|
||||
if ((DMA2_BASE->CCR5 & DMA_CCR_EN) && (DMA2_BASE->ISR & DMA_ISR_GIF5)) {
|
||||
dma_irq_handler(DMA2, DMA_CH5);
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,101 @@
|
|||
/* *****************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
* ****************************************************************************/
|
||||
|
||||
# On an exception, push a fake stack thread mode stack frame and redirect
|
||||
# thread execution to a thread mode error handler
|
||||
|
||||
# From RM008:
|
||||
# The SP is decremented by eight words by the completion of the stack push.
|
||||
# Figure 5-1 shows the contents of the stack after an exception pre-empts the
|
||||
# current program flow.
|
||||
#
|
||||
# Old SP--> <previous>
|
||||
# xPSR
|
||||
# PC
|
||||
# LR
|
||||
# r12
|
||||
# r3
|
||||
# r2
|
||||
# r1
|
||||
# SP--> r0
|
||||
|
||||
.text
|
||||
.globl __exc_hardfault
|
||||
.globl __exc_nmi
|
||||
.globl __exc_hardfault
|
||||
.globl __exc_memmanage
|
||||
.globl __exc_busfault
|
||||
.globl __exc_usagefault
|
||||
|
||||
.code 16
|
||||
.thumb_func
|
||||
__exc_nmi:
|
||||
mov r0, #1
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_hardfault:
|
||||
mov r0, #2
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_memmanage:
|
||||
mov r0, #3
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_busfault:
|
||||
mov r0, #4
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__exc_usagefault:
|
||||
mov r0, #5
|
||||
b __default_exc
|
||||
|
||||
.thumb_func
|
||||
__default_exc:
|
||||
ldr r2, NVIC_CCR @ Enable returning to thread mode even if there are
|
||||
mov r1 ,#1 @ pending exceptions. See flag NONEBASETHRDENA.
|
||||
str r1, [r2]
|
||||
cpsid i @ Disable global interrupts
|
||||
ldr r2, SYSTICK_CSR @ Disable systick handler
|
||||
mov r1, #0
|
||||
str r1, [r2]
|
||||
ldr r1, CPSR_MASK @ Set default CPSR
|
||||
push {r1}
|
||||
ldr r1, TARGET_PC @ Set target pc
|
||||
push {r1}
|
||||
sub sp, sp, #24 @ Don't care
|
||||
ldr r1, EXC_RETURN @ Return to thread mode
|
||||
mov lr, r1
|
||||
bx lr @ Exception exit
|
||||
|
||||
.align 4
|
||||
CPSR_MASK: .word 0x61000000
|
||||
EXC_RETURN: .word 0xFFFFFFF9
|
||||
TARGET_PC: .word __error
|
||||
NVIC_CCR: .word 0xE000ED14 @ NVIC configuration control register
|
||||
SYSTICK_CSR: .word 0xE000E010 @ Systick control register
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/exti.c
|
||||
* @brief External interrupt control routines
|
||||
*/
|
||||
|
||||
#include <libmaple/exti.h>
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/bitband.h>
|
||||
|
||||
static inline void dispatch_single_exti(uint32 exti_num);
|
||||
static inline void dispatch_extis(uint32 start, uint32 stop);
|
||||
|
||||
/*
|
||||
* Internal state
|
||||
*/
|
||||
|
||||
typedef struct exti_channel {
|
||||
void (*handler)(void *);
|
||||
void *arg;
|
||||
} exti_channel;
|
||||
|
||||
static exti_channel exti_channels[] = {
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI0
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI1
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI2
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI3
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI4
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI5
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI6
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI7
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI8
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI9
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI10
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI11
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI12
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI13
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI14
|
||||
{ .handler = NULL, .arg = NULL }, // EXTI15
|
||||
};
|
||||
|
||||
/*
|
||||
* Portable routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Register a handler to run upon external interrupt.
|
||||
*
|
||||
* This function assumes that the interrupt request corresponding to
|
||||
* the given external interrupt is masked.
|
||||
*
|
||||
* @param num External interrupt line number.
|
||||
* @param port Port to use as source input for external interrupt.
|
||||
* @param handler Function handler to execute when interrupt is triggered.
|
||||
* @param mode Type of transition to trigger on, one of:
|
||||
* EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING.
|
||||
* @see exti_num
|
||||
* @see exti_cfg
|
||||
* @see voidFuncPtr
|
||||
* @see exti_trigger_mode
|
||||
*/
|
||||
void exti_attach_interrupt(exti_num num,
|
||||
exti_cfg port,
|
||||
voidFuncPtr handler,
|
||||
exti_trigger_mode mode) {
|
||||
// Call callback version with arg being null
|
||||
exti_attach_callback(num, port, (voidArgumentFuncPtr)handler, NULL, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a handler with an argument to run upon external interrupt.
|
||||
*
|
||||
* This function assumes that the interrupt request corresponding to
|
||||
* the given external interrupt is masked.
|
||||
*
|
||||
* @param num External interrupt line number.
|
||||
* @param port Port to use as source input for external interrupt.
|
||||
* @param handler Function handler to execute when interrupt is triggered.
|
||||
* @param arg Argument to pass to the interrupt handler.
|
||||
* @param mode Type of transition to trigger on, one of:
|
||||
* EXTI_RISING, EXTI_FALLING, EXTI_RISING_FALLING.
|
||||
* @see exti_num
|
||||
* @see exti_cfg
|
||||
* @see voidFuncPtr
|
||||
* @see exti_trigger_mode
|
||||
*/
|
||||
void exti_attach_callback(exti_num num,
|
||||
exti_cfg port,
|
||||
voidArgumentFuncPtr handler,
|
||||
void *arg,
|
||||
exti_trigger_mode mode) {
|
||||
ASSERT(handler);
|
||||
|
||||
/* Register the handler */
|
||||
exti_channels[num].handler = handler;
|
||||
exti_channels[num].arg = arg;
|
||||
|
||||
/* Set trigger mode */
|
||||
switch (mode) {
|
||||
case EXTI_RISING:
|
||||
bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1);
|
||||
break;
|
||||
case EXTI_FALLING:
|
||||
bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1);
|
||||
break;
|
||||
case EXTI_RISING_FALLING:
|
||||
bb_peri_set_bit(&EXTI_BASE->RTSR, num, 1);
|
||||
bb_peri_set_bit(&EXTI_BASE->FTSR, num, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Use the chip-specific exti_select() to map num to port */
|
||||
exti_select(num, port);
|
||||
|
||||
/* Unmask external interrupt request */
|
||||
bb_peri_set_bit(&EXTI_BASE->IMR, num, 1);
|
||||
|
||||
/* Enable the interrupt line */
|
||||
switch(num)
|
||||
{
|
||||
case EXTI0:
|
||||
nvic_irq_enable(NVIC_EXTI0);
|
||||
break;
|
||||
case EXTI1:
|
||||
nvic_irq_enable(NVIC_EXTI1);
|
||||
break;
|
||||
case EXTI2:
|
||||
nvic_irq_enable(NVIC_EXTI2);
|
||||
break;
|
||||
case EXTI3:
|
||||
nvic_irq_enable(NVIC_EXTI3);
|
||||
break;
|
||||
case EXTI4:
|
||||
nvic_irq_enable(NVIC_EXTI4);
|
||||
break;
|
||||
case EXTI5:
|
||||
case EXTI6:
|
||||
case EXTI7:
|
||||
case EXTI8:
|
||||
case EXTI9:
|
||||
nvic_irq_enable(NVIC_EXTI_9_5);
|
||||
break;
|
||||
case EXTI10:
|
||||
case EXTI11:
|
||||
case EXTI12:
|
||||
case EXTI13:
|
||||
case EXTI14:
|
||||
case EXTI15:
|
||||
nvic_irq_enable(NVIC_EXTI_15_10);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an external interrupt handler
|
||||
* @param num External interrupt line to disable.
|
||||
* @see exti_num
|
||||
*/
|
||||
void exti_detach_interrupt(exti_num num) {
|
||||
/* First, mask the interrupt request */
|
||||
bb_peri_set_bit(&EXTI_BASE->IMR, num, 0);
|
||||
|
||||
/* Then, clear the trigger selection registers */
|
||||
bb_peri_set_bit(&EXTI_BASE->FTSR, num, 0);
|
||||
bb_peri_set_bit(&EXTI_BASE->RTSR, num, 0);
|
||||
|
||||
/* Finally, unregister the user's handler */
|
||||
exti_channels[num].handler = NULL;
|
||||
exti_channels[num].arg = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Private routines
|
||||
*/
|
||||
|
||||
void exti_do_select(__io uint32 *exti_cr, exti_num num, exti_cfg port) {
|
||||
uint32 shift = 4 * (num % 4);
|
||||
uint32 cr = *exti_cr;
|
||||
cr &= ~(0xF << shift);
|
||||
cr |= port << shift;
|
||||
*exti_cr = cr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handlers
|
||||
*/
|
||||
|
||||
void __irq_exti0(void) {
|
||||
dispatch_single_exti(EXTI0);
|
||||
}
|
||||
|
||||
void __irq_exti1(void) {
|
||||
dispatch_single_exti(EXTI1);
|
||||
}
|
||||
|
||||
void __irq_exti2(void) {
|
||||
dispatch_single_exti(EXTI2);
|
||||
}
|
||||
|
||||
void __irq_exti3(void) {
|
||||
dispatch_single_exti(EXTI3);
|
||||
}
|
||||
|
||||
void __irq_exti4(void) {
|
||||
dispatch_single_exti(EXTI4);
|
||||
}
|
||||
|
||||
void __irq_exti9_5(void) {
|
||||
dispatch_extis(5, 9);
|
||||
}
|
||||
|
||||
void __irq_exti15_10(void) {
|
||||
dispatch_extis(10, 15);
|
||||
}
|
||||
|
||||
/*
|
||||
* Auxiliary functions
|
||||
*/
|
||||
|
||||
/* Clear the pending bits for EXTIs whose bits are set in exti_msk.
|
||||
*
|
||||
* If a pending bit is cleared as the last instruction in an ISR, it
|
||||
* won't actually be cleared in time and the ISR will fire again. To
|
||||
* compensate, this function NOPs for 2 cycles after clearing the
|
||||
* pending bits to ensure it takes effect. */
|
||||
static __always_inline void clear_pending_msk(uint32 exti_msk) {
|
||||
EXTI_BASE->PR = exti_msk;
|
||||
asm volatile("nop");
|
||||
asm volatile("nop");
|
||||
}
|
||||
|
||||
/* This dispatch routine is for non-multiplexed EXTI lines only; i.e.,
|
||||
* it doesn't check EXTI_PR. */
|
||||
static __always_inline void dispatch_single_exti(uint32 exti) {
|
||||
voidArgumentFuncPtr handler = exti_channels[exti].handler;
|
||||
|
||||
if (!handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
handler(exti_channels[exti].arg);
|
||||
clear_pending_msk(1U << exti);
|
||||
}
|
||||
|
||||
/* Dispatch routine for EXTIs which share an IRQ. */
|
||||
static __always_inline void dispatch_extis(uint32 start, uint32 stop) {
|
||||
uint32 pr = EXTI_BASE->PR;
|
||||
uint32 handled_msk = 0;
|
||||
uint32 exti;
|
||||
|
||||
/* Dispatch user handlers for pending EXTIs. */
|
||||
for (exti = start; exti <= stop; exti++) {
|
||||
uint32 eb = (1U << exti);
|
||||
if (pr & eb) {
|
||||
voidArgumentFuncPtr handler = exti_channels[exti].handler;
|
||||
if (handler) {
|
||||
handler(exti_channels[exti].arg);
|
||||
handled_msk |= eb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the pending bits for handled EXTIs. */
|
||||
clear_pending_msk(handled_msk);
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
#include "exti_private.h"
|
||||
|
||||
void exti_select(exti_num num, exti_cfg port) {
|
||||
exti_do_select(&AFIO_BASE->EXTICR1 + num / 4, num, port);
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/flash.c
|
||||
* @brief Flash management functions
|
||||
*/
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <libmaple/flash.h>
|
||||
|
||||
/**
|
||||
* @brief Set flash wait states
|
||||
*
|
||||
* Note that not all wait states are available on every MCU. See the
|
||||
* Flash programming manual for your MCU for restrictions on the
|
||||
* allowed value of wait_states for a given system clock (SYSCLK)
|
||||
* frequency.
|
||||
*
|
||||
* @param wait_states number of wait states (one of
|
||||
* FLASH_WAIT_STATE_0, FLASH_WAIT_STATE_1,
|
||||
* ..., FLASH_WAIT_STATE_7).
|
||||
*/
|
||||
void flash_set_latency(uint32 wait_states) {
|
||||
uint32 val = FLASH_BASE->ACR;
|
||||
|
||||
val &= ~FLASH_ACR_LATENCY;
|
||||
val |= wait_states;
|
||||
|
||||
FLASH_BASE->ACR = val;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
* Copyright (c) 2010 Bryan Newbold.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/fsmc.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>,
|
||||
* Bryan Newbold <bnewbold@robocracy.org>
|
||||
* @brief STM32F1 FSMC support.
|
||||
*/
|
||||
|
||||
#include <libmaple/stm32.h>
|
||||
|
||||
#if STM32_HAVE_FSMC /* Don't try building the rest for MCUs without FSMC */
|
||||
|
||||
#include <libmaple/fsmc.h>
|
||||
#include <libmaple/gpio.h>
|
||||
|
||||
void fsmc_sram_init_gpios(void) {
|
||||
/* Data lines... */
|
||||
gpio_set_mode(GPIOD, 0, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 1, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 8, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 9, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 10, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 14, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 15, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 7, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 8, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 9, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 10, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 11, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 12, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 13, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 14, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOE, 15, GPIO_AF_OUTPUT_PP);
|
||||
|
||||
/* Address lines... */
|
||||
gpio_set_mode(GPIOD, 11, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 12, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOD, 13, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 0, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 1, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 2, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 3, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 4, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 5, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 12, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 13, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 14, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOF, 15, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 0, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 1, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 2, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 3, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 4, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(GPIOG, 5, GPIO_AF_OUTPUT_PP);
|
||||
|
||||
/* And control lines... */
|
||||
gpio_set_mode(GPIOD, 4, GPIO_AF_OUTPUT_PP); // NOE
|
||||
gpio_set_mode(GPIOD, 5, GPIO_AF_OUTPUT_PP); // NWE
|
||||
|
||||
gpio_set_mode(GPIOD, 7, GPIO_AF_OUTPUT_PP); // NE1
|
||||
gpio_set_mode(GPIOG, 9, GPIO_AF_OUTPUT_PP); // NE2
|
||||
gpio_set_mode(GPIOG, 10, GPIO_AF_OUTPUT_PP); // NE3
|
||||
gpio_set_mode(GPIOG, 12, GPIO_AF_OUTPUT_PP); // NE4
|
||||
|
||||
gpio_set_mode(GPIOE, 0, GPIO_AF_OUTPUT_PP); // NBL0
|
||||
gpio_set_mode(GPIOE, 1, GPIO_AF_OUTPUT_PP); // NBL1
|
||||
}
|
||||
|
||||
#endif /* STM32_HAVE_FSMC */
|
|
@ -0,0 +1,50 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/gpio.c
|
||||
* @brief Generic STM32 GPIO support.
|
||||
*/
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/rcc.h>
|
||||
|
||||
/*
|
||||
* GPIO routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize a GPIO device.
|
||||
*
|
||||
* Enables the clock for and resets the given device.
|
||||
*
|
||||
* @param dev GPIO device to initialize.
|
||||
*/
|
||||
void gpio_init(gpio_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/gpio.c
|
||||
* @brief STM32F1 GPIO support.
|
||||
*/
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/rcc.h>
|
||||
|
||||
/*
|
||||
* GPIO devices
|
||||
*/
|
||||
|
||||
gpio_dev gpioa = {
|
||||
.regs = GPIOA_BASE,
|
||||
.clk_id = RCC_GPIOA,
|
||||
.exti_port = EXTI_PA,
|
||||
};
|
||||
/** GPIO port A device. */
|
||||
gpio_dev* const GPIOA = &gpioa;
|
||||
|
||||
gpio_dev gpiob = {
|
||||
.regs = GPIOB_BASE,
|
||||
.clk_id = RCC_GPIOB,
|
||||
.exti_port = EXTI_PB,
|
||||
};
|
||||
/** GPIO port B device. */
|
||||
gpio_dev* const GPIOB = &gpiob;
|
||||
|
||||
gpio_dev gpioc = {
|
||||
.regs = GPIOC_BASE,
|
||||
.clk_id = RCC_GPIOC,
|
||||
.exti_port = EXTI_PC,
|
||||
};
|
||||
/** GPIO port C device. */
|
||||
gpio_dev* const GPIOC = &gpioc;
|
||||
|
||||
gpio_dev gpiod = {
|
||||
.regs = GPIOD_BASE,
|
||||
.clk_id = RCC_GPIOD,
|
||||
.exti_port = EXTI_PD,
|
||||
};
|
||||
/** GPIO port D device. */
|
||||
gpio_dev* const GPIOD = &gpiod;
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
gpio_dev gpioe = {
|
||||
.regs = GPIOE_BASE,
|
||||
.clk_id = RCC_GPIOE,
|
||||
.exti_port = EXTI_PE,
|
||||
};
|
||||
/** GPIO port E device. */
|
||||
gpio_dev* const GPIOE = &gpioe;
|
||||
|
||||
gpio_dev gpiof = {
|
||||
.regs = GPIOF_BASE,
|
||||
.clk_id = RCC_GPIOF,
|
||||
.exti_port = EXTI_PF,
|
||||
};
|
||||
/** GPIO port F device. */
|
||||
gpio_dev* const GPIOF = &gpiof;
|
||||
|
||||
gpio_dev gpiog = {
|
||||
.regs = GPIOG_BASE,
|
||||
.clk_id = RCC_GPIOG,
|
||||
.exti_port = EXTI_PG,
|
||||
};
|
||||
/** GPIO port G device. */
|
||||
gpio_dev* const GPIOG = &gpiog;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* GPIO routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* Initialize and reset all available GPIO devices.
|
||||
*/
|
||||
void gpio_init_all(void) {
|
||||
gpio_init(GPIOA);
|
||||
gpio_init(GPIOB);
|
||||
gpio_init(GPIOC);
|
||||
gpio_init(GPIOD);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
gpio_init(GPIOE);
|
||||
gpio_init(GPIOF);
|
||||
gpio_init(GPIOG);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode of a GPIO pin.
|
||||
*
|
||||
* @param dev GPIO device.
|
||||
* @param pin Pin on the device whose mode to set, 0--15.
|
||||
* @param mode General purpose or alternate function mode to set the pin to.
|
||||
* @see gpio_pin_mode
|
||||
*/
|
||||
void gpio_set_mode(gpio_dev *dev, uint8 pin, gpio_pin_mode mode) {
|
||||
gpio_reg_map *regs = dev->regs;
|
||||
__io uint32 *cr = ®s->CRL + (pin >> 3);
|
||||
uint32 shift = (pin & 0x7) * 4;
|
||||
uint32 tmp = *cr;
|
||||
|
||||
tmp &= ~(0xF << shift);
|
||||
tmp |= (mode == GPIO_INPUT_PU ? GPIO_INPUT_PD : mode) << shift;
|
||||
*cr = tmp;
|
||||
|
||||
if (mode == GPIO_INPUT_PD) {
|
||||
regs->ODR &= ~(1U << pin);
|
||||
} else if (mode == GPIO_INPUT_PU) {
|
||||
regs->ODR |= (1U << pin);
|
||||
}
|
||||
}
|
||||
|
||||
gpio_pin_mode gpio_get_mode(gpio_dev *dev, uint8 pin) {
|
||||
gpio_reg_map *regs = dev->regs;
|
||||
__io uint32 *cr = ®s->CRL + (pin >> 3);
|
||||
uint32 shift = (pin & 0x7) * 4;
|
||||
uint32 tmp = *cr;
|
||||
|
||||
uint32 crMode = (*cr>>shift) & 0x0F;
|
||||
|
||||
// could be pull up or pull down. Nee to check the ODR
|
||||
if (crMode==GPIO_INPUT_PD && ((regs->ODR >> pin) & 0x01) !=0 )
|
||||
{
|
||||
crMode = GPIO_INPUT_PU;
|
||||
}
|
||||
|
||||
return(crMode);
|
||||
}
|
||||
|
||||
/*
|
||||
* AFIO
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the AFIO clock, and reset the AFIO registers.
|
||||
*/
|
||||
void afio_init(void) {
|
||||
rcc_clk_enable(RCC_AFIO);
|
||||
rcc_reset_dev(RCC_AFIO);
|
||||
}
|
||||
|
||||
#define AFIO_EXTI_SEL_MASK 0xF
|
||||
|
||||
/**
|
||||
* @brief Perform an alternate function remap.
|
||||
* @param remapping Remapping to perform.
|
||||
*/
|
||||
void afio_remap(afio_remap_peripheral remapping) {
|
||||
if (remapping & AFIO_REMAP_USE_MAPR2) {
|
||||
remapping &= ~AFIO_REMAP_USE_MAPR2;
|
||||
AFIO_BASE->MAPR2 |= remapping;
|
||||
} else {
|
||||
AFIO_BASE->MAPR |= remapping;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,520 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/i2c.c
|
||||
* @author Perry Hung <perry@leaflabs.com>
|
||||
* @brief Inter-Integrated Circuit (I2C) support.
|
||||
*
|
||||
* Currently, only master mode is supported.
|
||||
*/
|
||||
|
||||
#include "i2c_private.h"
|
||||
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/rcc.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/i2c.h>
|
||||
#include <libmaple/systick.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
static inline int32 wait_for_state_change(i2c_dev *dev,
|
||||
i2c_state state,
|
||||
uint32 timeout);
|
||||
static void set_ccr_trise(i2c_dev *dev, uint32 flags);
|
||||
|
||||
/**
|
||||
* @brief Fill data register with slave address
|
||||
* @param dev I2C device
|
||||
* @param addr Slave address
|
||||
* @param rw Read/write bit
|
||||
*/
|
||||
static inline void i2c_send_slave_addr(i2c_dev *dev, uint32 addr, uint32 rw) {
|
||||
dev->regs->DR = (addr << 1) | rw;
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple debugging trail. Define I2C_DEBUG to turn on.
|
||||
*/
|
||||
#ifdef I2C_DEBUG
|
||||
|
||||
#define NR_CRUMBS 128
|
||||
static struct crumb crumbs[NR_CRUMBS];
|
||||
static uint32 cur_crumb = 0;
|
||||
|
||||
static inline void i2c_drop_crumb(uint32 event, uint32 arg0, uint32 arg1) {
|
||||
if (cur_crumb < NR_CRUMBS) {
|
||||
struct crumb *crumb = &crumbs[cur_crumb++];
|
||||
crumb->event = event;
|
||||
crumb->arg0 = arg0;
|
||||
crumb->arg1 = arg1;
|
||||
}
|
||||
}
|
||||
#define I2C_CRUMB(event, arg0, arg1) i2c_drop_crumb(event, arg0, arg1)
|
||||
|
||||
#else
|
||||
#define I2C_CRUMB(event, arg0, arg1)
|
||||
#endif
|
||||
|
||||
struct crumb {
|
||||
uint32 event;
|
||||
uint32 arg0;
|
||||
uint32 arg1;
|
||||
};
|
||||
|
||||
enum {
|
||||
IRQ_ENTRY = 1,
|
||||
TXE_ONLY = 2,
|
||||
TXE_BTF = 3,
|
||||
STOP_SENT = 4,
|
||||
TEST = 5,
|
||||
RX_ADDR_START = 6,
|
||||
RX_ADDR_STOP = 7,
|
||||
RXNE_ONLY = 8,
|
||||
RXNE_SENDING = 9,
|
||||
RXNE_START_SENT = 10,
|
||||
RXNE_STOP_SENT = 11,
|
||||
RXNE_DONE = 12,
|
||||
ERROR_ENTRY = 13,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Reset an I2C bus.
|
||||
*
|
||||
* Reset is accomplished by clocking out pulses until any hung slaves
|
||||
* release SDA and SCL, then generating a START condition, then a STOP
|
||||
* condition.
|
||||
*
|
||||
* @param dev I2C device
|
||||
*/
|
||||
void i2c_bus_reset(const i2c_dev *dev) {
|
||||
/* Release both lines */
|
||||
i2c_master_release_bus(dev);
|
||||
|
||||
/*
|
||||
* Make sure the bus is free by clocking it until any slaves release the
|
||||
* bus.
|
||||
*/
|
||||
while (!gpio_read_bit(sda_port(dev), dev->sda_pin)) {
|
||||
/* Wait for any clock stretching to finish */
|
||||
while (!gpio_read_bit(scl_port(dev), dev->scl_pin))
|
||||
;
|
||||
delay_us(10);
|
||||
|
||||
/* Pull low */
|
||||
gpio_write_bit(scl_port(dev), dev->scl_pin, 0);
|
||||
delay_us(10);
|
||||
|
||||
/* Release high again */
|
||||
gpio_write_bit(scl_port(dev), dev->scl_pin, 1);
|
||||
delay_us(10);
|
||||
}
|
||||
|
||||
/* Generate start then stop condition */
|
||||
gpio_write_bit(sda_port(dev), dev->sda_pin, 0);
|
||||
delay_us(10);
|
||||
gpio_write_bit(scl_port(dev), dev->scl_pin, 0);
|
||||
delay_us(10);
|
||||
gpio_write_bit(scl_port(dev), dev->scl_pin, 1);
|
||||
delay_us(10);
|
||||
gpio_write_bit(sda_port(dev), dev->sda_pin, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize an I2C device and reset its registers to their
|
||||
* default values.
|
||||
* @param dev Device to initialize.
|
||||
*/
|
||||
void i2c_init(i2c_dev *dev) {
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
}
|
||||
|
||||
/* Hack for deprecated bit of STM32F1 functionality */
|
||||
#ifndef _I2C_HAVE_DEPRECATED_I2C_REMAP
|
||||
#define _i2c_handle_remap(dev, flags) ((void)0)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize an I2C device as bus master
|
||||
* @param dev Device to enable
|
||||
* @param flags Bitwise or of the following I2C options:
|
||||
* I2C_FAST_MODE: 400 khz operation,
|
||||
* I2C_DUTY_16_9: 16/9 Tlow/Thigh duty cycle (only applicable for
|
||||
* fast mode),
|
||||
* I2C_BUS_RESET: Reset the bus and clock out any hung slaves on
|
||||
* initialization,
|
||||
* I2C_10BIT_ADDRESSING: Enable 10-bit addressing,
|
||||
* I2C_REMAP: (deprecated, STM32F1 only) Remap I2C1 to SCL/PB8
|
||||
* SDA/PB9.
|
||||
*/
|
||||
void i2c_master_enable(i2c_dev *dev, uint32 flags) {
|
||||
/* PE must be disabled to configure the device */
|
||||
ASSERT(!(dev->regs->CR1 & I2C_CR1_PE));
|
||||
|
||||
/* Ugh */
|
||||
_i2c_handle_remap(dev, flags);
|
||||
|
||||
/* Reset the bus. Clock out any hung slaves. */
|
||||
if (flags & I2C_BUS_RESET) {
|
||||
i2c_bus_reset(dev);
|
||||
}
|
||||
|
||||
/* Turn on clock and set GPIO modes */
|
||||
i2c_init(dev);
|
||||
i2c_config_gpios(dev);
|
||||
|
||||
/* Configure clock and rise time */
|
||||
set_ccr_trise(dev, flags);
|
||||
|
||||
/* Enable event and buffer interrupts */
|
||||
nvic_irq_enable(dev->ev_nvic_line);
|
||||
nvic_irq_enable(dev->er_nvic_line);
|
||||
i2c_enable_irq(dev, I2C_IRQ_EVENT | I2C_IRQ_BUFFER | I2C_IRQ_ERROR);
|
||||
|
||||
/* Make it go! */
|
||||
i2c_peripheral_enable(dev);
|
||||
|
||||
dev->state = I2C_STATE_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Process an i2c transaction.
|
||||
*
|
||||
* Transactions are composed of one or more i2c_msg's, and may be read
|
||||
* or write tranfers. Multiple i2c_msg's will generate a repeated
|
||||
* start in between messages.
|
||||
*
|
||||
* @param dev I2C device
|
||||
* @param msgs Messages to send/receive
|
||||
* @param num Number of messages to send/receive
|
||||
* @param timeout Bus idle timeout in milliseconds before aborting the
|
||||
* transfer. 0 denotes no timeout.
|
||||
* @return 0 on success,
|
||||
* I2C_ERROR_PROTOCOL if there was a protocol error,
|
||||
* I2C_ERROR_TIMEOUT if the transfer timed out.
|
||||
*/
|
||||
int32 i2c_master_xfer(i2c_dev *dev,
|
||||
i2c_msg *msgs,
|
||||
uint16 num,
|
||||
uint32 timeout) {
|
||||
int32 rc;
|
||||
|
||||
ASSERT(dev->state == I2C_STATE_IDLE);
|
||||
|
||||
dev->msg = msgs;
|
||||
dev->msgs_left = num;
|
||||
dev->timestamp = systick_uptime();
|
||||
dev->state = I2C_STATE_BUSY;
|
||||
|
||||
i2c_enable_irq(dev, I2C_IRQ_EVENT);
|
||||
i2c_start_condition(dev);
|
||||
|
||||
rc = wait_for_state_change(dev, I2C_STATE_XFER_DONE, timeout);
|
||||
if (rc < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev->state = I2C_STATE_IDLE;
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for an I2C event, or time out in case of error.
|
||||
* @param dev I2C device
|
||||
* @param state I2C_state state to wait for
|
||||
* @param timeout Timeout, in milliseconds
|
||||
* @return 0 if target state is reached, a negative value on error.
|
||||
*/
|
||||
static inline int32 wait_for_state_change(i2c_dev *dev,
|
||||
i2c_state state,
|
||||
uint32 timeout) {
|
||||
i2c_state tmp;
|
||||
|
||||
while (1) {
|
||||
tmp = dev->state;
|
||||
|
||||
if (tmp == I2C_STATE_ERROR) {
|
||||
return I2C_STATE_ERROR;
|
||||
}
|
||||
|
||||
if (tmp == state) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (timeout) {
|
||||
if (systick_uptime() > (dev->timestamp + timeout)) {
|
||||
/* TODO: overflow? */
|
||||
/* TODO: racy? */
|
||||
return I2C_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Private API
|
||||
*/
|
||||
|
||||
/*
|
||||
* IRQ handler for I2C master. Handles transmission/reception.
|
||||
*/
|
||||
void _i2c_irq_handler(i2c_dev *dev) {
|
||||
/* WTFs:
|
||||
* - Where is I2C_MSG_10BIT_ADDR handled?
|
||||
*/
|
||||
i2c_msg *msg = dev->msg;
|
||||
|
||||
uint8 read = msg->flags & I2C_MSG_READ;
|
||||
|
||||
uint32 sr1 = dev->regs->SR1;
|
||||
uint32 sr2 = dev->regs->SR2;
|
||||
I2C_CRUMB(IRQ_ENTRY, sr1, sr2);
|
||||
|
||||
/*
|
||||
* Reset timeout counter
|
||||
*/
|
||||
dev->timestamp = systick_uptime();
|
||||
|
||||
/*
|
||||
* EV5: Start condition sent
|
||||
*/
|
||||
if (sr1 & I2C_SR1_SB) {
|
||||
msg->xferred = 0;
|
||||
i2c_enable_irq(dev, I2C_IRQ_BUFFER);
|
||||
|
||||
/*
|
||||
* Master receiver
|
||||
*/
|
||||
if (read) {
|
||||
i2c_enable_ack(dev);
|
||||
}
|
||||
|
||||
i2c_send_slave_addr(dev, msg->addr, read);
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV6: Slave address sent
|
||||
*/
|
||||
if (sr1 & I2C_SR1_ADDR) {
|
||||
/*
|
||||
* Special case event EV6_1 for master receiver.
|
||||
* Generate NACK and restart/stop condition after ADDR
|
||||
* is cleared.
|
||||
*/
|
||||
if (read) {
|
||||
if (msg->length == 1) {
|
||||
i2c_disable_ack(dev);
|
||||
if (dev->msgs_left > 1) {
|
||||
i2c_start_condition(dev);
|
||||
I2C_CRUMB(RX_ADDR_START, 0, 0);
|
||||
} else {
|
||||
i2c_stop_condition(dev);
|
||||
I2C_CRUMB(RX_ADDR_STOP, 0, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Master transmitter: write first byte to fill shift
|
||||
* register. We should get another TXE interrupt
|
||||
* immediately to fill DR again.
|
||||
*/
|
||||
if (msg->length > 1) {
|
||||
i2c_write(dev, msg->data[msg->xferred++]);
|
||||
} else if (msg->length == 0) { /* We're just sending an address */
|
||||
i2c_stop_condition(dev);
|
||||
/*
|
||||
* Turn off event interrupts to keep BTF from firing until
|
||||
* the end of the stop condition. Why on earth they didn't
|
||||
* have a start/stop condition request clear BTF is beyond
|
||||
* me.
|
||||
*/
|
||||
i2c_disable_irq(dev, I2C_IRQ_EVENT);
|
||||
I2C_CRUMB(STOP_SENT, 0, 0);
|
||||
dev->state = I2C_STATE_XFER_DONE;
|
||||
} /* else we're just sending one byte */
|
||||
}
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV8: Master transmitter
|
||||
* Transmit buffer empty, but we haven't finished transmitting the last
|
||||
* byte written.
|
||||
*/
|
||||
if ((sr1 & I2C_SR1_TXE) && !(sr1 & I2C_SR1_BTF)) {
|
||||
I2C_CRUMB(TXE_ONLY, 0, 0);
|
||||
if (dev->msgs_left) {
|
||||
i2c_write(dev, msg->data[msg->xferred++]);
|
||||
if (msg->xferred == msg->length) {
|
||||
/*
|
||||
* End of this message. Turn off TXE/RXNE and wait for
|
||||
* BTF to send repeated start or stop condition.
|
||||
*/
|
||||
i2c_disable_irq(dev, I2C_IRQ_BUFFER);
|
||||
dev->msgs_left--;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* This should be impossible...
|
||||
*/
|
||||
ASSERT(0);
|
||||
}
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV8_2: Master transmitter
|
||||
* Last byte sent, program repeated start/stop
|
||||
*/
|
||||
if ((sr1 & I2C_SR1_TXE) && (sr1 & I2C_SR1_BTF)) {
|
||||
I2C_CRUMB(TXE_BTF, 0, 0);
|
||||
if (dev->msgs_left) {
|
||||
I2C_CRUMB(TEST, 0, 0);
|
||||
/*
|
||||
* Repeated start insanity: We can't disable ITEVTEN or else SB
|
||||
* won't interrupt, but if we don't disable ITEVTEN, BTF will
|
||||
* continually interrupt us. What the fuck ST?
|
||||
*/
|
||||
i2c_start_condition(dev);
|
||||
while (!(dev->regs->SR1 & I2C_SR1_SB))
|
||||
;
|
||||
dev->msg++;
|
||||
} else {
|
||||
i2c_stop_condition(dev);
|
||||
|
||||
/*
|
||||
* Turn off event interrupts to keep BTF from firing until
|
||||
* the end of the stop condition. Why on earth they didn't
|
||||
* have a start/stop condition request clear BTF is beyond
|
||||
* me.
|
||||
*/
|
||||
i2c_disable_irq(dev, I2C_IRQ_EVENT);
|
||||
I2C_CRUMB(STOP_SENT, 0, 0);
|
||||
dev->state = I2C_STATE_XFER_DONE;
|
||||
}
|
||||
sr1 = sr2 = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* EV7: Master Receiver
|
||||
*/
|
||||
if (sr1 & I2C_SR1_RXNE) {
|
||||
I2C_CRUMB(RXNE_ONLY, 0, 0);
|
||||
msg->data[msg->xferred++] = dev->regs->DR;
|
||||
|
||||
/*
|
||||
* EV7_1: Second to last byte in the reception? Set NACK and generate
|
||||
* stop/restart condition in time for the last byte. We'll get one more
|
||||
* RXNE interrupt before shutting things down.
|
||||
*/
|
||||
if (msg->xferred == (msg->length - 1)) {
|
||||
i2c_disable_ack(dev);
|
||||
if (dev->msgs_left > 2) {
|
||||
i2c_start_condition(dev);
|
||||
I2C_CRUMB(RXNE_START_SENT, 0, 0);
|
||||
} else {
|
||||
i2c_stop_condition(dev);
|
||||
I2C_CRUMB(RXNE_STOP_SENT, 0, 0);
|
||||
}
|
||||
} else if (msg->xferred == msg->length) {
|
||||
dev->msgs_left--;
|
||||
if (dev->msgs_left == 0) {
|
||||
/*
|
||||
* We're done.
|
||||
*/
|
||||
I2C_CRUMB(RXNE_DONE, 0, 0);
|
||||
dev->state = I2C_STATE_XFER_DONE;
|
||||
} else {
|
||||
dev->msg++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handler for I2C error conditions. Aborts any pending I2C
|
||||
* transactions.
|
||||
*/
|
||||
void _i2c_irq_error_handler(i2c_dev *dev) {
|
||||
I2C_CRUMB(ERROR_ENTRY, dev->regs->SR1, dev->regs->SR2);
|
||||
|
||||
dev->error_flags = dev->regs->SR1 & (I2C_SR1_BERR |
|
||||
I2C_SR1_ARLO |
|
||||
I2C_SR1_AF |
|
||||
I2C_SR1_OVR);
|
||||
/* Clear flags */
|
||||
dev->regs->SR1 = 0;
|
||||
dev->regs->SR2 = 0;
|
||||
|
||||
i2c_stop_condition(dev);
|
||||
i2c_disable_irq(dev, I2C_IRQ_BUFFER | I2C_IRQ_EVENT | I2C_IRQ_ERROR);
|
||||
dev->state = I2C_STATE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* CCR/TRISE configuration helper
|
||||
*/
|
||||
static void set_ccr_trise(i2c_dev *dev, uint32 flags) {
|
||||
uint32 ccr = 0;
|
||||
uint32 trise = 0;
|
||||
uint32 clk_mhz = _i2c_bus_clk(dev);
|
||||
uint32 clk_hz = clk_mhz * (1000 * 1000);
|
||||
|
||||
i2c_set_input_clk(dev, clk_mhz);
|
||||
|
||||
if (flags & I2C_FAST_MODE) {
|
||||
ccr |= I2C_CCR_FS;
|
||||
|
||||
if (flags & I2C_DUTY_16_9) {
|
||||
/* Tlow/Thigh = 16/9 */
|
||||
ccr |= I2C_CCR_DUTY_16_9;
|
||||
ccr |= clk_hz / (400000 * 25);
|
||||
} else {
|
||||
/* Tlow/Thigh = 2 */
|
||||
ccr |= clk_hz / (400000 * 3);
|
||||
}
|
||||
|
||||
trise = (300 * clk_mhz / 1000) + 1;
|
||||
} else {
|
||||
/* Tlow/Thigh = 1 */
|
||||
ccr = clk_hz / (100000 * 2);
|
||||
trise = clk_mhz + 1;
|
||||
}
|
||||
|
||||
/* Set minimum required value if CCR < 1*/
|
||||
if ((ccr & I2C_CCR_CCR) == 0) {
|
||||
ccr |= 0x1;
|
||||
}
|
||||
|
||||
i2c_set_clk_control(dev, ccr);
|
||||
i2c_set_trise(dev, trise);
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/i2c.c
|
||||
* @brief STM32F1 I2C support
|
||||
*/
|
||||
|
||||
#include "i2c_private.h"
|
||||
#include <libmaple/i2c.h>
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
static i2c_dev i2c1 = I2C_DEV_OLD(1, &gpiob, 7, 6);
|
||||
static i2c_dev i2c2 = I2C_DEV_OLD(2, &gpiob, 11, 10);
|
||||
|
||||
/** STM32F1 I2C device 1 */
|
||||
i2c_dev* const I2C1 = &i2c1;
|
||||
/** STM32F1 I2C device 2 */
|
||||
i2c_dev* const I2C2 = &i2c2;
|
||||
|
||||
/*
|
||||
* Routines
|
||||
*/
|
||||
|
||||
static int i2c1_wants_remap(const i2c_dev *dev) {
|
||||
/* Check if we've got I2C1 configured for SDA/SCL remap on PB9/PB8 */
|
||||
return (dev->clk_id == RCC_I2C1) &&
|
||||
(scl_port(dev)->clk_id == RCC_GPIOB) &&
|
||||
(sda_port(dev)->clk_id == RCC_GPIOB) &&
|
||||
(dev->sda_pin == 9) &&
|
||||
(dev->scl_pin == 8);
|
||||
}
|
||||
|
||||
void i2c_config_gpios(const i2c_dev *dev) {
|
||||
if (i2c1_wants_remap(dev)) {
|
||||
afio_remap(AFIO_REMAP_I2C1);
|
||||
}
|
||||
gpio_set_mode(sda_port(dev), dev->sda_pin, GPIO_AF_OUTPUT_OD);
|
||||
gpio_set_mode(scl_port(dev), dev->scl_pin, GPIO_AF_OUTPUT_OD);
|
||||
}
|
||||
|
||||
void i2c_master_release_bus(const i2c_dev *dev) {
|
||||
gpio_write_bit(scl_port(dev), dev->scl_pin, 1);
|
||||
gpio_write_bit(sda_port(dev), dev->sda_pin, 1);
|
||||
gpio_set_mode(scl_port(dev), dev->scl_pin, GPIO_OUTPUT_OD);
|
||||
gpio_set_mode(sda_port(dev), dev->sda_pin, GPIO_OUTPUT_OD);
|
||||
}
|
||||
|
||||
/*
|
||||
* IRQ handlers
|
||||
*/
|
||||
|
||||
void __irq_i2c1_ev(void) {
|
||||
_i2c_irq_handler(I2C1);
|
||||
}
|
||||
|
||||
void __irq_i2c2_ev(void) {
|
||||
_i2c_irq_handler(I2C2);
|
||||
}
|
||||
|
||||
void __irq_i2c1_er(void) {
|
||||
_i2c_irq_error_handler(I2C1);
|
||||
}
|
||||
|
||||
void __irq_i2c2_er(void) {
|
||||
_i2c_irq_error_handler(I2C2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal APIs
|
||||
*/
|
||||
|
||||
void _i2c_irq_priority_fixup(i2c_dev *dev) {
|
||||
/*
|
||||
* Important STM32 Errata:
|
||||
*
|
||||
* See STM32F10xx8 and STM32F10xxB Errata sheet (Doc ID 14574 Rev 8),
|
||||
* Section 2.11.1, 2.11.2.
|
||||
*
|
||||
* 2.11.1:
|
||||
* When the EV7, EV7_1, EV6_1, EV6_3, EV2, EV8, and EV3 events are not
|
||||
* managed before the current byte is being transferred, problems may be
|
||||
* encountered such as receiving an extra byte, reading the same data twice
|
||||
* or missing data.
|
||||
*
|
||||
* 2.11.2:
|
||||
* In Master Receiver mode, when closing the communication using
|
||||
* method 2, the content of the last read data can be corrupted.
|
||||
*
|
||||
* If the user software is not able to read the data N-1 before the STOP
|
||||
* condition is generated on the bus, the content of the shift register
|
||||
* (data N) will be corrupted. (data N is shifted 1-bit to the left).
|
||||
*
|
||||
* ----------------------------------------------------------------------
|
||||
*
|
||||
* In order to ensure that events are not missed, the i2c interrupt must
|
||||
* not be preempted. We set the i2c interrupt priority to be the highest
|
||||
* interrupt in the system (priority level 0). All other interrupts have
|
||||
* been initialized to priority level 16. See nvic_init().
|
||||
*/
|
||||
nvic_irq_set_priority(dev->ev_nvic_line, 0);
|
||||
nvic_irq_set_priority(dev->er_nvic_line, 0);
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Michael Hope.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/iwdg.c
|
||||
* @brief Independent watchdog (IWDG) support
|
||||
*/
|
||||
|
||||
#include <libmaple/iwdg.h>
|
||||
|
||||
/**
|
||||
* @brief Initialise and start the watchdog
|
||||
*
|
||||
* The prescaler and reload set the timeout. For example, a prescaler
|
||||
* of IWDG_PRE_32 divides the 40 kHz clock by 32 and gives roughly 1
|
||||
* ms per reload.
|
||||
*
|
||||
* @param prescaler Prescaler for the 40 kHz IWDG clock.
|
||||
* @param reload Independent watchdog counter reload value.
|
||||
*/
|
||||
void iwdg_init(iwdg_prescaler prescaler, uint16 reload) {
|
||||
IWDG_BASE->KR = IWDG_KR_UNLOCK;
|
||||
IWDG_BASE->PR = prescaler;
|
||||
IWDG_BASE->RLR = reload;
|
||||
|
||||
/* Start things off */
|
||||
IWDG_BASE->KR = IWDG_KR_START;
|
||||
iwdg_feed();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the IWDG counter.
|
||||
*
|
||||
* Calling this function will cause the IWDG counter to be reset to
|
||||
* its reload value.
|
||||
*/
|
||||
void iwdg_feed(void) {
|
||||
IWDG_BASE->KR = IWDG_KR_FEED;
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/nvic.c
|
||||
* @brief Nested vector interrupt controller support.
|
||||
*/
|
||||
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/scb.h>
|
||||
#include <libmaple/stm32.h>
|
||||
|
||||
/**
|
||||
* @brief Set interrupt priority for an interrupt line
|
||||
*
|
||||
* Note: The STM32 only implements 4 bits of priority, ignoring the
|
||||
* lower 4 bits. This means there are only 16 levels of priority.
|
||||
* Bits[3:0] read as zero and ignore writes.
|
||||
*
|
||||
* @param irqn device to set
|
||||
* @param priority Priority to set, 0 being highest priority and 15
|
||||
* being lowest.
|
||||
*/
|
||||
void nvic_irq_set_priority(nvic_irq_num irqn, uint8 priority) {
|
||||
if (irqn < 0) {
|
||||
/* This interrupt is in the system handler block */
|
||||
SCB_BASE->SHP[((uint32)irqn & 0xF) - 4] = (priority & 0xF) << 4;
|
||||
} else {
|
||||
NVIC_BASE->IP[irqn] = (priority & 0xF) << 4;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the NVIC, setting interrupts to a default priority.
|
||||
*/
|
||||
void nvic_init(uint32 address, uint32 offset) {
|
||||
uint32 i;
|
||||
|
||||
nvic_set_vector_table(address, offset);
|
||||
|
||||
/*
|
||||
* Lower priority level for all peripheral interrupts to lowest
|
||||
* possible.
|
||||
*/
|
||||
for (i = 0; i < STM32_NR_INTERRUPTS; i++) {
|
||||
nvic_irq_set_priority((nvic_irq_num)i, 0xF);
|
||||
}
|
||||
|
||||
/* Lower systick interrupt priority to lowest level */
|
||||
nvic_irq_set_priority(NVIC_SYSTICK, 0xF);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the vector table base address.
|
||||
*
|
||||
* For stand-alone products, the vector table base address is normally
|
||||
* the start of Flash (0x08000000).
|
||||
*
|
||||
* @param address Vector table base address.
|
||||
* @param offset Offset from address. Some restrictions apply to the
|
||||
* use of nonzero offsets; see the ARM Cortex M3
|
||||
* Technical Reference Manual.
|
||||
*/
|
||||
void nvic_set_vector_table(uint32 address, uint32 offset) {
|
||||
SCB_BASE->VTOR = address | (offset & 0x1FFFFF80);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Force a system reset.
|
||||
*
|
||||
* Resets all major system components, excluding debug.
|
||||
*/
|
||||
void nvic_sys_reset() {
|
||||
uint32 prigroup = SCB_BASE->AIRCR & SCB_AIRCR_PRIGROUP;
|
||||
SCB_BASE->AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ | prigroup;
|
||||
asm volatile("dsb");
|
||||
while (1)
|
||||
;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/pwr.c
|
||||
* @brief Power control (PWR) support.
|
||||
*/
|
||||
|
||||
#include <libmaple/pwr.h>
|
||||
#include <libmaple/rcc.h>
|
||||
|
||||
/**
|
||||
* Enables the power interface clock, and resets the power device.
|
||||
*/
|
||||
void pwr_init(void) {
|
||||
rcc_clk_enable(RCC_PWR);
|
||||
rcc_reset_dev(RCC_PWR);
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/rcc.c
|
||||
* @brief Portable RCC routines.
|
||||
*/
|
||||
|
||||
#include <libmaple/rcc.h>
|
||||
|
||||
#include "rcc_private.h"
|
||||
|
||||
/**
|
||||
* @brief Get a peripheral's clock domain
|
||||
* @param id Clock ID of the peripheral whose clock domain to return
|
||||
* @return Clock source for the given clock ID
|
||||
*/
|
||||
rcc_clk_domain rcc_dev_clk(rcc_clk_id id) {
|
||||
return rcc_dev_table[id].clk_domain;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switch the clock used as the source of the system clock.
|
||||
*
|
||||
* After switching the source, this function blocks until the new
|
||||
* clock source is in use.
|
||||
*
|
||||
* @param sysclk_src New system clock source.
|
||||
* @see rcc_sysclk_src
|
||||
*/
|
||||
void rcc_switch_sysclk(rcc_sysclk_src sysclk_src) {
|
||||
uint32 cfgr = RCC_BASE->CFGR;
|
||||
cfgr &= ~RCC_CFGR_SW;
|
||||
cfgr |= sysclk_src;
|
||||
|
||||
/* Switch SYSCLK source. */
|
||||
RCC_BASE->CFGR = cfgr;
|
||||
|
||||
/* Wait for new source to come into use. */
|
||||
while ((RCC_BASE->CFGR & RCC_CFGR_SWS) != (sysclk_src << 2))
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Turning clocks off and on, querying their status.
|
||||
*/
|
||||
|
||||
/* IMPORTANT NOTE FOR IMPLEMENTORS:
|
||||
*
|
||||
* libmaple assumes that enum rcc_clk enumerators are two-byte
|
||||
* values, stored in a uint16, in the following way:
|
||||
*
|
||||
* - The high-order byte is the byte offset (from RCC_BASE) of the register
|
||||
* to touch when turning on or off the given clock.
|
||||
*
|
||||
* - The low-order byte is the bit in that register that turns the
|
||||
* clock on or off.
|
||||
*
|
||||
* Example for STM32F1: Turning on the high-speed external clock (HSE)
|
||||
* involves setting HSEON, bit 16, of RCC_CR. The high-order byte is
|
||||
* then offsetof(struct rcc_reg_map, CR) = 0, and the low-order byte
|
||||
* is 16.
|
||||
*
|
||||
* The corresponding value of RCC_CLK_HSE is thus (0 << 8) | 16 = 16.
|
||||
*
|
||||
* On all known STM32 series, this encoding has the property that
|
||||
* adding one to the low byte also gives the bit to check to determine
|
||||
* if the clock is ready. For example, on STM32F1, RCC_CR_HSERDY is
|
||||
* bit 17. If that's not the case on your series, rcc_is_clk_ready()
|
||||
* won't work for you. */
|
||||
|
||||
/* Returns the RCC register which controls the clock source. */
|
||||
static inline __io uint32* rcc_clk_reg(rcc_clk clock) {
|
||||
return (__io uint32*)((__io uint8*)RCC_BASE + (clock >> 8));
|
||||
}
|
||||
|
||||
/* Returns a mask in rcc_clk_reg(clock) to be used for turning the
|
||||
* clock on and off */
|
||||
static inline uint32 rcc_clk_on_mask(rcc_clk clock) {
|
||||
return 1 << (clock & 0xFF);
|
||||
}
|
||||
|
||||
/* Returns a mask in rcc_clk_reg(clock) to be used when checking the
|
||||
* readiness of the clock. */
|
||||
static inline uint32 rcc_clk_ready_mask(rcc_clk clock) {
|
||||
return rcc_clk_on_mask(clock) << 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn on a clock source.
|
||||
*
|
||||
* After this routine exits, callers should ensure that the clock
|
||||
* source is ready by waiting until rcc_is_clk_ready(clock) returns
|
||||
* true.
|
||||
*
|
||||
* @param clock Clock to turn on.
|
||||
* @see rcc_turn_off_clk()
|
||||
* @see rcc_is_clk_ready()
|
||||
*/
|
||||
void rcc_turn_on_clk(rcc_clk clock) {
|
||||
*rcc_clk_reg(clock) |= rcc_clk_on_mask(clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn off a clock source.
|
||||
*
|
||||
* In certain configurations, certain clock sources cannot be safely
|
||||
* turned off. (For example, the main PLL on STM32F1 devices cannot be
|
||||
* turned off if it has been selected as the SYSCLK source). Consult
|
||||
* the reference material for your MCU to ensure it is safe to call
|
||||
* this function.
|
||||
*
|
||||
* @param clock Clock to turn off.
|
||||
* @see rcc_turn_on_clk()
|
||||
* @see rcc_is_clk_ready()
|
||||
*/
|
||||
void rcc_turn_off_clk(rcc_clk clock) {
|
||||
*rcc_clk_reg(clock) &= ~rcc_clk_on_mask(clock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a clock is on.
|
||||
* @param clock Clock to check.
|
||||
* @return 1 if the clock is on, 0 if the clock is off.
|
||||
*/
|
||||
int rcc_is_clk_on(rcc_clk clock) {
|
||||
return !!(*rcc_clk_reg(clock) & rcc_clk_on_mask(clock));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a clock source is ready.
|
||||
*
|
||||
* In general, it is not safe to rely on a clock source unless this
|
||||
* function returns nonzero. Also note that this function may return
|
||||
* nonzero for a short period of time after a clock has been turned
|
||||
* off. Consult the reference material for your MCU for more details.
|
||||
*
|
||||
* @param clock Clock whose readiness to check for.
|
||||
* @return Nonzero if the clock is ready, zero otherwise.
|
||||
* @see rcc_turn_on_clk()
|
||||
* @see rcc_turn_off_clk()
|
||||
*/
|
||||
int rcc_is_clk_ready(rcc_clk clock) {
|
||||
return (int)(*rcc_clk_reg(clock) & rcc_clk_ready_mask(clock));
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/rcc.c
|
||||
* @brief STM32F1 RCC.
|
||||
*/
|
||||
|
||||
#include <libmaple/rcc.h>
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/bitband.h>
|
||||
|
||||
#include "rcc_private.h"
|
||||
|
||||
#define APB1 RCC_APB1
|
||||
#define APB2 RCC_APB2
|
||||
#define AHB RCC_AHB
|
||||
|
||||
/* Device descriptor table, maps rcc_clk_id onto bus and enable/reset
|
||||
* register bit numbers. */
|
||||
const struct rcc_dev_info rcc_dev_table[] = {
|
||||
[RCC_GPIOA] = { .clk_domain = APB2, .line_num = 2 },
|
||||
[RCC_GPIOB] = { .clk_domain = APB2, .line_num = 3 },
|
||||
[RCC_GPIOC] = { .clk_domain = APB2, .line_num = 4 },
|
||||
[RCC_GPIOD] = { .clk_domain = APB2, .line_num = 5 },
|
||||
[RCC_AFIO] = { .clk_domain = APB2, .line_num = 0 },
|
||||
[RCC_ADC1] = { .clk_domain = APB2, .line_num = 9 },
|
||||
[RCC_ADC2] = { .clk_domain = APB2, .line_num = 10 },
|
||||
[RCC_ADC3] = { .clk_domain = APB2, .line_num = 15 },
|
||||
[RCC_USART1] = { .clk_domain = APB2, .line_num = 14 },
|
||||
[RCC_USART2] = { .clk_domain = APB1, .line_num = 17 },
|
||||
[RCC_USART3] = { .clk_domain = APB1, .line_num = 18 },
|
||||
[RCC_TIMER1] = { .clk_domain = APB2, .line_num = 11 },
|
||||
[RCC_TIMER2] = { .clk_domain = APB1, .line_num = 0 },
|
||||
[RCC_TIMER3] = { .clk_domain = APB1, .line_num = 1 },
|
||||
[RCC_TIMER4] = { .clk_domain = APB1, .line_num = 2 },
|
||||
[RCC_SPI1] = { .clk_domain = APB2, .line_num = 12 },
|
||||
[RCC_SPI2] = { .clk_domain = APB1, .line_num = 14 },
|
||||
[RCC_DMA1] = { .clk_domain = AHB, .line_num = 0 },
|
||||
[RCC_PWR] = { .clk_domain = APB1, .line_num = 28},
|
||||
[RCC_BKP] = { .clk_domain = APB1, .line_num = 27},
|
||||
[RCC_I2C1] = { .clk_domain = APB1, .line_num = 21 },
|
||||
[RCC_I2C2] = { .clk_domain = APB1, .line_num = 22 },
|
||||
[RCC_CRC] = { .clk_domain = AHB, .line_num = 6},
|
||||
[RCC_FLITF] = { .clk_domain = AHB, .line_num = 4},
|
||||
[RCC_SRAM] = { .clk_domain = AHB, .line_num = 2},
|
||||
[RCC_USB] = { .clk_domain = APB1, .line_num = 23},
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
[RCC_GPIOE] = { .clk_domain = APB2, .line_num = 6 },
|
||||
[RCC_GPIOF] = { .clk_domain = APB2, .line_num = 7 },
|
||||
[RCC_GPIOG] = { .clk_domain = APB2, .line_num = 8 },
|
||||
[RCC_UART4] = { .clk_domain = APB1, .line_num = 19 },
|
||||
[RCC_UART5] = { .clk_domain = APB1, .line_num = 20 },
|
||||
[RCC_TIMER5] = { .clk_domain = APB1, .line_num = 3 },
|
||||
[RCC_TIMER6] = { .clk_domain = APB1, .line_num = 4 },
|
||||
[RCC_TIMER7] = { .clk_domain = APB1, .line_num = 5 },
|
||||
[RCC_TIMER8] = { .clk_domain = APB2, .line_num = 13 },
|
||||
[RCC_FSMC] = { .clk_domain = AHB, .line_num = 8 },
|
||||
[RCC_DAC] = { .clk_domain = APB1, .line_num = 29 },
|
||||
[RCC_DMA2] = { .clk_domain = AHB, .line_num = 1 },
|
||||
[RCC_SDIO] = { .clk_domain = AHB, .line_num = 10 },
|
||||
[RCC_SPI3] = { .clk_domain = APB1, .line_num = 15 },
|
||||
#endif
|
||||
#ifdef STM32_XL_DENSITY
|
||||
[RCC_TIMER9] = { .clk_domain = APB2, .line_num = 19 },
|
||||
[RCC_TIMER10] = { .clk_domain = APB2, .line_num = 20 },
|
||||
[RCC_TIMER11] = { .clk_domain = APB2, .line_num = 21 },
|
||||
[RCC_TIMER12] = { .clk_domain = APB1, .line_num = 6 },
|
||||
[RCC_TIMER13] = { .clk_domain = APB1, .line_num = 7 },
|
||||
[RCC_TIMER14] = { .clk_domain = APB1, .line_num = 8 },
|
||||
#endif
|
||||
};
|
||||
|
||||
__deprecated
|
||||
void rcc_clk_init(rcc_sysclk_src sysclk_src,
|
||||
rcc_pllsrc pll_src,
|
||||
rcc_pll_multiplier pll_mul) {
|
||||
/* Assume that we're going to clock the chip off the PLL, fed by
|
||||
* the HSE */
|
||||
ASSERT(sysclk_src == RCC_CLKSRC_PLL &&
|
||||
pll_src == RCC_PLLSRC_HSE);
|
||||
|
||||
RCC_BASE->CFGR = pll_src | pll_mul | (0x3<<22);
|
||||
|
||||
/* Turn on, and wait for, HSE. */
|
||||
rcc_turn_on_clk(RCC_CLK_HSE);
|
||||
while (!rcc_is_clk_ready(RCC_CLK_HSE))
|
||||
;
|
||||
|
||||
/* Do the same for the main PLL. */
|
||||
rcc_turn_on_clk(RCC_CLK_PLL);
|
||||
while(!rcc_is_clk_ready(RCC_CLK_PLL))
|
||||
;
|
||||
|
||||
/* Finally, switch over to the PLL. */
|
||||
rcc_switch_sysclk(RCC_CLKSRC_PLL);
|
||||
}
|
||||
|
||||
/* pll_cfg->data must point to a valid struct stm32f1_rcc_pll_data. */
|
||||
void rcc_configure_pll(rcc_pll_cfg *pll_cfg) {
|
||||
stm32f1_rcc_pll_data *data = pll_cfg->data;
|
||||
rcc_pll_multiplier pll_mul = data->pll_mul;
|
||||
uint32 cfgr;
|
||||
/* Check that the PLL is disabled. */
|
||||
ASSERT_FAULT(!rcc_is_clk_on(RCC_CLK_PLL));
|
||||
|
||||
cfgr = RCC_BASE->CFGR;
|
||||
cfgr &= ~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLMUL);
|
||||
cfgr |= pll_cfg->pllsrc | pll_mul;
|
||||
|
||||
RCC_BASE->CFGR = cfgr;
|
||||
}
|
||||
|
||||
void rcc_clk_enable(rcc_clk_id id) {
|
||||
static __io uint32* enable_regs[] = {
|
||||
[APB1] = &RCC_BASE->APB1ENR,
|
||||
[APB2] = &RCC_BASE->APB2ENR,
|
||||
[AHB] = &RCC_BASE->AHBENR,
|
||||
};
|
||||
rcc_do_clk_enable(enable_regs, id);
|
||||
}
|
||||
|
||||
void rcc_reset_dev(rcc_clk_id id) {
|
||||
static __io uint32* reset_regs[] = {
|
||||
[APB1] = &RCC_BASE->APB1RSTR,
|
||||
[APB2] = &RCC_BASE->APB2RSTR,
|
||||
};
|
||||
rcc_do_reset_dev(reset_regs, id);
|
||||
}
|
||||
|
||||
void rcc_set_prescaler(rcc_prescaler prescaler, uint32 divider) {
|
||||
static const uint32 masks[] = {
|
||||
[RCC_PRESCALER_AHB] = RCC_CFGR_HPRE,
|
||||
[RCC_PRESCALER_APB1] = RCC_CFGR_PPRE1,
|
||||
[RCC_PRESCALER_APB2] = RCC_CFGR_PPRE2,
|
||||
[RCC_PRESCALER_USB] = RCC_CFGR_USBPRE,
|
||||
[RCC_PRESCALER_ADC] = RCC_CFGR_ADCPRE,
|
||||
};
|
||||
rcc_do_set_prescaler(masks, prescaler, divider);
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/spi.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Serial Peripheral Interface (SPI) support.
|
||||
* Currently, there is no Integrated Interchip Sound (I2S) support.
|
||||
*/
|
||||
|
||||
#include <libmaple/spi.h>
|
||||
#include <libmaple/bitband.h>
|
||||
|
||||
static void spi_reconfigure(spi_dev *dev, uint32 cr1_config);
|
||||
|
||||
/*
|
||||
* SPI convenience routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize and reset a SPI device.
|
||||
* @param dev Device to initialize and reset.
|
||||
*/
|
||||
void spi_init(spi_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure and enable a SPI device as bus master.
|
||||
*
|
||||
* The device's peripheral will be disabled before being reconfigured.
|
||||
*
|
||||
* @param dev Device to configure as bus master
|
||||
* @param baud Bus baud rate
|
||||
* @param mode SPI mode
|
||||
* @param flags Logical OR of spi_cfg_flag values.
|
||||
* @see spi_cfg_flag
|
||||
*/
|
||||
void spi_master_enable(spi_dev *dev,
|
||||
spi_baud_rate baud,
|
||||
spi_mode mode,
|
||||
uint32 flags) {
|
||||
spi_reconfigure(dev, baud | flags | SPI_CR1_MSTR | mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure and enable a SPI device as a bus slave.
|
||||
*
|
||||
* The device's peripheral will be disabled before being reconfigured.
|
||||
*
|
||||
* @param dev Device to configure as a bus slave
|
||||
* @param mode SPI mode
|
||||
* @param flags Logical OR of spi_cfg_flag values.
|
||||
* @see spi_cfg_flag
|
||||
*/
|
||||
void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) {
|
||||
spi_reconfigure(dev, flags | mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Nonblocking SPI transmit.
|
||||
* @param dev SPI port to use for transmission
|
||||
* @param buf Buffer to transmit. The sizeof buf's elements are
|
||||
* inferred from dev's data frame format (i.e., are
|
||||
* correctly treated as 8-bit or 16-bit quantities).
|
||||
* @param len Maximum number of elements to transmit.
|
||||
* @return Number of elements transmitted.
|
||||
*/
|
||||
uint32 spi_tx(spi_dev *dev, const void *buf, uint32 len) {
|
||||
uint32 txed = 0;
|
||||
uint8 byte_frame = spi_dff(dev) == SPI_DFF_8_BIT;
|
||||
while (spi_is_tx_empty(dev) && (txed < len)) {
|
||||
if (byte_frame) {
|
||||
dev->regs->DR = ((const uint8*)buf)[txed++];
|
||||
} else {
|
||||
dev->regs->DR = ((const uint16*)buf)[txed++];
|
||||
}
|
||||
}
|
||||
return txed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a SPI peripheral
|
||||
* @param dev Device to enable
|
||||
*/
|
||||
void spi_peripheral_enable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a SPI peripheral
|
||||
* @param dev Device to disable
|
||||
*/
|
||||
void spi_peripheral_disable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR1, SPI_CR1_SPE_BIT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA requests whenever the transmit buffer is empty
|
||||
* @param dev SPI device on which to enable TX DMA requests
|
||||
*/
|
||||
void spi_tx_dma_enable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable DMA requests whenever the transmit buffer is empty
|
||||
* @param dev SPI device on which to disable TX DMA requests
|
||||
*/
|
||||
void spi_tx_dma_disable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_TXDMAEN_BIT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable DMA requests whenever the receive buffer is empty
|
||||
* @param dev SPI device on which to enable RX DMA requests
|
||||
*/
|
||||
void spi_rx_dma_enable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable DMA requests whenever the receive buffer is empty
|
||||
* @param dev SPI device on which to disable RX DMA requests
|
||||
*/
|
||||
void spi_rx_dma_disable(spi_dev *dev) {
|
||||
bb_peri_set_bit(&dev->regs->CR2, SPI_CR2_RXDMAEN_BIT, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* SPI auxiliary routines
|
||||
*/
|
||||
|
||||
static void spi_reconfigure(spi_dev *dev, uint32 cr1_config) {
|
||||
spi_irq_disable(dev, SPI_INTERRUPTS_ALL);
|
||||
spi_peripheral_disable(dev);
|
||||
dev->regs->CR1 = cr1_config;
|
||||
spi_peripheral_enable(dev);
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/spi.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief STM32F1 SPI/I2S.
|
||||
*/
|
||||
|
||||
#include <libmaple/spi.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include "spi_private.h"
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
static spi_dev spi1 = SPI_DEV(1);
|
||||
static spi_dev spi2 = SPI_DEV(2);
|
||||
|
||||
spi_dev *SPI1 = &spi1;
|
||||
spi_dev *SPI2 = &spi2;
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
static spi_dev spi3 = SPI_DEV(3);
|
||||
spi_dev *SPI3 = &spi3;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Routines
|
||||
*/
|
||||
|
||||
void spi_config_gpios(spi_dev *ignored,
|
||||
uint8 as_master,
|
||||
gpio_dev *nss_dev,
|
||||
uint8 nss_bit,
|
||||
gpio_dev *comm_dev,
|
||||
uint8 sck_bit,
|
||||
uint8 miso_bit,
|
||||
uint8 mosi_bit) {
|
||||
if (as_master) {
|
||||
// gpio_set_mode(nss_dev, nss_bit, GPIO_AF_OUTPUT_PP);// Roger Clark. Commented out, so that NSS can be driven as a normal GPIO pin during SPI use
|
||||
gpio_set_mode(comm_dev, sck_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(comm_dev, miso_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(comm_dev, mosi_bit, GPIO_AF_OUTPUT_PP);
|
||||
} else {
|
||||
gpio_set_mode(nss_dev, nss_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(comm_dev, sck_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(comm_dev, miso_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(comm_dev, mosi_bit, GPIO_INPUT_FLOATING);
|
||||
}
|
||||
}
|
||||
|
||||
void spi_foreach(void (*fn)(spi_dev*)) {
|
||||
fn(SPI1);
|
||||
fn(SPI2);
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
fn(SPI3);
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/* STM32F1 performance line ISR weak declarations */
|
||||
|
||||
#include <libmaple/stm32.h>
|
||||
|
||||
.thumb
|
||||
|
||||
/* Default handler for all non-overridden interrupts and exceptions */
|
||||
.globl __default_handler
|
||||
.type __default_handler, %function
|
||||
|
||||
__default_handler:
|
||||
b .
|
||||
|
||||
.weak __exc_nmi
|
||||
.globl __exc_nmi
|
||||
.set __exc_nmi, __default_handler
|
||||
.weak __exc_hardfault
|
||||
.globl __exc_hardfault
|
||||
.set __exc_hardfault, __default_handler
|
||||
.weak __exc_memmanage
|
||||
.globl __exc_memmanage
|
||||
.set __exc_memmanage, __default_handler
|
||||
.weak __exc_busfault
|
||||
.globl __exc_busfault
|
||||
.set __exc_busfault, __default_handler
|
||||
.weak __exc_usagefault
|
||||
.globl __exc_usagefault
|
||||
.set __exc_usagefault, __default_handler
|
||||
.weak __stm32reservedexception7
|
||||
.globl __stm32reservedexception7
|
||||
.set __stm32reservedexception7, __default_handler
|
||||
.weak __stm32reservedexception8
|
||||
.globl __stm32reservedexception8
|
||||
.set __stm32reservedexception8, __default_handler
|
||||
.weak __stm32reservedexception9
|
||||
.globl __stm32reservedexception9
|
||||
.set __stm32reservedexception9, __default_handler
|
||||
.weak __stm32reservedexception10
|
||||
.globl __stm32reservedexception10
|
||||
.set __stm32reservedexception10, __default_handler
|
||||
.weak __exc_svc
|
||||
.globl __exc_svc
|
||||
.set __exc_svc, __default_handler
|
||||
.weak __exc_debug_monitor
|
||||
.globl __exc_debug_monitor
|
||||
.set __exc_debug_monitor, __default_handler
|
||||
.weak __stm32reservedexception13
|
||||
.globl __stm32reservedexception13
|
||||
.set __stm32reservedexception13, __default_handler
|
||||
.weak __exc_pendsv
|
||||
.globl __exc_pendsv
|
||||
.set __exc_pendsv, __default_handler
|
||||
.weak __exc_systick
|
||||
.globl __exc_systick
|
||||
.set __exc_systick, __default_handler
|
||||
.weak __irq_wwdg
|
||||
.globl __irq_wwdg
|
||||
.set __irq_wwdg, __default_handler
|
||||
.weak __irq_pvd
|
||||
.globl __irq_pvd
|
||||
.set __irq_pvd, __default_handler
|
||||
.weak __irq_tamper
|
||||
.globl __irq_tamper
|
||||
.set __irq_tamper, __default_handler
|
||||
.weak __irq_rtc
|
||||
.globl __irq_rtc
|
||||
.set __irq_rtc, __default_handler
|
||||
.weak __irq_flash
|
||||
.globl __irq_flash
|
||||
.set __irq_flash, __default_handler
|
||||
.weak __irq_rcc
|
||||
.globl __irq_rcc
|
||||
.set __irq_rcc, __default_handler
|
||||
.weak __irq_exti0
|
||||
.globl __irq_exti0
|
||||
.set __irq_exti0, __default_handler
|
||||
.weak __irq_exti1
|
||||
.globl __irq_exti1
|
||||
.set __irq_exti1, __default_handler
|
||||
.weak __irq_exti2
|
||||
.globl __irq_exti2
|
||||
.set __irq_exti2, __default_handler
|
||||
.weak __irq_exti3
|
||||
.globl __irq_exti3
|
||||
.set __irq_exti3, __default_handler
|
||||
.weak __irq_exti4
|
||||
.globl __irq_exti4
|
||||
.set __irq_exti4, __default_handler
|
||||
.weak __irq_dma1_channel1
|
||||
.globl __irq_dma1_channel1
|
||||
.set __irq_dma1_channel1, __default_handler
|
||||
.weak __irq_dma1_channel2
|
||||
.globl __irq_dma1_channel2
|
||||
.set __irq_dma1_channel2, __default_handler
|
||||
.weak __irq_dma1_channel3
|
||||
.globl __irq_dma1_channel3
|
||||
.set __irq_dma1_channel3, __default_handler
|
||||
.weak __irq_dma1_channel4
|
||||
.globl __irq_dma1_channel4
|
||||
.set __irq_dma1_channel4, __default_handler
|
||||
.weak __irq_dma1_channel5
|
||||
.globl __irq_dma1_channel5
|
||||
.set __irq_dma1_channel5, __default_handler
|
||||
.weak __irq_dma1_channel6
|
||||
.globl __irq_dma1_channel6
|
||||
.set __irq_dma1_channel6, __default_handler
|
||||
.weak __irq_dma1_channel7
|
||||
.globl __irq_dma1_channel7
|
||||
.set __irq_dma1_channel7, __default_handler
|
||||
.weak __irq_adc
|
||||
.globl __irq_adc
|
||||
.set __irq_adc, __default_handler
|
||||
.weak __irq_usb_hp_can_tx
|
||||
.globl __irq_usb_hp_can_tx
|
||||
.set __irq_usb_hp_can_tx, __default_handler
|
||||
.weak __irq_usb_lp_can_rx0
|
||||
.globl __irq_usb_lp_can_rx0
|
||||
.set __irq_usb_lp_can_rx0, __default_handler
|
||||
.weak __irq_can_rx1
|
||||
.globl __irq_can_rx1
|
||||
.set __irq_can_rx1, __default_handler
|
||||
.weak __irq_can_sce
|
||||
.globl __irq_can_sce
|
||||
.set __irq_can_sce, __default_handler
|
||||
.weak __irq_exti9_5
|
||||
.globl __irq_exti9_5
|
||||
.set __irq_exti9_5, __default_handler
|
||||
.weak __irq_tim1_brk
|
||||
.globl __irq_tim1_brk
|
||||
.set __irq_tim1_brk, __default_handler
|
||||
.weak __irq_tim1_up
|
||||
.globl __irq_tim1_up
|
||||
.set __irq_tim1_up, __default_handler
|
||||
.weak __irq_tim1_trg_com
|
||||
.globl __irq_tim1_trg_com
|
||||
.set __irq_tim1_trg_com, __default_handler
|
||||
.weak __irq_tim1_cc
|
||||
.globl __irq_tim1_cc
|
||||
.set __irq_tim1_cc, __default_handler
|
||||
|
||||
.weakref __irq_tim2, __default_handler
|
||||
.globl __irq_tim2
|
||||
.weakref __irq_tim3, __default_handler
|
||||
.globl __irq_tim3
|
||||
.weakref __irq_tim4, __default_handler
|
||||
.globl __irq_tim4
|
||||
|
||||
.weak __irq_i2c1_ev
|
||||
.globl __irq_i2c1_ev
|
||||
.set __irq_i2c1_ev, __default_handler
|
||||
.weak __irq_i2c1_er
|
||||
.globl __irq_i2c1_er
|
||||
.set __irq_i2c1_er, __default_handler
|
||||
.weak __irq_i2c2_ev
|
||||
.globl __irq_i2c2_ev
|
||||
.set __irq_i2c2_ev, __default_handler
|
||||
.weak __irq_i2c2_er
|
||||
.globl __irq_i2c2_er
|
||||
.set __irq_i2c2_er, __default_handler
|
||||
.weak __irq_spi1
|
||||
.globl __irq_spi1
|
||||
.set __irq_spi1, __default_handler
|
||||
.weak __irq_spi2
|
||||
.globl __irq_spi2
|
||||
.set __irq_spi2, __default_handler
|
||||
.weak __irq_usart1
|
||||
.globl __irq_usart1
|
||||
.set __irq_usart1, __default_handler
|
||||
.weak __irq_usart2
|
||||
.globl __irq_usart2
|
||||
.set __irq_usart2, __default_handler
|
||||
.weak __irq_usart3
|
||||
.globl __irq_usart3
|
||||
.set __irq_usart3, __default_handler
|
||||
.weak __irq_exti15_10
|
||||
.globl __irq_exti15_10
|
||||
.set __irq_exti15_10, __default_handler
|
||||
.weak __irq_rtcalarm
|
||||
.globl __irq_rtcalarm
|
||||
.set __irq_rtcalarm, __default_handler
|
||||
.weak __irq_usbwakeup
|
||||
.globl __irq_usbwakeup
|
||||
.set __irq_usbwakeup, __default_handler
|
||||
#if defined (STM32_HIGH_DENSITY)
|
||||
.weak __irq_tim8_brk
|
||||
.globl __irq_tim8_brk
|
||||
.set __irq_tim8_brk, __default_handler
|
||||
.weak __irq_tim8_up
|
||||
.globl __irq_tim8_up
|
||||
.set __irq_tim8_up, __default_handler
|
||||
.weak __irq_tim8_trg_com
|
||||
.globl __irq_tim8_trg_com
|
||||
.set __irq_tim8_trg_com, __default_handler
|
||||
.weak __irq_tim8_cc
|
||||
.globl __irq_tim8_cc
|
||||
.set __irq_tim8_cc, __default_handler
|
||||
.weak __irq_adc3
|
||||
.globl __irq_adc3
|
||||
.set __irq_adc3, __default_handler
|
||||
.weak __irq_fsmc
|
||||
.globl __irq_fsmc
|
||||
.set __irq_fsmc, __default_handler
|
||||
.weak __irq_sdio
|
||||
.globl __irq_sdio
|
||||
.set __irq_sdio, __default_handler
|
||||
.weak __irq_tim5
|
||||
.globl __irq_tim5
|
||||
.set __irq_tim5, __default_handler
|
||||
.weak __irq_spi3
|
||||
.globl __irq_spi3
|
||||
.set __irq_spi3, __default_handler
|
||||
.weak __irq_uart4
|
||||
.globl __irq_uart4
|
||||
.set __irq_uart4, __default_handler
|
||||
.weak __irq_uart5
|
||||
.globl __irq_uart5
|
||||
.set __irq_uart5, __default_handler
|
||||
.weak __irq_tim6
|
||||
.globl __irq_tim6
|
||||
.set __irq_tim6, __default_handler
|
||||
.weak __irq_tim7
|
||||
.globl __irq_tim7
|
||||
.set __irq_tim7, __default_handler
|
||||
.weak __irq_dma2_channel1
|
||||
.globl __irq_dma2_channel1
|
||||
.set __irq_dma2_channel1, __default_handler
|
||||
.weak __irq_dma2_channel2
|
||||
.globl __irq_dma2_channel2
|
||||
.set __irq_dma2_channel2, __default_handler
|
||||
.weak __irq_dma2_channel3
|
||||
.globl __irq_dma2_channel3
|
||||
.set __irq_dma2_channel3, __default_handler
|
||||
.weak __irq_dma2_channel4_5
|
||||
.globl __irq_dma2_channel4_5
|
||||
.set __irq_dma2_channel4_5, __default_handler
|
||||
#endif /* STM32_HIGH_DENSITY */
|
|
@ -0,0 +1,118 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/* STM32F1 performance line vector table */
|
||||
|
||||
#include <libmaple/stm32.h>
|
||||
|
||||
.section ".stm32.interrupt_vector"
|
||||
|
||||
.globl __stm32_vector_table
|
||||
.type __stm32_vector_table, %object
|
||||
|
||||
__stm32_vector_table:
|
||||
/* CM3 core interrupts */
|
||||
.long __msp_init
|
||||
.long __exc_reset
|
||||
.long __exc_nmi
|
||||
.long __exc_hardfault
|
||||
.long __exc_memmanage
|
||||
.long __exc_busfault
|
||||
.long __exc_usagefault
|
||||
.long __stm32reservedexception7
|
||||
.long __stm32reservedexception8
|
||||
.long __stm32reservedexception9
|
||||
.long __stm32reservedexception10
|
||||
.long __exc_svc
|
||||
.long __exc_debug_monitor
|
||||
.long __stm32reservedexception13
|
||||
.long __exc_pendsv
|
||||
.long __exc_systick
|
||||
/* Peripheral interrupts */
|
||||
.long __irq_wwdg
|
||||
.long __irq_pvd
|
||||
.long __irq_tamper
|
||||
.long __irq_rtc
|
||||
.long __irq_flash
|
||||
.long __irq_rcc
|
||||
.long __irq_exti0
|
||||
.long __irq_exti1
|
||||
.long __irq_exti2
|
||||
.long __irq_exti3
|
||||
.long __irq_exti4
|
||||
.long __irq_dma1_channel1
|
||||
.long __irq_dma1_channel2
|
||||
.long __irq_dma1_channel3
|
||||
.long __irq_dma1_channel4
|
||||
.long __irq_dma1_channel5
|
||||
.long __irq_dma1_channel6
|
||||
.long __irq_dma1_channel7
|
||||
.long __irq_adc
|
||||
.long __irq_usb_hp_can_tx
|
||||
.long __irq_usb_lp_can_rx0
|
||||
.long __irq_can_rx1
|
||||
.long __irq_can_sce
|
||||
.long __irq_exti9_5
|
||||
.long __irq_tim1_brk
|
||||
.long __irq_tim1_up
|
||||
.long __irq_tim1_trg_com
|
||||
.long __irq_tim1_cc
|
||||
.long __irq_tim2
|
||||
.long __irq_tim3
|
||||
.long __irq_tim4
|
||||
.long __irq_i2c1_ev
|
||||
.long __irq_i2c1_er
|
||||
.long __irq_i2c2_ev
|
||||
.long __irq_i2c2_er
|
||||
.long __irq_spi1
|
||||
.long __irq_spi2
|
||||
.long __irq_usart1
|
||||
.long __irq_usart2
|
||||
.long __irq_usart3
|
||||
.long __irq_exti15_10
|
||||
.long __irq_rtcalarm
|
||||
.long __irq_usbwakeup
|
||||
#if defined (STM32_HIGH_DENSITY)
|
||||
.long __irq_tim8_brk
|
||||
.long __irq_tim8_up
|
||||
.long __irq_tim8_trg_com
|
||||
.long __irq_tim8_cc
|
||||
.long __irq_adc3
|
||||
.long __irq_fsmc
|
||||
.long __irq_sdio
|
||||
.long __irq_tim5
|
||||
.long __irq_spi3
|
||||
.long __irq_uart4
|
||||
.long __irq_uart5
|
||||
.long __irq_tim6
|
||||
.long __irq_tim7
|
||||
.long __irq_dma2_channel1
|
||||
.long __irq_dma2_channel2
|
||||
.long __irq_dma2_channel3
|
||||
.long __irq_dma2_channel4_5
|
||||
#endif /* STM32_HIGH_DENSITY */
|
||||
|
||||
.size __stm32_vector_table, . - __stm32_vector_table
|
|
@ -0,0 +1,88 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2010, 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/systick.c
|
||||
* @brief System timer (SysTick).
|
||||
*/
|
||||
|
||||
#include <libmaple/systick.h>
|
||||
|
||||
volatile uint32 systick_uptime_millis;
|
||||
static void (*systick_user_callback)(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize and enable SysTick.
|
||||
*
|
||||
* Clocks the system timer with the core clock, turns it on, and
|
||||
* enables interrupts.
|
||||
*
|
||||
* @param reload_val Appropriate reload counter to tick every 1 ms.
|
||||
*/
|
||||
void systick_init(uint32 reload_val) {
|
||||
SYSTICK_BASE->RVR = reload_val;
|
||||
systick_enable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clock the system timer with the core clock, but don't turn it
|
||||
* on or enable interrupt.
|
||||
*/
|
||||
void systick_disable() {
|
||||
SYSTICK_BASE->CSR = SYSTICK_CSR_CLKSOURCE_CORE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clock the system timer with the core clock and turn it on;
|
||||
* interrupt every 1 ms, for systick_timer_millis.
|
||||
*/
|
||||
void systick_enable() {
|
||||
/* re-enables init registers without changing reload val */
|
||||
SYSTICK_BASE->CSR = (SYSTICK_CSR_CLKSOURCE_CORE |
|
||||
SYSTICK_CSR_ENABLE |
|
||||
SYSTICK_CSR_TICKINT_PEND);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a callback to be called from the SysTick exception handler.
|
||||
*
|
||||
* To detach a callback, call this function again with a null argument.
|
||||
*/
|
||||
void systick_attach_callback(void (*callback)(void)) {
|
||||
systick_user_callback = callback;
|
||||
}
|
||||
|
||||
/*
|
||||
* SysTick ISR
|
||||
*/
|
||||
|
||||
void __exc_systick(void) {
|
||||
systick_uptime_millis++;
|
||||
if (systick_user_callback) {
|
||||
systick_user_callback();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,512 @@
|
|||
|
||||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/timer.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Portable timer routines.
|
||||
*/
|
||||
|
||||
#include <libmaple/timer.h>
|
||||
#include <libmaple/stm32.h>
|
||||
#include "timer_private.h"
|
||||
|
||||
static void disable_channel(timer_dev *dev, uint8 channel);
|
||||
static void pwm_mode(timer_dev *dev, uint8 channel);
|
||||
static void output_compare_mode(timer_dev *dev, uint8 channel);
|
||||
|
||||
static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid);
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*
|
||||
* Defer to the timer_private API for declaring these.
|
||||
*/
|
||||
|
||||
#if STM32_HAVE_TIMER(1)
|
||||
timer_dev timer1 = ADVANCED_TIMER(1);
|
||||
/** Timer 1 device (advanced) */
|
||||
timer_dev *const TIMER1 = &timer1;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(2)
|
||||
timer_dev timer2 = GENERAL_TIMER(2);
|
||||
/** Timer 2 device (general-purpose) */
|
||||
timer_dev *const TIMER2 = &timer2;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(3)
|
||||
timer_dev timer3 = GENERAL_TIMER(3);
|
||||
/** Timer 3 device (general-purpose) */
|
||||
timer_dev *const TIMER3 = &timer3;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(4)
|
||||
timer_dev timer4 = GENERAL_TIMER(4);
|
||||
/** Timer 4 device (general-purpose) */
|
||||
timer_dev *const TIMER4 = &timer4;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(5)
|
||||
timer_dev timer5 = GENERAL_TIMER(5);
|
||||
/** Timer 5 device (general-purpose) */
|
||||
timer_dev *const TIMER5 = &timer5;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(6)
|
||||
timer_dev timer6 = BASIC_TIMER(6);
|
||||
/** Timer 6 device (basic) */
|
||||
timer_dev *const TIMER6 = &timer6;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(7)
|
||||
timer_dev timer7 = BASIC_TIMER(7);
|
||||
/** Timer 7 device (basic) */
|
||||
timer_dev *const TIMER7 = &timer7;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(8)
|
||||
timer_dev timer8 = ADVANCED_TIMER(8);
|
||||
/** Timer 8 device (advanced) */
|
||||
timer_dev *const TIMER8 = &timer8;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(9)
|
||||
timer_dev timer9 = RESTRICTED_GENERAL_TIMER(9, TIMER_DIER_TIE_BIT);
|
||||
/** Timer 9 device (general-purpose) */
|
||||
timer_dev *const TIMER9 = &timer9;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(10)
|
||||
timer_dev timer10 = RESTRICTED_GENERAL_TIMER(10, TIMER_DIER_CC1IE_BIT);
|
||||
/** Timer 10 device (general-purpose) */
|
||||
timer_dev *const TIMER10 = &timer10;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(11)
|
||||
timer_dev timer11 = RESTRICTED_GENERAL_TIMER(11, TIMER_DIER_CC1IE_BIT);
|
||||
/** Timer 11 device (general-purpose) */
|
||||
timer_dev *const TIMER11 = &timer11;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(12)
|
||||
timer_dev timer12 = RESTRICTED_GENERAL_TIMER(12, TIMER_DIER_TIE_BIT);
|
||||
/** Timer 12 device (general-purpose) */
|
||||
timer_dev *const TIMER12 = &timer12;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(13)
|
||||
timer_dev timer13 = RESTRICTED_GENERAL_TIMER(13, TIMER_DIER_CC1IE_BIT);
|
||||
/** Timer 13 device (general-purpose) */
|
||||
timer_dev *const TIMER13 = &timer13;
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(14)
|
||||
timer_dev timer14 = RESTRICTED_GENERAL_TIMER(14, TIMER_DIER_CC1IE_BIT);
|
||||
/** Timer 14 device (general-purpose) */
|
||||
timer_dev *const TIMER14 = &timer14;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Routines
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Call a function on timer devices.
|
||||
* @param fn Function to call on each timer device.
|
||||
*/
|
||||
void timer_foreach(void (*fn)(timer_dev*)) {
|
||||
#if STM32_HAVE_TIMER(1)
|
||||
fn(TIMER1);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(2)
|
||||
fn(TIMER2);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(3)
|
||||
fn(TIMER3);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(4)
|
||||
fn(TIMER4);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(5)
|
||||
fn(TIMER5);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(6)
|
||||
fn(TIMER6);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(7)
|
||||
fn(TIMER7);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(8)
|
||||
fn(TIMER8);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(9)
|
||||
fn(TIMER9);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(10)
|
||||
fn(TIMER10);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(11)
|
||||
fn(TIMER11);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(12)
|
||||
fn(TIMER12);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(13)
|
||||
fn(TIMER13);
|
||||
#endif
|
||||
#if STM32_HAVE_TIMER(14)
|
||||
fn(TIMER14);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a timer, and reset its register map.
|
||||
* @param dev Timer to initialize
|
||||
*/
|
||||
void timer_init(timer_dev *dev) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
rcc_reset_dev(dev->clk_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable a timer.
|
||||
*
|
||||
* The timer will stop counting, all DMA requests and interrupts will
|
||||
* be disabled, and no state changes will be output.
|
||||
*
|
||||
* @param dev Timer to disable.
|
||||
*/
|
||||
void timer_disable(timer_dev *dev) {
|
||||
(dev->regs).bas->CR1 = 0;
|
||||
(dev->regs).bas->DIER = 0;
|
||||
switch (dev->type) {
|
||||
case TIMER_ADVANCED: /* fall-through */
|
||||
case TIMER_GENERAL:
|
||||
(dev->regs).gen->CCER = 0;
|
||||
break;
|
||||
case TIMER_BASIC:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mode of an individual timer channel.
|
||||
*
|
||||
* Note that not all timers can be configured in every mode. For
|
||||
* example, basic timers cannot be configured to output compare mode.
|
||||
* Be sure to use a timer which is appropriate for the mode you want.
|
||||
*
|
||||
* @param dev Timer whose channel mode to set
|
||||
* @param channel Relevant channel
|
||||
* @param mode New timer mode for channel
|
||||
*/
|
||||
void timer_set_mode(timer_dev *dev, uint8 channel, timer_mode mode) {
|
||||
ASSERT_FAULT(channel > 0 && channel <= 4);
|
||||
|
||||
/* TODO decide about the basic timers */
|
||||
ASSERT(dev->type != TIMER_BASIC);
|
||||
if (dev->type == TIMER_BASIC)
|
||||
return;
|
||||
|
||||
switch (mode) {
|
||||
case TIMER_DISABLED:
|
||||
disable_channel(dev, channel);
|
||||
break;
|
||||
case TIMER_PWM:
|
||||
pwm_mode(dev, channel);
|
||||
break;
|
||||
case TIMER_OUTPUT_COMPARE:
|
||||
output_compare_mode(dev, channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determine whether a timer has a particular capture/compare channel.
|
||||
*
|
||||
* Different timers have different numbers of capture/compare channels
|
||||
* (and some have none at all). Use this function to test whether a
|
||||
* given timer/channel combination will work.
|
||||
*
|
||||
* @param dev Timer device
|
||||
* @param channel Capture/compare channel, from 1 to 4
|
||||
* @return Nonzero if dev has channel, zero otherwise.
|
||||
*/
|
||||
int timer_has_cc_channel(timer_dev *dev, uint8 channel) {
|
||||
/* On all currently supported series: advanced and "full-featured"
|
||||
* general purpose timers have all four channels. Of the
|
||||
* restricted general timers, timers 9 and 12 have channels 1 and
|
||||
* 2; the others have channel 1 only. Basic timers have none. */
|
||||
rcc_clk_id id = dev->clk_id;
|
||||
ASSERT((1 <= channel) && (channel <= 4));
|
||||
if (id <= RCC_TIMER5 || id == RCC_TIMER8) {
|
||||
return 1; /* 1 and 8 are advanced, 2-5 are "full" general */
|
||||
} else if (id <= RCC_TIMER7) {
|
||||
return 0; /* 6 and 7 are basic */
|
||||
}
|
||||
/* The rest are restricted general. */
|
||||
return (((id == RCC_TIMER9 || id == RCC_TIMER12) && channel <= 2) ||
|
||||
channel == 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Attach a timer interrupt.
|
||||
* @param dev Timer device
|
||||
* @param interrupt Interrupt number to attach to; this may be any
|
||||
* timer_interrupt_id or timer_channel value appropriate
|
||||
* for the timer.
|
||||
* @param handler Handler to attach to the given interrupt.
|
||||
* @see timer_interrupt_id
|
||||
* @see timer_channel
|
||||
*/
|
||||
void timer_attach_interrupt(timer_dev *dev,
|
||||
uint8 interrupt,
|
||||
voidFuncPtr handler) {
|
||||
dev->handlers[interrupt] = handler;
|
||||
timer_enable_irq(dev, interrupt);
|
||||
enable_irq(dev, interrupt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Detach a timer interrupt.
|
||||
* @param dev Timer device
|
||||
* @param interrupt Interrupt number to detach; this may be any
|
||||
* timer_interrupt_id or timer_channel value appropriate
|
||||
* for the timer.
|
||||
* @see timer_interrupt_id
|
||||
* @see timer_channel
|
||||
*/
|
||||
void timer_detach_interrupt(timer_dev *dev, uint8 interrupt) {
|
||||
timer_disable_irq(dev, interrupt);
|
||||
dev->handlers[interrupt] = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Utilities
|
||||
*/
|
||||
|
||||
static void disable_channel(timer_dev *dev, uint8 channel) {
|
||||
timer_detach_interrupt(dev, channel);
|
||||
timer_cc_disable(dev, channel);
|
||||
}
|
||||
|
||||
static void pwm_mode(timer_dev *dev, uint8 channel) {
|
||||
timer_disable_irq(dev, channel);
|
||||
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_PWM_1, TIMER_OC_PE);
|
||||
timer_cc_enable(dev, channel);
|
||||
}
|
||||
|
||||
static void output_compare_mode(timer_dev *dev, uint8 channel) {
|
||||
timer_oc_set_mode(dev, channel, TIMER_OC_MODE_ACTIVE_ON_MATCH, 0);
|
||||
timer_cc_enable(dev, channel);
|
||||
}
|
||||
|
||||
static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id);
|
||||
static void enable_bas_gen_irq(timer_dev *dev);
|
||||
|
||||
static inline void enable_irq(timer_dev *dev, timer_interrupt_id iid) {
|
||||
if (dev->type == TIMER_ADVANCED) {
|
||||
enable_adv_irq(dev, iid);
|
||||
} else {
|
||||
enable_bas_gen_irq(dev);
|
||||
}
|
||||
}
|
||||
|
||||
/* Advanced control timers have several IRQ lines corresponding to
|
||||
* different timer interrupts.
|
||||
*
|
||||
* Note: This function assumes that the only advanced timers are TIM1
|
||||
* and TIM8, and needs the obvious changes if that assumption is
|
||||
* violated by a later STM32 series. */
|
||||
static void enable_adv_irq(timer_dev *dev, timer_interrupt_id id) {
|
||||
uint8 is_tim1 = dev->clk_id == RCC_TIMER1;
|
||||
nvic_irq_num irq_num;
|
||||
switch (id) {
|
||||
case TIMER_UPDATE_INTERRUPT:
|
||||
irq_num = (is_tim1 ?
|
||||
NVIC_TIMER1_UP_TIMER10 :
|
||||
NVIC_TIMER8_UP_TIMER13);
|
||||
break;
|
||||
case TIMER_CC1_INTERRUPT: /* Fall through */
|
||||
case TIMER_CC2_INTERRUPT: /* ... */
|
||||
case TIMER_CC3_INTERRUPT: /* ... */
|
||||
case TIMER_CC4_INTERRUPT:
|
||||
irq_num = is_tim1 ? NVIC_TIMER1_CC : NVIC_TIMER8_CC;
|
||||
break;
|
||||
case TIMER_COM_INTERRUPT: /* Fall through */
|
||||
case TIMER_TRG_INTERRUPT:
|
||||
irq_num = (is_tim1 ?
|
||||
NVIC_TIMER1_TRG_COM_TIMER11 :
|
||||
NVIC_TIMER8_TRG_COM_TIMER14);
|
||||
break;
|
||||
case TIMER_BREAK_INTERRUPT:
|
||||
irq_num = (is_tim1 ?
|
||||
NVIC_TIMER1_BRK_TIMER9 :
|
||||
NVIC_TIMER8_BRK_TIMER12);
|
||||
break;
|
||||
default:
|
||||
/* Can't happen, but placate the compiler */
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
nvic_irq_enable(irq_num);
|
||||
}
|
||||
|
||||
/* Basic and general purpose timers have a single IRQ line, which is
|
||||
* shared by all interrupts supported by a particular timer. */
|
||||
static void enable_bas_gen_irq(timer_dev *dev) {
|
||||
nvic_irq_num irq_num;
|
||||
switch (dev->clk_id) {
|
||||
case RCC_TIMER2:
|
||||
irq_num = NVIC_TIMER2;
|
||||
break;
|
||||
case RCC_TIMER3:
|
||||
irq_num = NVIC_TIMER3;
|
||||
break;
|
||||
case RCC_TIMER4:
|
||||
irq_num = NVIC_TIMER4;
|
||||
break;
|
||||
case RCC_TIMER5:
|
||||
irq_num = NVIC_TIMER5;
|
||||
break;
|
||||
case RCC_TIMER6:
|
||||
irq_num = NVIC_TIMER6;
|
||||
break;
|
||||
case RCC_TIMER7:
|
||||
irq_num = NVIC_TIMER7;
|
||||
break;
|
||||
case RCC_TIMER9:
|
||||
irq_num = NVIC_TIMER1_BRK_TIMER9;
|
||||
break;
|
||||
case RCC_TIMER10:
|
||||
irq_num = NVIC_TIMER1_UP_TIMER10;
|
||||
break;
|
||||
case RCC_TIMER11:
|
||||
irq_num = NVIC_TIMER1_TRG_COM_TIMER11;
|
||||
break;
|
||||
case RCC_TIMER12:
|
||||
irq_num = NVIC_TIMER8_BRK_TIMER12;
|
||||
break;
|
||||
case RCC_TIMER13:
|
||||
irq_num = NVIC_TIMER8_UP_TIMER13;
|
||||
break;
|
||||
case RCC_TIMER14:
|
||||
irq_num = NVIC_TIMER8_TRG_COM_TIMER14;
|
||||
break;
|
||||
default:
|
||||
ASSERT_FAULT(0);
|
||||
return;
|
||||
}
|
||||
nvic_irq_enable(irq_num);
|
||||
}
|
||||
|
||||
|
||||
/* Note.
|
||||
*
|
||||
* 2015/07/06 Roger Clark
|
||||
*
|
||||
* The IRQ handlers were initially in timer_f1.c however this seems to cause problems
|
||||
* in which the compiler / linker doesn't always link all the required handlers.
|
||||
* The work around was to move the handlers into this file
|
||||
*/
|
||||
|
||||
/*
|
||||
* IRQ handlers
|
||||
*
|
||||
* Defer to the timer_private dispatch API.
|
||||
*
|
||||
* FIXME: The names of these handlers are inaccurate since XL-density
|
||||
* devices came out. Update these to match the STM32F2 names, maybe
|
||||
* using some weak symbol magic to preserve backwards compatibility if
|
||||
* possible. Once that's done, we can just move the IRQ handlers into
|
||||
* the top-level libmaple/timer.c, and there will be no need for this
|
||||
* file.
|
||||
*/
|
||||
|
||||
void __irq_tim1_brk(void) {
|
||||
dispatch_adv_brk(TIMER1);
|
||||
#if STM32_HAVE_TIMER(9)
|
||||
dispatch_tim_9_12(TIMER9);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __irq_tim1_up(void) {
|
||||
dispatch_adv_up(TIMER1);
|
||||
#if STM32_HAVE_TIMER(10)
|
||||
dispatch_tim_10_11_13_14(TIMER10);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __irq_tim1_trg_com(void) {
|
||||
dispatch_adv_trg_com(TIMER1);
|
||||
#if STM32_HAVE_TIMER(11)
|
||||
dispatch_tim_10_11_13_14(TIMER11);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __irq_tim1_cc(void) {
|
||||
dispatch_adv_cc(TIMER1);
|
||||
}
|
||||
|
||||
void __irq_tim2(void) {
|
||||
dispatch_general(TIMER2);
|
||||
}
|
||||
|
||||
void __irq_tim3(void) {
|
||||
dispatch_general(TIMER3);
|
||||
}
|
||||
|
||||
void __irq_tim4(void) {
|
||||
dispatch_general(TIMER4);
|
||||
}
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
void __irq_tim5(void) {
|
||||
dispatch_general(TIMER5);
|
||||
}
|
||||
|
||||
void __irq_tim6(void) {
|
||||
dispatch_basic(TIMER6);
|
||||
}
|
||||
|
||||
void __irq_tim7(void) {
|
||||
dispatch_basic(TIMER7);
|
||||
}
|
||||
|
||||
void __irq_tim8_brk(void) {
|
||||
dispatch_adv_brk(TIMER8);
|
||||
#if STM32_HAVE_TIMER(12)
|
||||
dispatch_tim_9_12(TIMER12);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __irq_tim8_up(void) {
|
||||
dispatch_adv_up(TIMER8);
|
||||
#if STM32_HAVE_TIMER(13)
|
||||
dispatch_tim_10_11_13_14(TIMER13);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __irq_tim8_trg_com(void) {
|
||||
dispatch_adv_trg_com(TIMER8);
|
||||
#if STM32_HAVE_TIMER(14)
|
||||
dispatch_tim_10_11_13_14(TIMER14);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __irq_tim8_cc(void) {
|
||||
dispatch_adv_cc(TIMER8);
|
||||
}
|
||||
#endif /* defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY) */
|
|
@ -0,0 +1,41 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/timer.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief STM32F1 timer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2015/07/06
|
||||
* Note. The IRQ handlers which were initially in this file have been moved to timer.c
|
||||
* to resolve a linker issue in where some IRQ handlers were not being linked even though
|
||||
* they were being used.
|
||||
* This file has been retains for historical reasons, but can be moved at some time in the future
|
||||
* when full testing of the code in the new location has been completed.
|
||||
*/
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/usart.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>,
|
||||
* Perry Hung <perry@leaflabs.com>
|
||||
* @brief Portable USART routines
|
||||
*/
|
||||
|
||||
#include <libmaple/usart.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize a serial port.
|
||||
* @param dev Serial port to be initialized
|
||||
*/
|
||||
void usart_init(usart_dev *dev) {
|
||||
rb_init(dev->rb, USART_RX_BUF_SIZE, dev->rx_buf);
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
nvic_irq_enable(dev->irq_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable a serial port.
|
||||
*
|
||||
* USART is enabled in single buffer transmission mode, multibuffer
|
||||
* receiver mode, 8n1.
|
||||
*
|
||||
* Serial port must have a baud rate configured to work properly.
|
||||
*
|
||||
* @param dev Serial port to enable.
|
||||
* @see usart_set_baud_rate()
|
||||
*/
|
||||
void usart_enable(usart_dev *dev) {
|
||||
usart_reg_map *regs = dev->regs;
|
||||
regs->CR1 |= (USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE);// don't change the word length etc, and 'or' in the patten not overwrite |USART_CR1_M_8N1);
|
||||
regs->CR1 |= USART_CR1_UE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turn off a serial port.
|
||||
* @param dev Serial port to be disabled
|
||||
*/
|
||||
void usart_disable(usart_dev *dev) {
|
||||
/* FIXME this misbehaves (on F1) if you try to use PWM on TX afterwards */
|
||||
usart_reg_map *regs = dev->regs;
|
||||
|
||||
/* TC bit must be high before disabling the USART */
|
||||
while((regs->CR1 & USART_CR1_UE) && !(regs->SR & USART_SR_TC))
|
||||
;
|
||||
|
||||
/* Disable UE */
|
||||
regs->CR1 &= ~USART_CR1_UE;
|
||||
|
||||
/* Clean up buffer */
|
||||
usart_reset_rx(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Nonblocking USART transmit
|
||||
* @param dev Serial port to transmit over
|
||||
* @param buf Buffer to transmit
|
||||
* @param len Maximum number of bytes to transmit
|
||||
* @return Number of bytes transmitted
|
||||
*/
|
||||
uint32 usart_tx(usart_dev *dev, const uint8 *buf, uint32 len) {
|
||||
usart_reg_map *regs = dev->regs;
|
||||
uint32 txed = 0;
|
||||
while ((regs->SR & USART_SR_TXE) && (txed < len)) {
|
||||
regs->DR = buf[txed++];
|
||||
}
|
||||
return txed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Nonblocking USART receive.
|
||||
* @param dev Serial port to receive bytes from
|
||||
* @param buf Buffer to store received bytes into
|
||||
* @param len Maximum number of bytes to store
|
||||
* @return Number of bytes received
|
||||
*/
|
||||
uint32 usart_rx(usart_dev *dev, uint8 *buf, uint32 len) {
|
||||
uint32 rxed = 0;
|
||||
while (usart_data_available(dev) && rxed < len) {
|
||||
*buf++ = usart_getc(dev);
|
||||
rxed++;
|
||||
}
|
||||
return rxed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an unsigned integer to the specified serial port in
|
||||
* decimal format.
|
||||
*
|
||||
* This function blocks until the integer's digits have been
|
||||
* completely transmitted.
|
||||
*
|
||||
* @param dev Serial port to send on
|
||||
* @param val Number to print
|
||||
*/
|
||||
void usart_putudec(usart_dev *dev, uint32 val) {
|
||||
char digits[12];
|
||||
int i = 0;
|
||||
|
||||
do {
|
||||
digits[i++] = val % 10 + '0';
|
||||
val /= 10;
|
||||
} while (val > 0);
|
||||
|
||||
while (--i >= 0) {
|
||||
usart_putc(dev, digits[i]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/stm32f1/usart.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>,
|
||||
* Perry Hung <perry@leaflabs.com>
|
||||
* @brief STM32F1 USART.
|
||||
*/
|
||||
|
||||
#include <libmaple/usart.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include "usart_private.h"
|
||||
|
||||
/*
|
||||
* Devices
|
||||
*/
|
||||
|
||||
static ring_buffer usart1_rb;
|
||||
static usart_dev usart1 = {
|
||||
.regs = USART1_BASE,
|
||||
.rb = &usart1_rb,
|
||||
.max_baud = 4500000UL,
|
||||
.clk_id = RCC_USART1,
|
||||
.irq_num = NVIC_USART1,
|
||||
};
|
||||
/** USART1 device */
|
||||
usart_dev *USART1 = &usart1;
|
||||
|
||||
static ring_buffer usart2_rb;
|
||||
static usart_dev usart2 = {
|
||||
.regs = USART2_BASE,
|
||||
.rb = &usart2_rb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_USART2,
|
||||
.irq_num = NVIC_USART2,
|
||||
};
|
||||
/** USART2 device */
|
||||
usart_dev *USART2 = &usart2;
|
||||
|
||||
static ring_buffer usart3_rb;
|
||||
static usart_dev usart3 = {
|
||||
.regs = USART3_BASE,
|
||||
.rb = &usart3_rb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_USART3,
|
||||
.irq_num = NVIC_USART3,
|
||||
};
|
||||
/** USART3 device */
|
||||
usart_dev *USART3 = &usart3;
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
static ring_buffer uart4_rb;
|
||||
static usart_dev uart4 = {
|
||||
.regs = UART4_BASE,
|
||||
.rb = &uart4_rb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_UART4,
|
||||
.irq_num = NVIC_UART4,
|
||||
};
|
||||
/** UART4 device */
|
||||
usart_dev *UART4 = &uart4;
|
||||
|
||||
static ring_buffer uart5_rb;
|
||||
static usart_dev uart5 = {
|
||||
.regs = UART5_BASE,
|
||||
.rb = &uart5_rb,
|
||||
.max_baud = 2250000UL,
|
||||
.clk_id = RCC_UART5,
|
||||
.irq_num = NVIC_UART5,
|
||||
};
|
||||
/** UART5 device */
|
||||
usart_dev *UART5 = &uart5;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Routines
|
||||
*/
|
||||
|
||||
void usart_config_gpios_async(usart_dev *udev,
|
||||
gpio_dev *rx_dev, uint8 rx,
|
||||
gpio_dev *tx_dev, uint8 tx,
|
||||
unsigned flags) {
|
||||
gpio_set_mode(rx_dev, rx, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(tx_dev, tx, GPIO_AF_OUTPUT_PP);
|
||||
/*
|
||||
|
||||
CR1 bit 12 Word length 0=8 1=9
|
||||
CR1 bit 11 wake (default value is 0) we can safely set this value to 0 (zero) each time
|
||||
CR1 bit 10 parity enable (1 = enabled)
|
||||
CR1 bit 9 Parity selection 0 = Even 1 = Odd
|
||||
CR2 bits 13 and 12 00 = 1 01 = 0.5 10 = 2 11 = 1.5
|
||||
Not all USARTs support 1.5 or 0.5 bits so its best to avoid them.
|
||||
CR2 CR1
|
||||
0B00 0000
|
||||
0B10 0000
|
||||
0B00 1000
|
||||
0B10 1000
|
||||
|
||||
0B00 0010
|
||||
0B10 0010
|
||||
0B00 1010
|
||||
0B10 1010
|
||||
|
||||
0B00 0011
|
||||
0B10 0011
|
||||
0B00 1011
|
||||
0B10 1011
|
||||
|
||||
#define SERIAL_8N1 0B 0000 0000
|
||||
#define SERIAL_8N2 0B 0010 0000
|
||||
#define SERIAL_9N1 0B 0000 1000
|
||||
#define SERIAL_9N2 0B 0010 1000
|
||||
|
||||
#define SERIAL_8E1 0B 0000 0010
|
||||
#define SERIAL_8E2 0B 0010 0010
|
||||
#define SERIAL_9E1 0B 0000 1010
|
||||
#define SERIAL_9E2 0B 0010 1010
|
||||
|
||||
#define SERIAL_8O1 0B 0000 0011
|
||||
#define SERIAL_8O2 0B 0010 0011
|
||||
#define SERIAL_9O1 0B 0000 1011
|
||||
#define SERIAL_9O2 0B 0010 1011
|
||||
|
||||
*/
|
||||
|
||||
|
||||
udev->regs->CR1 = udev->regs->CR1 ^ ((udev->regs->CR1 ^ (flags&0x0F)<<9 ) & 0B0001111000000000);
|
||||
udev->regs->CR2 = udev->regs->CR2 ^ ((udev->regs->CR2 ^ (flags&0xF0)<<8 ) & 0B0011000000000000);
|
||||
}
|
||||
|
||||
void usart_set_baud_rate(usart_dev *dev, uint32 clock_speed, uint32 baud) {
|
||||
uint32 integer_part;
|
||||
uint32 fractional_part;
|
||||
uint32 tmp;
|
||||
|
||||
/* Figure out the clock speed, if the user doesn't give one. */
|
||||
if (clock_speed == 0) {
|
||||
clock_speed = _usart_clock_freq(dev);
|
||||
}
|
||||
ASSERT(clock_speed);
|
||||
|
||||
/* Convert desired baud rate to baud rate register setting. */
|
||||
integer_part = (25 * clock_speed) / (4 * baud);
|
||||
tmp = (integer_part / 100) << 4;
|
||||
fractional_part = integer_part - (100 * (tmp >> 4));
|
||||
tmp |= (((fractional_part * 16) + 50) / 100) & ((uint8)0x0F);
|
||||
|
||||
dev->regs->BRR = (uint16)tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call a function on each USART.
|
||||
* @param fn Function to call.
|
||||
*/
|
||||
void usart_foreach(void (*fn)(usart_dev*)) {
|
||||
fn(USART1);
|
||||
fn(USART2);
|
||||
fn(USART3);
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
fn(UART4);
|
||||
fn(UART5);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt handlers.
|
||||
*/
|
||||
|
||||
void __irq_usart1(void) {
|
||||
usart_irq(&usart1_rb, USART1_BASE);
|
||||
}
|
||||
|
||||
void __irq_usart2(void) {
|
||||
usart_irq(&usart2_rb, USART2_BASE);
|
||||
}
|
||||
|
||||
void __irq_usart3(void) {
|
||||
usart_irq(&usart3_rb, USART3_BASE);
|
||||
}
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
void __irq_uart4(void) {
|
||||
usart_irq(&uart4_rb, UART4_BASE);
|
||||
}
|
||||
|
||||
void __irq_uart5(void) {
|
||||
usart_irq(&uart5_rb, UART5_BASE);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,41 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/usart_private.c
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Private USART routines.
|
||||
*/
|
||||
|
||||
#include "usart_private.h"
|
||||
#include <libmaple/rcc.h>
|
||||
#include <libmaple/stm32.h>
|
||||
|
||||
uint32 _usart_clock_freq(usart_dev *dev) {
|
||||
rcc_clk_domain domain = rcc_dev_clk(dev->clk_id);
|
||||
return (domain == RCC_APB1 ? STM32_PCLK1 :
|
||||
(domain == RCC_APB2 ? STM32_PCLK2 : 0));
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
The USB submodule of libmaple is a separate piece of the codebase for
|
||||
reasons that are largely historical.
|
||||
|
||||
Current Status:
|
||||
|
||||
There's only support for the USB device peripheral found on
|
||||
STM32F103s.
|
||||
|
||||
We rely on the low level core library provided by ST to implement
|
||||
the USB transfer protocol for control endpoint transfers.
|
||||
|
||||
The virtual com port (which is exposed via
|
||||
<libmaple/usb_cdcacm.h>) serves two important purposes.
|
||||
|
||||
1) It allows serial data transfers between user sketches an a
|
||||
host computer.
|
||||
|
||||
2) It allows the host PC to issue a system reset into the DFU
|
||||
bootloader with the DTR + RTS + "1EAF" sequence (see
|
||||
leaflabs.com/docs/bootloader.html for more information on
|
||||
this).
|
||||
|
||||
After reset, Maple will run the DFU bootloader for a few seconds,
|
||||
during which the user can begin a DFU upload operation (uploads
|
||||
application binary into RAM/FLASH). Thus, without this virtual com
|
||||
port, it would be necessary to find an alternative means to reset
|
||||
the chip in order to enable the bootloader.
|
||||
|
||||
If you would like to develop your own USB application for whatever
|
||||
reason (e.g. to use faster isochronous enpoints for streaming
|
||||
audio, or implement the USB HID or Mass Storage specs), then
|
||||
ensure that you leave some hook for resetting Maple remotely in
|
||||
order to spin up the DFU bootloader. Please make sure to get
|
||||
yourself a unique vendor/product ID pair for your application, as
|
||||
some operating systems will assign a host-side driver based on
|
||||
these tags.
|
||||
|
||||
It would be possible to build a compound USB device, that
|
||||
implements endpoints for both the virtual COM port as well as some
|
||||
other components (mass storage etc.). However, this turns out to
|
||||
be a burden from the host driver side, as Windows and *nix handle
|
||||
compound USB devices quite differently.
|
||||
|
||||
Be mindful that enabling the USB peripheral isn't "free." The
|
||||
device must respond to periodic bus activity (every few
|
||||
milliseconds) by servicing an ISR. Therefore, the USB application
|
||||
should be disabled inside of timing critical applications.
|
||||
|
||||
In order to disconnect the device from the host, a USB_DISC pin is
|
||||
asserted (e.g. on Maple, this is PC12). Alternatively, the NVIC
|
||||
can be directly configured to disable the USB LP/HP IRQ's.
|
||||
|
||||
The files inside of usb_lib were provided by ST and are subject to
|
||||
their own license, all other files were written by the LeafLabs
|
||||
team and fall under the MIT license.
|
||||
|
||||
TODO:
|
||||
|
||||
- Generic USB driver core with series-provided backends, like
|
||||
libopencm3 has.
|
||||
- Strip out ST code.
|
||||
- Integration with a high level USB library (like LUFA/MyUSB) to
|
||||
allow users to write custom USB applications.
|
|
@ -0,0 +1,45 @@
|
|||
# Standard things
|
||||
sp := $(sp).x
|
||||
dirstack_$(sp) := $(d)
|
||||
d := $(dir)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)
|
||||
|
||||
# Local flags
|
||||
CFLAGS_$(d) = -I$(d) -I$(d)/$(MCU_SERIES) -I$(d)/usb_lib $(LIBMAPLE_INCLUDES) $(LIBMAPLE_PRIVATE_INCLUDES) -Wall
|
||||
|
||||
# Add usblib and series subdirectory to BUILDDIRS.
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/usb_lib
|
||||
|
||||
# Local rules and targets
|
||||
sSRCS_$(d) :=
|
||||
cSRCS_$(d) :=
|
||||
# We currently only have F1 performance line support. Sigh.
|
||||
ifeq ($(MCU_SERIES), stm32f1)
|
||||
ifeq ($(MCU_F1_LINE), performance)
|
||||
cSRCS_$(d) += $(MCU_SERIES)/usb.c
|
||||
cSRCS_$(d) += $(MCU_SERIES)/usb_reg_map.c
|
||||
cSRCS_$(d) += $(MCU_SERIES)/usb_cdcacm.c
|
||||
cSRCS_$(d) += usb_lib/usb_core.c
|
||||
cSRCS_$(d) += usb_lib/usb_init.c
|
||||
cSRCS_$(d) += usb_lib/usb_mem.c
|
||||
cSRCS_$(d) += usb_lib/usb_regs.c
|
||||
endif
|
||||
endif
|
||||
|
||||
sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
|
||||
cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
|
||||
|
||||
OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \
|
||||
$(cFILES_$(d):%.c=$(BUILD_PATH)/%.o)
|
||||
DEPS_$(d) := $(OBJS_$(d):%.o=%.d)
|
||||
|
||||
$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d))
|
||||
$(OBJS_$(d)): TGT_ASFLAGS :=
|
||||
|
||||
TGT_BIN += $(OBJS_$(d))
|
||||
|
||||
# Standard things
|
||||
-include $(DEPS_$(d))
|
||||
d := $(dirstack_$(sp))
|
||||
sp := $(basename $(sp))
|
|
@ -0,0 +1,387 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/usb/stm32f1/usb.c
|
||||
* @brief USB support.
|
||||
*
|
||||
* This is a mess.
|
||||
*/
|
||||
|
||||
#include <libmaple/usb.h>
|
||||
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/rcc.h>
|
||||
|
||||
/* Private headers */
|
||||
#include "usb_reg_map.h"
|
||||
#include "usb_lib_globals.h"
|
||||
|
||||
/* usb_lib headers */
|
||||
#include "usb_type.h"
|
||||
#include "usb_core.h"
|
||||
|
||||
static void dispatch_ctr_lp(void);
|
||||
|
||||
/*
|
||||
* usb_lib/ globals
|
||||
*/
|
||||
|
||||
uint16 SaveTState; /* caches TX status for later use */
|
||||
uint16 SaveRState; /* caches RX status for later use */
|
||||
|
||||
/*
|
||||
* Other state
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
RESUME_EXTERNAL,
|
||||
RESUME_INTERNAL,
|
||||
RESUME_LATER,
|
||||
RESUME_WAIT,
|
||||
RESUME_START,
|
||||
RESUME_ON,
|
||||
RESUME_OFF,
|
||||
RESUME_ESOF
|
||||
} RESUME_STATE;
|
||||
|
||||
struct {
|
||||
volatile RESUME_STATE eState;
|
||||
volatile uint8 bESOFcnt;
|
||||
} ResumeS;
|
||||
|
||||
static usblib_dev usblib = {
|
||||
.irq_mask = USB_ISR_MSK,
|
||||
.state = USB_UNCONNECTED,
|
||||
.prevState = USB_UNCONNECTED,
|
||||
.clk_id = RCC_USB,
|
||||
};
|
||||
usblib_dev *USBLIB = &usblib;
|
||||
|
||||
/*
|
||||
* Routines
|
||||
*/
|
||||
|
||||
void usb_init_usblib(usblib_dev *dev,
|
||||
void (**ep_int_in)(void),
|
||||
void (**ep_int_out)(void)) {
|
||||
rcc_clk_enable(dev->clk_id);
|
||||
|
||||
dev->ep_int_in = ep_int_in;
|
||||
dev->ep_int_out = ep_int_out;
|
||||
|
||||
/* usb_lib/ declares both and then assumes that pFoo points to Foo
|
||||
* (even though the names don't always match), which is stupid for
|
||||
* all of the obvious reasons, but whatever. Here we are. */
|
||||
pInformation = &Device_Info;
|
||||
pProperty = &Device_Property;
|
||||
pUser_Standard_Requests = &User_Standard_Requests;
|
||||
|
||||
pInformation->ControlState = 2; /* FIXME [0.0.12] use
|
||||
CONTROL_STATE enumerator */
|
||||
pProperty->Init();
|
||||
}
|
||||
|
||||
static void usb_suspend(void) {
|
||||
uint16 cntr;
|
||||
|
||||
/* TODO decide if read/modify/write is really what we want
|
||||
* (e.g. usb_resume_init() reconfigures CNTR). */
|
||||
cntr = USB_BASE->CNTR;
|
||||
cntr |= USB_CNTR_FSUSP;
|
||||
USB_BASE->CNTR = cntr;
|
||||
cntr |= USB_CNTR_LP_MODE;
|
||||
USB_BASE->CNTR = cntr;
|
||||
|
||||
USBLIB->prevState = USBLIB->state;
|
||||
USBLIB->state = USB_SUSPENDED;
|
||||
}
|
||||
|
||||
static void usb_resume_init(void) {
|
||||
uint16 cntr;
|
||||
|
||||
cntr = USB_BASE->CNTR;
|
||||
cntr &= ~USB_CNTR_LP_MODE;
|
||||
USB_BASE->CNTR = cntr;
|
||||
|
||||
/* Enable interrupt lines */
|
||||
USB_BASE->CNTR = USB_ISR_MSK;
|
||||
}
|
||||
|
||||
static void usb_resume(RESUME_STATE eResumeSetVal) {
|
||||
uint16 cntr;
|
||||
|
||||
if (eResumeSetVal != RESUME_ESOF) {
|
||||
ResumeS.eState = eResumeSetVal;
|
||||
}
|
||||
|
||||
switch (ResumeS.eState) {
|
||||
case RESUME_EXTERNAL:
|
||||
usb_resume_init();
|
||||
ResumeS.eState = RESUME_OFF;
|
||||
USBLIB->state = USBLIB->prevState;
|
||||
break;
|
||||
case RESUME_INTERNAL:
|
||||
usb_resume_init();
|
||||
ResumeS.eState = RESUME_START;
|
||||
break;
|
||||
case RESUME_LATER:
|
||||
ResumeS.bESOFcnt = 2;
|
||||
ResumeS.eState = RESUME_WAIT;
|
||||
break;
|
||||
case RESUME_WAIT:
|
||||
ResumeS.bESOFcnt--;
|
||||
if (ResumeS.bESOFcnt == 0) {
|
||||
ResumeS.eState = RESUME_START;
|
||||
}
|
||||
break;
|
||||
case RESUME_START:
|
||||
cntr = USB_BASE->CNTR;
|
||||
cntr |= USB_CNTR_RESUME;
|
||||
USB_BASE->CNTR = cntr;
|
||||
ResumeS.eState = RESUME_ON;
|
||||
ResumeS.bESOFcnt = 10;
|
||||
break;
|
||||
case RESUME_ON:
|
||||
ResumeS.bESOFcnt--;
|
||||
if (ResumeS.bESOFcnt == 0) {
|
||||
cntr = USB_BASE->CNTR;
|
||||
cntr &= ~USB_CNTR_RESUME;
|
||||
USB_BASE->CNTR = cntr;
|
||||
USBLIB->state = USBLIB->prevState;
|
||||
ResumeS.eState = RESUME_OFF;
|
||||
}
|
||||
break;
|
||||
case RESUME_OFF:
|
||||
case RESUME_ESOF:
|
||||
default:
|
||||
ResumeS.eState = RESUME_OFF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define SUSPEND_ENABLED 1
|
||||
void __irq_usb_lp_can_rx0(void) {
|
||||
uint16 istr = USB_BASE->ISTR;
|
||||
|
||||
/* Use USB_ISR_MSK to only include code for bits we care about. */
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_RESET)
|
||||
if (istr & USB_ISTR_RESET & USBLIB->irq_mask) {
|
||||
USB_BASE->ISTR = ~USB_ISTR_RESET;
|
||||
pProperty->Reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_PMAOVR)
|
||||
if (istr & ISTR_PMAOVR & USBLIB->irq_mask) {
|
||||
USB_BASE->ISTR = ~USB_ISTR_PMAOVR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_ERR)
|
||||
if (istr & USB_ISTR_ERR & USBLIB->irq_mask) {
|
||||
USB_BASE->ISTR = ~USB_ISTR_ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_WKUP)
|
||||
if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) {
|
||||
USB_BASE->ISTR = ~USB_ISTR_WKUP;
|
||||
usb_resume(RESUME_EXTERNAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_SUSP)
|
||||
if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) {
|
||||
/* check if SUSPEND is possible */
|
||||
if (SUSPEND_ENABLED) {
|
||||
usb_suspend();
|
||||
} else {
|
||||
/* if not possible then resume after xx ms */
|
||||
usb_resume(RESUME_LATER);
|
||||
}
|
||||
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
|
||||
USB_BASE->ISTR = ~USB_ISTR_SUSP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_SOF)
|
||||
if (istr & USB_ISTR_SOF & USBLIB->irq_mask) {
|
||||
USB_BASE->ISTR = ~USB_ISTR_SOF;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_ESOF)
|
||||
if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) {
|
||||
USB_BASE->ISTR = ~USB_ISTR_ESOF;
|
||||
/* resume handling timing is made with ESOFs */
|
||||
usb_resume(RESUME_ESOF); /* request without change of the machine state */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Service the correct transfer interrupt.
|
||||
*/
|
||||
|
||||
#if (USB_ISR_MSK & USB_ISTR_CTR)
|
||||
if (istr & USB_ISTR_CTR & USBLIB->irq_mask) {
|
||||
dispatch_ctr_lp();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Auxiliary routines
|
||||
*/
|
||||
|
||||
static inline uint8 dispatch_endpt_zero(uint16 istr_dir);
|
||||
static inline void dispatch_endpt(uint8 ep);
|
||||
static inline void set_rx_tx_status0(uint16 rx, uint16 tx);
|
||||
|
||||
static void handle_setup0(void);
|
||||
static void handle_in0(void);
|
||||
static void handle_out0(void);
|
||||
|
||||
static void dispatch_ctr_lp() {
|
||||
uint16 istr;
|
||||
while (((istr = USB_BASE->ISTR) & USB_ISTR_CTR) != 0) {
|
||||
/* TODO WTF, figure this out: RM0008 says CTR is read-only,
|
||||
* but ST's firmware claims it's clear-only, and emphasizes
|
||||
* the importance of clearing it in more than one place. */
|
||||
USB_BASE->ISTR = ~USB_ISTR_CTR;
|
||||
uint8 ep_id = istr & USB_ISTR_EP_ID;
|
||||
if (ep_id == 0) {
|
||||
/* TODO figure out why it's OK to break out of the loop
|
||||
* once we're done serving endpoint zero, but not okay if
|
||||
* there are multiple nonzero endpoint transfers to
|
||||
* handle. */
|
||||
if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
dispatch_endpt(ep_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME Dataflow on endpoint 0 RX/TX status is based off of ST's
|
||||
* code, and is ugly/confusing in its use of SaveRState/SaveTState.
|
||||
* Fixing this requires filling in handle_in0(), handle_setup0(),
|
||||
* handle_out0(). */
|
||||
static inline uint8 dispatch_endpt_zero(uint16 istr_dir) {
|
||||
uint32 epr = (uint16)USB_BASE->EP[0];
|
||||
|
||||
if (!(epr & (USB_EP_CTR_TX | USB_EP_SETUP | USB_EP_CTR_RX))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Cache RX/TX statuses in SaveRState/SaveTState, respectively.
|
||||
* The various handle_foo0() may clobber these values
|
||||
* before we reset them at the end of this routine. */
|
||||
SaveRState = epr & USB_EP_STAT_RX;
|
||||
SaveTState = epr & USB_EP_STAT_TX;
|
||||
|
||||
/* Set actual RX/TX statuses to NAK while we're thinking */
|
||||
set_rx_tx_status0(USB_EP_STAT_RX_NAK, USB_EP_STAT_TX_NAK);
|
||||
|
||||
if (istr_dir == 0) {
|
||||
/* ST RM0008: "If DIR bit=0, CTR_TX bit is set in the USB_EPnR
|
||||
* register related to the interrupting endpoint. The
|
||||
* interrupting transaction is of IN type (data transmitted by
|
||||
* the USB peripheral to the host PC)." */
|
||||
ASSERT_FAULT(epr & USB_EP_CTR_TX);
|
||||
usb_clear_ctr_tx(USB_EP0);
|
||||
handle_in0();
|
||||
} else {
|
||||
/* RM0008: "If DIR bit=1, CTR_RX bit or both CTR_TX/CTR_RX
|
||||
* are set in the USB_EPnR register related to the
|
||||
* interrupting endpoint. The interrupting transaction is of
|
||||
* OUT type (data received by the USB peripheral from the host
|
||||
* PC) or two pending transactions are waiting to be
|
||||
* processed."
|
||||
*
|
||||
* [mbolivar] Note how the following control flow (which
|
||||
* replicates ST's) doesn't seem to actually handle both
|
||||
* interrupts that are ostensibly pending when both CTR_RX and
|
||||
* CTR_TX are set.
|
||||
*
|
||||
* TODO sort this mess out.
|
||||
*/
|
||||
if (epr & USB_EP_CTR_TX) {
|
||||
usb_clear_ctr_tx(USB_EP0);
|
||||
handle_in0();
|
||||
} else { /* SETUP or CTR_RX */
|
||||
/* SETUP is held constant while CTR_RX is set, so clear it
|
||||
* either way */
|
||||
usb_clear_ctr_rx(USB_EP0);
|
||||
if (epr & USB_EP_SETUP) {
|
||||
handle_setup0();
|
||||
} else { /* CTR_RX */
|
||||
handle_out0();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_rx_tx_status0(SaveRState, SaveTState);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void dispatch_endpt(uint8 ep) {
|
||||
uint32 epr = USB_BASE->EP[ep];
|
||||
/* If ISTR_CTR is set and the ISTR gave us this EP_ID to handle,
|
||||
* then presumably at least one of CTR_RX and CTR_TX is set, but
|
||||
* again, ST's control flow allows for the possibility of neither.
|
||||
*
|
||||
* TODO try to find out if neither being set is possible. */
|
||||
if (epr & USB_EP_CTR_RX) {
|
||||
usb_clear_ctr_rx(ep);
|
||||
(USBLIB->ep_int_out[ep - 1])();
|
||||
}
|
||||
if (epr & USB_EP_CTR_TX) {
|
||||
usb_clear_ctr_tx(ep);
|
||||
(USBLIB->ep_int_in[ep - 1])();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void set_rx_tx_status0(uint16 rx, uint16 tx) {
|
||||
usb_set_ep_rx_stat(USB_EP0, rx);
|
||||
usb_set_ep_tx_stat(USB_EP0, tx);
|
||||
}
|
||||
|
||||
/* TODO Rip out usb_lib/ dependency from the following functions: */
|
||||
|
||||
static void handle_setup0(void) {
|
||||
Setup0_Process();
|
||||
}
|
||||
|
||||
static void handle_in0(void) {
|
||||
In0_Process();
|
||||
}
|
||||
|
||||
static void handle_out0(void) {
|
||||
Out0_Process();
|
||||
}
|
|
@ -0,0 +1,751 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/usb/stm32f1/usb_cdcacm.c
|
||||
* @brief USB CDC ACM (a.k.a. virtual serial terminal, VCOM).
|
||||
*
|
||||
* FIXME: this works on the STM32F1 USB peripherals, and probably no
|
||||
* place else. Nonportable bits really need to be factored out, and
|
||||
* the result made cleaner.
|
||||
*/
|
||||
|
||||
#include <libmaple/usb_cdcacm.h>
|
||||
|
||||
#include <libmaple/usb.h>
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/delay.h>
|
||||
|
||||
/* Private headers */
|
||||
#include "usb_lib_globals.h"
|
||||
#include "usb_reg_map.h"
|
||||
|
||||
/* usb_lib headers */
|
||||
#include "usb_type.h"
|
||||
#include "usb_core.h"
|
||||
#include "usb_def.h"
|
||||
|
||||
/******************************************************************************
|
||||
******************************************************************************
|
||||
***
|
||||
*** HACK ALERT! FIXME FIXME FIXME FIXME!
|
||||
***
|
||||
*** A bunch of LeafLabs-specific configuration lives in here for
|
||||
*** now. This mess REALLY needs to get teased apart, with
|
||||
*** appropriate pieces moved into Wirish.
|
||||
***
|
||||
******************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
#if !(defined(BOARD_maple) || defined(BOARD_maple_RET6) || \
|
||||
defined(BOARD_maple_mini) || defined(BOARD_maple_native))
|
||||
#warning USB CDC ACM relies on LeafLabs board-specific configuration.\
|
||||
You may have problems on non-LeafLabs boards.
|
||||
#endif
|
||||
|
||||
static void vcomDataTxCb(void);
|
||||
static void vcomDataRxCb(void);
|
||||
static uint8* vcomGetSetLineCoding(uint16);
|
||||
|
||||
static void usbInit(void);
|
||||
static void usbReset(void);
|
||||
static RESULT usbDataSetup(uint8 request);
|
||||
static RESULT usbNoDataSetup(uint8 request);
|
||||
static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting);
|
||||
static uint8* usbGetDeviceDescriptor(uint16 length);
|
||||
static uint8* usbGetConfigDescriptor(uint16 length);
|
||||
static uint8* usbGetStringDescriptor(uint16 length);
|
||||
static void usbSetConfiguration(void);
|
||||
static void usbSetDeviceAddress(void);
|
||||
|
||||
/*
|
||||
* Descriptors
|
||||
*/
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
#define LEAFLABS_ID_VENDOR 0x1EAF
|
||||
#define MAPLE_ID_PRODUCT 0x0004
|
||||
static const usb_descriptor_device usbVcomDescriptor_Device =
|
||||
USB_CDCACM_DECLARE_DEV_DESC(LEAFLABS_ID_VENDOR, MAPLE_ID_PRODUCT);
|
||||
|
||||
typedef struct {
|
||||
usb_descriptor_config_header Config_Header;
|
||||
usb_descriptor_interface CCI_Interface;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_ACM;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union;
|
||||
usb_descriptor_endpoint ManagementEndpoint;
|
||||
usb_descriptor_interface DCI_Interface;
|
||||
usb_descriptor_endpoint DataOutEndpoint;
|
||||
usb_descriptor_endpoint DataInEndpoint;
|
||||
} __packed usb_descriptor_config;
|
||||
|
||||
#define MAX_POWER (100 >> 1)
|
||||
static const usb_descriptor_config usbVcomDescriptor_Config = {
|
||||
.Config_Header = {
|
||||
.bLength = sizeof(usb_descriptor_config_header),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_CONFIGURATION,
|
||||
.wTotalLength = sizeof(usb_descriptor_config),
|
||||
.bNumInterfaces = 0x02,
|
||||
.bConfigurationValue = 0x01,
|
||||
.iConfiguration = 0x00,
|
||||
.bmAttributes = (USB_CONFIG_ATTR_BUSPOWERED |
|
||||
USB_CONFIG_ATTR_SELF_POWERED),
|
||||
.bMaxPower = MAX_POWER,
|
||||
},
|
||||
|
||||
.CCI_Interface = {
|
||||
.bLength = sizeof(usb_descriptor_interface),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
|
||||
.bInterfaceNumber = 0x00,
|
||||
.bAlternateSetting = 0x00,
|
||||
.bNumEndpoints = 0x01,
|
||||
.bInterfaceClass = USB_INTERFACE_CLASS_CDC,
|
||||
.bInterfaceSubClass = USB_INTERFACE_SUBCLASS_CDC_ACM,
|
||||
.bInterfaceProtocol = 0x01, /* Common AT Commands */
|
||||
.iInterface = 0x00,
|
||||
},
|
||||
|
||||
.CDC_Functional_IntHeader = {
|
||||
.bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2),
|
||||
.bDescriptorType = 0x24,
|
||||
.SubType = 0x00,
|
||||
.Data = {0x01, 0x10},
|
||||
},
|
||||
|
||||
.CDC_Functional_CallManagement = {
|
||||
.bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2),
|
||||
.bDescriptorType = 0x24,
|
||||
.SubType = 0x01,
|
||||
.Data = {0x03, 0x01},
|
||||
},
|
||||
|
||||
.CDC_Functional_ACM = {
|
||||
.bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(1),
|
||||
.bDescriptorType = 0x24,
|
||||
.SubType = 0x02,
|
||||
.Data = {0x06},
|
||||
},
|
||||
|
||||
.CDC_Functional_Union = {
|
||||
.bLength = CDC_FUNCTIONAL_DESCRIPTOR_SIZE(2),
|
||||
.bDescriptorType = 0x24,
|
||||
.SubType = 0x06,
|
||||
.Data = {0x00, 0x01},
|
||||
},
|
||||
|
||||
.ManagementEndpoint = {
|
||||
.bLength = sizeof(usb_descriptor_endpoint),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN |
|
||||
USB_CDCACM_MANAGEMENT_ENDP),
|
||||
.bmAttributes = USB_EP_TYPE_INTERRUPT,
|
||||
.wMaxPacketSize = USB_CDCACM_MANAGEMENT_EPSIZE,
|
||||
.bInterval = 0xFF,
|
||||
},
|
||||
|
||||
.DCI_Interface = {
|
||||
.bLength = sizeof(usb_descriptor_interface),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_INTERFACE,
|
||||
.bInterfaceNumber = 0x01,
|
||||
.bAlternateSetting = 0x00,
|
||||
.bNumEndpoints = 0x02,
|
||||
.bInterfaceClass = USB_INTERFACE_CLASS_DIC,
|
||||
.bInterfaceSubClass = 0x00, /* None */
|
||||
.bInterfaceProtocol = 0x00, /* None */
|
||||
.iInterface = 0x00,
|
||||
},
|
||||
|
||||
.DataOutEndpoint = {
|
||||
.bLength = sizeof(usb_descriptor_endpoint),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_OUT |
|
||||
USB_CDCACM_RX_ENDP),
|
||||
.bmAttributes = USB_EP_TYPE_BULK,
|
||||
.wMaxPacketSize = USB_CDCACM_RX_EPSIZE,
|
||||
.bInterval = 0x00,
|
||||
},
|
||||
|
||||
.DataInEndpoint = {
|
||||
.bLength = sizeof(usb_descriptor_endpoint),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT,
|
||||
.bEndpointAddress = (USB_DESCRIPTOR_ENDPOINT_IN | USB_CDCACM_TX_ENDP),
|
||||
.bmAttributes = USB_EP_TYPE_BULK,
|
||||
.wMaxPacketSize = USB_CDCACM_TX_EPSIZE,
|
||||
.bInterval = 0x00,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
String Descriptors:
|
||||
|
||||
we may choose to specify any or none of the following string
|
||||
identifiers:
|
||||
|
||||
iManufacturer: LeafLabs
|
||||
iProduct: Maple
|
||||
iSerialNumber: NONE
|
||||
iConfiguration: NONE
|
||||
iInterface(CCI): NONE
|
||||
iInterface(DCI): NONE
|
||||
|
||||
*/
|
||||
|
||||
/* Unicode language identifier: 0x0409 is US English */
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbVcomDescriptor_LangID = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(1),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {0x09, 0x04},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbVcomDescriptor_iManufacturer = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(8),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'L', 0, 'e', 0, 'a', 0, 'f', 0,
|
||||
'L', 0, 'a', 0, 'b', 0, 's', 0},
|
||||
};
|
||||
|
||||
/* FIXME move to Wirish */
|
||||
static const usb_descriptor_string usbVcomDescriptor_iProduct = {
|
||||
.bLength = USB_DESCRIPTOR_STRING_LEN(5),
|
||||
.bDescriptorType = USB_DESCRIPTOR_TYPE_STRING,
|
||||
.bString = {'M', 0, 'a', 0, 'p', 0, 'l', 0, 'e', 0},
|
||||
};
|
||||
|
||||
static ONE_DESCRIPTOR Device_Descriptor = {
|
||||
(uint8*)&usbVcomDescriptor_Device,
|
||||
sizeof(usb_descriptor_device)
|
||||
};
|
||||
|
||||
static ONE_DESCRIPTOR Config_Descriptor = {
|
||||
(uint8*)&usbVcomDescriptor_Config,
|
||||
sizeof(usb_descriptor_config)
|
||||
};
|
||||
|
||||
#define N_STRING_DESCRIPTORS 3
|
||||
static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = {
|
||||
{(uint8*)&usbVcomDescriptor_LangID, USB_DESCRIPTOR_STRING_LEN(1)},
|
||||
{(uint8*)&usbVcomDescriptor_iManufacturer,USB_DESCRIPTOR_STRING_LEN(8)},
|
||||
{(uint8*)&usbVcomDescriptor_iProduct, USB_DESCRIPTOR_STRING_LEN(5)}
|
||||
};
|
||||
|
||||
/*
|
||||
* Etc.
|
||||
*/
|
||||
|
||||
/* I/O state */
|
||||
|
||||
#define CDC_SERIAL_BUFFER_SIZE 512
|
||||
|
||||
/* Received data */
|
||||
static volatile uint8 vcomBufferRx[CDC_SERIAL_BUFFER_SIZE];
|
||||
/* Read index into vcomBufferRx */
|
||||
static volatile uint32 rx_offset = 0;
|
||||
/* Number of bytes left to transmit */
|
||||
static volatile uint32 n_unsent_bytes = 0;
|
||||
/* Are we currently sending an IN packet? */
|
||||
static volatile uint8 transmitting = 0;
|
||||
/* Number of unread bytes */
|
||||
static volatile uint32 n_unread_bytes = 0;
|
||||
|
||||
/* Other state (line coding, DTR/RTS) */
|
||||
|
||||
static volatile usb_cdcacm_line_coding line_coding = {
|
||||
/* This default is 115200 baud, 8N1. */
|
||||
.dwDTERate = 115200,
|
||||
.bCharFormat = USB_CDCACM_STOP_BITS_1,
|
||||
.bParityType = USB_CDCACM_PARITY_NONE,
|
||||
.bDataBits = 8,
|
||||
};
|
||||
|
||||
/* DTR in bit 0, RTS in bit 1. */
|
||||
static volatile uint8 line_dtr_rts = 0;
|
||||
|
||||
/*
|
||||
* Endpoint callbacks
|
||||
*/
|
||||
|
||||
static void (*ep_int_in[7])(void) =
|
||||
{vcomDataTxCb,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process};
|
||||
|
||||
static void (*ep_int_out[7])(void) =
|
||||
{NOP_Process,
|
||||
NOP_Process,
|
||||
vcomDataRxCb,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process,
|
||||
NOP_Process};
|
||||
|
||||
/*
|
||||
* Globals required by usb_lib/
|
||||
*
|
||||
* Mark these weak so they can be overriden to implement other USB
|
||||
* functionality.
|
||||
*/
|
||||
|
||||
#define NUM_ENDPTS 0x04
|
||||
__weak DEVICE Device_Table = {
|
||||
.Total_Endpoint = NUM_ENDPTS,
|
||||
.Total_Configuration = 1
|
||||
};
|
||||
|
||||
#define MAX_PACKET_SIZE 0x40 /* 64B, maximum for USB FS Devices */
|
||||
__weak DEVICE_PROP Device_Property = {
|
||||
.Init = usbInit,
|
||||
.Reset = usbReset,
|
||||
.Process_Status_IN = NOP_Process,
|
||||
.Process_Status_OUT = NOP_Process,
|
||||
.Class_Data_Setup = usbDataSetup,
|
||||
.Class_NoData_Setup = usbNoDataSetup,
|
||||
.Class_Get_Interface_Setting = usbGetInterfaceSetting,
|
||||
.GetDeviceDescriptor = usbGetDeviceDescriptor,
|
||||
.GetConfigDescriptor = usbGetConfigDescriptor,
|
||||
.GetStringDescriptor = usbGetStringDescriptor,
|
||||
.RxEP_buffer = NULL,
|
||||
.MaxPacketSize = MAX_PACKET_SIZE
|
||||
};
|
||||
|
||||
__weak USER_STANDARD_REQUESTS User_Standard_Requests = {
|
||||
.User_GetConfiguration = NOP_Process,
|
||||
.User_SetConfiguration = usbSetConfiguration,
|
||||
.User_GetInterface = NOP_Process,
|
||||
.User_SetInterface = NOP_Process,
|
||||
.User_GetStatus = NOP_Process,
|
||||
.User_ClearFeature = NOP_Process,
|
||||
.User_SetEndPointFeature = NOP_Process,
|
||||
.User_SetDeviceFeature = NOP_Process,
|
||||
.User_SetDeviceAddress = usbSetDeviceAddress
|
||||
};
|
||||
|
||||
/*
|
||||
* User hooks
|
||||
*/
|
||||
|
||||
static void (*rx_hook)(unsigned, void*) = 0;
|
||||
static void (*iface_setup_hook)(unsigned, void*) = 0;
|
||||
|
||||
void usb_cdcacm_set_hooks(unsigned hook_flags, void (*hook)(unsigned, void*)) {
|
||||
if (hook_flags & USB_CDCACM_HOOK_RX) {
|
||||
rx_hook = hook;
|
||||
}
|
||||
if (hook_flags & USB_CDCACM_HOOK_IFACE_SETUP) {
|
||||
iface_setup_hook = hook;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CDC ACM interface
|
||||
*/
|
||||
|
||||
void usb_cdcacm_enable(gpio_dev *disc_dev, uint8 disc_bit) {
|
||||
/* Present ourselves to the host. Writing 0 to "disc" pin must
|
||||
* pull USB_DP pin up while leaving USB_DM pulled down by the
|
||||
* transceiver. See USB 2.0 spec, section 7.1.7.3. */
|
||||
gpio_set_mode(disc_dev, disc_bit, GPIO_OUTPUT_PP);
|
||||
gpio_write_bit(disc_dev, disc_bit, 0);
|
||||
|
||||
/* Initialize the USB peripheral. */
|
||||
usb_init_usblib(USBLIB, ep_int_in, ep_int_out);
|
||||
}
|
||||
|
||||
void usb_cdcacm_disable(gpio_dev *disc_dev, uint8 disc_bit) {
|
||||
/* Turn off the interrupt and signal disconnect (see e.g. USB 2.0
|
||||
* spec, section 7.1.7.3). */
|
||||
nvic_irq_disable(NVIC_USB_LP_CAN_RX0);
|
||||
gpio_write_bit(disc_dev, disc_bit, 1);
|
||||
}
|
||||
|
||||
void usb_cdcacm_putc(char ch) {
|
||||
while (!usb_cdcacm_tx((uint8*)&ch, 1))
|
||||
;
|
||||
}
|
||||
|
||||
/* This function is non-blocking.
|
||||
*
|
||||
* It copies data from a usercode buffer into the USB peripheral TX
|
||||
* buffer, and returns the number of bytes copied. */
|
||||
uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) {
|
||||
/* Last transmission hasn't finished, so abort. */
|
||||
if (usb_cdcacm_is_transmitting()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We can only put USB_CDCACM_TX_EPSIZE bytes in the buffer. */
|
||||
if (len > USB_CDCACM_TX_EPSIZE) {
|
||||
len = USB_CDCACM_TX_EPSIZE;
|
||||
}
|
||||
|
||||
/* Queue bytes for sending. */
|
||||
if (len) {
|
||||
usb_copy_to_pma(buf, len, USB_CDCACM_TX_ADDR);
|
||||
}
|
||||
// We still need to wait for the interrupt, even if we're sending
|
||||
// zero bytes. (Sending zero-size packets is useful for flushing
|
||||
// host-side buffers.)
|
||||
usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, len);
|
||||
n_unsent_bytes = len;
|
||||
transmitting = 1;
|
||||
usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint32 usb_cdcacm_data_available(void) {
|
||||
return n_unread_bytes;
|
||||
}
|
||||
|
||||
uint8 usb_cdcacm_is_transmitting(void) {
|
||||
return transmitting;
|
||||
}
|
||||
|
||||
uint16 usb_cdcacm_get_pending(void) {
|
||||
return n_unsent_bytes;
|
||||
}
|
||||
|
||||
/* Nonblocking byte receive.
|
||||
*
|
||||
* Copies up to len bytes from our private data buffer (*NOT* the PMA)
|
||||
* into buf and deq's the FIFO. */
|
||||
uint32 usb_cdcacm_rx(uint8* buf, uint32 len) {
|
||||
/* Copy bytes to buffer. */
|
||||
uint32 n_copied = usb_cdcacm_peek(buf, len);
|
||||
|
||||
/* Mark bytes as read. */
|
||||
n_unread_bytes -= n_copied;
|
||||
rx_offset = (rx_offset + n_copied) % CDC_SERIAL_BUFFER_SIZE;
|
||||
|
||||
/* If all bytes have been read, re-enable the RX endpoint, which
|
||||
* was set to NAK when the current batch of bytes was received. */
|
||||
if (n_unread_bytes <= (CDC_SERIAL_BUFFER_SIZE - USB_CDCACM_RX_EPSIZE)) {
|
||||
usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
}
|
||||
|
||||
return n_copied;
|
||||
}
|
||||
|
||||
/* Nonblocking byte lookahead.
|
||||
*
|
||||
* Looks at unread bytes without marking them as read. */
|
||||
uint32 usb_cdcacm_peek(uint8* buf, uint32 len) {
|
||||
int i;
|
||||
uint32 head = rx_offset;
|
||||
|
||||
if (len > n_unread_bytes) {
|
||||
len = n_unread_bytes;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = vcomBufferRx[head];
|
||||
head = (head + 1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32 usb_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len) {
|
||||
int i;
|
||||
uint32 head = (rx_offset + offset) % CDC_SERIAL_BUFFER_SIZE;
|
||||
|
||||
if (len + offset > n_unread_bytes) {
|
||||
len = n_unread_bytes - offset;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = vcomBufferRx[head];
|
||||
head = (head + 1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Roger Clark. Added. for Arduino 1.0 API support of Serial.peek() */
|
||||
int usb_cdcacm_peek_char()
|
||||
{
|
||||
if (n_unread_bytes == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return vcomBufferRx[rx_offset];
|
||||
}
|
||||
|
||||
uint8 usb_cdcacm_get_dtr() {
|
||||
return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_DTR) != 0);
|
||||
}
|
||||
|
||||
uint8 usb_cdcacm_get_rts() {
|
||||
return ((line_dtr_rts & USB_CDCACM_CONTROL_LINE_RTS) != 0);
|
||||
}
|
||||
|
||||
void usb_cdcacm_get_line_coding(usb_cdcacm_line_coding *ret) {
|
||||
ret->dwDTERate = line_coding.dwDTERate;
|
||||
ret->bCharFormat = line_coding.bCharFormat;
|
||||
ret->bParityType = line_coding.bParityType;
|
||||
ret->bDataBits = line_coding.bDataBits;
|
||||
}
|
||||
|
||||
int usb_cdcacm_get_baud(void) {
|
||||
return line_coding.dwDTERate;
|
||||
}
|
||||
|
||||
int usb_cdcacm_get_stop_bits(void) {
|
||||
return line_coding.bCharFormat;
|
||||
}
|
||||
|
||||
int usb_cdcacm_get_parity(void) {
|
||||
return line_coding.bParityType;
|
||||
}
|
||||
|
||||
int usb_cdcacm_get_n_data_bits(void) {
|
||||
return line_coding.bDataBits;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Callbacks
|
||||
*/
|
||||
|
||||
static void vcomDataTxCb(void) {
|
||||
n_unsent_bytes = 0;
|
||||
transmitting = 0;
|
||||
}
|
||||
|
||||
static void vcomDataRxCb(void) {
|
||||
uint32 ep_rx_size;
|
||||
uint32 tail = (rx_offset + n_unread_bytes) % CDC_SERIAL_BUFFER_SIZE;
|
||||
uint8 ep_rx_data[USB_CDCACM_RX_EPSIZE];
|
||||
uint32 i;
|
||||
|
||||
usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_NAK);
|
||||
ep_rx_size = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP);
|
||||
/* This copy won't overwrite unread bytes, since we've set the RX
|
||||
* endpoint to NAK, and will only set it to VALID when all bytes
|
||||
* have been read. */
|
||||
usb_copy_from_pma((uint8*)ep_rx_data, ep_rx_size,
|
||||
USB_CDCACM_RX_ADDR);
|
||||
|
||||
for (i = 0; i < ep_rx_size; i++) {
|
||||
vcomBufferRx[tail] = ep_rx_data[i];
|
||||
tail = (tail + 1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
n_unread_bytes += ep_rx_size;
|
||||
|
||||
if (n_unread_bytes <= (CDC_SERIAL_BUFFER_SIZE - USB_CDCACM_RX_EPSIZE)) {
|
||||
usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
}
|
||||
|
||||
if (rx_hook) {
|
||||
rx_hook(USB_CDCACM_HOOK_RX, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8* vcomGetSetLineCoding(uint16 length) {
|
||||
if (length == 0) {
|
||||
pInformation->Ctrl_Info.Usb_wLength = sizeof(struct usb_cdcacm_line_coding);
|
||||
}
|
||||
return (uint8*)&line_coding;
|
||||
}
|
||||
|
||||
static void usbInit(void) {
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
USB_BASE->CNTR = USB_CNTR_FRES;
|
||||
|
||||
USBLIB->irq_mask = 0;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
USB_BASE->ISTR = 0;
|
||||
USBLIB->irq_mask = USB_CNTR_RESETM | USB_CNTR_SUSPM | USB_CNTR_WKUPM;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
|
||||
USB_BASE->ISTR = 0;
|
||||
USBLIB->irq_mask = USB_ISR_MSK;
|
||||
USB_BASE->CNTR = USBLIB->irq_mask;
|
||||
|
||||
nvic_irq_enable(NVIC_USB_LP_CAN_RX0);
|
||||
USBLIB->state = USB_UNCONNECTED;
|
||||
}
|
||||
|
||||
#define BTABLE_ADDRESS 0x00
|
||||
static void usbReset(void) {
|
||||
pInformation->Current_Configuration = 0;
|
||||
|
||||
/* current feature is current bmAttributes */
|
||||
pInformation->Current_Feature = (USB_CONFIG_ATTR_BUSPOWERED |
|
||||
USB_CONFIG_ATTR_SELF_POWERED);
|
||||
|
||||
USB_BASE->BTABLE = BTABLE_ADDRESS;
|
||||
|
||||
/* setup control endpoint 0 */
|
||||
usb_set_ep_type(USB_EP0, USB_EP_EP_TYPE_CONTROL);
|
||||
usb_set_ep_tx_stat(USB_EP0, USB_EP_STAT_TX_STALL);
|
||||
usb_set_ep_rx_addr(USB_EP0, USB_CDCACM_CTRL_RX_ADDR);
|
||||
usb_set_ep_tx_addr(USB_EP0, USB_CDCACM_CTRL_TX_ADDR);
|
||||
usb_clear_status_out(USB_EP0);
|
||||
|
||||
usb_set_ep_rx_count(USB_EP0, pProperty->MaxPacketSize);
|
||||
usb_set_ep_rx_stat(USB_EP0, USB_EP_STAT_RX_VALID);
|
||||
|
||||
/* setup management endpoint 1 */
|
||||
usb_set_ep_type(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_EP_TYPE_INTERRUPT);
|
||||
usb_set_ep_tx_addr(USB_CDCACM_MANAGEMENT_ENDP,
|
||||
USB_CDCACM_MANAGEMENT_ADDR);
|
||||
usb_set_ep_tx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_TX_NAK);
|
||||
usb_set_ep_rx_stat(USB_CDCACM_MANAGEMENT_ENDP, USB_EP_STAT_RX_DISABLED);
|
||||
|
||||
/* TODO figure out differences in style between RX/TX EP setup */
|
||||
|
||||
/* set up data endpoint OUT (RX) */
|
||||
usb_set_ep_type(USB_CDCACM_RX_ENDP, USB_EP_EP_TYPE_BULK);
|
||||
usb_set_ep_rx_addr(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_ADDR);
|
||||
usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE);
|
||||
usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
|
||||
/* set up data endpoint IN (TX) */
|
||||
usb_set_ep_type(USB_CDCACM_TX_ENDP, USB_EP_EP_TYPE_BULK);
|
||||
usb_set_ep_tx_addr(USB_CDCACM_TX_ENDP, USB_CDCACM_TX_ADDR);
|
||||
usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_NAK);
|
||||
usb_set_ep_rx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_RX_DISABLED);
|
||||
|
||||
USBLIB->state = USB_ATTACHED;
|
||||
SetDeviceAddress(0);
|
||||
|
||||
/* Reset the RX/TX state */
|
||||
n_unread_bytes = 0;
|
||||
n_unsent_bytes = 0;
|
||||
rx_offset = 0;
|
||||
transmitting = 0;
|
||||
}
|
||||
|
||||
static RESULT usbDataSetup(uint8 request) {
|
||||
uint8* (*CopyRoutine)(uint16) = 0;
|
||||
|
||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
|
||||
switch (request) {
|
||||
case USB_CDCACM_GET_LINE_CODING:
|
||||
CopyRoutine = vcomGetSetLineCoding;
|
||||
break;
|
||||
case USB_CDCACM_SET_LINE_CODING:
|
||||
CopyRoutine = vcomGetSetLineCoding;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call the user hook. */
|
||||
if (iface_setup_hook) {
|
||||
uint8 req_copy = request;
|
||||
iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy);
|
||||
}
|
||||
}
|
||||
|
||||
if (CopyRoutine == NULL) {
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
pInformation->Ctrl_Info.CopyData = CopyRoutine;
|
||||
pInformation->Ctrl_Info.Usb_wOffset = 0;
|
||||
(*CopyRoutine)(0);
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
static RESULT usbNoDataSetup(uint8 request) {
|
||||
RESULT ret = USB_UNSUPPORT;
|
||||
|
||||
if (Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) {
|
||||
switch (request) {
|
||||
case USB_CDCACM_SET_COMM_FEATURE:
|
||||
/* We support set comm. feature, but don't handle it. */
|
||||
ret = USB_SUCCESS;
|
||||
break;
|
||||
case USB_CDCACM_SET_CONTROL_LINE_STATE:
|
||||
/* Track changes to DTR and RTS. */
|
||||
line_dtr_rts = (pInformation->USBwValues.bw.bb0 &
|
||||
(USB_CDCACM_CONTROL_LINE_DTR |
|
||||
USB_CDCACM_CONTROL_LINE_RTS));
|
||||
ret = USB_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Call the user hook. */
|
||||
if (iface_setup_hook) {
|
||||
uint8 req_copy = request;
|
||||
iface_setup_hook(USB_CDCACM_HOOK_IFACE_SETUP, &req_copy);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static RESULT usbGetInterfaceSetting(uint8 interface, uint8 alt_setting) {
|
||||
if (alt_setting > 0) {
|
||||
return USB_UNSUPPORT;
|
||||
} else if (interface > 1) {
|
||||
return USB_UNSUPPORT;
|
||||
}
|
||||
|
||||
return USB_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8* usbGetDeviceDescriptor(uint16 length) {
|
||||
return Standard_GetDescriptorData(length, &Device_Descriptor);
|
||||
}
|
||||
|
||||
static uint8* usbGetConfigDescriptor(uint16 length) {
|
||||
return Standard_GetDescriptorData(length, &Config_Descriptor);
|
||||
}
|
||||
|
||||
static uint8* usbGetStringDescriptor(uint16 length) {
|
||||
uint8 wValue0 = pInformation->USBwValue0;
|
||||
|
||||
if (wValue0 > N_STRING_DESCRIPTORS) {
|
||||
return NULL;
|
||||
}
|
||||
return Standard_GetDescriptorData(length, &String_Descriptor[wValue0]);
|
||||
}
|
||||
|
||||
static void usbSetConfiguration(void) {
|
||||
if (pInformation->Current_Configuration != 0) {
|
||||
USBLIB->state = USB_CONFIGURED;
|
||||
}
|
||||
}
|
||||
|
||||
static void usbSetDeviceAddress(void) {
|
||||
USBLIB->state = USB_ADDRESSED;
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "usb_reg_map.h"
|
||||
|
||||
/* TODO these could use some improvement; they're fairly
|
||||
* straightforward ports of the analogous ST code. The PMA blit
|
||||
* routines in particular are obvious targets for performance
|
||||
* measurement and tuning. */
|
||||
|
||||
void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) {
|
||||
uint16 *dst = (uint16*)usb_pma_ptr(pma_offset);
|
||||
uint16 n = len >> 1;
|
||||
uint16 i;
|
||||
for (i = 0; i < n; i++) {
|
||||
*dst = (uint16)(*buf) | *(buf + 1) << 8;
|
||||
buf += 2;
|
||||
dst += 2;
|
||||
}
|
||||
if (len & 1) {
|
||||
*dst = *buf;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) {
|
||||
uint32 *src = (uint32*)usb_pma_ptr(pma_offset);
|
||||
uint16 *dst = (uint16*)buf;
|
||||
uint16 n = len >> 1;
|
||||
uint16 i;
|
||||
for (i = 0; i < n; i++) {
|
||||
*dst++ = *src++;
|
||||
}
|
||||
if (len & 1) {
|
||||
*dst = *src & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) {
|
||||
uint16 nblocks;
|
||||
if (count > 62) {
|
||||
/* use 32-byte memory block size */
|
||||
nblocks = count >> 5;
|
||||
if ((count & 0x1F) == 0) {
|
||||
nblocks--;
|
||||
}
|
||||
*rxc = (nblocks << 10) | 0x8000;
|
||||
} else {
|
||||
/* use 2-byte memory block size */
|
||||
nblocks = count >> 1;
|
||||
if ((count & 0x1) != 0) {
|
||||
nblocks++;
|
||||
}
|
||||
*rxc = nblocks << 10;
|
||||
}
|
||||
}
|
||||
|
||||
void usb_set_ep_rx_buf0_count(uint8 ep, uint16 count) {
|
||||
uint32 *rxc = usb_ep_rx_buf0_count_ptr(ep);
|
||||
usb_set_ep_rx_count_common(rxc, count);
|
||||
}
|
||||
|
||||
void usb_set_ep_rx_count(uint8 ep, uint16 count) {
|
||||
uint32 *rxc = usb_ep_rx_count_ptr(ep);
|
||||
usb_set_ep_rx_count_common(rxc, count);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,64 @@
|
|||
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
|
||||
* File Name : usb_init.c
|
||||
* Author : MCD Application Team
|
||||
* Version : V2.2.1
|
||||
* Date : 09/22/2008
|
||||
* Description : Initialization routines & global variables
|
||||
********************************************************************************
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
|
||||
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
|
||||
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
|
||||
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*******************************************************************************/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* The number of current endpoint, it will be used to specify an endpoint */
|
||||
u8 EPindex;
|
||||
/* The number of current device, it is an index to the Device_Table */
|
||||
/* u8 Device_no; */
|
||||
/* Points to the DEVICE_INFO structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
DEVICE_INFO *pInformation;
|
||||
/* Points to the DEVICE_PROP structure of current device */
|
||||
/* The purpose of this register is to speed up the execution */
|
||||
DEVICE_PROP *pProperty;
|
||||
/* Temporary save the state of Rx & Tx status. */
|
||||
/* Whenever the Rx or Tx state is changed, its value is saved */
|
||||
/* in this variable first and will be set to the EPRB or EPRA */
|
||||
/* at the end of interrupt process */
|
||||
u16 SaveState ;
|
||||
u16 wInterrupt_Mask;
|
||||
DEVICE_INFO Device_Info;
|
||||
USER_STANDARD_REQUESTS *pUser_Standard_Requests;
|
||||
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : USB_Init
|
||||
* Description : USB system initialization
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void USB_Init(void)
|
||||
{
|
||||
pInformation = &Device_Info;
|
||||
pInformation->ControlState = 2;
|
||||
pProperty = &Device_Property;
|
||||
pUser_Standard_Requests = &User_Standard_Requests;
|
||||
/* Initialize devices one by one */
|
||||
|
||||
pProperty->Init();
|
||||
}
|
||||
|
||||
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,73 @@
|
|||
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
|
||||
* File Name : usb_mem.c
|
||||
* Author : MCD Application Team
|
||||
* Version : V2.2.1
|
||||
* Date : 09/22/2008
|
||||
* Description : Utility functions for memory transfers to/from PMA
|
||||
********************************************************************************
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
|
||||
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
|
||||
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
|
||||
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*******************************************************************************/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/*******************************************************************************
|
||||
* Function Name : UserToPMABufferCopy
|
||||
* Description : Copy a buffer from user memory area to packet memory area (PMA)
|
||||
* Input : - pbUsrBuf: pointer to user memory area.
|
||||
* - wPMABufAddr: address into PMA.
|
||||
* - wNBytes: no. of bytes to be copied.
|
||||
* Output : None.
|
||||
* Return : None .
|
||||
*******************************************************************************/
|
||||
void UserToPMABufferCopy(const u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes)
|
||||
{
|
||||
u32 n = (wNBytes + 1) >> 1; /* n = (wNBytes + 1) / 2 */
|
||||
u32 i, temp1, temp2;
|
||||
u16 *pdwVal;
|
||||
pdwVal = (u16 *)(wPMABufAddr * 2 + PMAAddr);
|
||||
for (i = n; i != 0; i--)
|
||||
{
|
||||
temp1 = (u16) * pbUsrBuf;
|
||||
pbUsrBuf++;
|
||||
temp2 = temp1 | (u16) * pbUsrBuf << 8;
|
||||
*pdwVal++ = temp2;
|
||||
pdwVal++;
|
||||
pbUsrBuf++;
|
||||
}
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : PMAToUserBufferCopy
|
||||
* Description : Copy a buffer from user memory area to packet memory area (PMA)
|
||||
* Input : - pbUsrBuf = pointer to user memory area.
|
||||
* - wPMABufAddr = address into PMA.
|
||||
* - wNBytes = no. of bytes to be copied.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void PMAToUserBufferCopy(u8 *pbUsrBuf, u16 wPMABufAddr, u16 wNBytes)
|
||||
{
|
||||
u32 n = (wNBytes + 1) >> 1;/* /2*/
|
||||
u32 i;
|
||||
u32 *pdwVal;
|
||||
pdwVal = (u32 *)(wPMABufAddr * 2 + PMAAddr);
|
||||
for (i = n; i != 0; i--)
|
||||
{
|
||||
*(u16*)pbUsrBuf++ = *pdwVal++;
|
||||
pbUsrBuf++;
|
||||
}
|
||||
}
|
||||
|
||||
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,748 @@
|
|||
/******************** (C) COPYRIGHT 2008 STMicroelectronics ********************
|
||||
* File Name : usb_regs.c
|
||||
* Author : MCD Application Team
|
||||
* Version : V2.2.1
|
||||
* Date : 09/22/2008
|
||||
* Description : Interface functions to USB cell registers
|
||||
********************************************************************************
|
||||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
|
||||
* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
|
||||
* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
|
||||
* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||||
*******************************************************************************/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "usb_lib.h"
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Extern variables ----------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetCNTR.
|
||||
* Description : Set the CNTR register value.
|
||||
* Input : wRegValue: new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetCNTR(u16 wRegValue)
|
||||
{
|
||||
_SetCNTR(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetCNTR.
|
||||
* Description : returns the CNTR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : CNTR register Value.
|
||||
*******************************************************************************/
|
||||
u16 GetCNTR(void)
|
||||
{
|
||||
return(_GetCNTR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetISTR.
|
||||
* Description : Set the ISTR register value.
|
||||
* Input : wRegValue: new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetISTR(u16 wRegValue)
|
||||
{
|
||||
_SetISTR(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetISTR
|
||||
* Description : Returns the ISTR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : ISTR register Value
|
||||
*******************************************************************************/
|
||||
u16 GetISTR(void)
|
||||
{
|
||||
return(_GetISTR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetFNR
|
||||
* Description : Returns the FNR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : FNR register Value
|
||||
*******************************************************************************/
|
||||
u16 GetFNR(void)
|
||||
{
|
||||
return(_GetFNR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetDADDR
|
||||
* Description : Set the DADDR register value.
|
||||
* Input : wRegValue: new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetDADDR(u16 wRegValue)
|
||||
{
|
||||
_SetDADDR(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetDADDR
|
||||
* Description : Returns the DADDR register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : DADDR register Value
|
||||
*******************************************************************************/
|
||||
u16 GetDADDR(void)
|
||||
{
|
||||
return(_GetDADDR());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetBTABLE
|
||||
* Description : Set the BTABLE.
|
||||
* Input : wRegValue: New register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetBTABLE(u16 wRegValue)
|
||||
{
|
||||
_SetBTABLE(wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetBTABLE.
|
||||
* Description : Returns the BTABLE register value.
|
||||
* Input : None.
|
||||
* Output : None.
|
||||
* Return : BTABLE address.
|
||||
*******************************************************************************/
|
||||
u16 GetBTABLE(void)
|
||||
{
|
||||
return(_GetBTABLE());
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetENDPOINT
|
||||
* Description : Setthe Endpoint register value.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wRegValue.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetENDPOINT(u8 bEpNum, u16 wRegValue)
|
||||
{
|
||||
_SetENDPOINT(bEpNum, wRegValue);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetENDPOINT
|
||||
* Description : Return the Endpoint register value.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint register value.
|
||||
*******************************************************************************/
|
||||
u16 GetENDPOINT(u8 bEpNum)
|
||||
{
|
||||
return(_GetENDPOINT(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPType
|
||||
* Description : sets the type in the endpoint register.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wType: type definition.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPType(u8 bEpNum, u16 wType)
|
||||
{
|
||||
_SetEPType(bEpNum, wType);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPType
|
||||
* Description : Returns the endpoint type.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint Type
|
||||
*******************************************************************************/
|
||||
u16 GetEPType(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPType(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxStatus
|
||||
* Description : Set the status of Tx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wState: new state.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxStatus(u8 bEpNum, u16 wState)
|
||||
{
|
||||
_SetEPTxStatus(bEpNum, wState);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxStatus
|
||||
* Description : Set the status of Rx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wState: new state.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxStatus(u8 bEpNum, u16 wState)
|
||||
{
|
||||
_SetEPRxStatus(bEpNum, wState);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetDouBleBuffEPStall
|
||||
* Description : sets the status for Double Buffer Endpoint to STALL
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* bDir: Endpoint direction.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetDouBleBuffEPStall(u8 bEpNum, u8 bDir)
|
||||
{
|
||||
u16 Endpoint_DTOG_Status;
|
||||
Endpoint_DTOG_Status = GetENDPOINT(bEpNum);
|
||||
if (bDir == EP_DBUF_OUT)
|
||||
{ /* OUT double buffered endpoint */
|
||||
_SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPRX_DTOG1);
|
||||
}
|
||||
else if (bDir == EP_DBUF_IN)
|
||||
{ /* IN double buffered endpoint */
|
||||
_SetENDPOINT(bEpNum, Endpoint_DTOG_Status & ~EPTX_DTOG1);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPTxStatus
|
||||
* Description : Returns the endpoint Tx status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint TX Status
|
||||
*******************************************************************************/
|
||||
u16 GetEPTxStatus(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPTxStatus(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPRxStatus
|
||||
* Description : Returns the endpoint Rx status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint RX Status
|
||||
*******************************************************************************/
|
||||
u16 GetEPRxStatus(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPRxStatus(bEpNum));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxValid
|
||||
* Description : Valid the endpoint Tx Status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxValid(u8 bEpNum)
|
||||
{
|
||||
_SetEPTxStatus(bEpNum, EP_TX_VALID);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxValid
|
||||
* Description : Valid the endpoint Rx Status.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxValid(u8 bEpNum)
|
||||
{
|
||||
_SetEPRxStatus(bEpNum, EP_RX_VALID);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEP_KIND
|
||||
* Description : Clear the EP_KIND bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEP_KIND(u8 bEpNum)
|
||||
{
|
||||
_SetEP_KIND(bEpNum);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEP_KIND
|
||||
* Description : set the EP_KIND bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEP_KIND(u8 bEpNum)
|
||||
{
|
||||
_ClearEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : Clear_Status_Out
|
||||
* Description : Clear the Status Out of the related Endpoint
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Clear_Status_Out(u8 bEpNum)
|
||||
{
|
||||
_ClearEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : Set_Status_Out
|
||||
* Description : Set the Status Out of the related Endpoint
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void Set_Status_Out(u8 bEpNum)
|
||||
{
|
||||
_SetEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDoubleBuff
|
||||
* Description : Enable the double buffer feature for the endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDoubleBuff(u8 bEpNum)
|
||||
{
|
||||
_SetEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEPDoubleBuff
|
||||
* Description : Disable the double buffer feature for the endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEPDoubleBuff(u8 bEpNum)
|
||||
{
|
||||
_ClearEP_KIND(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetTxStallStatus
|
||||
* Description : Returns the Stall status of the Tx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Tx Stall status.
|
||||
*******************************************************************************/
|
||||
u16 GetTxStallStatus(u8 bEpNum)
|
||||
{
|
||||
return(_GetTxStallStatus(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetRxStallStatus
|
||||
* Description : Returns the Stall status of the Rx endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx Stall status.
|
||||
*******************************************************************************/
|
||||
u16 GetRxStallStatus(u8 bEpNum)
|
||||
{
|
||||
return(_GetRxStallStatus(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEP_CTR_RX
|
||||
* Description : Clear the CTR_RX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEP_CTR_RX(u8 bEpNum)
|
||||
{
|
||||
_ClearEP_CTR_RX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearEP_CTR_TX
|
||||
* Description : Clear the CTR_TX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearEP_CTR_TX(u8 bEpNum)
|
||||
{
|
||||
_ClearEP_CTR_TX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ToggleDTOG_RX
|
||||
* Description : Toggle the DTOG_RX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ToggleDTOG_RX(u8 bEpNum)
|
||||
{
|
||||
_ToggleDTOG_RX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ToggleDTOG_TX
|
||||
* Description : Toggle the DTOG_TX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ToggleDTOG_TX(u8 bEpNum)
|
||||
{
|
||||
_ToggleDTOG_TX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearDTOG_RX.
|
||||
* Description : Clear the DTOG_RX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearDTOG_RX(u8 bEpNum)
|
||||
{
|
||||
_ClearDTOG_RX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ClearDTOG_TX.
|
||||
* Description : Clear the DTOG_TX bit.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void ClearDTOG_TX(u8 bEpNum)
|
||||
{
|
||||
_ClearDTOG_TX(bEpNum);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPAddress
|
||||
* Description : Set the endpoint address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* bAddr: New endpoint address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPAddress(u8 bEpNum, u8 bAddr)
|
||||
{
|
||||
_SetEPAddress(bEpNum, bAddr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPAddress
|
||||
* Description : Get the endpoint address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint address.
|
||||
*******************************************************************************/
|
||||
u8 GetEPAddress(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPAddress(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxAddr
|
||||
* Description : Set the endpoint Tx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wAddr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxAddr(u8 bEpNum, u16 wAddr)
|
||||
{
|
||||
_SetEPTxAddr(bEpNum, wAddr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxAddr
|
||||
* Description : Set the endpoint Rx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wAddr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxAddr(u8 bEpNum, u16 wAddr)
|
||||
{
|
||||
_SetEPRxAddr(bEpNum, wAddr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPTxAddr
|
||||
* Description : Returns the endpoint Tx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx buffer address.
|
||||
*******************************************************************************/
|
||||
u16 GetEPTxAddr(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPTxAddr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPRxAddr.
|
||||
* Description : Returns the endpoint Rx buffer address.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx buffer address.
|
||||
*******************************************************************************/
|
||||
u16 GetEPRxAddr(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPRxAddr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPTxCount.
|
||||
* Description : Set the Tx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wCount: new count value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPTxCount(u8 bEpNum, u16 wCount)
|
||||
{
|
||||
_SetEPTxCount(bEpNum, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPCountRxReg.
|
||||
* Description : Set the Count Rx Register value.
|
||||
* Input : *pdwReg: point to the register.
|
||||
* wCount: the new register value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPCountRxReg(u32 *pdwReg, u16 wCount)
|
||||
{
|
||||
_SetEPCountRxReg(dwReg, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPRxCount
|
||||
* Description : Set the Rx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wCount: the new count value.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPRxCount(u8 bEpNum, u16 wCount)
|
||||
{
|
||||
_SetEPRxCount(bEpNum, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPTxCount
|
||||
* Description : Get the Tx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None
|
||||
* Return : Tx count value.
|
||||
*******************************************************************************/
|
||||
u16 GetEPTxCount(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPTxCount(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPRxCount
|
||||
* Description : Get the Rx count.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Rx count value.
|
||||
*******************************************************************************/
|
||||
u16 GetEPRxCount(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPRxCount(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuffAddr
|
||||
* Description : Set the addresses of the buffer 0 and 1.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* wBuf0Addr: new address of buffer 0.
|
||||
* wBuf1Addr: new address of buffer 1.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuffAddr(u8 bEpNum, u16 wBuf0Addr, u16 wBuf1Addr)
|
||||
{
|
||||
_SetEPDblBuffAddr(bEpNum, wBuf0Addr, wBuf1Addr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf0Addr
|
||||
* Description : Set the Buffer 1 address.
|
||||
* Input : bEpNum: Endpoint Number
|
||||
* wBuf0Addr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf0Addr(u8 bEpNum, u16 wBuf0Addr)
|
||||
{
|
||||
_SetEPDblBuf0Addr(bEpNum, wBuf0Addr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf1Addr
|
||||
* Description : Set the Buffer 1 address.
|
||||
* Input : bEpNum: Endpoint Number
|
||||
* wBuf1Addr: new address.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf1Addr(u8 bEpNum, u16 wBuf1Addr)
|
||||
{
|
||||
_SetEPDblBuf1Addr(bEpNum, wBuf1Addr);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf0Addr
|
||||
* Description : Returns the address of the Buffer 0.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
u16 GetEPDblBuf0Addr(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf0Addr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf1Addr
|
||||
* Description : Returns the address of the Buffer 1.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Address of the Buffer 1.
|
||||
*******************************************************************************/
|
||||
u16 GetEPDblBuf1Addr(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf1Addr(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuffCount
|
||||
* Description : Set the number of bytes for a double Buffer
|
||||
* endpoint.
|
||||
* Input : bEpNum,bDir, wCount
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuffCount(u8 bEpNum, u8 bDir, u16 wCount)
|
||||
{
|
||||
_SetEPDblBuffCount(bEpNum, bDir, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf0Count
|
||||
* Description : Set the number of bytes in the buffer 0 of a double Buffer
|
||||
* endpoint.
|
||||
* Input : bEpNum, bDir, wCount
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf0Count(u8 bEpNum, u8 bDir, u16 wCount)
|
||||
{
|
||||
_SetEPDblBuf0Count(bEpNum, bDir, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : SetEPDblBuf1Count
|
||||
* Description : Set the number of bytes in the buffer 0 of a double Buffer
|
||||
* endpoint.
|
||||
* Input : bEpNum, bDir, wCount
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void SetEPDblBuf1Count(u8 bEpNum, u8 bDir, u16 wCount)
|
||||
{
|
||||
_SetEPDblBuf1Count(bEpNum, bDir, wCount);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf0Count
|
||||
* Description : Returns the number of byte received in the buffer 0 of a double
|
||||
* Buffer endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint Buffer 0 count
|
||||
*******************************************************************************/
|
||||
u16 GetEPDblBuf0Count(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf0Count(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBuf1Count
|
||||
* Description : Returns the number of data received in the buffer 1 of a double
|
||||
* Buffer endpoint.
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : Endpoint Buffer 1 count.
|
||||
*******************************************************************************/
|
||||
u16 GetEPDblBuf1Count(u8 bEpNum)
|
||||
{
|
||||
return(_GetEPDblBuf1Count(bEpNum));
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : GetEPDblBufDir
|
||||
* Description : gets direction of the double buffered endpoint
|
||||
* Input : bEpNum: Endpoint Number.
|
||||
* Output : None.
|
||||
* Return : EP_DBUF_OUT, EP_DBUF_IN,
|
||||
* EP_DBUF_ERR if the endpoint counter not yet programmed.
|
||||
*******************************************************************************/
|
||||
EP_DBUF_DIR GetEPDblBufDir(u8 bEpNum)
|
||||
{
|
||||
if ((u16)(*_pEPRxCount(bEpNum) & 0xFC00) != 0)
|
||||
return(EP_DBUF_OUT);
|
||||
else if (((u16)(*_pEPTxCount(bEpNum)) & 0x03FF) != 0)
|
||||
return(EP_DBUF_IN);
|
||||
else
|
||||
return(EP_DBUF_ERR);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : FreeUserBuffer
|
||||
* Description : free buffer used from the application realizing it to the line
|
||||
toggles bit SW_BUF in the double buffered endpoint register
|
||||
* Input : bEpNum, bDir
|
||||
* Output : None.
|
||||
* Return : None.
|
||||
*******************************************************************************/
|
||||
void FreeUserBuffer(u8 bEpNum, u8 bDir)
|
||||
{
|
||||
if (bDir == EP_DBUF_OUT)
|
||||
{ /* OUT double buffered endpoint */
|
||||
_ToggleDTOG_TX(bEpNum);
|
||||
}
|
||||
else if (bDir == EP_DBUF_IN)
|
||||
{ /* IN double buffered endpoint */
|
||||
_ToggleDTOG_RX(bEpNum);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : ToWord
|
||||
* Description : merge two byte in a word.
|
||||
* Input : bh: byte high, bl: bytes low.
|
||||
* Output : None.
|
||||
* Return : resulted word.
|
||||
*******************************************************************************/
|
||||
u16 ToWord(u8 bh, u8 bl)
|
||||
{
|
||||
u16 wRet;
|
||||
wRet = (u16)bl | ((u16)bh << 8);
|
||||
return(wRet);
|
||||
}
|
||||
/*******************************************************************************
|
||||
* Function Name : ByteSwap
|
||||
* Description : Swap two byte in a word.
|
||||
* Input : wSwW: word to Swap.
|
||||
* Output : None.
|
||||
* Return : resulted word.
|
||||
*******************************************************************************/
|
||||
u16 ByteSwap(u16 wSwW)
|
||||
{
|
||||
u8 bTemp;
|
||||
u16 wRet;
|
||||
bTemp = (u8)(wSwW & 0xff);
|
||||
wRet = (wSwW >> 8) | ((u16)bTemp << 8);
|
||||
return(wRet);
|
||||
}
|
||||
|
||||
/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/
|
|
@ -0,0 +1,152 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file libmaple/util.c
|
||||
* @brief Utility procedures for debugging
|
||||
*/
|
||||
|
||||
#include <libmaple/libmaple.h>
|
||||
#include <libmaple/usart.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/nvic.h>
|
||||
|
||||
/* (Undocumented) hooks used by Wirish to direct our behavior here */
|
||||
extern __weak void __lm_error(void);
|
||||
extern __weak usart_dev* __lm_enable_error_usart(void);
|
||||
|
||||
/* If you define ERROR_LED_PORT and ERROR_LED_PIN, then a failed
|
||||
* ASSERT() will also throb() an LED connected to that port and pin.
|
||||
*/
|
||||
#if defined(ERROR_LED_PORT) && defined(ERROR_LED_PIN)
|
||||
#define HAVE_ERROR_LED
|
||||
#endif
|
||||
|
||||
/* (Called from exc.S with global interrupts disabled.) */
|
||||
__attribute__((noreturn)) void __error(void) {
|
||||
if (__lm_error) {
|
||||
__lm_error();
|
||||
}
|
||||
/* Reenable global interrupts */
|
||||
nvic_globalirq_enable();
|
||||
throb();
|
||||
}
|
||||
|
||||
/*
|
||||
* Print an error message on a UART upon a failed assertion (if one is
|
||||
* available), and punt to __error().
|
||||
*
|
||||
* @param file Source file of failed assertion
|
||||
* @param line Source line of failed assertion
|
||||
* @param exp String representation of failed assertion
|
||||
* @sideeffect Turns of all peripheral interrupts except USB.
|
||||
*/
|
||||
void _fail(const char* file, int line, const char* exp) {
|
||||
if (__lm_enable_error_usart) {
|
||||
/* Initialize the error USART */
|
||||
usart_dev *err_usart = __lm_enable_error_usart();
|
||||
|
||||
/* Print failed assert message */
|
||||
usart_putstr(err_usart, "ERROR: FAILED ASSERT(");
|
||||
usart_putstr(err_usart, exp);
|
||||
usart_putstr(err_usart, "): ");
|
||||
usart_putstr(err_usart, file);
|
||||
usart_putstr(err_usart, ": ");
|
||||
usart_putudec(err_usart, line);
|
||||
usart_putc(err_usart, '\n');
|
||||
usart_putc(err_usart, '\r');
|
||||
}
|
||||
/* Shutdown and error fade */
|
||||
__error();
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide an __assert_func handler to libc so that calls to assert()
|
||||
* get redirected to _fail.
|
||||
*/
|
||||
void __assert_func(const char* file, int line, const char* method,
|
||||
const char* expression) {
|
||||
_fail(file, line, expression);
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide an abort() implementation that aborts execution and punts
|
||||
* to __error().
|
||||
*/
|
||||
void abort() {
|
||||
if (__lm_enable_error_usart) {
|
||||
/* Initialize the error USART */
|
||||
usart_dev *err_usart = __lm_enable_error_usart();
|
||||
/* Print abort message. */
|
||||
usart_putstr(err_usart, "ERROR: PROGRAM ABORTED VIA abort()\r\n");
|
||||
}
|
||||
|
||||
/* Shutdown and error fade */
|
||||
__error();
|
||||
}
|
||||
|
||||
/* This was public as of v0.0.12, so we've got to keep it public. */
|
||||
/**
|
||||
* @brief Fades the error LED on and off
|
||||
* @sideeffect Sets output push-pull on ERROR_LED_PIN.
|
||||
*/
|
||||
__attribute__((noreturn)) void throb(void) {
|
||||
#ifdef HAVE_ERROR_LED
|
||||
int32 slope = 1;
|
||||
uint32 CC = 0x0000;
|
||||
uint32 TOP_CNT = 0x0200;
|
||||
uint32 i = 0;
|
||||
volatile int dly;
|
||||
|
||||
gpio_set_mode(ERROR_LED_PORT, ERROR_LED_PIN, GPIO_MODE_OUTPUT);
|
||||
/* Error fade. */
|
||||
while (1) {
|
||||
if (CC == TOP_CNT) {
|
||||
slope = -1;
|
||||
} else if (CC == 0) {
|
||||
slope = 1;
|
||||
}
|
||||
|
||||
if (i == TOP_CNT) {
|
||||
CC += slope;
|
||||
i = 0;
|
||||
}
|
||||
|
||||
if (i < CC) {
|
||||
gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 1);
|
||||
} else {
|
||||
gpio_write_bit(ERROR_LED_PORT, ERROR_LED_PIN, 0);
|
||||
}
|
||||
i++;
|
||||
for( dly=0;dly<10;dly++);
|
||||
}
|
||||
#else
|
||||
/* No error LED is defined; do nothing. */
|
||||
while (1)
|
||||
;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 LeafLabs LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
extern void setup(void);
|
||||
extern void loop(void);
|
||||
extern void init(void);
|
||||
|
||||
// Force init to be called *first*, i.e. before static object allocation.
|
||||
// Otherwise, statically allocated objects that need libmaple may fail.
|
||||
__attribute__(( constructor (101))) void premain() {
|
||||
init();
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
setup();
|
||||
|
||||
while (1) {
|
||||
loop();
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/pwm.cpp
|
||||
* @brief Wiring-style pwmWrite().
|
||||
*/
|
||||
|
||||
#include "pwm.h"
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <libmaple/timer.h>
|
||||
|
||||
#include "boards.h"
|
||||
#include "io.h"
|
||||
|
||||
void pwmWrite(uint8 pin, uint16 duty_cycle) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS) {
|
||||
return;
|
||||
}
|
||||
timer_dev *dev = PIN_MAP[pin].timer_device;
|
||||
uint8 cc_channel = PIN_MAP[pin].timer_channel;
|
||||
ASSERT(dev && cc_channel);
|
||||
timer_set_compare(dev, cc_channel, duty_cycle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Roger Clark. Added new function to replicate more closely what the Arduino API does
|
||||
* Note. This implementation is currently slower than it could be,
|
||||
* because pinMode needs to be called to set the special (new) mode of PWM
|
||||
* Some optimisation may be possible with pinMode or even in this function
|
||||
*/
|
||||
void analogWrite(uint8 pin, int duty_cycle8)
|
||||
{
|
||||
pinMode(pin,PWM);
|
||||
pwmWrite(pin,duty_cycle8 * 257);// 257 maps 255 to 65535 (i.e 255*257 = 65535)
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/pwm.h
|
||||
* @brief Wiring-style PWM interface.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_PWM_H_
|
||||
#define _WIRISH_PWM_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
|
||||
/**
|
||||
* Set the PWM duty on the given pin.
|
||||
*
|
||||
* User code is expected to determine and honor the maximum value
|
||||
* (based on the configured period).
|
||||
*
|
||||
* @param pin PWM output pin
|
||||
* @param duty_cycle Duty cycle to set. (Range is 0 to 65535)
|
||||
*/
|
||||
void pwmWrite(uint8 pin, uint16 duty_cycle16);
|
||||
|
||||
/**
|
||||
* Roger Clark. 20140103
|
||||
* Added function to replicate the Arduino PWM functionality or range 0 to 255
|
||||
* User code is expected to determine and honor the maximum value
|
||||
* (based on the configured period).
|
||||
*
|
||||
* @param pin PWM output pin
|
||||
* @param duty_cycle Duty cycle to set. (Range is 0 to 255)
|
||||
*/
|
||||
void analogWrite(uint8 pin, int duty_cycle8);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# Standard things
|
||||
sp := $(sp).x
|
||||
dirstack_$(sp) := $(d)
|
||||
d := $(dir)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)
|
||||
|
||||
# Add board directory and MCU-specific directory to BUILDDIRS. These
|
||||
# are in subdirectories, but they're logically part of the Wirish
|
||||
# submodule.
|
||||
WIRISH_BOARD_PATH := boards/$(BOARD)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/$(WIRISH_BOARD_PATH)
|
||||
BUILDDIRS += $(BUILD_PATH)/$(d)/$(MCU_SERIES)
|
||||
|
||||
# Safe includes for Wirish.
|
||||
WIRISH_INCLUDES := -I$(d)/include -I$(d)/$(WIRISH_BOARD_PATH)/include
|
||||
|
||||
# Local flags. Add -I$(d) to allow for private includes.
|
||||
CFLAGS_$(d) := $(LIBMAPLE_INCLUDES) $(WIRISH_INCLUDES) -I$(d)
|
||||
|
||||
# Local rules and targets
|
||||
sSRCS_$(d) := start.S
|
||||
cSRCS_$(d) := start_c.c
|
||||
cSRCS_$(d) += syscalls.c
|
||||
cSRCS_$(d) += $(MCU_SERIES)/util_hooks.c
|
||||
cppSRCS_$(d) := boards.cpp
|
||||
cppSRCS_$(d) += cxxabi-compat.cpp
|
||||
cppSRCS_$(d) += ext_interrupts.cpp
|
||||
cppSRCS_$(d) += HardwareSerial.cpp
|
||||
cppSRCS_$(d) += HardwareTimer.cpp
|
||||
cppSRCS_$(d) += Print.cpp
|
||||
cppSRCS_$(d) += pwm.cpp
|
||||
ifeq ($(MCU_SERIES), stm32f1)
|
||||
cppSRCS_$(d) += usb_serial.cpp # HACK: this is currently STM32F1 only.
|
||||
cppSRCS_$(d) += HardwareSPI.cpp # FIXME: port to F2 and fix wirish.h
|
||||
endif
|
||||
cppSRCS_$(d) += wirish_analog.cpp
|
||||
cppSRCS_$(d) += wirish_digital.cpp
|
||||
cppSRCS_$(d) += wirish_math.cpp
|
||||
cppSRCS_$(d) += wirish_shift.cpp
|
||||
cppSRCS_$(d) += wirish_time.cpp
|
||||
cppSRCS_$(d) += $(MCU_SERIES)/boards_setup.cpp
|
||||
cppSRCS_$(d) += $(MCU_SERIES)/wirish_digital.cpp
|
||||
cppSRCS_$(d) += $(MCU_SERIES)/wirish_debug.cpp
|
||||
cppSRCS_$(d) += $(WIRISH_BOARD_PATH)/board.cpp
|
||||
|
||||
sFILES_$(d) := $(sSRCS_$(d):%=$(d)/%)
|
||||
cFILES_$(d) := $(cSRCS_$(d):%=$(d)/%)
|
||||
cppFILES_$(d) := $(cppSRCS_$(d):%=$(d)/%)
|
||||
|
||||
OBJS_$(d) := $(sFILES_$(d):%.S=$(BUILD_PATH)/%.o) \
|
||||
$(cFILES_$(d):%.c=$(BUILD_PATH)/%.o) \
|
||||
$(cppFILES_$(d):%.cpp=$(BUILD_PATH)/%.o)
|
||||
DEPS_$(d) := $(OBJS_$(d):%.o=%.d)
|
||||
|
||||
$(OBJS_$(d)): TGT_CFLAGS := $(CFLAGS_$(d))
|
||||
|
||||
TGT_BIN += $(OBJS_$(d))
|
||||
|
||||
# Standard things
|
||||
-include $(DEPS_$(d))
|
||||
d := $(dirstack_$(sp))
|
||||
sp := $(basename $(sp))
|
|
@ -0,0 +1,83 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung (from libmaple/util.c).
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* STM32F1 implementations for libmaple/util.c hooks
|
||||
*
|
||||
* These need more love and attention before being made public API
|
||||
* (this includes being easily overridable by user code).
|
||||
*/
|
||||
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/stm32.h>
|
||||
#include <libmaple/timer.h>
|
||||
#include <libmaple/adc.h>
|
||||
#include <libmaple/usart.h>
|
||||
|
||||
/* Failed ASSERT()s send out a message using this USART config. */
|
||||
#ifndef ERROR_USART
|
||||
#define ERROR_USART USART1
|
||||
#define ERROR_USART_BAUD 9600
|
||||
#define ERROR_TX_PORT GPIOA
|
||||
#define ERROR_TX_PIN 2
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Disables all peripheral interrupts except USB (when available),
|
||||
* turns off commonly-used peripherals. Called by __error() with
|
||||
* global interrupts disabled.
|
||||
*/
|
||||
void __lm_error(void) {
|
||||
/* Turn off peripheral interrupts */
|
||||
nvic_irq_disable_all();
|
||||
|
||||
/* Turn off timers */
|
||||
timer_disable_all();
|
||||
|
||||
/* Turn off ADC */
|
||||
adc_disable_all();
|
||||
|
||||
/* Turn off all USARTs */
|
||||
usart_disable_all();
|
||||
|
||||
#if STM32_HAVE_USB
|
||||
/* Turn the USB interrupt back on so the bootloader keeps on functioning */
|
||||
nvic_irq_enable(NVIC_USB_HP_CAN_TX);
|
||||
nvic_irq_enable(NVIC_USB_LP_CAN_RX0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable the error USART for writing.
|
||||
*/
|
||||
usart_dev* __lm_enable_error_usart() {
|
||||
gpio_set_mode(ERROR_TX_PORT, ERROR_TX_PIN, GPIO_AF_OUTPUT_PP);
|
||||
usart_init(ERROR_USART);
|
||||
usart_set_baud_rate(ERROR_USART, USART_USE_PCLK, ERROR_USART_BAUD);
|
||||
return ERROR_USART;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
#include <wiring_pulse.h>
|
||||
#include "boards.h"
|
||||
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
|
||||
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
|
||||
* to 3 minutes in length, but must be called at least a few dozen microseconds
|
||||
* before the start of the pulse. */
|
||||
|
||||
|
||||
/*
|
||||
* Roger Clark
|
||||
*
|
||||
* Note. The API spec for this function published on http://www.arduino.cc/en/Reference/PulseIn
|
||||
* doesn't reflect what either the AVR or SAM version of this function actualy do with regard to the timeout value
|
||||
*
|
||||
* "timeout (optional): the number of microseconds to wait for the pulse to start; default is one second (unsigned long) "
|
||||
*
|
||||
* Because the timeout, is actually coded as the total time to both wait while the input is in the state requested
|
||||
* then wait for the opposite state duration
|
||||
* then count the length of the pulse when it has the value of state (HIGH or LOW)
|
||||
*
|
||||
* So I think the code for both the AVR and the Due is wrong in that it doesnt match the spec
|
||||
*
|
||||
* I have done basically the same as the AVR and Due code, except to make the timeout a bit more accurate I have put in a dummy volatile varable
|
||||
* dummyWidth so that both the waiting while loops take the same number of clock cycles to execute as the acount width counting loop
|
||||
*
|
||||
* to be slighly more accurate the maxLoops variable really needs to take into account the loop setup code, but its probably as good as necessary
|
||||
*
|
||||
*/
|
||||
uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout )
|
||||
{
|
||||
// cache the port and bit of the pin in order to speed up the
|
||||
// pulse width measuring loop and achieve finer resolution. calling
|
||||
// digitalRead() instead yields much coarser resolution.
|
||||
|
||||
gpio_dev *dev=PIN_MAP[pin].gpio_device;
|
||||
uint32_t bit = (1U << PIN_MAP[pin].gpio_bit);
|
||||
|
||||
|
||||
uint32_t width = 0; // keep initialization out of time critical area
|
||||
|
||||
// convert the timeout from microseconds to a number of times through
|
||||
// the initial loop; it takes 16 clock cycles per iteration.
|
||||
uint32_t numloops = 0;
|
||||
uint32_t maxloops = timeout * ( F_CPU / 16000000);
|
||||
volatile uint32_t dummyWidth=0;
|
||||
|
||||
// wait for any previous pulse to end
|
||||
while ( (dev->regs->IDR & bit) == bit) {
|
||||
if (numloops++ == maxloops) {
|
||||
return 0;
|
||||
}
|
||||
dummyWidth++;
|
||||
}
|
||||
|
||||
// wait for the pulse to start
|
||||
while ((dev->regs->IDR & bit) != bit) {
|
||||
if (numloops++ == maxloops) {
|
||||
return 0;
|
||||
}
|
||||
dummyWidth++;
|
||||
}
|
||||
|
||||
// wait for the pulse to stop
|
||||
while ((dev->regs->IDR & bit) == bit) {
|
||||
if (numloops++ == maxloops) {
|
||||
return 0;
|
||||
}
|
||||
width++;
|
||||
}
|
||||
|
||||
// Excluding time taking up by the interrupts, it needs 16 clock cycles to look through the last while loop
|
||||
// 5 is added as a fiddle factor to correct for interrupts etc. But ultimately this would only be accurate if it was done ona hardware timer
|
||||
|
||||
return (uint32_t)( ( (unsigned long long)(width+5) * (unsigned long long) 16000000.0) /(unsigned long long)F_CPU ) ;
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/stm32f1/wirish_debug.cpp
|
||||
* @brief High level debug port configuration
|
||||
*/
|
||||
|
||||
#include <wirish_debug.h>
|
||||
#include <libmaple/gpio.h>
|
||||
|
||||
void disableDebugPorts(void) {
|
||||
afio_cfg_debug_ports(AFIO_DEBUG_NONE);
|
||||
}
|
||||
|
||||
void enableDebugPorts(void) {
|
||||
afio_cfg_debug_ports(AFIO_DEBUG_FULL_SWJ);
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* STM32F1 implementations for basic GPIO functionality.
|
||||
*/
|
||||
|
||||
#include <io.h>
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/timer.h>
|
||||
|
||||
#include <boards.h>
|
||||
|
||||
void pinMode(uint8 pin, WiringPinMode mode) {
|
||||
gpio_pin_mode outputMode;
|
||||
bool pwm = false;
|
||||
|
||||
if (pin >= BOARD_NR_GPIO_PINS) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch(mode) {
|
||||
case OUTPUT:
|
||||
outputMode = GPIO_OUTPUT_PP;
|
||||
break;
|
||||
case OUTPUT_OPEN_DRAIN:
|
||||
outputMode = GPIO_OUTPUT_OD;
|
||||
break;
|
||||
case INPUT:
|
||||
case INPUT_FLOATING:
|
||||
outputMode = GPIO_INPUT_FLOATING;
|
||||
break;
|
||||
case INPUT_ANALOG:
|
||||
outputMode = GPIO_INPUT_ANALOG;
|
||||
break;
|
||||
case INPUT_PULLUP:
|
||||
outputMode = GPIO_INPUT_PU;
|
||||
break;
|
||||
case INPUT_PULLDOWN:
|
||||
outputMode = GPIO_INPUT_PD;
|
||||
break;
|
||||
case PWM:
|
||||
outputMode = GPIO_AF_OUTPUT_PP;
|
||||
pwm = true;
|
||||
break;
|
||||
case PWM_OPEN_DRAIN:
|
||||
outputMode = GPIO_AF_OUTPUT_OD;
|
||||
pwm = true;
|
||||
break;
|
||||
default:
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_set_mode(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, outputMode);
|
||||
|
||||
if (PIN_MAP[pin].timer_device != NULL) {
|
||||
/* Enable/disable timer channels if we're switching into or
|
||||
* out of PWM. */
|
||||
timer_set_mode(PIN_MAP[pin].timer_device,
|
||||
PIN_MAP[pin].timer_channel,
|
||||
pwm ? TIMER_PWM : TIMER_DISABLED);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,354 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief USB virtual serial terminal
|
||||
*/
|
||||
|
||||
#include "usb_serial.h"
|
||||
|
||||
#include "string.h"
|
||||
#include "stdint.h"
|
||||
|
||||
#include <libmaple/nvic.h>
|
||||
#include <libmaple/usb_cdcacm.h>
|
||||
#include <libmaple/usb.h>
|
||||
#include <libmaple/iwdg.h>
|
||||
|
||||
#include "wirish.h"
|
||||
|
||||
/*
|
||||
* Hooks used for bootloader reset signalling
|
||||
*/
|
||||
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
static void rxHook(unsigned, void*);
|
||||
static void ifaceSetupHook(unsigned, void*);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* USBSerial interface
|
||||
*/
|
||||
|
||||
#define USB_TIMEOUT 50
|
||||
|
||||
USBSerial::USBSerial(void) {
|
||||
#if !BOARD_HAVE_SERIALUSB
|
||||
ASSERT(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void USBSerial::begin(void) {
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
usb_cdcacm_set_hooks(USB_CDCACM_HOOK_RX, rxHook);
|
||||
usb_cdcacm_set_hooks(USB_CDCACM_HOOK_IFACE_SETUP, ifaceSetupHook);
|
||||
#endif
|
||||
}
|
||||
|
||||
//Roger Clark. Two new begin functions has been added so that normal Arduino Sketches that use Serial.begin(xxx) will compile.
|
||||
void USBSerial::begin(unsigned long ignoreBaud)
|
||||
{
|
||||
volatile unsigned long removeCompilerWarningsIgnoreBaud=ignoreBaud;
|
||||
|
||||
ignoreBaud=removeCompilerWarningsIgnoreBaud;
|
||||
}
|
||||
void USBSerial::begin(unsigned long ignoreBaud, uint8_t ignore)
|
||||
{
|
||||
volatile unsigned long removeCompilerWarningsIgnoreBaud=ignoreBaud;
|
||||
volatile uint8_t removeCompilerWarningsIgnore=ignore;
|
||||
|
||||
ignoreBaud=removeCompilerWarningsIgnoreBaud;
|
||||
ignore=removeCompilerWarningsIgnore;
|
||||
}
|
||||
|
||||
void USBSerial::end(void) {
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
usb_cdcacm_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
usb_cdcacm_remove_hooks(USB_CDCACM_HOOK_RX | USB_CDCACM_HOOK_IFACE_SETUP);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t USBSerial::write(uint8 ch) {
|
||||
size_t n = 0;
|
||||
this->write(&ch, 1);
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t USBSerial::write(const char *str) {
|
||||
size_t n = 0;
|
||||
this->write(str, strlen(str));
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t USBSerial::write(const void *buf, uint32 len) {
|
||||
size_t n = 0;
|
||||
if (!this->isConnected() || !buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 txed = 0;
|
||||
uint32 old_txed = 0;
|
||||
uint32 start = millis();
|
||||
|
||||
uint32 sent = 0;
|
||||
|
||||
while (txed < len && (millis() - start < USB_TIMEOUT)) {
|
||||
sent = usb_cdcacm_tx((const uint8*)buf + txed, len - txed);
|
||||
txed += sent;
|
||||
if (old_txed != txed) {
|
||||
start = millis();
|
||||
}
|
||||
old_txed = txed;
|
||||
}
|
||||
|
||||
|
||||
if (sent == USB_CDCACM_TX_EPSIZE) {
|
||||
while (usb_cdcacm_is_transmitting() != 0) {
|
||||
}
|
||||
/* flush out to avoid having the pc wait for more data */
|
||||
usb_cdcacm_tx(NULL, 0);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int USBSerial::available(void) {
|
||||
return usb_cdcacm_data_available();
|
||||
}
|
||||
|
||||
int USBSerial::peek(void)
|
||||
{
|
||||
uint8 b;
|
||||
if (usb_cdcacm_peek(&b, 1)==1)
|
||||
{
|
||||
return b;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void USBSerial::flush(void)
|
||||
{
|
||||
/*Roger Clark. Rather slow method. Need to improve this */
|
||||
uint8 b;
|
||||
while(usb_cdcacm_data_available())
|
||||
{
|
||||
this->read(&b, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 USBSerial::read(void *buf, uint32 len) {
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 rxed = 0;
|
||||
while (rxed < len) {
|
||||
rxed += usb_cdcacm_rx((uint8*)buf + rxed, len - rxed);
|
||||
}
|
||||
|
||||
return rxed;
|
||||
}
|
||||
|
||||
/* Blocks forever until 1 byte is received */
|
||||
int USBSerial::read(void) {
|
||||
uint8 b;
|
||||
/*
|
||||
this->read(&b, 1);
|
||||
return b;
|
||||
*/
|
||||
|
||||
if (usb_cdcacm_rx(&b, 1)==0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
uint8 USBSerial::pending(void) {
|
||||
return usb_cdcacm_get_pending();
|
||||
}
|
||||
|
||||
uint8 USBSerial::isConnected(void) {
|
||||
return usb_is_connected(USBLIB) && usb_is_configured(USBLIB);
|
||||
}
|
||||
|
||||
uint8 USBSerial::getDTR(void) {
|
||||
return usb_cdcacm_get_dtr();
|
||||
}
|
||||
|
||||
uint8 USBSerial::getRTS(void) {
|
||||
return usb_cdcacm_get_rts();
|
||||
}
|
||||
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
#ifdef SERIAL_USB
|
||||
USBSerial Serial;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bootloader hook implementations
|
||||
*/
|
||||
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
|
||||
enum reset_state_t {
|
||||
DTR_UNSET,
|
||||
DTR_HIGH,
|
||||
DTR_NEGEDGE,
|
||||
DTR_LOW
|
||||
};
|
||||
|
||||
static reset_state_t reset_state = DTR_UNSET;
|
||||
|
||||
static void ifaceSetupHook(unsigned hook, void *requestvp) {
|
||||
uint8 request = *(uint8*)requestvp;
|
||||
|
||||
// Ignore requests we're not interested in.
|
||||
if (request != USB_CDCACM_SET_CONTROL_LINE_STATE) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
// We need to see a negative edge on DTR before we start looking
|
||||
// for the in-band magic reset byte sequence.
|
||||
uint8 dtr = usb_cdcacm_get_dtr();
|
||||
switch (reset_state) {
|
||||
case DTR_UNSET:
|
||||
reset_state = dtr ? DTR_HIGH : DTR_LOW;
|
||||
break;
|
||||
case DTR_HIGH:
|
||||
reset_state = dtr ? DTR_HIGH : DTR_NEGEDGE;
|
||||
break;
|
||||
case DTR_NEGEDGE:
|
||||
reset_state = dtr ? DTR_HIGH : DTR_LOW;
|
||||
break;
|
||||
case DTR_LOW:
|
||||
reset_state = dtr ? DTR_HIGH : DTR_LOW;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(BOOTLOADER_robotis)
|
||||
uint8 dtr = usb_cdcacm_get_dtr();
|
||||
uint8 rts = usb_cdcacm_get_rts();
|
||||
|
||||
if (rts && !dtr) {
|
||||
reset_state = DTR_NEGEDGE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((usb_cdcacm_get_baud() == 1200) && (reset_state == DTR_NEGEDGE)) {
|
||||
iwdg_init(IWDG_PRE_4, 10);
|
||||
while (1);
|
||||
}
|
||||
}
|
||||
|
||||
#define RESET_DELAY 100000
|
||||
#ifdef SERIAL_USB
|
||||
static void wait_reset(void) {
|
||||
delay_us(RESET_DELAY);
|
||||
nvic_sys_reset();
|
||||
}
|
||||
#endif
|
||||
|
||||
#define STACK_TOP 0x20000800
|
||||
#define EXC_RETURN 0xFFFFFFF9
|
||||
#define DEFAULT_CPSR 0x61000000
|
||||
static void rxHook(unsigned hook, void *ignored) {
|
||||
/* FIXME this is mad buggy; we need a new reset sequence. E.g. NAK
|
||||
* after each RX means you can't reset if any bytes are waiting. */
|
||||
if (reset_state == DTR_NEGEDGE) {
|
||||
reset_state = DTR_LOW;
|
||||
|
||||
if (usb_cdcacm_data_available() >= 4) {
|
||||
// The magic reset sequence is "1EAF".
|
||||
#ifdef SERIAL_USB
|
||||
static const uint8 magic[4] = {'1', 'E', 'A', 'F'};
|
||||
#else
|
||||
#if defined(BOOTLOADER_robotis)
|
||||
static const uint8 magic[4] = {'C', 'M', '9', 'X'};
|
||||
#else
|
||||
static const uint8 magic[4] = {'1', 'E', 'A', 'F'};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uint8 chkBuf[4];
|
||||
|
||||
// Peek at the waiting bytes, looking for reset sequence,
|
||||
// bailing on mismatch.
|
||||
usb_cdcacm_peek_ex(chkBuf, usb_cdcacm_data_available() - 4, 4);
|
||||
for (unsigned i = 0; i < sizeof(magic); i++) {
|
||||
if (chkBuf[i] != magic[i]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
// Got the magic sequence -> reset, presumably into the bootloader.
|
||||
// Return address is wait_reset, but we must set the thumb bit.
|
||||
uintptr_t target = (uintptr_t)wait_reset | 0x1;
|
||||
asm volatile("mov r0, %[stack_top] \n\t" // Reset stack
|
||||
"mov sp, r0 \n\t"
|
||||
"mov r0, #1 \n\t"
|
||||
"mov r1, %[target_addr] \n\t"
|
||||
"mov r2, %[cpsr] \n\t"
|
||||
"push {r2} \n\t" // Fake xPSR
|
||||
"push {r1} \n\t" // PC target addr
|
||||
"push {r0} \n\t" // Fake LR
|
||||
"push {r0} \n\t" // Fake R12
|
||||
"push {r0} \n\t" // Fake R3
|
||||
"push {r0} \n\t" // Fake R2
|
||||
"push {r0} \n\t" // Fake R1
|
||||
"push {r0} \n\t" // Fake R0
|
||||
"mov lr, %[exc_return] \n\t"
|
||||
"bx lr"
|
||||
:
|
||||
: [stack_top] "r" (STACK_TOP),
|
||||
[target_addr] "r" (target),
|
||||
[exc_return] "r" (EXC_RETURN),
|
||||
[cpsr] "r" (DEFAULT_CPSR)
|
||||
: "r0", "r1", "r2");
|
||||
#endif
|
||||
|
||||
#if defined(BOOTLOADER_robotis)
|
||||
iwdg_init(IWDG_PRE_4, 10);
|
||||
#endif
|
||||
|
||||
/* Can't happen. */
|
||||
ASSERT_FAULT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BOARD_HAVE_SERIALUSB
|
|
@ -0,0 +1,81 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Wirish USB virtual serial port (SerialUSB).
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_USB_SERIAL_H_
|
||||
#define _WIRISH_USB_SERIAL_H_
|
||||
|
||||
#include "Print.h"
|
||||
#include "boards.h"
|
||||
#include "Stream.h"
|
||||
|
||||
/**
|
||||
* @brief Virtual serial terminal.
|
||||
*/
|
||||
class USBSerial : public Stream {
|
||||
public:
|
||||
USBSerial(void);
|
||||
|
||||
void begin(void);
|
||||
|
||||
// Roger Clark. Added dummy function so that existing Arduino sketches which specify baud rate will compile.
|
||||
void begin(unsigned long);
|
||||
void begin(unsigned long, uint8_t);
|
||||
void end(void);
|
||||
|
||||
operator bool() { return true; } // Roger Clark. This is needed because in cardinfo.ino it does if (!Serial) . It seems to be a work around for the Leonardo that we needed to implement just to be compliant with the API
|
||||
|
||||
virtual int available(void);// Changed to virtual
|
||||
|
||||
uint32 read(void *buf, uint32 len);
|
||||
// uint8 read(void);
|
||||
|
||||
// Roger Clark. added functions to support Arduino 1.0 API
|
||||
virtual int peek(void);
|
||||
virtual int read(void);
|
||||
int availableForWrite(void);
|
||||
virtual void flush(void);
|
||||
|
||||
|
||||
size_t write(uint8);
|
||||
size_t write(const char *str);
|
||||
size_t write(const void*, uint32);
|
||||
|
||||
uint8 getRTS();
|
||||
uint8 getDTR();
|
||||
uint8 isConnected();
|
||||
uint8 pending();
|
||||
};
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
extern USBSerial Serial;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef WiringPrivate_h
|
||||
#define WiringPrivate_h
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2015 Roger Clark
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
#ifndef _WIRISH_PULSE_H_
|
||||
#define _WIRISH_PULSE_H_
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
|
||||
uint32_t pulseIn( uint32_t ulPin, uint32_t ulState, uint32_t ulTimeout = 1000000L ) ;
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,102 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Main include file for the Wirish core.
|
||||
*
|
||||
* Includes most of Wirish, and (transitively or otherwise)
|
||||
* substantial pieces of libmaple proper.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_WIRISH_H_
|
||||
#define _WIRISH_WIRISH_H_
|
||||
|
||||
/*
|
||||
* 20141030. Roger Clark
|
||||
Added the block of includes up to avr/interrupt so that stdlib functions like memcpy would be included and could be used.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <WString.h>
|
||||
#include <avr/dtostrf.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include <libmaple/stm32.h>
|
||||
|
||||
#include <boards.h>
|
||||
#include <io.h>
|
||||
#include <bit_constants.h>
|
||||
#include <pwm.h>
|
||||
#include <ext_interrupts.h>
|
||||
#include <wirish_debug.h>
|
||||
#include <wirish_math.h>
|
||||
#include <wirish_time.h>
|
||||
#include <wirish_constants.h>
|
||||
#include <wiring_pulse.h>
|
||||
|
||||
#if STM32_MCU_SERIES == STM32_SERIES_F1 /* FIXME [0.0.13?] port to F2 */
|
||||
//#include <HardwareSPI.h>
|
||||
#endif
|
||||
|
||||
#include <HardwareSerial.h>
|
||||
#include <HardwareTimer.h>
|
||||
#include <usb_serial.h>
|
||||
#include <wirish_types.h>
|
||||
|
||||
#include <libmaple/libmaple.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define SS BOARD_SPI1_NSS_PIN
|
||||
#define MOSI BOARD_SPI1_MOSI_PIN
|
||||
#define MISO BOARD_SPI1_MISO_PIN
|
||||
#define SCK BOARD_SPI1_SCK_PIN
|
||||
|
||||
|
||||
typedef unsigned int word;
|
||||
// typedef uint16 word;// definition from Arduino website, now appears to be incorrect for 32 bit devices
|
||||
|
||||
/* Wiring macros and bit defines */
|
||||
|
||||
#define true 0x1
|
||||
#define false 0x0
|
||||
|
||||
#define lowByte(w) ((w) & 0xFF)
|
||||
#define highByte(w) (((w) >> 8) & 0xFF)
|
||||
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
|
||||
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
|
||||
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
|
||||
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : \
|
||||
bitClear(value, bit))
|
||||
#define bit(b) (1UL << (b))
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2011, 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/wirish_analog.cpp
|
||||
* @brief Wiring-style analogRead() implementation.
|
||||
*/
|
||||
|
||||
#include "io.h"
|
||||
#include <libmaple/adc.h>
|
||||
#include "boards.h"
|
||||
|
||||
/* Unlike Wiring and Arduino, this assumes that the pin's mode is set
|
||||
* to INPUT_ANALOG. That's faster, but it does require some extra work
|
||||
* on the user's part. Not too much, we think ;). */
|
||||
uint16 analogRead(uint8 pin) {
|
||||
const adc_dev *dev = PIN_MAP[pin].adc_device;
|
||||
if (dev == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return adc_read(dev, PIN_MAP[pin].adc_channel);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _WIRING_CONSTANTS_
|
||||
#define _WIRING_CONSTANTS_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
enum BitOrder {
|
||||
LSBFIRST = 0,
|
||||
MSBFIRST = 1
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/wirish_debug.h
|
||||
* @brief High level debug port configuration
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_WIRISH_DEBUG_H_
|
||||
#define _WIRISH_WIRISH_DEBUG_H_
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
|
||||
/**
|
||||
* @brief Disable the JTAG and Serial Wire (SW) debug ports.
|
||||
*
|
||||
* You can call this function in order to use the JTAG and SW debug
|
||||
* pins as ordinary GPIOs.
|
||||
*
|
||||
* @see enableDebugPorts()
|
||||
*/
|
||||
void disableDebugPorts(void);
|
||||
|
||||
/**
|
||||
* @brief Enable the JTAG and Serial Wire (SW) debug ports.
|
||||
*
|
||||
* After you call this function, the JTAG and SW debug pins will no
|
||||
* longer be usable as GPIOs.
|
||||
*
|
||||
* @see disableDebugPorts()
|
||||
*/
|
||||
void enableDebugPorts(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,97 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
* Arduino-compatible digital I/O implementation.
|
||||
*/
|
||||
|
||||
#include "io.h"
|
||||
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/timer.h>
|
||||
|
||||
#include "wirish_time.h"
|
||||
#include "boards.h"
|
||||
|
||||
uint32 digitalRead(uint8 pin) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return gpio_read_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit) ?
|
||||
HIGH : LOW;
|
||||
}
|
||||
|
||||
void digitalWrite(uint8 pin, uint8 val) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_write_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit, val);
|
||||
}
|
||||
|
||||
#if FALSE
|
||||
// Roger Clark. Deprecated these functions as they are not part of the standard Arduino API
|
||||
void togglePin(uint8 pin) {
|
||||
if (pin >= BOARD_NR_GPIO_PINS) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_toggle_bit(PIN_MAP[pin].gpio_device, PIN_MAP[pin].gpio_bit);
|
||||
}
|
||||
|
||||
#define BUTTON_DEBOUNCE_DELAY 1
|
||||
|
||||
uint8 isButtonPressed(uint8 pin, uint32 pressedLevel) {
|
||||
if (digitalRead(pin) == pressedLevel) {
|
||||
delay(BUTTON_DEBOUNCE_DELAY);
|
||||
while (digitalRead(pin) == pressedLevel)
|
||||
;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 waitForButtonPress(uint32 timeout) {
|
||||
uint32 start = millis();
|
||||
uint32 time;
|
||||
if (timeout == 0) {
|
||||
while (!isButtonPressed())
|
||||
;
|
||||
return true;
|
||||
}
|
||||
do {
|
||||
time = millis();
|
||||
/* properly handle wrap-around */
|
||||
if ((start > time && time + (0xffffffffU - start) > timeout) ||
|
||||
time - start > timeout) {
|
||||
return false;
|
||||
}
|
||||
} while (!isButtonPressed());
|
||||
return true;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Modified by LeafLabs, LLC.
|
||||
*
|
||||
* Part of the Wiring project - http://wiring.org.co Copyright (c)
|
||||
* 2004-06 Hernando Barragan Modified 13 August 2006, David A. Mellis
|
||||
* for Arduino - http://www.arduino.cc/
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*/
|
||||
|
||||
#include "stdlib.h"
|
||||
#include "wirish_math.h"
|
||||
|
||||
void randomSeed(unsigned int seed) {
|
||||
if (seed != 0) {
|
||||
srand(seed);
|
||||
}
|
||||
}
|
||||
|
||||
long random(long howbig) {
|
||||
if (howbig == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rand() % howbig;
|
||||
}
|
||||
|
||||
long random(long howsmall, long howbig) {
|
||||
if (howsmall >= howbig) {
|
||||
return howsmall;
|
||||
}
|
||||
|
||||
long diff = howbig - howsmall;
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/wirish_math.h
|
||||
* @brief Includes <math.h>; provides Wiring-compatible math routines.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_WIRISH_MATH_H_
|
||||
#define _WIRISH_WIRISH_MATH_H_
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize the pseudo-random number generator.
|
||||
* @param seed the number used to initialize the seed; cannot be zero.
|
||||
*/
|
||||
void randomSeed(unsigned int seed);
|
||||
|
||||
/**
|
||||
* @brief Generate a pseudo-random number with upper bound.
|
||||
* @param max An upper bound on the returned value, exclusive.
|
||||
* @return A pseudo-random number in the range [0,max).
|
||||
* @see randomSeed()
|
||||
*/
|
||||
long random(long max);
|
||||
|
||||
/**
|
||||
* @brief Generate a pseudo-random number with lower and upper bounds.
|
||||
* @param min Lower bound on the returned value, inclusive.
|
||||
* @param max Upper bound on the returned value, exclusive.
|
||||
* @return A pseudo-random number in the range [min, max).
|
||||
* @see randomSeed()
|
||||
*/
|
||||
long random(long min, long max);
|
||||
|
||||
/**
|
||||
* @brief Remap a number from one range to another.
|
||||
*
|
||||
* That is, a value equal to fromStart gets mapped to toStart, a value
|
||||
* of fromEnd to toEnd, and other values are mapped proportionately.
|
||||
*
|
||||
* Does not constrain value to lie within [fromStart, fromEnd].
|
||||
*
|
||||
* If a "start" value is larger than its corresponding "end", the
|
||||
* ranges are reversed, so map(n, 1, 10, 10, 1) would reverse the
|
||||
* range [1,10].
|
||||
*
|
||||
* Negative numbers may appear as any argument.
|
||||
*
|
||||
* @param value the value to map.
|
||||
* @param fromStart the beginning of the value's current range.
|
||||
* @param fromEnd the end of the value's current range.
|
||||
* @param toStart the beginning of the value's mapped range.
|
||||
* @param toEnd the end of the value's mapped range.
|
||||
* @return the mapped value.
|
||||
*/
|
||||
static inline long map(long value, long fromStart, long fromEnd,
|
||||
long toStart, long toEnd) {
|
||||
return (value - fromStart) * (toEnd - toStart) / (fromEnd - fromStart) +
|
||||
toStart;
|
||||
}
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define HALF_PI 1.5707963267948966192313216916398
|
||||
#define TWO_PI 6.283185307179586476925286766559
|
||||
#define DEG_TO_RAD 0.017453292519943295769236907684886
|
||||
#define RAD_TO_DEG 57.295779513082320876798154814105
|
||||
|
||||
|
||||
/*
|
||||
* Roger Clark 20141113
|
||||
*
|
||||
* Added BitOrder definition from SAM wiring_constants.h, as its needed for SPI
|
||||
* as Maple doesn't have a wiring_constants file (though it probably should have in the long term to make it more compatible with the Arduino 1.0 + API
|
||||
* also added definition for EULER and SERIAL and DISPLAY, also from the same SAM header
|
||||
*/
|
||||
|
||||
#define EULER 2.718281828459045235360287471352
|
||||
#define SERIAL 0x0
|
||||
#define DISPLAY 0x1
|
||||
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
#define max(a,b) ((a)>(b)?(a):(b))
|
||||
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))
|
||||
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
|
||||
#define radians(deg) ((deg)*DEG_TO_RAD)
|
||||
#define degrees(rad) ((rad)*RAD_TO_DEG)
|
||||
#define sq(x) ((x)*(x))
|
||||
|
||||
/* undefine stdlib's abs if encountered */
|
||||
#ifdef abs
|
||||
#undef abs
|
||||
#endif
|
||||
#define abs(x) (((x) > 0) ? (x) : -(x))
|
||||
|
||||
/* Following are duplicate declarations (with Doxygen comments) for
|
||||
* some of the math.h functions; this is for the convenience of the
|
||||
* Sphinx docs.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Compute the cosine of an angle, in radians.
|
||||
* @param x The radian measure of the angle.
|
||||
* @return The cosine of x. This value will be between -1 and 1.
|
||||
*/
|
||||
double cos(double x);
|
||||
|
||||
/**
|
||||
* Compute the sine of an angle, in radians.
|
||||
* @param x The radian measure of the angle.
|
||||
* @return The sine of x. This value will be between -1 and 1.
|
||||
*/
|
||||
double sin(double x);
|
||||
|
||||
/**
|
||||
* Compute the tangent of an angle, in radians.
|
||||
* @param x The radian measure of the angle.
|
||||
* @return The tangent of x. There are no limits on the return value
|
||||
* of this function.
|
||||
*/
|
||||
double tan(double x);
|
||||
|
||||
/**
|
||||
* Compute the square root of a number.
|
||||
* @param x The number whose square root to find. This value cannot
|
||||
* be negative.
|
||||
* @return The square root of x. The return value is never negative.
|
||||
*/
|
||||
double sqrt(double x);
|
||||
|
||||
/**
|
||||
* Compute an exponentiation.
|
||||
* @param x the base. This value cannot be zero if y <= 0. This value
|
||||
* cannot be negative if y is not an integral value.
|
||||
* @param y the exponent.
|
||||
* @return x raised to the power y.
|
||||
*/
|
||||
double pow(double x, double y);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2012 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
#include "wirish.h"
|
||||
|
||||
void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value) {
|
||||
digitalWrite(clockPin, LOW);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
int bit = bitOrder == LSBFIRST ? i : (7 - i);
|
||||
digitalWrite(dataPin, (value >> bit) & 0x1);
|
||||
gpio_toggle_bit(PIN_MAP[clockPin].gpio_device, PIN_MAP[clockPin].gpio_bit);// togglePin(clockPin);
|
||||
gpio_toggle_bit(PIN_MAP[clockPin].gpio_device, PIN_MAP[clockPin].gpio_bit);// togglePin(clockPin);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @brief Delay implementation.
|
||||
*/
|
||||
|
||||
#include "wirish_time.h"
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <libmaple/delay.h>
|
||||
|
||||
void delay(unsigned long ms) {
|
||||
uint32 i;
|
||||
for (i = 0; i < ms; i++) {
|
||||
delayMicroseconds(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void delayMicroseconds(uint32 us) {
|
||||
delay_us(us);
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Perry Hung.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/wirish_time.h
|
||||
* @brief Timing and delay functions.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_WIRISH_TIME_H_
|
||||
#define _WIRISH_WIRISH_TIME_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <libmaple/systick.h>
|
||||
|
||||
#include <boards.h>
|
||||
|
||||
/**
|
||||
* Returns time (in milliseconds) since the beginning of program
|
||||
* execution. On overflow, restarts at 0.
|
||||
* @see micros()
|
||||
*/
|
||||
static inline uint32 millis(void) {
|
||||
return systick_uptime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns time (in microseconds) since the beginning of program
|
||||
* execution. On overflow, restarts at 0.
|
||||
* @see millis()
|
||||
*/
|
||||
static inline uint32 micros(void) {
|
||||
uint32 ms;
|
||||
uint32 cycle_cnt;
|
||||
|
||||
do {
|
||||
ms = millis();
|
||||
cycle_cnt = systick_get_count();
|
||||
asm volatile("nop"); //allow interrupt to fire
|
||||
asm volatile("nop");
|
||||
} while (ms != millis());
|
||||
|
||||
#define US_PER_MS 1000
|
||||
/* SYSTICK_RELOAD_VAL is 1 less than the number of cycles it
|
||||
* actually takes to complete a SysTick reload */
|
||||
return ((ms * US_PER_MS) +
|
||||
(SYSTICK_RELOAD_VAL + 1 - cycle_cnt) / CYCLES_PER_MICROSECOND);
|
||||
#undef US_PER_MS
|
||||
}
|
||||
|
||||
/**
|
||||
* Delay for at least the given number of milliseconds.
|
||||
*
|
||||
* Interrupts, etc. may cause the actual number of milliseconds to
|
||||
* exceed ms. However, this function will return no less than ms
|
||||
* milliseconds from the time it is called.
|
||||
*
|
||||
* @param ms the number of milliseconds to delay.
|
||||
* @see delayMicroseconds()
|
||||
*/
|
||||
void delay(unsigned long ms);
|
||||
|
||||
/**
|
||||
* Delay for at least the given number of microseconds.
|
||||
*
|
||||
* Interrupts, etc. may cause the actual number of microseconds to
|
||||
* exceed us. However, this function will return no less than us
|
||||
* microseconds from the time it is called.
|
||||
*
|
||||
* @param us the number of microseconds to delay.
|
||||
* @see delay()
|
||||
*/
|
||||
void delayMicroseconds(uint32 us);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,69 @@
|
|||
/******************************************************************************
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2011 LeafLabs, LLC.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*****************************************************************************/
|
||||
|
||||
/**
|
||||
* @file wirish/include/wirish/wirish_types.h
|
||||
* @author Marti Bolivar <mbolivar@leaflabs.com>
|
||||
* @brief Wirish library type definitions.
|
||||
*/
|
||||
|
||||
#ifndef _WIRISH_WIRISH_TYPES_H_
|
||||
#define _WIRISH_WIRISH_TYPES_H_
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include <libmaple/timer.h>
|
||||
#include <libmaple/adc.h>
|
||||
|
||||
/**
|
||||
* Invalid stm32_pin_info adc_channel value.
|
||||
* @see stm32_pin_info
|
||||
*/
|
||||
#define ADCx 0xFF
|
||||
|
||||
/**
|
||||
* @brief Stores STM32-specific information related to a given Maple pin.
|
||||
* @see PIN_MAP
|
||||
*/
|
||||
typedef struct stm32_pin_info {
|
||||
gpio_dev *gpio_device; /**< Maple pin's GPIO device */
|
||||
timer_dev *timer_device; /**< Pin's timer device, if any. */
|
||||
const adc_dev *adc_device; /**< ADC device, if any. */
|
||||
uint8 gpio_bit; /**< Pin's GPIO port bit. */
|
||||
uint8 timer_channel; /**< Timer channel, or 0 if none. */
|
||||
uint8 adc_channel; /**< Pin ADC channel, or ADCx if none. */
|
||||
uint8 pinMode; /**< mode specific by pinMode call (Roger Clark added to optimize compatibility with Arduino API*/
|
||||
} stm32_pin_info;
|
||||
|
||||
/**
|
||||
* Variable attribute, instructs the linker to place the marked
|
||||
* variable in Flash instead of RAM. */
|
||||
#define __FLASH__ __attr_flash
|
||||
|
||||
typedef bool boolean;
|
||||
typedef uint8 byte;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,815 @@
|
|||
/*
|
||||
This is the core graphics library for all our displays, providing a common
|
||||
set of graphics primitives (points, lines, circles, etc.). It needs to be
|
||||
paired with a hardware-specific library for each display device we carry
|
||||
(to handle the lower-level functions).
|
||||
|
||||
Adafruit invests time and resources providing this open source code, please
|
||||
support Adafruit & open-source hardware by purchasing products from Adafruit!
|
||||
|
||||
Copyright (c) 2013 Adafruit Industries. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "Adafruit_GFX_AS.h"
|
||||
|
||||
#ifdef LOAD_GLCD
|
||||
#include "glcdfont.c"
|
||||
#endif
|
||||
|
||||
#ifdef LOAD_FONT2
|
||||
#include "Font16.h"
|
||||
#endif
|
||||
|
||||
#ifdef LOAD_FONT4
|
||||
#include "Font32.h"
|
||||
#endif
|
||||
|
||||
#ifdef LOAD_FONT6
|
||||
#include "Font64.h"
|
||||
#endif
|
||||
|
||||
#ifdef LOAD_FONT7
|
||||
#include "Font7s.h"
|
||||
#endif
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#else
|
||||
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
|
||||
#endif
|
||||
|
||||
Adafruit_GFX::Adafruit_GFX(int16_t w, int16_t h):
|
||||
WIDTH(w), HEIGHT(h)
|
||||
{
|
||||
_width = WIDTH;
|
||||
_height = HEIGHT;
|
||||
rotation = 0;
|
||||
cursor_y = cursor_x = 0;
|
||||
textsize = 1;
|
||||
textcolor = textbgcolor = 0xFFFF;
|
||||
wrap = true;
|
||||
}
|
||||
|
||||
// Draw a circle outline
|
||||
void Adafruit_GFX::drawCircle(int16_t x0, int16_t y0, int16_t r,
|
||||
uint16_t color) {
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
drawPixel(x0 , y0+r, color);
|
||||
drawPixel(x0 , y0-r, color);
|
||||
drawPixel(x0+r, y0 , color);
|
||||
drawPixel(x0-r, y0 , color);
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
drawPixel(x0 + x, y0 + y, color);
|
||||
drawPixel(x0 - x, y0 + y, color);
|
||||
drawPixel(x0 + x, y0 - y, color);
|
||||
drawPixel(x0 - x, y0 - y, color);
|
||||
drawPixel(x0 + y, y0 + x, color);
|
||||
drawPixel(x0 - y, y0 + x, color);
|
||||
drawPixel(x0 + y, y0 - x, color);
|
||||
drawPixel(x0 - y, y0 - x, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawCircleHelper( int16_t x0, int16_t y0,
|
||||
int16_t r, uint8_t cornername, uint16_t color) {
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
if (cornername & 0x4) {
|
||||
drawPixel(x0 + x, y0 + y, color);
|
||||
drawPixel(x0 + y, y0 + x, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
drawPixel(x0 + x, y0 - y, color);
|
||||
drawPixel(x0 + y, y0 - x, color);
|
||||
}
|
||||
if (cornername & 0x8) {
|
||||
drawPixel(x0 - y, y0 + x, color);
|
||||
drawPixel(x0 - x, y0 + y, color);
|
||||
}
|
||||
if (cornername & 0x1) {
|
||||
drawPixel(x0 - y, y0 - x, color);
|
||||
drawPixel(x0 - x, y0 - y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_GFX::fillCircle(int16_t x0, int16_t y0, int16_t r,
|
||||
uint16_t color) {
|
||||
drawFastVLine(x0, y0-r, 2*r+1, color);
|
||||
fillCircleHelper(x0, y0, r, 3, 0, color);
|
||||
}
|
||||
|
||||
// Used to do circles and roundrects
|
||||
void Adafruit_GFX::fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
|
||||
uint8_t cornername, int16_t delta, uint16_t color) {
|
||||
|
||||
int16_t f = 1 - r;
|
||||
int16_t ddF_x = 1;
|
||||
int16_t ddF_y = -2 * r;
|
||||
int16_t x = 0;
|
||||
int16_t y = r;
|
||||
|
||||
while (x<y) {
|
||||
if (f >= 0) {
|
||||
y--;
|
||||
ddF_y += 2;
|
||||
f += ddF_y;
|
||||
}
|
||||
x++;
|
||||
ddF_x += 2;
|
||||
f += ddF_x;
|
||||
|
||||
if (cornername & 0x1) {
|
||||
drawFastVLine(x0+x, y0-y, 2*y+1+delta, color);
|
||||
drawFastVLine(x0+y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
if (cornername & 0x2) {
|
||||
drawFastVLine(x0-x, y0-y, 2*y+1+delta, color);
|
||||
drawFastVLine(x0-y, y0-x, 2*x+1+delta, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Bresenham's algorithm - thx wikpedia
|
||||
void Adafruit_GFX::drawLine(int16_t x0, int16_t y0,
|
||||
int16_t x1, int16_t y1,
|
||||
uint16_t color) {
|
||||
int16_t steep = abs(y1 - y0) > abs(x1 - x0);
|
||||
if (steep) {
|
||||
swap(x0, y0);
|
||||
swap(x1, y1);
|
||||
}
|
||||
|
||||
if (x0 > x1) {
|
||||
swap(x0, x1);
|
||||
swap(y0, y1);
|
||||
}
|
||||
|
||||
int16_t dx, dy;
|
||||
dx = x1 - x0;
|
||||
dy = abs(y1 - y0);
|
||||
|
||||
int16_t err = dx / 2;
|
||||
int16_t ystep;
|
||||
|
||||
if (y0 < y1) {
|
||||
ystep = 1;
|
||||
} else {
|
||||
ystep = -1;
|
||||
}
|
||||
|
||||
for (; x0<=x1; x0++) {
|
||||
if (steep) {
|
||||
drawPixel(y0, x0, color);
|
||||
} else {
|
||||
drawPixel(x0, y0, color);
|
||||
}
|
||||
err -= dy;
|
||||
if (err < 0) {
|
||||
y0 += ystep;
|
||||
err += dx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Draw a rectangle
|
||||
void Adafruit_GFX::drawRect(int16_t x, int16_t y,
|
||||
int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
drawFastHLine(x, y, w, color);
|
||||
drawFastHLine(x, y+h-1, w, color);
|
||||
drawFastVLine(x, y, h, color);
|
||||
drawFastVLine(x+w-1, y, h, color);
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawFastVLine(int16_t x, int16_t y,
|
||||
int16_t h, uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
drawLine(x, y, x, y+h-1, color);
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawFastHLine(int16_t x, int16_t y,
|
||||
int16_t w, uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
drawLine(x, y, x+w-1, y, color);
|
||||
}
|
||||
|
||||
void Adafruit_GFX::fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
// Update in subclasses if desired!
|
||||
for (int16_t i=x; i<x+w; i++) {
|
||||
drawFastVLine(i, y, h, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_GFX::fillScreen(uint16_t color) {
|
||||
fillRect(0, 0, _width, _height, color);
|
||||
}
|
||||
|
||||
// Draw a rounded rectangle
|
||||
void Adafruit_GFX::drawRoundRect(int16_t x, int16_t y, int16_t w,
|
||||
int16_t h, int16_t r, uint16_t color) {
|
||||
// smarter version
|
||||
drawFastHLine(x+r , y , w-2*r, color); // Top
|
||||
drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
|
||||
drawFastVLine(x , y+r , h-2*r, color); // Left
|
||||
drawFastVLine(x+w-1, y+r , h-2*r, color); // Right
|
||||
// draw four corners
|
||||
drawCircleHelper(x+r , y+r , r, 1, color);
|
||||
drawCircleHelper(x+w-r-1, y+r , r, 2, color);
|
||||
drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
|
||||
drawCircleHelper(x+r , y+h-r-1, r, 8, color);
|
||||
}
|
||||
|
||||
// Fill a rounded rectangle
|
||||
void Adafruit_GFX::fillRoundRect(int16_t x, int16_t y, int16_t w,
|
||||
int16_t h, int16_t r, uint16_t color) {
|
||||
// smarter version
|
||||
fillRect(x+r, y, w-2*r, h, color);
|
||||
|
||||
// draw four corners
|
||||
fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
|
||||
fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
|
||||
}
|
||||
|
||||
// Draw a triangle
|
||||
void Adafruit_GFX::drawTriangle(int16_t x0, int16_t y0,
|
||||
int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color) {
|
||||
drawLine(x0, y0, x1, y1, color);
|
||||
drawLine(x1, y1, x2, y2, color);
|
||||
drawLine(x2, y2, x0, y0, color);
|
||||
}
|
||||
|
||||
// Fill a triangle
|
||||
void Adafruit_GFX::fillTriangle ( int16_t x0, int16_t y0,
|
||||
int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color) {
|
||||
|
||||
int16_t a, b, y, last;
|
||||
|
||||
// Sort coordinates by Y order (y2 >= y1 >= y0)
|
||||
if (y0 > y1) {
|
||||
swap(y0, y1); swap(x0, x1);
|
||||
}
|
||||
if (y1 > y2) {
|
||||
swap(y2, y1); swap(x2, x1);
|
||||
}
|
||||
if (y0 > y1) {
|
||||
swap(y0, y1); swap(x0, x1);
|
||||
}
|
||||
|
||||
if(y0 == y2) { // Handle awkward all-on-same-line case as its own thing
|
||||
a = b = x0;
|
||||
if(x1 < a) a = x1;
|
||||
else if(x1 > b) b = x1;
|
||||
if(x2 < a) a = x2;
|
||||
else if(x2 > b) b = x2;
|
||||
drawFastHLine(a, y0, b-a+1, color);
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t
|
||||
dx01 = x1 - x0,
|
||||
dy01 = y1 - y0,
|
||||
dx02 = x2 - x0,
|
||||
dy02 = y2 - y0,
|
||||
dx12 = x2 - x1,
|
||||
dy12 = y2 - y1,
|
||||
sa = 0,
|
||||
sb = 0;
|
||||
|
||||
// For upper part of triangle, find scanline crossings for segments
|
||||
// 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
|
||||
// is included here (and second loop will be skipped, avoiding a /0
|
||||
// error there), otherwise scanline y1 is skipped here and handled
|
||||
// in the second loop...which also avoids a /0 error here if y0=y1
|
||||
// (flat-topped triangle).
|
||||
if(y1 == y2) last = y1; // Include y1 scanline
|
||||
else last = y1-1; // Skip it
|
||||
|
||||
for(y=y0; y<=last; y++) {
|
||||
a = x0 + sa / dy01;
|
||||
b = x0 + sb / dy02;
|
||||
sa += dx01;
|
||||
sb += dx02;
|
||||
/* longhand:
|
||||
a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
|
||||
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
|
||||
*/
|
||||
if(a > b) swap(a,b);
|
||||
drawFastHLine(a, y, b-a+1, color);
|
||||
}
|
||||
|
||||
// For lower part of triangle, find scanline crossings for segments
|
||||
// 0-2 and 1-2. This loop is skipped if y1=y2.
|
||||
sa = dx12 * (y - y1);
|
||||
sb = dx02 * (y - y0);
|
||||
for(; y<=y2; y++) {
|
||||
a = x1 + sa / dy12;
|
||||
b = x0 + sb / dy02;
|
||||
sa += dx12;
|
||||
sb += dx02;
|
||||
/* longhand:
|
||||
a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
|
||||
b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
|
||||
*/
|
||||
if(a > b) swap(a,b);
|
||||
drawFastHLine(a, y, b-a+1, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Adafruit_GFX::drawBitmap(int16_t x, int16_t y,
|
||||
const uint8_t *bitmap, int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
|
||||
int16_t i, j, byteWidth = (w + 7) / 8;
|
||||
|
||||
for(j=0; j<h; j++) {
|
||||
for(i=0; i<w; i++ ) {
|
||||
if(pgm_read_byte(bitmap + j * byteWidth + i / 8) & (128 >> (i & 7))) {
|
||||
drawPixel(x+i, y+j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#if ARDUINO >= 100
|
||||
size_t Adafruit_GFX::write(uint8_t c) {
|
||||
//#else
|
||||
//void Adafruit_GFX::write(uint8_t c) {
|
||||
//#endif
|
||||
if (c == '\n') {
|
||||
cursor_y += textsize*8;
|
||||
cursor_x = 0;
|
||||
} else if (c == '\r') {
|
||||
// skip em
|
||||
} else {
|
||||
drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
|
||||
cursor_x += textsize*6;
|
||||
if (wrap && (cursor_x > (_width - textsize*6))) {
|
||||
cursor_y += textsize*8;
|
||||
cursor_x = 0;
|
||||
}
|
||||
}
|
||||
//#if ARDUINO >= 100
|
||||
return 1;
|
||||
//#endif
|
||||
}
|
||||
|
||||
// Draw a character
|
||||
void Adafruit_GFX::drawChar(int16_t x, int16_t y, unsigned char c,
|
||||
uint16_t color, uint16_t bg, uint8_t size) {
|
||||
#ifdef LOAD_GLCD
|
||||
if((x >= _width) || // Clip right
|
||||
(y >= _height) || // Clip bottom
|
||||
((x + 6 * size - 1) < 0) || // Clip left
|
||||
((y + 8 * size - 1) < 0)) // Clip top
|
||||
return;
|
||||
|
||||
for (int8_t i=0; i<6; i++ ) {
|
||||
uint8_t line;
|
||||
if (i == 5)
|
||||
line = 0x0;
|
||||
else
|
||||
line = pgm_read_byte(font+(c*5)+i);
|
||||
for (int8_t j = 0; j<8; j++) {
|
||||
if (line & 0x1) {
|
||||
if (size == 1) // default size
|
||||
drawPixel(x+i, y+j, color);
|
||||
else { // big size
|
||||
fillRect(x+(i*size), y+(j*size), size, size, color);
|
||||
}
|
||||
} else if (bg != color) {
|
||||
if (size == 1) // default size
|
||||
drawPixel(x+i, y+j, bg);
|
||||
else { // big size
|
||||
fillRect(x+i*size, y+j*size, size, size, bg);
|
||||
}
|
||||
}
|
||||
line >>= 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Adafruit_GFX::setCursor(int16_t x, int16_t y) {
|
||||
cursor_x = x;
|
||||
cursor_y = y;
|
||||
}
|
||||
|
||||
void Adafruit_GFX::setTextSize(uint8_t s) {
|
||||
textsize = (s > 0) ? s : 1;
|
||||
}
|
||||
|
||||
void Adafruit_GFX::setTextColor(uint16_t c) {
|
||||
// For 'transparent' background, we'll set the bg
|
||||
// to the same as fg instead of using a flag
|
||||
textcolor = textbgcolor = c;
|
||||
}
|
||||
|
||||
void Adafruit_GFX::setTextColor(uint16_t c, uint16_t b) {
|
||||
textcolor = c;
|
||||
textbgcolor = b;
|
||||
}
|
||||
|
||||
void Adafruit_GFX::setTextWrap(boolean w) {
|
||||
wrap = w;
|
||||
}
|
||||
|
||||
uint8_t Adafruit_GFX::getRotation(void) {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
void Adafruit_GFX::setRotation(uint8_t x) {
|
||||
rotation = (x & 3);
|
||||
switch(rotation) {
|
||||
case 0:
|
||||
case 2:
|
||||
_width = WIDTH;
|
||||
_height = HEIGHT;
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
_width = HEIGHT;
|
||||
_height = WIDTH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the size of the display (per current rotation)
|
||||
int16_t Adafruit_GFX::width(void) {
|
||||
return _width;
|
||||
}
|
||||
|
||||
int16_t Adafruit_GFX::height(void) {
|
||||
return _height;
|
||||
}
|
||||
|
||||
void Adafruit_GFX::invertDisplay(boolean i) {
|
||||
// Do nothing, must be subclassed if supported
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawUnicode
|
||||
** Descriptions: draw a unicode
|
||||
***************************************************************************************/
|
||||
int16_t Adafruit_GFX::drawUnicode(uint16_t uniCode, int16_t x, int16_t y, int16_t size)
|
||||
{
|
||||
|
||||
if (size) uniCode -= 32;
|
||||
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
uint32_t flash_address = 0;
|
||||
int16_t gap = 0;
|
||||
|
||||
// if (size == 1) {
|
||||
// flash_address = pgm_read_dword(&chrtbl_f8[uniCode]);
|
||||
// width = pgm_read_byte(widtbl_f8+uniCode);
|
||||
// height = chr_hgt_f8;
|
||||
// gap = 1;
|
||||
// }
|
||||
#ifdef LOAD_FONT2
|
||||
if (size == 2) {
|
||||
flash_address = pgm_read_dword(&chrtbl_f16[uniCode]);
|
||||
width = pgm_read_byte(widtbl_f16+uniCode);
|
||||
height = chr_hgt_f16;
|
||||
gap = 1;
|
||||
}
|
||||
#endif
|
||||
// if (size == 3) {
|
||||
// flash_address = pgm_read_dword(&chrtbl_f24[uniCode]);
|
||||
// width = pgm_read_byte(widtbl_f24+uniCode);
|
||||
// height = chr_hgt_f24;
|
||||
// gap = 0;
|
||||
// }
|
||||
#ifdef LOAD_FONT4
|
||||
if (size == 4) {
|
||||
flash_address = pgm_read_dword(&chrtbl_f32[uniCode]);
|
||||
width = pgm_read_byte(widtbl_f32+uniCode);
|
||||
height = chr_hgt_f32;
|
||||
gap = -3;
|
||||
}
|
||||
#endif
|
||||
// if (size == 5) {
|
||||
// flash_address = pgm_read_dword(&chrtbl_f48[uniCode]);
|
||||
// width = pgm_read_byte(widtbl_f48+uniCode);
|
||||
// height = chr_hgt_f48;
|
||||
// gap = -3;
|
||||
// }
|
||||
#ifdef LOAD_FONT6
|
||||
if (size == 6) {
|
||||
flash_address = pgm_read_dword(&chrtbl_f64[uniCode]);
|
||||
width = pgm_read_byte(widtbl_f64+uniCode);
|
||||
height = chr_hgt_f64;
|
||||
gap = -3;
|
||||
}
|
||||
#endif
|
||||
#ifdef LOAD_FONT7
|
||||
if (size == 7) {
|
||||
flash_address = pgm_read_dword(&chrtbl_f7s[uniCode]);
|
||||
width = pgm_read_byte(widtbl_f7s+uniCode);
|
||||
height = chr_hgt_f7s;
|
||||
gap = 2;
|
||||
}
|
||||
#endif
|
||||
|
||||
int16_t w = (width+7)/8;
|
||||
int16_t pX = 0;
|
||||
int16_t pY = y;
|
||||
int16_t color = 0;
|
||||
byte line = 0;
|
||||
|
||||
//fillRect(x,pY,width+gap,height,textbgcolor);
|
||||
|
||||
for(int16_t i=0; i<height; i++)
|
||||
{
|
||||
if (textcolor != textbgcolor) {
|
||||
if (textsize == 1) drawFastHLine(x, pY, width+gap, textbgcolor);
|
||||
else fillRect(x, pY, (width+gap)*textsize, textsize, textbgcolor);
|
||||
}
|
||||
for (int16_t k = 0;k < w; k++)
|
||||
{
|
||||
line = pgm_read_byte(flash_address+w*i+k);
|
||||
if(line) {
|
||||
if (textsize==1){
|
||||
pX = x + k*8;
|
||||
if(line & 0x80) drawPixel(pX, pY, textcolor);
|
||||
if(line & 0x40) drawPixel(pX+1, pY, textcolor);
|
||||
if(line & 0x20) drawPixel(pX+2, pY, textcolor);
|
||||
if(line & 0x10) drawPixel(pX+3, pY, textcolor);
|
||||
if(line & 0x8) drawPixel(pX+4, pY, textcolor);
|
||||
if(line & 0x4) drawPixel(pX+5, pY, textcolor);
|
||||
if(line & 0x2) drawPixel(pX+6, pY, textcolor);
|
||||
if(line & 0x1) drawPixel(pX+7, pY, textcolor);
|
||||
}
|
||||
else {
|
||||
pX = x + k*8*textsize;
|
||||
if(line & 0x80) fillRect(pX, pY, textsize, textsize, textcolor);
|
||||
if(line & 0x40) fillRect(pX+textsize, pY, textsize, textsize, textcolor);
|
||||
if(line & 0x20) fillRect(pX+2*textsize, pY, textsize, textsize, textcolor);
|
||||
if(line & 0x10) fillRect(pX+3*textsize, pY, textsize, textsize, textcolor);
|
||||
if(line & 0x8) fillRect(pX+4*textsize, pY, textsize, textsize, textcolor);
|
||||
if(line & 0x4) fillRect(pX+5*textsize, pY, textsize, textsize, textcolor);
|
||||
if(line & 0x2) fillRect(pX+6*textsize, pY, textsize, textsize, textcolor);
|
||||
if(line & 0x1) fillRect(pX+7*textsize, pY, textsize, textsize, textcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
pY+=textsize;
|
||||
}
|
||||
return (width+gap)*textsize; // x +
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawNumber unsigned with size
|
||||
** Descriptions: drawNumber
|
||||
***************************************************************************************/
|
||||
int16_t Adafruit_GFX::drawNumber(long long_num,int16_t poX, int16_t poY, int16_t size)
|
||||
{
|
||||
char tmp[10];
|
||||
if (long_num < 0) sprintf(tmp, "%li", long_num);
|
||||
else sprintf(tmp, "%lu", long_num);
|
||||
return drawString(tmp, poX, poY, size);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawChar
|
||||
** Descriptions: draw char
|
||||
***************************************************************************************/
|
||||
int16_t Adafruit_GFX::drawChar(char c, int16_t x, int16_t y, int16_t size)
|
||||
{
|
||||
return drawUnicode(c, x, y, size);
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawString
|
||||
** Descriptions: draw string
|
||||
***************************************************************************************/
|
||||
int16_t Adafruit_GFX::drawString(char *string, int16_t poX, int16_t poY, int16_t size)
|
||||
{
|
||||
int16_t sumX = 0;
|
||||
|
||||
while(*string)
|
||||
{
|
||||
int16_t xPlus = drawChar(*string, poX, poY, size);
|
||||
sumX += xPlus;
|
||||
*string++;
|
||||
poX += xPlus; /* Move cursor right */
|
||||
}
|
||||
return sumX;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawCentreString
|
||||
** Descriptions: draw string across centre
|
||||
***************************************************************************************/
|
||||
int16_t Adafruit_GFX::drawCentreString(char *string, int16_t dX, int16_t poY, int16_t size)
|
||||
{
|
||||
int16_t sumX = 0;
|
||||
int16_t len = 0;
|
||||
char *pointer = string;
|
||||
char ascii;
|
||||
|
||||
while(*pointer)
|
||||
{
|
||||
ascii = *pointer;
|
||||
//if (size==0)len += 1+pgm_read_byte(widtbl_log+ascii);
|
||||
//if (size==1)len += 1+pgm_read_byte(widtbl_f8+ascii-32);
|
||||
#ifdef LOAD_FONT2
|
||||
if (size==2)len += 1+pgm_read_byte(widtbl_f16+ascii-32);
|
||||
#endif
|
||||
//if (size==3)len += 1+pgm_read_byte(widtbl_f48+ascii-32)/2;
|
||||
#ifdef LOAD_FONT4
|
||||
if (size==4)len += pgm_read_byte(widtbl_f32+ascii-32)-3;
|
||||
#endif
|
||||
//if (size==5) len += pgm_read_byte(widtbl_f48+ascii-32)-3;
|
||||
#ifdef LOAD_FONT6
|
||||
if (size==6) len += pgm_read_byte(widtbl_f64+ascii-32)-3;
|
||||
#endif
|
||||
#ifdef LOAD_FONT7
|
||||
if (size==7) len += pgm_read_byte(widtbl_f7s+ascii-32)+2;
|
||||
#endif
|
||||
*pointer++;
|
||||
}
|
||||
len = len*textsize;
|
||||
int16_t poX = dX - len/2;
|
||||
|
||||
if (poX < 0) poX = 0;
|
||||
|
||||
while(*string)
|
||||
{
|
||||
|
||||
int16_t xPlus = drawChar(*string, poX, poY, size);
|
||||
sumX += xPlus;
|
||||
*string++;
|
||||
poX += xPlus; /* Move cursor right */
|
||||
}
|
||||
|
||||
return sumX;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawRightString
|
||||
** Descriptions: draw string right justified
|
||||
***************************************************************************************/
|
||||
int16_t Adafruit_GFX::drawRightString(char *string, int16_t dX, int16_t poY, int16_t size)
|
||||
{
|
||||
int16_t sumX = 0;
|
||||
int16_t len = 0;
|
||||
char *pointer = string;
|
||||
char ascii;
|
||||
|
||||
while(*pointer)
|
||||
{
|
||||
ascii = *pointer;
|
||||
//if (size==0)len += 1+pgm_read_byte(widtbl_log+ascii);
|
||||
//if (size==1)len += 1+pgm_read_byte(widtbl_f8+ascii-32);
|
||||
#ifdef LOAD_FONT2
|
||||
if (size==2)len += 1+pgm_read_byte(widtbl_f16+ascii-32);
|
||||
#endif
|
||||
//if (size==3)len += 1+pgm_read_byte(widtbl_f48+ascii-32)/2;
|
||||
#ifdef LOAD_FONT4
|
||||
//if (size==4)len += pgm_read_byte(widtbl_f32+ascii-32)-3;
|
||||
if (size==4)len += pgm_read_byte(widtbl_f32+ascii-32);
|
||||
#endif
|
||||
//if (size==5) len += pgm_read_byte(widtbl_f48+ascii-32)-3;
|
||||
#ifdef LOAD_FONT6
|
||||
if (size==6) len += pgm_read_byte(widtbl_f64+ascii-32)-3;
|
||||
#endif
|
||||
#ifdef LOAD_FONT7
|
||||
if (size==7) len += pgm_read_byte(widtbl_f7s+ascii-32)+2;
|
||||
#endif
|
||||
*pointer++;
|
||||
}
|
||||
|
||||
len = len*textsize;
|
||||
int16_t poX = dX - len;
|
||||
|
||||
if (poX < 0) poX = 0;
|
||||
|
||||
while(*string)
|
||||
{
|
||||
|
||||
int16_t xPlus = drawChar(*string, poX, poY, size);
|
||||
sumX += xPlus;
|
||||
*string++;
|
||||
poX += xPlus; /* Move cursor right */
|
||||
}
|
||||
|
||||
return sumX;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: drawFloat
|
||||
** Descriptions: drawFloat
|
||||
***************************************************************************************/
|
||||
int16_t Adafruit_GFX::drawFloat(float floatNumber, int16_t decimal, int16_t poX, int16_t poY, int16_t size)
|
||||
{
|
||||
unsigned long temp=0;
|
||||
float decy=0.0;
|
||||
float rounding = 0.5;
|
||||
|
||||
float eep = 0.000001;
|
||||
|
||||
int16_t sumX = 0;
|
||||
int16_t xPlus = 0;
|
||||
|
||||
if(floatNumber-0.0 < eep) // floatNumber < 0
|
||||
{
|
||||
xPlus = drawChar('-',poX, poY, size);
|
||||
floatNumber = -floatNumber;
|
||||
|
||||
poX += xPlus;
|
||||
sumX += xPlus;
|
||||
}
|
||||
|
||||
for (unsigned char i=0; i<decimal; ++i)
|
||||
{
|
||||
rounding /= 10.0;
|
||||
}
|
||||
|
||||
floatNumber += rounding;
|
||||
|
||||
temp = (long)floatNumber;
|
||||
|
||||
|
||||
xPlus = drawNumber(temp,poX, poY, size);
|
||||
|
||||
poX += xPlus;
|
||||
sumX += xPlus;
|
||||
|
||||
if(decimal>0)
|
||||
{
|
||||
xPlus = drawChar('.',poX, poY, size);
|
||||
poX += xPlus; /* Move cursor right */
|
||||
sumX += xPlus;
|
||||
}
|
||||
else
|
||||
{
|
||||
return sumX;
|
||||
}
|
||||
|
||||
decy = floatNumber - temp;
|
||||
for(unsigned char i=0; i<decimal; i++)
|
||||
{
|
||||
decy *= 10; /* for the next decimal */
|
||||
temp = decy; /* get the decimal */
|
||||
xPlus = drawNumber(temp,poX, poY, size);
|
||||
|
||||
poX += xPlus; /* Move cursor right */
|
||||
sumX += xPlus;
|
||||
decy -= temp;
|
||||
}
|
||||
return sumX;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#ifndef _ADAFRUIT_GFX_H
|
||||
#define _ADAFRUIT_GFX_H
|
||||
|
||||
#include "Load_fonts.h"
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
#define swap(a, b) { int16_t t = a; a = b; b = t; }
|
||||
|
||||
class Adafruit_GFX : public Print {
|
||||
|
||||
public:
|
||||
|
||||
Adafruit_GFX(int16_t w, int16_t h); // Constructor
|
||||
|
||||
// This MUST be defined by the subclass:
|
||||
virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
|
||||
|
||||
// These MAY be overridden by the subclass to provide device-specific
|
||||
// optimized code. Otherwise 'generic' versions are used.
|
||||
virtual void
|
||||
drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1, uint16_t color),
|
||||
drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
|
||||
drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
|
||||
drawRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillRect(int16_t x, int16_t y, int16_t w, int16_t h, uint16_t color),
|
||||
fillScreen(uint16_t color),
|
||||
invertDisplay(boolean i);
|
||||
|
||||
// These exist only with Adafruit_GFX (no subclass overrides)
|
||||
void
|
||||
drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
drawCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
uint16_t color),
|
||||
fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
|
||||
fillCircleHelper(int16_t x0, int16_t y0, int16_t r, uint8_t cornername,
|
||||
int16_t delta, uint16_t color),
|
||||
drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
|
||||
int16_t x2, int16_t y2, uint16_t color),
|
||||
drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
|
||||
int16_t radius, uint16_t color),
|
||||
drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap,
|
||||
int16_t w, int16_t h, uint16_t color),
|
||||
drawChar(int16_t x, int16_t y, unsigned char c, uint16_t color,
|
||||
uint16_t bg, uint8_t size),
|
||||
setCursor(int16_t x, int16_t y),
|
||||
setTextColor(uint16_t c),
|
||||
setTextColor(uint16_t c, uint16_t bg),
|
||||
setTextSize(uint8_t s),
|
||||
setTextWrap(boolean w),
|
||||
setRotation(uint8_t r);
|
||||
|
||||
int16_t drawUnicode(uint16_t uniCode, int16_t x, int16_t y, int16_t size);
|
||||
int16_t drawNumber(long long_num,int16_t poX, int16_t poY, int16_t size);
|
||||
int16_t drawChar(char c, int16_t x, int16_t y, int16_t size);
|
||||
int16_t drawString(char *string, int16_t poX, int16_t poY, int16_t size);
|
||||
int16_t drawCentreString(char *string, int16_t dX, int16_t poY, int16_t size);
|
||||
int16_t drawRightString(char *string, int16_t dX, int16_t poY, int16_t size);
|
||||
int16_t drawFloat(float floatNumber,int16_t decimal,int16_t poX, int16_t poY, int16_t size);
|
||||
|
||||
#if ARDUINO >= 100
|
||||
virtual size_t write(uint8_t);
|
||||
#else
|
||||
virtual void write(uint8_t);
|
||||
#endif
|
||||
|
||||
int16_t
|
||||
height(void),
|
||||
width(void);
|
||||
|
||||
uint8_t getRotation(void);
|
||||
|
||||
protected:
|
||||
const int16_t
|
||||
WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes
|
||||
int16_t
|
||||
_width, _height, // Display w/h as modified by current rotation
|
||||
cursor_x, cursor_y;
|
||||
uint16_t
|
||||
textcolor, textbgcolor;
|
||||
uint8_t
|
||||
textsize,
|
||||
rotation;
|
||||
boolean
|
||||
wrap; // If set, 'wrap' text at right edge of display
|
||||
};
|
||||
|
||||
#endif // _ADAFRUIT_GFX_H
|
|
@ -0,0 +1,527 @@
|
|||
// Font size 2
|
||||
|
||||
#include "Font16.h"
|
||||
//#include <avr/pgmspace.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#else
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
PROGMEM const unsigned char widtbl_f16[96] = // character width table
|
||||
{
|
||||
5, 2, 3, 8, 7, 8, 8, 2, // char 32 - 39
|
||||
6, 6, 7, 5, 2, 5, 4, 6, // char 40 - 47
|
||||
7, 7, 7, 7, 7, 7, 7, 7, // char 48 - 55
|
||||
7, 7, 2, 2, 5, 5, 5, 7, // char 56 - 63
|
||||
8, 7, 7, 7, 7, 7, 7, 7, // char 64 - 71
|
||||
6, 3, 7, 7, 6, 9, 7, 7, // char 72 - 79
|
||||
7, 7, 7, 7, 7, 7, 7, 9, // char 80 - 87
|
||||
7, 7, 7, 3, 6, 3, 7, 8, // char 88 - 95
|
||||
3, 6, 6, 6, 6, 6, 5, 6, // char 96 - 103
|
||||
6, 4, 4, 5, 4, 7, 6, 7, // char 104 - 111
|
||||
6, 7, 5, 5, 4, 6, 7, 7, // char 112 - 119
|
||||
5, 6, 6, 4, 2, 4, 7, 5 // char 120 - 127
|
||||
};
|
||||
|
||||
// Row format, MSB left
|
||||
|
||||
PROGMEM const unsigned char chr_f16_20[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_21[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // row 1 - 11
|
||||
0x00, 0x40, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_22[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0xA0, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_23[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x24, 0x24, 0x24, 0xFF, 0x24, 0x24, 0xFF, 0x24, // row 1 - 11
|
||||
0x24, 0x24, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_24[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x3C, 0x42, 0x40, 0x40, 0x70, 0x40, 0x70, 0x40, // row 1 - 11
|
||||
0x40, 0xFE, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_25[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x61, 0x91, 0x92, 0x64, 0x08, 0x10, 0x26, 0x49, // row 1 - 11
|
||||
0x89, 0x86, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_26[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x20, 0x50, 0x88, 0x88, 0x50, 0x20, 0x52, 0x8C, // row 1 - 11
|
||||
0x8C, 0x73, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_27[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x40, 0x40, 0x40, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_28[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x0C, 0x10, 0x20, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x40, 0x40, 0x20, 0x10, 0x0C // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_29[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0xC0, 0x20, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, // row 1 - 11
|
||||
0x08, 0x08, 0x10, 0x20, 0xC0 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_2A[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x92, 0x54, 0x38, 0x54, 0x92, 0x10, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_2B[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_2C[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0xC0, 0xC0, 0x40, 0x80, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_2D[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_2E[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0xC0, 0xC0, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_2F[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, // row 1 - 11
|
||||
0x40, 0x80, 0x80, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_30[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x44, 0x82, 0x82, 0x82, 0x82, 0x44, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_31[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x10, 0x30, 0x50, 0x10, 0x10, 0x10, 0x10, 0x10, // row 1 - 11
|
||||
0x10, 0x7C, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_32[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x02, 0x04, 0x18, 0x20, 0x40, // row 1 - 11
|
||||
0x80, 0xFE, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_33[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x78, 0x84, 0x02, 0x04, 0x38, 0x04, 0x02, 0x02, // row 1 - 11
|
||||
0x84, 0x78, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_34[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x04, 0x0C, 0x14, 0x24, 0x44, 0x84, 0xFE, 0x04, // row 1 - 11
|
||||
0x04, 0x04, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_35[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xFC, 0x80, 0x80, 0x80, 0xF8, 0x04, 0x02, 0x02, // row 1 - 11
|
||||
0x84, 0x78, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_36[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x3C, 0x40, 0x80, 0x80, 0xB8, 0xC4, 0x82, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_37[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x7E, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, // row 1 - 11
|
||||
0x10, 0x10, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_38[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x44, 0x38, 0x44, 0x82, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_39[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x46, 0x3A, 0x02, 0x02, // row 1 - 11
|
||||
0x04, 0x78, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_3A[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_3B[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, // row 1 - 11
|
||||
0x40, 0x80, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_3C[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x40, 0x20, // row 1 - 11
|
||||
0x10, 0x08, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_3D[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_3E[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x10, 0x20, // row 1 - 11
|
||||
0x40, 0x80, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_3F[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x02, 0x04, 0x08, 0x10, 0x10, // row 1 - 11
|
||||
0x00, 0x10, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_40[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x3C, 0x42, 0x99, 0xA5, 0xA5, 0xA5, 0xA5, 0x9E, // row 1 - 11
|
||||
0x40, 0x3E, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_41[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x10, 0x10, 0x28, 0x28, 0x44, 0x44, 0x7C, 0x82, // row 1 - 11
|
||||
0x82, 0x82, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_42[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xF8, 0x84, 0x82, 0x84, 0xF8, 0x84, 0x82, 0x82, // row 1 - 11
|
||||
0x84, 0xF8, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_43[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x3C, 0x42, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x42, 0x3C, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_44[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xF8, 0x84, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, // row 1 - 11
|
||||
0x84, 0xF8, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_45[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xFE, 0x80, 0x80, 0x80, 0xFC, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x80, 0xFE, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_46[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xFE, 0x80, 0x80, 0x80, 0xF8, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x80, 0x80, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_47[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x3C, 0x42, 0x80, 0x80, 0x80, 0x9C, 0x82, 0x82, // row 1 - 11
|
||||
0x42, 0x3C, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_48[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x84, 0x84, 0x84, 0x84, 0xFC, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x84, 0x84, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_49[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xE0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // row 1 - 11
|
||||
0x40, 0xE0, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_4A[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_4B[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x84, 0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, // row 1 - 11
|
||||
0x84, 0x82, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_4C[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x80, 0xFC, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_4D[32] = // 2 unsigned chars per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0x80, 0xC1, 0x80, 0xA2, 0x80, // row 1 - 6
|
||||
0xA2, 0x80, 0x94, 0x80, 0x94, 0x80, 0x88, 0x80, 0x88, 0x80, 0x80, 0x80, // row 7 - 12
|
||||
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 13 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_4E[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xC2, 0xC2, 0xA2, 0xA2, 0x92, 0x92, 0x8A, 0x8A, // row 1 - 11
|
||||
0x86, 0x86, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_4F[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_50[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xF8, 0x84, 0x82, 0x82, 0x82, 0x84, 0xF8, 0x80, // row 1 - 11
|
||||
0x80, 0x80, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_51[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x08, 0x06, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_52[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xF8, 0x84, 0x82, 0x82, 0x84, 0xF8, 0x90, 0x88, // row 1 - 11
|
||||
0x84, 0x82, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_53[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x80, 0x60, 0x1C, 0x02, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_54[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xFE, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, // row 1 - 11
|
||||
0x10, 0x10, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_55[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_56[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x44, 0x44, 0x28, 0x28, // row 1 - 11
|
||||
0x10, 0x10, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_57[32] = // 2 unsigned chars per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // row 1 - 6
|
||||
0x88, 0x80, 0x88, 0x80, 0x49, 0x00, 0x55, 0x00, 0x55, 0x00, 0x22, 0x00, // row 7 - 12
|
||||
0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 13 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_58[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x28, 0x44, // row 1 - 11
|
||||
0x82, 0x82, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_59[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, // row 1 - 11
|
||||
0x10, 0x10, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_5A[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xFE, 0x02, 0x04, 0x08, 0x10, 0x10, 0x20, 0x40, // row 1 - 11
|
||||
0x80, 0xFE, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_5B[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0xE0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x80, 0x80, 0xE0, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_5C[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x40, // row 1 - 11
|
||||
0x40, 0x80, 0x80, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_5D[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // row 1 - 11
|
||||
0x20, 0x20, 0xE0, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_5E[32] = // 1 unsigned chars per row
|
||||
{
|
||||
0x00, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_5F[32] = // 1 unsigned chars per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0xFF, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_60[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_61[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x04, 0x74, 0x8C, // row 1 - 11
|
||||
0x8C, 0x74, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_62[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xB0, 0xC8, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0xC8, 0xB0, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_63[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_64[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x34, 0x4C, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x4C, 0x34, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_65[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x84, 0xF8, 0x80, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_66[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x30, 0x48, 0x40, 0x40, 0x40, 0xE0, 0x40, 0x40, // row 1 - 11
|
||||
0x40, 0x40, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_67[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x4C, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x4C, 0x34, 0x04, 0x08, 0x70 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_68[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xB0, 0xC8, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x84, 0x84, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_69[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, // row 1 - 11
|
||||
0x40, 0x40, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_6A[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x10, // row 1 - 11
|
||||
0x10, 0x10, 0x10, 0x90, 0x60 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_6B[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x88, 0x90, 0xA0, 0xC0, 0xA0, // row 1 - 11
|
||||
0x90, 0x88, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_6C[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0xC0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // row 1 - 11
|
||||
0x40, 0x40, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_6D[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xD2, 0x92, 0x92, 0x92, // row 1 - 11
|
||||
0x92, 0x92, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_6E[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xC8, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x84, 0x84, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_6F[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x44, 0x82, 0x82, 0x82, // row 1 - 11
|
||||
0x44, 0x38, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_70[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xC8, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0xC8, 0xB0, 0x80, 0x80, 0x80 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_71[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x4C, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x4C, 0x34, 0x04, 0x04, 0x06 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_72[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, // row 1 - 11
|
||||
0x80, 0x80, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_73[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x88, 0x80, 0x70, 0x08, // row 1 - 11
|
||||
0x88, 0x70, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_74[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0xE0, 0x40, 0x40, 0x40, 0x40, // row 1 - 11
|
||||
0x40, 0x30, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_75[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x4C, 0x34, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_76[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x82, 0x44, // row 1 - 11
|
||||
0x28, 0x10, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_77[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x82, 0x82, 0x92, 0x92, // row 1 - 11
|
||||
0xAA, 0x44, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_78[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88, 0x50, 0x20, 0x50, // row 1 - 11
|
||||
0x88, 0x88, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_79[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x84, 0x84, 0x84, 0x84, // row 1 - 11
|
||||
0x4C, 0x34, 0x04, 0x08, 0x70 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_7A[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x04, 0x08, 0x30, 0x40, // row 1 - 11
|
||||
0x80, 0xFC, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_7B[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x20, 0x20, // row 1 - 11
|
||||
0x20, 0x20, 0x20, 0x20, 0x10 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_7C[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, // row 1 - 11
|
||||
0x40, 0x40, 0x40, 0x40, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_7D[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x20, 0x20, // row 1 - 11
|
||||
0x20, 0x20, 0x20, 0x20, 0x40 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_7E[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x32, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
PROGMEM const unsigned char chr_f16_7F[16] = // 1 unsigned char per row
|
||||
{
|
||||
0x00, 0x00, 0x30, 0x48, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 11
|
||||
0x00, 0x00, 0x00, 0x00, 0x00 // row 12 - 16
|
||||
};
|
||||
|
||||
PROGMEM const unsigned char* const chrtbl_f16[] = // character pointer table
|
||||
{
|
||||
chr_f16_20, chr_f16_21, chr_f16_22, chr_f16_23, chr_f16_24, chr_f16_25, chr_f16_26, chr_f16_27,
|
||||
chr_f16_28, chr_f16_29, chr_f16_2A, chr_f16_2B, chr_f16_2C, chr_f16_2D, chr_f16_2E, chr_f16_2F,
|
||||
chr_f16_30, chr_f16_31, chr_f16_32, chr_f16_33, chr_f16_34, chr_f16_35, chr_f16_36, chr_f16_37,
|
||||
chr_f16_38, chr_f16_39, chr_f16_3A, chr_f16_3B, chr_f16_3C, chr_f16_3D, chr_f16_3E, chr_f16_3F,
|
||||
chr_f16_40, chr_f16_41, chr_f16_42, chr_f16_43, chr_f16_44, chr_f16_45, chr_f16_46, chr_f16_47,
|
||||
chr_f16_48, chr_f16_49, chr_f16_4A, chr_f16_4B, chr_f16_4C, chr_f16_4D, chr_f16_4E, chr_f16_4F,
|
||||
chr_f16_50, chr_f16_51, chr_f16_52, chr_f16_53, chr_f16_54, chr_f16_55, chr_f16_56, chr_f16_57,
|
||||
chr_f16_58, chr_f16_59, chr_f16_5A, chr_f16_5B, chr_f16_5C, chr_f16_5D, chr_f16_5E, chr_f16_5F,
|
||||
chr_f16_60, chr_f16_61, chr_f16_62, chr_f16_63, chr_f16_64, chr_f16_65, chr_f16_66, chr_f16_67,
|
||||
chr_f16_68, chr_f16_69, chr_f16_6A, chr_f16_6B, chr_f16_6C, chr_f16_6D, chr_f16_6E, chr_f16_6F,
|
||||
chr_f16_70, chr_f16_71, chr_f16_72, chr_f16_73, chr_f16_74, chr_f16_75, chr_f16_76, chr_f16_77,
|
||||
chr_f16_78, chr_f16_79, chr_f16_7A, chr_f16_7B, chr_f16_7C, chr_f16_7D, chr_f16_7E, chr_f16_7F
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
#define nr_chrs_f16 96
|
||||
#define chr_hgt_f16 16
|
||||
#define data_size_f16 8
|
||||
#define firstchr_f16 32
|
||||
|
||||
extern const unsigned char widtbl_f16[96];
|
||||
extern const unsigned char* const chrtbl_f16[96];
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
#define nr_chrs_f32 96
|
||||
#define chr_hgt_f32 26
|
||||
#define data_size_f32 8
|
||||
#define firstchr_f32 32
|
||||
|
||||
extern const unsigned char widtbl_f32[96];
|
||||
extern const unsigned char* const chrtbl_f32[96];
|
|
@ -0,0 +1,363 @@
|
|||
// Font size 6 is intended to display numbers and time
|
||||
// This font only contains characters [space] 0 1 2 3 4 5 6 7 8 9 . : a p m
|
||||
// The Pipe character | is a narrow space to aid formatting
|
||||
// All other characters print as a space
|
||||
|
||||
#include "Font64.h"
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#else
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
|
||||
const unsigned char widtbl_f64[96] PROGMEM = // character width table
|
||||
{
|
||||
15, 15, 15, 15, 15, 15, 15, 15, // char 32 - 39
|
||||
15, 15, 15, 15, 15, 20, 18, 15, // char 40 - 47
|
||||
30, 30, 30, 30, 30, 30, 30, 30, // char 48 - 55
|
||||
30, 30, 18, 15, 15, 15, 15, 15, // char 56 - 63
|
||||
15, 15, 15, 15, 15, 15, 15, 15, // char 64 - 71
|
||||
15, 15, 15, 15, 15, 15, 15, 15, // char 72 - 79
|
||||
15, 15, 15, 15, 15, 15, 15, 15, // char 80 - 87
|
||||
15, 15, 15, 15, 15, 15, 15, 15, // char 88 - 95
|
||||
15, 30, 15, 15, 15, 15, 15, 15, // char 96 - 103
|
||||
15, 15, 15, 15, 15, 45, 15, 15, // char 104 - 111
|
||||
32, 15, 15, 15, 15, 15, 15, 15, // char 112 - 119
|
||||
15, 15, 15, 15, 10, 15, 15, 15 // char 120 - 127
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Row format, MSB left
|
||||
|
||||
const unsigned char chr_f64_20[96] PROGMEM = // 2 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 6
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 7 - 12
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 13 - 18
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 19 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 25 - 30
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 31 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 43 - 48
|
||||
};
|
||||
const unsigned char chr_f64_2D[144] PROGMEM = // 3 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 4
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 5 - 8
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 9 - 12
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 13 - 16
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFC, 0x00, // row 17 - 20
|
||||
0x1F, 0xFC, 0x00, 0x1F, 0xFC, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x00, // row 21 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 25 - 28
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 29 - 32
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 33 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 40
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 41 - 44
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 45 - 48
|
||||
};
|
||||
const unsigned char chr_f64_2E[144] PROGMEM = // 3 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 4
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 5 - 8
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 9 - 12
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 13 - 16
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 17 - 20
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 21 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 25 - 28
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, // row 29 - 32
|
||||
0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, // row 33 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 40
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 41 - 44
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 45 - 48
|
||||
};
|
||||
const unsigned char chr_f64_30[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x03, 0xFF, 0xF0, 0x00, // row 1 - 3
|
||||
0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 4 - 6
|
||||
0x1F, 0x00, 0x3E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x3E, 0x00, 0x1F, 0x00, // row 7 - 9
|
||||
0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, // row 10 - 12
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 13 - 15
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 16 - 18
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 19 - 21
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 22 - 24
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x3C, 0x00, 0x0F, 0x00, // row 25 - 27
|
||||
0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0x1F, 0x00, // row 28 - 30
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x3E, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 31 - 33
|
||||
0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, // row 34 - 36
|
||||
0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_31[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x01, 0xC0, 0x00, // row 1 - 3
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, // row 4 - 6
|
||||
0x00, 0x0F, 0xC0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, 0xFF, 0xC0, 0x00, // row 7 - 9
|
||||
0x07, 0xFF, 0xC0, 0x00, 0x07, 0xFB, 0xC0, 0x00, 0x07, 0xC3, 0xC0, 0x00, // row 10 - 12
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 13 - 15
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 16 - 18
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 19 - 21
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 22 - 24
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 25 - 27
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 28 - 30
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 31 - 33
|
||||
0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x03, 0xC0, 0x00, // row 34 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_32[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0xFF, 0xF8, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x07, 0xE0, 0x7F, 0x00, // row 4 - 6
|
||||
0x0F, 0x80, 0x1F, 0x00, 0x0F, 0x80, 0x0F, 0x00, 0x0F, 0x00, 0x0F, 0x80, // row 7 - 9
|
||||
0x1F, 0x00, 0x07, 0x80, 0x1E, 0x00, 0x07, 0x80, 0x1E, 0x00, 0x07, 0x80, // row 10 - 12
|
||||
0x1E, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x80, // row 13 - 15
|
||||
0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0x00, // row 16 - 18
|
||||
0x00, 0x00, 0x7E, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, // row 19 - 21
|
||||
0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0xFF, 0x80, 0x00, // row 22 - 24
|
||||
0x01, 0xFE, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, // row 25 - 27
|
||||
0x0F, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, // row 28 - 30
|
||||
0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0x80, // row 31 - 33
|
||||
0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x80, // row 34 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_33[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x03, 0xFF, 0xF0, 0x00, // row 1 - 3
|
||||
0x07, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 4 - 6
|
||||
0x1F, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x3E, 0x00, 0x1F, 0x00, // row 7 - 9
|
||||
0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, // row 10 - 12
|
||||
0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x3E, 0x00, // row 13 - 15
|
||||
0x00, 0x00, 0x7E, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x3F, 0xF0, 0x00, // row 16 - 18
|
||||
0x00, 0x3F, 0xFC, 0x00, 0x00, 0x3F, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x00, // row 19 - 21
|
||||
0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x0F, 0x80, // row 22 - 24
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 25 - 27
|
||||
0x7C, 0x00, 0x0F, 0x80, 0x7C, 0x00, 0x1F, 0x80, 0x3E, 0x00, 0x1F, 0x00, // row 28 - 30
|
||||
0x3F, 0x00, 0x3F, 0x00, 0x1F, 0xC0, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, // row 31 - 33
|
||||
0x07, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0x80, 0x00, // row 34 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_34[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, // row 1 - 3
|
||||
0x00, 0x01, 0xF0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x07, 0xF0, 0x00, // row 4 - 6
|
||||
0x00, 0x07, 0xF0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1E, 0xF0, 0x00, // row 7 - 9
|
||||
0x00, 0x1E, 0xF0, 0x00, 0x00, 0x3C, 0xF0, 0x00, 0x00, 0x78, 0xF0, 0x00, // row 10 - 12
|
||||
0x00, 0xF8, 0xF0, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x01, 0xE0, 0xF0, 0x00, // row 13 - 15
|
||||
0x03, 0xC0, 0xF0, 0x00, 0x07, 0xC0, 0xF0, 0x00, 0x07, 0x80, 0xF0, 0x00, // row 16 - 18
|
||||
0x0F, 0x00, 0xF0, 0x00, 0x1F, 0x00, 0xF0, 0x00, 0x1E, 0x00, 0xF0, 0x00, // row 19 - 21
|
||||
0x3C, 0x00, 0xF0, 0x00, 0x78, 0x00, 0xF0, 0x00, 0x7F, 0xFF, 0xFF, 0x80, // row 22 - 24
|
||||
0x7F, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFF, 0x80, // row 25 - 27
|
||||
0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, // row 28 - 30
|
||||
0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, // row 31 - 33
|
||||
0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, // row 34 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_35[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFE, 0x00, // row 1 - 3
|
||||
0x07, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFE, 0x00, // row 4 - 6
|
||||
0x07, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, // row 7 - 9
|
||||
0x0F, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, // row 10 - 12
|
||||
0x0E, 0x00, 0x00, 0x00, 0x1E, 0x3F, 0xC0, 0x00, 0x1E, 0xFF, 0xF0, 0x00, // row 13 - 15
|
||||
0x1F, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 16 - 18
|
||||
0x1F, 0x00, 0x3F, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F, 0x00, // row 19 - 21
|
||||
0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, // row 22 - 24
|
||||
0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x07, 0x80, // row 25 - 27
|
||||
0x3C, 0x00, 0x07, 0x80, 0x3C, 0x00, 0x0F, 0x80, 0x3C, 0x00, 0x0F, 0x00, // row 28 - 30
|
||||
0x3E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x3F, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 31 - 33
|
||||
0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, // row 34 - 36
|
||||
0x00, 0x7F, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_36[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0xFF, 0xF0, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x0F, 0xE0, 0x7E, 0x00, // row 4 - 6
|
||||
0x1F, 0x80, 0x1F, 0x00, 0x1F, 0x00, 0x0F, 0x00, 0x1E, 0x00, 0x0F, 0x80, // row 7 - 9
|
||||
0x3E, 0x00, 0x07, 0x80, 0x3C, 0x00, 0x07, 0x80, 0x3C, 0x00, 0x00, 0x00, // row 10 - 12
|
||||
0x3C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x3F, 0x80, 0x00, // row 13 - 15
|
||||
0x78, 0xFF, 0xF0, 0x00, 0x7B, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFC, 0x00, // row 16 - 18
|
||||
0x7F, 0xC0, 0xFE, 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x7E, 0x00, 0x1F, 0x00, // row 19 - 21
|
||||
0x7C, 0x00, 0x0F, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x78, 0x00, 0x07, 0x80, // row 22 - 24
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 25 - 27
|
||||
0x78, 0x00, 0x07, 0x80, 0x3C, 0x00, 0x0F, 0x80, 0x3C, 0x00, 0x0F, 0x00, // row 28 - 30
|
||||
0x3E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x3F, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 31 - 33
|
||||
0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x01, 0xFF, 0xF0, 0x00, // row 34 - 36
|
||||
0x00, 0x7F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_37[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0x80, // row 1 - 3
|
||||
0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0x80, // row 4 - 6
|
||||
0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1E, 0x00, // row 7 - 9
|
||||
0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xF8, 0x00, // row 10 - 12
|
||||
0x00, 0x01, 0xF0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x03, 0xE0, 0x00, // row 13 - 15
|
||||
0x00, 0x07, 0xC0, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x0F, 0x80, 0x00, // row 16 - 18
|
||||
0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, // row 19 - 21
|
||||
0x00, 0x3E, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, // row 22 - 24
|
||||
0x00, 0x7C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, // row 25 - 27
|
||||
0x00, 0xF8, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, // row 28 - 30
|
||||
0x00, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x01, 0xF0, 0x00, 0x00, // row 31 - 33
|
||||
0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, // row 34 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_38[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x00, // row 1 - 3
|
||||
0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 4 - 6
|
||||
0x1F, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x3E, 0x00, 0x1F, 0x00, // row 7 - 9
|
||||
0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, // row 10 - 12
|
||||
0x3E, 0x00, 0x1F, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1F, 0x00, 0x3E, 0x00, // row 13 - 15
|
||||
0x0F, 0xC0, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, // row 16 - 18
|
||||
0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x1F, 0x80, 0x7E, 0x00, // row 19 - 21
|
||||
0x3E, 0x00, 0x1F, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x7C, 0x00, 0x0F, 0x80, // row 22 - 24
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 25 - 27
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x7C, 0x00, 0x0F, 0x80, // row 28 - 30
|
||||
0x7C, 0x00, 0x0F, 0x80, 0x3E, 0x00, 0x1F, 0x00, 0x3F, 0x80, 0x7F, 0x00, // row 31 - 33
|
||||
0x1F, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xF8, 0x00, // row 34 - 36
|
||||
0x00, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_39[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xE0, 0x00, // row 1 - 3
|
||||
0x07, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0xFE, 0x00, // row 4 - 6
|
||||
0x3F, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x3C, 0x00, 0x0F, 0x00, // row 7 - 9
|
||||
0x7C, 0x00, 0x0F, 0x00, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 10 - 12
|
||||
0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, 0x78, 0x00, 0x07, 0x80, // row 13 - 15
|
||||
0x7C, 0x00, 0x0F, 0x80, 0x3C, 0x00, 0x0F, 0x80, 0x3E, 0x00, 0x1F, 0x80, // row 16 - 18
|
||||
0x1F, 0x00, 0x3F, 0x80, 0x1F, 0xC0, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0x80, // row 19 - 21
|
||||
0x07, 0xFF, 0xF7, 0x80, 0x03, 0xFF, 0xC7, 0x80, 0x00, 0x7F, 0x07, 0x80, // row 22 - 24
|
||||
0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x00, // row 25 - 27
|
||||
0x78, 0x00, 0x0F, 0x00, 0x78, 0x00, 0x1F, 0x00, 0x7C, 0x00, 0x1E, 0x00, // row 28 - 30
|
||||
0x3C, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x7E, 0x00, 0x1F, 0x81, 0xFC, 0x00, // row 31 - 33
|
||||
0x0F, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xC0, 0x00, // row 34 - 36
|
||||
0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_3A[144] PROGMEM = // 3 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 4
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 5 - 8
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, // row 9 - 12
|
||||
0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, // row 13 - 16
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 17 - 20
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 21 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xC0, 0x00, // row 25 - 28
|
||||
0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, 0x07, 0xC0, 0x00, // row 29 - 32
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 33 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 40
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 41 - 44
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 45 - 48
|
||||
};
|
||||
const unsigned char chr_f64_61[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 3
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 4 - 6
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 7 - 9
|
||||
0x00, 0x7F, 0xC0, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xFC, 0x00, // row 10 - 12
|
||||
0x07, 0xFF, 0xFE, 0x00, 0x0F, 0xC0, 0x7E, 0x00, 0x1F, 0x00, 0x1F, 0x00, // row 13 - 15
|
||||
0x1E, 0x00, 0x0F, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x1E, 0x00, 0x0F, 0x00, // row 16 - 18
|
||||
0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0xFF, 0x00, // row 19 - 21
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xCF, 0x00, // row 22 - 24
|
||||
0x1F, 0xF0, 0x0F, 0x00, 0x1F, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0x0F, 0x00, // row 25 - 27
|
||||
0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x3C, 0x00, 0x1F, 0x00, // row 28 - 30
|
||||
0x3C, 0x00, 0x3F, 0x00, 0x3E, 0x00, 0x7F, 0x00, 0x1F, 0x01, 0xFF, 0xC0, // row 31 - 33
|
||||
0x1F, 0xFF, 0xE7, 0xC0, 0x0F, 0xFF, 0xC7, 0xC0, 0x07, 0xFF, 0x03, 0xC0, // row 34 - 36
|
||||
0x01, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
const unsigned char chr_f64_6D[288] PROGMEM = // 6 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 2
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 3 - 4
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 5 - 6
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 7 - 8
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1F, 0xC0, 0x00, // row 9 - 10
|
||||
0x1E, 0x3F, 0xF0, 0x7F, 0xF0, 0x00, 0x1E, 0xFF, 0xF8, 0xFF, 0xF8, 0x00, // row 11 - 12
|
||||
0x1E, 0xFF, 0xFD, 0xFF, 0xFC, 0x00, 0x1F, 0xE0, 0x7F, 0xE0, 0x7C, 0x00, // row 13 - 14
|
||||
0x1F, 0x80, 0x3F, 0x80, 0x3E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1E, 0x00, // row 15 - 16
|
||||
0x1F, 0x00, 0x1F, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 17 - 18
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 19 - 20
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 21 - 22
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 23 - 24
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 25 - 26
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 27 - 28
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 29 - 30
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 31 - 32
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 33 - 34
|
||||
0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1E, 0x00, // row 35 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 38
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 39 - 40
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 41 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 44
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 45 - 46
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 47 - 48
|
||||
};
|
||||
const unsigned char chr_f64_70[192] PROGMEM = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 3
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 4 - 6
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 7 - 9
|
||||
0x00, 0x0F, 0xE0, 0x00, 0x1E, 0x3F, 0xFC, 0x00, 0x1E, 0x7F, 0xFE, 0x00, // row 10 - 12
|
||||
0x1E, 0xFF, 0xFF, 0x00, 0x1F, 0xF0, 0x3F, 0x80, 0x1F, 0xC0, 0x0F, 0x80, // row 13 - 15
|
||||
0x1F, 0x80, 0x07, 0xC0, 0x1F, 0x00, 0x03, 0xC0, 0x1F, 0x00, 0x03, 0xC0, // row 16 - 18
|
||||
0x1F, 0x00, 0x03, 0xE0, 0x1E, 0x00, 0x01, 0xE0, 0x1E, 0x00, 0x01, 0xE0, // row 19 - 21
|
||||
0x1E, 0x00, 0x01, 0xE0, 0x1E, 0x00, 0x01, 0xE0, 0x1E, 0x00, 0x01, 0xE0, // row 22 - 24
|
||||
0x1E, 0x00, 0x01, 0xE0, 0x1E, 0x00, 0x01, 0xE0, 0x1E, 0x00, 0x01, 0xE0, // row 25 - 27
|
||||
0x1E, 0x00, 0x03, 0xE0, 0x1F, 0x00, 0x03, 0xC0, 0x1F, 0x00, 0x07, 0xC0, // row 28 - 30
|
||||
0x1F, 0x80, 0x07, 0xC0, 0x1F, 0xC0, 0x0F, 0x80, 0x1F, 0xF0, 0x3F, 0x80, // row 31 - 33
|
||||
0x1E, 0xFF, 0xFF, 0x00, 0x1E, 0x7F, 0xFE, 0x00, 0x1E, 0x3F, 0xFC, 0x00, // row 34 - 36
|
||||
0x1E, 0x0F, 0xE0, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x1E, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
|
||||
const unsigned char* const chrtbl_f64[] PROGMEM = // character pointer table
|
||||
{
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_2D, chr_f64_2E, chr_f64_20,
|
||||
chr_f64_30, chr_f64_31, chr_f64_32, chr_f64_33, chr_f64_34, chr_f64_35, chr_f64_36, chr_f64_37,
|
||||
chr_f64_38, chr_f64_39, chr_f64_3A, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_61, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_6D, chr_f64_20, chr_f64_20,
|
||||
chr_f64_70, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20,
|
||||
chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20, chr_f64_20
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
#define nr_chrs_f64 96
|
||||
#define chr_hgt_f64 48
|
||||
#define data_size_f64 8
|
||||
#define firstchr_f64 32
|
||||
|
||||
extern const unsigned char widtbl_f64[96];
|
||||
extern const unsigned char* const chrtbl_f64[96];
|
|
@ -0,0 +1,270 @@
|
|||
// Font size 7 is a 7 segment font intended to display numbers and time
|
||||
// This font only contains characters [space] 0 1 2 3 4 5 6 7 8 9 : .
|
||||
// All other characters print as a space
|
||||
|
||||
#include "Font7s.h"
|
||||
//#include <avr/pgmspace.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#else
|
||||
#define PROGMEM
|
||||
#endif
|
||||
|
||||
PROGMEM const unsigned char widtbl_f7s[96] = // character width table
|
||||
{
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 32 - 39
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 40 - 47
|
||||
32, 32, 32, 32, 32, 32, 32, 32, // char 48 - 55
|
||||
32, 32, 12, 12, 12, 12, 12, 12, // char 56 - 63
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 64 - 71
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 72 - 79
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 80 - 87
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 88 - 95
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 96 - 103
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 104 - 111
|
||||
12, 12, 12, 12, 12, 12, 12, 12, // char 112 - 119
|
||||
12, 12, 12, 12, 12, 12, 12, 12 // char 120 - 127
|
||||
};
|
||||
|
||||
// Row format, MSB left
|
||||
|
||||
PROGMEM const unsigned char chr_f7s_20[96] = // 2 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 6
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 7 - 12
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 13 - 18
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 19 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 25 - 30
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 31 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 43 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_2E[96] = // 2 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 6
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 7 - 12
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 13 - 18
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 19 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 25 - 30
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 31 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 42
|
||||
0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x0E, 0x00, 0x00, 0x00 // row 43 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_30[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x20, 0x0C, 0xFF, 0xFE, 0x70, // row 4 - 6
|
||||
0x1E, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0xF8, // row 19 - 21
|
||||
0x38, 0x00, 0x00, 0x38, 0x20, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, // row 22 - 24
|
||||
0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x18, 0x3E, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x1E, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x0C, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, // row 43 - 45
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_31[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 3
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, // row 4 - 6
|
||||
0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x78, // row 19 - 21
|
||||
0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, // row 22 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_32[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x20, 0x00, 0xFF, 0xFE, 0x70, // row 4 - 6
|
||||
0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF8, // row 19 - 21
|
||||
0x00, 0xFF, 0xFE, 0x38, 0x03, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, // row 22 - 24
|
||||
0x27, 0xFF, 0xFF, 0xC0, 0x39, 0xFF, 0xFF, 0x00, 0x3E, 0x00, 0x00, 0x00, // row 25 - 27
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 28 - 30
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 31 - 33
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 34 - 36
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 37 - 39
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, // row 40 - 42
|
||||
0x0C, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, // row 43 - 45
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_33[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x20, 0x00, 0xFF, 0xFE, 0x70, // row 4 - 6
|
||||
0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF8, // row 19 - 21
|
||||
0x00, 0xFF, 0xFE, 0x38, 0x03, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, // row 22 - 24
|
||||
0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x00, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, // row 43 - 45
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_34[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 3
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0C, 0x00, 0x00, 0x70, // row 4 - 6
|
||||
0x1E, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0xF8, // row 19 - 21
|
||||
0x38, 0xFF, 0xFE, 0x38, 0x23, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, // row 22 - 24
|
||||
0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_35[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x0C, 0xFF, 0xFE, 0x00, // row 4 - 6
|
||||
0x1E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 7 - 9
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 10 - 12
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 13 - 15
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 16 - 18
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, // row 19 - 21
|
||||
0x38, 0xFF, 0xFE, 0x00, 0x23, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, // row 22 - 24
|
||||
0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x00, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, // row 43 - 45
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_36[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x00, 0x0C, 0xFF, 0xFE, 0x00, // row 4 - 6
|
||||
0x1E, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 7 - 9
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 10 - 12
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 13 - 15
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, // row 16 - 18
|
||||
0x3F, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, // row 19 - 21
|
||||
0x38, 0xFF, 0xFE, 0x00, 0x23, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFF, 0xE0, // row 22 - 24
|
||||
0x27, 0xFF, 0xFF, 0xC0, 0x39, 0xFF, 0xFF, 0x18, 0x3E, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x1E, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x0C, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, // row 43 - 45
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_37[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x20, 0x00, 0xFF, 0xFE, 0x70, // row 4 - 6
|
||||
0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF8, // row 19 - 21
|
||||
0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, // row 22 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 43 - 45
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_38[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x20, 0x0C, 0xFF, 0xFE, 0x70, // row 4 - 6
|
||||
0x1E, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0xF8, // row 19 - 21
|
||||
0x38, 0xFF, 0xFE, 0x38, 0x23, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, // row 22 - 24
|
||||
0x27, 0xFF, 0xFF, 0xC0, 0x39, 0xFF, 0xFF, 0x18, 0x3E, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x1E, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x0C, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, // row 43 - 45
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_39[192] = // 4 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x01, 0xFF, 0xFF, 0x00, // row 1 - 3
|
||||
0x03, 0xFF, 0xFF, 0x80, 0x01, 0xFF, 0xFF, 0x20, 0x0C, 0xFF, 0xFE, 0x70, // row 4 - 6
|
||||
0x1E, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 7 - 9
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 10 - 12
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 13 - 15
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, // row 16 - 18
|
||||
0x3F, 0x00, 0x01, 0xF8, 0x3F, 0x00, 0x01, 0xF8, 0x3E, 0x00, 0x00, 0xF8, // row 19 - 21
|
||||
0x38, 0xFF, 0xFE, 0x38, 0x23, 0xFF, 0xFF, 0x88, 0x0F, 0xFF, 0xFF, 0xE0, // row 22 - 24
|
||||
0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x18, 0x00, 0x00, 0x00, 0x78, // row 25 - 27
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 28 - 30
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 31 - 33
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 34 - 36
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, // row 37 - 39
|
||||
0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00, 0x00, 0xF0, // row 40 - 42
|
||||
0x00, 0xFF, 0xFE, 0x60, 0x01, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, // row 43 - 45
|
||||
0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00 // row 46 - 48
|
||||
};
|
||||
PROGMEM const unsigned char chr_f7s_3A[96] = // 2 bytes per row
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 1 - 6
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 7 - 12
|
||||
0x00, 0x00, 0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x0E, 0x00, // row 13 - 18
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 19 - 24
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 25 - 30
|
||||
0x0E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x0E, 0x00, 0x00, 0x00, // row 31 - 36
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // row 37 - 42
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // row 43 - 48
|
||||
};
|
||||
|
||||
PROGMEM const unsigned char* const chrtbl_f7s[96] = // character pointer table
|
||||
{
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_2E, chr_f7s_20,
|
||||
chr_f7s_30, chr_f7s_31, chr_f7s_32, chr_f7s_33, chr_f7s_34, chr_f7s_35, chr_f7s_36, chr_f7s_37,
|
||||
chr_f7s_38, chr_f7s_39, chr_f7s_3A, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20,
|
||||
chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20, chr_f7s_20
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue