raspi_lcd 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,715 @@
1
+ // bcm2835.c
2
+ // C and C++ support for Broadcom BCM 2835 as used in Raspberry Pi
3
+ // http://elinux.org/RPi_Low-level_peripherals
4
+ // http://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
5
+ //
6
+ // Author: Mike McCauley (mikem@open.com.au)
7
+ // Copyright (C) 2011 Mike McCauley
8
+ // $Id: bcm2835.c,v 1.4 2012/07/16 23:57:59 mikem Exp mikem $
9
+
10
+ #include <stdlib.h>
11
+ #include <stdio.h>
12
+ #include <errno.h>
13
+ #include <fcntl.h>
14
+ #include <sys/mman.h>
15
+ #include <string.h>
16
+ #include <time.h>
17
+ #include <unistd.h>
18
+
19
+ #include "bcm2835.h"
20
+
21
+ // This define enables a little test program (by default a blinking output on pin RPI_GPIO_PIN_11)
22
+ // You can do some safe, non-destructive testing on any platform with:
23
+ // gcc bcm2835.c -D BCM2835_TEST
24
+ // ./a.out
25
+ //#define BCM2835_TEST
26
+
27
+ // Locals to hold pointers to the hardware
28
+ static volatile uint32_t *gpio = MAP_FAILED;
29
+ static volatile uint32_t *pwm = MAP_FAILED;
30
+ static volatile uint32_t *clk = MAP_FAILED;
31
+ static volatile uint32_t *pads = MAP_FAILED;
32
+ static volatile uint32_t *spi0 = MAP_FAILED;
33
+
34
+ static int memfd = -1;
35
+
36
+ // This define allows us to test on hardware other than RPi.
37
+ // It prevents access to the kernel memory, and does not do any peripheral access
38
+ // Instead it prints out what it _would_ do if debug were 0
39
+ static uint8_t debug = 0;
40
+
41
+
42
+ //
43
+ // Low level register access functions
44
+ //
45
+
46
+ void bcm2835_set_debug(uint8_t d)
47
+ {
48
+ debug = d;
49
+ }
50
+
51
+ // safe read from peripheral
52
+ uint32_t bcm2835_peri_read(volatile uint32_t* paddr)
53
+ {
54
+ if (debug)
55
+ {
56
+ printf("bcm2835_peri_read paddr %08X\n", (unsigned) paddr);
57
+ return 0;
58
+ }
59
+ else
60
+ {
61
+ // Make sure we dont return the _last_ read which might get lost
62
+ // if subsequent code changes to a different peripheral
63
+ uint32_t ret = *paddr;
64
+ uint32_t dummy = *paddr;
65
+ return ret;
66
+ }
67
+ }
68
+
69
+ // read from peripheral without the read barrier
70
+ uint32_t bcm2835_peri_read_nb(volatile uint32_t* paddr)
71
+ {
72
+ if (debug)
73
+ {
74
+ printf("bcm2835_peri_read_nb paddr %08X\n", (unsigned) paddr);
75
+ return 0;
76
+ }
77
+ else
78
+ {
79
+ return *paddr;
80
+ }
81
+ }
82
+
83
+ // safe write to peripheral
84
+ void bcm2835_peri_write(volatile uint32_t* paddr, uint32_t value)
85
+ {
86
+ if (debug)
87
+ {
88
+ printf("bcm2835_peri_write paddr %08X, value %08X\n", (unsigned) paddr, value);
89
+ }
90
+ else
91
+ {
92
+ // Make sure we don't rely on the first write, which may get
93
+ // lost if the previous access was to a different peripheral.
94
+ *paddr = value;
95
+ *paddr = value;
96
+ }
97
+ }
98
+
99
+ // write to peripheral without the write barrier
100
+ void bcm2835_peri_write_nb(volatile uint32_t* paddr, uint32_t value)
101
+ {
102
+ if (debug)
103
+ {
104
+ printf("bcm2835_peri_write_nb paddr %08X, value %08X\n",
105
+ (unsigned) paddr, value);
106
+ }
107
+ else
108
+ {
109
+ *paddr = value;
110
+ }
111
+ }
112
+
113
+ // Set/clear only the bits in value covered by the mask
114
+ void bcm2835_peri_set_bits(volatile uint32_t* paddr, uint32_t value, uint32_t mask)
115
+ {
116
+ uint32_t v = bcm2835_peri_read(paddr);
117
+ v = (v & ~mask) | (value & mask);
118
+ bcm2835_peri_write(paddr, v);
119
+ }
120
+
121
+ //
122
+ // Low level convenience functions
123
+ //
124
+
125
+ // Function select
126
+ // pin is a BCM2835 GPIO pin number NOT RPi pin number
127
+ // There are 6 control registers, each control the functions of a block
128
+ // of 10 pins.
129
+ // Each control register has 10 sets of 3 bits per GPIO pin:
130
+ //
131
+ // 000 = GPIO Pin X is an input
132
+ // 001 = GPIO Pin X is an output
133
+ // 100 = GPIO Pin X takes alternate function 0
134
+ // 101 = GPIO Pin X takes alternate function 1
135
+ // 110 = GPIO Pin X takes alternate function 2
136
+ // 111 = GPIO Pin X takes alternate function 3
137
+ // 011 = GPIO Pin X takes alternate function 4
138
+ // 010 = GPIO Pin X takes alternate function 5
139
+ //
140
+ // So the 3 bits for port X are:
141
+ // X / 10 + ((X % 10) * 3)
142
+ void bcm2835_gpio_fsel(uint8_t pin, uint8_t mode)
143
+ {
144
+ // Function selects are 10 pins per 32 bit word, 3 bits per pin
145
+ volatile uint32_t* paddr = gpio + BCM2835_GPFSEL0/4 + (pin/10);
146
+ uint8_t shift = (pin % 10) * 3;
147
+ uint32_t mask = BCM2835_GPIO_FSEL_MASK << shift;
148
+ uint32_t value = mode << shift;
149
+ bcm2835_peri_set_bits(paddr, value, mask);
150
+ }
151
+
152
+ // Set output pin
153
+ void bcm2835_gpio_set(uint8_t pin)
154
+ {
155
+ volatile uint32_t* paddr = gpio + BCM2835_GPSET0/4 + pin/32;
156
+ uint8_t shift = pin % 32;
157
+ bcm2835_peri_write(paddr, 1 << shift);
158
+ }
159
+
160
+ // Clear output pin
161
+ void bcm2835_gpio_clr(uint8_t pin)
162
+ {
163
+ volatile uint32_t* paddr = gpio + BCM2835_GPCLR0/4 + pin/32;
164
+ uint8_t shift = pin % 32;
165
+ bcm2835_peri_write(paddr, 1 << shift);
166
+ }
167
+
168
+ // Read input pin
169
+ uint8_t bcm2835_gpio_lev(uint8_t pin)
170
+ {
171
+ volatile uint32_t* paddr = gpio + BCM2835_GPLEV0/4 + pin/32;
172
+ uint8_t shift = pin % 32;
173
+ uint32_t value = bcm2835_peri_read(paddr);
174
+ return (value & (1 << shift)) ? HIGH : LOW;
175
+ }
176
+
177
+ // See if an event detection bit is set
178
+ // Sigh cant support interrupts yet
179
+ uint8_t bcm2835_gpio_eds(uint8_t pin)
180
+ {
181
+ volatile uint32_t* paddr = gpio + BCM2835_GPEDS0/4 + pin/32;
182
+ uint8_t shift = pin % 32;
183
+ uint32_t value = bcm2835_peri_read(paddr);
184
+ return (value & (1 << shift)) ? HIGH : LOW;
185
+ }
186
+
187
+ // Write a 1 to clear the bit in EDS
188
+ void bcm2835_gpio_set_eds(uint8_t pin)
189
+ {
190
+ volatile uint32_t* paddr = gpio + BCM2835_GPEDS0/4 + pin/32;
191
+ uint8_t shift = pin % 32;
192
+ uint32_t value = 1 << shift;
193
+ bcm2835_peri_write(paddr, value);
194
+ }
195
+
196
+ // Rising edge detect enable
197
+ void bcm2835_gpio_ren(uint8_t pin)
198
+ {
199
+ volatile uint32_t* paddr = gpio + BCM2835_GPREN0/4 + pin/32;
200
+ uint8_t shift = pin % 32;
201
+ uint32_t value = 1 << shift;
202
+ bcm2835_peri_set_bits(paddr, value, value);
203
+ }
204
+ void bcm2835_gpio_clr_ren(uint8_t pin)
205
+ {
206
+ volatile uint32_t* paddr = gpio + BCM2835_GPREN0/4 + pin/32;
207
+ uint8_t shift = pin % 32;
208
+ uint32_t value = 1 << shift;
209
+ bcm2835_peri_set_bits(paddr, 0, value);
210
+ }
211
+
212
+ // Falling edge detect enable
213
+ void bcm2835_gpio_fen(uint8_t pin)
214
+ {
215
+ volatile uint32_t* paddr = gpio + BCM2835_GPFEN0/4 + pin/32;
216
+ uint8_t shift = pin % 32;
217
+ uint32_t value = 1 << shift;
218
+ bcm2835_peri_set_bits(paddr, value, value);
219
+ }
220
+ void bcm2835_gpio_clr_fen(uint8_t pin)
221
+ {
222
+ volatile uint32_t* paddr = gpio + BCM2835_GPFEN0/4 + pin/32;
223
+ uint8_t shift = pin % 32;
224
+ uint32_t value = 1 << shift;
225
+ bcm2835_peri_set_bits(paddr, 0, value);
226
+ }
227
+
228
+ // High detect enable
229
+ void bcm2835_gpio_hen(uint8_t pin)
230
+ {
231
+ volatile uint32_t* paddr = gpio + BCM2835_GPHEN0/4 + pin/32;
232
+ uint8_t shift = pin % 32;
233
+ uint32_t value = 1 << shift;
234
+ bcm2835_peri_set_bits(paddr, value, value);
235
+ }
236
+ void bcm2835_gpio_clr_hen(uint8_t pin)
237
+ {
238
+ volatile uint32_t* paddr = gpio + BCM2835_GPHEN0/4 + pin/32;
239
+ uint8_t shift = pin % 32;
240
+ uint32_t value = 1 << shift;
241
+ bcm2835_peri_set_bits(paddr, 0, value);
242
+ }
243
+
244
+ // Low detect enable
245
+ void bcm2835_gpio_len(uint8_t pin)
246
+ {
247
+ volatile uint32_t* paddr = gpio + BCM2835_GPLEN0/4 + pin/32;
248
+ uint8_t shift = pin % 32;
249
+ uint32_t value = 1 << shift;
250
+ bcm2835_peri_set_bits(paddr, value, value);
251
+ }
252
+ void bcm2835_gpio_clr_len(uint8_t pin)
253
+ {
254
+ volatile uint32_t* paddr = gpio + BCM2835_GPLEN0/4 + pin/32;
255
+ uint8_t shift = pin % 32;
256
+ uint32_t value = 1 << shift;
257
+ bcm2835_peri_set_bits(paddr, 0, value);
258
+ }
259
+
260
+ // Async rising edge detect enable
261
+ void bcm2835_gpio_aren(uint8_t pin)
262
+ {
263
+ volatile uint32_t* paddr = gpio + BCM2835_GPAREN0/4 + pin/32;
264
+ uint8_t shift = pin % 32;
265
+ uint32_t value = 1 << shift;
266
+ bcm2835_peri_set_bits(paddr, value, value);
267
+ }
268
+ void bcm2835_gpio_clr_aren(uint8_t pin)
269
+ {
270
+ volatile uint32_t* paddr = gpio + BCM2835_GPAREN0/4 + pin/32;
271
+ uint8_t shift = pin % 32;
272
+ uint32_t value = 1 << shift;
273
+ bcm2835_peri_set_bits(paddr, 0, value);
274
+ }
275
+
276
+ // Async falling edge detect enable
277
+ void bcm2835_gpio_afen(uint8_t pin)
278
+ {
279
+ volatile uint32_t* paddr = gpio + BCM2835_GPAFEN0/4 + pin/32;
280
+ uint8_t shift = pin % 32;
281
+ uint32_t value = 1 << shift;
282
+ bcm2835_peri_set_bits(paddr, value, value);
283
+ }
284
+ void bcm2835_gpio_clr_afen(uint8_t pin)
285
+ {
286
+ volatile uint32_t* paddr = gpio + BCM2835_GPAFEN0/4 + pin/32;
287
+ uint8_t shift = pin % 32;
288
+ uint32_t value = 1 << shift;
289
+ bcm2835_peri_set_bits(paddr, 0, value);
290
+ }
291
+
292
+ // Set pullup/down
293
+ void bcm2835_gpio_pud(uint8_t pud)
294
+ {
295
+ volatile uint32_t* paddr = gpio + BCM2835_GPPUD/4;
296
+ bcm2835_peri_write(paddr, pud);
297
+ }
298
+
299
+ // Pullup/down clock
300
+ // Clocks the value of pud into the GPIO pin
301
+ void bcm2835_gpio_pudclk(uint8_t pin, uint8_t on)
302
+ {
303
+ volatile uint32_t* paddr = gpio + BCM2835_GPPUDCLK0/4 + pin/32;
304
+ uint8_t shift = pin % 32;
305
+ bcm2835_peri_write(paddr, (on ? 1 : 0) << shift);
306
+ }
307
+
308
+ // Read GPIO pad behaviour for groups of GPIOs
309
+ uint32_t bcm2835_gpio_pad(uint8_t group)
310
+ {
311
+ volatile uint32_t* paddr = pads + BCM2835_PADS_GPIO_0_27/4 + group*2;
312
+ return bcm2835_peri_read(paddr);
313
+ }
314
+
315
+ // Set GPIO pad behaviour for groups of GPIOs
316
+ // powerup value for al pads is
317
+ // BCM2835_PAD_SLEW_RATE_UNLIMITED | BCM2835_PAD_HYSTERESIS_ENABLED | BCM2835_PAD_DRIVE_8mA
318
+ void bcm2835_gpio_set_pad(uint8_t group, uint32_t control)
319
+ {
320
+ volatile uint32_t* paddr = pads + BCM2835_PADS_GPIO_0_27/4 + group*2;
321
+ bcm2835_peri_write(paddr, control);
322
+ }
323
+
324
+ // Some convenient arduino like functions
325
+ // milliseconds
326
+ void bcm2835_delay(unsigned int millis)
327
+ {
328
+ struct timespec sleeper;
329
+
330
+ sleeper.tv_sec = (time_t)(millis / 1000);
331
+ sleeper.tv_nsec = (long)(millis % 1000) * 1000000;
332
+ nanosleep(&sleeper, NULL);
333
+ }
334
+
335
+ // microseconds
336
+ void bcm2835_delayMicroseconds(unsigned int micros)
337
+ {
338
+ struct timespec t0, t1;
339
+ double t_us;
340
+ // Calling nanosleep() takes at least 100-200 us, so use it for
341
+ // long waits and use a busy wait on the hires timer for the rest.
342
+ clock_gettime(CLOCK_MONOTONIC_RAW, &t0);
343
+ if (micros > 450)
344
+ {
345
+ t1.tv_sec = 0;
346
+ t1.tv_nsec = 1000 * (long)(micros - 200);
347
+ nanosleep(&t1, NULL);
348
+ }
349
+
350
+ while (1)
351
+ {
352
+ clock_gettime(CLOCK_MONOTONIC_RAW, &t1);
353
+ t_us = (t1.tv_sec - t0.tv_sec) * 1e6 + (t1.tv_nsec - t0.tv_nsec) * 1e-3;
354
+ if (t_us >= micros)
355
+ break;
356
+ }
357
+ }
358
+
359
+ //
360
+ // Higher level convenience functions
361
+ //
362
+
363
+ // Set the state of an output
364
+ void bcm2835_gpio_write(uint8_t pin, uint8_t on)
365
+ {
366
+ if (on)
367
+ {
368
+ bcm2835_gpio_set(pin);
369
+ }
370
+ else
371
+ {
372
+ bcm2835_gpio_clr(pin);
373
+ }
374
+ }
375
+
376
+ // Set the pullup/down resistor for a pin
377
+ //
378
+ // The GPIO Pull-up/down Clock Registers control the actuation of internal pull-downs on
379
+ // the respective GPIO pins. These registers must be used in conjunction with the GPPUD
380
+ // register to effect GPIO Pull-up/down changes. The following sequence of events is
381
+ // required:
382
+ // 1. Write to GPPUD to set the required control signal (i.e. Pull-up or Pull-Down or neither
383
+ // to remove the current Pull-up/down)
384
+ // 2. Wait 150 cycles ? this provides the required set-up time for the control signal
385
+ // 3. Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads you wish to
386
+ // modify ? NOTE only the pads which receive a clock will be modified, all others will
387
+ // retain their previous state.
388
+ // 4. Wait 150 cycles ? this provides the required hold time for the control signal
389
+ // 5. Write to GPPUD to remove the control signal
390
+ // 6. Write to GPPUDCLK0/1 to remove the clock
391
+ //
392
+ // RPi has P1-03 and P1-05 with 1k8 pullup resistor
393
+ void bcm2835_gpio_set_pud(uint8_t pin, uint8_t pud)
394
+ {
395
+ bcm2835_gpio_pud(pud);
396
+ delayMicroseconds(10);
397
+ bcm2835_gpio_pudclk(pin, 1);
398
+ delayMicroseconds(10);
399
+ bcm2835_gpio_pud(BCM2835_GPIO_PUD_OFF);
400
+ bcm2835_gpio_pudclk(pin, 0);
401
+ }
402
+
403
+ void bcm2835_spi_begin(void)
404
+ {
405
+ // Set the SPI0 pins to the Alt 0 function to enable SPI0 access on them
406
+ bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_ALT0); // CE1
407
+ bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_ALT0); // CE0
408
+ bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_ALT0); // MISO
409
+ bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_ALT0); // MOSI
410
+ bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_ALT0); // CLK
411
+
412
+ // Set the SPI CS register to the some sensible defaults
413
+ volatile uint32_t* paddr = spi0 + BCM2835_SPI0_CS/4;
414
+ bcm2835_peri_write(paddr, 0); // All 0s
415
+
416
+ // Clear TX and RX fifos
417
+ bcm2835_peri_write_nb(paddr, BCM2835_SPI0_CS_CLEAR);
418
+ }
419
+
420
+ void bcm2835_spi_end(void)
421
+ {
422
+ // Set all the SPI0 pins back to input
423
+ bcm2835_gpio_fsel(RPI_GPIO_P1_26, BCM2835_GPIO_FSEL_INPT); // CE1
424
+ bcm2835_gpio_fsel(RPI_GPIO_P1_24, BCM2835_GPIO_FSEL_INPT); // CE0
425
+ bcm2835_gpio_fsel(RPI_GPIO_P1_21, BCM2835_GPIO_FSEL_INPT); // MISO
426
+ bcm2835_gpio_fsel(RPI_GPIO_P1_19, BCM2835_GPIO_FSEL_INPT); // MOSI
427
+ bcm2835_gpio_fsel(RPI_GPIO_P1_23, BCM2835_GPIO_FSEL_INPT); // CLK
428
+ }
429
+
430
+ void bcm2835_spi_setBitOrder(uint8_t order)
431
+ {
432
+ // BCM2835_SPI_BIT_ORDER_MSBFIRST is the only one suported by SPI0
433
+ }
434
+
435
+ // defaults to 0, which means a divider of 65536.
436
+ // The divisor must be a power of 2. Odd numbers
437
+ // rounded down. The maximum SPI clock rate is
438
+ // of the APB clock
439
+ void bcm2835_spi_setClockDivider(uint16_t divider)
440
+ {
441
+ volatile uint32_t* paddr = spi0 + BCM2835_SPI0_CLK/4;
442
+ bcm2835_peri_write(paddr, divider);
443
+ }
444
+
445
+ void bcm2835_spi_setDataMode(uint8_t mode)
446
+ {
447
+ volatile uint32_t* paddr = spi0 + BCM2835_SPI0_CS/4;
448
+ // Mask in the CPO and CPHA bits of CS
449
+ bcm2835_peri_set_bits(paddr, mode << 2, BCM2835_SPI0_CS_CPOL | BCM2835_SPI0_CS_CPHA);
450
+ }
451
+
452
+ // Writes (and reads) a single byte to SPI
453
+ uint8_t bcm2835_spi_transfer(uint8_t value)
454
+ {
455
+ volatile uint32_t* paddr = spi0 + BCM2835_SPI0_CS/4;
456
+ volatile uint32_t* fifo = spi0 + BCM2835_SPI0_FIFO/4;
457
+
458
+ // This is Polled transfer as per section 10.6.1
459
+ // BUG ALERT: what happens if we get interupted in this section, and someone else
460
+ // accesses a different peripheral?
461
+ // Clear TX and RX fifos
462
+ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
463
+
464
+ // Set TA = 1
465
+ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
466
+
467
+ // Maybe wait for TXD
468
+ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))
469
+ delayMicroseconds(10);
470
+
471
+ // Write to FIFO, no barrier
472
+ bcm2835_peri_write_nb(fifo, value);
473
+
474
+ // Wait for DONE to be set
475
+ while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE))
476
+ delayMicroseconds(10);
477
+
478
+ // Read any byte that was sent back by the slave while we sere sending to it
479
+ uint32_t ret = bcm2835_peri_read_nb(fifo);
480
+
481
+ // Set TA = 0, and also set the barrier
482
+ bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
483
+
484
+ return ret;
485
+ }
486
+
487
+ // Writes (and reads) an number of bytes to SPI
488
+ void bcm2835_spi_transfernb(char* tbuf, char* rbuf, uint32_t len)
489
+ {
490
+ volatile uint32_t* paddr = spi0 + BCM2835_SPI0_CS/4;
491
+ volatile uint32_t* fifo = spi0 + BCM2835_SPI0_FIFO/4;
492
+
493
+ // This is Polled transfer as per section 10.6.1
494
+ // BUG ALERT: what happens if we get interupted in this section, and someone else
495
+ // accesses a different peripheral?
496
+
497
+ // Clear TX and RX fifos
498
+ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_CLEAR, BCM2835_SPI0_CS_CLEAR);
499
+
500
+ // Set TA = 1
501
+ bcm2835_peri_set_bits(paddr, BCM2835_SPI0_CS_TA, BCM2835_SPI0_CS_TA);
502
+
503
+ uint32_t i;
504
+ for (i = 0; i < len; i++)
505
+ {
506
+ // Maybe wait for TXD
507
+ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_TXD))
508
+ delayMicroseconds(10);
509
+
510
+ // Write to FIFO, no barrier
511
+ bcm2835_peri_write_nb(fifo, tbuf[i]);
512
+
513
+ // Wait for RXD
514
+ while (!(bcm2835_peri_read(paddr) & BCM2835_SPI0_CS_RXD))
515
+ delayMicroseconds(10);
516
+
517
+ // then read the data byte
518
+ rbuf[i] = bcm2835_peri_read_nb(fifo);
519
+ }
520
+ // Wait for DONE to be set
521
+ while (!(bcm2835_peri_read_nb(paddr) & BCM2835_SPI0_CS_DONE))
522
+ delayMicroseconds(10);
523
+
524
+ // Set TA = 0, and also set the barrier
525
+ bcm2835_peri_set_bits(paddr, 0, BCM2835_SPI0_CS_TA);
526
+ }
527
+
528
+ // Writes (and reads) an number of bytes to SPI
529
+ // Read bytes are copied over onto the transmit buffer
530
+ void bcm2835_spi_transfern(char* buf, uint32_t len)
531
+ {
532
+ bcm2835_spi_transfernb(buf, buf, len);
533
+ }
534
+
535
+ void bcm2835_spi_chipSelect(uint8_t cs)
536
+ {
537
+ volatile uint32_t* paddr = spi0 + BCM2835_SPI0_CS/4;
538
+ // Mask in the CS bits of CS
539
+ bcm2835_peri_set_bits(paddr, cs, BCM2835_SPI0_CS_CS);
540
+ }
541
+
542
+ void bcm2835_spi_setChipSelectPolarity(uint8_t cs, uint8_t active)
543
+ {
544
+ volatile uint32_t* paddr = spi0 + BCM2835_SPI0_CS/4;
545
+ uint8_t shift = 21 + cs;
546
+ // Mask in the appropriate CSPOLn bit
547
+ bcm2835_peri_set_bits(paddr, active << shift, 1 << shift);
548
+ }
549
+
550
+ // Allocate page-aligned memory.
551
+ void *malloc_aligned(size_t size)
552
+ {
553
+ void *mem;
554
+ errno = posix_memalign(&mem, BCM2835_PAGE_SIZE, size);
555
+ return (errno ? NULL : mem);
556
+ }
557
+
558
+ // Map 'size' bytes starting at 'off' in file 'fd' to memory.
559
+ // Return mapped address on success, MAP_FAILED otherwise.
560
+ // On error print message.
561
+ static void *mapmem(const char *msg, size_t size, int fd, off_t off)
562
+ {
563
+ void *map = mmap(NULL, size, (PROT_READ | PROT_WRITE), MAP_SHARED, fd, off);
564
+ if(MAP_FAILED == map){
565
+ fprintf(stderr, "bcm2835_init: %s mmap failed: %s\n", msg, strerror(errno)) ;
566
+ }
567
+ return map;
568
+ }
569
+
570
+ static void unmapmem(void **pmem, size_t size)
571
+ {
572
+ if(*pmem == MAP_FAILED) return;
573
+ munmap(*pmem, size);
574
+ *pmem = MAP_FAILED;
575
+ }
576
+
577
+ // Initialise this library.
578
+ int bcm2835_init(void)
579
+ {
580
+ if (debug) {
581
+ pads = (uint32_t*)BCM2835_GPIO_PADS;
582
+ clk = (uint32_t*)BCM2835_CLOCK_BASE;
583
+ gpio = (uint32_t*)BCM2835_GPIO_BASE;
584
+ pwm = (uint32_t*)BCM2835_GPIO_PWM;
585
+ spi0 = (uint32_t*)BCM2835_SPI0_BASE;
586
+ return 1; // Success
587
+ }
588
+ int ok = 0;
589
+ // Open the master /dev/memory device
590
+ if ((memfd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
591
+ fprintf(stderr, "bcm2835_init: Unable to open /dev/mem: %s\n",
592
+ strerror(errno)) ;
593
+ goto exit;
594
+ }
595
+
596
+ // GPIO:
597
+ gpio = mapmem("gpio", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_BASE);
598
+ if (gpio == MAP_FAILED) goto exit;
599
+
600
+ // PWM
601
+ pwm = mapmem("pwm", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PWM);
602
+ if (pwm == MAP_FAILED) goto exit;
603
+
604
+ // Clock control (needed for PWM)
605
+ clk = mapmem("clk", BCM2835_BLOCK_SIZE, memfd, BCM2835_CLOCK_BASE);
606
+ if (clk == MAP_FAILED) goto exit;
607
+
608
+ pads = mapmem("pads", BCM2835_BLOCK_SIZE, memfd, BCM2835_GPIO_PADS);
609
+ if (pads == MAP_FAILED) goto exit;
610
+
611
+ spi0 = mapmem("spi0", BCM2835_BLOCK_SIZE, memfd, BCM2835_SPI0_BASE);
612
+ if (spi0 == MAP_FAILED) goto exit;
613
+
614
+ ok = 1;
615
+ exit:
616
+ if(!ok){
617
+ bcm2835_close();
618
+ }
619
+ return ok;
620
+ }
621
+
622
+ // Close this library and deallocate everything
623
+ int bcm2835_close(void)
624
+ {
625
+ int ok = 1; // Success.
626
+ if (debug) return ok;
627
+ unmapmem((void**) &gpio, BCM2835_BLOCK_SIZE);
628
+ unmapmem((void**) &pwm, BCM2835_BLOCK_SIZE);
629
+ unmapmem((void**) &clk, BCM2835_BLOCK_SIZE);
630
+ unmapmem((void**) &spi0, BCM2835_BLOCK_SIZE);
631
+ if (memfd >= 0)
632
+ {
633
+ close(memfd);
634
+ memfd = -1;
635
+ }
636
+ return ok;
637
+ }
638
+
639
+ #ifdef BCM2835_TEST
640
+ // this is a simple test program that prints out what it will do rather than
641
+ // actually doing it
642
+ int main(int argc, char **argv)
643
+ {
644
+ // Be non-destructive
645
+ bcm2835_set_debug(1);
646
+
647
+ if (!bcm2835_init())
648
+ return 1;
649
+
650
+ // Configure some GPIO pins fo some testing
651
+ // Set RPI pin P1-11 to be an output
652
+ bcm2835_gpio_fsel(RPI_GPIO_P1_11, BCM2835_GPIO_FSEL_OUTP);
653
+ // Set RPI pin P1-15 to be an input
654
+ bcm2835_gpio_fsel(RPI_GPIO_P1_15, BCM2835_GPIO_FSEL_INPT);
655
+ // with a pullup
656
+ bcm2835_gpio_set_pud(RPI_GPIO_P1_15, BCM2835_GPIO_PUD_UP);
657
+ // And a low detect enable
658
+ bcm2835_gpio_len(RPI_GPIO_P1_15);
659
+ // and input hysteresis disabled on GPIOs 0 to 27
660
+ bcm2835_gpio_set_pad(BCM2835_PAD_GROUP_GPIO_0_27, BCM2835_PAD_SLEW_RATE_UNLIMITED|BCM2835_PAD_DRIVE_8mA);
661
+
662
+ #if 1
663
+ // Blink
664
+ while (1)
665
+ {
666
+ // Turn it on
667
+ bcm2835_gpio_write(RPI_GPIO_P1_11, HIGH);
668
+
669
+ // wait a bit
670
+ bcm2835_delay(500);
671
+
672
+ // turn it off
673
+ bcm2835_gpio_write(RPI_GPIO_P1_11, LOW);
674
+
675
+ // wait a bit
676
+ bcm2835_delay(500);
677
+ }
678
+ #endif
679
+
680
+ #if 0
681
+ // Read input
682
+ while (1)
683
+ {
684
+ // Read some data
685
+ uint8_t value = bcm2835_gpio_lev(RPI_GPIO_P1_15);
686
+ printf("read from pin 15: %d\n", value);
687
+
688
+ // wait a bit
689
+ bcm2835_delay(500);
690
+ }
691
+ #endif
692
+
693
+ #if 0
694
+ // Look for a low event detection
695
+ // eds will be set whenever pin 15 goes low
696
+ while (1)
697
+ {
698
+ if (bcm2835_gpio_eds(RPI_GPIO_P1_15))
699
+ {
700
+ // Now clear the eds flag by setting it to 1
701
+ bcm2835_gpio_set_eds(RPI_GPIO_P1_15);
702
+ printf("low event detect for pin 15\n");
703
+ }
704
+
705
+ // wait a bit
706
+ bcm2835_delay(500);
707
+ }
708
+ #endif
709
+
710
+ if (!bcm2835_close())
711
+ return 1;
712
+
713
+ return 0;
714
+ }
715
+ #endif