first commit
This commit is contained in:
264
RHutil_pigpio/RasPi.cpp
Normal file
264
RHutil_pigpio/RasPi.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
// RasPi.cpp
|
||||
//(9/22/2019) Contributed by Brody M. This file is based off RHutil\RasPi.cpp
|
||||
// but modified for the pigpio library instead of BCM2835. Original
|
||||
// code maintained where possible. Unused code commented out and
|
||||
// left in place.
|
||||
|
||||
// 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"
|
||||
#include <stdio.h>
|
||||
|
||||
int spiHandle;
|
||||
|
||||
//Initialize the values for sanity
|
||||
timeval RHStartTime;
|
||||
|
||||
void SPIClass::begin()
|
||||
{
|
||||
//Set SPI Defaults
|
||||
//Retaining BCM2835 macros for compatibility with RadioHead
|
||||
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(uint32_t spiChannel, uint32_t spiBaud, uint32_t spiFlags)
|
||||
void SPIClass::begin(uint16_t divider, uint8_t bitOrder, uint8_t dataMode)
|
||||
{
|
||||
|
||||
//Set CS pins polarity to low
|
||||
//bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, 0);
|
||||
|
||||
//pigpio SPI Defailts
|
||||
//SPI Speed
|
||||
//BCM2835 divider of 256 is approx 1MHz SCLK, depending on model
|
||||
//uint32_t spiBaud = 1000000;
|
||||
//Spi Flag Settings
|
||||
//21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
||||
//b b b b b b R T n n n n W A u2 u1 u0 p2 p1 p0 m m
|
||||
//m m bits = mode
|
||||
//Mode 0 = 0 0
|
||||
|
||||
uint32_t spiBaud = convertClockDivider(divider);
|
||||
//datamode is 0 to 3 on BCM2835
|
||||
uint32_t spiFlags = 0; //Zero is a good default start.
|
||||
//on pigpio, the least sig 2 bits set datamode, which will probably be zero.
|
||||
spiFlags = 0x00000000 | (uint32_t) dataMode;
|
||||
//According to documentation, bitOrder for SPI MAIN in pigpio is always MSBFIRST. So bitOrder ignored.
|
||||
printf("\nSPI Settings:\nBaud rate=%d\nFlags=%d\n\n", spiBaud, spiFlags);
|
||||
spiHandle = spiOpen(0, spiBaud, spiFlags); //spiChannel assumed to be zero.
|
||||
|
||||
//Initialize a timestamp for millis calculation
|
||||
gettimeofday(&RHStartTime, NULL);
|
||||
}
|
||||
|
||||
void SPIClass::end()
|
||||
{
|
||||
//End the SPI
|
||||
//bcm2835_spi_end();
|
||||
spiClose(spiHandle);
|
||||
}
|
||||
|
||||
uint32_t SPIClass::convertClockDivider(uint16_t rate)
|
||||
{
|
||||
//Simple divide default RPi SPI clock by divider amount.
|
||||
//Nominal clock at 250MHz for Zero.
|
||||
return 250000000/rate;
|
||||
}
|
||||
/*
|
||||
//Thes functions aren't necessary
|
||||
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)
|
||||
{
|
||||
char txByte[1] = {(char)_data};
|
||||
char rxByte[1];
|
||||
//For RF Compatibility, just transfer 1 byte
|
||||
spiXfer(spiHandle, txByte, rxByte, 1);
|
||||
return (byte)rxByte[0];
|
||||
}
|
||||
|
||||
|
||||
//void pinMode(unsigned char pin, unsigned char mode)
|
||||
void pinMode(uint8_t pin, WiringPinMode mode)
|
||||
{
|
||||
if (mode == OUTPUT)
|
||||
{
|
||||
gpioSetMode(pin, PI_OUTPUT);
|
||||
//bcm2835_gpio_fsel(pin,BCM2835_GPIO_FSEL_OUTP);
|
||||
}
|
||||
else if (mode == INPUT)
|
||||
{
|
||||
gpioSetMode(pin, PI_INPUT);
|
||||
//bcm2835_gpio_fsel(pin,BCM2835_GPIO_FSEL_INPT);
|
||||
}
|
||||
else if (mode == INPUT_PULLUP)
|
||||
{
|
||||
gpioSetMode(pin, PI_INPUT);
|
||||
gpioSetPullUpDown(pin, PI_PUD_UP);
|
||||
}
|
||||
else if (mode == INPUT_PULLDOWN)
|
||||
{
|
||||
gpioSetMode(pin, PI_INPUT);
|
||||
gpioSetPullUpDown(pin, PI_PUD_DOWN);
|
||||
}
|
||||
else
|
||||
{
|
||||
//For safety
|
||||
gpioSetMode(pin, PI_INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
void digitalWrite(unsigned char pin, unsigned char value)
|
||||
{
|
||||
//bcm2835_gpio_write(pin,value);
|
||||
//Could have just written gpioWrite(pin, value)
|
||||
if(value == HIGH)
|
||||
{
|
||||
gpioWrite(pin, PI_ON);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioWrite(pin, PI_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//******************************
|
||||
//* Attach Interupt
|
||||
//* Emulate Arduino Function
|
||||
//******************************
|
||||
|
||||
void attachInterrupt(unsigned char pin, void (*handler)(void), int mode)
|
||||
{
|
||||
switch(mode)
|
||||
{
|
||||
case CHANGE:
|
||||
gpioSetISRFunc(pin, EITHER_EDGE, 0, (void (*)(int,int,unsigned int))handler);
|
||||
break;
|
||||
case RISING:
|
||||
gpioSetISRFunc(pin, RISING_EDGE, 0, (void (*)(int,int,unsigned int))handler);
|
||||
break;
|
||||
case FALLING:
|
||||
gpioSetISRFunc(pin, FALLING_EDGE, 0, (void (*)(int,int,unsigned int))handler);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
size_t charsPrinted = 0;
|
||||
charsPrinted = print(s);
|
||||
printf("\n");
|
||||
return charsPrinted + 1;
|
||||
}
|
||||
|
||||
size_t SerialSimulator::print(const char* s)
|
||||
{
|
||||
return (size_t)printf(s);
|
||||
}
|
||||
|
||||
size_t SerialSimulator::print(unsigned int n, int base)
|
||||
{
|
||||
if (base == DEC)
|
||||
return (size_t)printf("%d", n);
|
||||
else if (base == HEX)
|
||||
return (size_t)printf("%02x", n);
|
||||
else if (base == OCT)
|
||||
return (size_t)printf("%o", n);
|
||||
// TODO: BIN
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t SerialSimulator::print(char ch)
|
||||
{
|
||||
return (size_t)printf("%c", ch);
|
||||
}
|
||||
|
||||
size_t SerialSimulator::println(char ch)
|
||||
{
|
||||
return (size_t)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)
|
||||
{
|
||||
size_t charsPrinted = 0;
|
||||
charsPrinted = print((unsigned int)ch, base);
|
||||
printf("\n");
|
||||
return charsPrinted + 1;
|
||||
}
|
||||
|
||||
#endif
|
214
RHutil_pigpio/RasPi.h
Normal file
214
RHutil_pigpio/RasPi.h
Normal file
@@ -0,0 +1,214 @@
|
||||
// RasPi.h
|
||||
//(9/22/2019) Contributed by Brody M. This file is based off RHutil\RasPi.h
|
||||
// but modified for the pigpio library instead of BCM2835. Original
|
||||
// code maintained where possible. Unused code commented out and
|
||||
// left in place. WiringPinMode enumeration declaration borrowed from
|
||||
// STM32ArduinoCompat\wirish.h. Also some enumeration declarations
|
||||
// "borrowed" from bcm2835.h to maintain original code and for simplicity.
|
||||
|
||||
// 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 <pigpio.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
#define HIGH 0x1
|
||||
#define LOW 0x0
|
||||
|
||||
#define CHANGE 1
|
||||
#define FALLING 2
|
||||
#define RISING 3
|
||||
|
||||
#define memcpy_P memcpy
|
||||
|
||||
//#ifndef OUTPUT
|
||||
// #define OUTPUT BCM2835_GPIO_FSEL_OUTP
|
||||
//#endif
|
||||
|
||||
class SPIClass
|
||||
{
|
||||
public:
|
||||
//pigpio SPI ID
|
||||
//We need to make sure this handle can be accessed by all SPI Functions
|
||||
static byte transfer(byte _data);
|
||||
// SPI Configuration methods
|
||||
static void begin(); // Default
|
||||
//static void begin(uint32_t,uint32_t,uint32_t);
|
||||
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);
|
||||
static uint32_t convertClockDivider(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();
|
||||
|
||||
//The WiringPinMode enumeration declaration is borrowed from STM32ArduinoCompat\wirish.h
|
||||
|
||||
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;
|
||||
|
||||
void pinMode(uint8_t pin, WiringPinMode mode);
|
||||
|
||||
//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);
|
||||
|
||||
void attachInterrupt(unsigned char pin, void (*handler)(void), int mode);
|
||||
|
||||
|
||||
|
||||
//The following lines are borrowed from bcm2835.h, which is part of the BCM2835 library
|
||||
//(https://www.airspayce.com/mikem/bcm2835/). The original RadioHead library expects
|
||||
//BCM2835. We could eliminate this by modifying more RadioHead code, but this leaves
|
||||
//the library more "original". Another option would be to include bcm2835.h directly,
|
||||
//but this method is easier.
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCM2835_SPI_BIT_ORDER_LSBFIRST = 0,
|
||||
BCM2835_SPI_BIT_ORDER_MSBFIRST = 1
|
||||
}bcm2835SPIBitOrder;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCM2835_SPI_MODE0 = 0,
|
||||
BCM2835_SPI_MODE1 = 1,
|
||||
BCM2835_SPI_MODE2 = 2,
|
||||
BCM2835_SPI_MODE3 = 3
|
||||
}bcm2835SPIMode;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCM2835_SPI_CS0 = 0,
|
||||
BCM2835_SPI_CS1 = 1,
|
||||
BCM2835_SPI_CS2 = 2,
|
||||
BCM2835_SPI_CS_NONE = 3
|
||||
} bcm2835SPIChipSelect;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
BCM2835_SPI_CLOCK_DIVIDER_65536 = 0,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_512 = 512,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_256 = 256,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_128 = 128,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_64 = 64,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_32 = 32,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_16 = 16,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_8 = 8,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_4 = 4,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_2 = 2,
|
||||
BCM2835_SPI_CLOCK_DIVIDER_1 = 1
|
||||
} bcm2835SPIClockDivider;
|
||||
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user