Browse Source

Added new SPI driver helpers.

Changed the gertboard code to use it
and ran more tests on he Gertboard code.
pull/22/head
Gordon Henderson 12 years ago
parent
commit
99095e3fa0
7 changed files with 330 additions and 99 deletions
  1. +37
    -7
      examples/gertboard.c
  2. +28
    -4
      gpio/gpio.1
  3. +90
    -4
      gpio/gpio.c
  4. +3
    -2
      wiringPi/Makefile
  5. +20
    -82
      wiringPi/gertboard.c
  6. +117
    -0
      wiringPi/wiringPiSPI.c
  7. +35
    -0
      wiringPi/wiringPiSPI.h

+ 37
- 7
examples/gertboard.c View File

@@ -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 ;
int h1 ;
double angle ;
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, h1) ;
gertboardAnalogWrite (0, buffer [i]) ;


#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 ;


+ 28
- 4
gpio/gpio.1 View File

@@ -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
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 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"




+ 90
- 4
gpio/gpio.c View File

@@ -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" ;




/* /*
@@ -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: * 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)


+ 3
- 2
wiringPi/Makefile View File

@@ -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:


+ 20
- 82
wiringPi/gertboard.c View File

@@ -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
// 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) 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 ; 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 ;
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) int gertboardAnalogRead (int chan)
{ {
uint8_t spiBufTx [4] ;
uint8_t spiBufRx [4] ;
struct spi_ioc_transfer spi ;
uint8_t spiData [2] ;


uint8_t chanBits ; uint8_t chanBits ;


if (chan == 0) if (chan == 0)
chanBits = 0b0110100 ;
chanBits = 0b11010000 ;
else 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) 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 ; return -1 ;


if (setParams (spiFdD2A) != 0)
if (wiringPiSPISetup (SPI_D2A, SPI_DAC_SPEED) < 0)
return -1 ; return -1 ;


return 0 ; return 0 ;


+ 117
- 0
wiringPi/wiringPiSPI.c View File

@@ -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 ;
}

+ 35
- 0
wiringPi/wiringPiSPI.h View File

@@ -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