summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2020-02-08 21:06:12 +0000
committerMike Crute <mike@crute.us>2020-02-08 21:06:12 +0000
commit72425223659251589e7013ebbec337a037b449d7 (patch)
tree777535058a399f2ae85aad39712f4d3a93a0cf2b
downloadrelay-driver-72425223659251589e7013ebbec337a037b449d7.tar.bz2
relay-driver-72425223659251589e7013ebbec337a037b449d7.tar.xz
relay-driver-72425223659251589e7013ebbec337a037b449d7.zip
Initial importHEADmaster
-rw-r--r--Makefile7
-rw-r--r--pix_driver.c258
-rw-r--r--relay_control.c95
3 files changed, 360 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..152671c
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,7 @@
1obj-m := relay_control.o
2
3all:
4 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
5
6clean:
7 make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
diff --git a/pix_driver.c b/pix_driver.c
new file mode 100644
index 0000000..10d3d21
--- /dev/null
+++ b/pix_driver.c
@@ -0,0 +1,258 @@
1#include <linux/init.h>
2#include <linux/module.h>
3#include <linux/kthread.h>
4#include <linux/delay.h>
5#include <linux/gpio.h>
6
7MODULE_LICENSE("GPL");
8
9/* GPIO */
10
11#define A1 17 // 0
12#define A2 18 // 1
13#define A3 27 // 2
14#define OE 22 // 3
15#define LE 23 // 4
16#define SDI 24 // 5
17#define CLK 25 // 6
18
19#define LINES 8
20#define PER_LINE 12
21
22static u8 pix_screen[LINES][PER_LINE] = {
23 {
24 0b00000000,0b00000000,0b00000000,0b00000000,
25 0b00000000,0b00000000,0b00000000,0b00000000,
26 0b00000000,0b00000000,0b00000000,0b00000000,
27 },
28 {
29 0b00000000,0b00000000,0b00000000,0b00000000,
30 0b00000000,0b00000000,0b00000000,0b00000000,
31 0b00000000,0b00000000,0b00000000,0b00000000,
32 },
33 {
34 0b00000000,0b00000000,0b00000000,0b00000000,
35 0b00000000,0b00000000,0b00000000,0b00000000,
36 0b00000000,0b00000000,0b00000000,0b00000000,
37 },
38 {
39 0b00000000,0b00000000,0b00000000,0b00000000,
40 0b00000000,0b00000000,0b00000000,0b00000000,
41 0b00000000,0b00000000,0b00000000,0b00000000,
42 },
43 {
44 0b00000000,0b00000000,0b00000000,0b00000000,
45 0b00000000,0b00000000,0b00000000,0b00000000,
46 0b00000000,0b00000000,0b00000000,0b00000000,
47 },
48 {
49 0b00000000,0b00000000,0b00000000,0b00000000,
50 0b00000000,0b00000000,0b00000000,0b00000000,
51 0b00000000,0b00000000,0b00000000,0b00000000,
52 },
53 {
54 0b00000000,0b00000000,0b00000000,0b00000000,
55 0b00000000,0b00000000,0b00000000,0b00000000,
56 0b00000000,0b00000000,0b00000000,0b00000000,
57 },
58 {
59 0b00000000,0b00000000,0b00000000,0b00000000,
60 0b00000000,0b00000000,0b00000000,0b00000000,
61 0b00000000,0b00000000,0b00000000,0b00000000,
62 },
63};
64
65void pix_line(u8 row){
66 gpio_set_value(A1, !(row & 0b00000001));
67 gpio_set_value(A2, !(row & 0b00000010));
68 gpio_set_value(A3, !(row & 0b00000100));
69}
70
71void pix_dot(int x, int y, int r, int g, int b) {
72 uint8_t l,p,t;
73
74 if(y % 2){
75 x = (x + 16);
76 }
77 y = (y / 2) - ((y / 2) % 1);
78
79 l = x / 8;
80 p = 7 - x % 8;
81 t = pix_screen[y][l];
82
83 //printf("line:%i, l:%i, p:%i, t:%i\n", y,l,p,t);
84
85 if(r) {
86 t |= 1 << p;
87 }else{
88 t &= ~(1 << p);
89 }
90 pix_screen[y][l] = t;
91
92 l = x / 8 + 4;
93 p = 7 - x % 8;
94 t = pix_screen[y][l];
95 if(g) {
96 t |= 1 << p;
97 }else{
98 t &= ~(1 << p);
99 }
100 pix_screen[y][l] = t;
101
102 l = x / 8 + 8;
103 p = 7 - x % 8;
104 t = pix_screen[y][l];
105 if(b) {
106 t |= 1 << p;
107 }else{
108 t &= ~(1 << p);
109 }
110 pix_screen[y][l] = t;
111}
112
113void pix_gpio_init(void){
114 printk(KERN_INFO "PIX: starting gpio...");
115 gpio_request(A1, "A1");
116 gpio_request(A2, "A2");
117 gpio_request(A3, "A3");
118
119 gpio_request(OE, "OE");
120 gpio_request(LE, "LE");
121 gpio_request(SDI, "SDI");
122 gpio_request(CLK, "CLK");
123
124 gpio_direction_output(A1, 0);
125 gpio_direction_output(A2, 0);
126 gpio_direction_output(A3, 0);
127
128 gpio_direction_output(OE, 1);
129 gpio_direction_output(LE, 0);
130 gpio_direction_output(SDI, 0);
131 gpio_direction_output(CLK, 0);
132 printk(KERN_INFO "PIX: starting gpio done.");
133}
134
135void pix_gpio_exit(void){
136 printk(KERN_INFO "PIX: stopping gpio...");
137 gpio_free(A1);
138 gpio_free(A2);
139 gpio_free(A3);
140
141 gpio_free(OE);
142 gpio_free(LE);
143 gpio_free(SDI);
144 gpio_free(CLK);
145 printk(KERN_INFO "PIX: stopping gpio done.");
146}
147
148
149
150/* SYSFS */
151
152static struct kobject *pix_kobject;
153
154static ssize_t set_pix(struct kobject *kobj, struct kobj_attribute *attr, const char *buff, size_t count) {
155 u8 x = 0;
156 u8 y = 0;
157 u8 r = 0;
158 u8 g = 0;
159 u8 b = 0;
160 sscanf(buff, "%hhd %hhd %hhd %hhd %hhd", &x, &y, &r, &g, &b);
161
162 pix_dot(x,y,r,g,b);
163 // printk(KERN_INFO "PIX: %d %d %d %d %d", x,y,r,g,b);
164
165 return count;
166}
167
168static struct kobj_attribute pix_attribute =__ATTR(dot, (S_IWUSR | S_IRUGO), NULL, set_pix);
169
170void pix_sysfs_init(void){
171 printk(KERN_INFO "PIX: starting sysfs...");
172 pix_kobject = kobject_create_and_add("pix", NULL);
173 if (sysfs_create_file(pix_kobject, &pix_attribute.attr)) {
174 pr_debug("failed to create pix sysfs!\n");
175 }
176 printk(KERN_INFO "PIX: starting sysfs done.");
177}
178
179void pix_sysfs_exit(void){
180 printk(KERN_INFO "PIX: stopping sysfs...");
181 kobject_put(pix_kobject);
182 printk(KERN_INFO "PIX: stopping sysfs done.");
183}
184
185
186/* THREAD */
187
188#define THREAD_PRIORITY 45
189#define THREAD_NAME "pix"
190
191struct task_struct *task;
192
193int pix_thread(void *data){
194 u8 line, pos, bit;
195 struct task_struct *TSK;
196 struct sched_param PARAM = { .sched_priority = MAX_RT_PRIO - 50 };
197 //struct sched_param PARAM = { .sched_priority = DEFAULT_PRIO };
198 TSK = current;
199
200 PARAM.sched_priority = THREAD_PRIORITY;
201 sched_setscheduler(TSK, SCHED_FIFO, &PARAM);
202
203 while(1) {
204 for(line = 0; line < LINES; line++) {
205 pix_line(line);
206 for(pos = 0; pos < PER_LINE; pos++) {
207 for (bit = 0; bit < 8; bit++) {
208 gpio_set_value(SDI, !!(pix_screen[line][pos] & (1 << (7 - bit))));
209 gpio_set_value(CLK, 1);
210 gpio_set_value(CLK, 0);
211 }
212 }
213 gpio_set_value(LE, 1);
214 gpio_set_value(LE, 0);
215 gpio_set_value(OE, 0);
216 usleep_range(2000, 2000);
217 gpio_set_value(OE, 1);
218 }
219 if (kthread_should_stop()) break;
220 }
221 return 0;
222}
223
224void pix_thread_init(void){
225 printk(KERN_INFO "PIX: starting thread...");
226 task = kthread_run(pix_thread, NULL, THREAD_NAME);
227 printk(KERN_INFO "PIX: starting thread done.");
228}
229
230void pix_thread_exit(void){
231 printk(KERN_INFO "PIX: stopping thread...");
232 kthread_stop(task);
233 printk(KERN_INFO "PIX: stopping thread done.");
234}
235
236/* MODULE */
237
238static int __init pix_init(void){
239 printk(KERN_INFO "PIX: staring...");
240 pix_gpio_init();
241 pix_thread_init();
242 pix_sysfs_init();
243 printk(KERN_INFO "PIX: staring done.");
244 return 0;
245}
246
247static void __exit pix_exit(void){
248 printk(KERN_INFO "PIX: stopping...");
249 pix_sysfs_exit();
250 pix_thread_exit();
251 pix_gpio_exit();
252 printk(KERN_INFO "PIX: stopping done.");
253}
254
255module_init(pix_init);
256module_exit(pix_exit);
257
258
diff --git a/relay_control.c b/relay_control.c
new file mode 100644
index 0000000..7b0e59c
--- /dev/null
+++ b/relay_control.c
@@ -0,0 +1,95 @@
1#include <linux/init.h>
2#include <linux/module.h>
3#include <linux/gpio.h>
4#include <linux/string.h>
5
6MODULE_LICENSE("GPL");
7
8#define RELAY_K1 18
9#define RELAY_K2 23
10#define RELAY_K3 24
11#define RELAY_K4 25
12
13#define NO_OFF 0
14#define NO_ON 1
15
16static struct kobject *relay_kobject;
17
18static ssize_t set_relay(struct kobject *kobj, struct kobj_attribute *attr, const char *buff, size_t count) {
19 int relay = 0;
20 u8 v = 0;
21 sscanf(buff, "%hhd", &v);
22
23 if (strcmp(attr->attr.name, "relay1") == 0) {
24 relay = RELAY_K1;
25 } else if (strcmp(attr->attr.name, "relay2") == 0) {
26 relay = RELAY_K2;
27 } else if (strcmp(attr->attr.name, "relay3") == 0) {
28 relay = RELAY_K3;
29 } else if (strcmp(attr->attr.name, "relay4") == 0) {
30 relay = RELAY_K4;
31 }
32
33 gpio_set_value(relay, (v == 0) ? NO_OFF : NO_ON);
34 return count;
35}
36
37static ssize_t get_relay(struct kobject *kobj, struct kobj_attribute *attr, char *buff) {
38 int relay = 0;
39 if (strcmp(attr->attr.name, "relay1") == 0) {
40 relay = RELAY_K1;
41 } else if (strcmp(attr->attr.name, "relay2") == 0) {
42 relay = RELAY_K2;
43 } else if (strcmp(attr->attr.name, "relay3") == 0) {
44 relay = RELAY_K3;
45 } else if (strcmp(attr->attr.name, "relay4") == 0) {
46 relay = RELAY_K4;
47 }
48 return sprintf(buff, "%d", gpio_get_value(relay));
49}
50
51static struct kobj_attribute relay1_attribute = __ATTR(relay1, (S_IWUSR | S_IRUGO), get_relay, set_relay);
52static struct kobj_attribute relay2_attribute = __ATTR(relay2, (S_IWUSR | S_IRUGO), get_relay, set_relay);
53static struct kobj_attribute relay3_attribute = __ATTR(relay3, (S_IWUSR | S_IRUGO), get_relay, set_relay);
54static struct kobj_attribute relay4_attribute = __ATTR(relay4, (S_IWUSR | S_IRUGO), get_relay, set_relay);
55
56static int __init relay_init(void) {
57 gpio_request(RELAY_K1, "RELAY_K1");
58 gpio_request(RELAY_K2, "RELAY_K2");
59 gpio_request(RELAY_K3, "RELAY_K3");
60 gpio_request(RELAY_K4, "RELAY_K4");
61
62 gpio_direction_output(RELAY_K1, NO_ON);
63 gpio_direction_output(RELAY_K2, NO_ON);
64 gpio_direction_output(RELAY_K3, NO_ON);
65 gpio_direction_output(RELAY_K4, NO_ON);
66
67 relay_kobject = kobject_create_and_add("relay", NULL);
68
69 if (sysfs_create_file(relay_kobject, &relay1_attribute.attr)) {
70 pr_debug("failed to create relay1 sysfs!\n");
71 }
72 if (sysfs_create_file(relay_kobject, &relay2_attribute.attr)) {
73 pr_debug("failed to create relay2 sysfs!\n");
74 }
75 if (sysfs_create_file(relay_kobject, &relay3_attribute.attr)) {
76 pr_debug("failed to create relay3 sysfs!\n");
77 }
78 if (sysfs_create_file(relay_kobject, &relay4_attribute.attr)) {
79 pr_debug("failed to create relay4 sysfs!\n");
80 }
81
82 return 0;
83}
84
85static void __exit relay_exit(void) {
86 kobject_put(relay_kobject);
87
88 gpio_free(RELAY_K1);
89 gpio_free(RELAY_K2);
90 gpio_free(RELAY_K3);
91 gpio_free(RELAY_K4);
92}
93
94module_init(relay_init);
95module_exit(relay_exit);