debugging lightswitch
[wakeup.git] / src / lightswitch.c
1 #include <sys/stat.h>
2 #include <sys/types.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <sys/mman.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <time.h>
10 #include <getopt.h>
11
12 #define PAGE_SIZE (4*1024)
13 #define BLOCK_SIZE (4*1024)
14  
15 /*  Direct access to GPIO hardware  */
16
17 // Access from ARM Running Linux
18 // For Raspberry Pi 2 and Pi 3, change BCM2708_PERI_BASE to 0x3F000000 for the code to work.
19  
20 //#define BCM2708_PERI_BASE        0x20000000
21 #define BCM2708_PERI_BASE        0x3F000000
22 #define GPIO_BASE                (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */
23  
24  
25 // I/O access
26 volatile unsigned *gpio;
27  
28  
29 // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or SET_GPIO_ALT(x,y)
30 #define INP_GPIO(g) *(gpio+((g)/10)) &= ~(7<<(((g)%10)*3))
31 #define OUT_GPIO(g) *(gpio+((g)/10)) |=  (1<<(((g)%10)*3))
32 #define SET_GPIO_ALT(g,a) *(gpio+(((g)/10))) |= (((a)<=3?(a)+4:(a)==4?3:2)<<(((g)%10)*3))
33  
34 #define GPIO_SET *(gpio+7)  // sets   bits which are 1 ignores bits which are 0
35 #define GPIO_CLR *(gpio+10) // clears bits which are 1 ignores bits which are 0
36  
37 #define GET_GPIO(g) (*(gpio+13)&(1<<g)) // 0 if LOW, (1<<g) if HIGH
38  
39 #define GPIO_PULL *(gpio+37) // Pull up/pull down
40 #define GPIO_PULLCLK0 *(gpio+38) // Pull up/pull down clock
41  
42 void setup_io();
43  
44
45
46 /*  GPIO pin assignments */
47
48 #define SWITCH_IN    2
49
50 #define FIRMASK 0x03
51
52 #define TEST_CYCLES  (60 * 5)  //  1 minute
53
54 unsigned fir_record[TEST_CYCLES];
55
56 int main(int argc, char *argv[])
57 {
58    unsigned int fir;  // A simple FIR filter
59
60    int    old_state, new_state;
61    struct timespec interval;
62
63    interval.tv_sec   = 0;
64    interval.tv_nsec  = 200000000;
65
66    // Set up gpi pointer for direct register access
67    setup_io();
68  
69    // Initialize the IO pins.
70    //GPIO_PULL = 0;
71    INP_GPIO(SWITCH_IN);
72
73    //   Initialize to switched off state
74    fir = 0xffff;
75    old_state = 1;  // Off
76
77    int cycle = 0;
78    //while (1)
79    while (cycle < TEST_CYCLES)
80    {
81       unsigned input = GET_GPIO(SWITCH_IN) == 0 ? 0 : 1;
82  
83       fir <<= 1;
84       fir |= input;
85
86       fprintf(stderr, "FIR =  0x%x\r", fir);
87       if ( (fir & FIRMASK) == 0)
88       {
89          new_state = 0;   // On
90       }
91       if ( (fir & FIRMASK) == FIRMASK)
92       {
93          new_state = 1;   // Off
94       }
95
96       if (new_state != old_state)
97       {
98          //fprintf(stderr, "Changed state to %d\r", new_state);
99          if (new_state == 0)
100          {
101             system("lightcontrol -r 100 -g 100 -b 100 -w 100");
102          }
103          else
104          {
105             system("lightcontrol -r 0 -g 0 -b 0 -w 0");
106          }
107
108          old_state = new_state;
109       }
110       fir_record[cycle++] = fir;
111
112       nanosleep(&interval, NULL);
113    }
114
115    for (int i = 0; i < TEST_CYCLES; i++)
116    {
117       //printf("FIR = 0x%08x\n", fir_record[i]);
118    }
119
120    return 0;
121 }
122
123 //
124 // Set up a memory regions to access GPIO
125 //
126 void setup_io()
127 {
128    void *gpio_map;
129    int  mem_fd;
130
131    /* open /dev/mem */
132    if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0)
133    {
134       printf("can't open /dev/mem \n");
135       exit(-1);
136    }
137  
138    /* mmap GPIO */
139    gpio_map = mmap(
140       NULL,             //Any adddress in our space will do
141       BLOCK_SIZE,       //Map length
142       PROT_READ|PROT_WRITE,// Enable reading & writting to mapped memory
143       MAP_SHARED,       //Shared with other processes
144       mem_fd,           //File to map
145       GPIO_BASE         //Offset to GPIO peripheral
146    );
147  
148    close(mem_fd); //No need to keep mem_fd open after mmap
149  
150    if (gpio_map == MAP_FAILED)
151    {
152       printf("mmap error %d, errno = %d\n", gpio_map, errno);//errno also set!
153       exit(-1);
154    }
155  
156    // Always use volatile pointer!
157    gpio = (volatile unsigned *)gpio_map;
158  
159  
160 } // setup_io