first commit
This commit is contained in:
246
RHutil/HardwareSerial.cpp
Normal file
246
RHutil/HardwareSerial.cpp
Normal file
@@ -0,0 +1,246 @@
|
||||
// HardwareSerial.cpp
|
||||
//
|
||||
// Copyright (C) 2015 Mike McCauley
|
||||
// $Id: HardwareSerial.cpp,v 1.4 2020/08/05 04:32:19 mikem Exp mikem $
|
||||
|
||||
#include <RadioHead.h>
|
||||
#if (RH_PLATFORM == RH_PLATFORM_UNIX)
|
||||
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
HardwareSerial::HardwareSerial(const char* deviceName)
|
||||
: _deviceName(deviceName),
|
||||
_device(-1)
|
||||
{
|
||||
// Override device name from environment
|
||||
char* e = getenv("RH_HARDWARESERIAL_DEVICE_NAME");
|
||||
if (e)
|
||||
_deviceName = e;
|
||||
}
|
||||
|
||||
void HardwareSerial::begin(int baud)
|
||||
{
|
||||
if (openDevice())
|
||||
setBaud(baud);
|
||||
}
|
||||
|
||||
void HardwareSerial::end()
|
||||
{
|
||||
closeDevice();
|
||||
}
|
||||
|
||||
void HardwareSerial::flush()
|
||||
{
|
||||
tcdrain(_device);
|
||||
}
|
||||
|
||||
int HardwareSerial::peek(void)
|
||||
{
|
||||
printf("HardwareSerial::peek not implemented\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HardwareSerial::available()
|
||||
{
|
||||
int bytes;
|
||||
|
||||
if (ioctl(_device, FIONREAD, &bytes) != 0)
|
||||
{
|
||||
fprintf(stderr, "HardwareSerial::available ioctl failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int HardwareSerial::read()
|
||||
{
|
||||
uint8_t data;
|
||||
ssize_t result = ::read(_device, &data, 1);
|
||||
if (result != 1)
|
||||
{
|
||||
fprintf(stderr, "HardwareSerial::read read failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
// printf("got: %02x\n", data);
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t HardwareSerial::write(uint8_t ch)
|
||||
{
|
||||
size_t result = ::write(_device, &ch, 1);
|
||||
if (result != 1)
|
||||
{
|
||||
fprintf(stderr, "HardwareSerial::write failed: %s\n", strerror(errno));
|
||||
return 0;
|
||||
}
|
||||
// printf("sent: %02x\n", ch);
|
||||
return 1; // OK
|
||||
}
|
||||
|
||||
bool HardwareSerial::openDevice()
|
||||
{
|
||||
if (_device == -1)
|
||||
closeDevice();
|
||||
_device = open(_deviceName, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
if (_device == -1)
|
||||
{
|
||||
// Could not open the port.
|
||||
fprintf(stderr, "HardwareSerial::openDevice could not open %s: %s\n", _deviceName, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Device opened
|
||||
fcntl(_device, F_SETFL, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HardwareSerial::closeDevice()
|
||||
{
|
||||
if (_device != -1)
|
||||
close(_device);
|
||||
_device = -1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HardwareSerial::setBaud(int baud)
|
||||
{
|
||||
speed_t speed;
|
||||
|
||||
// This is kind of ugly, but its prob better than a case
|
||||
if (baud == 50)
|
||||
speed = B50;
|
||||
else if (baud == 75)
|
||||
speed = B75;
|
||||
else if (baud == 110)
|
||||
speed = B110;
|
||||
else if (baud == 134)
|
||||
speed = B134;
|
||||
else if (baud == 150)
|
||||
speed = B150;
|
||||
else if (baud == 200)
|
||||
speed = B200;
|
||||
else if (baud == 300)
|
||||
speed = B300;
|
||||
else if (baud == 600)
|
||||
speed = B600;
|
||||
else if (baud == 1200)
|
||||
speed = B1200;
|
||||
else if (baud == 1800)
|
||||
speed = B1800;
|
||||
else if (baud == 2400)
|
||||
speed = B2400;
|
||||
else if (baud == 4800)
|
||||
speed = B4800;
|
||||
else if (baud == 9600)
|
||||
speed = B9600;
|
||||
else if (baud == 19200)
|
||||
speed = B19200;
|
||||
else if (baud == 38400)
|
||||
speed = B38400;
|
||||
else if (baud == 57600)
|
||||
speed = B57600;
|
||||
#ifdef B76800
|
||||
else if (baud == 76800) // Not available on Linux
|
||||
speed = B76800;
|
||||
#endif
|
||||
else if (baud == 115200)
|
||||
speed = B115200;
|
||||
else if (baud == 230400)
|
||||
speed = B230400;
|
||||
#ifdef B460800
|
||||
else if (baud == 460800) // Not available on OSX
|
||||
speed = B460800;
|
||||
#endif
|
||||
#ifdef B921600
|
||||
else if (baud == 921600) // Not available on OSX
|
||||
speed = B921600;
|
||||
#endif
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "HardwareSerial::setBaud: unsupported baud rate %d\n", baud);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct termios options;
|
||||
// Get current options
|
||||
if (tcgetattr(_device, &options) != 0)
|
||||
{
|
||||
fprintf(stderr, "HardwareSerial::setBaud: could not tcgetattr %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set new speed options
|
||||
cfsetispeed(&options, speed);
|
||||
cfsetospeed(&options, speed);
|
||||
// Enable the receiver and set local mode...
|
||||
options.c_cflag |= (CLOCAL | CREAD);
|
||||
|
||||
// Force mode to 8,N,1
|
||||
// to be compatible with Arduino HardwareSerial
|
||||
// Should this be configurable? Prob not, must have 8 bits, dont need parity.
|
||||
options.c_cflag &= ~(PARENB | CSTOPB | CSIZE);
|
||||
options.c_cflag |= CS8;
|
||||
|
||||
// Disable flow control and input character conversions
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY | ICRNL | INLCR);
|
||||
|
||||
// Raw input:
|
||||
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
|
||||
|
||||
// Raw output
|
||||
options.c_oflag &= ~(OPOST | OCRNL | ONLCR);
|
||||
|
||||
// Set the options in the port
|
||||
if (tcsetattr(_device, TCSANOW, &options) != 0)
|
||||
{
|
||||
fprintf(stderr, "HardwareSerial::setBaud: could not tcsetattr %s\n", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
_baud = baud;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Block until something is available
|
||||
void HardwareSerial::waitAvailable()
|
||||
{
|
||||
waitAvailableTimeout(0); // 0 = Wait forever
|
||||
}
|
||||
|
||||
// Block until something is available or timeout expires
|
||||
bool HardwareSerial::waitAvailableTimeout(uint16_t timeout)
|
||||
{
|
||||
int max_fd;
|
||||
fd_set input;
|
||||
int result;
|
||||
|
||||
FD_ZERO(&input);
|
||||
FD_SET(_device, &input);
|
||||
max_fd = _device + 1;
|
||||
|
||||
if (timeout)
|
||||
{
|
||||
struct timeval timer;
|
||||
// Timeout is in milliseconds
|
||||
timer.tv_sec = timeout / 1000;
|
||||
timer.tv_usec = (timeout % 1000) * 1000;
|
||||
result = select(max_fd, &input, NULL, NULL, &timer);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = select(max_fd, &input, NULL, NULL, NULL);
|
||||
}
|
||||
if (result < 0)
|
||||
fprintf(stderr, "HardwareSerial::waitAvailableTimeout: select failed %s\n", strerror(errno));
|
||||
return result > 0;
|
||||
}
|
||||
|
||||
#endif
|
100
RHutil/HardwareSerial.h
Normal file
100
RHutil/HardwareSerial.h
Normal file
@@ -0,0 +1,100 @@
|
||||
// HardwareSerial.h
|
||||
// Author: Mike McCauley (mikem@airspayce.com)
|
||||
// Copyright (C) 2015 Mike McCauley
|
||||
// $Id: HardwareSerial.h,v 1.4 2020/08/05 04:32:19 mikem Exp mikem $
|
||||
#ifndef HardwareSerial_h
|
||||
#define HardwareSerial_h
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/// \class HardwareSerial HardwareSerial.h <RHutil/HardwareSerial.h>
|
||||
/// \brief Encapsulates a Posix compliant serial port as a HarwareSerial
|
||||
///
|
||||
/// This class provides access to a serial port on Unix and OSX.
|
||||
/// It is equivalent to HardwareSerial in Arduino, and can be used by RH_Serial
|
||||
/// We implement just enough to provide the services RadioHead needs.
|
||||
/// Additional methods not present on Arduino are also provided for waiting for characters.
|
||||
///
|
||||
/// The device port is configured for 8 bits, no parity, 1 stop bit and full raw transparency, so it can be used
|
||||
/// to send and receive any 8 bit character. A limited range of baud rates is supported.
|
||||
///
|
||||
/// \par Device Names
|
||||
///
|
||||
/// Device naming conventions vary from OS to OS. ON linux, an FTDI serial port may have a name like
|
||||
/// /dev/ttyUSB0. On OSX, it might be something like /dev/tty.usbserial-A501YSWL
|
||||
/// \par errors
|
||||
///
|
||||
/// A number of these methods print error messages to stderr in the event of an IO error.
|
||||
class HardwareSerial
|
||||
{
|
||||
public:
|
||||
/// Constructor
|
||||
// \param [in] deviceName Name of the derial port device to connect to
|
||||
HardwareSerial(const char* deviceName);
|
||||
|
||||
/// Open and configure the port.
|
||||
/// The named port is opened, and the given baud rate is set.
|
||||
/// The port is configure for raw input and output and 8,N,1 protocol
|
||||
/// with no flow control.
|
||||
/// This must be called before any other operations are attempted.
|
||||
/// IO failures and unsupported baud rates will result in an error message on stderr.
|
||||
/// \param[in] baud The desired baud rate. The only rates supported are: 50, 75, 110, 134, 150
|
||||
/// 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400. On some platform
|
||||
/// such as Linux you may also use: 460800, 921600.
|
||||
void begin(int baud);
|
||||
|
||||
/// Close the port.
|
||||
/// If begin() has previously been called successfully, the device port will be closed.
|
||||
/// It may be reopened again with another call to begin().
|
||||
void end();
|
||||
|
||||
/// Flush remaining data.
|
||||
/// Blocks until any data yet to be transmtted is sent.
|
||||
void flush();
|
||||
|
||||
/// Peek at the nex available character without consuming it.
|
||||
/// CAUTION: Not implemented.
|
||||
int peek(void);
|
||||
|
||||
/// Returns the number of bytes immediately available to be read from the
|
||||
/// device.
|
||||
/// \return 0 if none available else the number of characters available for immediate reading
|
||||
int available();
|
||||
|
||||
/// Read and return the next available character.
|
||||
/// If no character is available prints a message to stderr and returns 0;
|
||||
/// \return The next available character
|
||||
int read();
|
||||
|
||||
/// Transmit a single character oin the serial port.
|
||||
/// Returns immediately.
|
||||
/// IO errors are repored by printing aa message to stderr.
|
||||
/// \param[in] ch The character to send. Anything in the range 0x00 to 0xff is permitted
|
||||
/// \return 1 if successful else 0
|
||||
size_t write(uint8_t ch);
|
||||
|
||||
// These are not usually in HardwareSerial but we
|
||||
// need them in a Unix environment
|
||||
|
||||
/// Wait until a character is available from the port.
|
||||
void waitAvailable();
|
||||
|
||||
/// Wait until a a character is available from the port.
|
||||
/// or the timeout expires
|
||||
/// \param[in] timeout The maximum time to wait in milliseconds. 0 means wait forever.
|
||||
/// \return true if a message is available as reported by available()
|
||||
bool waitAvailableTimeout(uint16_t timeout);
|
||||
|
||||
protected:
|
||||
bool openDevice();
|
||||
bool closeDevice();
|
||||
bool setBaud(int baud);
|
||||
|
||||
private:
|
||||
const char* _deviceName;
|
||||
int _device; // file desriptor
|
||||
int _baud;
|
||||
};
|
||||
|
||||
#endif
|
176
RHutil/RasPi.cpp
Normal file
176
RHutil/RasPi.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
// RasPi.cpp
|
||||
//
|
||||
// Routines for implementing RadioHead on Raspberry Pi
|
||||
// using BCM2835 library for GPIO
|
||||
//
|
||||
// Contributed by Mike Poublon and used with permission
|
||||
|
||||
|
||||
#include <RadioHead.h>
|
||||
|
||||
#if (RH_PLATFORM == RH_PLATFORM_RASPI)
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include "RasPi.h"
|
||||
|
||||
//Initialize the values for sanity
|
||||
timeval RHStartTime;
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
//Set SPI Defaults
|
||||
uint16_t divider = BCM2835_SPI_CLOCK_DIVIDER_256;
|
||||
uint8_t bitorder = BCM2835_SPI_BIT_ORDER_MSBFIRST;
|
||||
uint8_t datamode = BCM2835_SPI_MODE0;
|
||||
|
||||
begin(divider, bitorder, datamode);
|
||||
}
|
||||
|
||||
void SPIClass::begin(uint16_t divider, uint8_t bitOrder, uint8_t dataMode)
|
||||
{
|
||||
setClockDivider(divider);
|
||||
setBitOrder(bitOrder);
|
||||
setDataMode(dataMode);
|
||||
|
||||
//Set CS pins polarity to low
|
||||
bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, 0);
|
||||
|
||||
bcm2835_spi_begin();
|
||||
|
||||
//Initialize a timestamp for millis calculation
|
||||
gettimeofday(&RHStartTime, NULL);
|
||||
}
|
||||
|
||||
void SPIClass::end()
|
||||
{
|
||||
//End the SPI
|
||||
bcm2835_spi_end();
|
||||
}
|
||||
|
||||
void SPIClass::setBitOrder(uint8_t bitOrder)
|
||||
{
|
||||
//Set the SPI bit Order
|
||||
bcm2835_spi_setBitOrder(bitOrder);
|
||||
}
|
||||
|
||||
void SPIClass::setDataMode(uint8_t mode)
|
||||
{
|
||||
//Set SPI data mode
|
||||
bcm2835_spi_setDataMode(mode);
|
||||
}
|
||||
|
||||
void SPIClass::setClockDivider(uint16_t rate)
|
||||
{
|
||||
//Set SPI clock divider
|
||||
bcm2835_spi_setClockDivider(rate);
|
||||
}
|
||||
|
||||
byte SPIClass::transfer(byte _data)
|
||||
{
|
||||
//Set which CS pin to use for next transfers
|
||||
bcm2835_spi_chipSelect(BCM2835_SPI_CS0);
|
||||
//Transfer 1 byte
|
||||
byte data;
|
||||
data = bcm2835_spi_transfer((uint8_t)_data);
|
||||
return data;
|
||||
}
|
||||
|
||||
void pinMode(unsigned char pin, unsigned char mode)
|
||||
{
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
bcm2835_gpio_fsel(pin,BCM2835_GPIO_FSEL_OUTP);
|
||||
}
|
||||
else
|
||||
{
|
||||
bcm2835_gpio_fsel(pin,BCM2835_GPIO_FSEL_INPT);
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(unsigned char pin, unsigned char value)
|
||||
{
|
||||
bcm2835_gpio_write(pin,value);
|
||||
}
|
||||
|
||||
unsigned long millis()
|
||||
{
|
||||
//Declare a variable to store current time
|
||||
struct timeval RHCurrentTime;
|
||||
//Get current time
|
||||
gettimeofday(&RHCurrentTime,NULL);
|
||||
//Calculate the difference between our start time and the end time
|
||||
unsigned long difference = ((RHCurrentTime.tv_sec - RHStartTime.tv_sec) * 1000);
|
||||
difference += ((RHCurrentTime.tv_usec - RHStartTime.tv_usec)/1000);
|
||||
//Return the calculated value
|
||||
return difference;
|
||||
}
|
||||
|
||||
void delay (unsigned long ms)
|
||||
{
|
||||
//Implement Delay function
|
||||
struct timespec ts;
|
||||
ts.tv_sec=0;
|
||||
ts.tv_nsec=(ms * 1000);
|
||||
nanosleep(&ts,&ts);
|
||||
}
|
||||
|
||||
long random(long min, long max)
|
||||
{
|
||||
long diff = max - min;
|
||||
long ret = diff * rand() + min;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SerialSimulator::begin(int baud)
|
||||
{
|
||||
//No implementation neccesary - Serial emulation on Linux = standard console
|
||||
//
|
||||
//Initialize a timestamp for millis calculation - we do this here as well in case SPI
|
||||
//isn't used for some reason
|
||||
gettimeofday(&RHStartTime, NULL);
|
||||
}
|
||||
|
||||
size_t SerialSimulator::println(const char* s)
|
||||
{
|
||||
print(s);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
size_t SerialSimulator::print(const char* s)
|
||||
{
|
||||
printf(s);
|
||||
}
|
||||
|
||||
size_t SerialSimulator::print(unsigned int n, int base)
|
||||
{
|
||||
if (base == DEC)
|
||||
printf("%d", n);
|
||||
else if (base == HEX)
|
||||
printf("%02x", n);
|
||||
else if (base == OCT)
|
||||
printf("%o", n);
|
||||
// TODO: BIN
|
||||
}
|
||||
|
||||
size_t SerialSimulator::print(char ch)
|
||||
{
|
||||
printf("%c", ch);
|
||||
}
|
||||
|
||||
size_t SerialSimulator::println(char ch)
|
||||
{
|
||||
printf("%c\n", ch);
|
||||
}
|
||||
|
||||
size_t SerialSimulator::print(unsigned char ch, int base)
|
||||
{
|
||||
return print((unsigned int)ch, base);
|
||||
}
|
||||
|
||||
size_t SerialSimulator::println(unsigned char ch, int base)
|
||||
{
|
||||
print((unsigned int)ch, base);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#endif
|
75
RHutil/RasPi.h
Normal file
75
RHutil/RasPi.h
Normal file
@@ -0,0 +1,75 @@
|
||||
// RasPi.h
|
||||
//
|
||||
// Routines for implementing RadioHead on Raspberry Pi
|
||||
// using BCM2835 library for GPIO
|
||||
// Contributed by Mike Poublon and used with permission
|
||||
|
||||
#ifndef RASPI_h
|
||||
#define RASPI_h
|
||||
|
||||
#include <bcm2835.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef OUTPUT
|
||||
#define OUTPUT BCM2835_GPIO_FSEL_OUTP
|
||||
#endif
|
||||
|
||||
class SPIClass
|
||||
{
|
||||
public:
|
||||
static byte transfer(byte _data);
|
||||
// SPI Configuration methods
|
||||
static void begin(); // Default
|
||||
static void begin(uint16_t, uint8_t, uint8_t);
|
||||
static void end();
|
||||
static void setBitOrder(uint8_t);
|
||||
static void setDataMode(uint8_t);
|
||||
static void setClockDivider(uint16_t);
|
||||
};
|
||||
|
||||
extern SPIClass SPI;
|
||||
|
||||
class SerialSimulator
|
||||
{
|
||||
public:
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
// TODO: move these from being inlined
|
||||
static void begin(int baud);
|
||||
static size_t println(const char* s);
|
||||
static size_t print(const char* s);
|
||||
static size_t print(unsigned int n, int base = DEC);
|
||||
static size_t print(char ch);
|
||||
static size_t println(char ch);
|
||||
static size_t print(unsigned char ch, int base = DEC);
|
||||
static size_t println(unsigned char ch, int base = DEC);
|
||||
};
|
||||
|
||||
extern SerialSimulator Serial;
|
||||
|
||||
void RasPiSetup();
|
||||
|
||||
void pinMode(unsigned char pin, unsigned char mode);
|
||||
|
||||
void digitalWrite(unsigned char pin, unsigned char value);
|
||||
|
||||
unsigned long millis();
|
||||
|
||||
void delay (unsigned long delay);
|
||||
|
||||
long random(long min, long max);
|
||||
|
||||
#endif
|
71
RHutil/atomic.h
Normal file
71
RHutil/atomic.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This is port of Dean Camera's ATOMIC_BLOCK macros for AVR to ARM Cortex M3
|
||||
* v1.0
|
||||
* Mark Pendrith, Nov 27, 2012.
|
||||
*
|
||||
* From Mark:
|
||||
* >When I ported the macros I emailed Dean to ask what attribution would be
|
||||
* >appropriate, and here is his response:
|
||||
* >
|
||||
* >>Mark,
|
||||
* >>I think it's great that you've ported the macros; consider them
|
||||
* >>public domain, to do with whatever you wish. I hope you find them >useful .
|
||||
* >>
|
||||
* >>Cheers!
|
||||
* >>- Dean
|
||||
*/
|
||||
|
||||
#ifdef __arm__
|
||||
#ifndef _CORTEX_M3_ATOMIC_H_
|
||||
#define _CORTEX_M3_ATOMIC_H_
|
||||
|
||||
static __inline__ uint32_t __get_primask(void) \
|
||||
{ uint32_t primask = 0; \
|
||||
__asm__ volatile ("MRS %[result], PRIMASK\n\t":[result]"=r"(primask)::); \
|
||||
return primask; } // returns 0 if interrupts enabled, 1 if disabled
|
||||
|
||||
static __inline__ void __set_primask(uint32_t setval) \
|
||||
{ __asm__ volatile ("MSR PRIMASK, %[value]\n\t""dmb\n\t""dsb\n\t""isb\n\t"::[value]"r"(setval):);
|
||||
__asm__ volatile ("" ::: "memory");}
|
||||
|
||||
static __inline__ uint32_t __iSeiRetVal(void) \
|
||||
{ __asm__ volatile ("CPSIE i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
|
||||
__asm__ volatile ("" ::: "memory"); return 1; }
|
||||
|
||||
static __inline__ uint32_t __iCliRetVal(void) \
|
||||
{ __asm__ volatile ("CPSID i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
|
||||
__asm__ volatile ("" ::: "memory"); return 1; }
|
||||
|
||||
static __inline__ void __iSeiParam(const uint32_t *__s) \
|
||||
{ __asm__ volatile ("CPSIE i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
|
||||
__asm__ volatile ("" ::: "memory"); (void)__s; }
|
||||
|
||||
static __inline__ void __iCliParam(const uint32_t *__s) \
|
||||
{ __asm__ volatile ("CPSID i\n\t""dmb\n\t""dsb\n\t""isb\n\t"); \
|
||||
__asm__ volatile ("" ::: "memory"); (void)__s; }
|
||||
|
||||
static __inline__ void __iRestore(const uint32_t *__s) \
|
||||
{ __set_primask(*__s); __asm__ volatile ("dmb\n\t""dsb\n\t""isb\n\t"); \
|
||||
__asm__ volatile ("" ::: "memory"); }
|
||||
|
||||
|
||||
#define ATOMIC_BLOCK(type) \
|
||||
for ( type, __ToDo = __iCliRetVal(); __ToDo ; __ToDo = 0 )
|
||||
|
||||
#define ATOMIC_RESTORESTATE \
|
||||
uint32_t primask_save __attribute__((__cleanup__(__iRestore))) = __get_primask()
|
||||
|
||||
#define ATOMIC_FORCEON \
|
||||
uint32_t primask_save __attribute__((__cleanup__(__iSeiParam))) = 0
|
||||
|
||||
#define NONATOMIC_BLOCK(type) \
|
||||
for ( type, __ToDo = __iSeiRetVal(); __ToDo ; __ToDo = 0 )
|
||||
|
||||
#define NONATOMIC_RESTORESTATE \
|
||||
uint32_t primask_save __attribute__((__cleanup__(__iRestore))) = __get_primask()
|
||||
|
||||
#define NONATOMIC_FORCEOFF \
|
||||
uint32_t primask_save __attribute__((__cleanup__(__iCliParam))) = 0
|
||||
|
||||
#endif
|
||||
#endif
|
84
RHutil/simulator.h
Normal file
84
RHutil/simulator.h
Normal file
@@ -0,0 +1,84 @@
|
||||
// simulator.h
|
||||
// Lets Arduino RadioHead sketches run within a simulator on Linux as a single process
|
||||
// Copyright (C) 2014 Mike McCauley
|
||||
// $Id: simulator.h,v 1.4 2015/08/13 02:45:47 mikem Exp $
|
||||
|
||||
#ifndef simulator_h
|
||||
#define simulator_h
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Equivalent types for common Arduino types like uint8_t are in stdint.h
|
||||
|
||||
// Access to some globals
|
||||
// Command line args passed to the process.
|
||||
extern int _simulator_argc;
|
||||
extern char** _simulator_argv;
|
||||
|
||||
// Definitions for various Arduino functions
|
||||
extern void delay(unsigned long ms);
|
||||
extern unsigned long millis();
|
||||
extern long random(long to);
|
||||
extern long random(long from, long to);
|
||||
|
||||
// Equavalent to HardwareSerial in Arduino
|
||||
// but outputs to stdout
|
||||
class SerialSimulator
|
||||
{
|
||||
public:
|
||||
#define DEC 10
|
||||
#define HEX 16
|
||||
#define OCT 8
|
||||
#define BIN 2
|
||||
|
||||
// TODO: move these from being inlined
|
||||
void begin(int baud) {}
|
||||
|
||||
size_t println(const char* s)
|
||||
{
|
||||
print(s);
|
||||
return printf("\n");
|
||||
}
|
||||
size_t print(const char* s)
|
||||
{
|
||||
return printf("%s", s); // This style prevent warnings from [-Wformat-security]
|
||||
}
|
||||
size_t print(unsigned int n, int base = DEC)
|
||||
{
|
||||
if (base == DEC)
|
||||
return printf("%d", n);
|
||||
else if (base == HEX)
|
||||
return printf("%02x", n);
|
||||
else if (base == OCT)
|
||||
return printf("%o", n);
|
||||
// TODO: BIN
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
size_t print(char ch)
|
||||
{
|
||||
return printf("%c", ch);
|
||||
}
|
||||
size_t println(char ch)
|
||||
{
|
||||
return printf("%c\n", ch);
|
||||
}
|
||||
size_t print(unsigned char ch, int base = DEC)
|
||||
{
|
||||
return print((unsigned int)ch, base);
|
||||
}
|
||||
size_t println(unsigned char ch, int base = DEC)
|
||||
{
|
||||
print((unsigned int)ch, base);
|
||||
return printf("\n");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Global instance of the Serial output
|
||||
extern SerialSimulator Serial;
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user