diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 12 | ||||
-rw-r--r-- | anzeige.c | 173 | ||||
-rw-r--r-- | input_gadgets.c | 57 | ||||
-rw-r--r-- | input_gadgets.h | 2 | ||||
-rw-r--r-- | multiplexer.c | 128 | ||||
-rw-r--r-- | multiplexer.h | 52 |
7 files changed, 258 insertions, 167 deletions
@@ -1 +1,2 @@ anzeige +*.o @@ -1,5 +1,13 @@ -anzeige: anzeige.c fonts.h - gcc -o "$@" -Werror=implicit-function-declaration -lpthread "$<" +CFLAGS="-Werror=implicit-function-declaration" + +anzeige: anzeige.c fonts.h input_gadgets.o multiplexer.o + gcc -o "$@" $(CFLAGS) -lpthread -lcurl $^ + +input_gadgeds.o: input_gadgeds.c input_gadgeds.h + gcc -o "$@" $(CFLAGS) -c -lcurl "$<" + +multiplexer.o: multiplexer.c multiplexer.h + gcc -o "$@" $(CFLAGS) -c -lpthread "$<" all: anzeige @@ -1,18 +1,3 @@ -// -// How to access GPIO registers from C-code on the Raspberry-Pi -// Example program -// 15-January-2012 -// Dom and Gert -// Revised: 15-Feb-2013 - -#ifndef __arm__ -#define SKIP_GPIO -#endif - -// Access from ARM Running Linux - -#define BCM2708_PERI_BASE 0x20000000 -#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ #define _GNU_SOURCE #include <stdio.h> @@ -25,67 +10,25 @@ #include <pthread.h> #include "fonts.h" +#include "input_gadgets.h" +#include "multiplexer.h" -#define PAGE_SIZE (4*1024) -#define BLOCK_SIZE (4*1024) - -#define SER_DAT_PIN 26 -#define SER_CLK_PIN 19 -#define GATE_PIN 13 -#define PAR_CLK_PIN 6 -#define SENSE_PIN 5 - -int mem_fd; -void *gpio_map; - -typedef struct { - char buf[3][40]; - int should_buf, is_buf, keep_running; -} t_display_data; - -// I/O access -volatile unsigned *gpio; - - -// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) -#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) -#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) -#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) - -#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0 -#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0 -#define GPIO_ALTER(a) *(gpio+(a==0?10:7)) // alters (a==0: clear, else: set) bits which are 1 ignores bits which are 0 - -#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH - -#define GPIO_PULL *(gpio+37) // Pull up/pull down -#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock - -void setup_io(); void drop_privileges(); -void *put_on_display(void *param); - -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"); -} int main(int argc, char **argv) { pthread_t thread_id; t_display_data display_data; -#ifndef SKIP_GPIO // Set up gpi pointer for direct register access - setup_io(); -#endif + multiplexer_setup_root(); // Drop root privileges drop_privileges(); + gadgets_retrieve_temperature(); + return 0; + /************************************************************************\ * You are about to change the GPIO settings of your computer. * * Mess this up and it will stop working! * @@ -93,25 +36,8 @@ int main(int argc, char **argv) * so at least you still have your code changes written to the SD-card! * \************************************************************************/ -#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(&thread_id, NULL, put_on_display, &display_data); + // configure the gpio pins and start the multiplexer thread + thread_id = multiplexer_setup_non_root(&display_data); for (int i=0; i<20; i++) { usleep(2500000); @@ -127,41 +53,6 @@ int main(int argc, char **argv) } // main - -// -// Set up a memory regions to access GPIO -// -void setup_io() -{ - /* open /dev/mem */ - if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { - perror("can't open /dev/mem"); - exit(-1); - } - - /* 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"); - exit(-1); - } - - // Always use volatile pointer! - gpio = (volatile unsigned *)gpio_map; - - -} // setup_io - // // Drop (root) privileges // @@ -178,51 +69,3 @@ void drop_privileges() exit(-1); } } // drop_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; - - while (display_data -> keep_running) { - -#ifdef SKIP_GPIO - usleep(100000); - printf("=\n"); -#endif - display_data -> is_buf = display_data -> should_buf; - for (line=0; line<7; line++) { -#ifdef SKIP_GPIO - for (column=0; column<40; column++) { - if ((*(display_data -> buf[display_data -> is_buf] + column)>>line) & 0x01) - printf("X"); - else - printf("."); -#else - GPIO_CLR = 1<<GATE_PIN; // Licht an - for (column=0; column<8; column++) { - GPIO_CLR = 1<<SER_CLK_PIN; - GPIO_ALTER(column == line) = 1<<SER_DAT_PIN; - GPIO_SET = 1<<SER_CLK_PIN; - } - for (column=39; column>=0; column--) { - GPIO_CLR = 1<<SER_CLK_PIN; - GPIO_ALTER((*(display_data -> buf[display_data -> is_buf] + column)>>line) & 0x01) = 1<<SER_DAT_PIN; - GPIO_SET = 1<<SER_CLK_PIN; -#endif - } - usleep(1000); -#ifdef SKIP_GPIO - printf("\n"); -#else - GPIO_SET = 1<<GATE_PIN; // Licht aus - GPIO_CLR = 1<<PAR_CLK_PIN; - GPIO_SET = 1<<PAR_CLK_PIN; -#endif - } - } - return NULL; -} // put_on_screen diff --git a/input_gadgets.c b/input_gadgets.c new file mode 100644 index 0000000..35dc766 --- /dev/null +++ b/input_gadgets.c @@ -0,0 +1,57 @@ +#include <string.h> +#include <stdlib.h> +#include <curl/curl.h> + +struct MemoryStruct { + char *memory; + size_t size; +}; + +static size_t +WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) +{ + size_t realsize = size * nmemb; + struct MemoryStruct *mem = (struct MemoryStruct *)userp; + + char *ptr = realloc(mem->memory, mem->size + realsize + 1); + if(ptr == NULL) { + /* out of memory! */ + printf("not enough memory (realloc returned NULL)\n"); + return 0; + } + + mem->memory = ptr; + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + mem->memory[mem->size] = 0; + + return realsize; +} + +int gadgets_retrieve_temperature() { + CURL *curl_handle; + CURLcode res; + struct MemoryStruct chunk; + + chunk.memory = malloc(1); + chunk.size = 0; + + curl_global_init(CURL_GLOBAL_ALL); + + curl_handle = curl_easy_init(); + if (!curl_handle) { + perror("Failed to init curl"); + return -1; + } + curl_easy_setopt(curl_handle, CURLOPT_URL, "https://wetter.mb.fh-jena.de/station/datenbank/php_giese/online.php"); + curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + res = curl_easy_perform(curl_handle); + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + curl_easy_cleanup(curl_handle); + printf("%lu bytes retrieved\n", (unsigned long)chunk.size); + return 0; +} diff --git a/input_gadgets.h b/input_gadgets.h new file mode 100644 index 0000000..11413a8 --- /dev/null +++ b/input_gadgets.h @@ -0,0 +1,2 @@ + +void gadgets_retrieve_temperature(); diff --git a/multiplexer.c b/multiplexer.c new file mode 100644 index 0000000..5f82ee5 --- /dev/null +++ b/multiplexer.c @@ -0,0 +1,128 @@ +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <pthread.h> + +#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 +// +void 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"); + exit(-1); + } + + /* 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"); + exit(-1); + } + + // 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; + + while (display_data -> keep_running) { + +#ifdef SKIP_GPIO + usleep(100000); + printf("=\n"); +#endif + display_data -> is_buf = display_data -> should_buf; + for (line=0; line<7; line++) { +#ifdef SKIP_GPIO + for (column=0; column<40; column++) { + if ((*(display_data -> buf[display_data -> is_buf] + column)>>line) & 0x01) + printf("X"); + else + printf("."); +#else + GPIO_CLR = 1<<GATE_PIN; // Licht an + for (column=0; column<8; column++) { + GPIO_CLR = 1<<SER_CLK_PIN; + GPIO_ALTER(column == line) = 1<<SER_DAT_PIN; + GPIO_SET = 1<<SER_CLK_PIN; + } + for (column=39; column>=0; column--) { + GPIO_CLR = 1<<SER_CLK_PIN; + GPIO_ALTER((*(display_data -> buf[display_data -> is_buf] + column)>>line) & 0x01) = 1<<SER_DAT_PIN; + GPIO_SET = 1<<SER_CLK_PIN; +#endif + } + usleep(1000); +#ifdef SKIP_GPIO + printf("\n"); +#else + GPIO_SET = 1<<GATE_PIN; // Licht aus + GPIO_CLR = 1<<PAR_CLK_PIN; + GPIO_SET = 1<<PAR_CLK_PIN; +#endif + } + } + return NULL; +} // put_on_display + +pthread_t multiplexer_setup_non_root(t_display_data *display_data) +{ + pthread_t thread_id; + +#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(&thread_id, NULL, put_on_display, display_data); + return thread_id; +} // multiplexer_setup_non_root diff --git a/multiplexer.h b/multiplexer.h new file mode 100644 index 0000000..806ef19 --- /dev/null +++ b/multiplexer.h @@ -0,0 +1,52 @@ +// +// How to access GPIO registers from C-code on the Raspberry-Pi +// Example program +// 15-January-2012 +// Dom and Gert +// Revised: 15-Feb-2013 + +#ifndef __arm__ +#define SKIP_GPIO +#endif + +// Access from ARM Running Linux + +#define BCM2708_PERI_BASE 0x20000000 +#define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ + +#define PAGE_SIZE (4*1024) +#define BLOCK_SIZE (4*1024) + +#define SER_DAT_PIN 26 +#define SER_CLK_PIN 19 +#define GATE_PIN 13 +#define PAR_CLK_PIN 6 +#define SENSE_PIN 5 + +int mem_fd; +void *gpio_map; + +typedef struct { + char buf[3][40]; + int should_buf, is_buf, keep_running; +} t_display_data; + +// I/O access +volatile unsigned *gpio; + +// GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y) +#define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3)) +#define OUT_GPIO(g) *(gpio+((g)/10)) |= (1<<(((g)%10)*3)) +#define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3)) + +#define GPIO_SET *(gpio+7) // sets bits which are 1 ignores bits which are 0 +#define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0 +#define GPIO_ALTER(a) *(gpio+(a==0?10:7)) // alters (a==0: clear, else: set) bits which are 1 ignores bits which are 0 + +#define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH + +#define GPIO_PULL *(gpio+37) // Pull up/pull down +#define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock + +void multiplexer_setup_root(); +pthread_t multiplexer_setup_non_root(t_display_data *display_data); |