mirror of
https://github.com/pascallanger/DIY-Multiprotocol-TX-Module.git
synced 2025-12-14 19:53:14 +00:00
Multi Module Board Definition Updates (#133)
This commit is contained in:
@@ -193,7 +193,8 @@ size_t HardwareSerial::write(unsigned char ch) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* edogaldo: Waits for the transmission of outgoing serial data to complete (Arduino 1.0 api specs) */
|
||||
void HardwareSerial::flush(void) {
|
||||
usart_reset_rx(this->usart_device);
|
||||
usart_reset_tx(this->usart_device);
|
||||
while(!rb_is_empty(this->usart_device->wb)); // wait for TX buffer empty
|
||||
while(!((this->usart_device->regs->SR) & (1<<USART_SR_TC_BIT))); // wait for TC (Transmission Complete) flag set
|
||||
}
|
||||
|
||||
@@ -138,10 +138,24 @@ void HardwareTimer::detachInterrupt(int channel) {
|
||||
timer_detach_interrupt(this->dev, (uint8)channel);
|
||||
}
|
||||
|
||||
|
||||
void HardwareTimer::enableDMA(int channel) {
|
||||
timer_dma_enable_req(this->dev, (uint8)channel);
|
||||
}
|
||||
|
||||
void HardwareTimer::disableDMA(int channel) {
|
||||
timer_dma_disable_req(this->dev, (uint8)channel);
|
||||
}
|
||||
|
||||
void HardwareTimer::refresh(void) {
|
||||
timer_generate_update(this->dev);
|
||||
}
|
||||
|
||||
void HardwareTimer::setMasterModeTrGo(uint32_t mode) {
|
||||
this->dev->regs.bas->CR2 &= ~TIMER_CR2_MMS;
|
||||
this->dev->regs.bas->CR2 |= mode;
|
||||
}
|
||||
|
||||
/* CARLOS Changes to add encoder mode.*/
|
||||
|
||||
//direction of movement. (to be better described).
|
||||
|
||||
@@ -177,7 +177,8 @@ public:
|
||||
* 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 channel the channel to attach the ISR to, from 0 to 4.
|
||||
* Channel 0 is for overflow interrupt (update interrupt).
|
||||
* @param handler The ISR to attach to the given channel.
|
||||
* @see voidFuncPtr
|
||||
*/
|
||||
@@ -189,7 +190,8 @@ public:
|
||||
*
|
||||
* The handler will no longer be called by this timer.
|
||||
*
|
||||
* @param channel the channel whose interrupt to detach, from 1 to 4.
|
||||
* @param channel the channel whose interrupt to detach, from 0 to 4.
|
||||
* Channel 0 is for overflow interrupt (update interrupt).
|
||||
* @see HardwareTimer::attachInterrupt()
|
||||
*/
|
||||
void detachInterrupt(int channel);
|
||||
@@ -209,6 +211,23 @@ public:
|
||||
*/
|
||||
void refresh(void);
|
||||
|
||||
// SYFRE
|
||||
/**
|
||||
* @brief Set the Master mode TRGO signal
|
||||
* These bits allow to select the information to be sent in master mode to slave timers for
|
||||
* synchronization (TRGO).
|
||||
* mode:
|
||||
* TIMER_CR2_MMS_RESET
|
||||
* TIMER_CR2_MMS_ENABLE
|
||||
* TIMER_CR2_MMS_UPDATE
|
||||
* TIMER_CR2_MMS_COMPARE_PULSE
|
||||
* TIMER_CR2_MMS_COMPARE_OC1REF
|
||||
* TIMER_CR2_MMS_COMPARE_OC2REF
|
||||
* TIMER_CR2_MMS_COMPARE_OC3REF
|
||||
* TIMER_CR2_MMS_COMPARE_OC4REF
|
||||
*/
|
||||
void setMasterModeTrGo(uint32_t mode);
|
||||
|
||||
//CARLOS.
|
||||
/*
|
||||
added these functions to make sense for the encoder mode.
|
||||
@@ -228,6 +247,12 @@ public:
|
||||
|
||||
/* Escape hatch */
|
||||
|
||||
/**
|
||||
* @brief Enable/disable DMA request for the input channel.
|
||||
*/
|
||||
void enableDMA(int channel);
|
||||
void disableDMA(int channel);
|
||||
|
||||
/**
|
||||
* @brief Get a pointer to the underlying libmaple timer_dev for
|
||||
* this HardwareTimer instance.
|
||||
|
||||
@@ -44,6 +44,48 @@ IPAddress::IPAddress(const uint8_t *address)
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
}
|
||||
|
||||
bool IPAddress::fromString(const char *address)
|
||||
{
|
||||
// TODO: add support for "a", "a.b", "a.b.c" formats
|
||||
|
||||
uint16_t acc = 0; // Accumulator
|
||||
uint8_t dots = 0;
|
||||
|
||||
while (*address)
|
||||
{
|
||||
char c = *address++;
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
acc = acc * 10 + (c - '0');
|
||||
if (acc > 255) {
|
||||
// Value out of [0..255] range
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (c == '.')
|
||||
{
|
||||
if (dots == 3) {
|
||||
// Too much dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
_address.bytes[dots++] = acc;
|
||||
acc = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Invalid char
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dots != 3) {
|
||||
// Too few dots (there must be 3 dots)
|
||||
return false;
|
||||
}
|
||||
_address.bytes[3] = acc;
|
||||
return true;
|
||||
}
|
||||
|
||||
IPAddress& IPAddress::operator=(const uint8_t *address)
|
||||
{
|
||||
memcpy(_address.bytes, address, sizeof(_address.bytes));
|
||||
|
||||
@@ -46,6 +46,9 @@ public:
|
||||
IPAddress(uint32_t address);
|
||||
IPAddress(const uint8_t *address);
|
||||
|
||||
bool fromString(const char *address);
|
||||
bool fromString(const String &address) { return fromString(address.c_str()); }
|
||||
|
||||
// Overloaded cast operator to allow IPAddress objects to be used where a pointer
|
||||
// to a four-byte uint8_t array is expected
|
||||
operator uint32_t() const { return _address.dword; };
|
||||
|
||||
@@ -99,10 +99,6 @@ size_t Print::print(unsigned long n, int base) {
|
||||
}
|
||||
|
||||
size_t Print::print(long long n, int base) {
|
||||
if (base == BYTE)
|
||||
{
|
||||
return write((uint8)n);
|
||||
}
|
||||
if (n < 0) {
|
||||
print('-');
|
||||
n = -n;
|
||||
@@ -111,19 +107,23 @@ size_t Print::print(long long n, int 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;
|
||||
return printNumber(n, base);
|
||||
}
|
||||
|
||||
size_t Print::print(double n, int digits) {
|
||||
return printFloat(n, digits);
|
||||
}
|
||||
|
||||
size_t Print::print(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
return print(reinterpret_cast<const char *>(ifsh));
|
||||
}
|
||||
|
||||
size_t Print::print(const Printable& x)
|
||||
{
|
||||
return x.printTo(*this);
|
||||
}
|
||||
|
||||
size_t Print::println(void)
|
||||
{
|
||||
size_t n = print('\r');
|
||||
@@ -198,6 +198,20 @@ size_t Print::println(double n, int digits) {
|
||||
return s;
|
||||
}
|
||||
|
||||
size_t Print::println(const __FlashStringHelper *ifsh)
|
||||
{
|
||||
size_t n = print(ifsh);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t Print::println(const Printable& x)
|
||||
{
|
||||
size_t n = print(x);
|
||||
n += println();
|
||||
return n;
|
||||
}
|
||||
|
||||
#ifdef SUPPORTS_PRINTF
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include "WString.h"
|
||||
#include "Printable.h"
|
||||
|
||||
enum {
|
||||
BYTE = 0,
|
||||
BIN = 2,
|
||||
OCT = 8,
|
||||
DEC = 10,
|
||||
@@ -51,6 +51,8 @@ public:
|
||||
size_t print(long long, int=DEC);
|
||||
size_t print(unsigned long long, int=DEC);
|
||||
size_t print(double, int=2);
|
||||
size_t print(const __FlashStringHelper *);
|
||||
size_t print(const Printable&);
|
||||
size_t println(void);
|
||||
size_t println(const String &s);
|
||||
size_t println(char);
|
||||
@@ -63,6 +65,8 @@ public:
|
||||
size_t println(long long, int=DEC);
|
||||
size_t println(unsigned long long, int=DEC);
|
||||
size_t println(double, int=2);
|
||||
size_t println(const __FlashStringHelper *);
|
||||
size_t println(const Printable&);
|
||||
#ifdef SUPPORTS_PRINTF
|
||||
// Roger Clark. Work in progress to add printf support
|
||||
int printf(const char * format, ...);
|
||||
|
||||
@@ -268,3 +268,68 @@ String Stream::readStringUntil(char terminator)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) {
|
||||
// any zero length target string automatically matches and would make
|
||||
// a mess of the rest of the algorithm.
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
if (t->len <= 0)
|
||||
return t - targets;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int c = timedRead();
|
||||
if (c < 0)
|
||||
return -1;
|
||||
|
||||
for (struct MultiTarget *t = targets; t < targets+tCount; ++t) {
|
||||
// the simple case is if we match, deal with that first.
|
||||
if (c == t->str[t->index]) {
|
||||
if (++t->index == t->len)
|
||||
return t - targets;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
// if not we need to walk back and see if we could have matched further
|
||||
// down the stream (ie '1112' doesn't match the first position in '11112'
|
||||
// but it will match the second position so we can't just reset the current
|
||||
// index to 0 when we find a mismatch.
|
||||
if (t->index == 0)
|
||||
continue;
|
||||
|
||||
int origIndex = t->index;
|
||||
do {
|
||||
--t->index;
|
||||
// first check if current char works against the new current index
|
||||
if (c != t->str[t->index])
|
||||
continue;
|
||||
|
||||
// if it's the only char then we're good, nothing more to check
|
||||
if (t->index == 0) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we need to check the rest of the found string
|
||||
int diff = origIndex - t->index;
|
||||
size_t i;
|
||||
for (i = 0; i < t->index; ++i) {
|
||||
if (t->str[i] != t->str[i + diff])
|
||||
break;
|
||||
}
|
||||
|
||||
// if we successfully got through the previous loop then our current
|
||||
// index is good.
|
||||
if (i == t->index) {
|
||||
t->index++;
|
||||
break;
|
||||
}
|
||||
|
||||
// otherwise we just try the next index
|
||||
} while (t->index);
|
||||
}
|
||||
}
|
||||
// unreachable
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ class Stream : public Print
|
||||
// parsing methods
|
||||
|
||||
void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second
|
||||
unsigned long getTimeout(void) { return _timeout; }
|
||||
|
||||
bool find(char *target); // reads data from the stream until the target string is found
|
||||
bool find(uint8_t *target) { return find ((char *)target); }
|
||||
@@ -64,6 +65,8 @@ class Stream : public Print
|
||||
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 find(char target) { return find (&target, 1); }
|
||||
|
||||
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); }
|
||||
|
||||
@@ -97,6 +100,16 @@ class Stream : public Print
|
||||
// this allows format characters (typically commas) in values to be ignored
|
||||
|
||||
float parseFloat(char skipChar); // as above but the given skipChar is ignored
|
||||
|
||||
struct MultiTarget {
|
||||
const char *str; // string you're searching for
|
||||
size_t len; // length of string you're searching for
|
||||
size_t index; // index used by the search routine.
|
||||
};
|
||||
|
||||
// This allows you to search for an arbitrary number of strings.
|
||||
// Returns index of the target that is found first or -1 if timeout occurs.
|
||||
int findMulti(struct MultiTarget *targets, int tCount);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -195,7 +195,7 @@ String & String::copy(const __FlashStringHelper *pstr, unsigned int length)
|
||||
void String::move(String &rhs)
|
||||
{
|
||||
if (buffer) {
|
||||
if (capacity >= rhs.len) {
|
||||
if (rhs && capacity >= rhs.len) {
|
||||
strcpy(buffer, rhs.buffer);
|
||||
len = rhs.len;
|
||||
rhs.len = 0;
|
||||
|
||||
@@ -161,6 +161,10 @@ public:
|
||||
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; }
|
||||
char* begin() { return buffer; }
|
||||
char* end() { return buffer + length(); }
|
||||
const char* begin() const { return c_str(); }
|
||||
const char* end() const { return c_str() + length(); }
|
||||
|
||||
// search
|
||||
int indexOf( char ch ) const;
|
||||
|
||||
@@ -160,4 +160,6 @@ uint16 analogRead(uint8 pin);
|
||||
*/
|
||||
void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value);
|
||||
|
||||
uint32 shiftIn( uint32 ulDataPin, uint32 ulClockPin, uint32 ulBitOrder );
|
||||
|
||||
#endif
|
||||
|
||||
@@ -120,8 +120,12 @@ extern char* ltoa( long value, char *string, int radix )
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
extern char* utoa( unsigned long value, char *string, int radix )
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \
|
||||
(__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2)))
|
||||
extern char* utoa( unsigned value, char *string, int radix )
|
||||
#else
|
||||
extern char* utoa( unsigned int value, char *string, int radix )
|
||||
#endif
|
||||
{
|
||||
return ultoa( value, string, radix ) ;
|
||||
}
|
||||
|
||||
@@ -31,7 +31,12 @@ extern void itoa( int n, char s[] ) ;
|
||||
|
||||
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 ) ;
|
||||
#if __GNUC__ > 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ > 9 || \
|
||||
(__GNUC_MINOR__ == 9 && __GNUC_PATCHLEVEL__ > 2)))
|
||||
extern char* utoa( unsigned value, char *string, int radix ) ;
|
||||
#else
|
||||
extern char* utoa( unsigned int value, char *string, int radix ) ;
|
||||
#endif
|
||||
extern char* ultoa( unsigned long value, char *string, int radix ) ;
|
||||
#endif /* 0 */
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ void adc_set_extsel(adc_dev *dev, adc_extsel_event event) {
|
||||
uint32 cr2 = dev->regs->CR2;
|
||||
cr2 &= ~ADC_CR2_EXTSEL;
|
||||
cr2 |= event;
|
||||
cr2 |= ADC_CR2_EXTTRIG;
|
||||
dev->regs->CR2 = cr2;
|
||||
}
|
||||
|
||||
|
||||
@@ -203,7 +203,7 @@ void adc_foreach(void (*fn)(adc_dev*)) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void adc_config_gpio(adc_dev *ignored, gpio_dev *gdev, uint8 bit) {
|
||||
void adc_config_gpio(adc_dev *ignored __attribute__((unused)), gpio_dev *gdev, uint8 bit) {
|
||||
gpio_set_mode(gdev, bit, GPIO_INPUT_ANALOG);
|
||||
}
|
||||
|
||||
|
||||
@@ -341,7 +341,6 @@ void dma_set_per_addr(dma_dev *dev, dma_channel channel, __io void *addr) {
|
||||
* @see dma_attach_interrupt()
|
||||
* @see dma_enable()
|
||||
*/
|
||||
__deprecated
|
||||
void dma_setup_transfer(dma_dev *dev,
|
||||
dma_channel channel,
|
||||
__io void *peripheral_address,
|
||||
|
||||
@@ -142,7 +142,6 @@ 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;
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Nonblocking SPI transmit.
|
||||
* @brief Blocking 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
|
||||
@@ -93,15 +93,21 @@ void spi_slave_enable(spi_dev *dev, spi_mode mode, uint32 flags) {
|
||||
* @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++];
|
||||
}
|
||||
}
|
||||
uint32 txed = len;
|
||||
spi_reg_map *regs = dev->regs;
|
||||
if ( spi_dff(dev) == SPI_DFF_8_BIT ) {
|
||||
const uint8 * dp8 = (const uint8*)buf;
|
||||
while ( len-- ) {
|
||||
while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty
|
||||
regs->DR = *dp8++;
|
||||
}
|
||||
} else {
|
||||
const uint16 * dp16 = (const uint16*)buf;
|
||||
while ( len-- ) {
|
||||
while ( (regs->SR & SPI_SR_TXE)==0 ) ; //while ( spi_is_tx_empty(dev)==0 ); // wait Tx to be empty
|
||||
regs->DR = *dp16++;
|
||||
}
|
||||
}
|
||||
return txed;
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ spi_dev *SPI3 = &spi3;
|
||||
* Routines
|
||||
*/
|
||||
|
||||
void spi_config_gpios(spi_dev *ignored,
|
||||
void spi_config_gpios(spi_dev *ignored __attribute__((unused)),
|
||||
uint8 as_master,
|
||||
gpio_dev *nss_dev,
|
||||
uint8 nss_bit,
|
||||
|
||||
@@ -327,7 +327,7 @@ static void output_compare_mode(timer_dev *dev, uint8 channel) {
|
||||
}
|
||||
|
||||
//added by CARLOS.
|
||||
static void encoder_mode(timer_dev *dev, uint8 channel) {
|
||||
static void encoder_mode(timer_dev *dev, uint8 channel __attribute__((unused))) {
|
||||
|
||||
//prescaler.
|
||||
//(dev->regs).gen->PSC = 1;
|
||||
|
||||
@@ -203,15 +203,15 @@ void usart_foreach(void (*fn)(usart_dev*)) {
|
||||
void __irq_usart1(void) {
|
||||
usart_irq(&usart1_rb, &usart1_wb, USART1_BASE);
|
||||
}
|
||||
/*
|
||||
void __irq_usart2(void) {
|
||||
usart_irq(&usart2_rb, &usart2_wb, USART2_BASE);
|
||||
}
|
||||
|
||||
//void __irq_usart2(void) {
|
||||
// usart_irq(&usart2_rb, &usart2_wb, USART2_BASE);
|
||||
//}
|
||||
|
||||
//void __irq_usart3(void) {
|
||||
// usart_irq(&usart3_rb, &usart3_wb, USART3_BASE);
|
||||
//}
|
||||
|
||||
void __irq_usart3(void) {
|
||||
usart_irq(&usart3_rb, &usart3_wb, USART3_BASE);
|
||||
}
|
||||
*/
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
void __irq_uart4(void) {
|
||||
usart_irq(&uart4_rb, &uart4_wb, UART4_BASE);
|
||||
|
||||
@@ -62,8 +62,8 @@
|
||||
|
||||
#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.
|
||||
//#warning USB CDC ACM relies on LeafLabs board-specific configuration.\
|
||||
// You may have problems on non-LeafLabs boards.
|
||||
#endif
|
||||
|
||||
static void vcomDataTxCb(void);
|
||||
@@ -261,18 +261,28 @@ static ONE_DESCRIPTOR String_Descriptor[N_STRING_DESCRIPTORS] = {
|
||||
|
||||
/* I/O state */
|
||||
|
||||
#define CDC_SERIAL_BUFFER_SIZE 512
|
||||
#define CDC_SERIAL_RX_BUFFER_SIZE 256 // must be power of 2
|
||||
#define CDC_SERIAL_RX_BUFFER_SIZE_MASK (CDC_SERIAL_RX_BUFFER_SIZE-1)
|
||||
|
||||
/* 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;
|
||||
static volatile uint8 vcomBufferRx[CDC_SERIAL_RX_BUFFER_SIZE];
|
||||
/* Write index to vcomBufferRx */
|
||||
static volatile uint32 rx_head;
|
||||
/* Read index from vcomBufferRx */
|
||||
static volatile uint32 rx_tail;
|
||||
|
||||
#define CDC_SERIAL_TX_BUFFER_SIZE 256 // must be power of 2
|
||||
#define CDC_SERIAL_TX_BUFFER_SIZE_MASK (CDC_SERIAL_TX_BUFFER_SIZE-1)
|
||||
// Tx data
|
||||
static volatile uint8 vcomBufferTx[CDC_SERIAL_TX_BUFFER_SIZE];
|
||||
// Write index to vcomBufferTx
|
||||
static volatile uint32 tx_head;
|
||||
// Read index from vcomBufferTx
|
||||
static volatile uint32 tx_tail;
|
||||
// Are we currently sending an IN packet?
|
||||
static volatile int8 transmitting;
|
||||
|
||||
|
||||
|
||||
/* Other state (line coding, DTR/RTS) */
|
||||
|
||||
@@ -374,9 +384,13 @@ 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);
|
||||
|
||||
|
||||
if (disc_dev!=NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
@@ -385,7 +399,10 @@ 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);
|
||||
if (disc_dev!=NULL)
|
||||
{
|
||||
gpio_write_bit(disc_dev, disc_bit, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void usb_cdcacm_putc(char ch) {
|
||||
@@ -393,30 +410,34 @@ void usb_cdcacm_putc(char ch) {
|
||||
;
|
||||
}
|
||||
|
||||
/* This function is blocking.
|
||||
/* This function is non-blocking.
|
||||
*
|
||||
* It copies data from a usercode buffer into the USB peripheral TX
|
||||
* It copies data from a user 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. */
|
||||
while ( usb_cdcacm_is_transmitting()>0 ) ; // wait for end of transmission
|
||||
uint32 usb_cdcacm_tx(const uint8* buf, uint32 len)
|
||||
{
|
||||
if (len==0) return 0; // no data to send
|
||||
|
||||
/* We can only put USB_CDCACM_TX_EPSIZE bytes in the buffer. */
|
||||
if (len > USB_CDCACM_TX_EPSIZE) {
|
||||
len = USB_CDCACM_TX_EPSIZE;
|
||||
}
|
||||
uint32 head = tx_head; // load volatile variable
|
||||
uint32 tx_unsent = (head - tx_tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK;
|
||||
|
||||
/* Queue bytes for sending. */
|
||||
if (len) {
|
||||
usb_copy_to_pma(buf, len, USB_CDCACM_TX_ADDR);
|
||||
// We can only put bytes in the buffer if there is place
|
||||
if (len > (CDC_SERIAL_TX_BUFFER_SIZE-tx_unsent-1) ) {
|
||||
len = (CDC_SERIAL_TX_BUFFER_SIZE-tx_unsent-1);
|
||||
}
|
||||
// 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);
|
||||
if (len==0) return 0; // buffer full
|
||||
|
||||
uint16 i;
|
||||
// copy data from user buffer to USB Tx buffer
|
||||
for (i=0; i<len; i++) {
|
||||
vcomBufferTx[head] = buf[i];
|
||||
head = (head+1) & CDC_SERIAL_TX_BUFFER_SIZE_MASK;
|
||||
}
|
||||
tx_head = head; // store volatile variable
|
||||
|
||||
if (transmitting<0) {
|
||||
vcomDataTxCb(); // initiate data transmission
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
@@ -424,69 +445,73 @@ uint32 usb_cdcacm_tx(const uint8* buf, uint32 len) {
|
||||
|
||||
|
||||
uint32 usb_cdcacm_data_available(void) {
|
||||
return n_unread_bytes;
|
||||
return (rx_head - rx_tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
}
|
||||
|
||||
uint8 usb_cdcacm_is_transmitting(void) {
|
||||
return transmitting;
|
||||
return ( transmitting>0 ? transmitting : 0);
|
||||
}
|
||||
|
||||
uint16 usb_cdcacm_get_pending(void) {
|
||||
return n_unsent_bytes;
|
||||
return (tx_head - tx_tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK;
|
||||
}
|
||||
|
||||
/* Nonblocking byte receive.
|
||||
/* Non-blocking 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) {
|
||||
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;
|
||||
uint16 tail = rx_tail; // load volatile variable
|
||||
tail = (tail + n_copied) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
rx_tail = tail; // store volatile variable
|
||||
|
||||
/* 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 == 0) {
|
||||
usb_set_ep_rx_count(USB_CDCACM_RX_ENDP, USB_CDCACM_RX_EPSIZE);
|
||||
uint32 rx_unread = (rx_head - tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
// If buffer was emptied to a pre-set value, re-enable the RX endpoint
|
||||
if ( rx_unread <= 64 ) { // experimental value, gives the best performance
|
||||
usb_set_ep_rx_stat(USB_CDCACM_RX_ENDP, USB_EP_STAT_RX_VALID);
|
||||
}
|
||||
|
||||
}
|
||||
return n_copied;
|
||||
}
|
||||
|
||||
/* Nonblocking byte lookahead.
|
||||
/* Non-blocking byte lookahead.
|
||||
*
|
||||
* Looks at unread bytes without marking them as read. */
|
||||
uint32 usb_cdcacm_peek(uint8* buf, uint32 len) {
|
||||
uint32 usb_cdcacm_peek(uint8* buf, uint32 len)
|
||||
{
|
||||
int i;
|
||||
uint32 head = rx_offset;
|
||||
uint32 tail = rx_tail;
|
||||
uint32 rx_unread = (rx_head-tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
|
||||
if (len > n_unread_bytes) {
|
||||
len = n_unread_bytes;
|
||||
if (len > rx_unread) {
|
||||
len = rx_unread;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = vcomBufferRx[head];
|
||||
head = (head + 1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
buf[i] = vcomBufferRx[tail];
|
||||
tail = (tail + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
uint32 usb_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len) {
|
||||
uint32 usb_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len)
|
||||
{
|
||||
int i;
|
||||
uint32 head = (rx_offset + offset) % CDC_SERIAL_BUFFER_SIZE;
|
||||
uint32 tail = (rx_tail + offset) & CDC_SERIAL_RX_BUFFER_SIZE_MASK ;
|
||||
uint32 rx_unread = (rx_head-tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
|
||||
if (len + offset > n_unread_bytes) {
|
||||
len = n_unread_bytes - offset;
|
||||
if (len + offset > rx_unread) {
|
||||
len = rx_unread - offset;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
buf[i] = vcomBufferRx[head];
|
||||
head = (head + 1) % CDC_SERIAL_BUFFER_SIZE;
|
||||
buf[i] = vcomBufferRx[tail];
|
||||
tail = (tail + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
}
|
||||
|
||||
return len;
|
||||
@@ -495,12 +520,12 @@ uint32 usb_cdcacm_peek_ex(uint8* buf, uint32 offset, uint32 len) {
|
||||
/* Roger Clark. Added. for Arduino 1.0 API support of Serial.peek() */
|
||||
int usb_cdcacm_peek_char()
|
||||
{
|
||||
if (n_unread_bytes == 0)
|
||||
if (usb_cdcacm_data_available() == 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return vcomBufferRx[rx_offset];
|
||||
return vcomBufferRx[rx_tail];
|
||||
}
|
||||
|
||||
uint8 usb_cdcacm_get_dtr() {
|
||||
@@ -534,41 +559,75 @@ 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 vcomDataTxCb(void)
|
||||
{
|
||||
uint32 tail = tx_tail; // load volatile variable
|
||||
uint32 tx_unsent = (tx_head - tail) & CDC_SERIAL_TX_BUFFER_SIZE_MASK;
|
||||
if (tx_unsent==0) {
|
||||
if ( (--transmitting)==0) goto flush; // no more data to send
|
||||
return; // it was already flushed, keep Tx endpoint disabled
|
||||
}
|
||||
transmitting = 1;
|
||||
// We can only send up to USB_CDCACM_TX_EPSIZE bytes in the endpoint.
|
||||
if (tx_unsent > USB_CDCACM_TX_EPSIZE) {
|
||||
tx_unsent = USB_CDCACM_TX_EPSIZE;
|
||||
}
|
||||
// copy the bytes from USB Tx buffer to PMA buffer
|
||||
uint32 *dst = usb_pma_ptr(USB_CDCACM_TX_ADDR);
|
||||
uint16 tmp = 0;
|
||||
uint16 val;
|
||||
int i;
|
||||
for (i = 0; i < tx_unsent; i++) {
|
||||
val = vcomBufferTx[tail];
|
||||
tail = (tail + 1) & CDC_SERIAL_TX_BUFFER_SIZE_MASK;
|
||||
if (i&1) {
|
||||
*dst++ = tmp | (val<<8);
|
||||
} else {
|
||||
tmp = val;
|
||||
}
|
||||
}
|
||||
if ( tx_unsent&1 ) {
|
||||
*dst = tmp;
|
||||
}
|
||||
tx_tail = tail; // store volatile variable
|
||||
flush:
|
||||
// enable Tx endpoint
|
||||
usb_set_ep_tx_count(USB_CDCACM_TX_ENDP, tx_unsent);
|
||||
usb_set_ep_tx_stat(USB_CDCACM_TX_ENDP, USB_EP_STAT_TX_VALID);
|
||||
}
|
||||
|
||||
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];
|
||||
|
||||
static void vcomDataRxCb(void)
|
||||
{
|
||||
uint32 head = rx_head; // load volatile variable
|
||||
|
||||
uint32 ep_rx_size = usb_get_ep_rx_count(USB_CDCACM_RX_ENDP);
|
||||
// This copy won't overwrite unread bytes as long as there is
|
||||
// enough room in the USB Rx buffer for next packet
|
||||
uint32 *src = usb_pma_ptr(USB_CDCACM_RX_ADDR);
|
||||
uint16 tmp = 0;
|
||||
uint8 val;
|
||||
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;
|
||||
if (i&1) {
|
||||
val = tmp>>8;
|
||||
} else {
|
||||
tmp = *src++;
|
||||
val = tmp&0xFF;
|
||||
}
|
||||
vcomBufferRx[head] = val;
|
||||
head = (head + 1) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
}
|
||||
rx_head = head; // store volatile variable
|
||||
|
||||
n_unread_bytes += ep_rx_size;
|
||||
|
||||
if ( n_unread_bytes == 0 ) {
|
||||
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);
|
||||
}
|
||||
uint32 rx_unread = (head - rx_tail) & CDC_SERIAL_RX_BUFFER_SIZE_MASK;
|
||||
// only enable further Rx if there is enough room to receive one more packet
|
||||
if ( rx_unread < (CDC_SERIAL_RX_BUFFER_SIZE-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);
|
||||
@@ -646,10 +705,11 @@ static void usbReset(void) {
|
||||
SetDeviceAddress(0);
|
||||
|
||||
/* Reset the RX/TX state */
|
||||
n_unread_bytes = 0;
|
||||
n_unsent_bytes = 0;
|
||||
rx_offset = 0;
|
||||
transmitting = 0;
|
||||
rx_head = 0;
|
||||
rx_tail = 0;
|
||||
tx_head = 0;
|
||||
tx_tail = 0;
|
||||
transmitting = -1;
|
||||
}
|
||||
|
||||
static RESULT usbDataSetup(uint8 request) {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
/* 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. */
|
||||
* measurement and tuning.
|
||||
|
||||
void usb_copy_to_pma(const uint8 *buf, uint16 len, uint16 pma_offset) {
|
||||
uint16 *dst = (uint16*)usb_pma_ptr(pma_offset);
|
||||
@@ -57,7 +57,7 @@ void usb_copy_from_pma(uint8 *buf, uint16 len, uint16 pma_offset) {
|
||||
*dst = *src & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) {
|
||||
uint16 nblocks;
|
||||
if (count > 62) {
|
||||
@@ -76,12 +76,12 @@ static void usb_set_ep_rx_count_common(uint32 *rxc, uint16 count) {
|
||||
*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);
|
||||
|
||||
@@ -88,7 +88,7 @@ void _fail(const char* file, int line, const char* exp) {
|
||||
* 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,
|
||||
void __assert_func(const char* file, int line, const char* method __attribute__((unused)),
|
||||
const char* expression) {
|
||||
_fail(file, line, expression);
|
||||
}
|
||||
|
||||
36
BootLoaders/Boards/stm32/cores/maple/new.cpp
Normal file
36
BootLoaders/Boards/stm32/cores/maple/new.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
Copyright (c) 2014 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 <stdlib.h>
|
||||
|
||||
void *operator new(size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void *operator new[](size_t size) {
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void operator delete(void * ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
void operator delete[](void * ptr) {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
198
BootLoaders/Boards/stm32/cores/maple/sdio.cpp
Normal file
198
BootLoaders/Boards/stm32/cores/maple/sdio.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/******************************************************************************
|
||||
* 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/sdio.c
|
||||
* @author stevstrong
|
||||
* @brief Secure digital input/output interface.
|
||||
*/
|
||||
|
||||
#include <libmaple/sdio.h>
|
||||
#include <libmaple/gpio.h>
|
||||
#include <boards.h>
|
||||
#include "wirish.h"
|
||||
|
||||
|
||||
//#include <libmaple/libmaple.h>
|
||||
//#include <libmaple/rcc.h>
|
||||
//#include <series/gpio.h>
|
||||
//#include "wirish.h"
|
||||
//#include "boards.h"
|
||||
//
|
||||
|
||||
#if defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
|
||||
sdio_dev * SDIO = SDIO_BASE;
|
||||
|
||||
#define DELAY_LONG 10
|
||||
#define DELAY_SHORT 1
|
||||
|
||||
uint8_t dly = DELAY_LONG; // microseconds delay after accessing registers
|
||||
|
||||
/*
|
||||
* SDIO convenience routines
|
||||
*/
|
||||
void sdio_gpios_init(void)
|
||||
{
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_AF_OUTPUT_PP);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_AF_OUTPUT_PP);
|
||||
/*
|
||||
* Todo just remove it, not needed for F1.
|
||||
*/
|
||||
/*
|
||||
gpio_set_af_mode(BOARD_SDIO_D0, 12);
|
||||
gpio_set_af_mode(BOARD_SDIO_D1, 12);
|
||||
gpio_set_af_mode(BOARD_SDIO_D2, 12);
|
||||
gpio_set_af_mode(BOARD_SDIO_D3, 12);
|
||||
gpio_set_af_mode(BOARD_SDIO_CLK, 12);
|
||||
gpio_set_af_mode(BOARD_SDIO_CMD, 12);
|
||||
*/
|
||||
}
|
||||
|
||||
void sdio_gpios_deinit(void)
|
||||
{
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D0].gpio_device, PIN_MAP[BOARD_SDIO_D0].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D1].gpio_device, PIN_MAP[BOARD_SDIO_D1].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D2].gpio_device, PIN_MAP[BOARD_SDIO_D2].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_D3].gpio_device, PIN_MAP[BOARD_SDIO_D3].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_CLK].gpio_device, PIN_MAP[BOARD_SDIO_CLK].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
gpio_set_mode(PIN_MAP[BOARD_SDIO_CMD].gpio_device, PIN_MAP[BOARD_SDIO_CMD].gpio_bit, GPIO_INPUT_FLOATING);
|
||||
|
||||
/*
|
||||
* Todo just remove it, not needed for F1.
|
||||
*/
|
||||
/*
|
||||
gpio_set_af_mode(BOARD_SDIO_D0, 0);
|
||||
gpio_set_af_mode(BOARD_SDIO_D1, 0);
|
||||
gpio_set_af_mode(BOARD_SDIO_D2, 0);
|
||||
gpio_set_af_mode(BOARD_SDIO_D3, 0);
|
||||
gpio_set_af_mode(BOARD_SDIO_CLK, 0);
|
||||
gpio_set_af_mode(BOARD_SDIO_CMD, 0);
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize and reset the SDIO device.
|
||||
*/
|
||||
void sdio_init(void)
|
||||
{
|
||||
rcc_clk_enable(RCC_SDIO);
|
||||
rcc_reset_dev(RCC_SDIO);
|
||||
}
|
||||
|
||||
void sdio_power_on(void)
|
||||
{
|
||||
SDIO->POWER = SDIO_POWER_PWRCTRL_ON;
|
||||
// After a data write, data cannot be written to this register for three SDIOCLK clock periods
|
||||
// plus two PCLK2 clock periods.
|
||||
delay_us(DELAY_LONG);
|
||||
}
|
||||
|
||||
void sdio_power_off(void)
|
||||
{
|
||||
SDIO->POWER = SDIO_POWER_PWRCTRL_OFF;
|
||||
// After a data write, data cannot be written to this register for three SDIOCLK clock periods
|
||||
// plus two PCLK2 clock periods.
|
||||
delay_us(DELAY_LONG);
|
||||
}
|
||||
|
||||
void sdio_set_clock(uint32_t clk)
|
||||
{
|
||||
if (clk>24000000UL) clk = 24000000UL; // limit the SDIO master clock to 24MHz
|
||||
|
||||
if (clk<1000000) dly = DELAY_LONG;
|
||||
else dly = DELAY_SHORT;
|
||||
|
||||
sdio_disable();
|
||||
SDIO->CLKCR = (SDIO->CLKCR & (~(SDIO_CLKCR_CLKDIV|SDIO_CLKCR_BYPASS))) | SDIO_CLKCR_CLKEN | (((SDIOCLK/clk)-2)&SDIO_CLKCR_CLKDIV);
|
||||
delay_us(dly);
|
||||
}
|
||||
|
||||
void sdio_set_dbus_width(uint16_t bus_w)
|
||||
{
|
||||
SDIO->CLKCR = (SDIO->CLKCR & (~SDIO_CLKCR_WIDBUS)) | bus_w;
|
||||
delay_us(dly);
|
||||
}
|
||||
|
||||
void sdio_set_dblock_size(uint8_t dbsize)
|
||||
{
|
||||
SDIO->DCTRL = (SDIO->DCTRL&(~SDIO_DCTRL_DBLOCKSIZE)) | ((dbsize&0xF)<<4);
|
||||
delay_us(dly);
|
||||
}
|
||||
|
||||
void sdio_enable(void)
|
||||
{
|
||||
SDIO->CLKCR |= SDIO_CLKCR_CLKEN;
|
||||
delay_us(dly);
|
||||
}
|
||||
|
||||
void sdio_disable(void)
|
||||
{
|
||||
SDIO->CLKCR ^= SDIO_CLKCR_CLKEN;
|
||||
delay_us(dly);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure and enable the SDIO device.
|
||||
*/
|
||||
void sdio_begin(void)
|
||||
{
|
||||
sdio_gpios_init();
|
||||
sdio_init();
|
||||
sdio_power_on();
|
||||
// Set initial SCK rate.
|
||||
sdio_set_clock(400000);
|
||||
delay_us(200); // generate 80 pulses at 400kHz
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the SDIO device.
|
||||
*/
|
||||
void sdio_end(void)
|
||||
{
|
||||
sdio_disable();
|
||||
while ( sdio_cmd_xfer_ongoing() );
|
||||
sdio_power_off();
|
||||
rcc_clk_disable(RCC_SDIO);
|
||||
sdio_gpios_deinit();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send command by the SDIO device.
|
||||
*/
|
||||
uint8_t sdio_cmd_send(uint16_t cmd_index_resp_type, uint32_t arg)
|
||||
{
|
||||
uint8_t retries = 10; // in case of errors
|
||||
do { // retry command if errors detected
|
||||
// clear interrupt flags - IMPORTANT!!!
|
||||
SDIO->ICR = SDIO_ICR_CMD_FLAGS;
|
||||
// write command
|
||||
SDIO->ARG = arg;
|
||||
SDIO->CMD = (uint32_t)(SDIO_CMD_CPSMEN | cmd_index_resp_type );
|
||||
while ( (SDIO->STA&SDIO_STA_CMDACT) ) ; // wait for actual command transfer to finish
|
||||
// wait for response, if the case
|
||||
if ( cmd_index_resp_type&(SDIO_CMD_WAIT_SHORT_RESP|SDIO_CMD_WAIT_LONG_RESP) ) {
|
||||
while ( !(SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CMD_ERROR_FLAGS)) ) ;
|
||||
} else break; // no response required
|
||||
if ( SDIO->STA&(SDIO_STA_CMDREND|SDIO_STA_CTIMEOUT) )
|
||||
break; // response received or timeout
|
||||
// ignore CRC error for CMD5 and ACMD41
|
||||
if ( ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==5) || ((cmd_index_resp_type&SDIO_CMD_CMDINDEX)==41) )
|
||||
break;
|
||||
} while ( (--retries) );
|
||||
return (uint8_t)retries;
|
||||
}
|
||||
|
||||
#endif // defined(STM32_HIGH_DENSITY) || defined(STM32_XL_DENSITY)
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <wiring_pulse.h>
|
||||
#include "boards.h"
|
||||
#include "variant.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
|
||||
@@ -28,13 +29,13 @@
|
||||
*/
|
||||
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
|
||||
// cache the IDR address 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);
|
||||
|
||||
__io uint32_t * const idr = portInputRegister(digitalPinToPort(pin));
|
||||
const uint32_t bit = digitalPinToBitMask(pin);
|
||||
const uint32_t stateMask = (state ? bit:0);
|
||||
|
||||
uint32_t width = 0; // keep initialization out of time critical area
|
||||
|
||||
@@ -45,23 +46,23 @@ uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout )
|
||||
volatile uint32_t dummyWidth=0;
|
||||
|
||||
// wait for any previous pulse to end
|
||||
while ( (dev->regs->IDR & bit) == bit) {
|
||||
while ((*idr & bit) == stateMask) {
|
||||
if (numloops++ == maxloops) {
|
||||
return 0;
|
||||
}
|
||||
dummyWidth++;
|
||||
dummyWidth++;
|
||||
}
|
||||
|
||||
// wait for the pulse to start
|
||||
while ((dev->regs->IDR & bit) != bit) {
|
||||
while ((*idr & bit) != stateMask) {
|
||||
if (numloops++ == maxloops) {
|
||||
return 0;
|
||||
}
|
||||
dummyWidth++;
|
||||
dummyWidth++;
|
||||
}
|
||||
|
||||
// wait for the pulse to stop
|
||||
while ((dev->regs->IDR & bit) == bit) {
|
||||
while ((*idr & bit) == stateMask) {
|
||||
if (numloops++ == maxloops) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -80,10 +80,13 @@ void pinMode(uint8 pin, WiringPinMode mode) {
|
||||
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. */
|
||||
if ( pwm ) { // we're switching into PWM, enable timer channels
|
||||
timer_set_mode(PIN_MAP[pin].timer_device,
|
||||
PIN_MAP[pin].timer_channel,
|
||||
pwm ? TIMER_PWM : TIMER_DISABLED);
|
||||
TIMER_PWM );
|
||||
} else { // disable channel output in non pwm-Mode
|
||||
timer_cc_disable(PIN_MAP[pin].timer_device,
|
||||
PIN_MAP[pin].timer_channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
205
BootLoaders/Boards/stm32/cores/maple/tone.cpp
Normal file
205
BootLoaders/Boards/stm32/cores/maple/tone.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// tone(pin,frequency[,duration]) generate a tone on a given pin
|
||||
//
|
||||
// noTone(pin) switch off the tone on the pin
|
||||
//
|
||||
// setToneTimerChannel(timer,channel) force use of given timer/channel
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <HardwareTimer.h>
|
||||
|
||||
|
||||
#define PinTimer(pin) (PIN_MAP[pin].timer_device->clk_id-RCC_TIMER1+1)
|
||||
#define PinChannel(pin) (PIN_MAP[pin].timer_channel)
|
||||
|
||||
// if USE_PIN_TIMER is set, the PWM timer/channel is used for PWM pins
|
||||
#define USE_PIN_TIMER
|
||||
|
||||
// if USE_BSRR is set the tone pin will be written via the fast BSRR register
|
||||
// instead of using the slow digitalWrite() function in the interrupt handler
|
||||
#define USE_BSRR
|
||||
|
||||
// construct static timer array (
|
||||
|
||||
|
||||
#ifdef STM32_HIGH_DENSITY
|
||||
// define default timer and channel
|
||||
#ifndef TONE_TIMER
|
||||
#define TONE_TIMER 8
|
||||
#endif
|
||||
#ifndef TONE_CHANNEL
|
||||
#define TONE_CHANNEL 8
|
||||
#endif
|
||||
|
||||
HardwareTimer TTimer1(1), TTimer2(2), TTimer3(3), TTimer4(4),TTimer5(5), TTimer6(6), TTimer7(7), TTimer8(8);
|
||||
HardwareTimer *TTimer[8] = { &TTimer1,&TTimer2,&TTimer3,&TTimer4,&TTimer5,&TTimer6,&TTimer7,&TTimer8 };
|
||||
#else
|
||||
// define default timer and channel
|
||||
#ifndef TONE_TIMER
|
||||
#define TONE_TIMER 4
|
||||
#endif
|
||||
#ifndef TONE_CHANNEL
|
||||
#define TONE_CHANNEL 4
|
||||
#endif
|
||||
|
||||
HardwareTimer TTimer1(1), TTimer2(2), TTimer3(3), TTimer4(4);
|
||||
HardwareTimer *TTimer[4] = { &TTimer1,&TTimer2,&TTimer3,&TTimer4 };
|
||||
#endif
|
||||
|
||||
|
||||
uint8_t tone_force_channel = 0; // forced timer channel
|
||||
uint8_t tone_force_ntimer = 0; // forced timer
|
||||
|
||||
HardwareTimer *tone_timer;// = TTimer[TONE_TIMER-1]; // timer used to generate frequency
|
||||
uint8_t tone_channel = TONE_CHANNEL; // timer channel used to generate frequency
|
||||
uint8_t tone_ntimer = TONE_TIMER; // timer used to generate frequency
|
||||
|
||||
bool tone_state = true; // last pin state for toggling
|
||||
short tone_pin = -1; // pin for outputting sound
|
||||
short tone_freq = 444; // tone frequency (0=pause)
|
||||
volatile uint32_t tone_nhw = 0; // tone duration in number of half waves
|
||||
uint16_t tone_tcount = 0; // time between handler calls in 1/36 usec
|
||||
uint16_t tone_ncount = 0; // handler call between toggling
|
||||
uint16_t tone_n = 0; // remaining handler calls before toggling
|
||||
uint32_t tone_next = 0; // counter value of next interrupt
|
||||
|
||||
#ifdef USE_BSRR
|
||||
volatile uint32_t *tone_bsrr; // BSRR set register (lower 16 bits)
|
||||
uint32_t tone_smask=0; // BSRR set bitmask
|
||||
uint32_t tone_rmask=0; // BSRR reset bitmask
|
||||
#endif
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// timer hander for tone with no duration specified,
|
||||
// will keep going until noTone() is called
|
||||
void tone_handler_1(void) {
|
||||
tone_next += tone_tcount; // comparator value for next interrupt
|
||||
tone_timer->setCompare(tone_channel, tone_next); // and install it
|
||||
if(--tone_n == 0){
|
||||
tone_state = !tone_state; // toggle tone output
|
||||
|
||||
#ifdef USE_BSRR
|
||||
if(tone_state)
|
||||
*tone_bsrr = tone_smask;
|
||||
else
|
||||
*tone_bsrr = tone_rmask;
|
||||
#else
|
||||
digitalWrite(tone_pin,tone_state);// and output it
|
||||
#endif
|
||||
|
||||
tone_n = tone_ncount; // reset interrupt counter
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// timer hander for tone with a specified duration,
|
||||
// will stop automatically when duration time is up.
|
||||
void tone_handler_2(void) {
|
||||
tone_next += tone_tcount;
|
||||
tone_timer->setCompare(tone_channel, tone_next);
|
||||
if(--tone_n == 0){
|
||||
if(tone_freq>0){ // toggle pin
|
||||
tone_state = !tone_state;
|
||||
#ifdef USE_BSRR
|
||||
if(tone_state)
|
||||
*tone_bsrr = tone_smask;
|
||||
else
|
||||
*tone_bsrr = tone_rmask;
|
||||
#else
|
||||
digitalWrite(tone_pin,tone_state);// and output it
|
||||
#endif
|
||||
}
|
||||
tone_n = tone_ncount;
|
||||
if(!--tone_nhw){ // check if tone duration has finished
|
||||
tone_timer->pause(); // disable timer
|
||||
pinMode(tone_pin, INPUT); // disable tone pin
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// play a tone on given pin with given frequency and optional duration in msec
|
||||
void tone(uint32_t pin, uint32_t freq, uint32_t duration) {
|
||||
tone_pin = pin;
|
||||
|
||||
#ifdef USE_PIN_TIMER
|
||||
// if the pin has a PWM timer/channel, use it (unless the timer/channel are forced)
|
||||
if(PinChannel(tone_pin) && !tone_force_channel){
|
||||
tone_channel = PinChannel(tone_pin);
|
||||
tone_ntimer = PinTimer(tone_pin);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
// set timer and channel to default resp values forced with setToneTimerChannel
|
||||
tone_ntimer = tone_force_channel?tone_force_ntimer:TONE_TIMER;
|
||||
tone_channel = tone_force_channel?tone_force_channel:TONE_CHANNEL;
|
||||
}
|
||||
|
||||
tone_timer = TTimer[tone_ntimer-1];
|
||||
tone_freq = freq;
|
||||
tone_nhw = 0;
|
||||
tone_next = 0;
|
||||
|
||||
tone_timer->pause();
|
||||
|
||||
if(freq > 0){
|
||||
uint32_t count = (F_CPU/4)/freq; // timer counts per half wave
|
||||
tone_ncount = tone_n = (count>>16)+1; // number of 16-bit count chunk
|
||||
tone_tcount = count/tone_ncount; // size of count chunk
|
||||
if(duration > 0) // number of half waves to be generated
|
||||
tone_nhw = ((duration*freq)/1000)<<1;
|
||||
else // no duration specified, continuous sound until noTone() called
|
||||
tone_nhw = 0;
|
||||
|
||||
pinMode(tone_pin, PWM); // configure output pin
|
||||
pinMode(tone_pin, OUTPUT); // configure output pin
|
||||
|
||||
#ifdef USE_BSRR
|
||||
// Set up BSRR register values for fast ISR
|
||||
tone_bsrr = &((PIN_MAP[tone_pin].gpio_device)->regs->BSRR);
|
||||
tone_smask = (BIT(PIN_MAP[tone_pin].gpio_bit));
|
||||
tone_rmask = tone_smask<<16;
|
||||
#endif
|
||||
|
||||
// Set up an interrupt on given timer and channel
|
||||
tone_next = tone_tcount; // prepare channel compare register
|
||||
tone_timer->setMode(tone_channel,TIMER_OUTPUT_COMPARE);
|
||||
tone_timer->setCompare(tone_channel,tone_next);
|
||||
// attach corresponding handler routine
|
||||
tone_timer->attachInterrupt(tone_channel,tone_nhw?tone_handler_2:tone_handler_1);
|
||||
|
||||
// Refresh the tone timer
|
||||
tone_timer->refresh();
|
||||
|
||||
// Start the timer counting
|
||||
tone_timer->resume();
|
||||
|
||||
} else {
|
||||
|
||||
// detach handler routine
|
||||
tone_timer->detachInterrupt(tone_channel);
|
||||
// disactive pin by configuring it as input
|
||||
pinMode(tone_pin, INPUT);
|
||||
|
||||
}
|
||||
|
||||
//while(tone_nhw) ; // blocks till duration elapsed
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// disable tone on specified pin, if any
|
||||
void noTone(uint32_t pin){
|
||||
tone(pin,0,0); // it's all handled in tone()
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// set timer and channel to some different value
|
||||
// must be called before calling tone() or after noTone() was called
|
||||
void setToneTimerChannel(uint8_t ntimer, uint8_t channel){
|
||||
tone_force_ntimer = ntimer;
|
||||
tone_force_channel = channel;
|
||||
}
|
||||
28
BootLoaders/Boards/stm32/cores/maple/tone.h
Normal file
28
BootLoaders/Boards/stm32/cores/maple/tone.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright (c) 2015 Arduino LLC. 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
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
void tone(uint32_t _pin, uint32_t frequency, uint32_t duration = 0);
|
||||
void noTone(uint32_t _pin);
|
||||
|
||||
#endif
|
||||
@@ -54,6 +54,9 @@ static void ifaceSetupHook(unsigned, void*);
|
||||
*/
|
||||
|
||||
#define USB_TIMEOUT 50
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
bool USBSerial::_hasBegun = false;
|
||||
#endif
|
||||
|
||||
USBSerial::USBSerial(void) {
|
||||
#if !BOARD_HAVE_SERIALUSB
|
||||
@@ -62,8 +65,13 @@ USBSerial::USBSerial(void) {
|
||||
}
|
||||
|
||||
void USBSerial::begin(void) {
|
||||
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
usb_cdcacm_enable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
if (_hasBegun)
|
||||
return;
|
||||
_hasBegun = true;
|
||||
|
||||
usb_cdcacm_enable(BOARD_USB_DISC_DEV, (uint8_t)BOARD_USB_DISC_BIT);
|
||||
usb_cdcacm_set_hooks(USB_CDCACM_HOOK_RX, rxHook);
|
||||
usb_cdcacm_set_hooks(USB_CDCACM_HOOK_IFACE_SETUP, ifaceSetupHook);
|
||||
#endif
|
||||
@@ -75,6 +83,7 @@ void USBSerial::begin(unsigned long ignoreBaud)
|
||||
volatile unsigned long removeCompilerWarningsIgnoreBaud=ignoreBaud;
|
||||
|
||||
ignoreBaud=removeCompilerWarningsIgnoreBaud;
|
||||
begin();
|
||||
}
|
||||
void USBSerial::begin(unsigned long ignoreBaud, uint8_t ignore)
|
||||
{
|
||||
@@ -83,13 +92,16 @@ volatile uint8_t removeCompilerWarningsIgnore=ignore;
|
||||
|
||||
ignoreBaud=removeCompilerWarningsIgnoreBaud;
|
||||
ignore=removeCompilerWarningsIgnore;
|
||||
begin();
|
||||
}
|
||||
|
||||
void USBSerial::end(void) {
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
usb_cdcacm_disable(BOARD_USB_DISC_DEV, BOARD_USB_DISC_BIT);
|
||||
usb_cdcacm_disable(BOARD_USB_DISC_DEV, (uint8_t)BOARD_USB_DISC_BIT);
|
||||
usb_cdcacm_remove_hooks(USB_CDCACM_HOOK_RX | USB_CDCACM_HOOK_IFACE_SETUP);
|
||||
_hasBegun = false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
size_t USBSerial::write(uint8 ch) {
|
||||
@@ -100,44 +112,23 @@ size_t n = 0;
|
||||
|
||||
size_t USBSerial::write(const char *str) {
|
||||
size_t n = 0;
|
||||
this->write(str, strlen(str));
|
||||
this->write((const uint8*)str, strlen(str));
|
||||
return n;
|
||||
}
|
||||
|
||||
size_t USBSerial::write(const void *buf, uint32 len) {
|
||||
size_t USBSerial::write(const uint8 *buf, uint32 len)
|
||||
{
|
||||
size_t n = 0;
|
||||
if (!this->isConnected() || !buf) {
|
||||
if (!(bool) *this || !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;
|
||||
while (txed < len) {
|
||||
txed += usb_cdcacm_tx((const uint8*)buf + txed, len - txed);
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
// this code leads to a serious performance drop and appears to be
|
||||
// unnecessary - everything seems to work fine without, -jcw, 2015-11-05
|
||||
// see http://stm32duino.com/posting.php?mode=quote&f=3&p=7746
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
return n;
|
||||
return n;
|
||||
}
|
||||
|
||||
int USBSerial::available(void) {
|
||||
@@ -168,19 +159,28 @@ void USBSerial::flush(void)
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 USBSerial::read(void *buf, uint32 len) {
|
||||
if (!buf) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32 USBSerial::read(uint8 * buf, uint32 len) {
|
||||
uint32 rxed = 0;
|
||||
while (rxed < len) {
|
||||
rxed += usb_cdcacm_rx((uint8*)buf + rxed, len - rxed);
|
||||
rxed += usb_cdcacm_rx(buf + rxed, len - rxed);
|
||||
}
|
||||
|
||||
return rxed;
|
||||
}
|
||||
|
||||
size_t USBSerial::readBytes(char *buf, const size_t& len)
|
||||
{
|
||||
size_t rxed=0;
|
||||
unsigned long startMillis;
|
||||
startMillis = millis();
|
||||
if (len <= 0) return 0;
|
||||
do {
|
||||
rxed += usb_cdcacm_rx((uint8 *)buf + rxed, len - rxed);
|
||||
if (rxed == len) return rxed;
|
||||
} while(millis() - startMillis < _timeout);
|
||||
return rxed;
|
||||
}
|
||||
|
||||
/* Blocks forever until 1 byte is received */
|
||||
int USBSerial::read(void) {
|
||||
uint8 b;
|
||||
@@ -203,10 +203,6 @@ uint8 USBSerial::pending(void) {
|
||||
return usb_cdcacm_get_pending();
|
||||
}
|
||||
|
||||
uint8 USBSerial::isConnected(void) {
|
||||
return usb_is_connected(USBLIB) && usb_is_configured(USBLIB) && usb_cdcacm_get_dtr();
|
||||
}
|
||||
|
||||
uint8 USBSerial::getDTR(void) {
|
||||
return usb_cdcacm_get_dtr();
|
||||
}
|
||||
@@ -215,6 +211,10 @@ uint8 USBSerial::getRTS(void) {
|
||||
return usb_cdcacm_get_rts();
|
||||
}
|
||||
|
||||
USBSerial::operator bool() {
|
||||
return usb_is_connected(USBLIB) && usb_is_configured(USBLIB) && usb_cdcacm_get_dtr();
|
||||
}
|
||||
|
||||
#if BOARD_HAVE_SERIALUSB
|
||||
#ifdef SERIAL_USB
|
||||
USBSerial Serial;
|
||||
@@ -236,7 +236,7 @@ enum reset_state_t {
|
||||
|
||||
static reset_state_t reset_state = DTR_UNSET;
|
||||
|
||||
static void ifaceSetupHook(unsigned hook, void *requestvp) {
|
||||
static void ifaceSetupHook(unsigned hook __attribute__((unused)), void *requestvp) {
|
||||
uint8 request = *(uint8*)requestvp;
|
||||
|
||||
// Ignore requests we're not interested in.
|
||||
@@ -290,7 +290,7 @@ static void wait_reset(void) {
|
||||
#define STACK_TOP 0x20000800
|
||||
#define EXC_RETURN 0xFFFFFFF9
|
||||
#define DEFAULT_CPSR 0x61000000
|
||||
static void rxHook(unsigned hook, void *ignored) {
|
||||
static void rxHook(unsigned hook __attribute__((unused)), void *ignored __attribute__((unused))) {
|
||||
/* 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) {
|
||||
|
||||
@@ -44,38 +44,51 @@ public:
|
||||
|
||||
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);
|
||||
// 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);
|
||||
size_t readBytes(char *buf, const size_t& len);
|
||||
uint32 read(uint8 * buf, uint32 len);
|
||||
// uint8 read(void);
|
||||
|
||||
// Roger Clark. added functions to support Arduino 1.0 API
|
||||
// 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);
|
||||
size_t write(const uint8*, uint32);
|
||||
|
||||
uint8 getRTS();
|
||||
uint8 getDTR();
|
||||
uint8 isConnected();
|
||||
uint8 pending();
|
||||
|
||||
/* SukkoPera: This is the Arduino way to check if an USB CDC serial
|
||||
* connection is open.
|
||||
|
||||
* Used for instance in cardinfo.ino.
|
||||
*/
|
||||
operator bool();
|
||||
|
||||
/* Old libmaple way to check for serial connection.
|
||||
*
|
||||
* Deprecated, use the above.
|
||||
*/
|
||||
uint8 isConnected() __attribute__((deprecated("Use !Serial instead"))) { return (bool) *this; }
|
||||
|
||||
protected:
|
||||
static bool _hasBegun;
|
||||
};
|
||||
|
||||
#ifdef SERIAL_USB
|
||||
extern USBSerial Serial;
|
||||
#ifdef SERIAL_USB
|
||||
extern USBSerial Serial;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <WCharacter.h>
|
||||
#include <tone.h>
|
||||
|
||||
typedef unsigned int word;
|
||||
// typedef uint16 word;// definition from Arduino website, now appears to be incorrect for 32 bit devices
|
||||
@@ -103,5 +104,7 @@ typedef unsigned int word;
|
||||
#define clockCyclesToMicroseconds(a) ( ((a) * 1000L) / (F_CPU / 1000L) )
|
||||
#define microsecondsToClockCycles(a) ( (a) * (F_CPU / 1000000L) )
|
||||
|
||||
#define digitalPinToInterrupt(pin) (pin)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -47,3 +47,12 @@ long random(long howsmall, long howbig) {
|
||||
return random(diff) + howsmall;
|
||||
}
|
||||
|
||||
extern uint16_t makeWord( uint16_t w )
|
||||
{
|
||||
return w ;
|
||||
}
|
||||
|
||||
extern uint16_t makeWord( uint8_t h, uint8_t l )
|
||||
{
|
||||
return (h << 8) | l ;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#define _WIRISH_WIRISH_MATH_H_
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize the pseudo-random number generator.
|
||||
@@ -78,11 +79,12 @@ long random(long min, long max);
|
||||
* @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;
|
||||
}
|
||||
// Fix by Pito 9/2017
|
||||
static inline int32_t map(int32_t value, int32_t fromStart, int32_t fromEnd,
|
||||
int32_t toStart, int32_t toEnd) {
|
||||
return ((int64_t)(value - fromStart) * (toEnd - toStart)) / (fromEnd - fromStart) +
|
||||
toStart;
|
||||
}
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define HALF_PI 1.5707963267948966192313216916398
|
||||
@@ -161,4 +163,9 @@ double sqrt(double x);
|
||||
*/
|
||||
double pow(double x, double y);
|
||||
|
||||
extern uint16_t makeWord( uint16_t w ) ;
|
||||
extern uint16_t makeWord( uint8_t h, uint8_t l ) ;
|
||||
|
||||
#define word(...) makeWord(__VA_ARGS__)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,3 +35,28 @@ void shiftOut(uint8 dataPin, uint8 clockPin, uint8 bitOrder, uint8 value) {
|
||||
gpio_toggle_bit(PIN_MAP[clockPin].gpio_device, PIN_MAP[clockPin].gpio_bit);// togglePin(clockPin);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t shiftIn( uint32_t ulDataPin, uint32_t ulClockPin, uint32_t ulBitOrder )
|
||||
{
|
||||
uint8_t value = 0 ;
|
||||
uint8_t i ;
|
||||
|
||||
|
||||
for ( i=0 ; i < 8 ; ++i )
|
||||
{
|
||||
digitalWrite( ulClockPin, HIGH ) ;
|
||||
|
||||
if ( ulBitOrder == LSBFIRST )
|
||||
{
|
||||
value |= digitalRead( ulDataPin ) << i ;
|
||||
}
|
||||
else
|
||||
{
|
||||
value |= digitalRead( ulDataPin ) << (7 - i) ;
|
||||
}
|
||||
|
||||
digitalWrite( ulClockPin, LOW ) ;
|
||||
}
|
||||
|
||||
return value ;
|
||||
}
|
||||
|
||||
@@ -32,11 +32,15 @@
|
||||
|
||||
#include <libmaple/libmaple_types.h>
|
||||
#include <libmaple/delay.h>
|
||||
#include "Arduino.h"
|
||||
|
||||
void delay(unsigned long ms) {
|
||||
uint32 start = millis();
|
||||
while (millis() - start < ms)
|
||||
;
|
||||
do
|
||||
{
|
||||
yield();
|
||||
}
|
||||
while (millis() - start < ms);
|
||||
}
|
||||
|
||||
void delayMicroseconds(uint32 us) {
|
||||
|
||||
@@ -55,7 +55,6 @@ typedef struct stm32_pin_info {
|
||||
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;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user