Merged from git.drogon.net, SPI driver helpers, C++ wrappers, softPwm, piNes, gertboard, SPI
This commit is contained in:
committed by
Philip Howard
parent
21f0472265
commit
ae40bdaf6a
@@ -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
examples/delayTest.c
Normal file
68
examples/delayTest.c
Normal 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
examples/gertboard.c
Normal file
77
examples/gertboard.c
Normal 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
Normal file
BIN
examples/gertboard.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
44
examples/nes.c
Normal file
44
examples/nes.c
Normal 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
examples/softPwm.c
Normal file
69
examples/softPwm.c
Normal 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 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
102
gpio/gpio.1
102
gpio/gpio.1
@@ -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 ]
|
.B \-v
|
||||||
.TP
|
.PP
|
||||||
.B gpio
|
.B gpio
|
||||||
.RB [ \-g ]
|
.B [ \-g ]
|
||||||
.RB < read/write/pwm/mode ...>
|
.B read/write/pwm/mode ...
|
||||||
.TP
|
.PP
|
||||||
.B gpio
|
.B gpio
|
||||||
.RB [ \-p ]
|
.B [ \-p ]
|
||||||
.RB < read/write/mode ...>
|
.B read/write/mode
|
||||||
.TP
|
.B ...
|
||||||
|
.PP
|
||||||
.B gpio
|
.B gpio
|
||||||
.RB < export/edge/unexport/unexportall/exports ...>
|
.B unexportall/exports
|
||||||
|
.PP
|
||||||
|
.B gpio
|
||||||
|
.B export/edge/unexport
|
||||||
|
.B ...
|
||||||
|
.PP
|
||||||
|
.B gpio
|
||||||
|
.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
|
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
|
||||||
@@ -64,6 +91,14 @@ Set a pin into \fIinput\fR, \fIoutput\fR or \fIpwm\fR mode. Can also
|
|||||||
use the literals \fIup\fR, \fIdown\fR or \fItri\fR to set the internal
|
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
|
||||||
|
.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
|
.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
|
||||||
@@ -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
|
.B drive
|
||||||
Un-Export all the GPIO pins in the /sys/class/gpio directory.
|
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
|
.B pwm-bal/pwm-ms
|
||||||
Print a list (if any) of all the exported GPIO pins and their current values.
|
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
|
||||||
|
|
||||||
|
|||||||
450
gpio/gpio.c
450
gpio/gpio.c
@@ -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>
|
||||||
|
|
||||||
#define VERSION "1.0"
|
#ifndef TRUE
|
||||||
|
# define TRUE (1==1)
|
||||||
|
# define FALSE (1==2)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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)
|
changeOwner (argv [0], fName) ;
|
||||||
{
|
|
||||||
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
|
|
||||||
|
|
||||||
sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
|
sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
|
||||||
if (chown (fName, uid, gid) != 0)
|
changeOwner (argv [0], fName) ;
|
||||||
{
|
|
||||||
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) ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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)
|
/**/ if (strcasecmp (mode, "none") == 0) fprintf (fd, "none\n") ;
|
||||||
fprintf (fd, "none\n") ;
|
else if (strcasecmp (mode, "rising") == 0) fprintf (fd, "rising\n") ;
|
||||||
else if (strcasecmp (mode, "rising") == 0)
|
else if (strcasecmp (mode, "falling") == 0) fprintf (fd, "falling\n") ;
|
||||||
fprintf (fd, "rising\n") ;
|
else if (strcasecmp (mode, "both") == 0) fprintf (fd, "both\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!
|
// Change ownership of the value and edge files, 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)
|
changeOwner (argv [0], fName) ;
|
||||||
{
|
|
||||||
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
|
|
||||||
|
|
||||||
sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
|
sprintf (fName, "/sys/class/gpio/gpio%d/edge", pin) ;
|
||||||
if (chown (fName, uid, gid) != 0)
|
changeOwner (argv [0], fName) ;
|
||||||
{
|
|
||||||
fprintf (stderr, "%s: Unable to change ownership of the value file: %s\n", argv [1], strerror (errno)) ;
|
|
||||||
exit (1) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
/**/ if (strcasecmp (mode, "in") == 0) pinMode (pin, INPUT) ;
|
||||||
pinMode (pin, INPUT) ;
|
else if (strcasecmp (mode, "out") == 0) pinMode (pin, OUTPUT) ;
|
||||||
else if (strcasecmp (mode, "out") == 0)
|
else if (strcasecmp (mode, "pwm") == 0) pinMode (pin, PWM_OUTPUT) ;
|
||||||
pinMode (pin, OUTPUT) ;
|
else if (strcasecmp (mode, "up") == 0) pullUpDnControl (pin, PUD_UP) ;
|
||||||
else if (strcasecmp (mode, "pwm") == 0)
|
else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
|
||||||
pinMode (pin, PWM_OUTPUT) ;
|
else if (strcasecmp (mode, "tri") == 0) pullUpDnControl (pin, PUD_OFF) ;
|
||||||
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 ;
|
||||||
|
|
||||||
@@ -489,6 +686,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]) ;
|
printf ("%s: %s\n", argv [0], usage) ;
|
||||||
return 1 ;
|
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)
|
/**/ if (strcasecmp (argv [1], "exports" ) == 0) { doExports (argc, argv) ; return 0 ; }
|
||||||
{ doExports () ; return 0 ; }
|
else if (strcasecmp (argv [1], "export" ) == 0) { doExport (argc, argv) ; return 0 ; }
|
||||||
else if (strcasecmp (argv [1], "export" ) == 0)
|
else if (strcasecmp (argv [1], "edge" ) == 0) { doEdge (argc, argv) ; return 0 ; }
|
||||||
{ doExport (argc, argv) ; return 0 ; }
|
else if (strcasecmp (argv [1], "unexportall") == 0) { doUnexportall (argc, argv) ; return 0 ; }
|
||||||
else if (strcasecmp (argv [1], "edge" ) == 0)
|
else if (strcasecmp (argv [1], "unexport" ) == 0) { doUnexport (argc, argv) ; return 0 ; }
|
||||||
{ doEdge (argc, argv) ; return 0 ; }
|
|
||||||
else if (strcasecmp (argv [1], "unexportall") == 0)
|
// Check for drive or load commands:
|
||||||
{ doUnexportall (argc, argv) ; return 0 ; }
|
|
||||||
else if (strcasecmp (argv [1], "unexport") == 0)
|
if (strcasecmp (argv [1], "drive") == 0) { doPadDrive (argc, argv) ; return 0 ; }
|
||||||
{ doUnexport (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)
|
// Check for PWM operations
|
||||||
doWrite (argc, argv) ;
|
|
||||||
else if (strcasecmp (argv [1], "read" ) == 0)
|
if (wpMode != WPI_MODE_PIFACE)
|
||||||
doRead (argc, argv) ;
|
{
|
||||||
else if (strcasecmp (argv [1], "mode" ) == 0)
|
if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode (PWM_MODE_BAL) ; return 0 ; }
|
||||||
doMode (argc, argv) ;
|
if (strcasecmp (argv [1], "pwm-ms") == 0) { doPwmMode (PWM_MODE_MS) ; return 0 ; }
|
||||||
else if (strcasecmp (argv [1], "pwm" ) == 0)
|
if (strcasecmp (argv [1], "pwmr") == 0) { doPwmRange (argc, argv) ; return 0 ; }
|
||||||
doPwm (argc, argv) ;
|
}
|
||||||
|
|
||||||
|
// 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
wiringPi/gertboard.c
Normal file
122
wiringPi/gertboard.c
Normal 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
wiringPi/gertboard.h
Normal file
39
wiringPi/gertboard.h
Normal 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
|
||||||
@@ -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
wiringPi/piNes.c
Normal file
113
wiringPi/piNes.c
Normal 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
wiringPi/piNes.h
Normal file
45
wiringPi/piNes.h
Normal 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
wiringPi/softPwm.c
Normal file
130
wiringPi/softPwm.c
Normal 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
wiringPi/softPwm.h
Normal file
34
wiringPi/softPwm.h
Normal 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
|
||||||
@@ -71,12 +71,16 @@
|
|||||||
|
|
||||||
// Function stubs
|
// Function stubs
|
||||||
|
|
||||||
void (*pinMode) (int pin, int mode) ;
|
void (*pinMode) (int pin, int mode) ;
|
||||||
void (*pullUpDnControl) (int pin, int pud) ;
|
void (*pullUpDnControl) (int pin, int pud) ;
|
||||||
void (*digitalWrite) (int pin, int value) ;
|
void (*digitalWrite) (int pin, int value) ;
|
||||||
void (*pwmWrite) (int pin, int value) ;
|
void (*pwmWrite) (int pin, int value) ;
|
||||||
int (*digitalRead) (int pin) ;
|
void (*setPadDrive) (int group, int value) ;
|
||||||
int (*waitForInterrupt) (int pin, int mS) ;
|
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)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
*(pwm + PWM_CONTROL) = 0 ; // Stop PWM
|
||||||
|
delayMicroseconds (10) ;
|
||||||
|
|
||||||
// Gert/Doms Values
|
// Gert/Doms Values
|
||||||
*(clk + PWMCLK_DIV) = 0x5A000000 | (32<<12) ; // set pwm div to 32 (19.2/3 = 600KHz)
|
*(clk + PWMCLK_DIV) = BCM_PASSWORD | (32<<12) ; // set pwm div to 32 (19.2/32 = 600KHz)
|
||||||
*(clk + PWMCLK_CNTL) = 0x5A000011 ; // Source=osc and enable
|
*(clk + PWMCLK_CNTL) = BCM_PASSWORD | 0x11 ; // Source=osc and enable
|
||||||
digitalWrite (pin, LOW) ;
|
|
||||||
*(pwm + PWM_CONTROL) = 0 ; // Disable PWM
|
|
||||||
delayMicroseconds (10) ;
|
|
||||||
*(pwm + PWM0_RANGE) = 0x400 ;
|
|
||||||
delayMicroseconds (10) ;
|
|
||||||
*(pwm + PWM1_RANGE) = 0x400 ;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
int port, gpioPin ;
|
|
||||||
|
|
||||||
gpioPin = pinToGpio [pin & 63] ;
|
|
||||||
port = gpioToPwmPort [gpioPin] ;
|
|
||||||
|
|
||||||
*(pwm + port) = value & 0x3FF ;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pwmWriteGpio (int pin, int value)
|
void pwmWriteGpio (int pin, int value)
|
||||||
{
|
{
|
||||||
int port, gpioPin ;
|
int port ;
|
||||||
|
|
||||||
gpioPin = pin & 63 ;
|
pin = pin & 63 ;
|
||||||
port = gpioToPwmPort [gpioPin] ;
|
port = gpioToPwmPort [pin] ;
|
||||||
|
|
||||||
*(pwm + port) = value & 0x3FF ;
|
*(pwm + port) = value ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmWriteWPi (int pin, int value)
|
||||||
|
{
|
||||||
|
pwmWriteGpio (pinToGpio [pin & 63], value) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmWriteSys (int pin, int value)
|
||||||
|
{
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pwmWriteSys (int pin, int value)
|
/*
|
||||||
|
* setPadDrive:
|
||||||
|
* Set the PAD driver value
|
||||||
|
*********************************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
void setPadDriveWPi (int group, int value)
|
||||||
|
{
|
||||||
|
uint32_t wrVal ;
|
||||||
|
|
||||||
|
if ((group < 0) || (group > 2))
|
||||||
|
return ;
|
||||||
|
|
||||||
|
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 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 = pinToGpio [pin & 63] ;
|
||||||
|
|
||||||
pin &= 63 ;
|
if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0)
|
||||||
|
|
||||||
gpioPin = pinToGpio [pin] ;
|
|
||||||
|
|
||||||
if ((*(gpio + gpioToGPLEV [gpioPin]) & (1 << gpioPin)) != 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)
|
|
||||||
{
|
|
||||||
pin = pinToGpio [pin & 63] ;
|
|
||||||
|
|
||||||
*(gpio + 37) = pud ;
|
|
||||||
delayMicroseconds (10) ;
|
|
||||||
*(gpio + gpioToPUDCLK [pin]) = 1 << pin ;
|
|
||||||
delayMicroseconds (10) ;
|
|
||||||
|
|
||||||
*(gpio + 37) = 0 ;
|
|
||||||
*(gpio + gpioToPUDCLK [pin]) = 0 ;
|
|
||||||
}
|
|
||||||
|
|
||||||
void pullUpDnControlGpio (int pin, int pud)
|
void pullUpDnControlGpio (int pin, int pud)
|
||||||
{
|
{
|
||||||
pin &= 63 ;
|
pin &= 63 ;
|
||||||
|
pud &= 3 ;
|
||||||
|
|
||||||
*(gpio + 37) = pud ;
|
*(gpio + GPPUD) = pud ; delayMicroseconds (5) ;
|
||||||
delayMicroseconds (10) ;
|
*(gpio + gpioToPUDCLK [pin]) = 1 << (pin & 31) ; delayMicroseconds (5) ;
|
||||||
*(gpio + gpioToPUDCLK [pin]) = 1 << pin ;
|
|
||||||
delayMicroseconds (10) ;
|
|
||||||
|
|
||||||
*(gpio + 37) = 0 ;
|
*(gpio + GPPUD) = 0 ; delayMicroseconds (5) ;
|
||||||
*(gpio + gpioToPUDCLK [pin]) = 0 ;
|
*(gpio + gpioToPUDCLK [pin]) = 0 ; delayMicroseconds (5) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pullUpDnControlWPi (int pin, int pud)
|
||||||
|
{
|
||||||
|
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
|
pinMode = pinModeWPi ;
|
||||||
uint8_t *gpioMem, *padsMem, *pwmMem, *clkMem ;
|
pullUpDnControl = pullUpDnControlWPi ;
|
||||||
uint32_t *pads ;
|
digitalWrite = digitalWriteWPi ;
|
||||||
#endif
|
pwmWrite = pwmWriteWPi ;
|
||||||
|
setPadDrive = setPadDriveWPi ;
|
||||||
pinMode = pinModeWPi ;
|
digitalRead = digitalReadWPi ;
|
||||||
pullUpDnControl = pullUpDnControlWPi ;
|
waitForInterrupt = waitForInterruptWPi ;
|
||||||
digitalWrite = digitalWriteWPi ;
|
delayMicroseconds = delayMicrosecondsWPi ;
|
||||||
pwmWrite = pwmWriteWPi ;
|
pwmSetMode = pwmSetModeWPi ;
|
||||||
digitalRead = digitalReadWPi ;
|
pwmSetRange = pwmSetRangeWPi ;
|
||||||
waitForInterrupt = waitForInterruptWPi ;
|
|
||||||
|
|
||||||
// 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)) ;
|
#ifdef DEBUG_PADS
|
||||||
// *(pads + 11) = 0x1F ;
|
printf ("Checking pads @ 0x%08X\n", (unsigned int)pads) ;
|
||||||
printf ("%08X %08X %08X\n", *(pads + 11), *(pads + 12), *(pads + 13)) ;
|
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 ;
|
pinMode = pinModeGpio ;
|
||||||
pullUpDnControl = pullUpDnControlGpio ;
|
pullUpDnControl = pullUpDnControlGpio ;
|
||||||
digitalWrite = digitalWriteGpio ;
|
digitalWrite = digitalWriteGpio ;
|
||||||
pwmWrite = pwmWriteGpio ;
|
pwmWrite = pwmWriteGpio ;
|
||||||
digitalRead = digitalReadGpio ;
|
setPadDrive = setPadDriveGpio ;
|
||||||
waitForInterrupt = waitForInterruptGpio ;
|
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 ;
|
pinMode = pinModeSys ;
|
||||||
pullUpDnControl = pullUpDnControlSys ;
|
pullUpDnControl = pullUpDnControlSys ;
|
||||||
digitalWrite = digitalWriteSys ;
|
digitalWrite = digitalWriteSys ;
|
||||||
pwmWrite = pwmWriteSys ;
|
pwmWrite = pwmWriteSys ;
|
||||||
digitalRead = digitalReadSys ;
|
setPadDrive = setPadDriveSys ;
|
||||||
waitForInterrupt = waitForInterruptSys ;
|
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) ;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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 (*pinMode) (int pin, int mode) ;
|
||||||
extern void (*pullUpDnControl) (int pin, int pud) ;
|
extern void (*pullUpDnControl) (int pin, int pud) ;
|
||||||
extern void (*digitalWrite) (int pin, int value) ;
|
extern void (*digitalWrite) (int pin, int value) ;
|
||||||
extern void (*pwmWrite) (int pin, int value) ;
|
extern void (*pwmWrite) (int pin, int value) ;
|
||||||
extern int (*digitalRead) (int pin) ;
|
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
wiringPi/wiringPiSPI.c
Normal file
117
wiringPi/wiringPiSPI.c
Normal 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
wiringPi/wiringPiSPI.h
Normal file
35
wiringPi/wiringPiSPI.h
Normal 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
|
||||||
@@ -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) ;
|
cfmakeraw (&options) ;
|
||||||
cfsetispeed (&options, myBaud) ;
|
cfsetispeed (&options, myBaud) ;
|
||||||
cfsetospeed (&options, myBaud) ;
|
cfsetospeed (&options, myBaud) ;
|
||||||
|
|
||||||
options.c_cflag |= (CLOCAL | CREAD) ;
|
options.c_cflag |= (CLOCAL | CREAD) ;
|
||||||
options.c_cflag &= ~PARENB ;
|
options.c_cflag &= ~PARENB ;
|
||||||
options.c_cflag &= ~CSTOPB ;
|
options.c_cflag &= ~CSTOPB ;
|
||||||
options.c_cflag &= ~CSIZE ;
|
options.c_cflag &= ~CSIZE ;
|
||||||
options.c_cflag |= CS8 ;
|
options.c_cflag |= CS8 ;
|
||||||
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
|
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG) ;
|
||||||
options.c_oflag &= ~OPOST ;
|
options.c_oflag &= ~OPOST ;
|
||||||
|
|
||||||
options.c_cc [VMIN] = 0 ;
|
options.c_cc [VMIN] = 0 ;
|
||||||
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds)
|
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);
|
||||||
|
|
||||||
@@ -116,6 +110,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
|
||||||
|
|||||||
@@ -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, ...) ;
|
||||||
|
|||||||
Reference in New Issue
Block a user