From 72425223659251589e7013ebbec337a037b449d7 Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Sat, 8 Feb 2020 21:06:12 +0000 Subject: Initial import --- pix_driver.c | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 pix_driver.c (limited to 'pix_driver.c') 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 @@ +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL"); + +/* GPIO */ + +#define A1 17 // 0 +#define A2 18 // 1 +#define A3 27 // 2 +#define OE 22 // 3 +#define LE 23 // 4 +#define SDI 24 // 5 +#define CLK 25 // 6 + +#define LINES 8 +#define PER_LINE 12 + +static u8 pix_screen[LINES][PER_LINE] = { + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, + { + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + 0b00000000,0b00000000,0b00000000,0b00000000, + }, +}; + +void pix_line(u8 row){ + gpio_set_value(A1, !(row & 0b00000001)); + gpio_set_value(A2, !(row & 0b00000010)); + gpio_set_value(A3, !(row & 0b00000100)); +} + +void pix_dot(int x, int y, int r, int g, int b) { + uint8_t l,p,t; + + if(y % 2){ + x = (x + 16); + } + y = (y / 2) - ((y / 2) % 1); + + l = x / 8; + p = 7 - x % 8; + t = pix_screen[y][l]; + + //printf("line:%i, l:%i, p:%i, t:%i\n", y,l,p,t); + + if(r) { + t |= 1 << p; + }else{ + t &= ~(1 << p); + } + pix_screen[y][l] = t; + + l = x / 8 + 4; + p = 7 - x % 8; + t = pix_screen[y][l]; + if(g) { + t |= 1 << p; + }else{ + t &= ~(1 << p); + } + pix_screen[y][l] = t; + + l = x / 8 + 8; + p = 7 - x % 8; + t = pix_screen[y][l]; + if(b) { + t |= 1 << p; + }else{ + t &= ~(1 << p); + } + pix_screen[y][l] = t; +} + +void pix_gpio_init(void){ + printk(KERN_INFO "PIX: starting gpio..."); + gpio_request(A1, "A1"); + gpio_request(A2, "A2"); + gpio_request(A3, "A3"); + + gpio_request(OE, "OE"); + gpio_request(LE, "LE"); + gpio_request(SDI, "SDI"); + gpio_request(CLK, "CLK"); + + gpio_direction_output(A1, 0); + gpio_direction_output(A2, 0); + gpio_direction_output(A3, 0); + + gpio_direction_output(OE, 1); + gpio_direction_output(LE, 0); + gpio_direction_output(SDI, 0); + gpio_direction_output(CLK, 0); + printk(KERN_INFO "PIX: starting gpio done."); +} + +void pix_gpio_exit(void){ + printk(KERN_INFO "PIX: stopping gpio..."); + gpio_free(A1); + gpio_free(A2); + gpio_free(A3); + + gpio_free(OE); + gpio_free(LE); + gpio_free(SDI); + gpio_free(CLK); + printk(KERN_INFO "PIX: stopping gpio done."); +} + + + +/* SYSFS */ + +static struct kobject *pix_kobject; + +static ssize_t set_pix(struct kobject *kobj, struct kobj_attribute *attr, const char *buff, size_t count) { + u8 x = 0; + u8 y = 0; + u8 r = 0; + u8 g = 0; + u8 b = 0; + sscanf(buff, "%hhd %hhd %hhd %hhd %hhd", &x, &y, &r, &g, &b); + + pix_dot(x,y,r,g,b); + // printk(KERN_INFO "PIX: %d %d %d %d %d", x,y,r,g,b); + + return count; +} + +static struct kobj_attribute pix_attribute =__ATTR(dot, (S_IWUSR | S_IRUGO), NULL, set_pix); + +void pix_sysfs_init(void){ + printk(KERN_INFO "PIX: starting sysfs..."); + pix_kobject = kobject_create_and_add("pix", NULL); + if (sysfs_create_file(pix_kobject, &pix_attribute.attr)) { + pr_debug("failed to create pix sysfs!\n"); + } + printk(KERN_INFO "PIX: starting sysfs done."); +} + +void pix_sysfs_exit(void){ + printk(KERN_INFO "PIX: stopping sysfs..."); + kobject_put(pix_kobject); + printk(KERN_INFO "PIX: stopping sysfs done."); +} + + +/* THREAD */ + +#define THREAD_PRIORITY 45 +#define THREAD_NAME "pix" + +struct task_struct *task; + +int pix_thread(void *data){ + u8 line, pos, bit; + struct task_struct *TSK; + struct sched_param PARAM = { .sched_priority = MAX_RT_PRIO - 50 }; + //struct sched_param PARAM = { .sched_priority = DEFAULT_PRIO }; + TSK = current; + + PARAM.sched_priority = THREAD_PRIORITY; + sched_setscheduler(TSK, SCHED_FIFO, &PARAM); + + while(1) { + for(line = 0; line < LINES; line++) { + pix_line(line); + for(pos = 0; pos < PER_LINE; pos++) { + for (bit = 0; bit < 8; bit++) { + gpio_set_value(SDI, !!(pix_screen[line][pos] & (1 << (7 - bit)))); + gpio_set_value(CLK, 1); + gpio_set_value(CLK, 0); + } + } + gpio_set_value(LE, 1); + gpio_set_value(LE, 0); + gpio_set_value(OE, 0); + usleep_range(2000, 2000); + gpio_set_value(OE, 1); + } + if (kthread_should_stop()) break; + } + return 0; +} + +void pix_thread_init(void){ + printk(KERN_INFO "PIX: starting thread..."); + task = kthread_run(pix_thread, NULL, THREAD_NAME); + printk(KERN_INFO "PIX: starting thread done."); +} + +void pix_thread_exit(void){ + printk(KERN_INFO "PIX: stopping thread..."); + kthread_stop(task); + printk(KERN_INFO "PIX: stopping thread done."); +} + +/* MODULE */ + +static int __init pix_init(void){ + printk(KERN_INFO "PIX: staring..."); + pix_gpio_init(); + pix_thread_init(); + pix_sysfs_init(); + printk(KERN_INFO "PIX: staring done."); + return 0; +} + +static void __exit pix_exit(void){ + printk(KERN_INFO "PIX: stopping..."); + pix_sysfs_exit(); + pix_thread_exit(); + pix_gpio_exit(); + printk(KERN_INFO "PIX: stopping done."); +} + +module_init(pix_init); +module_exit(pix_exit); + + -- cgit v1.2.3