Changed the gertboard code to use it and ran more tests on he Gertboard code.pull/22/head
@@ -14,33 +14,63 @@ | |||
#include <stdio.h> | |||
#include <stdint.h> | |||
//#include <stdlib.h> | |||
#include <math.h> | |||
#define B_SIZE 200 | |||
#undef DO_TIMING | |||
#include <wiringPi.h> | |||
#include <gertboard.h> | |||
int main (void) | |||
{ | |||
int angle ; | |||
int h1 ; | |||
double angle ; | |||
int i ; | |||
uint32_t x1 ; | |||
int buffer [B_SIZE] ; | |||
#ifdef DO_TIMING | |||
unsigned int now, then ; | |||
#endif | |||
printf ("Raspberry Pi Gertboard SPI test program\n") ; | |||
if (gertboardSPISetup () == -1) | |||
if (wiringPiSetupSys () < 0) | |||
return -1 ; | |||
if (gertboardSPISetup () < 0) | |||
return 1 ; | |||
// Generate a Sine Wave | |||
for (i = 0 ; i < B_SIZE ; ++i) | |||
{ | |||
angle = ((double)i / (double)B_SIZE) * M_PI * 2.0 ; | |||
buffer [i] = (int)rint ((sin (angle)) * 127.0 + 128.0) ; | |||
} | |||
for (;;) | |||
{ | |||
for (angle = 0 ; angle < 360 ; ++angle) | |||
#ifdef DO_TIMING | |||
then = millis () ; | |||
#endif | |||
for (i = 0 ; i < B_SIZE ; ++i) | |||
{ | |||
h1 = (int)rint (sin ((double)angle * M_PI / 180.0) * 127.0 + 128.0) ; | |||
gertboardAnalogWrite (0, h1) ; | |||
gertboardAnalogWrite (0, buffer [i]) ; | |||
#ifndef DO_TIMING | |||
x1 = gertboardAnalogRead (0) ; | |||
gertboardAnalogWrite (1, x1 >> 2) ; // 10-bit A/D, 8-bit D/A | |||
#endif | |||
} | |||
#ifdef DO_TIMING | |||
now = millis () ; | |||
printf ("%4d mS, %9.7f S/sample", now - then, ((double)(now - then) / 1000.0) / (double)B_SIZE) ; | |||
printf (" -> %9.4f samples/sec \n", 1 / (((double)(now - then) / 1000.0) / (double)B_SIZE)) ; | |||
#endif | |||
} | |||
return 0 ; | |||
@@ -36,14 +36,23 @@ range | |||
.PP | |||
.B gpio | |||
.B load \ i2c/spi | |||
.PP | |||
.B gpio | |||
.B gbr | |||
channel | |||
.PP | |||
.B gpio | |||
.B gbw | |||
channel value | |||
.SH DESCRIPTION | |||
.B GPIO | |||
is a command line tool to allow the user easy access to the GPIO pins | |||
on the Raspberry Pi. It's designed for simple testing and diagnostic | |||
purposes, but can be used in shell scripts for general if somewhat slow | |||
control of the GPIO pins. | |||
is a swiss army knofe of a command line tool to allow the user easy | |||
access to the GPIO pins on the Raspberry Pi and the SPI A/D and D/A | |||
convertors on the Gertboard. It's designed for simple testing and | |||
diagnostic purposes, but can be used in shell scripts for general if | |||
somewhat slow control of the GPIO pins. | |||
Additionally, it can be used to set the exports in the \fI/sys/class/gpio\fR | |||
system directory to allow subsequent programs to use the \fR/sys/class/gpio\fR | |||
@@ -142,6 +151,21 @@ Change the PWM range register. The default is 1024. | |||
This loads the i2c or the spi drivers into the system and changes the permissions on | |||
the associated /dev/ entries so that the current user has access to them. | |||
.TP | |||
.B gbr | |||
channel | |||
This reads the analog to digital convertor on the Gertboard on the given | |||
channel. The board jumpers need to be in-place to do this operation. | |||
.TP | |||
.B gbw | |||
channel value | |||
This writes the supplied value to the output channel on the Gertboards | |||
SPI digital to analogue convertor. | |||
The board jumpers need to be in-place to do this operation. | |||
.SH "WiringPi vs. GPIO Pin numbering" | |||
@@ -1,6 +1,7 @@ | |||
/* | |||
* gpio.c: | |||
* Set-UID command-line interface to the Raspberry Pi's GPIO | |||
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | |||
* Pi's GPIO. | |||
* Copyright (c) 2012 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
@@ -21,7 +22,6 @@ | |||
*********************************************************************** | |||
*/ | |||
#include <wiringPi.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
@@ -32,12 +32,15 @@ | |||
#include <sys/types.h> | |||
#include <fcntl.h> | |||
#include <wiringPi.h> | |||
#include <gertboard.h> | |||
#ifndef TRUE | |||
# define TRUE (1==1) | |||
# define FALSE (1==2) | |||
#endif | |||
#define VERSION "1.1" | |||
#define VERSION "1.2" | |||
static int wpMode ; | |||
@@ -49,7 +52,9 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio drive <group> <value>\n" | |||
" gpio pwm-bal/pwm-ms \n" | |||
" gpio pwmr <range> \n" | |||
" gpio load spi/i2c" ; | |||
" gpio load spi/i2c\n" | |||
" gpio gbr <channel>\n" | |||
" gpio gbw <channel> <value>\n" ; | |||
/* | |||
@@ -519,6 +524,82 @@ static void doPadDrive (int argc, char *argv []) | |||
/* | |||
* doGbw: | |||
* gpio gbw channel value | |||
********************************************************************************* | |||
*/ | |||
static void doGbw (int argc, char *argv []) | |||
{ | |||
int channel, value ; | |||
if (argc != 4) | |||
{ | |||
fprintf (stderr, "Usage: %s gbr <channel> <value>\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
channel = atoi (argv [2]) ; | |||
value = atoi (argv [3]) ; | |||
if ((channel < 0) || (channel > 1)) | |||
{ | |||
fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
if ((value < 0) || (value > 1023)) | |||
{ | |||
fprintf (stderr, "%s: value must be from 0 to 255\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
if (gertboardSPISetup () == -1) | |||
{ | |||
fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ; | |||
exit (1) ; | |||
} | |||
gertboardAnalogWrite (channel, value) ; | |||
} | |||
/* | |||
* doGbr: | |||
* gpio gbr channel | |||
********************************************************************************* | |||
*/ | |||
static void doGbr (int argc, char *argv []) | |||
{ | |||
int channel ; | |||
if (argc != 3) | |||
{ | |||
fprintf (stderr, "Usage: %s gbr <channel>\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
channel = atoi (argv [2]) ; | |||
if ((channel < 0) || (channel > 1)) | |||
{ | |||
fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
if (gertboardSPISetup () == -1) | |||
{ | |||
fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ; | |||
exit (1) ; | |||
} | |||
printf ("%d\n",gertboardAnalogRead (channel)) ; | |||
} | |||
/* | |||
* doWrite: | |||
* gpio write pin value | |||
********************************************************************************* | |||
@@ -709,6 +790,11 @@ int main (int argc, char *argv []) | |||
if (strcasecmp (argv [1], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; } | |||
if (strcasecmp (argv [1], "load" ) == 0) { doLoad (argc, argv) ; return 0 ; } | |||
// Gertboard commands | |||
if (strcasecmp (argv [1], "gbr" ) == 0) { doGbr (argc, argv) ; return 0 ; } | |||
if (strcasecmp (argv [1], "gbw" ) == 0) { doGbw (argc, argv) ; return 0 ; } | |||
// Check for -g argument | |||
if (strcasecmp (argv [1], "-g") == 0) | |||
@@ -38,12 +38,12 @@ LIBS = | |||
SRC = wiringPi.c wiringPiFace.c wiringSerial.c wiringShift.c \ | |||
gertboard.c \ | |||
piNes.c \ | |||
lcd.c piHiPri.c piThread.c softPwm.c | |||
lcd.c piHiPri.c piThread.c softPwm.c wiringPiSPI.c | |||
OBJ = wiringPi.o wiringPiFace.o wiringSerial.o wiringShift.o \ | |||
gertboard.o \ | |||
piNes.o \ | |||
lcd.o piHiPri.o piThread.o softPwm.o | |||
lcd.o piHiPri.o piThread.o softPwm.o wiringPiSPI.o | |||
all: $(TARGET) | |||
@@ -78,6 +78,7 @@ install: $(TARGET) | |||
install -m 0644 piNes.h /usr/local/include | |||
install -m 0644 softPwm.h /usr/local/include | |||
install -m 0644 lcd.h /usr/local/include | |||
install -m 0644 wiringPiSPI.h /usr/local/include | |||
install -m 0644 libwiringPi.a /usr/local/lib | |||
uninstall: | |||
@@ -38,23 +38,16 @@ | |||
#include <sys/ioctl.h> | |||
#include <linux/spi/spidev.h> | |||
#include "gertboard.h" | |||
#include "wiringPiSPI.h" | |||
// The SPI bus parameters | |||
// Variables as they need to be passed as pointers later on | |||
static char *spiA2D = "/dev/spidev0.0" ; | |||
static char *spiD2A = "/dev/spidev0.1" ; | |||
static uint8_t spiMode = 0 ; | |||
static uint8_t spiBPW = 8 ; | |||
static uint32_t spiSpeed = 100000 ; // 1MHz | |||
static uint16_t spiDelay = 0; | |||
#include "gertboard.h" | |||
// Locals here to keep track of everything | |||
// The A-D convertor won't run at more than 1MHz @ 3.3v | |||
static int spiFdA2D ; | |||
static int spiFdD2A ; | |||
#define SPI_ADC_SPEED 1000000 | |||
#define SPI_DAC_SPEED 1000000 | |||
#define SPI_A2D 0 | |||
#define SPI_D2A 1 | |||
/* | |||
@@ -66,10 +59,7 @@ static int spiFdD2A ; | |||
void gertboardAnalogWrite (int chan, int value) | |||
{ | |||
uint8_t spiBufTx [2] ; | |||
uint8_t spiBufRx [2] ; | |||
struct spi_ioc_transfer spi ; | |||
uint8_t spiData [2] ; | |||
uint8_t chanBits, dataBits ; | |||
if (chan == 0) | |||
@@ -80,17 +70,10 @@ void gertboardAnalogWrite (int chan, int value) | |||
chanBits |= ((value >> 4) & 0x0F) ; | |||
dataBits = ((value << 4) & 0xF0) ; | |||
spiBufTx [0] = chanBits ; | |||
spiBufTx [1] = dataBits ; | |||
spi.tx_buf = (unsigned long)spiBufTx ; | |||
spi.rx_buf = (unsigned long)spiBufRx ; | |||
spi.len = 2 ; | |||
spi.delay_usecs = spiDelay ; | |||
spi.speed_hz = spiSpeed ; | |||
spi.bits_per_word = spiBPW ; | |||
spiData [0] = chanBits ; | |||
spiData [1] = dataBits ; | |||
ioctl (spiFdD2A, SPI_IOC_MESSAGE(1), &spi) ; | |||
wiringPiSPIDataRW (SPI_D2A, spiData, 2) ; | |||
} | |||
@@ -103,60 +86,21 @@ void gertboardAnalogWrite (int chan, int value) | |||
int gertboardAnalogRead (int chan) | |||
{ | |||
uint8_t spiBufTx [4] ; | |||
uint8_t spiBufRx [4] ; | |||
struct spi_ioc_transfer spi ; | |||
uint8_t spiData [2] ; | |||
uint8_t chanBits ; | |||
if (chan == 0) | |||
chanBits = 0b0110100 ; | |||
chanBits = 0b11010000 ; | |||
else | |||
chanBits = 0b0111100 ; | |||
spiBufTx [0] = chanBits ; | |||
spiBufTx [1] = 0 ; | |||
spi.tx_buf = (unsigned long)spiBufTx ; | |||
spi.rx_buf = (unsigned long)spiBufRx ; | |||
spi.len = 4 ; | |||
spi.delay_usecs = spiDelay ; | |||
spi.speed_hz = spiSpeed ; | |||
spi.bits_per_word = spiBPW ; | |||
ioctl (spiFdA2D, SPI_IOC_MESSAGE(1), &spi) ; | |||
return spiBufRx [0] << 8 | spiBufRx [1] ; | |||
} | |||
/* | |||
* setParams: | |||
* Output the SPI bus parameters to the given device | |||
********************************************************************************* | |||
*/ | |||
chanBits = 0b11110000 ; | |||
static int setParams (int fd) | |||
{ | |||
if (ioctl (fd, SPI_IOC_WR_MODE, &spiMode) < 0) | |||
return -1 ; | |||
if (ioctl (fd, SPI_IOC_RD_MODE, &spiMode) < 0) | |||
return -1 ; | |||
if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0) | |||
return -1 ; | |||
if (ioctl (fd, SPI_IOC_RD_BITS_PER_WORD, &spiBPW) < 0) | |||
return -1 ; | |||
spiData [0] = chanBits ; | |||
spiData [1] = 0 ; | |||
if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &spiSpeed) < 0) | |||
return -1 ; | |||
if (ioctl (fd, SPI_IOC_RD_MAX_SPEED_HZ, &spiSpeed) < 0) | |||
return -1 ; | |||
wiringPiSPIDataRW (SPI_A2D, spiData, 2) ; | |||
return 0 ; | |||
return ((spiData [0] << 7) | (spiData [1] >> 1)) & 0x3FF ; | |||
} | |||
@@ -168,16 +112,10 @@ static int setParams (int fd) | |||
int gertboardSPISetup (void) | |||
{ | |||
if ((spiFdA2D = open (spiA2D, O_RDWR)) < 0) | |||
return -1 ; | |||
if (setParams (spiFdA2D) != 0) | |||
return -1 ; | |||
if ((spiFdD2A = open (spiD2A, O_RDWR)) < 0) | |||
if (wiringPiSPISetup (SPI_A2D, SPI_ADC_SPEED) < 0) | |||
return -1 ; | |||
if (setParams (spiFdD2A) != 0) | |||
if (wiringPiSPISetup (SPI_D2A, SPI_DAC_SPEED) < 0) | |||
return -1 ; | |||
return 0 ; | |||
@@ -0,0 +1,117 @@ | |||
/* | |||
* wiringPiSPI.c: | |||
* Simplified SPI access routines | |||
* Copyright (c) 2012 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
* | |||
* wiringPi 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 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* wiringPi 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 wiringPi. | |||
* If not, see <http://www.gnu.org/licenses/>. | |||
*********************************************************************** | |||
*/ | |||
#include <stdint.h> | |||
#include <fcntl.h> | |||
#include <sys/ioctl.h> | |||
#include <linux/spi/spidev.h> | |||
#include "wiringPiSPI.h" | |||
// The SPI bus parameters | |||
// Variables as they need to be passed as pointers later on | |||
static char *spiDev0 = "/dev/spidev0.0" ; | |||
static char *spiDev1 = "/dev/spidev0.1" ; | |||
static uint8_t spiMode = 0 ; | |||
static uint8_t spiBPW = 8 ; | |||
static uint16_t spiDelay = 0; | |||
static uint32_t spiSpeeds [2] ; | |||
static int spiFds [2] ; | |||
/* | |||
* wiringPiSPIGetFd: | |||
* Return the file-descriptor for the given channel | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSPIGetFd (int channel) | |||
{ | |||
return spiFds [channel &1] ; | |||
} | |||
/* | |||
* wiringPiSPIDataRW: | |||
* Write and Read a block of data over the SPI bus. | |||
* Note the data ia being read into the transmit buffer, so will | |||
* overwrite it! | |||
* This is also a full-duplex operation. | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) | |||
{ | |||
struct spi_ioc_transfer spi ; | |||
channel &= 1 ; | |||
spi.tx_buf = (unsigned long)data ; | |||
spi.rx_buf = (unsigned long)data ; | |||
spi.len = len ; | |||
spi.delay_usecs = spiDelay ; | |||
spi.speed_hz = spiSpeeds [channel] ; | |||
spi.bits_per_word = spiBPW ; | |||
return ioctl (spiFds [channel], SPI_IOC_MESSAGE(1), &spi) ; | |||
} | |||
/* | |||
* wiringPiSPISetup: | |||
* Open the SPI device, and set it up, etc. | |||
********************************************************************************* | |||
*/ | |||
int wiringPiSPISetup (int channel, int speed) | |||
{ | |||
int fd ; | |||
channel &= 1 ; | |||
if ((fd = open (channel == 0 ? spiDev0 : spiDev1, O_RDWR)) < 0) | |||
return -1 ; | |||
spiSpeeds [channel] = speed ; | |||
spiFds [channel] = fd ; | |||
// Set SPI parameters. | |||
// Why are we reading it afterwriting it? I've no idea, but for now I'm blindly | |||
// copying example code I've seen online... | |||
if (ioctl (fd, SPI_IOC_WR_MODE, &spiMode) < 0) return -1 ; | |||
if (ioctl (fd, SPI_IOC_RD_MODE, &spiMode) < 0) return -1 ; | |||
if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0) return -1 ; | |||
if (ioctl (fd, SPI_IOC_RD_BITS_PER_WORD, &spiBPW) < 0) return -1 ; | |||
if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0) return -1 ; | |||
if (ioctl (fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) return -1 ; | |||
return fd ; | |||
} |
@@ -0,0 +1,35 @@ | |||
/* | |||
* wiringPiSPI.h: | |||
* Simplified SPI access routines | |||
* Copyright (c) 2012 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
* | |||
* wiringPi 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 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* wiringPi 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 wiringPi. | |||
* If not, see <http://www.gnu.org/licenses/>. | |||
*********************************************************************** | |||
*/ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
int wiringPiSPIGetFd (int channel) ; | |||
int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ; | |||
int wiringPiSPISetup (int channel, int speed) ; | |||
#ifdef __cplusplus | |||
} | |||
#endif |