Browse Source

Merged from git.drogon.net, SPI driver helpers, C++ wrappers, softPwm, piNes, gertboard, SPI

pull/1/head
Gordon Henderson 12 years ago
committed by Philip Howard
parent
commit
ae40bdaf6a
22 changed files with 1703 additions and 274 deletions
  1. +21
    -4
      examples/Makefile
  2. +68
    -0
      examples/delayTest.c
  3. +77
    -0
      examples/gertboard.c
  4. BIN
      examples/gertboard.png
  5. +44
    -0
      examples/nes.c
  6. +69
    -0
      examples/softPwm.c
  7. +1
    -1
      gpio/Makefile
  8. +83
    -19
      gpio/gpio.1
  9. +360
    -90
      gpio/gpio.c
  10. +122
    -0
      wiringPi/gertboard.c
  11. +39
    -0
      wiringPi/gertboard.h
  12. +8
    -0
      wiringPi/lcd.h
  13. +113
    -0
      wiringPi/piNes.c
  14. +45
    -0
      wiringPi/piNes.h
  15. +130
    -0
      wiringPi/softPwm.c
  16. +34
    -0
      wiringPi/softPwm.h
  17. +296
    -135
      wiringPi/wiringPi.c
  18. +15
    -6
      wiringPi/wiringPi.h
  19. +117
    -0
      wiringPi/wiringPiSPI.c
  20. +35
    -0
      wiringPi/wiringPiSPI.h
  21. +25
    -19
      wiringPi/wiringSerial.c
  22. +1
    -0
      wiringPi/wiringSerial.h

+ 21
- 4
examples/Makefile View File

@@ -35,11 +35,11 @@ LIBS = -lwiringPi
# Should not alter anything below this line # Should not alter anything below this line
############################################################################### ###############################################################################


SRC = test1.c test2.c speed.c lcd.c wfi.c piface.c
SRC = test1.c test2.c speed.c lcd.c wfi.c piface.c gertboard.c nes.c delayTest.c softPwm.c


OBJ = test1.o test2.o speed.o lcd.o wfi.o piface.o
OBJ = test1.o test2.o speed.o lcd.o wfi.o piface.o gertboard.o nes.o delayTest.o softPwm.o


all: test1 test2 speed lcd wfi piface
all: test1 test2 speed lcd wfi piface gertboard nes softPwm


test1: test1.o test1: test1.o
@echo [link] @echo [link]
@@ -65,13 +65,30 @@ piface: piface.o
@echo [link] @echo [link]
$(CC) -o $@ piface.o $(LDFLAGS) $(LIBS) -lpthread $(CC) -o $@ piface.o $(LDFLAGS) $(LIBS) -lpthread


gertboard: gertboard.o
@echo [link]
$(CC) -o $@ gertboard.o $(LDFLAGS) $(LIBS) -lm

nes: nes.o
@echo [link]
$(CC) -o $@ nes.o $(LDFLAGS) $(LIBS) -lm

softPwm: softPwm.o
@echo [link]
$(CC) -o $@ softPwm.o $(LDFLAGS) $(LIBS) -lm -lpthread


delayTest: delayTest.o
@echo [link]
$(CC) -o $@ delayTest.o $(LDFLAGS) $(LIBS)



.c.o: .c.o:
@echo [CC] $< @echo [CC] $<
@$(CC) -c $(CFLAGS) $< -o $@ @$(CC) -c $(CFLAGS) $< -o $@


clean: clean:
rm -f $(OBJ) *~ core tags test1 test2 speed lcd wfi piface
rm -f $(OBJ) *~ core tags test1 test2 speed lcd wfi piface gertboard nes delayTest softPwm


tags: $(SRC) tags: $(SRC)
@echo [ctags] @echo [ctags]


+ 68
- 0
examples/delayTest.c View File

@@ -0,0 +1,68 @@

#include <stdio.h>
#include <unistd.h>
#include <wiringPi.h>

#include <time.h>
#include <sys/types.h>
#include <sys/time.h>

#define CYCLES 1000
#define DELAY 99

int main()
{
int x ;
struct timeval t1, t2 ;
long long t ;
unsigned int max, min ;

unsigned int values [CYCLES] ;

max = 0 ;
min = 1000000 ;

if (wiringPiSetup () == -1)
return 1 ;

piHiPri (10) ;
sleep (1) ;

// Baseline test

gettimeofday (&t1, NULL) ;
gettimeofday (&t2, NULL) ;

t = t2.tv_usec - t1.tv_usec ;
printf ("Baseline test: %lld\n", t);

for (x = 0 ; x < CYCLES ; ++x)
{
gettimeofday (&t1, NULL) ;
delayMicroseconds (DELAY) ;
gettimeofday (&t2, NULL) ;
t = t2.tv_usec - t1.tv_usec ;
if (t > max) max = t ;
if (t < min) min = t ;
values [x] = t ;
}

printf ("Done: Max: %d, min: %d\n", max, min) ;

for (x = 0 ; x < CYCLES ; ++x)
{
printf ("%4d", values [x]) ;
if (values [x] > DELAY)
printf (".") ;
else if (values [x] < DELAY)
printf ("-") ;
else
printf (" ") ;
if (((x + 1) % 20) == 0)
printf ("\n") ;
}
printf ("\n") ;

return 0 ;
}

+ 77
- 0
examples/gertboard.c View File

@@ -0,0 +1,77 @@

/*
* gertboard.c:
* Simple test for the SPI bus on the Gertboard
*
* Hardware setup:
* D/A port 0 jumpered to A/D port 0.
*
* We output a sine wave on D/A port 0 and sample A/D port 0. We then
* copy this value to D/A port 1 and use a 'scope on both D/A ports
* to check all's well.
*
*/

#include <stdio.h>
#include <stdint.h>
#include <math.h>

#define B_SIZE 200
#undef DO_TIMING

#include <wiringPi.h>
#include <gertboard.h>

int main (void)
{
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 (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 (;;)
{
#ifdef DO_TIMING
then = millis () ;
#endif

for (i = 0 ; i < B_SIZE ; ++i)
{
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 ;
}

BIN
examples/gertboard.png View File

Before After
Width: 400  |  Height: 240  |  Size: 4.7 KiB

+ 44
- 0
examples/nes.c View File

@@ -0,0 +1,44 @@

#include <stdio.h>
#include <errno.h>
#include <string.h>

#include <wiringPi.h>
#include <piNes.h>

#define BLANK "| "

int main ()
{
int joystick ;
unsigned int buttons ;

if (wiringPiSetup () == -1)
{
fprintf (stdout, "oops: %s\n", strerror (errno)) ;
return 1 ;
}

if ((joystick = setupNesJoystick (2, 1, 0)) == -1)
{
fprintf (stdout, "Unable to setup joystick\n") ;
return 1 ;
}

for (;;)
{
buttons = readNesJoystick (joystick) ;

if ((buttons & NES_UP) != 0) printf ("| UP " ) ; else printf (BLANK) ;
if ((buttons & NES_DOWN) != 0) printf ("| DOWN " ) ; else printf (BLANK) ;
if ((buttons & NES_LEFT) != 0) printf ("| LEFT " ) ; else printf (BLANK) ;
if ((buttons & NES_RIGHT) != 0) printf ("|RIGHT " ) ; else printf (BLANK) ;
if ((buttons & NES_SELECT) != 0) printf ("|SELECT" ) ; else printf (BLANK) ;
if ((buttons & NES_START) != 0) printf ("|START " ) ; else printf (BLANK) ;
if ((buttons & NES_A) != 0) printf ("| A " ) ; else printf (BLANK) ;
if ((buttons & NES_B) != 0) printf ("| B " ) ; else printf (BLANK) ;
printf ("|\n") ;
}

return 0 ;
}

+ 69
- 0
examples/softPwm.c View File

@@ -0,0 +1,69 @@

#include <stdio.h>
#include <errno.h>
#include <string.h>

#include <wiringPi.h>
#include <softPwm.h>

#define RANGE 100
#define NUM_LEDS 12

int ledMap [NUM_LEDS] = { 0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13 } ;

int values [NUM_LEDS] = { 0, 17, 32, 50, 67, 85, 100, 85, 67, 50, 32, 17 } ;

int main ()
{
int i, j ;
char buf [80] ;

if (wiringPiSetup () == -1)
{
fprintf (stdout, "oops: %s\n", strerror (errno)) ;
return 1 ;
}

for (i = 0 ; i < NUM_LEDS ; ++i)
{
softPwmCreate (ledMap [i], 0, RANGE) ;
printf ("%3d, %3d, %3d\n", i, ledMap [i], values [i]) ;
}

fgets (buf, 80, stdin) ;

// Bring all up one by one:

for (i = 0 ; i < NUM_LEDS ; ++i)
for (j = 0 ; j <= 100 ; ++j)
{
softPwmWrite (ledMap [i], j) ;
delay (10) ;
}

fgets (buf, 80, stdin) ;

// Down fast

for (i = 100 ; i > 0 ; --i)
{
for (j = 0 ; j < NUM_LEDS ; ++j)
softPwmWrite (ledMap [j], i) ;
delay (10) ;
}

fgets (buf, 80, stdin) ;

for (;;)
{
for (i = 0 ; i < NUM_LEDS ; ++i)
softPwmWrite (ledMap [i], values [i]) ;

delay (50) ;

i = values [0] ;
for (j = 0 ; j < NUM_LEDS - 1 ; ++j)
values [j] = values [j + 1] ;
values [NUM_LEDS - 1] = i ;
}
}

+ 1
- 1
gpio/Makefile View File

@@ -41,7 +41,7 @@ OBJ = gpio.o


all: gpio all: gpio


gpio: gpio.o
gpio: gpio.o /usr/local/lib/libwiringPi.a
@echo [LD] @echo [LD]
@$(CC) -o $@ gpio.o $(LDFLAGS) $(LIBS) @$(CC) -o $@ gpio.o $(LDFLAGS) $(LIBS)


+ 83
- 19
gpio/gpio.1 View File

@@ -4,28 +4,55 @@
gpio \- Command-line access to Raspberry Pi and PiFace GPIO gpio \- Command-line access to Raspberry Pi and PiFace GPIO


.SH SYNOPSIS .SH SYNOPSIS
.TP
.B gpio .B gpio
.RB [ \-v ]
.TP
.B \-v
.PP
.B gpio .B gpio
.RB [ \-g ]
.RB < read/write/pwm/mode ...>
.TP
.B [ \-g ]
.B read/write/pwm/mode ...
.PP
.B gpio .B gpio
.RB [ \-p ]
.RB < read/write/mode ...>
.TP
.B [ \-p ]
.B read/write/mode
.B ...
.PP
.B gpio
.B unexportall/exports
.PP
.B gpio
.B export/edge/unexport
.B ...
.PP
.B gpio .B gpio
.RB < export/edge/unexport/unexportall/exports ...>
.B drive
group value
.PP
.B gpio
.B pwm-bal/pwm-ms
.PP
.B gpio
.B pwmr
range
.PP
.B gpio
.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
@@ -65,6 +92,14 @@ use the literals \fIup\fR, \fIdown\fR or \fItri\fR to set the internal
pull-up, pull-down or tristate (off) controls. pull-up, pull-down or tristate (off) controls.


.TP .TP
.B unexportall
Un-Export all the GPIO pins in the /sys/class/gpio directory.

.TP
.B exports
Print a list (if any) of all the exported GPIO pins and their current values.

.TP
.B export .B export
Export a GPIO pin in the \fI/sys/class/gpio\fR directory. Use like the Export a GPIO pin in the \fI/sys/class/gpio\fR directory. Use like the
mode command above however only \fIin\fR and \fIout\fR are supported at mode command above however only \fIin\fR and \fIout\fR are supported at
@@ -96,12 +131,41 @@ requiring root/sudo.
Un-Export a GPIO pin in the /sys/class/gpio directory. Un-Export a GPIO pin in the /sys/class/gpio directory.


.TP .TP
.B unexportall
Un-Export all the GPIO pins in the /sys/class/gpio directory.
.B drive
group value

Change the pad driver value for the given pad group to the supplied drive
value. Group is 0, 1 or 2 and value is 0-7. Do not use unless you are
absolutely sure you know what you're doing.


.TP .TP
.B exports
Print a list (if any) of all the exported GPIO pins and their current values.
.B pwm-bal/pwm-ms
Change the PWM mode to balanced (the default) or mark:space ratio (traditional)

.TP
.B pwmr
Change the PWM range register. The default is 1024.

.TP
.B load i2c/spi
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" .SH "WiringPi vs. GPIO Pin numbering"


@@ -170,7 +234,7 @@ Gordon Henderson


.SH "REPORTING BUGS" .SH "REPORTING BUGS"


Report bugs to <gordon@drogon.net>
Report bugs to <projects@drogon.net>


.SH COPYRIGHT .SH COPYRIGHT




+ 360
- 90
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,15 +32,144 @@
#include <sys/types.h> #include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>


#include <wiringPi.h>
#include <gertboard.h>

#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif


#define VERSION "1.0"
#define VERSION "1.2"


static int wpMode ; static int wpMode ;


char *usage = "Usage: gpio -v\n" char *usage = "Usage: gpio -v\n"
" gpio -h\n"
" gpio [-g] <read/write/pwm/mode> ...\n" " gpio [-g] <read/write/pwm/mode> ...\n"
" gpio [-p] <read/write/mode> ...\n" " gpio [-p] <read/write/mode> ...\n"
" gpio <export/edge/unexport/unexportall/exports> ..." ;
" gpio export/edge/unexport/unexportall/exports ...\n"
" gpio drive <group> <value>\n"
" gpio pwm-bal/pwm-ms \n"
" gpio pwmr <range> \n"
" gpio load spi/i2c\n"
" gpio gbr <channel>\n"
" gpio gbw <channel> <value>\n" ;


/*
* changeOwner:
* Change the ownership of the file to the real userId of the calling
* program so we can access it.
*********************************************************************************
*/

static void changeOwner (char *cmd, char *file)
{
uid_t uid = getuid () ;
uid_t gid = getgid () ;

if (chown (file, uid, gid) != 0)
{
if (errno == ENOENT) // Warn that it's not there
fprintf (stderr, "%s: Warning: File not present: %s\n", cmd, file) ;
else
{
fprintf (stderr, "%s: Unable to change ownership of %s: %s\n", cmd, file, strerror (errno)) ;
exit (1) ;
}
}
}


/*
* moduleLoaded:
* Return true/false if the supplied module is loaded
*********************************************************************************
*/

static int moduleLoaded (char *modName)
{
int len = strlen (modName) ;
int found = FALSE ;
FILE *fd = fopen ("/proc/modules", "r") ;
char line [80] ;

if (fd == NULL)
{
fprintf (stderr, "gpio: Unable to check modules: %s\n", strerror (errno)) ;
exit (1) ;
}

while (fgets (line, 80, fd) != NULL)
{
if (strncmp (line, modName, len) != 0)
continue ;

found = TRUE ;
break ;
}

fclose (fd) ;

return found ;
}


/*
* doLoad:
* Load either the spi or i2c modules and change device ownerships, etc.
*********************************************************************************
*/

static void _doLoadUsage (char *argv [])
{
fprintf (stderr, "Usage: %s load <spi/i2c>\n", argv [0]) ;
exit (1) ;
}

static void doLoad (int argc, char *argv [])
{
char *module ;
char cmd [80] ;
char *file1, *file2 ;

if (argc != 3)
_doLoadUsage (argv) ;

/**/ if (strcasecmp (argv [2], "spi") == 0)
{
module = "spi_bcm2708" ;
file1 = "/dev/spidev0.0" ;
file2 = "/dev/spidev0.1" ;
}
else if (strcasecmp (argv [2], "i2c") == 0)
{
module = "i2c_bcm2708" ;
file1 = "/dev/i2c-0" ;
file2 = "/dev/i2c-1" ;
}
else
_doLoadUsage (argv) ;

if (!moduleLoaded (module))
{
sprintf (cmd, "modprobe %s", module) ;
system (cmd) ;
}

if (!moduleLoaded (module))
{
fprintf (stderr, "%s: Unable to load %s\n", argv [0], module) ;
exit (1) ;
}

sleep (1) ; // To let things get settled

changeOwner (argv [0], file1) ;
changeOwner (argv [0], file2) ;
}





/* /*
@@ -49,7 +178,7 @@ char *usage = "Usage: gpio -v\n"
********************************************************************************* *********************************************************************************
*/ */


void doExports (void)
static void doExports (int argc, char *argv [])
{ {
int fd ; int fd ;
int i, l, first ; int i, l, first ;
@@ -140,8 +269,6 @@ void doExport (int argc, char *argv [])
int pin ; int pin ;
char *mode ; char *mode ;
char fName [128] ; char fName [128] ;
uid_t uid ;
gid_t gid ;


if (argc != 4) if (argc != 4)
{ {
@@ -183,27 +310,11 @@ void doExport (int argc, char *argv [])


// Change ownership so the current user can actually use it! // Change ownership so the current user can actually use it!


uid = getuid () ;
gid = getgid () ;

sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
if (chown (fName, uid, gid) != 0)
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}

// Also change ownership of the edge file - if it exists
changeOwner (argv [0], fName) ;


sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ; sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
if (chown (fName, uid, gid) != 0)
{
if (errno != ENOENT) // Silently ignore File not found - older kernel
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}
}
changeOwner (argv [0], fName) ;


} }


@@ -222,8 +333,6 @@ void doEdge (int argc, char *argv [])
int pin ; int pin ;
char *mode ; char *mode ;
char fName [128] ; char fName [128] ;
uid_t uid ;
gid_t gid ;


if (argc != 4) if (argc != 4)
{ {
@@ -231,8 +340,7 @@ void doEdge (int argc, char *argv [])
exit (1) ; exit (1) ;
} }


pin = atoi (argv [2]) ;

pin = atoi (argv [2]) ;
mode = argv [3] ; mode = argv [3] ;


// Export the pin and set direction to input // Export the pin and set direction to input
@@ -263,40 +371,23 @@ void doEdge (int argc, char *argv [])
exit (1) ; exit (1) ;
} }


/**/ if (strcasecmp (mode, "none") == 0)
fprintf (fd, "none\n") ;
else if (strcasecmp (mode, "rising") == 0)
fprintf (fd, "rising\n") ;
else if (strcasecmp (mode, "falling") == 0)
fprintf (fd, "falling\n") ;
else if (strcasecmp (mode, "both") == 0)
fprintf (fd, "both\n") ;
/**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\n") ;
else else
{ {
fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ; fprintf (stderr, "%s: Invalid mode: %s. Should be none, rising, falling or both\n", argv [1], mode) ;
exit (1) ; exit (1) ;
} }


// Change ownership so the current user can actually use it!

uid = getuid () ;
gid = getgid () ;
// Change ownership of the value and edge files, so the current user can actually use it!


sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ; sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
if (chown (fName, uid, gid) != 0)
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}

// Also change ownership of the edge file
changeOwner (argv [0], fName) ;


sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ; sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
if (chown (fName, uid, gid) != 0)
{
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
exit (1) ;
}
changeOwner (argv [0], fName) ;


fclose (fd) ; fclose (fd) ;
} }
@@ -383,18 +474,12 @@ void doMode (int argc, char *argv [])


mode = argv [3] ; mode = argv [3] ;


/**/ if (strcasecmp (mode, "in") == 0)
pinMode (pin, INPUT) ;
else if (strcasecmp (mode, "out") == 0)
pinMode (pin, OUTPUT) ;
else if (strcasecmp (mode, "pwm") == 0)
pinMode (pin, PWM_OUTPUT) ;
else if (strcasecmp (mode, "up") == 0)
pullUpDnControl (pin, PUD_UP) ;
else if (strcasecmp (mode, "down") == 0)
pullUpDnControl (pin, PUD_DOWN) ;
else if (strcasecmp (mode, "tri") == 0)
pullUpDnControl (pin, PUD_OFF) ;
/**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
else else
{ {
fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ; fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ;
@@ -402,13 +487,125 @@ void doMode (int argc, char *argv [])
} }
} }



/*
* doPadDrive:
* gpio drive group value
*********************************************************************************
*/

static void doPadDrive (int argc, char *argv [])
{
int group, val ;

if (argc != 4)
{
fprintf (stderr, "Usage: %s drive group value\n", argv [0]) ;
exit (1) ;
}

group = atoi (argv [2]) ;
val = atoi (argv [3]) ;

if ((group < 0) || (group > 2))
{
fprintf (stderr, "%s: drive group not 0, 1 or 2: %d\n", argv [0], group) ;
exit (1) ;
}

if ((val < 0) || (val > 7))
{
fprintf (stderr, "%s: drive value not 0-7: %d\n", argv [0], val) ;
exit (1) ;
}

setPadDrive (group, val) ;
}


/*
* 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
********************************************************************************* *********************************************************************************
*/ */


void doWrite (int argc, char *argv [])
static void doWrite (int argc, char *argv [])
{ {
int pin, val ; int pin, val ;


@@ -490,6 +687,39 @@ void doPwm (int argc, char *argv [])




/* /*
* doPwmMode: doPwmRange:
* Change the PWM mode and Range values
*********************************************************************************
*/

static void doPwmMode (int mode)
{
pwmSetMode (mode) ;
}

static void doPwmRange (int argc, char *argv [])
{
unsigned int range ;

if (argc != 3)
{
fprintf (stderr, "Usage: %s pwmr <range>\n", argv [0]) ;
exit (1) ;
}

range = (unsigned int)strtoul (argv [2], NULL, 10) ;

if (range == 0)
{
fprintf (stderr, "%s: range must be > 0\n", argv [0]) ;
exit (1) ;
}

pwmSetRange (range) ;
}


/*
* main: * main:
* Start here * Start here
********************************************************************************* *********************************************************************************
@@ -505,10 +735,10 @@ int main (int argc, char *argv [])
return 1 ; return 1 ;
} }


if (geteuid () != 0)
if (strcasecmp (argv [1], "-h") == 0)
{ {
fprintf (stderr, "%s: Must be root to run\n", argv [0]) ;
return 1 ;
printf ("%s: %s\n", argv [0], usage) ;
return 0 ;
} }


if (strcasecmp (argv [1], "-v") == 0) if (strcasecmp (argv [1], "-v") == 0)
@@ -516,21 +746,54 @@ int main (int argc, char *argv [])
printf ("gpio version: %s\n", VERSION) ; printf ("gpio version: %s\n", VERSION) ;
printf ("Copyright (c) 2012 Gordon Henderson\n") ; printf ("Copyright (c) 2012 Gordon Henderson\n") ;
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
printf ("For details type: %s -warranty\n", argv [0]) ;
return 0 ; return 0 ;
} }


if (strcasecmp (argv [1], "-warranty") == 0)
{
printf ("gpio version: %s\n", VERSION) ;
printf ("Copyright (c) 2012 Gordon Henderson\n") ;
printf ("\n") ;
printf (" This program is free software; you can redistribute it and/or modify\n") ;
printf (" it under the terms of the GNU Leser General Public License as published\n") ;
printf (" by the Free Software Foundation, either version 3 of the License, or\n") ;
printf (" (at your option) any later version.\n") ;
printf ("\n") ;
printf (" This program is distributed in the hope that it will be useful,\n") ;
printf (" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") ;
printf (" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n") ;
printf (" GNU Lesser General Public License for more details.\n") ;
printf ("\n") ;
printf (" You should have received a copy of the GNU Lesser General Public License\n") ;
printf (" along with this program. If not, see <http://www.gnu.org/licenses/>.\n") ;
printf ("\n") ;
return 0 ;
}

if (geteuid () != 0)
{
fprintf (stderr, "%s: Must be root to run. Program should be suid root. This is an error.\n", argv [0]) ;
return 1 ;
}

// Initial test for /sys/class/gpio operations: // Initial test for /sys/class/gpio operations:


/**/ if (strcasecmp (argv [1], "exports" ) == 0)
{ doExports () ; return 0 ; }
else if (strcasecmp (argv [1], "export" ) == 0)
{ doExport (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "edge" ) == 0)
{ doEdge (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "unexportall") == 0)
{ doUnexportall (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "unexport") == 0)
{ doUnexport (argc, argv) ; return 0 ; }
/**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argc, argv) ; return 0 ; }
else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }

// Check for drive or load commands:

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 // Check for -g argument


@@ -538,7 +801,7 @@ int main (int argc, char *argv [])
{ {
if (wiringPiSetupGpio () == -1) if (wiringPiSetupGpio () == -1)
{ {
fprintf (stderr, "%s: Unable to initialise GPIO in GPIO mode.\n", argv [0]) ;
fprintf (stderr, "%s: Unable to initialise GPIO mode.\n", argv [0]) ;
exit (1) ; exit (1) ;
} }


@@ -570,23 +833,30 @@ int main (int argc, char *argv [])
{ {
if (wiringPiSetup () == -1) if (wiringPiSetup () == -1)
{ {
fprintf (stderr, "%s: Unable to initialise GPIO in wiringPi mode\n", argv [0]) ;
fprintf (stderr, "%s: Unable to initialise wiringPi mode\n", argv [0]) ;
exit (1) ; exit (1) ;
} }
wpMode = WPI_MODE_PINS ; wpMode = WPI_MODE_PINS ;
} }


/**/ if (strcasecmp (argv [1], "write" ) == 0)
doWrite (argc, argv) ;
else if (strcasecmp (argv [1], "read" ) == 0)
doRead (argc, argv) ;
else if (strcasecmp (argv [1], "mode" ) == 0)
doMode (argc, argv) ;
else if (strcasecmp (argv [1], "pwm" ) == 0)
doPwm (argc, argv) ;
// Check for PWM operations

if (wpMode != WPI_MODE_PIFACE)
{
if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode (PWM_MODE_BAL) ; return 0 ; }
if (strcasecmp (argv [1], "pwm-ms") == 0) { doPwmMode (PWM_MODE_MS) ; return 0 ; }
if (strcasecmp (argv [1], "pwmr") == 0) { doPwmRange (argc, argv) ; return 0 ; }
}

// Check for wiring commands

/**/ if (strcasecmp (argv [1], "read" ) == 0) doRead (argc, argv) ;
else if (strcasecmp (argv [1], "write") == 0) doWrite (argc, argv) ;
else if (strcasecmp (argv [1], "pwm" ) == 0) doPwm (argc, argv) ;
else if (strcasecmp (argv [1], "mode" ) == 0) doMode (argc, argv) ;
else else
{ {
fprintf (stderr, "%s: Unknown command: %s. (read/write/pwm/mode expected)\n", argv [0], argv [1]) ;
fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
exit (1) ; exit (1) ;
} }
return 0 ; return 0 ;


+ 122
- 0
wiringPi/gertboard.c View File

@@ -0,0 +1,122 @@
/*
* gertboard.c:
* Access routines for the SPI devices on the Gertboard
* Copyright (c) 2012 Gordon Henderson
*
* The Gertboard has:
*
* An MCP3002 dual-channel A to D convertor connected
* to the SPI bus, selected by chip-select A, and:
*
* An MCP4802 dual-channel D to A convertor connected
* to the SPI bus, selected via chip-select B.
*
***********************************************************************
* 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 <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>

#include "wiringPiSPI.h"

#include "gertboard.h"

// The A-D convertor won't run at more than 1MHz @ 3.3v

#define SPI_ADC_SPEED 1000000
#define SPI_DAC_SPEED 1000000
#define SPI_A2D 0
#define SPI_D2A 1


/*
* gertboardAnalogWrite:
* Write an 8-bit data value to the MCP4802 Analog to digital
* convertor on the Gertboard.
*********************************************************************************
*/

void gertboardAnalogWrite (int chan, int value)
{
uint8_t spiData [2] ;
uint8_t chanBits, dataBits ;

if (chan == 0)
chanBits = 0x30 ;
else
chanBits = 0xB0 ;

chanBits |= ((value >> 4) & 0x0F) ;
dataBits = ((value << 4) & 0xF0) ;

spiData [0] = chanBits ;
spiData [1] = dataBits ;

wiringPiSPIDataRW (SPI_D2A, spiData, 2) ;
}


/*
* gertboardAnalogRead:
* Return the analog value of the given channel (0/1).
* The A/D is a 10-bit device
*********************************************************************************
*/

int gertboardAnalogRead (int chan)
{
uint8_t spiData [2] ;

uint8_t chanBits ;

if (chan == 0)
chanBits = 0b11010000 ;
else
chanBits = 0b11110000 ;

spiData [0] = chanBits ;
spiData [1] = 0 ;

wiringPiSPIDataRW (SPI_A2D, spiData, 2) ;

return ((spiData [0] << 7) | (spiData [1] >> 1)) & 0x3FF ;
}


/*
* gertboardSPISetup:
* Initialise the SPI bus, etc.
*********************************************************************************
*/

int gertboardSPISetup (void)
{
if (wiringPiSPISetup (SPI_A2D, SPI_ADC_SPEED) < 0)
return -1 ;

if (wiringPiSPISetup (SPI_D2A, SPI_DAC_SPEED) < 0)
return -1 ;

return 0 ;
}

+ 39
- 0
wiringPi/gertboard.h View File

@@ -0,0 +1,39 @@
/*
* gertboard.h:
* Access routines for the SPI devices on the Gertboard
* Copyright (c) 2012 Gordon Henderson
*
* The Gertboard has an MCP4802 dual-channel D to A convertor
* connected to the SPI bus, selected via chip-select B.
*
***********************************************************************
* 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

extern void gertboardAnalogWrite (int chan, int value) ;
extern int gertboardAnalogRead (int chan) ;
extern int gertboardSPISetup (void) ;

#ifdef __cplusplus
}
#endif

+ 8
- 0
wiringPi/lcd.h View File

@@ -33,5 +33,13 @@ extern void lcdPutchar (int fd, uint8_t data) ;
extern void lcdPuts (int fd, char *string) ; extern void lcdPuts (int fd, char *string) ;
extern void lcdPrintf (int fd, char *message, ...) ; extern void lcdPrintf (int fd, char *message, ...) ;


#ifdef __cplusplus
extern "C" {
#endif

extern int lcdInit (int rows, int cols, int bits, int rs, int strb, extern int lcdInit (int rows, int cols, int bits, int rs, int strb,
int d0, int d1, int d2, int d3, int d4, int d5, int d6, int d7) ; int d0, int d1, int d2, int d3, int d4, int d5, int d6, int d7) ;

#ifdef __cplusplus
}
#endif

+ 113
- 0
wiringPi/piNes.c View File

@@ -0,0 +1,113 @@
/*
* piNes.c:
* Driver for the NES Joystick controller on the Raspberry Pi
* 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 <wiringPi.h>

#include "piNes.h"

#define MAX_NES_JOYSTICKS 8

#define NES_RIGHT 0x01
#define NES_LEFT 0x02
#define NES_DOWN 0x04
#define NES_UP 0x08
#define NES_START 0x10
#define NES_SELECT 0x20
#define NES_B 0x40
#define NES_A 0x80


#define PULSE_TIME 25

// Data to store the pins for each controller

struct nesPinsStruct
{
unsigned int cPin, dPin, lPin ;
} ;

static struct nesPinsStruct nesPins [MAX_NES_JOYSTICKS] ;

static int joysticks = 0 ;


/*
* setupNesJoystick:
* Create a new NES joystick interface, program the pins, etc.
*********************************************************************************
*/

int setupNesJoystick (int dPin, int cPin, int lPin)
{
if (joysticks == MAX_NES_JOYSTICKS)
return -1 ;

nesPins [joysticks].dPin = dPin ;
nesPins [joysticks].cPin = cPin ;
nesPins [joysticks].lPin = lPin ;

digitalWrite (lPin, LOW) ;
digitalWrite (cPin, LOW) ;

pinMode (lPin, OUTPUT) ;
pinMode (cPin, OUTPUT) ;
pinMode (dPin, INPUT) ;

return joysticks++ ;
}


/*
* readNesJoystick:
* Do a single scan of the NES Joystick.
*********************************************************************************
*/

unsigned int readNesJoystick (int joystick)
{
unsigned int value = 0 ;
int i ;

struct nesPinsStruct *pins = &nesPins [joystick] ;
// Toggle Latch - which presents the first bit

digitalWrite (pins->lPin, HIGH) ; delayMicroseconds (PULSE_TIME) ;
digitalWrite (pins->lPin, LOW) ; delayMicroseconds (PULSE_TIME) ;

// Read first bit

value = digitalRead (pins->dPin) ;

// Now get the next 7 bits with the clock

for (i = 0 ; i < 7 ; ++i)
{
digitalWrite (pins->cPin, HIGH) ; delayMicroseconds (PULSE_TIME) ;
digitalWrite (pins->cPin, LOW) ; delayMicroseconds (PULSE_TIME) ;
value = (value << 1) | digitalRead (pins->dPin) ;
}

return value ^ 0xFF ;
}

+ 45
- 0
wiringPi/piNes.h View File

@@ -0,0 +1,45 @@
/*
* piNes.h:
* Driver for the NES Joystick controller on the Raspberry Pi
* 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/>.
***********************************************************************
*/

#define MAX_NES_JOYSTICKS 8

#define NES_RIGHT 0x01
#define NES_LEFT 0x02
#define NES_DOWN 0x04
#define NES_UP 0x08
#define NES_START 0x10
#define NES_SELECT 0x20
#define NES_B 0x40
#define NES_A 0x80

#ifdef __cplusplus
extern "C" {
#endif

extern int setupNesJoystick (int dPin, int cPin, int lPin) ;
extern unsigned int readNesJoystick (int joystick) ;

#ifdef __cplusplus
}
#endif

+ 130
- 0
wiringPi/softPwm.c View File

@@ -0,0 +1,130 @@
/*
* softPwm.c:
* Provide 2 channels of software driven PWM.
* 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 <stdio.h>
#include <pthread.h>

#include "wiringPi.h"
#include "softPwm.h"

#define MAX_PINS 64

// The PWM Frequency is derived from the "pulse time" below. Essentially,
// the frequency is a function of the range and this pulse time.
// The total period will be range * pulse time in uS, so a pulse time
// of 100 and a range of 100 gives a period of 100 * 100 = 10,000 uS
// which is a frequency of 100Hz.
//
// It's possible to get a higher frequency by lowering the pulse time,
// however CPU uage will skyrocket as wiringPi uses a hard-loop to time
// periods under 100uS - this is because the Linux timer calls are just
// accurate at all, and have an overhead.
//
// Another way to increase the frequency is to reduce the range - however
// that reduces the overall output accuracy...

#define PULSE_TIME 100

static int marks [MAX_PINS] ;
static int range [MAX_PINS] ;

int newPin = -1 ;


/*
* softPwmThread:
* Thread to do the actual PWM output
*********************************************************************************
*/

static PI_THREAD (softPwmThread)
{
int pin, mark, space ;

pin = newPin ;
newPin = -1 ;

piHiPri (50) ;

for (;;)
{
mark = marks [pin] ;
space = range [pin] - mark ;

if (mark != 0)
digitalWrite (pin, HIGH) ;
delayMicroseconds (mark * 100) ;

if (space != 0)
digitalWrite (pin, LOW) ;
delayMicroseconds (space * 100) ;
}

return NULL ;
}


/*
* softPwmWrite:
* Write a PWM value to the given pin
*********************************************************************************
*/

void softPwmWrite (int pin, int value)
{
pin &= 63 ;

/**/ if (value < 0)
value = 0 ;
else if (value > range [pin])
value = range [pin] ;

marks [pin] = value ;
}


/*
* softPwmCreate:
* Create a new PWM thread.
*********************************************************************************
*/

int softPwmCreate (int pin, int initialValue, int pwmRange)
{
int res ;

pinMode (pin, OUTPUT) ;
digitalWrite (pin, LOW) ;

marks [pin] = initialValue ;
range [pin] = pwmRange ;

newPin = pin ;
res = piThreadCreate (softPwmThread) ;

while (newPin != -1)
delay (1) ;

return res ;
}

+ 34
- 0
wiringPi/softPwm.h View File

@@ -0,0 +1,34 @@
/*
* softPwm.h:
* Provide 2 channels of software driven PWM.
* 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

extern int softPwmCreate (int pin, int value, int range) ;
extern void softPwmWrite (int pin, int value) ;

#ifdef __cplusplus
}
#endif

+ 296
- 135
wiringPi/wiringPi.c View File

@@ -71,12 +71,16 @@


// Function stubs // Function stubs


void (*pinMode) (int pin, int mode) ;
void (*pullUpDnControl) (int pin, int pud) ;
void (*digitalWrite) (int pin, int value) ;
void (*pwmWrite) (int pin, int value) ;
int (*digitalRead) (int pin) ;
int (*waitForInterrupt) (int pin, int mS) ;
void (*pinMode) (int pin, int mode) ;
void (*pullUpDnControl) (int pin, int pud) ;
void (*digitalWrite) (int pin, int value) ;
void (*pwmWrite) (int pin, int value) ;
void (*setPadDrive) (int group, int value) ;
int (*digitalRead) (int pin) ;
int (*waitForInterrupt) (int pin, int mS) ;
void (*delayMicroseconds) (unsigned int howLong) ;
void (*pwmSetMode) (int mode) ;
void (*pwmSetRange) (unsigned int range) ;




#ifndef TRUE #ifndef TRUE
@@ -84,6 +88,11 @@ int (*waitForInterrupt) (int pin, int mS) ;
#define FALSE (1==2) #define FALSE (1==2)
#endif #endif


// BCM Magic

#define BCM_PASSWORD 0x5A000000


// Port function select bits // Port function select bits


#define FSEL_INPT 0b000 #define FSEL_INPT 0b000
@@ -100,10 +109,11 @@ int (*waitForInterrupt) (int pin, int mS) ;
// Take from Gert/Doms code. Some of this is not in the manual // Take from Gert/Doms code. Some of this is not in the manual
// that I can find )-: // that I can find )-:


#define BCM2708_PERI_BASE 0x20000000
#define BCM2708_PERI_BASE 0x20000000
#define GPIO_PADS (BCM2708_PERI_BASE + 0x100000) #define GPIO_PADS (BCM2708_PERI_BASE + 0x100000)
#define CLOCK_BASE (BCM2708_PERI_BASE + 0x101000) #define CLOCK_BASE (BCM2708_PERI_BASE + 0x101000)
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000)
#define GPIO_TIMER (BCM2708_PERI_BASE + 0x00B000)
#define GPIO_PWM (BCM2708_PERI_BASE + 0x20C000) #define GPIO_PWM (BCM2708_PERI_BASE + 0x20C000)


#define PAGE_SIZE (4*1024) #define PAGE_SIZE (4*1024)
@@ -137,12 +147,27 @@ int (*waitForInterrupt) (int pin, int mS) ;
#define PWM0_SERIAL 0x0002 // Run in serial mode #define PWM0_SERIAL 0x0002 // Run in serial mode
#define PWM0_ENABLE 0x0001 // Channel Enable #define PWM0_ENABLE 0x0001 // Channel Enable


// Timer

#define TIMER_LOAD (0x400 >> 2)
#define TIMER_VALUE (0x404 >> 2)
#define TIMER_CONTROL (0x408 >> 2)
#define TIMER_IRQ_CLR (0x40C >> 2)
#define TIMER_IRQ_RAW (0x410 >> 2)
#define TIMER_IRQ_MASK (0x414 >> 2)
#define TIMER_RELOAD (0x418 >> 2)
#define TIMER_PRE_DIV (0x41C >> 2)
#define TIMER_COUNTER (0x420 >> 2)


// Locals to hold pointers to the hardware // Locals to hold pointers to the hardware


static volatile uint32_t *gpio ; static volatile uint32_t *gpio ;
static volatile uint32_t *pwm ; static volatile uint32_t *pwm ;
static volatile uint32_t *clk ; static volatile uint32_t *clk ;
static volatile uint32_t *pads ;
static volatile uint32_t *timer ;

static volatile uint32_t *timerIrqRaw ;


// The BCM2835 has 54 GPIO pins. // The BCM2835 has 54 GPIO pins.
// BCM2835 data sheet, Page 90 onwards. // BCM2835 data sheet, Page 90 onwards.
@@ -273,6 +298,8 @@ static uint8_t gpioToFEN [] =
// gpioToPUDCLK // gpioToPUDCLK
// (Word) offset to the Pull Up Down Clock regsiter // (Word) offset to the Pull Up Down Clock regsiter


#define GPPUD 37

static uint8_t gpioToPUDCLK [] = static uint8_t gpioToPUDCLK [] =
{ {
38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38, 38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,38,
@@ -352,30 +379,42 @@ void pinModeGpio (int pin, int mode)
if (!pwmRunning) if (!pwmRunning)
{ {


// Gert/Doms Values
*(clk + PWMCLK_DIV) = 0x5A000000 | (32<<12) ; // set pwm div to 32 (19.2/3 = 600KHz)
*(clk + PWMCLK_CNTL) = 0x5A000011 ; // Source=osc and enable
digitalWrite (pin, LOW) ;
*(pwm + PWM_CONTROL) = 0 ; // Disable PWM
*(pwm + PWM_CONTROL) = 0 ; // Stop PWM
delayMicroseconds (10) ; delayMicroseconds (10) ;
*(pwm + PWM0_RANGE) = 0x400 ;
delayMicroseconds (10) ;
*(pwm + PWM1_RANGE) = 0x400 ;
// Gert/Doms Values
*(clk + PWMCLK_DIV) = BCM_PASSWORD | (32<<12) ; // set pwm div to 32 (19.2/32 = 600KHz)
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Source=osc and enable

delayMicroseconds (10) ; delayMicroseconds (10) ;


*(pwm + PWM0_RANGE) = 0x400 ; delayMicroseconds (10) ;
*(pwm + PWM1_RANGE) = 0x400 ; delayMicroseconds (10) ;

// Enable PWMs // Enable PWMs


*(pwm + PWM0_DATA) = 512 ; *(pwm + PWM0_DATA) = 512 ;
*(pwm + PWM1_DATA) = 512 ; *(pwm + PWM1_DATA) = 512 ;


// Balanced mode (default)

*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ; *(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ;

pwmRunning = TRUE ;
} }


} }


// When we change mode of any pin, we remove the pull up/downs // When we change mode of any pin, we remove the pull up/downs
// Or we used to... Hm. Commented out now because for some wieird reason,
// it seems to block subsequent attempts to set the pull up/downs and I've
// not quite gotten to the bottom of why this happens
// The down-side is that the pull up/downs are rememberd in the SoC between
// power cycles, so it's going to be a good idea to explicitly set them in
// any new code.
//
// pullUpDnControl (pin, PUD_OFF) ;


pullUpDnControl (pin, PUD_OFF) ;
} }


void pinModeWPi (int pin, int mode) void pinModeWPi (int pin, int mode)
@@ -389,6 +428,38 @@ void pinModeSys (int pin, int mode)
} }




/*
* pwmControl:
* Allow the user to control some of the PWM functions
*********************************************************************************
*/

void pwmSetModeWPi (int mode)
{
if (mode == PWM_MODE_MS)
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE | PWM0_MS_MODE | PWM1_MS_MODE ;
else
*(pwm + PWM_CONTROL) = PWM0_ENABLE | PWM1_ENABLE ;
}

void pwmSetModeSys (int mode)
{
return ;
}


void pwmSetRangeWPi (unsigned int range)
{
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ;
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ;
}

void pwmSetRangeSys (unsigned int range)
{
return ;
}


#ifdef notYetReady #ifdef notYetReady
/* /*
* pinED01: * pinED01:
@@ -414,12 +485,12 @@ void pinEnableED01Pi (int pin)


void digitalWriteWPi (int pin, int value) void digitalWriteWPi (int pin, int value)
{ {
int gpioPin = pinToGpio [pin & 63] ;
pin = pinToGpio [pin & 63] ;


if (value == LOW) if (value == LOW)
*(gpio + gpioToGPCLR [gpioPin]) = 1 << gpioPin ;
*(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ;
else else
*(gpio + gpioToGPSET [gpioPin]) = 1 << gpioPin ;
*(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ;
} }


void digitalWriteGpio (int pin, int value) void digitalWriteGpio (int pin, int value)
@@ -427,9 +498,9 @@ void digitalWriteGpio (int pin, int value)
pin &= 63 ; pin &= 63 ;


if (value == LOW) if (value == LOW)
*(gpio + gpioToGPCLR [pin]) = 1 << pin ;
*(gpio + gpioToGPCLR [pin]) = 1 << (pin & 31) ;
else else
*(gpio + gpioToGPSET [pin]) = 1 << pin ;
*(gpio + gpioToGPSET [pin]) = 1 << (pin & 31) ;
} }


void digitalWriteSys (int pin, int value) void digitalWriteSys (int pin, int value)
@@ -452,28 +523,55 @@ void digitalWriteSys (int pin, int value)
********************************************************************************* *********************************************************************************
*/ */


void pwmWriteWPi (int pin, int value)
void pwmWriteGpio (int pin, int value)
{ {
int port, gpioPin ;
int port ;


gpioPin = pinToGpio [pin & 63] ;
port = gpioToPwmPort [gpioPin] ;
pin = pin & 63 ;
port = gpioToPwmPort [pin] ;


*(pwm + port) = value & 0x3FF ;
*(pwm + port) = value ;
} }


void pwmWriteGpio (int pin, int value)
void pwmWriteWPi (int pin, int value)
{
pwmWriteGpio (pinToGpio [pin & 63], value) ;
}

void pwmWriteSys (int pin, int value)
{
return ;
}


/*
* setPadDrive:
* Set the PAD driver value
*********************************************************************************
*/

void setPadDriveWPi (int group, int value)
{ {
int port, gpioPin ;
uint32_t wrVal ;


gpioPin = pin & 63 ;
port = gpioToPwmPort [gpioPin] ;
if ((group < 0) || (group > 2))
return ;


*(pwm + port) = value & 0x3FF ;
wrVal = BCM_PASSWORD | 0x18 | (value & 7) ;
*(pads + group + 11) = wrVal ;

#ifdef DEBUG_PADS
printf ("setPadDrive: Group: %d, value: %d (%08X)\n", group, value, wrVal) ;
printf ("Read : %08X\n", *(pads + group + 11)) ;
#endif
} }


void setPadDriveGpio (int group, int value)
{
setPadDriveWPi (group, value) ;
}


void pwmWriteSys (int pin, int value)
void setPadDriveSys (int group, int value)
{ {
return ; return ;
} }
@@ -487,13 +585,9 @@ void pwmWriteSys (int pin, int value)


int digitalReadWPi (int pin) int digitalReadWPi (int pin)
{ {
int gpioPin ;

pin &= 63 ;

gpioPin = pinToGpio [pin] ;
pin = pinToGpio [pin & 63] ;


if ((*(gpio + gpioToGPLEV [gpioPin]) & (1 << gpioPin)) != 0)
if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0)
return HIGH ; return HIGH ;
else else
return LOW ; return LOW ;
@@ -503,7 +597,7 @@ int digitalReadGpio (int pin)
{ {
pin &= 63 ; pin &= 63 ;


if ((*(gpio + gpioToGPLEV [pin]) & (1 << pin)) != 0)
if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0)
return HIGH ; return HIGH ;
else else
return LOW ; return LOW ;
@@ -533,30 +627,21 @@ int digitalReadSys (int pin)
********************************************************************************* *********************************************************************************
*/ */


void pullUpDnControlWPi (int pin, int pud)
void pullUpDnControlGpio (int pin, int pud)
{ {
pin = pinToGpio [pin & 63] ;
pin &= 63 ;
pud &= 3 ;


*(gpio + 37) = pud ;
delayMicroseconds (10) ;
*(gpio + gpioToPUDCLK [pin]) = 1 << pin ;
delayMicroseconds (10) ;
*(gpio + GPPUD) = pud ; delayMicroseconds (5) ;
*(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ;
*(gpio + 37) = 0 ;
*(gpio + gpioToPUDCLK [pin]) = 0 ;
*(gpio + GPPUD) = 0 ; delayMicroseconds (5) ;
*(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ;
} }


void pullUpDnControlGpio (int pin, int pud)
void pullUpDnControlWPi (int pin, int pud)
{ {
pin &= 63 ;

*(gpio + 37) = pud ;
delayMicroseconds (10) ;
*(gpio + gpioToPUDCLK [pin]) = 1 << pin ;
delayMicroseconds (10) ;
*(gpio + 37) = 0 ;
*(gpio + gpioToPUDCLK [pin]) = 0 ;
pullUpDnControlGpio (pinToGpio [pin & 63], pud) ;
} }


void pullUpDnControlSys (int pin, int pud) void pullUpDnControlSys (int pin, int pud)
@@ -615,6 +700,94 @@ int waitForInterruptGpio (int pin, int mS)







/*
* delay:
* Wait for some number of milli seconds
*********************************************************************************
*/

void delay (unsigned int howLong)
{
struct timespec sleeper, dummy ;

sleeper.tv_sec = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;

nanosleep (&sleeper, &dummy) ;
}


/*
* delayMicroseconds:
* This is somewhat intersting. It seems that on the Pi, a single call
* to nanosleep takes some 80 to 130 microseconds anyway, so while
* obeying the standards (may take longer), it's not always what we
* want!
*
* So what I'll do now is if the delay is less than 100uS we'll do it
* in a hard loop, watching a built-in counter on the ARM chip. This is
* somewhat sub-optimal in that it uses 100% CPU, something not an issue
* in a microcontroller, but under a multi-tasking, multi-user OS, it's
* wastefull, however we've no real choice )-:
*********************************************************************************
*/

void delayMicrosecondsSys (unsigned int howLong)
{
struct timespec sleeper, dummy ;

sleeper.tv_sec = 0 ;
sleeper.tv_nsec = (long)(howLong * 1000) ;

nanosleep (&sleeper, &dummy) ;
}

void delayMicrosecondsHard (unsigned int howLong)
{
*(timer + TIMER_LOAD) = howLong ;
*(timer + TIMER_IRQ_CLR) = 0 ;

while (*timerIrqRaw == 0)
;
}

void delayMicrosecondsWPi (unsigned int howLong)
{
struct timespec sleeper, dummy ;

/**/ if (howLong == 0)
return ;
else if (howLong < 100)
delayMicrosecondsHard (howLong) ;
else
{
sleeper.tv_sec = 0 ;
sleeper.tv_nsec = (long)(howLong * 1000) ;
nanosleep (&sleeper, &dummy) ;
}
}


/*
* millis:
* Return a number of milliseconds as an unsigned int.
*********************************************************************************
*/

unsigned int millis (void)
{
struct timeval tv ;
unsigned long long t1 ;

gettimeofday (&tv, NULL) ;

t1 = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;

return (uint32_t)(t1 - epoch) ;
}


/* /*
* wiringPiSetup: * wiringPiSetup:
* Must be called once at the start of your program execution. * Must be called once at the start of your program execution.
@@ -627,20 +800,19 @@ int waitForInterruptGpio (int pin, int mS)
int wiringPiSetup (void) int wiringPiSetup (void)
{ {
int fd ; int fd ;
uint8_t *gpioMem, *pwmMem, *clkMem ;
uint8_t *gpioMem, *pwmMem, *clkMem, *padsMem, *timerMem ;
struct timeval tv ; struct timeval tv ;


#ifdef DEBUG_PADS
uint8_t *gpioMem, *padsMem, *pwmMem, *clkMem ;
uint32_t *pads ;
#endif

pinMode = pinModeWPi ;
pullUpDnControl = pullUpDnControlWPi ;
digitalWrite = digitalWriteWPi ;
pwmWrite = pwmWriteWPi ;
digitalRead = digitalReadWPi ;
waitForInterrupt = waitForInterruptWPi ;
pinMode = pinModeWPi ;
pullUpDnControl = pullUpDnControlWPi ;
digitalWrite = digitalWriteWPi ;
pwmWrite = pwmWriteWPi ;
setPadDrive = setPadDriveWPi ;
digitalRead = digitalReadWPi ;
waitForInterrupt = waitForInterruptWPi ;
delayMicroseconds = delayMicrosecondsWPi ;
pwmSetMode = pwmSetModeWPi ;
pwmSetRange = pwmSetRangeWPi ;
// Open the master /dev/memory device // Open the master /dev/memory device


@@ -711,7 +883,8 @@ int wiringPiSetup (void)
return -1 ; return -1 ;
} }
#ifdef DEBUG_PADS
// The drive pads

if ((padsMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) if ((padsMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
{ {
fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ; fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ;
@@ -728,14 +901,41 @@ int wiringPiSetup (void)
fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ; fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ;
return -1 ; return -1 ;
} }
printf ("Checking pads @ 0x%08X\n", (unsigned int)pads) ;


printf ("%08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ;
// *(pads + 11) = 0x1F ;
printf ("%08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ;
#ifdef DEBUG_PADS
printf ("Checking pads @ 0x%08X\n", (unsigned int)pads) ;
printf (" -> %08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ;
#endif #endif


// The system timer

if ((timerMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
{
fprintf (stderr, "wiringPiSetup: timerMem malloc failed: %s\n", strerror (errno)) ;
return -1 ;
}

if (((uint32_t)timerMem % PAGE_SIZE) != 0)
timerMem += PAGE_SIZE - ((uint32_t)timerMem % PAGE_SIZE) ;

timer = (uint32_t *)mmap(timerMem, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, GPIO_TIMER) ;

if ((int32_t)timer < 0)
{
fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ;
return -1 ;
}

// Set the timer to free-running, 1MHz.
// 0xF9 is 249, the timer divide is base clock / (divide+1)
// so base clock is 250MHz / 250 = 1MHz.

*(timer + TIMER_CONTROL) = 0x0000280 ;
*(timer + TIMER_PRE_DIV) = 0x00000F9 ;
timerIrqRaw = timer + TIMER_IRQ_RAW ;

// Initialise our epoch for millis()

gettimeofday (&tv, NULL) ; gettimeofday (&tv, NULL) ;
epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ; epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;


@@ -759,12 +959,16 @@ int wiringPiSetupGpio (void)
if (x != 0) if (x != 0)
return x ; return x ;


pinMode = pinModeGpio ;
pullUpDnControl = pullUpDnControlGpio ;
digitalWrite = digitalWriteGpio ;
pwmWrite = pwmWriteGpio ;
digitalRead = digitalReadGpio ;
waitForInterrupt = waitForInterruptGpio ;
pinMode = pinModeGpio ;
pullUpDnControl = pullUpDnControlGpio ;
digitalWrite = digitalWriteGpio ;
pwmWrite = pwmWriteGpio ;
setPadDrive = setPadDriveGpio ;
digitalRead = digitalReadGpio ;
waitForInterrupt = waitForInterruptGpio ;
delayMicroseconds = delayMicrosecondsWPi ; // Same
pwmSetMode = pwmSetModeWPi ;
pwmSetRange = pwmSetRangeWPi ;


return 0 ; return 0 ;
} }
@@ -785,12 +989,17 @@ int wiringPiSetupSys (void)
struct timeval tv ; struct timeval tv ;
char fName [128] ; char fName [128] ;


pinMode = pinModeSys ;
pullUpDnControl = pullUpDnControlSys ;
digitalWrite = digitalWriteSys ;
pwmWrite = pwmWriteSys ;
digitalRead = digitalReadSys ;
waitForInterrupt = waitForInterruptSys ;
pinMode = pinModeSys ;
pullUpDnControl = pullUpDnControlSys ;
digitalWrite = digitalWriteSys ;
pwmWrite = pwmWriteSys ;
setPadDrive = setPadDriveSys ;
digitalRead = digitalReadSys ;
waitForInterrupt = waitForInterruptSys ;
delayMicroseconds = delayMicrosecondsSys ;
pwmSetMode = pwmSetModeSys ;
pwmSetRange = pwmSetRangeSys ;



// Open and scan the directory, looking for exported GPIOs, and pre-open // Open and scan the directory, looking for exported GPIOs, and pre-open
// the 'value' interface to speed things up for later // the 'value' interface to speed things up for later
@@ -808,51 +1017,3 @@ int wiringPiSetupSys (void)


return 0 ; return 0 ;
} }





/*
* delay: delayMicroseconds
* Wait for some number of milli/micro seconds
*********************************************************************************
*/

void delay (unsigned int howLong)
{
struct timespec sleeper, dummy ;

sleeper.tv_sec = (time_t)(howLong / 1000) ;
sleeper.tv_nsec = (long)(howLong % 1000) * 1000000 ;

nanosleep (&sleeper, &dummy) ;
}

void delayMicroseconds (unsigned int howLong)
{
struct timespec sleeper, dummy ;

sleeper.tv_sec = 0 ;
sleeper.tv_nsec = (long)(howLong * 1000) ;

nanosleep (&sleeper, &dummy) ;
}

/*
* millis:
* Return a number of milliseconds as an unsigned int.
*********************************************************************************
*/

unsigned int millis (void)
{
struct timeval tv ;
unsigned long long t1 ;

gettimeofday (&tv, NULL) ;

t1 = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;

return (uint32_t)(t1 - epoch) ;
}

+ 15
- 6
wiringPi/wiringPi.h View File

@@ -41,6 +41,12 @@
#define PUD_DOWN 1 #define PUD_DOWN 1
#define PUD_UP 2 #define PUD_UP 2


// PWM

#define PWM_MODE_MS 0
#define PWM_MODE_BAL 1


// Function prototypes // Function prototypes
// c++ wrappers thanks to a commend by Nick Lott // c++ wrappers thanks to a commend by Nick Lott
// (and others on the Raspberry Pi forums) // (and others on the Raspberry Pi forums)
@@ -58,11 +64,15 @@ extern int wiringPiSetupPiFace (void) ;


extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio program only extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio program only


extern void (*pinMode) (int pin, int mode) ;
extern void (*pullUpDnControl) (int pin, int pud) ;
extern void (*digitalWrite) (int pin, int value) ;
extern void (*pwmWrite) (int pin, int value) ;
extern int (*digitalRead) (int pin) ;
extern void (*pinMode) (int pin, int mode) ;
extern void (*pullUpDnControl) (int pin, int pud) ;
extern void (*digitalWrite) (int pin, int value) ;
extern void (*pwmWrite) (int pin, int value) ;
extern void (*setPadDrive) (int group, int value) ;
extern int (*digitalRead) (int pin) ;
extern void (*delayMicroseconds) (unsigned int howLong) ;
extern void (*pwmSetMode) (int mode) ;
extern void (*pwmSetRange) (unsigned int range) ;


// Interrupts // Interrupts


@@ -84,7 +94,6 @@ extern int piHiPri (int pri) ;
// Extras from arduino land // Extras from arduino land


extern void delay (unsigned int howLong) ; extern void delay (unsigned int howLong) ;
extern void delayMicroseconds (unsigned int howLong) ;
extern unsigned int millis (void) ; extern unsigned int millis (void) ;


#ifdef __cplusplus #ifdef __cplusplus


+ 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

+ 25
- 19
wiringPi/wiringSerial.c View File

@@ -20,8 +20,6 @@
*********************************************************************** ***********************************************************************
*/ */


#undef DEBUG

#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
@@ -49,10 +47,6 @@ int serialOpen (char *device, int baud)
speed_t myBaud ; speed_t myBaud ;
int status, fd ; int status, fd ;


#ifdef DEBUG
printf ("openSerialPort: <%s> baud: $d\n", device, baud) ;
#endif

switch (baud) switch (baud)
{ {
case 50: myBaud = B50 ; break ; case 50: myBaud = B50 ; break ;
@@ -86,22 +80,22 @@ int serialOpen (char *device, int baud)


tcgetattr (fd, &options) ; tcgetattr (fd, &options) ;


cfmakeraw (&options) ;
cfsetispeed (&options, myBaud) ;
cfsetospeed (&options, myBaud) ;
cfmakeraw (&options) ;
cfsetispeed (&options, myBaud) ;
cfsetospeed (&options, myBaud) ;


options.c_cflag |= (CLOCAL | CREAD) ;
options.c_cflag &= ~PARENB ;
options.c_cflag &= ~CSTOPB ;
options.c_cflag &= ~CSIZE ;
options.c_cflag |= CS8 ;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
options.c_oflag &= ~OPOST ;
options.c_cflag |= (CLOCAL | CREAD) ;
options.c_cflag &= ~PARENB ;
options.c_cflag &= ~CSTOPB ;
options.c_cflag &= ~CSIZE ;
options.c_cflag |= CS8 ;
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
options.c_oflag &= ~OPOST ;


options.c_cc [VMIN] = 0 ;
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds)
options.c_cc [VMIN] = 0 ;
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds)


tcsetattr (fd, TCSANOW, &options) ;
tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ;


ioctl (fd, TIOCMGET, &status); ioctl (fd, TIOCMGET, &status);


@@ -117,6 +111,18 @@ int serialOpen (char *device, int baud)




/* /*
* serialFlush:
* Flush the serial buffers (both tx & rx)
*********************************************************************************
*/

void serialFlush (int fd)
{
tcflush (fd, TCIOFLUSH) ;
}


/*
* serialClose: * serialClose:
* Release the serial port * Release the serial port
********************************************************************************* *********************************************************************************


+ 1
- 0
wiringPi/wiringSerial.h View File

@@ -26,6 +26,7 @@ extern "C" {


extern int serialOpen (char *device, int baud) ; extern int serialOpen (char *device, int baud) ;
extern void serialClose (int fd) ; extern void serialClose (int fd) ;
extern void serialFlush (int fd) ;
extern void serialPutchar (int fd, unsigned char c) ; extern void serialPutchar (int fd, unsigned char c) ;
extern void serialPuts (int fd, char *s) ; extern void serialPuts (int fd, char *s) ;
extern void serialPrintf (int fd, char *message, ...) ; extern void serialPrintf (int fd, char *message, ...) ;


Loading…
Cancel
Save