#ifndef SKIP_GPIO #include #include #include #endif #include #include #include #include #include #include "multiplexer.h" /** TODO void printButton(int g) { if (GET_GPIO(g)) // !=0 <-> bit is 1 <- port is HIGH=3.3V printf("Button pressed!\n"); else // port is LOW=0V printf("Button released!\n"); } **/ // // Set up a memory regions to access GPIO // int multiplexer_setup_root() { #ifndef SKIP_GPIO /* open /dev/mem */ if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { perror("can't open /dev/mem"); return EXIT_FAILURE; } /* mmap GPIO */ gpio_map = mmap( NULL, //Any adddress in our space will do BLOCK_SIZE, //Map length PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory MAP_SHARED, //Shared with other processes mem_fd, //File to map GPIO_BASE //Offset to GPIO peripheral ); close(mem_fd); //No need to keep mem_fd open after mmap if (gpio_map == MAP_FAILED) { perror("mmap error"); return EXIT_FAILURE; } // Always use volatile pointer! gpio = (volatile unsigned *)gpio_map; #endif } // multiplexer_setup_root // // Shift the bits provided in content into the display // void *put_on_display(void *param) { t_display_data *display_data = param; int line, column; #ifndef SKIP_GPIO struct timespec start_time, stop_time; #endif while (display_data -> keep_running) { #ifdef SKIP_GPIO usleep(10000); printf("=\n"); #endif display_data -> is_buf = display_data -> should_buf; #ifdef SKIP_GPIO for (line=0; line<7; line++) { for (column=0; column<40; column++) { if (display_data -> buf[display_data -> is_buf][column] & (0x01 << line)) printf("X"); else printf(" "); #else for (line=7; line>=0; line--) { GPIO_CLR = 1< keep_running = 0; perror("clock_gettime failed"); break; } for (column=0; column<8; column++) { GPIO_CLR = 1<=0; column--) { GPIO_CLR = 1< buf[display_data -> is_buf][column] & (0x01 << line)) = 1< keep_running = 0; perror("clock_gettime failed"); break; } // wait until start_time + 1ms int wait = (start_time.tv_sec - stop_time.tv_sec) * 1000000 + (start_time.tv_nsec - stop_time.tv_nsec) / 1000 + 1000; if (wait > 0) usleep(wait); GPIO_SET = 1< keep_running) { if (clock_gettime(CLOCK_MONOTONIC_RAW, &start_time) != 0) { scroll_data -> keep_running = 0; perror("clock_gettime failed"); break; } if (scroll_data -> update) { if ((buf[is_buf] . len != scroll_data -> input_len) || (memcmp(&buf[is_buf] . buf[buf[is_buf] . start], scroll_data -> input, scroll_data -> input_len) != 0)) { is_buf = (is_buf + 1) % 2; // copy the currently visible, old content memcpy(buf[is_buf] . buf, &buf[(is_buf + 1) % 2] . buf[column + 1], 39); buf[is_buf] . start = 39; // set the length of the new content buf[is_buf] . len = scroll_data -> input_len; // copy the new content from input for (int i=0; i<2; i++) memcpy( &buf[is_buf] . buf[39 + i * buf[is_buf] . len], scroll_data -> input, buf[is_buf] . len ); column = 0; } // clear update flag scroll_data -> update = 0; } for (int i=0; i<40; i++) display_data . buf[(display_data . should_buf + 1) % 3][i] = buf[is_buf] . buf[column + i]; column++; if (buf[is_buf] . len > 0) while (column >= buf[is_buf] . start + buf[is_buf] . len) column -= buf[is_buf] . len; if (clock_gettime(CLOCK_MONOTONIC_RAW, &stop_time) != 0) { scroll_data -> keep_running = 0; perror("clock_gettime failed"); break; } // wait until start_time + 50ms int wait = (start_time.tv_sec - stop_time.tv_sec) * 1000000 + (start_time.tv_nsec - stop_time.tv_nsec) / 1000 + 25000; if (wait > 0) usleep(wait); display_data . should_buf = (display_data . should_buf + 1) % 3; } display_data . keep_running = 0; pthread_join(display_data . thread_id, NULL); } // scroll_it void multiplexer_setup_non_root(t_display_data *display_data) { #ifndef SKIP_GPIO // must use INP_GPIO before we can use OUT_GPIO INP_GPIO(SER_DAT_PIN); OUT_GPIO(SER_DAT_PIN); INP_GPIO(SER_CLK_PIN); OUT_GPIO(SER_CLK_PIN); INP_GPIO(GATE_PIN); OUT_GPIO(GATE_PIN); INP_GPIO(PAR_CLK_PIN); OUT_GPIO(PAR_CLK_PIN); INP_GPIO(SENSE_PIN); #endif for (int i=0; i<3; i++) memset(display_data -> buf[i],0,40); display_data -> is_buf = 0; display_data -> should_buf = 0; display_data -> keep_running = 1; pthread_create(&display_data -> thread_id, NULL, put_on_display, display_data); return; } // multiplexer_setup_non_root void multiplexer_setup_scroll(t_scroll_data *scroll_data) { scroll_data -> update = 0; scroll_data -> keep_running = 1; pthread_create(&scroll_data -> thread_id, NULL, scroll_it, scroll_data); return; } // multiplexer_setup_scroll