forked from xobs/chumbot
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcylon.c
190 lines (163 loc) · 4.39 KB
/
cylon.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
/*
* Cylon lights connected to LCD pins 0-17, located on bank 1, pins 0-17.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <signal.h>
#include <pthread.h>
#define HW_PINCTRL_MUXSEL1 0x80018110
#define HW_PINCTRL_MUXSEL2 0x80018120
#define HW_PINCTRL_MUXSEL3 0x80018130
#define HW_PINCTRL_MUXSEL3_SET 0x80018134
#define HW_PINCTRL_MUXSEL3_CLR 0x80018138
#define HW_PINCTRL_DOUT1 0x80018510
#define HW_PINCTRL_DOUT1_SET 0x80018514
#define HW_PINCTRL_DOUT1_CLR 0x80018518
#define HW_PINCTRL_DOE1 0x80018710
#define HW_PINCTRL_DOE1_SET 0x80018714
#define HW_PINCTRL_DOE1_CLR 0x80018718
#define HW_PWM_CTRL 0x80064000
#define HW_PWM_CTRL_SET 0x80064004
#define HW_PWM_CTRL_CLR 0x80064008
#define HW_PWM_ACTIVE0 0x80064010
#define HW_PWM_PERIOD0 0x80064020
#define HW_PWM_ACTIVE1 0x80064030
#define HW_PWM_PERIOD1 0x80064040
#define HW_PWM_ACTIVE2 0x80064050
#define HW_PWM_PERIOD2 0x80064060
#define HW_PWM_ACTIVE3 0x80064070
#define HW_PWM_PERIOD3 0x80064080
#define HW_PWM_ACTIVE4 0x80064090
#define HW_PWM_PERIOD4 0x800640a0
static int cylon_pin[] = {
16,
14,
12,
11,
9,
7,
4,
2,
0,
17,
15,
13,
10,
8,
6,
5,
3,
1,
1,
3,
5,
6,
8,
10,
13,
15,
17,
0,
2,
4,
7,
9,
11,
12,
14,
16,
};
static pthread_t cylon_thread;
static int exit_cylon;
static int *mem = 0;
static int fd = 0;
static int *prev_mem_range = 0;
/******************************************************************************
* read_kernel_memory
*
* params:
* long offset - the offset of memory location to read
*
* desc:
* this function will return the 4-bytes at the specified
* memory offset of kernel memory
*****************************************************************************/
static int read_kernel_memory(long offset) {
int result;
int *mem_range = (int *)(offset & ~0xFFFF);
if( mem_range != prev_mem_range )
{
prev_mem_range = mem_range;
if(mem)
munmap(mem, 0xFFFF);
if(fd)
close(fd);
fd = open("/dev/mem", O_RDWR);
if( fd < 0 ) {
perror("Unable to open /dev/mem");
fd = 0;
return -1;
}
mem = mmap(0, 0xffff, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset&~0xFFFF);
if( -1 == (int)mem ) {
perror("Unable to mmap file");
if( -1 == close(fd) )
perror("Also couldn't close file");
fd=0;
return -1;
}
}
int scaled_offset = (offset-(offset&~0xFFFF));
result = mem[scaled_offset/sizeof(long)];
return result;
}
/******************************************************************************
* write_kernel_memory
*
* params:
* long offset - the offset of memory location to write
*
* desc:
* this function will write the 4-byte value at the specified
* memory offset of kernel memory
*****************************************************************************/
static int write_kernel_memory(long offset, long value) {
int old_value = read_kernel_memory(offset);
int scaled_offset = (offset-(offset & 0xFFFF0000L));
if(mem)
mem[scaled_offset/sizeof(long)] = value;
return old_value;
}
int cylon_init(void) {
// Change mux to use pins as GPIOs
write_kernel_memory(HW_PINCTRL_MUXSEL2, 0xffffffff);
write_kernel_memory(HW_PINCTRL_MUXSEL3_SET, 0x0000000f);
write_kernel_memory(HW_PINCTRL_DOUT1, 0x00000000);
write_kernel_memory(HW_PINCTRL_DOE1, 0x0003ffff);
return 0;
}
void *cylon_process(void *ignored) {
int cylon_progress = 0;
while(!exit_cylon) {
write_kernel_memory(HW_PINCTRL_DOUT1_SET, 1<<cylon_pin[cylon_progress]);
// Increment the current pin, looping if necessary.
cylon_progress++;
if(cylon_progress >= sizeof(cylon_pin)/sizeof(*cylon_pin))
cylon_progress = 0;
write_kernel_memory(HW_PINCTRL_DOUT1_CLR, 1<<cylon_pin[cylon_progress]);
usleep(30000);
}
return NULL;
}
int cylon_start(void) {
exit_cylon = 0;
pthread_create(&cylon_thread, NULL, cylon_process, NULL);
pthread_detach(cylon_thread);
return 0;
}
void cylon_stop(void) {
exit_cylon = 1;
}