├── osd
├── README.md
├── osd
├── Makefile
├── osd-backup.c
└── osd.c
├── .DS_Store
├── LICENSE
├── rfkill
├── rfkill
└── README.txt
├── resources
├── .DS_Store
├── AUD0.png
├── AUD25.png
├── AUD50.png
├── AUD75.png
├── main.png
├── plug.png
├── AUD100.png
├── audio_2.png
├── battery.png
├── joystick.png
├── joystick.psd
├── wifi_1.png
├── wifi_2.png
├── wifi_3.png
├── bluetooth.png
├── wifi_error.png
├── low-battery.png
├── wifi_warning.png
├── main_no_joystick.png
└── main_no_joystick_pocketfe.png
├── .gitmodules
├── .idea
├── vcs.xml
├── modules.xml
└── Retropie-open-OSD.iml
├── Makefile
├── general.cfg
├── SystemConfigs
└── MintyPi-Lite
│ ├── general.cfg
│ └── mintypi-lite.cfg
├── keysGamepad.cfg
├── keysKeyboard.cfg
├── keysWill.cfg
├── .gitignore
├── README.md
└── monitor.py
/osd/README.md:
--------------------------------------------------------------------------------
1 | Build instructions:
2 |
3 | ./make
4 |
--------------------------------------------------------------------------------
/osd/osd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/osd/osd
--------------------------------------------------------------------------------
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/.DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Software and/or source code may not be used without express permission.
--------------------------------------------------------------------------------
/rfkill/rfkill:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/rfkill/rfkill
--------------------------------------------------------------------------------
/resources/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/.DS_Store
--------------------------------------------------------------------------------
/resources/AUD0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/AUD0.png
--------------------------------------------------------------------------------
/resources/AUD25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/AUD25.png
--------------------------------------------------------------------------------
/resources/AUD50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/AUD50.png
--------------------------------------------------------------------------------
/resources/AUD75.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/AUD75.png
--------------------------------------------------------------------------------
/resources/main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/main.png
--------------------------------------------------------------------------------
/resources/plug.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/plug.png
--------------------------------------------------------------------------------
/resources/AUD100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/AUD100.png
--------------------------------------------------------------------------------
/resources/audio_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/audio_2.png
--------------------------------------------------------------------------------
/resources/battery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/battery.png
--------------------------------------------------------------------------------
/resources/joystick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/joystick.png
--------------------------------------------------------------------------------
/resources/joystick.psd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/joystick.psd
--------------------------------------------------------------------------------
/resources/wifi_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/wifi_1.png
--------------------------------------------------------------------------------
/resources/wifi_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/wifi_2.png
--------------------------------------------------------------------------------
/resources/wifi_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/wifi_3.png
--------------------------------------------------------------------------------
/resources/bluetooth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/bluetooth.png
--------------------------------------------------------------------------------
/resources/wifi_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/wifi_error.png
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "osd/lib"]
2 | path = osd/lib
3 | url = https://github.com/vascofazza/raspidmx.git
4 |
--------------------------------------------------------------------------------
/resources/low-battery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/low-battery.png
--------------------------------------------------------------------------------
/resources/wifi_warning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/wifi_warning.png
--------------------------------------------------------------------------------
/resources/main_no_joystick.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/main_no_joystick.png
--------------------------------------------------------------------------------
/resources/main_no_joystick_pocketfe.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/withgallantry/OneForAll/HEAD/resources/main_no_joystick_pocketfe.png
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | TARGETS=osd/lib/lib \
2 | osd
3 |
4 | default :all
5 |
6 | all:
7 | for target in $(TARGETS); do ($(MAKE) -C $$target); done
8 |
9 | clean:
10 | for target in $(TARGETS); do ($(MAKE) -C $$target clean); done
11 |
12 |
--------------------------------------------------------------------------------
/general.cfg:
--------------------------------------------------------------------------------
1 | [GENERAL]
2 | KEYS_CONFIG=keysKeyboard.cfg
3 | SHUTDOWN_DETECT=27
4 | SHOW_OVERLAY_HOTKEY_ONLY=false
5 |
6 | [BATTERY]
7 | ENABLED=True
8 | FULL_BATT_VOLTAGE=375
9 | BATT_LOW_VOLTAGE=340
10 | BATT_SHUTDOWN_VOLT=328
11 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SystemConfigs/MintyPi-Lite/general.cfg:
--------------------------------------------------------------------------------
1 | [GENERAL]
2 | KEYS_CONFIG=keysKeyboard.cfg
3 | SHUTDOWN_DETECT=27
4 | SHOW_OVERLAY_HOTKEY_ONLY=false
5 | BACKLIGHT_PWM=true
6 | SENSOR_DETECT=22
7 | SENSOR_COMMAND=shutdown
8 |
9 | [BATTERY]
10 | ENABLED=True
11 | FULL_BATT_VOLTAGE=373
12 | BATT_LOW_VOLTAGE=330
13 | BATT_SHUTDOWN_VOLT=322
14 |
--------------------------------------------------------------------------------
/keysGamepad.cfg:
--------------------------------------------------------------------------------
1 | [KEYS]
2 | BTN_DPAD_LEFT=26
3 | BTN_DPAD_RIGHT=13
4 | BTN_DPAD_DOWN=6
5 | BTN_DPAD_UP=12
6 | BTN_A=5
7 | BTN_B=7
8 | BTN_X=4
9 | BTN_Y=17
10 | BTN_TL=16
11 | BTN_TR=20
12 | BTN_SELECT=22
13 | BTN_START=15
14 |
15 | [HOTKEYS]
16 | OSD_SHOW=22
17 | VOLUME_UP=12
18 | VOLUME_DOWN=6
19 | TOGGLE_WIFI=26
20 | TOGGLE_BLE=13
21 | TOGGLE_JOYSTICK=5
22 | SAFE_SHUTDOWN=-1
23 |
24 | [COMBOS]
25 |
26 | [JOYSTICK]
27 | ENABLED=True
28 | DEADZONE=300
29 | VCC=1600
30 |
--------------------------------------------------------------------------------
/.idea/Retropie-open-OSD.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/keysKeyboard.cfg:
--------------------------------------------------------------------------------
1 | [KEYS]
2 | KEY_LEFT=26 #Left DPAD
3 | KEY_RIGHT=13 #Right DPAD
4 | KEY_DOWN=6 #Down DPAD
5 | KEY_UP=12 #Up DPAD
6 | KEY_LEFTCTRL=5 #A Button
7 | KEY_LEFTALT=7 #B Button
8 | KEY_Z=4 #X Button
9 | KEY_X=17 #Y Button
10 | KEY_G=16 #L1 Button
11 | KEY_H=20 #R1 Button
12 | KEY_SPACE=22 #Select Button
13 | KEY_ENTER=15 #Start Button
14 |
15 | [COMBOS]
16 | KEY_ESC=4,17
17 |
18 | [HOTKEYS]
19 | OSD_SHOW=22
20 | VOLUME_UP=12
21 | VOLUME_DOWN=6
22 | TOGGLE_WIFI=17
23 | TOGGLE_BLE=4
24 | TOGGLE_JOYSTICK=5
25 | SAFE_SHUTDOWN=-1
26 |
27 | [JOYSTICK]
28 | ENABLED=False
29 | DEADZONE=300
30 | VCC=1600
31 |
--------------------------------------------------------------------------------
/SystemConfigs/MintyPi-Lite/mintypi-lite.cfg:
--------------------------------------------------------------------------------
1 | [KEYS]
2 | KEY_LEFT=4 #Left DPAD
3 | KEY_RIGHT=15 #Right DPAD
4 | KEY_DOWN=17 #Down DPAD
5 | KEY_UP=23 #Up DPAD
6 | KEY_LEFTCTRL=12 #A Button
7 | KEY_LEFTALT=26 #B Button
8 | KEY_Z=16 #X Button
9 | KEY_X=20 #Y Button
10 | KEY_G=27 #L1 Button
11 | KEY_H=6 #R1 Button
12 | KEY_SPACE=5 #Select Button
13 | KEY_ENTER=13 #Start Button
14 |
15 | [COMBOS]
16 | KEY_ESC=4,17
17 |
18 | [HOTKEYS]
19 | OSD_SHOW=7
20 | VOLUME_UP=23
21 | VOLUME_DOWN=17
22 | TOGGLE_WIFI=4
23 | TOGGLE_BLE=12
24 | TOGGLE_JOYSTICK=20
25 |
26 | [JOYSTICK]
27 | ENABLED=False
28 | DEADZONE=300
29 | VCC=1600
30 |
--------------------------------------------------------------------------------
/osd/Makefile:
--------------------------------------------------------------------------------
1 | OBJS=osd.o
2 | BIN=osd
3 |
4 | CFLAGS+=-Wall -g -O3 -I./lib/common $(shell libpng-config --cflags)
5 | LDFLAGS+=-L/opt/vc/lib/ -lbcm_host -lm $(shell libpng-config --ldflags) -L./lib/lib -lraspidmx
6 |
7 | INCLUDES+=-I/opt/vc/include/ -I/opt/vc/include/interface/vcos/pthreads -I/opt/vc/include/interface/vmcs_host/linux
8 |
9 | all: $(BIN)
10 |
11 | %.o: %.c
12 | @rm -f $@
13 | $(CC) $(CFLAGS) $(INCLUDES) -g -c $< -o $@ -Wno-deprecated-declarations
14 |
15 | $(BIN): $(OBJS)
16 | $(CC) -o $@ -Wl,--whole-archive $(OBJS) $(LDFLAGS) -pthread -Wl,--no-whole-archive -rdynamic
17 | chmod +x $@
18 | clean:
19 | @rm -f $(OBJS)
20 | @rm -f $(BIN)
21 |
--------------------------------------------------------------------------------
/keysWill.cfg:
--------------------------------------------------------------------------------
1 | # This config was created by Will (https://www.instagram.com/invader_meh/). The keys used are most suited for most emulators
2 | [KEYS]
3 | KEY_LEFT=26 #Left DPAD
4 | KEY_RIGHT=13 #Right DPAD
5 | KEY_DOWN=6 #Down DPAD
6 | KEY_UP=12 #Up DPAD
7 | KEY_X=5 #A Button
8 | KEY_Z=7 #B Button
9 | KEY_S=4 #X Button
10 | KEY_A=17 #Y Button
11 | KEY_U=16 #L1 Button
12 | KEY_Y=20 #R1 Button
13 | KEY_ESC=22 #Select Button
14 | KEY_ENTER=15 #Start Button
15 |
16 | [COMBOS]
17 |
18 | [HOTKEYS]
19 | OSD_SHOW=22
20 | VOLUME_UP=12
21 | VOLUME_DOWN=6
22 | TOGGLE_WIFI=26
23 | TOGGLE_BLE=4
24 | TOGGLE_JOYSTICK=5
25 |
26 | [JOYSTICK]
27 | ENABLED=False
28 | DEADZONE=300
29 | VCC=1600
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | q# Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | *.idea*
11 |
12 | # Linker output
13 | *.ilk
14 | *.map
15 | *.exp
16 |
17 | # Precompiled Headers
18 | *.gch
19 | *.pch
20 |
21 | # Libraries
22 | *.lib
23 | *.a
24 | *.la
25 | *.lo
26 |
27 | # Shared objects (inc. Windows DLLs)
28 | *.dll
29 | *.so
30 | *.so.*
31 | *.dylib
32 |
33 | # Executables
34 | *.exe
35 | *.out
36 | *.app
37 | *.i*86
38 | *.x86_64
39 | *.hex
40 |
41 | # Debug files
42 | *.dSYM/
43 | *.su
44 | *.idb
45 | *.pdb
46 |
47 | # Kernel Module Compile Results
48 | *.mod*
49 | *.cmd
50 | .tmp_versions/
51 | modules.order
52 | Module.symvers
53 | Mkfile.old
54 | dkms.conf
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # One For All
3 |
4 | One For All is software that was originally written and works best with with Helders [Retro PSU](https://heldergametech.com/shop/gameboy-zero/retropsu/).
5 |
6 | This software is designed to be used on Raspberry Pi handheld systems, such as the Gameboy Zero projects. This software handles battery monitoring, GPIO pins as control inputs, an analog joystick and safe shutdown. You will need specific hardware for some of these functions, which is listed below. The easiest way is to use Helders Retro PSU.
7 |
8 | ## Build instructions:
9 |
10 | * git clone --recursive https://github.com/withgallantry/OneForAll.git
11 |
12 | * make
13 |
14 | ## How to use it:
15 |
16 | * Configure (edit) the monitor script accordingly to your hardware configuration
17 |
18 | * sudo python monitor_evdev.py
--------------------------------------------------------------------------------
/rfkill/README.txt:
--------------------------------------------------------------------------------
1 | RFKILL binary taken from:
2 |
3 | pi@retropie:~ $ sudo apt-get install rfkill
4 | Reading package lists... Done
5 | Building dependency tree
6 | Reading state information... Done
7 | The following packages will be upgraded:
8 | rfkill
9 | 1 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
10 | Need to get 8,022 B of archives.
11 | After this operation, 38.9 kB disk space will be freed.
12 | Get:1 http://mirrordirector.raspbian.org/raspbian/ jessie/main rfkill armhf 0.5-1 [8,022 B]
13 | Fetched 8,022 B in 0s (55.8 kB/s)
14 | Reading changelogs... Done
15 | (Reading database ... 86916 files and directories currently installed.)
16 | Preparing to unpack .../rfkill_0.5-1_armhf.deb ...
17 | Unpacking rfkill (0.5-1) over (0.5-1) ...
18 | Processing triggers for man-db (2.7.0.2-5) ...
19 | Setting up rfkill (0.5-1) ...
20 |
--------------------------------------------------------------------------------
/osd/osd-backup.c:
--------------------------------------------------------------------------------
1 | //-------------------------------------------------------------------------
2 | //
3 | //
4 | // This file originates from Vascofazza's Retropie open OSD project.
5 | // Author: Federico Scozzafava
6 | //
7 | // THIS HEADER MUST REMAIN WITH THIS FILE AT ALL TIMES
8 | //
9 | // This firmware is free software: you can redistribute it and/or modify
10 | // it under the terms of the GNU General Public License as published by
11 | // the Free Software Foundation, either version 3 of the License, or
12 | // (at your option) any later version.
13 | //
14 | // This firmware is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this repo. If not, see .
21 | //
22 | //
23 | //-------------------------------------------------------------------------
24 |
25 | #define _GNU_SOURCE
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include "font.h"
35 | #include "imageGraphics.h"
36 | #include "imageLayer.h"
37 | #include "loadpng.h"
38 | #include
39 |
40 | #include "bcm_host.h"
41 |
42 | //-------------------------------------------------------------------------
43 |
44 | #define NDEBUG
45 |
46 | #define BATTERY_IMAGE "/home/pi/Retropie-open-OSD/resources/battery.png"
47 | #define CHARGE_IMAGE "/home/pi/Retropie-open-OSD/resources/plug.png"
48 | #define INFO_IMAGE "/home/pi/Retropie-open-OSD/resources/main16.png"
49 | //#define INFO_IMAGE "/home/pi/Retropie-open-OSD/resources/battery.png"
50 | #define BATTERY_TH 20
51 | #define AUDIO_IMAGES (const char*[5]){"/home/pi/Retropie-open-OSD/resources/AUD0.png","/home/pi/Retropie-open-OSD/resources/AUD25.png","/home/pi/Retropie-open-OSD/resources/AUD50.png","/home/pi/Retropie-open-OSD/resources/AUD75.png","/home/pi/Retropie-open-OSD/resources/AUD100.png"}
52 | #define WIFI_IMAGES (const char*[5]){"/home/pi/Retropie-open-OSD/resources/wifi_warning.png", "/home/pi/Retropie-open-OSD/resources/wifi_error.png", "/home/pi/Retropie-open-OSD/resources/wifi_1.png", "/home/pi/Retropie-open-OSD/resources/wifi_2.png", "/home/pi/Retropie-open-OSD/resources/wifi_3.png"}
53 | #define BRIGHTNESS_MAX 7
54 |
55 | volatile bool run = true;
56 |
57 | //-------------------------------------------------------------------------
58 |
59 | static RGBA8_T clearColor = {0,0,0,0};
60 | static RGBA8_T backgroundColour = { 0, 0, 0, 100 };
61 | static RGBA8_T textColour = { 255, 255, 255, 255 };
62 | static RGBA8_T greenColour = { 0, 255, 0, 200 };
63 | static RGBA8_T redColour = { 255, 0, 0, 200 };
64 | static int battery = 0, infos = 0, hud = 1, brightness = 0, charge = 0, audio = 0, wifi = 0, voltage = 0;
65 | static float temp = 0.f;
66 |
67 | void updateInfo(IMAGE_LAYER_T*);
68 | void getInput();
69 | void clearLayer(IMAGE_LAYER_T*);
70 | void updateBattery(float, IMAGE_LAYER_T*);
71 |
72 | static void
73 | signalHandler(int signalNumber)
74 | {
75 | switch (signalNumber)
76 | {
77 | case SIGUSR1:
78 | getInput();
79 | break;
80 | case SIGINT:
81 | case SIGTERM:
82 |
83 | run = false;
84 | break;
85 | };
86 | }
87 |
88 | void updateBattery(float batval, IMAGE_LAYER_T* batteryLayer)
89 | {
90 | IMAGE_T *image = &(batteryLayer->image);
91 | clearImageRGB(image,&clearColor);
92 | //to config params
93 | RGBA8_T *col = battery < BATTERY_TH ? &redColour : &greenColour;
94 | imageBoxFilledRGB(image, 2,3,2+(int)round((batteryLayer->image.width-7)*batval),batteryLayer->image.height-3, col);
95 | changeSourceAndUpdateImageLayer(batteryLayer);
96 | }
97 |
98 | void getInput()
99 | {
100 | char buffer[100];
101 | char *bp = buffer;
102 | int c;
103 | while(run && '\n' != (c=fgetc(stdin)) && (bp-buffer) < sizeof(buffer))
104 | *bp++=c;
105 | *bp = 0;//terminator
106 | #ifndef NDEBUG
107 | printf("buffer: %s\n", buffer);
108 | #endif
109 | char *saveptr;
110 | char *word;
111 | char *str = buffer;
112 | while((word = strtok_r(str," ",&saveptr)))
113 | {
114 | #ifndef NDEBUG
115 | printf("word: %s\n", word);
116 | #endif
117 | str = NULL;
118 | if(word[0] == 'b')
119 | {
120 | //Battery
121 | battery = atoi(word+1);
122 | }
123 | else if(word[0] == 'w')
124 | {
125 | //wifi
126 | wifi= atoi(word+1);
127 | }
128 | else if(word[0] == 'a')
129 | {
130 | //audio
131 | audio= atoi(word+1);
132 | }
133 | else if(word[0] == 'l')
134 | {
135 | //Brightness
136 | brightness= atoi(word+1);
137 | }
138 | else if(word[0] == 't')
139 | {
140 | //temperature
141 | temp= atof(word+1);
142 | }
143 | else if(word[0] == 'v')
144 | {
145 | //voltage
146 | voltage= atoi(word+1);
147 | }
148 | else if(!strcmp(word, "on"))
149 | {
150 | infos = 1;
151 | }
152 | else if(!strcmp(word, "off"))
153 | {
154 | infos = 0;
155 | }
156 | else if(!strcmp(word, "allon"))
157 | {
158 | hud = 1;
159 | }
160 | else if(!strcmp(word, "alloff"))
161 | {
162 | hud = 0;
163 | }
164 | else if(!strcmp(word, "charge"))
165 | {
166 | charge = 1;
167 | }
168 | else if(!strcmp(word, "ncharge"))
169 | {
170 | charge = 0;
171 | }
172 | else if(!strcmp(word,"quit"))
173 | run = false;
174 | }
175 | #ifndef NDEBUG
176 | printf("out\n");
177 | #endif
178 | }
179 |
180 | void clearLayer(IMAGE_LAYER_T *layer)
181 | {
182 | IMAGE_T *image = &(layer->image);
183 | clearImageRGB(image, &clearColor);
184 | changeSourceAndUpdateImageLayer(layer);
185 | }
186 |
187 | //-------------------------------------------------------------------------
188 |
189 | int main(int argc, char *argv[])
190 | {
191 | uint32_t displayNumber = 0;
192 |
193 | //-------------------------------------------------------------------
194 |
195 | int opt;
196 |
197 | while ((opt = getopt(argc, argv, "d:")) != -1)
198 | {
199 | switch (opt)
200 | {
201 | case 'd':
202 |
203 | displayNumber = atoi(optarg);
204 | break;
205 |
206 | default:
207 |
208 | fprintf(stderr, "Usage: %s [-d ]\n", basename(argv[0]));
209 | fprintf(stderr, " -d - Raspberry Pi display number\n");
210 | exit(EXIT_FAILURE);
211 | break;
212 | }
213 | }
214 |
215 | if (signal(SIGINT, signalHandler) == SIG_ERR)
216 | {
217 | perror("installing SIGINT signal handler");
218 | exit(EXIT_FAILURE);
219 | }
220 |
221 | //---------------------------------------------------------------------
222 |
223 | if (signal(SIGTERM, signalHandler) == SIG_ERR)
224 | {
225 | perror("installing SIGTERM signal handler");
226 | exit(EXIT_FAILURE);
227 | }
228 |
229 | //---------------------------------------------------------------------
230 |
231 | if (signal(SIGUSR1, signalHandler) == SIG_ERR)
232 | {
233 | perror("installing SIGTERM signal handler");
234 | exit(EXIT_FAILURE);
235 | }
236 |
237 | //-------------------------------------------------------------------
238 |
239 | VC_IMAGE_TYPE_T type = VC_IMAGE_RGBA32;
240 |
241 | //---------------------------------------------------------------------
242 |
243 | bcm_host_init();
244 |
245 | //---------------------------------------------------------------------
246 |
247 | DISPMANX_DISPLAY_HANDLE_T display
248 | = vc_dispmanx_display_open(displayNumber);
249 | assert(display != 0);
250 |
251 | //---------------------------------------------------------------------
252 |
253 | DISPMANX_MODEINFO_T info;
254 | int result = vc_dispmanx_display_get_info(display, &info);
255 | assert(result == 0);
256 |
257 | //---------------------------------------------------------------------
258 |
259 | static int layer = 30000;
260 |
261 | IMAGE_LAYER_T infoLayer;
262 |
263 | if (loadPng(&(infoLayer.image), INFO_IMAGE) == false)
264 | {
265 | fprintf(stderr, "unable to load %s\n", INFO_IMAGE);
266 | exit(EXIT_FAILURE);
267 | }
268 |
269 |
270 | createResourceImageLayer(&infoLayer, layer + 3);
271 |
272 |
273 | IMAGE_LAYER_T bimageLayer;
274 | if (loadPng(&(bimageLayer.image), BATTERY_IMAGE) == false)
275 | {
276 | fprintf(stderr, "unable to load %s\n", argv[optind]);
277 | }
278 | createResourceImageLayer(&bimageLayer, layer+2);
279 |
280 | IMAGE_LAYER_T batteryLayer;
281 | initImageLayer(&batteryLayer,
282 | bimageLayer.image.width,
283 | bimageLayer.image.height,
284 | VC_IMAGE_RGBA16);
285 | createResourceImageLayer(&batteryLayer, layer+1);
286 |
287 | IMAGE_LAYER_T cimageLayer;
288 | initImageLayer(&cimageLayer,
289 | bimageLayer.image.width,
290 | bimageLayer.image.height,
291 | type);
292 | createResourceImageLayer(&cimageLayer, layer+2);
293 |
294 | IMAGE_LAYER_T wimageLayer;
295 | initImageLayer(&wimageLayer,
296 | bimageLayer.image.height,
297 | bimageLayer.image.height,
298 | type);
299 | createResourceImageLayer(&wimageLayer, layer+2);
300 |
301 | IMAGE_LAYER_T aimageLayer;
302 | initImageLayer(&aimageLayer,
303 | 20,
304 | 11,
305 | type);
306 | createResourceImageLayer(&aimageLayer, layer+2);
307 |
308 | int xOffset = info.width-bimageLayer.image.width-1;
309 | int yOffset = 1;
310 | DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
311 | assert(update != 0);
312 |
313 | addElementImageLayerOffset(&infoLayer,
314 | (info.width - infoLayer.image.width) / 2,
315 | (info.height - infoLayer.image.height) / 2,
316 | display,
317 | update);
318 |
319 | addElementImageLayerOffset(&wimageLayer,
320 | xOffset-wimageLayer.image.width-2,
321 | yOffset,
322 | display,
323 | update);
324 |
325 | addElementImageLayerOffset(&aimageLayer,
326 | (xOffset-wimageLayer.image.width)-aimageLayer.image.width-8,
327 | yOffset,
328 | display,
329 | update);
330 |
331 | addElementImageLayerOffset(&batteryLayer,
332 | xOffset,
333 | yOffset,
334 | display,
335 | update);
336 | addElementImageLayerOffset(&bimageLayer,
337 | xOffset,
338 | yOffset,
339 | display,
340 | update);
341 | addElementImageLayerOffset(&cimageLayer,
342 | xOffset,
343 | yOffset,
344 | display,
345 | update);
346 |
347 |
348 | result = vc_dispmanx_update_submit_sync(update);
349 | assert(result == 0);
350 |
351 | while (run)
352 | {
353 | float batval = battery/100.f;
354 | {
355 | updateBattery(batval, &batteryLayer);
356 | }
357 | if(charge > 0 && hud)
358 | {
359 | //TODO preload for efficiency
360 | if (loadPng(&(cimageLayer.image), CHARGE_IMAGE) == false)
361 | {
362 | fprintf(stderr, "unable to charge load %s\n", argv[optind]);
363 | }
364 | changeSourceAndUpdateImageLayer(&cimageLayer);
365 | charge = -1;
366 | }
367 | else if(!charge && hud)
368 | {
369 | clearLayer(&cimageLayer);
370 | charge = -1;
371 | }
372 | if(wifi > 0 && hud)
373 | {
374 | //TODO preload for efficienty
375 | if (loadPng(&(wimageLayer.image), WIFI_IMAGES[wifi-1]) == false)
376 | {
377 | fprintf(stderr, "unable to wifi load %s\n", argv[optind]);
378 | }
379 | changeSourceAndUpdateImageLayer(&wimageLayer);
380 | wifi = -1;
381 | }
382 | else if (!wifi)
383 | {
384 | clearLayer(&wimageLayer);
385 | }
386 | if(audio > 0)
387 | {
388 | //TODO preload for efficienty
389 | if (loadPng(&(aimageLayer.image), AUDIO_IMAGES[audio-1]) == false)
390 | {
391 | fprintf(stderr, "unable to audio load %s\n", argv[optind]);
392 | }
393 | changeSourceAndUpdateImageLayer(&aimageLayer);
394 | audio = -1;
395 | }
396 | else if (!audio)
397 | {
398 | clearLayer(&aimageLayer);
399 | }
400 | if (!hud) {
401 | clearLayer(&batteryLayer);
402 | clearLayer(&wimageLayer);
403 | clearLayer(&aimageLayer);
404 | clearLayer(&bimageLayer);
405 | clearLayer(&cimageLayer);
406 | }
407 | if(infos > 0)
408 | {
409 | updateInfo(&infoLayer);
410 | }
411 | else if(!infos)
412 | {
413 | infos = -1;
414 | clearLayer(&infoLayer);
415 | }
416 | else
417 | {
418 | pause(); //stop thread
419 | }
420 | usleep(1000000); //sleep 1sec
421 | }
422 | //---------------------------------------------------------------------
423 |
424 | destroyImageLayer(&infoLayer);
425 | destroyImageLayer(&batteryLayer);
426 | destroyImageLayer(&wimageLayer);
427 | destroyImageLayer(&aimageLayer);
428 | destroyImageLayer(&bimageLayer);
429 | destroyImageLayer(&cimageLayer);
430 | result = vc_dispmanx_display_close(display);
431 | assert(result == 0);
432 |
433 | //---------------------------------------------------------------------
434 |
435 | return 0;
436 | }
437 |
438 | void updateInfo(IMAGE_LAYER_T *infoLayer)
439 | {
440 | IMAGE_T *image = &(infoLayer->image);
441 | // clearImageRGB(image, &backgroundColour);
442 | loadPng(&(infoLayer->image), INFO_IMAGE);
443 | // int x = 1, y = 1;
444 | // drawStringRGB(x, y, buffer, &textColour, image);
445 | changeSourceAndUpdateImageLayer(infoLayer);
446 | }
447 |
448 |
--------------------------------------------------------------------------------
/monitor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | # sudo apt-get install python-serial
3 | #
4 | # This file originates from Vascofazza's Retropie open OSD project.
5 | # Author: Federico Scozzafava
6 | #
7 | # THIS HEADER MUST REMAIN WITH THIS FILE AT ALL TIMES
8 | #
9 | # This firmware is free software: you can redistribute it and/or modify
10 | # it under the terms of the GNU General Public License as published by
11 | # the Free Software Foundation, either version 3 of the License, or
12 | # (at your option) any later version.
13 | #
14 | # This firmware is distributed in the hope that it will be useful,
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | # GNU General Public License for more details.
18 | #
19 | # You should have received a copy of the GNU General Public License
20 | # along with this repo. If not, see .
21 | #
22 | import Adafruit_ADS1x15
23 | import RPi.GPIO as gpio
24 | import configparser
25 | import logging
26 | import logging.handlers
27 | import os
28 | import re
29 | import signal
30 | import sys
31 | import thread as thread
32 | import time
33 | import uinput
34 | from subprocess import Popen, PIPE, check_output, check_call
35 | from threading import Event
36 |
37 | # Batt variables
38 | voltscale = 118.0 # ADJUST THIS
39 | currscale = 640.0
40 | resdivmul = 4.0
41 | resdivval = 1000.0
42 | dacres = 20.47
43 | dacmax = 4096.0
44 |
45 | backlightSetting = 1024
46 |
47 | batt_threshold = 4
48 |
49 | temperature_max = 70.0
50 | temperature_threshold = 5.0
51 |
52 | # BT Variables
53 | bt_state = 'UNKNOWN'
54 |
55 | # Wifi variables
56 | wifi_state = 'UNKNOWN'
57 | wif = 0
58 | wifi_off = 0
59 | wifi_warning = 1
60 | wifi_error = 2
61 | wifi_1bar = 3
62 | wifi_2bar = 4
63 | wifi_3bar = 5
64 |
65 |
66 | def str2bool(v):
67 | return v.lower() in ("yes", "true", "True", "1")
68 |
69 |
70 | bin_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
71 | osd_path = bin_dir + '/osd/osd'
72 | rfkill_path = bin_dir + '/rfkill/rfkill'
73 |
74 | # General Configuration
75 | generalConfig = configparser.ConfigParser()
76 | generalConfig.read(bin_dir + '/general.cfg')
77 |
78 | general = generalConfig['GENERAL']
79 |
80 | # Keys Configuration
81 | keysConfig = configparser.ConfigParser(inline_comment_prefixes="#")
82 | keysConfig.read(bin_dir + '/' + general['KEYS_CONFIG'])
83 | hotkeys = keysConfig['HOTKEYS']
84 |
85 | if generalConfig.has_option("GENERAL", "DEBUG"):
86 | logging.basicConfig(filename=bin_dir + '/osd.log', level=logging.DEBUG)
87 |
88 | HOTKEYS = []
89 | BUTTONS = []
90 | KEYS = {}
91 | PREVIOUS_KEYSTATES = {}
92 | COMBO_CURRENT_KEYS = set()
93 |
94 | KEY_COMBOS = {}
95 |
96 | # GPIO Init
97 | gpio.setwarnings(False)
98 | gpio.setmode(gpio.BCM)
99 |
100 | for key, pin in keysConfig.items('KEYS'):
101 | BUTTONS.append(int(pin))
102 | KEYS.update({int(pin): getattr(uinput, key.upper())})
103 | PREVIOUS_KEYSTATES.update({int(pin): 0})
104 |
105 | for key, pinSet in keysConfig.items('COMBOS'):
106 | pins = set(map(int, pinSet.split(',')))
107 | KEY_COMBOS.update({frozenset(pins): getattr(uinput, key.upper())})
108 |
109 | VOLUME_UP = int(hotkeys['VOLUME_UP'])
110 | VOLUME_DOWN = int(hotkeys['VOLUME_DOWN'])
111 | TOGGLE_WIFI = int(hotkeys['TOGGLE_WIFI'])
112 | TOGGLE_BLE = int(hotkeys['TOGGLE_BLE'])
113 | TOGGLE_JOYSTICK = int(hotkeys['TOGGLE_JOYSTICK'])
114 | SHOW_OSD_KEY = int(hotkeys['OSD_SHOW'])
115 | SHUTDOWN = int(general['SHUTDOWN_DETECT'])
116 | SHOW_OVERLAY_HOTKEY_ONLY = str2bool(general['SHOW_OVERLAY_HOTKEY_ONLY'])
117 |
118 | if generalConfig.has_option("GENERAL", "BACKLIGHT_PWM"):
119 | if str2bool(general['BACKLIGHT_PWM']):
120 | import wiringpi
121 |
122 | wiringpi.wiringPiSetupGpio()
123 |
124 | wiringpi.pinMode(13, wiringpi.OUTPUT)
125 | wiringpi.pinMode(13, wiringpi.PWM_OUTPUT)
126 | wiringpi.pwmWrite(13, backlightSetting)
127 |
128 | BRIGHTNESS_UP = int(hotkeys['BRIGHTNESS_UP'])
129 | BRIGHTNESS_DOWN = int(hotkeys['BRIGHTNESS_DOWN'])
130 |
131 | if generalConfig.has_option("GENERAL", "SENSOR_DETECT"):
132 | SENSOR_DETECT = int(general['SENSOR_DETECT'])
133 | else:
134 | SENSOR_DETECT = -1
135 |
136 | if keysConfig.has_option("HOTKEYS", "SAFE_SHUTDOWN"):
137 | SAFE_SHUTDOWN = int(hotkeys['SAFE_SHUTDOWN'])
138 | else:
139 | SAFE_SHUTDOWN = -1
140 |
141 | if keysConfig.has_option("HOTKEYS", "QUICKSAVE"):
142 | QUICKSAVE = int(hotkeys['QUICKSAVE'])
143 | else:
144 | QUICKSAVE = -1
145 |
146 | if keysConfig.has_option("HOTKEYS", "QUICKSAVE"):
147 | KEYS.update({int(QUICKSAVE): uinput.KEY_F2})
148 | KEYS.update({int(99): uinput.KEY_F4})
149 |
150 | # Joystick Hardware settings
151 | joystickConfig = keysConfig['JOYSTICK'] # TODO: Make this go to keys
152 | DZONE = int(joystickConfig['DEADZONE']) # dead zone applied to joystick (mV)
153 | VREF = int(joystickConfig['VCC']) # joystick Vcc (mV)
154 | JOYSTICK_ENABLED = joystickConfig['ENABLED']
155 |
156 | if JOYSTICK_ENABLED == 'True':
157 | KEYS.update({10001: uinput.ABS_X + (0, VREF, 0, 0),
158 | 10002: uinput.ABS_Y + (0, VREF, 0, 0), })
159 |
160 | # Battery config
161 | battery = generalConfig['BATTERY']
162 | monitoring_enabled = str2bool(battery['ENABLED'])
163 | batt_full = int(battery['FULL_BATT_VOLTAGE'])
164 | batt_low = int(battery['BATT_LOW_VOLTAGE'])
165 | batt_shdn = int(battery['BATT_SHUTDOWN_VOLT'])
166 |
167 | BOUNCE_TIME = 0.03 # Debounce time in seconds
168 |
169 | # GPIO Init
170 | gpio.setup(BUTTONS, gpio.IN, pull_up_down=gpio.PUD_UP)
171 |
172 | if not SHUTDOWN == -1:
173 | gpio.setup(SHUTDOWN, gpio.IN, pull_up_down=gpio.PUD_UP)
174 |
175 | if not SENSOR_DETECT == -1:
176 | gpio.setup(SENSOR_DETECT, gpio.IN, pull_up_down=gpio.PUD_UP)
177 |
178 | if keysConfig.has_option("HOTKEYS", "QUICKSAVE"):
179 | gpio.setup(int(QUICKSAVE), gpio.IN, pull_up_down=gpio.PUD_UP)
180 |
181 | # Global Variables
182 | global brightness
183 | global volt
184 | global info
185 | global wifi
186 | global volume
187 | global charge
188 | global bat
189 | global joystick
190 | global bluetooth
191 | global lowbattery
192 | global LAST_TRIGGERED_COMBO
193 | LAST_TRIGGERED_COMBO = None
194 |
195 | brightness = -1
196 | info = False
197 | volt = 410
198 | volume = 1
199 | wifi = 2
200 | charge = 0
201 | bat = 0
202 | last_bat_read = 450
203 | joystick = False
204 | showOverlay = False
205 | lowbattery = 0
206 | overrideCounter = Event()
207 |
208 | if JOYSTICK_ENABLED == 'True':
209 | joystick = True
210 |
211 | # TO DO REPLACE A LOT OF OLD CALLS WITH THE CHECK_OUTPUT
212 | if monitoring_enabled:
213 | adc = Adafruit_ADS1x15.ADS1015(address=0x48, busnum=1)
214 | else:
215 | adc = False
216 |
217 | device = uinput.Device(KEYS.values(), name="OneForAll", version=0x3)
218 |
219 | time.sleep(1)
220 |
221 |
222 | def hotkeyAction(key):
223 | if key == QUICKSAVE:
224 | return True
225 |
226 | if not gpio.input(SHOW_OSD_KEY) or (key == SHOW_OSD_KEY):
227 | if key in HOTKEYS:
228 | return True
229 |
230 | return False
231 |
232 |
233 | def handle_sensor(pin):
234 | command = "backlight"
235 | if generalConfig.has_option("GENERAL", "SENSOR_COMMAND"):
236 | command = general['SENSOR_COMMAND']
237 |
238 | if command == "backlight":
239 | global backlightSetting
240 | state = 0 if gpio.input(pin) else 1
241 | if state == 1:
242 | wiringpi.pwmWrite(13, 0)
243 | if state == 0:
244 | wiringpi.pwmWrite(13, backlightSetting)
245 |
246 | if command == "shutdown":
247 | device.emit(uinput.KEY_SPACE, state)
248 | device.emit(uinput.KEY_F2, state)
249 | doShutdown()
250 |
251 |
252 | def handle_quicksave(pin):
253 | logging.debug("Handling QUICKSAVE press")
254 | state = 0 if gpio.input(pin) else 1
255 | if not gpio.input(SHOW_OSD_KEY):
256 | logging.debug("Loading Game")
257 | device.emit(uinput.KEY_SPACE, state)
258 | device.emit(uinput.KEY_F4, state)
259 | device.syn()
260 | if gpio.input(SHOW_OSD_KEY):
261 | logging.debug("Saving Game")
262 | device.emit(uinput.KEY_SPACE, state)
263 | device.emit(uinput.KEY_F2, state)
264 | device.syn()
265 |
266 |
267 | def handle_button(pin):
268 | global showOverlay
269 | global info
270 | global LAST_TRIGGERED_COMBO
271 | time.sleep(BOUNCE_TIME)
272 | state = 0 if gpio.input(pin) else 1
273 |
274 | if state == 1:
275 | COMBO_CURRENT_KEYS.add(pin)
276 | else:
277 | COMBO_CURRENT_KEYS.discard(pin)
278 |
279 | if frozenset(COMBO_CURRENT_KEYS) in KEY_COMBOS:
280 | # If the current set of keys are in the mapping, execute the function
281 | if KEY_COMBOS[frozenset(COMBO_CURRENT_KEYS)] == LAST_TRIGGERED_COMBO:
282 | device.emit(KEY_COMBOS[frozenset(COMBO_CURRENT_KEYS)], 2)
283 | else:
284 | device.emit(KEY_COMBOS[frozenset(COMBO_CURRENT_KEYS)], 1)
285 | LAST_TRIGGERED_COMBO = KEY_COMBOS[frozenset(COMBO_CURRENT_KEYS)]
286 | else:
287 | if LAST_TRIGGERED_COMBO is not None:
288 | device.emit(LAST_TRIGGERED_COMBO, 0)
289 | LAST_TRIGGERED_COMBO = None
290 |
291 | if pin == SHOW_OSD_KEY:
292 | if state == 1:
293 | showOverlay = True
294 | try:
295 | info = showOverlay
296 | overrideCounter.set()
297 | except Exception:
298 | pass
299 | else:
300 | showOverlay = False
301 | try:
302 | info = showOverlay
303 | overrideCounter.set()
304 | except Exception:
305 | pass
306 |
307 | if not hotkeyAction(pin):
308 | key = KEYS[pin]
309 | if PREVIOUS_KEYSTATES[pin] == 1 and state == 1:
310 | device.emit(key, 2)
311 | else:
312 | device.emit(key, state)
313 | PREVIOUS_KEYSTATES.update({pin: state})
314 | time.sleep(BOUNCE_TIME)
315 | logging.debug("Pin: {}, KeyCode: {}, Event: {}".format(pin, key, 'press' if state else 'release'))
316 | else:
317 | checkKeyInputPowerSaving()
318 |
319 | device.syn()
320 | PREVIOUS_KEYSTATES.update({pin: state})
321 |
322 |
323 | def handle_shutdown(pin):
324 | state = 0 if gpio.input(pin) else 1
325 | if (state):
326 | logging.info("SHUTDOWN")
327 | doShutdown()
328 |
329 |
330 | # Initialise Safe shutdown
331 | if not SHUTDOWN == -1:
332 | gpio.add_event_detect(SHUTDOWN, gpio.BOTH, callback=handle_shutdown, bouncetime=1)
333 |
334 | if not SENSOR_DETECT == -1:
335 | gpio.add_event_detect(SENSOR_DETECT, gpio.BOTH, callback=handle_sensor, bouncetime=1)
336 |
337 | if keysConfig.has_option("HOTKEYS", "QUICKSAVE"):
338 | gpio.add_event_detect(QUICKSAVE, gpio.BOTH, callback=handle_quicksave, bouncetime=1)
339 |
340 | # Initialise Buttons
341 | for button in BUTTONS:
342 | gpio.add_event_detect(button, gpio.BOTH, callback=handle_button, bouncetime=1)
343 | logging.debug("Button: {}".format(button))
344 |
345 | for key, pin in keysConfig.items('HOTKEYS'):
346 | HOTKEYS.append(int(pin))
347 |
348 | if not int(pin) in BUTTONS and int(pin) != QUICKSAVE:
349 | if pin != -1:
350 | gpio.setup(int(pin), gpio.IN, pull_up_down=gpio.PUD_UP)
351 | gpio.add_event_detect(int(pin), gpio.BOTH, callback=handle_button, bouncetime=1)
352 |
353 | # Send centering commands
354 | device.emit(uinput.ABS_X, VREF / 2, syn=False);
355 | device.emit(uinput.ABS_Y, VREF / 2);
356 |
357 | # Set up OSD service
358 | try:
359 | if JOYSTICK_ENABLED == 'False':
360 | osd_proc = Popen([osd_path, bin_dir, "nojoystick"], shell=False, stdin=PIPE, stdout=None, stderr=None)
361 | else:
362 | osd_proc = Popen([osd_path, bin_dir, "full"], shell=False, stdin=PIPE, stdout=None, stderr=None)
363 | osd_in = osd_proc.stdin
364 | time.sleep(1)
365 | osd_poll = osd_proc.poll()
366 | if (osd_poll):
367 | logging.error("ERROR: Failed to start OSD, got return code [" + str(osd_poll) + "]\n")
368 | sys.exit(1)
369 | except Exception as e:
370 | logging.exception("ERROR: Failed start OSD binary");
371 | sys.exit(1);
372 |
373 |
374 | # Check for shutdown state
375 | def checkShdn(volt):
376 | global lowbattery
377 | global info
378 | if volt < batt_shdn:
379 | lowbattery = 1
380 | info = 1
381 | overrideCounter.set()
382 | doShutdown()
383 |
384 |
385 | # Read voltage
386 | def readVoltage():
387 | global last_bat_read;
388 | voltVal = adc.read_adc(0, gain=1)
389 | print voltVal
390 | print 'read'
391 | volt = int((float(voltVal) * (4.09 / 2047.0)) * 100)
392 |
393 | if volt < 300 or (last_bat_read > 300 and last_bat_read - volt > 6 and not last_bat_read == 450):
394 | volt = last_bat_read;
395 |
396 | last_bat_read = volt;
397 |
398 | return volt
399 |
400 |
401 | # Get voltage percent
402 | def getVoltagepercent(volt):
403 | return clamp(int(float(volt - batt_shdn) / float(batt_full - batt_shdn) * 100), 0, 100)
404 |
405 |
406 | def readVolumeLevel():
407 | process = os.popen("amixer get Master | grep 'Left:' | awk -F'[][]' '{ print $2 }'")
408 | res = process.readline()
409 | process.close()
410 |
411 | vol = 0;
412 | try:
413 | vol = int(res.replace("%", "").replace("'C\n", ""))
414 | except Exception as e:
415 | logging.info("Audio Err : " + str(e))
416 |
417 | return vol;
418 |
419 |
420 | # Read wifi (Credits: kite's SAIO project) Modified to only read, not set wifi.
421 | def readModeWifi(toggle=False):
422 | ret = 0;
423 | wifiVal = not os.path.exists(osd_path + 'wifi') # int(ser.readline().rstrip('\r\n'))
424 | if toggle:
425 | wifiVal = not wifiVal
426 | global wifi_state
427 | if (wifiVal):
428 | if os.path.exists(osd_path + 'wifi'):
429 | os.remove(osd_path + 'wifi')
430 | if (wifi_state != 'ON'):
431 | wifi_state = 'ON'
432 | logging.info("Wifi [ENABLING]")
433 | try:
434 | out = check_output(['sudo', rfkill_path, 'unblock', 'wifi'])
435 | logging.info("Wifi [" + str(out) + "]")
436 | except Exception as e:
437 | logging.info("Wifi : " + str(e))
438 | ret = wifi_warning # Get signal strength
439 |
440 | else:
441 | with open(osd_path + 'wifi', 'a'):
442 | n = 1
443 | if (wifi_state != 'OFF'):
444 | wifi_state = 'OFF'
445 | logging.info("Wifi [DISABLING]")
446 | try:
447 | out = check_output(['sudo', rfkill_path, 'block', 'wifi'])
448 | logging.info("Wifi [" + str(out) + "]")
449 | except Exception as e:
450 | logging.info("Wifi : " + str(e))
451 | ret = wifi_error
452 | return ret
453 | # check signal
454 | raw = check_output(['cat', '/proc/net/wireless'])
455 | strengthObj = re.search(r'.wlan0: \d*\s*(\d*)\.\s*[-]?(\d*)\.', raw, re.I)
456 | if strengthObj:
457 | strength = 0
458 | if (int(strengthObj.group(1)) > 0):
459 | strength = int(strengthObj.group(1))
460 | elif (int(strengthObj.group(2)) > 0):
461 | strength = int(strengthObj.group(2))
462 | logging.info("Wifi [" + str(strength) + "]strength")
463 | if (strength > 55):
464 | ret = wifi_3bar
465 | elif (strength > 40):
466 | ret = wifi_2bar
467 | elif (strength > 5):
468 | ret = wifi_1bar
469 | else:
470 | ret = wifi_warning
471 | else:
472 | logging.info("Wifi [---]strength")
473 | ret = wifi_error
474 | return ret
475 |
476 |
477 | def readModeBluetooth(toggle=False):
478 | ret = 0;
479 | BtVal = not os.path.exists(osd_path + 'bluetooth') # int(ser.readline().rstrip('\r\n'))
480 | if toggle:
481 | BtVal = not BtVal
482 | global bt_state
483 | if (BtVal):
484 | if os.path.exists(osd_path + 'bluetooth'):
485 | os.remove(osd_path + 'bluetooth')
486 | if (bt_state != 'ON'):
487 | bt_state = 'ON'
488 | logging.info("BT [ENABLING]")
489 | try:
490 | out = check_output(['sudo', rfkill_path, 'unblock', 'bluetooth'])
491 | logging.info("BT [" + str(out) + "]")
492 | except Exception as e:
493 | logging.info("BT : " + str(e))
494 | ret = wifi_warning # Get signal strength
495 |
496 | else:
497 | with open(osd_path + 'bluetooth', 'a'):
498 | n = 1
499 | if (bt_state != 'OFF'):
500 | bt_state = 'OFF'
501 | logging.info("BT [DISABLING]")
502 | try:
503 | out = check_output(['sudo', rfkill_path, 'block', 'bluetooth'])
504 | logging.info("BT [" + str(out) + "]")
505 | except Exception as e:
506 | logging.info("BT : " + str(e))
507 | ret = wifi_error
508 | return ret
509 | # check if it's enabled
510 | raw = check_output(['hcitool', 'dev'])
511 | return True if raw.find("hci0") > -1 else False
512 |
513 |
514 | # Do a shutdown
515 | def doShutdown(channel=None):
516 | # check_call("sudo killall emulationstation", shell=True)
517 | # time.sleep(1)
518 | check_call("sudo shutdown -h now", shell=True)
519 | try:
520 | sys.stdout.close()
521 | except:
522 | pass
523 | try:
524 | sys.stderr.close()
525 | except:
526 | pass
527 | sys.exit(0)
528 |
529 |
530 | # Signals the OSD binary
531 | def updateOSD(volt=0, bat=0, temp=0, wifi=0, audio=0, lowbattery=0, info=False, charge=False, bluetooth=False):
532 | global showOverlay
533 | showState = showOverlay if SHOW_OVERLAY_HOTKEY_ONLY else True
534 | commands = "s" + str(int(showState)) + " p" + str(int((backlightSetting / 1024) * 100)) + " v" + str(
535 | volt) + " b" + str(bat) + " t" + str(temp) + " w" + str(
536 | wifi) + " a" + str(
537 | audio) + " j" + ("1 " if joystick else "0 ") + " u" + ("1 " if bluetooth else "0 ") + " l" + (
538 | "1 " if lowbattery else "0 ") + " " + ("on " if info else "off ") + (
539 | "charge" if charge else "ncharge") + "\n"
540 | # print commands
541 | osd_proc.send_signal(signal.SIGUSR1)
542 | osd_in.write(commands)
543 | osd_in.flush()
544 |
545 |
546 | # Misc functions
547 | def clamp(n, minn, maxn):
548 | return max(min(maxn, n), minn)
549 |
550 |
551 | def volumeUp():
552 | global volume
553 | volume = min(100, volume + 5)
554 | os.system("amixer sset -q 'PCM' " + str(volume) + "%")
555 |
556 |
557 | def volumeDown():
558 | global volume
559 | volume = max(0, volume - 5)
560 | os.system("amixer sset -q 'PCM' " + str(volume) + "%")
561 |
562 |
563 | def inputReading():
564 | global volume
565 | global wifi
566 | global info
567 | global volt
568 | global bat
569 | global charge
570 | global joystick
571 | while (1):
572 | if joystick == True:
573 | checkJoystickInput()
574 | time.sleep(.05)
575 |
576 |
577 | def checkKeyInputPowerSaving():
578 | global info
579 | global wifi
580 | global joystick
581 | global bluetooth
582 | global bat
583 | global volume
584 | global volt
585 | global showOverlay
586 |
587 | info = showOverlay
588 | overrideCounter.set()
589 |
590 | if not gpio.input(SHOW_OSD_KEY):
591 | if not gpio.input(VOLUME_UP):
592 | volumeUp()
593 | time.sleep(0.6)
594 | elif not gpio.input(VOLUME_DOWN):
595 | volumeDown()
596 | time.sleep(0.6)
597 | elif not gpio.input(TOGGLE_WIFI):
598 | wifi = readModeWifi(True)
599 | time.sleep(0.6)
600 | elif not gpio.input(TOGGLE_JOYSTICK):
601 | joystick = not joystick
602 | time.sleep(0.6)
603 | elif not gpio.input(TOGGLE_BLE):
604 | bluetooth = readModeBluetooth(True)
605 | time.sleep(0.6)
606 | elif not gpio.input(BRIGHTNESS_UP):
607 | brightnessUp()
608 | time.sleep(0.6)
609 | elif not gpio.input(BRIGHTNESS_DOWN):
610 | brightnessDown()
611 | time.sleep(0.6)
612 | elif SAFE_SHUTDOWN != -1:
613 | if not gpio.input(SAFE_SHUTDOWN):
614 | doShutdown()
615 |
616 |
617 | def checkJoystickInput():
618 | an1 = adc.read_adc(2, gain=2 / 3);
619 | an0 = adc.read_adc(1, gain=2 / 3);
620 |
621 | logging.debug("X: {} | Y: {}".format(an0, an1))
622 | logging.debug("Above: {} | Below: {}".format((VREF / 2 + DZONE), (VREF / 2 - DZONE)))
623 |
624 | # Check and apply joystick states
625 | if (an0 > ((VREF / 2 + DZONE)) or (an0 < (VREF / 2 - DZONE))) and an0 <= VREF:
626 | val = an0 - 100 - 200 * (an0 < VREF / 2 - DZONE) + 200 * (an0 > VREF / 2 + DZONE)
627 | device.emit(uinput.ABS_X, val, syn=False)
628 | else:
629 | # Center the sticks if within deadzone
630 | device.emit(uinput.ABS_X, VREF / 2, syn=False)
631 | if ((an1 > (VREF / 2 + DZONE)) or (an1 < (VREF / 2 - DZONE))) and an1 <= VREF:
632 | valy = an1 + 100 - 200 * (an1 < VREF / 2 - DZONE) + 200 * (an1 > VREF / 2 + DZONE)
633 | device.emit(uinput.ABS_Y, valy)
634 | else:
635 | # Center the sticks if within deadzone
636 | device.emit(uinput.ABS_Y, VREF / 2)
637 |
638 |
639 | def constrain(val, min_val, max_val):
640 | return min(max_val, max(min_val, val))
641 |
642 |
643 | def brightnessUp():
644 | global backlightSetting
645 | backlightSetting = constrain(backlightSetting + 128, 0, 1024)
646 | wiringpi.pwmWrite(13, backlightSetting);
647 |
648 |
649 | def brightnessDown():
650 | global backlightSetting
651 | backlightSetting = constrain(backlightSetting - 128, 0, 1024)
652 | wiringpi.pwmWrite(13, backlightSetting);
653 |
654 |
655 | def exit_gracefully(signum=None, frame=None):
656 | gpio.cleanup
657 | osd_proc.terminate()
658 | sys.exit(0)
659 |
660 |
661 | signal.signal(signal.SIGINT, exit_gracefully)
662 | signal.signal(signal.SIGTERM, exit_gracefully)
663 |
664 | # Read Initial States
665 | volume = readVolumeLevel()
666 |
667 | wifi = readModeWifi()
668 | bluetooth = bluetooth = readModeBluetooth()
669 |
670 | if JOYSTICK_ENABLED == 'True':
671 | inputReadingThread = thread.start_new_thread(inputReading, ())
672 |
673 | try:
674 | while 1:
675 | try:
676 | if not adc == False:
677 | volt = readVoltage()
678 | bat = getVoltagepercent(volt)
679 | checkShdn(volt)
680 | updateOSD(volt, bat, 20, wifi, volume, lowbattery, info, charge, bluetooth)
681 | print 'update OSD'
682 | overrideCounter.wait(10)
683 | if overrideCounter.is_set():
684 | overrideCounter.clear()
685 | runCounter = 0;
686 |
687 | except Exception:
688 | logging.info("EXCEPTION")
689 | pass
690 |
691 | except KeyboardInterrupt:
692 | exit_gracefully()
693 |
--------------------------------------------------------------------------------
/osd/osd.c:
--------------------------------------------------------------------------------
1 | //-------------------------------------------------------------------------
2 | //
3 | //
4 | // This file originates from Vascofazza's Retropie open OSD project.
5 | // Author: Federico Scozzafava
6 | //
7 | // THIS HEADER MUST REMAIN WITH THIS FILE AT ALL TIMES
8 | //
9 | // This firmware is free software: you can redistribute it and/or modify
10 | // it under the terms of the GNU General Public License as published by
11 | // the Free Software Foundation, either version 3 of the License, or
12 | // (at your option) any later version.
13 | //
14 | // This firmware is distributed in the hope that it will be useful,
15 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | // GNU General Public License for more details.
18 | //
19 | // You should have received a copy of the GNU General Public License
20 | // along with this repo. If not, see .
21 | //
22 | //
23 | //-------------------------------------------------------------------------
24 |
25 | #define _GNU_SOURCE
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include
33 | #include
34 | #include
35 | #include "font.h"
36 | #include "imageGraphics.h"
37 | #include "imageLayer.h"
38 | #include "loadpng.h"
39 | #include
40 | #include
41 |
42 | #include "bcm_host.h"
43 |
44 | //-------------------------------------------------------------------------
45 |
46 | #define NDEBUG
47 | #define BATTERY_IMAGE "./resources/battery.png"
48 | #define CHARGE_IMAGE "./resources/plug.png"
49 | #define LOW_BATTERY_IMAGE "./resources/low-battery.png"
50 | #define INFO_IMAGE "./resources/main.png"
51 | #define INFO_NO_JOYSTICK "./resources/main_no_joystick.png"
52 | #define JOYSTICK_IMAGE "./resources/joystick.png"
53 | #define BLUETOOTH_IMAGE "./resources/bluetooth.png"
54 | #define BATTERY_TH 20
55 | #define AUDIO_IMAGES (const char*[5]){"./resources/AUD0.png","./resources/AUD25.png","./resources/AUD50.png","./resources/AUD75.png","./resources/AUD100.png"}
56 | #define WIFI_IMAGES (const char*[5]){"./resources/wifi_warning.png", "./resources/wifi_error.png", "./resources/wifi_1.png", "./resources/wifi_2.png", "./resources/wifi_3.png"}
57 |
58 | volatile bool run = true;
59 | volatile bool show = false;
60 |
61 | //-------------------------------------------------------------------------
62 |
63 | static RGBA8_T clearColor = {0,0,0,0};
64 | static RGBA8_T backgroundColour = { 0, 0, 0, 100 };
65 | static RGBA8_T textColour = { 255, 255, 255, 255 };
66 | static RGBA8_T greenColour = { 0, 255, 0, 200 };
67 | static RGBA8_T redColour = { 255, 0, 0, 200 };
68 | static int battery = 0, infos = 0, hud = 1, charge = 0, low_battery = 0, audio = 0, wifi = 0, wifi_loaded = 0, voltage = 0, backlight = 0, vol_image = 0, infos_loaded = 0, warning_loaded = 0, joystick = 0, bluetooth = 0;
69 | static float temp = 0.f;
70 |
71 | void updateInfo(IMAGE_LAYER_T*, char[]);
72 | void updateInfoText(IMAGE_LAYER_T*, bool);
73 | void getInput();
74 | void clearLayer(IMAGE_LAYER_T*);
75 | void updateBattery(float, IMAGE_LAYER_T*);
76 | char *getcwd(char *buf, size_t size);
77 |
78 | static void
79 | signalHandler(int signalNumber)
80 | {
81 | switch (signalNumber)
82 | {
83 | case SIGUSR1:
84 | getInput();
85 | break;
86 | case SIGINT:
87 | case SIGTERM:
88 |
89 | run = false;
90 | break;
91 | };
92 | }
93 |
94 | void updateBattery(float batval, IMAGE_LAYER_T* batteryLayer)
95 | {
96 | IMAGE_T *image = &(batteryLayer->image);
97 | clearImageRGB(image,&clearColor);
98 | //to config params
99 | RGBA8_T *col = battery < BATTERY_TH ? &redColour : &greenColour;
100 | imageBoxFilledRGB(image, 2,3,2+(int)round((batteryLayer->image.width-7)*batval),batteryLayer->image.height-3, col);
101 | changeSourceAndUpdateImageLayer(batteryLayer);
102 | }
103 |
104 | int getImageIconFromVolume(int vol) {
105 | if (vol == 0) {
106 | return 1;
107 | }
108 | if (vol <= 25) {
109 | return 2;
110 | }
111 | if (vol <= 50) {
112 | return 3;
113 | }
114 | if (vol <= 75) {
115 | return 4;
116 | }
117 | if (vol <= 100) {
118 | return 5;
119 | }
120 | return 1;
121 | }
122 |
123 | void getInput()
124 | {
125 | char buffer[100];
126 | char *bp = buffer;
127 | int c;
128 | while(run && '\n' != (c=fgetc(stdin)) && (bp-buffer) < sizeof(buffer))
129 | *bp++=c;
130 | *bp = 0;//terminator
131 | #ifndef NDEBUG
132 | printf("buffer: %s\n", buffer);
133 | #endif
134 | char *saveptr;
135 | char *word;
136 | char *str = buffer;
137 | while((word = strtok_r(str," ",&saveptr)))
138 | {
139 | #ifndef NDEBUG
140 | printf("word: %s\n", word);
141 | #endif
142 | str = NULL;
143 | if(word[0] == 'b')
144 | {
145 | //Battery
146 | battery = atoi(word+1);
147 | }
148 | else if(word[0] == 's')
149 | {
150 | show = atoi(word+1) > 0;
151 | }
152 | else if(word[0] == 'w')
153 | {
154 | //wifi
155 | wifi= atoi(word+1);
156 | }
157 | else if(word[0] == 'p')
158 | {
159 | //backlight setting
160 | backlight= atoi(word+1);
161 | }
162 | else if(word[0] == 'a')
163 | {
164 | //audio
165 | audio= atoi(word+1);
166 | }
167 | else if(word[0] == 'j')
168 | {
169 | joystick= atoi(word+1);
170 | }
171 | else if(word[0] == 'u')
172 | {
173 | bluetooth= atoi(word+1);
174 | }
175 | else if(word[0] == 'l')
176 | {
177 | low_battery= atoi(word+1);
178 | }
179 | else if(word[0] == 't')
180 | {
181 | //temperature
182 | temp= atof(word+1);
183 | }
184 | else if(word[0] == 'v')
185 | {
186 | //voltage
187 | voltage= atoi(word+1);
188 | }
189 | else if(!strcmp(word, "on"))
190 | {
191 | infos = 1;
192 | }
193 | else if(!strcmp(word, "off"))
194 | {
195 | infos = 0;
196 | }
197 | else if(!strcmp(word, "allon"))
198 | {
199 | hud = 1;
200 | }
201 | else if(!strcmp(word, "alloff"))
202 | {
203 | hud = 1;
204 | }
205 | else if(!strcmp(word, "charge"))
206 | {
207 | charge = 1;
208 | }
209 | else if(!strcmp(word, "ncharge"))
210 | {
211 | charge = 0;
212 | }
213 | else if(!strcmp(word,"quit"))
214 | run = false;
215 | }
216 | #ifndef NDEBUG
217 | printf("out\n");
218 | #endif
219 | }
220 |
221 | void clearLayer(IMAGE_LAYER_T *layer)
222 | {
223 | IMAGE_T *image = &(layer->image);
224 | clearImageRGB(image, &clearColor);
225 | changeSourceAndUpdateImageLayer(layer);
226 | }
227 |
228 | //-------------------------------------------------------------------------
229 |
230 | int main(int argc, char *argv[])
231 | {
232 | uint32_t displayNumber = 0;
233 |
234 | //-------------------------------------------------------------------
235 |
236 | if(argc==1) {
237 | perror("No file path provided");
238 | return 1;
239 | }
240 |
241 | chdir(argv[1]);
242 |
243 | bool no_joystick;
244 |
245 | if (strcmp( argv[2], "nojoystick") == 0) {
246 | no_joystick = true;
247 | } else
248 | {
249 | no_joystick = false;
250 | }
251 |
252 | int opt;
253 |
254 | while ((opt = getopt(argc, argv, "d:")) != -1)
255 | {
256 | switch (opt)
257 | {
258 | case 'd':
259 |
260 | displayNumber = atoi(optarg);
261 | break;
262 |
263 | default:
264 |
265 | fprintf(stderr, "Usage: %s [-d ]\n", basename(argv[0]));
266 | fprintf(stderr, " -d - Raspberry Pi display number\n");
267 | exit(EXIT_FAILURE);
268 | break;
269 | }
270 | }
271 |
272 | if (signal(SIGINT, signalHandler) == SIG_ERR)
273 | {
274 | perror("installing SIGINT signal handler");
275 | exit(EXIT_FAILURE);
276 | }
277 |
278 | //---------------------------------------------------------------------
279 |
280 | if (signal(SIGTERM, signalHandler) == SIG_ERR)
281 | {
282 | perror("installing SIGTERM signal handler");
283 | exit(EXIT_FAILURE);
284 | }
285 |
286 | //---------------------------------------------------------------------
287 |
288 | if (signal(SIGUSR1, signalHandler) == SIG_ERR)
289 | {
290 | perror("installing SIGTERM signal handler");
291 | exit(EXIT_FAILURE);
292 | }
293 |
294 | //-------------------------------------------------------------------
295 |
296 | VC_IMAGE_TYPE_T type = VC_IMAGE_RGBA32;
297 |
298 | //---------------------------------------------------------------------
299 |
300 | bcm_host_init();
301 |
302 | //---------------------------------------------------------------------
303 |
304 | DISPMANX_DISPLAY_HANDLE_T display
305 | = vc_dispmanx_display_open(displayNumber);
306 | assert(display != 0);
307 |
308 | //---------------------------------------------------------------------
309 |
310 | DISPMANX_MODEINFO_T info;
311 | int result = vc_dispmanx_display_get_info(display, &info);
312 | assert(result == 0);
313 |
314 | //---------------------------------------------------------------------
315 |
316 | static int layer = 30000;
317 |
318 | IMAGE_LAYER_T infoTextLayer;
319 | initImageLayer(&infoTextLayer,
320 | 320,
321 | 240,
322 | type);
323 | createResourceImageLayer(&infoTextLayer, layer + 4);
324 |
325 | IMAGE_LAYER_T infoLayer;
326 | initImageLayer(&infoLayer,
327 | 320,
328 | 240,
329 | type);
330 | createResourceImageLayer(&infoLayer, layer);
331 |
332 | IMAGE_LAYER_T warningLayer;
333 | initImageLayer(&warningLayer,
334 | 320,
335 | 240,
336 | type);
337 | createResourceImageLayer(&warningLayer, layer);
338 |
339 | IMAGE_LAYER_T bimageLayer;
340 | if (loadPng(&(bimageLayer.image), BATTERY_IMAGE) == false)
341 | {
342 | fprintf(stderr, "unable to load %s\n", argv[optind]);
343 | }
344 | createResourceImageLayer(&bimageLayer, layer+2);
345 |
346 | IMAGE_LAYER_T batteryLayer;
347 | initImageLayer(&batteryLayer,
348 | bimageLayer.image.width,
349 | bimageLayer.image.height,
350 | VC_IMAGE_RGBA16);
351 | createResourceImageLayer(&batteryLayer, layer+1);
352 |
353 | IMAGE_LAYER_T cimageLayer;
354 | initImageLayer(&cimageLayer,
355 | bimageLayer.image.width,
356 | bimageLayer.image.height,
357 | type);
358 | createResourceImageLayer(&cimageLayer, layer+2);
359 |
360 | IMAGE_LAYER_T wimageLayer;
361 | initImageLayer(&wimageLayer,
362 | bimageLayer.image.height,
363 | bimageLayer.image.height,
364 | type);
365 | createResourceImageLayer(&wimageLayer, layer+2);
366 |
367 | IMAGE_LAYER_T aimageLayer;
368 | IMAGE_LAYER_T joystickImageLayer;
369 | IMAGE_LAYER_T bluetoothImageLayer;
370 |
371 |
372 | initImageLayer(&aimageLayer,
373 | 22,
374 | 13,
375 | type);
376 | createResourceImageLayer(&aimageLayer, layer+2);
377 |
378 |
379 |
380 | initImageLayer(&joystickImageLayer,
381 | 11,
382 | 11,
383 | type);
384 | createResourceImageLayer(&joystickImageLayer, layer+2);
385 |
386 |
387 |
388 | initImageLayer(&bluetoothImageLayer,
389 | 15,
390 | 13,
391 | type);
392 | createResourceImageLayer(&bluetoothImageLayer, layer+2);
393 |
394 |
395 | int xOffset = info.width-bimageLayer.image.width-1;
396 | int yOffset = 1;
397 | DISPMANX_UPDATE_HANDLE_T update = vc_dispmanx_update_start(0);
398 | assert(update != 0);
399 |
400 | addElementImageLayerOffset(&infoTextLayer,
401 | (info.width - infoTextLayer.image.width) / 2,
402 | (info.height - infoTextLayer.image.height) / 2,
403 | display,
404 | update);
405 |
406 | addElementImageLayerOffset(&infoLayer,
407 | (info.width - infoLayer.image.width) / 2,
408 | (info.height - infoLayer.image.height) / 2,
409 | display,
410 | update);
411 |
412 | addElementImageLayerOffset(&warningLayer,
413 | (info.width - warningLayer.image.width) / 2,
414 | (info.height - warningLayer.image.height) / 2,
415 | display,
416 | update);
417 |
418 | addElementImageLayerOffset(&wimageLayer,
419 | xOffset-wimageLayer.image.width-2,
420 | yOffset,
421 | display,
422 | update);
423 |
424 | addElementImageLayerOffset(&aimageLayer,
425 | (xOffset-wimageLayer.image.width)-aimageLayer.image.width-7,
426 | yOffset,
427 | display,
428 | update);
429 |
430 |
431 |
432 | addElementImageLayerOffset(&joystickImageLayer,
433 | (xOffset-wimageLayer.image.width)-aimageLayer.image.width - 22,
434 | yOffset + 1,
435 | display,
436 | update);
437 |
438 | addElementImageLayerOffset(&bluetoothImageLayer,
439 | (xOffset-wimageLayer.image.width)-aimageLayer.image.width - 38,
440 | yOffset ,
441 | display,
442 | update);
443 |
444 | addElementImageLayerOffset(&batteryLayer,
445 | xOffset,
446 | yOffset,
447 | display,
448 | update);
449 | addElementImageLayerOffset(&bimageLayer,
450 | xOffset,
451 | yOffset,
452 | display,
453 | update);
454 |
455 | addElementImageLayerOffset(&cimageLayer,
456 | xOffset,
457 | yOffset,
458 | display,
459 | update);
460 |
461 | result = vc_dispmanx_update_submit_sync(update);
462 | assert(result == 0);
463 |
464 | while (run)
465 | {
466 | int sleepTime = 10000000;
467 |
468 | if(infos > 0)
469 | {
470 | sleepTime = 100000;
471 |
472 | if (no_joystick) {
473 | updateInfo(&infoLayer, INFO_NO_JOYSTICK);
474 | } else {
475 | updateInfo(&infoLayer, INFO_IMAGE);
476 | }
477 | updateInfoText(&infoTextLayer, no_joystick);
478 |
479 | }
480 | else if(infos <= 0)
481 | {
482 | clearLayer(&infoLayer);
483 | clearLayer(&infoTextLayer);
484 | infos_loaded = 0;
485 | }
486 |
487 | if (low_battery == 1) {
488 | updateWarning(&warningLayer, LOW_BATTERY_IMAGE);
489 | } else if (low_battery >= 2) {
490 | clearLayer(&warningLayer);
491 | warning_loaded = 0;
492 | }
493 |
494 | if (show) {
495 |
496 | float batval = battery/100.f;
497 | {
498 | if (loadPng(&(bimageLayer.image), BATTERY_IMAGE) == false)
499 | {
500 | fprintf(stderr, "unable to load %s\n", argv[optind]);
501 | }
502 | changeSourceAndUpdateImageLayer(&bimageLayer);
503 | updateBattery(batval, &batteryLayer);
504 | }
505 | if(charge > 0 && hud)
506 | {
507 | //TODO preload for efficiency
508 | if (loadPng(&(cimageLayer.image), CHARGE_IMAGE) == false)
509 | {
510 | fprintf(stderr, "unable to charge load %s\n", argv[optind]);
511 | }
512 | changeSourceAndUpdateImageLayer(&cimageLayer);
513 | charge = -1;
514 | }
515 | else if(!charge && hud)
516 | {
517 | clearLayer(&cimageLayer);
518 | charge = -1;
519 | }
520 | if(wifi > 0 && hud)
521 | {
522 | if (wifi_loaded == 0) {
523 | //TODO preload for efficienty
524 | if (loadPng(&(wimageLayer.image), WIFI_IMAGES[wifi-1]) == false)
525 | {
526 | fprintf(stderr, "unable to wifi load %s\n", argv[optind]);
527 | }
528 | changeSourceAndUpdateImageLayer(&wimageLayer);
529 | wifi_loaded = 1;
530 | }
531 | }
532 | else if (!wifi)
533 | {
534 | clearLayer(&wimageLayer);
535 | wifi_loaded = 0;
536 | }
537 | if(audio >= 0)
538 | {
539 | vol_image = getImageIconFromVolume(audio);
540 | //TODO preload for efficienty
541 | if (loadPng(&(aimageLayer.image), AUDIO_IMAGES[vol_image-1]) == false)
542 | {
543 | fprintf(stderr, "unable to audio load %s\n", argv[optind]);
544 | }
545 | changeSourceAndUpdateImageLayer(&aimageLayer);
546 | //audio = -1;
547 | }
548 | else if (!audio)
549 | {
550 | clearLayer(&aimageLayer);
551 | }
552 | if (!hud) {
553 | clearLayer(&batteryLayer);
554 | clearLayer(&wimageLayer);
555 | clearLayer(&aimageLayer);
556 | clearLayer(&bimageLayer);
557 | clearLayer(&cimageLayer);
558 | }
559 | if(joystick > 0) {
560 | if (loadPng(&(joystickImageLayer.image), JOYSTICK_IMAGE) == false) {
561 | fprintf(stderr, "unable to joystick load %s\n", argv[optind]);
562 | }
563 | changeSourceAndUpdateImageLayer(&joystickImageLayer);
564 | }
565 | else if(joystick <= 0) {
566 | clearLayer(&joystickImageLayer);
567 | }
568 | if(bluetooth > 0) {
569 | if (loadPng(&(bluetoothImageLayer.image), BLUETOOTH_IMAGE) == false) {
570 | fprintf(stderr, "unable to baluetooth load %s\n", argv[optind]);
571 | }
572 | changeSourceAndUpdateImageLayer(&bluetoothImageLayer);
573 | }
574 | else if(bluetooth <= 0) {
575 | clearLayer(&bluetoothImageLayer);
576 | }
577 | } else {
578 | clearLayer(&batteryLayer);
579 | clearLayer(&wimageLayer);
580 | clearLayer(&aimageLayer);
581 | clearLayer(&bimageLayer);
582 | clearLayer(&cimageLayer);
583 | clearLayer(&bluetoothImageLayer);
584 | }
585 | usleep(sleepTime);
586 | }
587 | //---------------------------------------------------------------------
588 |
589 | destroyImageLayer(&infoLayer);
590 | destroyImageLayer(&batteryLayer);
591 | destroyImageLayer(&wimageLayer);
592 |
593 | destroyImageLayer(&infoTextLayer);
594 | destroyImageLayer(&aimageLayer);
595 | destroyImageLayer(&bimageLayer);
596 | destroyImageLayer(&cimageLayer);
597 |
598 | result = vc_dispmanx_display_close(display);
599 | assert(result == 0);
600 |
601 | //---------------------------------------------------------------------
602 |
603 | return 0;
604 | }
605 |
606 | void updateInfo(IMAGE_LAYER_T *infoLayer, char imageType[])
607 | {
608 | if (infos_loaded == 0) {
609 | //clearImageRGB(image, &backgroundColour);
610 | loadPng(&(infoLayer->image), imageType);
611 | changeSourceAndUpdateImageLayer(infoLayer);
612 | infos_loaded = 1;
613 | }
614 | }
615 |
616 | void updateWarning(IMAGE_LAYER_T *infoLayer, char imageType[])
617 | {
618 | if (warning_loaded == 0) {
619 | //clearImageRGB(image, &backgroundColour);
620 | loadPng(&(infoLayer->image), imageType);
621 | changeSourceAndUpdateImageLayer(infoLayer);
622 | warning_loaded = 1;
623 | }
624 | }
625 |
626 | void updateInfoText(IMAGE_LAYER_T *infoLayer, bool no_joystick)
627 | {
628 | clearImageRGB(&(infoLayer->image), &clearColor);
629 | char volumeText[60];
630 | char wifiText[20];
631 | char joystickText[20];
632 | char bluetoothText[20];
633 | char backlightText[60];
634 | snprintf(volumeText, sizeof(volumeText),"Volume: %d%%", audio);
635 | snprintf(backlightText, sizeof(backlightText),"Backlight: %d%%", backlight);
636 |
637 | if (wifi > 0) {
638 | snprintf(wifiText, sizeof(wifiText),"WiFi Enabled");
639 | } else if (wifi <= 0) {
640 | snprintf(wifiText, sizeof(wifiText),"WiFi Disabled");
641 | }
642 |
643 |
644 | if (joystick > 0) {
645 | snprintf(joystickText, sizeof(joystickText),"Joystick Enabled");
646 | } else if (joystick <= 0) {
647 | snprintf(joystickText, sizeof(joystickText),"Joystick Disabled");
648 | }
649 |
650 | if (bluetooth > 0) {
651 | snprintf(bluetoothText, sizeof(bluetoothText),"Bluetooth Enabled");
652 | } else if (bluetooth <= 0) {
653 | snprintf(bluetoothText, sizeof(bluetoothText),"Bluetooth Disabled");
654 | }
655 |
656 | if (no_joystick == false) {
657 | drawStringRGB(137, 29, volumeText, &textColour, &(infoLayer->image));
658 | // drawStringRGB(137, 76, backlightText, &textColour, &(infoLayer->image));
659 | drawStringRGB(137, 76, volumeText, &textColour, &(infoLayer->image));
660 |
661 | drawStringRGB(137, 124, wifiText, &textColour, &(infoLayer->image));
662 | drawStringRGB(137, 167, joystickText, &textColour, &(infoLayer->image));
663 | drawStringRGB(137, 214, bluetoothText, &textColour, &(infoLayer->image));
664 | }
665 | else if (no_joystick == true) {
666 | drawStringRGB(137, 74, volumeText, &textColour, &(infoLayer->image));
667 | drawStringRGB(137, 122, volumeText, &textColour, &(infoLayer->image));
668 |
669 | drawStringRGB(137, 170, wifiText, &textColour, &(infoLayer->image));
670 | drawStringRGB(137, 214, bluetoothText, &textColour, &(infoLayer->image));
671 | }
672 |
673 | changeSourceAndUpdateImageLayer(infoLayer);
674 | }
675 |
--------------------------------------------------------------------------------