Added new SPI driver helpers.

Changed the gertboard code to use it
and ran more tests on he Gertboard code.
pull/6/head
Gordon Henderson 13 years ago
parent 4666573910
commit 99095e3fa0

@ -14,33 +14,63 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
//#include <stdlib.h>
#include <math.h> #include <math.h>
#define B_SIZE 200
#undef DO_TIMING
#include <wiringPi.h> #include <wiringPi.h>
#include <gertboard.h> #include <gertboard.h>
int main (void) int main (void)
{ {
int angle ; double angle ;
int h1 ; int i ;
uint32_t x1 ; uint32_t x1 ;
int buffer [B_SIZE] ;
#ifdef DO_TIMING
unsigned int now, then ;
#endif
printf ("Raspberry Pi Gertboard SPI test program\n") ; printf ("Raspberry Pi Gertboard SPI test program\n") ;
if (gertboardSPISetup () == -1) if (wiringPiSetupSys () < 0)
return -1 ;
if (gertboardSPISetup () < 0)
return 1 ; 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 (;;)
{ {
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, buffer [i]) ;
gertboardAnalogWrite (0, h1) ;
#ifndef DO_TIMING
x1 = gertboardAnalogRead (0) ; x1 = gertboardAnalogRead (0) ;
gertboardAnalogWrite (1, x1 >> 2) ; // 10-bit A/D, 8-bit D/A 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 ; return 0 ;

@ -36,14 +36,23 @@ range
.PP .PP
.B gpio .B gpio
.B load \ i2c/spi .B load \ i2c/spi
.PP
.B gpio
.B gbr
channel
.PP
.B gpio
.B gbw
channel value
.SH DESCRIPTION .SH DESCRIPTION
.B GPIO .B GPIO
is a command line tool to allow the user easy access to the GPIO pins is a swiss army knofe of a command line tool to allow the user easy
on the Raspberry Pi. It's designed for simple testing and diagnostic access to the GPIO pins on the Raspberry Pi and the SPI A/D and D/A
purposes, but can be used in shell scripts for general if somewhat slow convertors on the Gertboard. It's designed for simple testing and
control of the GPIO pins. 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 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 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 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. 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" .SH "WiringPi vs. GPIO Pin numbering"

@ -1,6 +1,7 @@
/* /*
* gpio.c: * 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 * Copyright (c) 2012 Gordon Henderson
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
@ -21,7 +22,6 @@
*********************************************************************** ***********************************************************************
*/ */
#include <wiringPi.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -32,12 +32,15 @@
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <wiringPi.h>
#include <gertboard.h>
#ifndef TRUE #ifndef TRUE
# define TRUE (1==1) # define TRUE (1==1)
# define FALSE (1==2) # define FALSE (1==2)
#endif #endif
#define VERSION "1.1" #define VERSION "1.2"
static int wpMode ; static int wpMode ;
@ -49,7 +52,9 @@ char *usage = "Usage: gpio -v\n"
" gpio drive <group> <value>\n" " gpio drive <group> <value>\n"
" gpio pwm-bal/pwm-ms \n" " gpio pwm-bal/pwm-ms \n"
" gpio pwmr <range> \n" " gpio pwmr <range> \n"
" gpio load spi/i2c" ; " gpio load spi/i2c\n"
" gpio gbr <channel>\n"
" gpio gbw <channel> <value>\n" ;
/* /*
@ -518,6 +523,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: * doWrite:
* gpio write pin value * 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], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; }
if (strcasecmp (argv [1], "load" ) == 0) { doLoad (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 // Check for -g argument
if (strcasecmp (argv [1], "-g") == 0) if (strcasecmp (argv [1], "-g") == 0)

@ -38,12 +38,12 @@ LIBS =
SRC = wiringPi.c wiringPiFace.c wiringSerial.c wiringShift.c \ SRC = wiringPi.c wiringPiFace.c wiringSerial.c wiringShift.c \
gertboard.c \ gertboard.c \
piNes.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 \ OBJ = wiringPi.o wiringPiFace.o wiringSerial.o wiringShift.o \
gertboard.o \ gertboard.o \
piNes.o \ piNes.o \
lcd.o piHiPri.o piThread.o softPwm.o lcd.o piHiPri.o piThread.o softPwm.o wiringPiSPI.o
all: $(TARGET) all: $(TARGET)
@ -78,6 +78,7 @@ install: $(TARGET)
install -m 0644 piNes.h /usr/local/include install -m 0644 piNes.h /usr/local/include
install -m 0644 softPwm.h /usr/local/include install -m 0644 softPwm.h /usr/local/include
install -m 0644 lcd.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 install -m 0644 libwiringPi.a /usr/local/lib
uninstall: uninstall:

@ -38,23 +38,16 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <linux/spi/spidev.h> #include <linux/spi/spidev.h>
#include "gertboard.h" #include "wiringPiSPI.h"
// The SPI bus parameters #include "gertboard.h"
// 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;
// Locals here to keep track of everything // The A-D convertor won't run at more than 1MHz @ 3.3v
static int spiFdA2D ; #define SPI_ADC_SPEED 1000000
static int spiFdD2A ; #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) void gertboardAnalogWrite (int chan, int value)
{ {
uint8_t spiBufTx [2] ; uint8_t spiData [2] ;
uint8_t spiBufRx [2] ;
struct spi_ioc_transfer spi ;
uint8_t chanBits, dataBits ; uint8_t chanBits, dataBits ;
if (chan == 0) if (chan == 0)
@ -80,17 +70,10 @@ void gertboardAnalogWrite (int chan, int value)
chanBits |= ((value >> 4) & 0x0F) ; chanBits |= ((value >> 4) & 0x0F) ;
dataBits = ((value << 4) & 0xF0) ; dataBits = ((value << 4) & 0xF0) ;
spiBufTx [0] = chanBits ; spiData [0] = chanBits ;
spiBufTx [1] = dataBits ; spiData [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 ;
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) int gertboardAnalogRead (int chan)
{ {
uint8_t spiBufTx [4] ; uint8_t spiData [2] ;
uint8_t spiBufRx [4] ;
struct spi_ioc_transfer spi ;
uint8_t chanBits ; uint8_t chanBits ;
if (chan == 0) if (chan == 0)
chanBits = 0b0110100 ; chanBits = 0b11010000 ;
else else
chanBits = 0b0111100 ; chanBits = 0b11110000 ;
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
*********************************************************************************
*/
static int setParams (int fd) spiData [0] = chanBits ;
{ spiData [1] = 0 ;
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, &spiSpeed) < 0) wiringPiSPIDataRW (SPI_A2D, spiData, 2) ;
return -1 ;
if (ioctl (fd, SPI_IOC_RD_MAX_SPEED_HZ, &spiSpeed) < 0)
return -1 ;
return 0 ; return ((spiData [0] << 7) | (spiData [1] >> 1)) & 0x3FF ;
} }
@ -168,16 +112,10 @@ static int setParams (int fd)
int gertboardSPISetup (void) int gertboardSPISetup (void)
{ {
if ((spiFdA2D = open (spiA2D, O_RDWR)) < 0) if (wiringPiSPISetup (SPI_A2D, SPI_ADC_SPEED) < 0)
return -1 ;
if (setParams (spiFdA2D) != 0)
return -1 ;
if ((spiFdD2A = open (spiD2A, O_RDWR)) < 0)
return -1 ; return -1 ;
if (setParams (spiFdD2A) != 0) if (wiringPiSPISetup (SPI_D2A, SPI_DAC_SPEED) < 0)
return -1 ; return -1 ;
return 0 ; 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
Loading…
Cancel
Save