forked from ggurov/hx711
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgb_common.c
361 lines (315 loc) · 9.15 KB
/
gb_common.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
//=============================================================================
//
//
// Gertboard Common code
//
// This file is part of the gertboard test suite
//
//
// Copyright (C) Gert Jan van Loo & Myra VanInwegen 2012
// No rights reserved
// You may treat this program as if it was in the public domain
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
// Notes:
// 1/ In some Linux systems (e.g. Debian) the UART is used by Linux.
// So for now do not demo the UART.
// 2/ At the moment (16-March-2012) there is no Linux driver for
// the audio yet so the PWM is free.
// This is likely to change and in that case the Linux
// audio/PWM driver must be disabled.
//
// This file contains code use by all the test programs for individual
// capabilities.
#include "gb_common.h"
#define BCM2708_PERI_BASE 0x20000000
#define CLOCK_BASE (BCM2708_PERI_BASE + 0x101000) /* Clocks */
#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO */
#define PWM_BASE (BCM2708_PERI_BASE + 0x20C000) /* PWM */
#define SPI0_BASE (BCM2708_PERI_BASE + 0x204000) /* SPI0 controller */
#define UART0_BASE (BCM2708_PERI_BASE + 0x201000) /* Uart 0 */
#define UART1_BASE (BCM2708_PERI_BASE + 0x215000) /* Uart 1 (not used) */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)
int mem_fd;
char *clk_mem_orig, *clk_mem, *clk_map;
char *gpio_mem_orig, *gpio_mem, *gpio_map;
char *pwm_mem_orig, *pwm_mem, *pwm_map;
char *spi0_mem_orig, *spi0_mem, *spi0_map;
char *uart_mem_orig, *uart_mem, *uart_map;
// I/O access
volatile unsigned *gpio;
volatile unsigned *pwm;
volatile unsigned *clk;
volatile unsigned *spi0;
volatile unsigned *uart;
//
// GPIO
//
// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3))
#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
#define GPIO_SET0 *(gpio+7) // Set GPIO high bits 0-31
#define GPIO_SET1 *(gpio+8) // Set GPIO high bits 32-53
#define GPIO_CLR0 *(gpio+10) // Set GPIO low bits 0-31
#define GPIO_CLR1 *(gpio+11) // Set GPIO low bits 32-53
#define GPIO_PULL *(gpio+37) // Pull up/pull down
#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
//
// UART 0
//
#define UART0_BAUD_HI *(uart+9)
#define UART0_BAUD_LO *(uart+10)
void setup_io();
void restore_io();
//
// This is a software loop to wait
// a short while.
//
void short_wait()
{ int w;
for (w=0; w<100; w++)
{ w++;
w--;
}
} // short_wait
//
// Simple SW wait loop
//
void long_wait(int v)
{ int w;
while (v--)
for (w=-800000; w<800000; w++)
{ w++;
w--;
}
} // long_wait
//
// Set up memory regions to access the peripherals.
// This is a bit of 'magic' which you should not touch.
// It it also the part of the code which makes that
// you have to use 'sudo' to run this program.
//
void setup_io()
{ unsigned long extra;
/* open /dev/mem */
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
printf("Can't open /dev/mem\n");
printf("Did you forgot to use 'sudo .. ?'\n");
exit (-1);
}
/*
* mmap clock
*/
if ((clk_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)clk_mem_orig % PAGE_SIZE;
if (extra)
clk_mem = clk_mem_orig + PAGE_SIZE - extra;
else
clk_mem = clk_mem_orig;
clk_map = (unsigned char *)mmap(
(caddr_t)clk_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
CLOCK_BASE
);
if ((long)clk_map < 0) {
printf("clk mmap error %d\n", (int)clk_map);
exit (-1);
}
clk = (volatile unsigned *)clk_map;
/*
* mmap GPIO
*/
if ((gpio_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)gpio_mem_orig % PAGE_SIZE;
if (extra)
gpio_mem = gpio_mem_orig + PAGE_SIZE - extra;
else
gpio_mem = gpio_mem_orig;
gpio_map = (unsigned char *)mmap(
(caddr_t)gpio_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
GPIO_BASE
);
if ((long)gpio_map < 0) {
printf("gpio mmap error %d\n", (int)gpio_map);
exit (-1);
}
gpio = (volatile unsigned *)gpio_map;
/*
* mmap PWM
*/
if ((pwm_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)pwm_mem_orig % PAGE_SIZE;
if (extra)
pwm_mem = pwm_mem_orig + PAGE_SIZE - extra;
else
pwm_mem = pwm_mem_orig;
pwm_map = (unsigned char *)mmap(
(caddr_t)pwm_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
PWM_BASE
);
if ((long)pwm_map < 0) {
printf("pwm mmap error %d\n", (int)pwm_map);
exit (-1);
}
pwm = (volatile unsigned *)pwm_map;
/*
* mmap SPI0
*/
if ((spi0_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)spi0_mem_orig % PAGE_SIZE;
if (extra)
spi0_mem = spi0_mem_orig + PAGE_SIZE - extra;
else
spi0_mem = spi0_mem_orig;
spi0_map = (unsigned char *)mmap(
(caddr_t)spi0_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
SPI0_BASE
);
if ((long)spi0_map < 0) {
printf("spi0 mmap error %d\n", (int)spi0_map);
exit (-1);
}
spi0 = (volatile unsigned *)spi0_map;
/*
* mmap UART
*/
if ((uart_mem_orig = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
printf("allocation error \n");
exit (-1);
}
extra = (unsigned long)uart_mem_orig % PAGE_SIZE;
if (extra)
uart_mem = uart_mem_orig + PAGE_SIZE - extra;
else
uart_mem = uart_mem_orig;
uart_map = (unsigned char *)mmap(
(caddr_t)uart_mem,
BLOCK_SIZE,
PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED,
mem_fd,
UART0_BASE
);
if ((long)uart_map < 0) {
printf("uart mmap error %d\n", (int)uart_map);
exit (-1);
}
uart = (volatile unsigned *)uart_map;
} // setup_io
//
// Undo what we did above
//
void restore_io()
{
munmap(uart_map,BLOCK_SIZE);
munmap(spi0_map,BLOCK_SIZE);
munmap(pwm_map,BLOCK_SIZE);
munmap(gpio_map,BLOCK_SIZE);
munmap(clk_map,BLOCK_SIZE);
// free memory
free(uart_mem_orig);
free(spi0_mem_orig);
free(pwm_mem_orig);
free(gpio_mem_orig);
free(clk_mem_orig);
close(mem_fd);
} // restore_io
// simple routine to convert the last several bits of an integer to a string
// showing its binary value
// nbits is the number of bits in i to look at
// i is integer we want to show as a binary number
// we only look at the nbits least significant bits of i and we assume that
// s is at least nbits+1 characters long
void make_binary_string(int nbits, int i, char *s)
{ char *p;
int bit;
p = s;
for (bit = 1 << (nbits-1); bit > 0; bit = bit >> 1, p++)
*p = (i & bit) ? '1' : '0';
*p = '\0';
}
//
// Find out what revision board the Raspberry Pi is
// Using the file '/proc/cpuinfo' for that.
// returns 1 or 2 for boards rev 1 or 2, and 0 if it wasn't able to tell
//
int pi_revision()
{
FILE *fp;
int revision, match, number;
char text[128]; // holds one line of file
revision = 0;
// Open the file with the CPU info
fp = fopen("/proc/cpuinfo","r");
if (fp)
{ // Find the line which starts 'Revision'
while (fgets(text, 128, fp)) // get one line of text from file
{
if (!strncmp(text,"Revision",8)) // strncmp returns 0 if string matches
{ // Get the revision number from the text
match = sscanf(text,"%*s : %0X",&number); // rev num is after the :
if (match == 1)
{ // Yes, we have a revision number
if (number >= 4)
revision = 2;
else
revision = 1;
} // have number
break; // no use in reading more lines, so break out of the while
} // have revision text
} // get line from file
fclose(fp);
} // Have open file
return revision;
} // pi_revision