forked from owendavies93/MAlice
/
utils.c
152 lines (117 loc) · 3.08 KB
/
utils.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
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
// ARM-specific memory sizes
#define PAGE_SIZE 4096
#define BLOCK_SIZE 4096
// GPIO controller physical address
#define GPIO_CONTROLLER 0x20200000
// GPIO controller virtual address
volatile unsigned *gpio;
void init_io() {
int mem_fd;
char *gpio_mem, *gpio_map;
if ((mem_fd = open("/dev/mem", O_RDWR | O_SYNC) ) < 0) {
perror("open");
exit(EXIT_FAILURE);
}
if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE - 1))) == NULL) {
printf("allocation error \n");
perror("malloc");
exit(EXIT_FAILURE);
}
// Align pointer to a 4K boundary
if ((unsigned long) gpio_mem % PAGE_SIZE)
gpio_mem += PAGE_SIZE - ((unsigned long) gpio_mem % PAGE_SIZE);
gpio_map = (unsigned char*) mmap(
(caddr_t) gpio_mem,
BLOCK_SIZE,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_FIXED,
mem_fd,
GPIO_CONTROLLER
);
if ((long) gpio_map < 0) {
perror("mmap");
exit(EXIT_FAILURE);
}
gpio = (volatile unsigned*) gpio_map;
}
void make_input(int pin) {
// 32-bit block containing pin
volatile unsigned *block = gpio + (pin / 10);
// Pin's location in block
int loc = (pin % 10) * 3;
// 0b000 is the 3-bit number to make pin an input
*block &= ~(~0b000 << loc);
}
void make_output(int pin) {
// Reset 3-bit configuration bits to 0b000
make_input(pin);
// 32-bit block containing pin
volatile unsigned *block = gpio + (pin / 10);
// Pin's location in block
int loc = (pin % 10) * 3;
// 0b001 is the 3-bit number to make pin an output
*block |= (0b001 << loc);
}
void set_high(int pin) {
// Sets bits which are 1 and ignores bits which are 0
*(gpio + 7) = 1 << pin;
}
void set_low(int pin) {
// Clears bits which are 1 and ignores bits which are 0
*(gpio + 10) = 1 << pin;
}
unsigned int read_in(int pin) {
// Returns the value of pin (high or low)
return (*(gpio + 13) >> pin) & 0b001;
}
void short_wait() {
// wait 100 clocks cycles for fun
int w = 0;
int i;
for (i = 0; i < 100; ++i) {
w++;
}
}
void pull_up(int pin) {
//No overflows!
int shift = (pin%32);
// enable pull=up on pin
*(gpio + 37) = 0b010;
short_wait();
// clock on GPIO pin
*(gpio + 38) = 0b001 << shift;
short_wait();
// set them back to 0
*(gpio + 37) = 0b000;
*(gpio + 38) = 0b000;
}
void pull_down(int pin) {
//No overflows!
int shift = (pin%32);
// enable pull down
*(gpio + 37) = 0b001;
short_wait();
// clock on GPIO pin
*(gpio + 38) = 0b001 << shift;
short_wait();
// set them back to 0
*(gpio + 37) = 0b000;
*(gpio + 38) = 0b000;
}
void stop_pull(int pin) {
//No overflows!
int shift = (pin%32);
//Clear the pull register.
*(gpio + 37) = 0b000;
// clock on GPIO pin
*(gpio + 38) = 0b001 << shift;
short_wait();
// set them back to 0
*(gpio + 37) = 0b000;
*(gpio + 38) = 0b000;
}