summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-05-23 17:30:58 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-07-13 22:01:33 +0100
commit4c60bc9e681865fcfc149775a1ed7ccd2613d5bf (patch)
tree99f8d91af2c171cf3843f0c14d41a20d9dc29c4f
parent3abb7c5dd5be2ec6744bfc0a80967b20f1b59e30 (diff)
downloadrockbox-4c60bc9e681865fcfc149775a1ed7ccd2613d5bf.tar.gz
rockbox-4c60bc9e681865fcfc149775a1ed7ccd2613d5bf.zip
New port: Shanling Q1 native
- Audio playback works - Touchscreen and buttons work - Bootloader works and is capable of dual boot - Plugins are working - Cabbiev2 theme has been ported - Stable for general usage Thanks to Marc Aarts for porting Cabbiev2 and plugin bitmaps. There's a few minor known issues: - Bootloader must be installed manually using 'usbboot' as there is no support in jztool yet. - Keymaps may be lacking, need further testing and feedback. - Some plugins may not be fully adapted to the screen size and could benefit from further tweaking. - LCD shows abnormal effects under some circumstances: for example, after viewing a mostly black screen an afterimage appears briefly when going back to a brightly-lit screen. Sudden power-off without proper shutdown of the backlight causes a "dissolving" effect. - CW2015 battery reporting driver is buggy, and disabled for now. Battery reporting is currently voltage-based using the AXP192. Change-Id: I635e83f02a880192c5a82cb0861ad3a61c137c3a
-rw-r--r--apps/SOURCES2
-rw-r--r--apps/features.txt8
-rw-r--r--apps/keymaps/keymap-shanlingq1.c77
-rw-r--r--apps/lang/english.lang145
-rw-r--r--apps/plugins/battery_bench.c3
-rw-r--r--apps/plugins/bitmaps/mono/SOURCES3
-rw-r--r--apps/plugins/bitmaps/native/SOURCES22
-rw-r--r--apps/plugins/bitmaps/native/bubbles_background.360x400x16.bmpbin0 -> 432054 bytes
-rw-r--r--apps/plugins/bitmaps/native/bubbles_emblem.360x400x16.bmpbin0 -> 12022 bytes
-rw-r--r--apps/plugins/bitmaps/native/invadrox_background.360x400x16.bmpbin0 -> 144634 bytes
-rw-r--r--apps/plugins/bitmaps/native/jewels.360x400x16.bmpbin0 -> 140814 bytes
-rw-r--r--apps/plugins/bitmaps/native/rockblox_background.360x400x16.bmpbin0 -> 432054 bytes
-rw-r--r--apps/plugins/bitmaps/native/sliding_puzzle.360x360x16.bmpbin0 -> 388854 bytes
-rw-r--r--apps/plugins/bitmaps/native/snake2_bottom.360x400x16.bmpbin0 -> 10854 bytes
-rw-r--r--apps/plugins/bitmaps/native/snake2_header1.360x400x16.bmpbin0 -> 41094 bytes
-rw-r--r--apps/plugins/bitmaps/native/snake2_header2.360x400x16.bmpbin0 -> 41094 bytes
-rw-r--r--apps/plugins/bitmaps/native/snake2_left.360x400x16.bmpbin0 -> 6326 bytes
-rw-r--r--apps/plugins/bitmaps/native/snake2_right.360x400x16.bmpbin0 -> 6326 bytes
-rw-r--r--apps/plugins/blackjack.c4
-rw-r--r--apps/plugins/brickmania.c3
-rw-r--r--apps/plugins/bubbles.c11
-rw-r--r--apps/plugins/calculator.c3
-rw-r--r--apps/plugins/calendar.c3
-rw-r--r--apps/plugins/chessbox/chessbox_pgn.h3
-rw-r--r--apps/plugins/chessclock.c3
-rw-r--r--apps/plugins/chip8.c3
-rw-r--r--apps/plugins/clix.c3
-rw-r--r--apps/plugins/cube.c3
-rw-r--r--apps/plugins/doom/i_video.c4
-rw-r--r--apps/plugins/flipit.c3
-rw-r--r--apps/plugins/fractals/fractal.h3
-rw-r--r--apps/plugins/imageviewer/imageviewer_button.h3
-rw-r--r--apps/plugins/invadrox.c20
-rw-r--r--apps/plugins/jewels.c3
-rw-r--r--apps/plugins/lib/keymaps.h12
-rw-r--r--apps/plugins/lib/pluginlib_actions.c2
-rw-r--r--apps/plugins/midi/midiplay.c3
-rw-r--r--apps/plugins/minesweeper.c3
-rw-r--r--apps/plugins/mp3_encoder.c3
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c3
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c3
-rw-r--r--apps/plugins/oscilloscope.c3
-rw-r--r--apps/plugins/pacbox/pacbox.h10
-rw-r--r--apps/plugins/pegbox.c3
-rw-r--r--apps/plugins/pong.c3
-rw-r--r--apps/plugins/reversi/reversi-gui.h3
-rw-r--r--apps/plugins/rockblox.c19
-rw-r--r--apps/plugins/rockboy/rockboy.c3
-rw-r--r--apps/plugins/rockpaint.c3
-rw-r--r--apps/plugins/sliding_puzzle.c3
-rw-r--r--apps/plugins/snake.c3
-rw-r--r--apps/plugins/snake2.c15
-rw-r--r--apps/plugins/sokoban.c3
-rw-r--r--apps/plugins/solitaire.c3
-rw-r--r--apps/plugins/spacerocks.c3
-rw-r--r--apps/plugins/star.c4
-rw-r--r--apps/plugins/stopwatch.lua2
-rw-r--r--apps/plugins/sudoku/sudoku.h3
-rw-r--r--apps/plugins/test_touchscreen.c5
-rw-r--r--apps/plugins/text_viewer/tv_button.h3
-rw-r--r--apps/plugins/vu_meter.c3
-rw-r--r--apps/plugins/wormlet.c6
-rw-r--r--apps/plugins/xobox.c3
-rw-r--r--apps/plugins/zxbox/keymaps.h3
-rw-r--r--apps/settings_list.c11
-rw-r--r--backdrops/cabbiev2.360x400x16.bmpbin0 -> 432054 bytes
-rw-r--r--bootloader/SOURCES2
-rw-r--r--bootloader/x1000.c11
-rw-r--r--docs/CREDITS1
-rw-r--r--firmware/SOURCES14
-rw-r--r--firmware/drivers/audio/es9218.c226
-rw-r--r--firmware/drivers/cw2015.c191
-rw-r--r--firmware/export/audiohw.h2
-rw-r--r--firmware/export/config.h4
-rw-r--r--firmware/export/config/shanlingq1.h119
-rw-r--r--firmware/export/cw2015.h57
-rw-r--r--firmware/export/es9218.h230
-rw-r--r--firmware/target/hosted/sdl/sim-ui-defines.h8
-rw-r--r--firmware/target/mips/ingenic_x1000/debug-x1000.c6
-rw-r--r--firmware/target/mips/ingenic_x1000/msc-x1000.c13
-rw-r--r--firmware/target/mips/ingenic_x1000/nand-x1000.c2
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/adc-target.h0
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c191
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/backlight-shanlingq1.c63
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/backlight-target.h33
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/boot.make31
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c195
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/button-target.h56
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/gpio-target.h32
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/i2c-target.h40
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c399
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c140
-rw-r--r--firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c116
-rw-r--r--firmware/target/mips/ingenic_x1000/spl-x1000.c2
-rwxr-xr-xtools/configure27
-rw-r--r--tools/scramble.c2
-rw-r--r--uisimulator/bitmaps/UI-shanlingq1.bmpbin0 -> 736538 bytes
-rw-r--r--uisimulator/buttonmap/SOURCES2
-rw-r--r--uisimulator/buttonmap/shanling-q1.c72
-rw-r--r--wps/AUTHORS1
-rw-r--r--wps/WPSLIST5
-rw-r--r--wps/cabbiev2.360x400x16.wps81
-rw-r--r--wps/cabbiev2/battery-360x400x16.bmpbin0 -> 58054 bytes
-rw-r--r--wps/cabbiev2/lock-360x400x16.bmpbin0 -> 6782 bytes
-rw-r--r--wps/cabbiev2/pb-360x400x16.bmpbin0 -> 6654 bytes
-rw-r--r--wps/cabbiev2/playmode-360x400x16.bmpbin0 -> 15714 bytes
-rw-r--r--wps/cabbiev2/repeat-360x400x16.bmpbin0 -> 9798 bytes
-rw-r--r--wps/cabbiev2/shuffle-360x400x16.bmpbin0 -> 4926 bytes
-rw-r--r--wps/cabbiev2/volume-360x400x16.bmpbin0 -> 44134 bytes
-rw-r--r--wps/cabbiev2/wpsbackdrop-360x400x16.bmpbin0 -> 432054 bytes
110 files changed, 2843 insertions, 15 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 5c49f0bbbc..6fdaea3ca8 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -298,4 +298,6 @@ keymaps/keymap-fiiom3klinux.c
298keymaps/keymap-fiiom3k.c 298keymaps/keymap-fiiom3k.c
299#elif CONFIG_KEYPAD == EROSQ_PAD 299#elif CONFIG_KEYPAD == EROSQ_PAD
300keymaps/keymap-erosq.c 300keymaps/keymap-erosq.c
301#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
302keymaps/keymap-shanlingq1.c
301#endif 303#endif
diff --git a/apps/features.txt b/apps/features.txt
index 4e7f986057..83c3f0a65f 100644
--- a/apps/features.txt
+++ b/apps/features.txt
@@ -182,12 +182,12 @@ depth_3d
182#endif 182#endif
183 183
184/* This should be AUDIOHW_HAVE_FILTER_ROLL_OFF but that is only defined later */ 184/* This should be AUDIOHW_HAVE_FILTER_ROLL_OFF but that is only defined later */
185#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018) || defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC) || defined(HAVE_AK4376) 185#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018) || defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC) || defined(HAVE_AK4376) || defined(HAVE_ES9218)
186filter_roll_off 186filter_roll_off
187#endif 187#endif
188 188
189/* This should be AUDIOHW_HAVE_POWER_MODE but that is not defined yet */ 189/* This should be AUDIOHW_HAVE_POWER_MODE but that is not defined yet */
190#if defined(HAVE_AK4376) 190#if defined(HAVE_AK4376) || defined(HAVE_ES9218)
191dac_power_mode 191dac_power_mode
192#endif 192#endif
193 193
@@ -195,6 +195,10 @@ dac_power_mode
195es9018 195es9018
196#endif 196#endif
197 197
198#if defined(HAVE_ES9218)
199es9218
200#endif
201
198/* These features are only used by the manual so they won't break binary 202/* These features are only used by the manual so they won't break binary
199 * compatibility 203 * compatibility
200 */ 204 */
diff --git a/apps/keymaps/keymap-shanlingq1.c b/apps/keymaps/keymap-shanlingq1.c
new file mode 100644
index 0000000000..4745139e7a
--- /dev/null
+++ b/apps/keymaps/keymap-shanlingq1.c
@@ -0,0 +1,77 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22/* Button Code Definitions for Shanling Q1 target */
23
24#include "config.h"
25#include "action.h"
26#include "button.h"
27#include "settings.h"
28
29/* {Action Code, Button code, Prereq button code } */
30
31static const struct button_mapping button_context_standard[] = {
32 {ACTION_STD_PREV, BUTTON_PREV, BUTTON_NONE},
33 {ACTION_STD_NEXT, BUTTON_NEXT, BUTTON_NONE},
34 {ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY},
35 {ACTION_STD_CANCEL, BUTTON_POWER|BUTTON_REL, BUTTON_POWER},
36 LAST_ITEM_IN_LIST
37}; /* button_context_standard */
38
39static const struct button_mapping button_context_wps[] = {
40 {ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY},
41 {ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE},
42 {ACTION_WPS_VOLUP, BUTTON_VOL_UP|BUTTON_REL, BUTTON_NONE},
43 {ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REL, BUTTON_NONE},
44 {ACTION_WPS_SKIPNEXT, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT},
45 {ACTION_WPS_SKIPPREV, BUTTON_PREV|BUTTON_REL, BUTTON_PREV},
46 {ACTION_WPS_SEEKFWD, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE},
47 {ACTION_WPS_STOPSEEK, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT|BUTTON_REPEAT},
48 {ACTION_WPS_SEEKBACK, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE},
49 {ACTION_WPS_STOPSEEK, BUTTON_PREV|BUTTON_REL, BUTTON_PREV|BUTTON_REPEAT},
50 {ACTION_STD_KEYLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER},
51 LAST_ITEM_IN_LIST
52}; /* button_context_wps */
53
54static const struct button_mapping button_context_list[] = {
55 {ACTION_LIST_VOLUP, BUTTON_VOL_UP|BUTTON_REL, BUTTON_NONE},
56 {ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REL, BUTTON_NONE},
57 LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
58}; /* button_context_list */
59
60const struct button_mapping* target_get_context_mapping(int context)
61{
62 switch (context)
63 {
64 default:
65 case CONTEXT_STD:
66 return button_context_standard;
67 case CONTEXT_WPS:
68 return button_context_wps;
69 case CONTEXT_TREE:
70 case CONTEXT_CUSTOM|CONTEXT_TREE:
71 case CONTEXT_MAINMENU:
72 case CONTEXT_BOOKMARKSCREEN:
73 //return button_context_tree;
74 case CONTEXT_LIST:
75 return button_context_list;
76 }
77}
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 4cbc6f30f6..f268434f60 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12205,20 +12205,159 @@
12205 </voice> 12205 </voice>
12206</phrase> 12206</phrase>
12207<phrase> 12207<phrase>
12208 id: LANG_FILTER_LINEAR_FAST
12209 desc: in sound settings
12210 user: core
12211 <source>
12212 *: none
12213 es9218: "Linear Fast"
12214 </source>
12215 <dest>
12216 *: none
12217 es9218: "Linear Fast"
12218 </dest>
12219 <voice>
12220 *: none
12221 es9218: "Linear Fast"
12222 </voice>
12223</phrase>
12224<phrase>
12225 id: LANG_FILTER_LINEAR_SLOW
12226 desc: in sound settings
12227 user: core
12228 <source>
12229 *: none
12230 es9218: "Linear Slow"
12231 </source>
12232 <dest>
12233 *: none
12234 es9218: "Linear Slow"
12235 </dest>
12236 <voice>
12237 *: none
12238 es9218: "Linear Slow"
12239 </voice>
12240</phrase>
12241<phrase>
12242 id: LANG_FILTER_MINIMUM_FAST
12243 desc: in sound settings
12244 user: core
12245 <source>
12246 *: none
12247 es9218: "Minimum Fast"
12248 </source>
12249 <dest>
12250 *: none
12251 es9218: "Minimum Fast"
12252 </dest>
12253 <voice>
12254 *: none
12255 es9218: "Minimum Fast"
12256 </voice>
12257</phrase>
12258<phrase>
12259 id: LANG_FILTER_MINIMUM_SLOW
12260 desc: in sound settings
12261 user: core
12262 <source>
12263 *: none
12264 es9218: "Minimum Slow"
12265 </source>
12266 <dest>
12267 *: none
12268 es9218: "Minimum Slow"
12269 </dest>
12270 <voice>
12271 *: none
12272 es9218: "Minimum Slow"
12273 </voice>
12274</phrase>
12275<phrase>
12276 id: LANG_FILTER_APODIZING_1
12277 desc: in sound settings
12278 user: core
12279 <source>
12280 *: none
12281 es9218: "Apodizing type 1"
12282 </source>
12283 <dest>
12284 *: none
12285 es9218: "Apodizing type 1"
12286 </dest>
12287 <voice>
12288 *: none
12289 es9218: "Apodizing type 1"
12290 </voice>
12291</phrase>
12292<phrase>
12293 id: LANG_FILTER_APODIZING_2
12294 desc: in sound settings
12295 user: core
12296 <source>
12297 *: none
12298 es9218: "Apodizing type 2"
12299 </source>
12300 <dest>
12301 *: none
12302 es9218: "Apodizing type 2"
12303 </dest>
12304 <voice>
12305 *: none
12306 es9218: "Apodizing type 2"
12307 </voice>
12308</phrase>
12309<phrase>
12310 id: LANG_FILTER_HYBRID_FAST
12311 desc: in sound settings
12312 user: core
12313 <source>
12314 *: none
12315 es9218: "Hybrid Fast"
12316 </source>
12317 <dest>
12318 *: none
12319 es9218: "Hybrid Fast"
12320 </dest>
12321 <voice>
12322 *: none
12323 es9218: "Hybrid Fast"
12324 </voice>
12325</phrase>
12326<phrase>
12327 id: LANG_FILTER_BRICK_WALL
12328 desc: in sound settings
12329 user: core
12330 <source>
12331 *: none
12332 es9218: "Brick Wall"
12333 </source>
12334 <dest>
12335 *: none
12336 es9218: "Brick Wall"
12337 </dest>
12338 <voice>
12339 *: none
12340 es9218: "Brick Wall"
12341 </voice>
12342</phrase>
12343<phrase>
12208 id: LANG_DAC_POWER_MODE 12344 id: LANG_DAC_POWER_MODE
12209 desc: in sound settings 12345 desc: in sound settings
12210 user: core 12346 user: core
12211 <source> 12347 <source>
12212 *: none 12348 *: none
12213 dac_power_mode: "DAC's power mode" 12349 dac_power_mode: "DAC's power mode"
12350 es9218: "DAC's output level"
12214 </source> 12351 </source>
12215 <dest> 12352 <dest>
12216 *: none 12353 *: none
12217 dac_power_mode: "DAC's power mode" 12354 dac_power_mode: "DAC's power mode"
12355 es9218: "DAC's output level"
12218 </dest> 12356 </dest>
12219 <voice> 12357 <voice>
12220 *: none 12358 *: none
12221 dac_power_mode: "DAC's power mode" 12359 dac_power_mode: "DAC's power mode"
12360 es9218: "DAC's output level"
12222 </voice> 12361 </voice>
12223</phrase> 12362</phrase>
12224<phrase> 12363<phrase>
@@ -12228,14 +12367,17 @@
12228 <source> 12367 <source>
12229 *: none 12368 *: none
12230 dac_power_mode: "High performance" 12369 dac_power_mode: "High performance"
12370 es9218: "High Gain (2 Vrms)"
12231 </source> 12371 </source>
12232 <dest> 12372 <dest>
12233 *: none 12373 *: none
12234 dac_power_mode: "High performance" 12374 dac_power_mode: "High performance"
12375 es9218: "High Gain (2 Vrms)"
12235 </dest> 12376 </dest>
12236 <voice> 12377 <voice>
12237 *: none 12378 *: none
12238 dac_power_mode: "High performance" 12379 dac_power_mode: "High performance"
12380 es9218: "High Gain (2 Vrms)"
12239 </voice> 12381 </voice>
12240</phrase> 12382</phrase>
12241<phrase> 12383<phrase>
@@ -12245,14 +12387,17 @@
12245 <source> 12387 <source>
12246 *: none 12388 *: none
12247 dac_power_mode: "Save battery" 12389 dac_power_mode: "Save battery"
12390 es9218: "Low Gain (1 Vrms)"
12248 </source> 12391 </source>
12249 <dest> 12392 <dest>
12250 *: none 12393 *: none
12251 dac_power_mode: "Save battery" 12394 dac_power_mode: "Save battery"
12395 es9218: "Low Gain (1 Vrms)"
12252 </dest> 12396 </dest>
12253 <voice> 12397 <voice>
12254 *: none 12398 *: none
12255 dac_power_mode: "Save battery" 12399 dac_power_mode: "Save battery"
12400 es9218: "Low Gain (1 Vrms)"
12256 </voice> 12401 </voice>
12257</phrase> 12402</phrase>
12258<phrase> 12403<phrase>
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index 2534e3bebe..6c477cbd09 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -234,6 +234,9 @@
234#define BATTERY_ON_TXT "Play" 234#define BATTERY_ON_TXT "Play"
235#define BATTERY_OFF_TXT "Power" 235#define BATTERY_OFF_TXT "Power"
236 236
237#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
238/* use touchscreen */
239
237#else 240#else
238#error "No keymap defined!" 241#error "No keymap defined!"
239#endif 242#endif
diff --git a/apps/plugins/bitmaps/mono/SOURCES b/apps/plugins/bitmaps/mono/SOURCES
index e6a24b2bc5..eb00bd9e8a 100644
--- a/apps/plugins/bitmaps/mono/SOURCES
+++ b/apps/plugins/bitmaps/mono/SOURCES
@@ -19,7 +19,8 @@ bubbles_bubble.138x110x1.bmp
19 ((LCD_WIDTH == 176) && (LCD_HEIGHT == 220)) 19 ((LCD_WIDTH == 176) && (LCD_HEIGHT == 220))
20bubbles_bubble.220x176x1.bmp 20bubbles_bubble.220x176x1.bmp
21#elif ((LCD_WIDTH == 320) && (LCD_HEIGHT == 240)) || \ 21#elif ((LCD_WIDTH == 320) && (LCD_HEIGHT == 240)) || \
22 ((LCD_WIDTH == 240) && (LCD_HEIGHT >= 320)) 22 ((LCD_WIDTH == 240) && (LCD_HEIGHT >= 320)) || \
23 ((LCD_WIDTH == 360) && (LCD_HEIGHT == 400))
23bubbles_bubble.320x240x1.bmp 24bubbles_bubble.320x240x1.bmp
24#elif ((LCD_WIDTH == 640) && (LCD_HEIGHT == 480)) || \ 25#elif ((LCD_WIDTH == 640) && (LCD_HEIGHT == 480)) || \
25 ((LCD_WIDTH == 480) && (LCD_HEIGHT == 640)) 26 ((LCD_WIDTH == 480) && (LCD_HEIGHT == 640))
diff --git a/apps/plugins/bitmaps/native/SOURCES b/apps/plugins/bitmaps/native/SOURCES
index 48eb18dfa4..37d0060213 100644
--- a/apps/plugins/bitmaps/native/SOURCES
+++ b/apps/plugins/bitmaps/native/SOURCES
@@ -158,6 +158,9 @@ jackpot_slots.30x420x1.bmp
158 ((LCD_WIDTH >= 480) && (LCD_HEIGHT >= 640)) 158 ((LCD_WIDTH >= 480) && (LCD_HEIGHT >= 640))
159bubbles_emblem.640x480x16.bmp 159bubbles_emblem.640x480x16.bmp
160bubbles_background.640x480x16.bmp 160bubbles_background.640x480x16.bmp
161#elif (LCD_WIDTH >= 360) && (LCD_HEIGHT >= 400)
162bubbles_emblem.360x400x16.bmp
163bubbles_background.360x400x16.bmp
161#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) 164#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
162bubbles_emblem.320x240x16.bmp 165bubbles_emblem.320x240x16.bmp
163bubbles_background.320x240x16.bmp 166bubbles_background.320x240x16.bmp
@@ -388,7 +391,9 @@ invadrox_shield.22x16x16.bmp
388invadrox_ufo.16x7x16.bmp 391invadrox_ufo.16x7x16.bmp
389invadrox_ufo_explode.21x8x16.bmp 392invadrox_ufo_explode.21x8x16.bmp
390invadrox_numbers.50x7x16.bmp 393invadrox_numbers.50x7x16.bmp
391#if LCD_WIDTH == 320 394#if LCD_WIDTH == 360 && LCD_HEIGHT == 400
395invadrox_background.360x400x16.bmp
396#elif LCD_WIDTH == 320
392invadrox_background.320x240x16.bmp 397invadrox_background.320x240x16.bmp
393#elif LCD_WIDTH == 240 398#elif LCD_WIDTH == 240
394invadrox_background.240x320x16.bmp 399invadrox_background.240x320x16.bmp
@@ -457,6 +462,8 @@ jewels.220x176x16.bmp
457jewels.320x240x16.bmp 462jewels.320x240x16.bmp
458#elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) 463#elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
459jewels.320x240x16.bmp 464jewels.320x240x16.bmp
465#elif (LCD_WIDTH == 360) && (LCD_HEIGHT == 400)
466jewels.360x400x16.bmp
460#elif ((LCD_WIDTH == 640) && (LCD_HEIGHT == 480)) || \ 467#elif ((LCD_WIDTH == 640) && (LCD_HEIGHT == 480)) || \
461 ((LCD_WIDTH == 480) && (LCD_HEIGHT == 640)) 468 ((LCD_WIDTH == 480) && (LCD_HEIGHT == 640))
462jewels.640x480x16.bmp 469jewels.640x480x16.bmp
@@ -546,6 +553,8 @@ puzzles_cursor.11x16x24.bmp
546#if LCD_DEPTH >= 16 /* colour versions*/ 553#if LCD_DEPTH >= 16 /* colour versions*/
547#if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480) 554#if (LCD_WIDTH == 640) && (LCD_HEIGHT == 480)
548rockblox_background.640x480x16.bmp 555rockblox_background.640x480x16.bmp
556#elif (LCD_WIDTH == 360) && (LCD_HEIGHT == 400)
557rockblox_background.360x400x16.bmp
549#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) 558#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
550rockblox_background.320x240x16.bmp 559rockblox_background.320x240x16.bmp
551#elif (LCD_WIDTH == 240) && (LCD_HEIGHT >= 320) 560#elif (LCD_WIDTH == 240) && (LCD_HEIGHT >= 320)
@@ -603,6 +612,12 @@ snake2_header2.640x480x16.bmp
603snake2_left.640x480x16.bmp 612snake2_left.640x480x16.bmp
604snake2_right.640x480x16.bmp 613snake2_right.640x480x16.bmp
605snake2_bottom.640x480x16.bmp 614snake2_bottom.640x480x16.bmp
615#elif (LCD_WIDTH >= 360) && (LCD_HEIGHT >= 400) && (LCD_DEPTH >= 16)
616snake2_header1.360x400x16.bmp
617snake2_header2.360x400x16.bmp
618snake2_left.360x400x16.bmp
619snake2_right.360x400x16.bmp
620snake2_bottom.360x400x16.bmp
606#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) && (LCD_DEPTH >= 16) 621#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) && (LCD_DEPTH >= 16)
607snake2_header1.320x240x16.bmp 622snake2_header1.320x240x16.bmp
608snake2_header2.320x240x16.bmp 623snake2_header2.320x240x16.bmp
@@ -874,7 +889,8 @@ superdom_boarditems.176x132x16.bmp
874#elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240) 889#elif (LCD_WIDTH == 320 && LCD_HEIGHT == 240)
875superdom_boarditems.320x240x16.bmp 890superdom_boarditems.320x240x16.bmp
876#elif ((LCD_WIDTH == 240) && (LCD_HEIGHT == 320)) || \ 891#elif ((LCD_WIDTH == 240) && (LCD_HEIGHT == 320)) || \
877 ((LCD_WIDTH == 240) && (LCD_HEIGHT == 400)) 892 ((LCD_WIDTH == 240) && (LCD_HEIGHT == 400)) || \
893 ((LCD_WIDTH == 360) && (LCD_HEIGHT == 400))
878superdom_boarditems.240x320x16.bmp 894superdom_boarditems.240x320x16.bmp
879#elif (LCD_WIDTH == 480 && LCD_HEIGHT == 640) 895#elif (LCD_WIDTH == 480 && LCD_HEIGHT == 640)
880superdom_boarditems.480x640x16.bmp 896superdom_boarditems.480x640x16.bmp
@@ -911,6 +927,8 @@ sliding_puzzle.132x132x16.bmp
911sliding_puzzle.176x176x16.bmp 927sliding_puzzle.176x176x16.bmp
912#elif SMALLER_DIMENSION <= 240 928#elif SMALLER_DIMENSION <= 240
913sliding_puzzle.240x240x16.bmp 929sliding_puzzle.240x240x16.bmp
930#elif SMALLER_DIMENSION <= 360
931sliding_puzzle.360x360x16.bmp
914#elif SMALLER_DIMENSION <= 480 932#elif SMALLER_DIMENSION <= 480
915sliding_puzzle.480x480x16.bmp 933sliding_puzzle.480x480x16.bmp
916#endif 934#endif
diff --git a/apps/plugins/bitmaps/native/bubbles_background.360x400x16.bmp b/apps/plugins/bitmaps/native/bubbles_background.360x400x16.bmp
new file mode 100644
index 0000000000..46d8133911
--- /dev/null
+++ b/apps/plugins/bitmaps/native/bubbles_background.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/bubbles_emblem.360x400x16.bmp b/apps/plugins/bitmaps/native/bubbles_emblem.360x400x16.bmp
new file mode 100644
index 0000000000..d34e466749
--- /dev/null
+++ b/apps/plugins/bitmaps/native/bubbles_emblem.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/invadrox_background.360x400x16.bmp b/apps/plugins/bitmaps/native/invadrox_background.360x400x16.bmp
new file mode 100644
index 0000000000..14c687a940
--- /dev/null
+++ b/apps/plugins/bitmaps/native/invadrox_background.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/jewels.360x400x16.bmp b/apps/plugins/bitmaps/native/jewels.360x400x16.bmp
new file mode 100644
index 0000000000..5cd35f2162
--- /dev/null
+++ b/apps/plugins/bitmaps/native/jewels.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/rockblox_background.360x400x16.bmp b/apps/plugins/bitmaps/native/rockblox_background.360x400x16.bmp
new file mode 100644
index 0000000000..b2b1289045
--- /dev/null
+++ b/apps/plugins/bitmaps/native/rockblox_background.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/sliding_puzzle.360x360x16.bmp b/apps/plugins/bitmaps/native/sliding_puzzle.360x360x16.bmp
new file mode 100644
index 0000000000..e74e3ecb6f
--- /dev/null
+++ b/apps/plugins/bitmaps/native/sliding_puzzle.360x360x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/snake2_bottom.360x400x16.bmp b/apps/plugins/bitmaps/native/snake2_bottom.360x400x16.bmp
new file mode 100644
index 0000000000..f6da503ab3
--- /dev/null
+++ b/apps/plugins/bitmaps/native/snake2_bottom.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/snake2_header1.360x400x16.bmp b/apps/plugins/bitmaps/native/snake2_header1.360x400x16.bmp
new file mode 100644
index 0000000000..f88acf2571
--- /dev/null
+++ b/apps/plugins/bitmaps/native/snake2_header1.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/snake2_header2.360x400x16.bmp b/apps/plugins/bitmaps/native/snake2_header2.360x400x16.bmp
new file mode 100644
index 0000000000..2acccd36b4
--- /dev/null
+++ b/apps/plugins/bitmaps/native/snake2_header2.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/snake2_left.360x400x16.bmp b/apps/plugins/bitmaps/native/snake2_left.360x400x16.bmp
new file mode 100644
index 0000000000..eac0c8e601
--- /dev/null
+++ b/apps/plugins/bitmaps/native/snake2_left.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/bitmaps/native/snake2_right.360x400x16.bmp b/apps/plugins/bitmaps/native/snake2_right.360x400x16.bmp
new file mode 100644
index 0000000000..316f40cb4c
--- /dev/null
+++ b/apps/plugins/bitmaps/native/snake2_right.360x400x16.bmp
Binary files differ
diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c
index 4242f5a89f..24cfbe583c 100644
--- a/apps/plugins/blackjack.c
+++ b/apps/plugins/blackjack.c
@@ -607,6 +607,10 @@ enum {
607#define BJACK_RIGHT BUTTON_RIGHT 607#define BJACK_RIGHT BUTTON_RIGHT
608#define BJACK_LEFT BUTTON_LEFT 608#define BJACK_LEFT BUTTON_LEFT
609 609
610#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
611#define BJACK_QUIT BUTTON_POWER
612#define BJACK_QUIT_NAME "QUIT"
613
610#else 614#else
611#error No keymap defined! 615#error No keymap defined!
612#endif 616#endif
diff --git a/apps/plugins/brickmania.c b/apps/plugins/brickmania.c
index 92f8d4d161..4983d5a417 100644
--- a/apps/plugins/brickmania.c
+++ b/apps/plugins/brickmania.c
@@ -350,6 +350,9 @@ CONFIG_KEYPAD == SANSA_CONNECT_PAD
350#define UP BUTTON_UP 350#define UP BUTTON_UP
351#define DOWN BUTTON_DOWN 351#define DOWN BUTTON_DOWN
352 352
353#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
354#define QUIT BUTTON_POWER
355
353#else 356#else
354#error No keymap defined! 357#error No keymap defined!
355#endif 358#endif
diff --git a/apps/plugins/bubbles.c b/apps/plugins/bubbles.c
index 50de10fa23..ffc814e7a0 100644
--- a/apps/plugins/bubbles.c
+++ b/apps/plugins/bubbles.c
@@ -120,6 +120,17 @@ enum {
120#define XOFS 128 120#define XOFS 128
121#define MAX_FPS 40 121#define MAX_FPS 40
122 122
123#elif (LCD_WIDTH == 360) && (LCD_HEIGHT == 400)
124#define XOFS 86
125#define YOFS 100
126#define SCORE_TXT_X 28
127#define SCORE_TXT_WIDTH 32
128#define SCORE_TXT_Y 48
129#define LEVEL_TXT_X 27
130#define LEVEL_TXT_WIDTH 32
131#define LEVEL_TXT_Y 5
132#define MAX_FPS 40
133
123/* 22x22 bubbles (iPod Video) */ 134/* 22x22 bubbles (iPod Video) */
124#elif (LCD_HEIGHT == 240) && (LCD_WIDTH == 320) 135#elif (LCD_HEIGHT == 240) && (LCD_WIDTH == 320)
125#define XOFS 72 136#define XOFS 72
diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c
index cbaea8aa7e..bd09330529 100644
--- a/apps/plugins/calculator.c
+++ b/apps/plugins/calculator.c
@@ -533,6 +533,9 @@ F3: equal to "="
533#define CALCULATOR_CALC BUTTON_MENU 533#define CALCULATOR_CALC BUTTON_MENU
534#define CALCULATOR_CLEAR BUTTON_BACK 534#define CALCULATOR_CLEAR BUTTON_BACK
535 535
536#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
537#define CALCULATOR_QUIT BUTTON_POWER
538
536#else 539#else
537#error No keymap defined! 540#error No keymap defined!
538#endif 541#endif
diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c
index e7f221a3c9..3299a81273 100644
--- a/apps/plugins/calendar.c
+++ b/apps/plugins/calendar.c
@@ -421,6 +421,9 @@
421#define CALENDAR_NEXT_MONTH BUTTON_VOL_UP 421#define CALENDAR_NEXT_MONTH BUTTON_VOL_UP
422#define CALENDAR_PREV_MONTH BUTTON_VOL_DOWN 422#define CALENDAR_PREV_MONTH BUTTON_VOL_DOWN
423 423
424#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
425/* use touchscreen */
426
424#else 427#else
425#error "No keypad setting." 428#error "No keypad setting."
426#endif 429#endif
diff --git a/apps/plugins/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h
index 827f045a4b..9d4f369ecc 100644
--- a/apps/plugins/chessbox/chessbox_pgn.h
+++ b/apps/plugins/chessbox/chessbox_pgn.h
@@ -581,6 +581,9 @@
581#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) 581#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT)
582#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) 582#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT)
583 583
584#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
585/* use touchscreen */
586
584#else 587#else
585#error No keymap defined! 588#error No keymap defined!
586#endif 589#endif
diff --git a/apps/plugins/chessclock.c b/apps/plugins/chessclock.c
index 91b04e713a..3d03cb9f6a 100644
--- a/apps/plugins/chessclock.c
+++ b/apps/plugins/chessclock.c
@@ -395,6 +395,9 @@
395#define CHC_SETTINGS_OK BUTTON_SELECT 395#define CHC_SETTINGS_OK BUTTON_SELECT
396#define CHC_SETTINGS_CANCEL BUTTON_POWER 396#define CHC_SETTINGS_CANCEL BUTTON_POWER
397 397
398#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
399#define CHC_QUIT BUTTON_POWER
400
398#else 401#else
399#error No keymap defined! 402#error No keymap defined!
400#endif 403#endif
diff --git a/apps/plugins/chip8.c b/apps/plugins/chip8.c
index 31866acd10..ac7f998690 100644
--- a/apps/plugins/chip8.c
+++ b/apps/plugins/chip8.c
@@ -1291,6 +1291,9 @@ CONFIG_KEYPAD == MROBE500_PAD
1291#define CHIP8_KEY6 BUTTON_RIGHT 1291#define CHIP8_KEY6 BUTTON_RIGHT
1292#define CHIP8_KEY8 BUTTON_BACK 1292#define CHIP8_KEY8 BUTTON_BACK
1293 1293
1294#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
1295/* use touchscreen */
1296
1294#else 1297#else
1295#error No keymap defined! 1298#error No keymap defined!
1296#endif 1299#endif
diff --git a/apps/plugins/clix.c b/apps/plugins/clix.c
index c127a300f2..9cd66a8034 100644
--- a/apps/plugins/clix.c
+++ b/apps/plugins/clix.c
@@ -316,6 +316,9 @@
316#define CLIX_BUTTON_RIGHT BUTTON_RIGHT 316#define CLIX_BUTTON_RIGHT BUTTON_RIGHT
317#define CLIX_BUTTON_CLICK BUTTON_SELECT 317#define CLIX_BUTTON_CLICK BUTTON_SELECT
318 318
319#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
320#define CLIX_BUTTON_QUIT BUTTON_POWER
321
319#else 322#else
320#error "no keymap" 323#error "no keymap"
321#endif 324#endif
diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c
index 857f2415d4..dfd7df8951 100644
--- a/apps/plugins/cube.c
+++ b/apps/plugins/cube.c
@@ -400,6 +400,9 @@
400#define CUBE_PAUSE BUTTON_PLAY 400#define CUBE_PAUSE BUTTON_PLAY
401#define CUBE_HIGHSPEED BUTTON_BACK 401#define CUBE_HIGHSPEED BUTTON_BACK
402 402
403#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
404/* use touchscreen */
405
403#else 406#else
404#error No keymap defined! 407#error No keymap defined!
405#endif 408#endif
diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c
index 2381a7614d..f5d07a8354 100644
--- a/apps/plugins/doom/i_video.c
+++ b/apps/plugins/doom/i_video.c
@@ -614,6 +614,10 @@ void I_ShutdownGraphics(void)
614#define DOOMBUTTON_WEAPON BUTTON_VOL_UP 614#define DOOMBUTTON_WEAPON BUTTON_VOL_UP
615#define DOOMBUTTON_MAP BUTTON_VOL_DOWN 615#define DOOMBUTTON_MAP BUTTON_VOL_DOWN
616 616
617#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
618#define DOOMBUTTON_ESC BUTTON_POWER
619#define DOOMBUTTON_MAP BUTTON_PREV
620
617#else 621#else
618#error Keymap not defined! 622#error Keymap not defined!
619#endif 623#endif
diff --git a/apps/plugins/flipit.c b/apps/plugins/flipit.c
index f6fb059f91..c659cf5ba5 100644
--- a/apps/plugins/flipit.c
+++ b/apps/plugins/flipit.c
@@ -496,6 +496,9 @@
496#define FLIPIT_STEP_BY_STEP BUTTON_VOL_UP 496#define FLIPIT_STEP_BY_STEP BUTTON_VOL_UP
497#define FLIPIT_TOGGLE BUTTON_SELECT 497#define FLIPIT_TOGGLE BUTTON_SELECT
498 498
499#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
500/* use touchscreen */
501
499#else 502#else
500#error No keymap defined! 503#error No keymap defined!
501#endif 504#endif
diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h
index b64bf942fe..8e9446df0d 100644
--- a/apps/plugins/fractals/fractal.h
+++ b/apps/plugins/fractals/fractal.h
@@ -504,6 +504,9 @@
504#define FRACTAL_PRECISION_DEC BUTTON_BACK 504#define FRACTAL_PRECISION_DEC BUTTON_BACK
505#define FRACTAL_RESET BUTTON_PLAY 505#define FRACTAL_RESET BUTTON_PLAY
506 506
507#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
508#define FRACTAL_QUIT BUTTON_POWER
509
507#else 510#else
508#error No keymap defined! 511#error No keymap defined!
509#endif 512#endif
diff --git a/apps/plugins/imageviewer/imageviewer_button.h b/apps/plugins/imageviewer/imageviewer_button.h
index d588de95ca..e6cd2ac089 100644
--- a/apps/plugins/imageviewer/imageviewer_button.h
+++ b/apps/plugins/imageviewer/imageviewer_button.h
@@ -539,6 +539,9 @@
539#define IMGVIEW_MENU BUTTON_POWER 539#define IMGVIEW_MENU BUTTON_POWER
540#define IMGVIEW_SLIDE_SHOW BUTTON_PLAY 540#define IMGVIEW_SLIDE_SHOW BUTTON_PLAY
541 541
542#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
543/* use touchscreen */
544
542#else 545#else
543#error No keymap defined! 546#error No keymap defined!
544#endif 547#endif
diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c
index c28ab7e830..5eedb6ffc5 100644
--- a/apps/plugins/invadrox.c
+++ b/apps/plugins/invadrox.c
@@ -296,6 +296,9 @@ CONFIG_KEYPAD == MROBE500_PAD
296#define RIGHT BUTTON_RIGHT 296#define RIGHT BUTTON_RIGHT
297#define FIRE BUTTON_SELECT 297#define FIRE BUTTON_SELECT
298 298
299#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
300/* use touchscreen */
301
299#else 302#else
300 #error INVADROX: Unsupported keypad 303 #error INVADROX: Unsupported keypad
301#endif 304#endif
@@ -648,6 +651,23 @@ CONFIG_KEYPAD == MROBE500_PAD
648#define LIVES_X 8 651#define LIVES_X 8
649#define MAX_Y 15 652#define MAX_Y 15
650 653
654#elif (LCD_WIDTH == 360) && (LCD_HEIGHT == 400)
655
656/* Shanling Q1
657 */
658#define ARCADISH_GRAPHICS
659#define PLAYFIELD_X 32
660#define SHIP_Y (PLAYFIELD_Y - 3 * SHIP_HEIGHT)
661#define ALIEN_START_Y (UFO_Y + 3 * ALIEN_HEIGHT)
662/* Redefine SCORE_Y */
663#undef SCORE_Y
664#define SCORE_Y 80
665#define SCORENUM_X (PLAYFIELD_X + NUMBERS_WIDTH)
666#define SCORENUM_Y SCORE_Y + (2 * (FONT_HEIGHT + 1) + 1)
667#define HISCORENUM_X (LCD_WIDTH - PLAYFIELD_X - 1 - 6 * NUMBERS_WIDTH - 5 * NUM_SPACING)
668#define SHIELD_Y (PLAYFIELD_Y - 6 * SHIP_HEIGHT)
669#define LIVES_X 10
670#define MAX_Y 18
651 671
652#else 672#else
653 #error INVADROX: Unsupported LCD type 673 #error INVADROX: Unsupported LCD type
diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c
index 7f7965b07d..3f209ae556 100644
--- a/apps/plugins/jewels.c
+++ b/apps/plugins/jewels.c
@@ -377,6 +377,9 @@ CONFIG_KEYPAD == MROBE500_PAD
377#define HK_SELECT "SELECT" 377#define HK_SELECT "SELECT"
378#define HK_CANCEL "BACK" 378#define HK_CANCEL "BACK"
379 379
380#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
381/* use touchscreen */
382
380#else 383#else
381#error No keymap defined! 384#error No keymap defined!
382#endif 385#endif
diff --git a/apps/plugins/lib/keymaps.h b/apps/plugins/lib/keymaps.h
index b660d4d85e..2cbca9e5ad 100644
--- a/apps/plugins/lib/keymaps.h
+++ b/apps/plugins/lib/keymaps.h
@@ -255,6 +255,15 @@
255#define BTN_FIRE BUTTON_SELECT 255#define BTN_FIRE BUTTON_SELECT
256#define BTN_PAUSE BUTTON_POWER 256#define BTN_PAUSE BUTTON_POWER
257 257
258#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
259#define BTN_FIRE BUTTON_CENTER
260#define BTN_PAUSE BUTTON_POWER
261#define BTN_HAVE_DIAGONAL
262#define BTN_DOWN_LEFT BUTTON_BOTTOMLEFT
263#define BTN_DOWN_RIGHT BUTTON_BOTTOMRIGHT
264#define BTN_UP_LEFT BUTTON_TOPLEFT
265#define BTN_UP_RIGHT BUTTON_TOPRIGHT
266
258#else 267#else
259#error Unsupported keypad 268#error Unsupported keypad
260#endif 269#endif
@@ -272,7 +281,8 @@
272#elif (CONFIG_KEYPAD != COWON_D2_PAD) && \ 281#elif (CONFIG_KEYPAD != COWON_D2_PAD) && \
273 (CONFIG_KEYPAD != DX50_PAD) && \ 282 (CONFIG_KEYPAD != DX50_PAD) && \
274 (CONFIG_KEYPAD != ONDAVX777_PAD) && \ 283 (CONFIG_KEYPAD != ONDAVX777_PAD) && \
275 (CONFIG_KEYPAD != CREATIVE_ZENXFI2_PAD) 284 (CONFIG_KEYPAD != CREATIVE_ZENXFI2_PAD) && \
285 (CONFIG_KEYPAD != SHANLING_Q1_PAD)
276#define BTN_FIRE BUTTON_BOTTOMLEFT 286#define BTN_FIRE BUTTON_BOTTOMLEFT
277#define BTN_PAUSE BUTTON_TOPLEFT 287#define BTN_PAUSE BUTTON_TOPLEFT
278#endif 288#endif
diff --git a/apps/plugins/lib/pluginlib_actions.c b/apps/plugins/lib/pluginlib_actions.c
index 028472d9a8..4115177eaa 100644
--- a/apps/plugins/lib/pluginlib_actions.c
+++ b/apps/plugins/lib/pluginlib_actions.c
@@ -499,6 +499,8 @@ const struct button_mapping pla_main_ctx[] =
499 {PLA_SELECT, BUTTON_SELECT, BUTTON_NONE}, 499 {PLA_SELECT, BUTTON_SELECT, BUTTON_NONE},
500 {PLA_SELECT_REL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, 500 {PLA_SELECT_REL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT},
501 {PLA_SELECT_REPEAT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE}, 501 {PLA_SELECT_REPEAT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE},
502#elif (CONFIG_KEYPAD == SHANLING_Q1_PAD)
503 {PLA_EXIT, BUTTON_POWER, BUTTON_NONE},
502#else 504#else
503# ifndef HAVE_TOUCHSCREEN 505# ifndef HAVE_TOUCHSCREEN
504# error pluginlib_actions: No actions defined 506# error pluginlib_actions: No actions defined
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c
index a28d1d3862..6345d3c741 100644
--- a/apps/plugins/midi/midiplay.c
+++ b/apps/plugins/midi/midiplay.c
@@ -325,6 +325,9 @@
325#define MIDI_VOL_DOWN BUTTON_VOL_DOWN 325#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
326#define MIDI_PLAYPAUSE BUTTON_PLAY 326#define MIDI_PLAYPAUSE BUTTON_PLAY
327 327
328#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
329/* use touchscreen */
330
328#else 331#else
329#error No keymap defined! 332#error No keymap defined!
330#endif 333#endif
diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c
index 19a6b99f12..a3c718d79f 100644
--- a/apps/plugins/minesweeper.c
+++ b/apps/plugins/minesweeper.c
@@ -443,6 +443,9 @@ CONFIG_KEYPAD == MROBE500_PAD
443# define MINESWP_DISCOVER (BUTTON_SELECT|BUTTON_REPEAT) 443# define MINESWP_DISCOVER (BUTTON_SELECT|BUTTON_REPEAT)
444# define MINESWP_INFO BUTTON_MENU 444# define MINESWP_INFO BUTTON_MENU
445 445
446#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
447/* use touchscreen */
448
446#else 449#else
447#error No keymap defined! 450#error No keymap defined!
448#endif 451#endif
diff --git a/apps/plugins/mp3_encoder.c b/apps/plugins/mp3_encoder.c
index db10185c91..99671815ca 100644
--- a/apps/plugins/mp3_encoder.c
+++ b/apps/plugins/mp3_encoder.c
@@ -2580,6 +2580,9 @@ CONFIG_KEYPAD == MROBE500_PAD
2580#define MP3ENC_DONE BUTTON_POWER 2580#define MP3ENC_DONE BUTTON_POWER
2581#define MP3ENC_SELECT BUTTON_SELECT 2581#define MP3ENC_SELECT BUTTON_SELECT
2582 2582
2583#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
2584/* use touchscreen */
2585
2583#else 2586#else
2584#error No keymap defined! 2587#error No keymap defined!
2585#endif 2588#endif
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c
index 505f3aa33d..b1445781d0 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.c
+++ b/apps/plugins/mpegplayer/mpeg_settings.c
@@ -354,6 +354,9 @@ struct mpeg_settings settings;
354#define MPEG_START_TIME_DOWN BUTTON_DOWN 354#define MPEG_START_TIME_DOWN BUTTON_DOWN
355#define MPEG_START_TIME_EXIT BUTTON_POWER 355#define MPEG_START_TIME_EXIT BUTTON_POWER
356 356
357#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
358#define MPEG_START_TIME_EXIT BUTTON_POWER
359
357#else 360#else
358#error No keymap defined! 361#error No keymap defined!
359#endif 362#endif
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 34eafd5d9c..e66b4df146 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -486,6 +486,9 @@ CONFIG_KEYPAD == SANSA_M200_PAD
486#define MPEG_RW BUTTON_LEFT 486#define MPEG_RW BUTTON_LEFT
487#define MPEG_FF BUTTON_RIGHT 487#define MPEG_FF BUTTON_RIGHT
488 488
489#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
490/* use touchscreen */
491
489#else 492#else
490#error No keymap defined! 493#error No keymap defined!
491#endif 494#endif
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index 881295d6ab..ae84e14f7f 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -548,6 +548,9 @@
548#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP 548#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
549#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN 549#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
550 550
551#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
552/* use touchscreen */
553
551#else 554#else
552#error No keymap defined! 555#error No keymap defined!
553#endif 556#endif
diff --git a/apps/plugins/pacbox/pacbox.h b/apps/plugins/pacbox/pacbox.h
index a3d42b099c..aa8c41fa95 100644
--- a/apps/plugins/pacbox/pacbox.h
+++ b/apps/plugins/pacbox/pacbox.h
@@ -398,6 +398,16 @@
398#define PACMAN_1UP BUTTON_VOL_UP 398#define PACMAN_1UP BUTTON_VOL_UP
399#define PACMAN_COIN BUTTON_PLAY 399#define PACMAN_COIN BUTTON_PLAY
400 400
401#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
402#define PACMAN_UP BUTTON_TOPMIDDLE
403#define PACMAN_DOWN BUTTON_BOTTOMMIDDLE
404#define PACMAN_LEFT BUTTON_MIDLEFT
405#define PACMAN_RIGHT BUTTON_MIDRIGHT
406#define PACMAN_MENU BUTTON_TOPLEFT
407#define PACMAN_1UP BUTTON_BOTTOMLEFT
408#define PACMAN_2UP BUTTON_BOTTOMRIGHT
409#define PACMAN_COIN BUTTON_CENTER
410
401#else 411#else
402 412
403#error Keymap not defined! 413#error Keymap not defined!
diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c
index f089c38023..cb6361547d 100644
--- a/apps/plugins/pegbox.c
+++ b/apps/plugins/pegbox.c
@@ -711,6 +711,9 @@ CONFIG_KEYPAD == MROBE500_PAD
711#define LVL_UP_TEXT "VOL+" 711#define LVL_UP_TEXT "VOL+"
712#define LVL_DOWN_TEXT "VOL-" 712#define LVL_DOWN_TEXT "VOL-"
713 713
714#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
715/* use touchscreen */
716
714#else 717#else
715#error "Unsupported keymap!" 718#error "Unsupported keymap!"
716#endif 719#endif
diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c
index 22484d0bc9..4a2c48e94c 100644
--- a/apps/plugins/pong.c
+++ b/apps/plugins/pong.c
@@ -325,6 +325,9 @@ CONFIG_KEYPAD == MROBE500_PAD
325#define PONG_RIGHT_UP BUTTON_BACK 325#define PONG_RIGHT_UP BUTTON_BACK
326#define PONG_RIGHT_DOWN BUTTON_RIGHT 326#define PONG_RIGHT_DOWN BUTTON_RIGHT
327 327
328#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
329/* use touchscreen */
330
328#else 331#else
329#error No keymap defined! 332#error No keymap defined!
330#endif 333#endif
diff --git a/apps/plugins/reversi/reversi-gui.h b/apps/plugins/reversi/reversi-gui.h
index 7e031e6103..926a71e1a2 100644
--- a/apps/plugins/reversi/reversi-gui.h
+++ b/apps/plugins/reversi/reversi-gui.h
@@ -361,6 +361,9 @@
361#define REVERSI_BUTTON_MAKE_MOVE BUTTON_SELECT 361#define REVERSI_BUTTON_MAKE_MOVE BUTTON_SELECT
362#define REVERSI_BUTTON_MENU BUTTON_MENU 362#define REVERSI_BUTTON_MENU BUTTON_MENU
363 363
364#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
365/* use touchscreen */
366
364#else 367#else
365#error No keymap defined! 368#error No keymap defined!
366#endif 369#endif
diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c
index 07a15bfb62..927710b37b 100644
--- a/apps/plugins/rockblox.c
+++ b/apps/plugins/rockblox.c
@@ -465,6 +465,9 @@
465#define ROCKBLOX_DROP BUTTON_PLAY 465#define ROCKBLOX_DROP BUTTON_PLAY
466#define ROCKBLOX_RESTART BUTTON_BACK 466#define ROCKBLOX_RESTART BUTTON_BACK
467 467
468#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
469/* use touchscreen */
470
468#else 471#else
469#error No keymap defined! 472#error No keymap defined!
470#endif 473#endif
@@ -534,6 +537,22 @@
534#define LEVEL_Y 142 537#define LEVEL_Y 142
535#define LINES_Y 218 538#define LINES_Y 218
536 539
540#elif (LCD_WIDTH == 360) && (LCD_HEIGHT == 400)
541
542#define BLOCK_WIDTH 19
543#define BLOCK_HEIGHT 19
544#define BOARD_X 27
545#define BOARD_Y 0
546#define LABEL_X 258
547#define SCORE_Y 40
548#define LEVEL_Y 92
549#define LINES_Y 140
550#define HIGH_LABEL_X 258
551#define HIGH_SCORE_Y 200
552#define HIGH_LEVEL_Y 258
553#define PREVIEW_X 258
554#define PREVIEW_Y 300
555
537#elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240) 556#elif (LCD_WIDTH == 320) && (LCD_HEIGHT == 240)
538 557
539#define BLOCK_WIDTH 12 558#define BLOCK_WIDTH 12
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c
index d2c56ff6cc..2c5c6e4dbf 100644
--- a/apps/plugins/rockboy/rockboy.c
+++ b/apps/plugins/rockboy/rockboy.c
@@ -468,6 +468,9 @@ static void setoptions (void)
468 options.SELECT = BUTTON_VOL_UP; 468 options.SELECT = BUTTON_VOL_UP;
469 options.MENU = BUTTON_POWER; 469 options.MENU = BUTTON_POWER;
470 470
471#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
472 /* use touchscreen */
473
471#else 474#else
472#error No Keymap Defined! 475#error No Keymap Defined!
473#endif 476#endif
diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c
index 0d3211d4d2..98fdb468d3 100644
--- a/apps/plugins/rockpaint.c
+++ b/apps/plugins/rockpaint.c
@@ -404,6 +404,9 @@
404#define ROCKPAINT_LEFT BUTTON_LEFT 404#define ROCKPAINT_LEFT BUTTON_LEFT
405#define ROCKPAINT_RIGHT BUTTON_RIGHT 405#define ROCKPAINT_RIGHT BUTTON_RIGHT
406 406
407#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
408/* use touchscreen */
409
407#else 410#else
408#error "Please define keys for this keypad" 411#error "Please define keys for this keypad"
409#endif 412#endif
diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c
index d1820b2f50..a34cb77669 100644
--- a/apps/plugins/sliding_puzzle.c
+++ b/apps/plugins/sliding_puzzle.c
@@ -357,6 +357,9 @@ CONFIG_KEYPAD == MROBE500_PAD
357#define PUZZLE_SHUFFLE BUTTON_BACK 357#define PUZZLE_SHUFFLE BUTTON_BACK
358#define PUZZLE_PICTURE BUTTON_PLAY 358#define PUZZLE_PICTURE BUTTON_PLAY
359 359
360#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
361/* use touchscreen */
362
360#else 363#else
361#error No keymap defined! 364#error No keymap defined!
362#endif 365#endif
diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c
index 459d345fa2..25c89b264b 100644
--- a/apps/plugins/snake.c
+++ b/apps/plugins/snake.c
@@ -313,6 +313,9 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left;
313#define SNAKE_DOWN BUTTON_DOWN 313#define SNAKE_DOWN BUTTON_DOWN
314#define SNAKE_PLAYPAUSE BUTTON_PLAY 314#define SNAKE_PLAYPAUSE BUTTON_PLAY
315 315
316#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
317/* use touchscreen */
318
316#else 319#else
317#error No keymap defined! 320#error No keymap defined!
318#endif 321#endif
diff --git a/apps/plugins/snake2.c b/apps/plugins/snake2.c
index 1536840daf..094fd854eb 100644
--- a/apps/plugins/snake2.c
+++ b/apps/plugins/snake2.c
@@ -62,6 +62,18 @@ Head and Tail are stored
62 #define TOP_X4 548 /* x-coord of the lowerright item (hi-score) */ 62 #define TOP_X4 548 /* x-coord of the lowerright item (hi-score) */
63 #define TOP_Y1 8 /* y-coord of the top row of items */ 63 #define TOP_Y1 8 /* y-coord of the top row of items */
64 #define TOP_Y2 50 /* y-coord of the bottom row of items */ 64 #define TOP_Y2 50 /* y-coord of the bottom row of items */
65#elif (LCD_WIDTH >= 360) && (LCD_HEIGHT >= 400)
66 #define MULTIPLIER 12 /*Modifier for porting on other screens*/
67 #define MODIFIER_1 12
68 #define MODIFIER_2 10
69 #define CENTER_X 12
70 #define CENTER_Y 40
71 #define TOP_X1 34 /* x-coord of the upperleft item (game type) */
72 #define TOP_X2 320 /* x-coord of the upperright item (maze type) */
73 #define TOP_X3 42 /* x-coord of the lowerleft item (speed) */
74 #define TOP_X4 314 /* x-coord of the lowerright item (hi-score) */
75 #define TOP_Y1 4 /* y-coord of the top row of items */
76 #define TOP_Y2 25 /* y-coord of the bottom row of items */
65#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240) 77#elif (LCD_WIDTH >= 320) && (LCD_HEIGHT >= 240)
66 #define MULTIPLIER 10 /*Modifier for porting on other screens*/ 78 #define MULTIPLIER 10 /*Modifier for porting on other screens*/
67 #define MODIFIER_1 10 79 #define MODIFIER_1 10
@@ -446,6 +458,9 @@ CONFIG_KEYPAD == MROBE500_PAD
446#define SNAKE2_PLAYPAUSE BUTTON_PLAY 458#define SNAKE2_PLAYPAUSE BUTTON_PLAY
447#define SNAKE2_PLAYPAUSE_TEXT "PLAY" 459#define SNAKE2_PLAYPAUSE_TEXT "PLAY"
448 460
461#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
462/* use touchscreen */
463
449#else 464#else
450#error No keymap defined! 465#error No keymap defined!
451#endif 466#endif
diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c
index 41c671a38c..247663a5c2 100644
--- a/apps/plugins/sokoban.c
+++ b/apps/plugins/sokoban.c
@@ -696,6 +696,9 @@
696#define BUTTON_SAVE BUTTON_BACK 696#define BUTTON_SAVE BUTTON_BACK
697#define BUTTON_SAVE_NAME "BACK" 697#define BUTTON_SAVE_NAME "BACK"
698 698
699#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
700/* use touchscreen */
701
699#else 702#else
700#error No keymap defined! 703#error No keymap defined!
701#endif 704#endif
diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c
index 2d737df678..a48bfbc9be 100644
--- a/apps/plugins/solitaire.c
+++ b/apps/plugins/solitaire.c
@@ -741,6 +741,9 @@ CONFIG_KEYPAD == MROBE500_PAD
741# define HK_CUR2STACK "HOLD SELECT" 741# define HK_CUR2STACK "HOLD SELECT"
742# define HK_REM2STACK "VOL+" 742# define HK_REM2STACK "VOL+"
743 743
744#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
745# define SOL_QUIT BUTTON_POWER
746
744#else 747#else
745#error No keymap defined! 748#error No keymap defined!
746#endif 749#endif
diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c
index 2d39c26b3d..8203fad612 100644
--- a/apps/plugins/spacerocks.c
+++ b/apps/plugins/spacerocks.c
@@ -372,6 +372,9 @@
372#define AST_RIGHT BUTTON_RIGHT 372#define AST_RIGHT BUTTON_RIGHT
373#define AST_FIRE BUTTON_PLAY 373#define AST_FIRE BUTTON_PLAY
374 374
375#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
376/* use touchscreen */
377
375#else 378#else
376#error No keymap defined! 379#error No keymap defined!
377#endif 380#endif
diff --git a/apps/plugins/star.c b/apps/plugins/star.c
index c186474ae3..874afc1cf1 100644
--- a/apps/plugins/star.c
+++ b/apps/plugins/star.c
@@ -668,6 +668,10 @@
668#define STAR_LEVEL_DOWN_NAME "VOL-" 668#define STAR_LEVEL_DOWN_NAME "VOL-"
669#define STAR_LEVEL_REPEAT_NAME "BACK" 669#define STAR_LEVEL_REPEAT_NAME "BACK"
670 670
671#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
672#define STAR_QUIT BUTTON_POWER
673#define STAR_QUIT_NAME "POWER"
674
671#else 675#else
672#error No keymap defined! 676#error No keymap defined!
673#endif 677#endif
diff --git a/apps/plugins/stopwatch.lua b/apps/plugins/stopwatch.lua
index 578ba7f42c..34a3c57d72 100644
--- a/apps/plugins/stopwatch.lua
+++ b/apps/plugins/stopwatch.lua
@@ -280,7 +280,7 @@ function arrangeButtons(btns)
280 end 280 end
281end 281end
282 282
283rb.touchscreen_set_mode(rb.TOUCHSCREEN_POINT) 283rb.touchscreen_mode(rb.TOUCHSCREEN_POINT)
284 284
285LapsView:init() 285LapsView:init()
286 286
diff --git a/apps/plugins/sudoku/sudoku.h b/apps/plugins/sudoku/sudoku.h
index 1332a9a80f..e06581fdc9 100644
--- a/apps/plugins/sudoku/sudoku.h
+++ b/apps/plugins/sudoku/sudoku.h
@@ -460,6 +460,9 @@
460#define SUDOKU_BUTTON_MENU BUTTON_MENU 460#define SUDOKU_BUTTON_MENU BUTTON_MENU
461#define SUDOKU_BUTTON_POSSIBLE BUTTON_BACK 461#define SUDOKU_BUTTON_POSSIBLE BUTTON_BACK
462 462
463#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
464/* use touchscreen */
465
463#else 466#else
464#error No keymap defined! 467#error No keymap defined!
465#endif 468#endif
diff --git a/apps/plugins/test_touchscreen.c b/apps/plugins/test_touchscreen.c
index 120ca8ac34..0d8e91f6a9 100644
--- a/apps/plugins/test_touchscreen.c
+++ b/apps/plugins/test_touchscreen.c
@@ -37,12 +37,17 @@
37#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD 37#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD
38#define TOUCHSCREEN_QUIT BUTTON_POWER 38#define TOUCHSCREEN_QUIT BUTTON_POWER
39#define TOUCHSCREEN_TOGGLE BUTTON_MENU 39#define TOUCHSCREEN_TOGGLE BUTTON_MENU
40#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
41#define TOUCHSCREEN_QUIT BUTTON_POWER
42#define TOUCHSCREEN_TOGGLE BUTTON_PLAY
40#elif (CONFIG_KEYPAD == ANDROID_PAD) 43#elif (CONFIG_KEYPAD == ANDROID_PAD)
41#define TOUCHSCREEN_QUIT BUTTON_BACK 44#define TOUCHSCREEN_QUIT BUTTON_BACK
42#define TOUCHSCREEN_TOGGLE BUTTON_MENU 45#define TOUCHSCREEN_TOGGLE BUTTON_MENU
43#elif (CONFIG_KEYPAD == SDL_PAD) 46#elif (CONFIG_KEYPAD == SDL_PAD)
44#define TOUCHSCREEN_QUIT BUTTON_MIDLEFT 47#define TOUCHSCREEN_QUIT BUTTON_MIDLEFT
45#define TOUCHSCREEN_TOGGLE BUTTON_CENTER 48#define TOUCHSCREEN_TOGGLE BUTTON_CENTER
49#else
50# error "No keymap defined!"
46#endif 51#endif
47 52
48/* plugin entry point */ 53/* plugin entry point */
diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h
index d9a57d114f..4d45fbba03 100644
--- a/apps/plugins/text_viewer/tv_button.h
+++ b/apps/plugins/text_viewer/tv_button.h
@@ -572,6 +572,9 @@
572#define TV_LINE_DOWN BUTTON_SCROLL_FWD 572#define TV_LINE_DOWN BUTTON_SCROLL_FWD
573#define TV_BOOKMARK BUTTON_PLAY 573#define TV_BOOKMARK BUTTON_PLAY
574 574
575#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
576#define TV_BOOKMARK BUTTON_PLAY
577
575#else 578#else
576#error No keymap defined! 579#error No keymap defined!
577#endif 580#endif
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c
index e24ad8dcdc..356a7fdd93 100644
--- a/apps/plugins/vu_meter.c
+++ b/apps/plugins/vu_meter.c
@@ -452,6 +452,9 @@
452#define LABEL_MENU "MENU" 452#define LABEL_MENU "MENU"
453#define LABEL_VOLUME "VOL+/VOL-" 453#define LABEL_VOLUME "VOL+/VOL-"
454 454
455#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
456/* use touchscreen */
457
455#else 458#else
456#error No keymap defined! 459#error No keymap defined!
457#endif 460#endif
diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c
index d76f6a7d5a..162cea6208 100644
--- a/apps/plugins/wormlet.c
+++ b/apps/plugins/wormlet.c
@@ -407,6 +407,9 @@ CONFIG_KEYPAD == MROBE500_PAD
407#define BTN_QUIT BUTTON_POWER 407#define BTN_QUIT BUTTON_POWER
408#define BTN_STOPRESET BUTTON_BACK 408#define BTN_STOPRESET BUTTON_BACK
409 409
410#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
411/* use touchscreen */
412
410#else 413#else
411#error No keymap defined! 414#error No keymap defined!
412#endif 415#endif
@@ -492,7 +495,8 @@ CONFIG_KEYPAD == MROBE500_PAD
492#define SPEED 4 495#define SPEED 4
493#define MAX_WORM_SEGMENTS 512 496#define MAX_WORM_SEGMENTS 512
494#elif ((LCD_WIDTH == 320) && (LCD_HEIGHT == 240)) || \ 497#elif ((LCD_WIDTH == 320) && (LCD_HEIGHT == 240)) || \
495 ((LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))) 498 ((LCD_WIDTH == 240) && ((LCD_HEIGHT == 320) || (LCD_HEIGHT == 400))) || \
499 ((LCD_WIDTH == 360) && (LCD_HEIGHT == 400))
496#define FOOD_SIZE 7 500#define FOOD_SIZE 7
497#define ARGH_SIZE 8 501#define ARGH_SIZE 8
498#define SPEED 4 502#define SPEED 4
diff --git a/apps/plugins/xobox.c b/apps/plugins/xobox.c
index cf959ad7f5..b8b1964db4 100644
--- a/apps/plugins/xobox.c
+++ b/apps/plugins/xobox.c
@@ -351,6 +351,9 @@ CONFIG_KEYPAD == MROBE500_PAD
351#define DOWN BUTTON_DOWN 351#define DOWN BUTTON_DOWN
352#define PAUSE BUTTON_PLAY 352#define PAUSE BUTTON_PLAY
353 353
354#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
355/* use touchscreen */
356
354#else 357#else
355#error "No keymap defined!" 358#error "No keymap defined!"
356#endif 359#endif
diff --git a/apps/plugins/zxbox/keymaps.h b/apps/plugins/zxbox/keymaps.h
index e9316a301b..e95a1d8c94 100644
--- a/apps/plugins/zxbox/keymaps.h
+++ b/apps/plugins/zxbox/keymaps.h
@@ -290,6 +290,9 @@
290#define ZX_UP BUTTON_UP 290#define ZX_UP BUTTON_UP
291#define ZX_DOWN BUTTON_DOWN 291#define ZX_DOWN BUTTON_DOWN
292 292
293#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
294/* use touchscreen */
295
293#else 296#else
294#error Keymap not defined! 297#error Keymap not defined!
295 298
diff --git a/apps/settings_list.c b/apps/settings_list.c
index c13df734e6..1cdbc4115d 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -242,6 +242,9 @@ static const char graphic_numeric[] = "graphic,numeric";
242 #define DEFAULT_FONT_HEIGHT 12 242 #define DEFAULT_FONT_HEIGHT 12
243#elif LCD_HEIGHT <= 320 243#elif LCD_HEIGHT <= 320
244 #define DEFAULT_FONT_HEIGHT 15 244 #define DEFAULT_FONT_HEIGHT 15
245#elif defined(SHANLING_Q1)
246 /* 16pt font looks pretty aliased & ugly */
247 #define DEFAULT_FONT_HEIGHT 18
245#elif LCD_HEIGHT <= 400 248#elif LCD_HEIGHT <= 400
246 #define DEFAULT_FONT_HEIGHT 16 249 #define DEFAULT_FONT_HEIGHT 16
247#elif LCD_HEIGHT <= 480 && LCD_WIDTH < 800 250#elif LCD_HEIGHT <= 480 && LCD_WIDTH < 800
@@ -261,7 +264,7 @@ static const char graphic_numeric[] = "graphic,numeric";
261#endif 264#endif
262 265
263#ifdef HAVE_LCD_COLOR 266#ifdef HAVE_LCD_COLOR
264 #if DEFAULT_FONT_HEIGHT >= 31 267 #if DEFAULT_FONT_HEIGHT >= 31 || defined(SHANLING_Q1)
265 #define DEFAULT_ICONSET "tango_icons.32x32" 268 #define DEFAULT_ICONSET "tango_icons.32x32"
266 #define DEFAULT_VIEWERS_ICONSET "tango_icons_viewers.32x32" 269 #define DEFAULT_VIEWERS_ICONSET "tango_icons_viewers.32x32"
267 #elif DEFAULT_FONT_HEIGHT >= 23 270 #elif DEFAULT_FONT_HEIGHT >= 23
@@ -848,7 +851,11 @@ const struct settings_list settings[] = {
848 851
849#ifdef AUDIOHW_HAVE_FILTER_ROLL_OFF 852#ifdef AUDIOHW_HAVE_FILTER_ROLL_OFF
850 CHOICE_SETTING(F_SOUNDSETTING, roll_off, LANG_FILTER_ROLL_OFF, 0, 853 CHOICE_SETTING(F_SOUNDSETTING, roll_off, LANG_FILTER_ROLL_OFF, 0,
851#if defined(AUDIOHW_HAVE_SHORT2_ROLL_OFF) 854#if defined(AUDIOHW_HAVE_ES9218_ROLL_OFF)
855 "roll_off", "linear fast,linear slow,minimum fast,minimum slow,apodizing 1,apodizing 2,hybrid fast,brick wall", sound_set_filter_roll_off,
856 8, ID2P(LANG_FILTER_LINEAR_FAST), ID2P(LANG_FILTER_LINEAR_SLOW), ID2P(LANG_FILTER_MINIMUM_FAST), ID2P(LANG_FILTER_MINIMUM_SLOW),
857 ID2P(LANG_FILTER_APODIZING_1), ID2P(LANG_FILTER_APODIZING_2), ID2P(LANG_FILTER_HYBRID_FAST), ID2P(LANG_FILTER_BRICK_WALL)),
858#elif defined(AUDIOHW_HAVE_SHORT2_ROLL_OFF)
852 "roll_off", "sharp,slow,short sharp,short slow", sound_set_filter_roll_off, 859 "roll_off", "sharp,slow,short sharp,short slow", sound_set_filter_roll_off,
853 4, ID2P(LANG_FILTER_SHARP), ID2P(LANG_FILTER_SLOW), ID2P(LANG_FILTER_SHORT_SHARP), ID2P(LANG_FILTER_SHORT_SLOW)), 860 4, ID2P(LANG_FILTER_SHARP), ID2P(LANG_FILTER_SLOW), ID2P(LANG_FILTER_SHORT_SHARP), ID2P(LANG_FILTER_SHORT_SLOW)),
854#elif defined(AUDIOHW_HAVE_SHORT_ROLL_OFF) 861#elif defined(AUDIOHW_HAVE_SHORT_ROLL_OFF)
diff --git a/backdrops/cabbiev2.360x400x16.bmp b/backdrops/cabbiev2.360x400x16.bmp
new file mode 100644
index 0000000000..e007b185d1
--- /dev/null
+++ b/backdrops/cabbiev2.360x400x16.bmp
Binary files differ
diff --git a/bootloader/SOURCES b/bootloader/SOURCES
index f72c58a0b7..6cdcd41ece 100644
--- a/bootloader/SOURCES
+++ b/bootloader/SOURCES
@@ -89,6 +89,6 @@ show_logo.c
89#elif defined(SANSA_CONNECT) 89#elif defined(SANSA_CONNECT)
90sansaconnect.c 90sansaconnect.c
91show_logo.c 91show_logo.c
92#elif defined(FIIO_M3K) 92#elif defined(FIIO_M3K) || defined(SHANLING_Q1)
93x1000.c 93x1000.c
94#endif 94#endif
diff --git a/bootloader/x1000.c b/bootloader/x1000.c
index 2c61773b11..3467547684 100644
--- a/bootloader/x1000.c
+++ b/bootloader/x1000.c
@@ -66,6 +66,17 @@
66# define BL_SELECT_NAME "PLAY" 66# define BL_SELECT_NAME "PLAY"
67# define BL_QUIT_NAME "POWER" 67# define BL_QUIT_NAME "POWER"
68# define BOOTBACKUP_FILE "/fiiom3k-boot.bin" 68# define BOOTBACKUP_FILE "/fiiom3k-boot.bin"
69#elif defined(SHANLING_Q1)
70# define BL_RECOVERY BUTTON_NEXT
71# define BL_UP BUTTON_PREV
72# define BL_DOWN BUTTON_NEXT
73# define BL_SELECT BUTTON_PLAY
74# define BL_QUIT BUTTON_POWER
75# define BL_UP_NAME "PREV"
76# define BL_DOWN_NAME "NEXT"
77# define BL_SELECT_NAME "PLAY"
78# define BL_QUIT_NAME "POWER"
79# define BOOTBACKUP_FILE "/shanlingq1-boot.bin"
69#else 80#else
70# error "Missing keymap!" 81# error "Missing keymap!"
71#endif 82#endif
diff --git a/docs/CREDITS b/docs/CREDITS
index 7dee2ce527..613aa1f660 100644
--- a/docs/CREDITS
+++ b/docs/CREDITS
@@ -706,6 +706,7 @@ Caleb Connolly
706Spencer Brennessel 706Spencer Brennessel
707Dana Conrad 707Dana Conrad
708Albert Song 708Albert Song
709Marc Aarts
709 710
710The libmad team 711The libmad team
711The wavpack team 712The wavpack team
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 2414682bb4..e055558b57 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -503,6 +503,8 @@ drivers/audio/pcm1792.c
503drivers/audio/cs4398.c 503drivers/audio/cs4398.c
504#elif defined (HAVE_ES9018) 504#elif defined (HAVE_ES9018)
505drivers/audio/es9018.c 505drivers/audio/es9018.c
506#elif defined (HAVE_ES9218)
507drivers/audio/es9218.c
506#endif /* defined(HAVE_*) */ 508#endif /* defined(HAVE_*) */
507#else /* PLATFORM_HOSTED */ 509#else /* PLATFORM_HOSTED */
508#if defined(SAMSUNG_YPR0) && defined(HAVE_AS3514) 510#if defined(SAMSUNG_YPR0) && defined(HAVE_AS3514)
@@ -1716,6 +1718,15 @@ target/mips/ingenic_x1000/fiiom3k/power-fiiom3k.c
1716target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c 1718target/mips/ingenic_x1000/fiiom3k/spl-fiiom3k.c
1717#endif /* FIIO_M3K */ 1719#endif /* FIIO_M3K */
1718 1720
1721#if defined(SHANLING_Q1)
1722target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c
1723target/mips/ingenic_x1000/shanlingq1/backlight-shanlingq1.c
1724target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
1725target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c
1726target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
1727target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c
1728#endif /* SHANLING_Q1 */
1729
1719#if defined(LYRE_PROTO1) 1730#if defined(LYRE_PROTO1)
1720target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c 1731target/arm/at91sam/lyre_proto1/adc-lyre_proto1.c
1721target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c 1732target/arm/at91sam/lyre_proto1/backlight-lyre_proto1.c
@@ -1948,6 +1959,9 @@ drivers/axp-pmu.c
1948#ifdef HAVE_FT6x06 1959#ifdef HAVE_FT6x06
1949drivers/ft6x06.c 1960drivers/ft6x06.c
1950#endif 1961#endif
1962#ifdef HAVE_CW2015
1963drivers/cw2015.c
1964#endif
1951#endif 1965#endif
1952 1966
1953/* firmware/kernel section */ 1967/* firmware/kernel section */
diff --git a/firmware/drivers/audio/es9218.c b/firmware/drivers/audio/es9218.c
new file mode 100644
index 0000000000..76d387221a
--- /dev/null
+++ b/firmware/drivers/audio/es9218.c
@@ -0,0 +1,226 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "audiohw.h"
23#include "system.h"
24#include "i2c-async.h"
25
26struct es9218_state {
27 enum es9218_clock_gear clk_gear;
28 uint32_t fsr;
29 uint32_t nco;
30};
31
32static struct es9218_state es9218;
33
34void es9218_open(void)
35{
36 /* Enable power supply */
37 es9218_set_power_pin(1);
38
39 /* "Wiggle" reset pin to get the internal oscillator to stabilize.
40 * This should also work if using an external powered oscillator,
41 * although in that case it's unnecessary to do this dance. */
42 es9218_set_reset_pin(1);
43 udelay(75);
44 es9218_set_reset_pin(0);
45 udelay(50);
46 es9218_set_reset_pin(1);
47 mdelay(2);
48
49 /* Initialize driver state */
50 es9218.clk_gear = ES9218_CLK_GEAR_1;
51 es9218.fsr = 0;
52 es9218.nco = 0;
53}
54
55void es9218_close(void)
56{
57 /* Turn off power supply */
58 es9218_set_power_pin(0);
59 es9218_set_reset_pin(0);
60}
61
62static void recalc_nco(void)
63{
64 /* nco * CLK *
65 * fsr = --------- *
66 * 2**32 */
67
68 uint32_t clk = es9218_get_mclk();
69 clk >>= (int)es9218.clk_gear;
70
71 uint64_t nco64 = es9218.fsr;
72 nco64 <<= 32;
73 nco64 /= clk;
74
75 /* let's just ignore overflow... */
76 uint32_t nco = nco64;
77 if(nco != es9218.nco) {
78 es9218.nco = nco;
79
80 /* registers must be written in this order */
81 es9218_write(ES9218_REG_PROG_NCO_BIT0_7, (nco >> 0) & 0xff);
82 es9218_write(ES9218_REG_PROG_NCO_BIT8_15, (nco >> 8) & 0xff);
83 es9218_write(ES9218_REG_PROG_NCO_BIT16_23, (nco >> 16) & 0xff);
84 es9218_write(ES9218_REG_PROG_NCO_BIT24_31, (nco >> 24) & 0xff);
85 }
86}
87
88void es9218_set_clock_gear(enum es9218_clock_gear gear)
89{
90 if(gear != es9218.clk_gear) {
91 es9218.clk_gear = gear;
92 es9218_update(ES9218_REG_SYSTEM, 0x0c, (uint8_t)(gear & 3) << 2);
93 recalc_nco();
94 }
95}
96
97void es9218_set_nco_frequency(uint32_t fsr)
98{
99 if(fsr != es9218.fsr) {
100 es9218.fsr = fsr;
101 recalc_nco();
102 }
103}
104
105void es9218_recompute_nco(void)
106{
107 recalc_nco();
108}
109
110void es9218_set_amp_mode(enum es9218_amp_mode mode)
111{
112 es9218_update(ES9218_REG_AMP_CONFIG, 0x03, (uint8_t)mode & 3);
113}
114
115void es9218_set_amp_powered(bool en)
116{
117 /* this doesn't seem to be necessary..? */
118 es9218_update(ES9218_REG_ANALOG_CTRL, 0x40, en ? 0x40 : 0x00);
119}
120
121void es9218_set_iface_role(enum es9218_iface_role role)
122{
123 /* asrc is used to lock onto the incoming audio frequency and is
124 * only used in aysnchronous slave mode. In synchronous operation,
125 * including master mode, it can be disabled to save power. */
126 int asrc_en = (role == ES9218_IFACE_ROLE_SLAVE ? 1 : 0);
127 int master_mode = (role == ES9218_IFACE_ROLE_MASTER ? 1 : 0);
128
129 es9218_update(ES9218_REG_MASTER_MODE_CONFIG, 1 << 7, master_mode << 7);
130 es9218_update(ES9218_REG_GENERAL_CONFIG, 1 << 7, asrc_en << 7);
131}
132
133void es9218_set_iface_format(enum es9218_iface_format fmt,
134 enum es9218_iface_bits bits)
135{
136 uint8_t val = 0;
137 val |= ((uint8_t)bits & 3) << 6;
138 val |= ((uint8_t)fmt & 3) << 4;
139 /* keep low 4 bits zero -> use normal I2S mode, disable DSD mode */
140 es9218_write(ES9218_REG_INPUT_SEL, val);
141}
142
143static int dig_vol_to_hw(int x)
144{
145 x = MIN(x, ES9218_DIG_VOLUME_MAX);
146 x = MAX(x, ES9218_DIG_VOLUME_MIN);
147 return 0xff - (x - ES9218_DIG_VOLUME_MIN) / ES9218_DIG_VOLUME_STEP;
148}
149
150static int amp_vol_to_hw(int x)
151{
152 x = MIN(x, ES9218_AMP_VOLUME_MAX);
153 x = MAX(x, ES9218_AMP_VOLUME_MIN);
154 return 24 - (x - ES9218_AMP_VOLUME_MIN) / ES9218_AMP_VOLUME_STEP;
155}
156
157void es9218_set_dig_volume(int vol_l, int vol_r)
158{
159 es9218_write(ES9218_REG_VOLUME_LEFT, dig_vol_to_hw(vol_l));
160 es9218_write(ES9218_REG_VOLUME_RIGHT, dig_vol_to_hw(vol_r));
161}
162
163void es9218_set_amp_volume(int vol)
164{
165 es9218_update(ES9218_REG_ANALOG_VOL, 0x1f, amp_vol_to_hw(vol));
166}
167
168void es9218_mute(bool en)
169{
170 es9218_update(ES9218_REG_FILTER_SYS_MUTE, 1, en ? 1 : 0);
171}
172
173void es9218_set_filter(enum es9218_filter_type filt)
174{
175 es9218_update(ES9218_REG_FILTER_SYS_MUTE, 0xe0, ((int)filt & 7) << 5);
176}
177
178void es9218_set_automute_time(int time)
179{
180 if(time < 0) time = 0;
181 if(time > 255) time = 255;
182 es9218_write(ES9218_REG_AUTOMUTE_TIME, time);
183}
184
185void es9218_set_automute_level(int dB)
186{
187 es9218_update(ES9218_REG_AUTOMUTE_LEVEL, 0x7f, dB);
188}
189
190void es9218_set_automute_fast_mode(bool en)
191{
192 es9218_update(ES9218_REG_MIX_AUTOMUTE, 0x10, en ? 0x10 : 0x00);
193}
194
195void es9218_set_dpll_bandwidth(int knob)
196{
197 es9218_update(ES9218_REG_ASRC_DPLL_BANDWIDTH, 0xf0, (knob & 0xf) << 4);
198}
199
200void es9218_set_thd_compensation(bool en)
201{
202 es9218_update(ES9218_REG_THD_COMP_BYPASS, 0x40, en ? 0x40 : 0);
203}
204
205void es9218_set_thd_coeffs(uint16_t c2, uint16_t c3)
206{
207 es9218_write(ES9218_REG_THD_COMP_C2_LO, c2 & 0xff);
208 es9218_write(ES9218_REG_THD_COMP_C2_HI, (c2 >> 8) & 0xff);
209 es9218_write(ES9218_REG_THD_COMP_C3_LO, c3 & 0xff);
210 es9218_write(ES9218_REG_THD_COMP_C3_HI, (c3 >> 8) & 0xff);
211}
212
213int es9218_read(int reg)
214{
215 return i2c_reg_read1(ES9218_BUS, ES9218_ADDR, reg);
216}
217
218void es9218_write(int reg, uint8_t val)
219{
220 i2c_reg_write1(ES9218_BUS, ES9218_ADDR, reg, val);
221}
222
223void es9218_update(int reg, uint8_t msk, uint8_t val)
224{
225 i2c_reg_modify1(ES9218_BUS, ES9218_ADDR, reg, msk, val, NULL);
226}
diff --git a/firmware/drivers/cw2015.c b/firmware/drivers/cw2015.c
new file mode 100644
index 0000000000..705ca16e22
--- /dev/null
+++ b/firmware/drivers/cw2015.c
@@ -0,0 +1,191 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "cw2015.h"
23#include "i2c-async.h"
24#include <string.h>
25#include "system.h"
26
27/* Headers for the debug menu */
28#ifndef BOOTLOADER
29# include "action.h"
30# include "list.h"
31# include <stdio.h>
32#endif
33
34/* Battery profile info is an opaque blob. According to this,
35 * https://lore.kernel.org/linux-pm/20200503154855.duwj2djgqfiyleq5@earth.universe/T/#u
36 * the blob only comes from Cellwise testing a physical battery and cannot be
37 * obtained any other way. It's specific to a given battery so each target has
38 * its own profile.
39 *
40 * Profile data seems to be retained on the chip so it's not a hard requirement
41 * to define this. Provided you don't lose power in the meantime, it should be
42 * enough to just boot the OF, then boot Rockbox and read out the battery info
43 * from the CW2015 debug screen.
44 */
45#if defined(SHANLING_Q1)
46static const uint8_t device_batinfo[CW2015_SIZE_BATINFO] = {
47 0x15, 0x7E, 0x61, 0x59, 0x57, 0x55, 0x56, 0x4C,
48 0x4E, 0x4D, 0x50, 0x4C, 0x45, 0x3A, 0x2D, 0x27,
49 0x22, 0x1E, 0x19, 0x1E, 0x2A, 0x3C, 0x48, 0x45,
50 0x1D, 0x94, 0x08, 0xF6, 0x15, 0x29, 0x48, 0x51,
51 0x5D, 0x60, 0x63, 0x66, 0x45, 0x1D, 0x83, 0x38,
52 0x09, 0x43, 0x16, 0x42, 0x76, 0x98, 0xA5, 0x1B,
53 0x41, 0x76, 0x99, 0xBF, 0x80, 0xC0, 0xEF, 0xCB,
54 0x2F, 0x00, 0x64, 0xA5, 0xB5, 0x0E, 0x30, 0x29,
55};
56#else
57# define NO_BATINFO
58#endif
59
60static uint8_t chip_batinfo[CW2015_SIZE_BATINFO];
61
62/* TODO: Finish implementing this
63 *
64 * Although this chip might give a better battery estimate than voltage does,
65 * the mainline linux driver has a lot of weird hacks due to oddities like the
66 * SoC getting stuck during charging, and from limited testing it seems this
67 * may occur for the Q1 too.
68 */
69
70static int cw2015_read_bat_info(uint8_t* data)
71{
72 for(int i = 0; i < CW2015_SIZE_BATINFO; ++i) {
73 int r = i2c_reg_read1(CW2015_BUS, CW2015_ADDR, CW2015_REG_BATINFO + i);
74 if(r < 0)
75 return r;
76
77 data[i] = r & 0xff;
78 }
79
80 return 0;
81}
82
83void cw2015_init(void)
84{
85 /* mdelay(100); */
86 int rc = cw2015_read_bat_info(&chip_batinfo[0]);
87 if(rc < 0)
88 memset(chip_batinfo, 0, sizeof(chip_batinfo));
89}
90
91int cw2015_get_vcell(void)
92{
93 int vcell_msb = i2c_reg_read1(CW2015_BUS, CW2015_ADDR, CW2015_REG_VCELL);
94 int vcell_lsb = i2c_reg_read1(CW2015_BUS, CW2015_ADDR, CW2015_REG_VCELL+1);
95
96 if(vcell_msb < 0 || vcell_lsb < 0)
97 return -1;
98
99 /* 14 bits, resolution 305 uV */
100 int v_raw = ((vcell_msb & 0x3f) << 8) | vcell_lsb;
101 return v_raw * 61 / 200;
102}
103
104int cw2015_get_soc(void)
105{
106 int soc_msb = i2c_reg_read1(CW2015_BUS, CW2015_ADDR, CW2015_REG_SOC);
107
108 if(soc_msb < 0)
109 return -1;
110
111 /* MSB is the state of charge in percentage.
112 * the LSB contains fractional information not useful to Rockbox. */
113 return soc_msb & 0xff;
114}
115
116int cw2015_get_rrt(void)
117{
118 int rrt_msb = i2c_reg_read1(CW2015_BUS, CW2015_ADDR, CW2015_REG_RRT_ALERT);
119 int rrt_lsb = i2c_reg_read1(CW2015_BUS, CW2015_ADDR, CW2015_REG_RRT_ALERT+1);
120
121 if(rrt_msb < 0 || rrt_lsb < 0)
122 return -1;
123
124 /* 13 bits, resolution 1 minute */
125 return ((rrt_msb & 0x1f) << 8) | rrt_lsb;
126}
127
128const uint8_t* cw2015_get_bat_info(void)
129{
130 return &chip_batinfo[0];
131}
132
133#ifndef BOOTLOADER
134enum {
135 CW2015_DEBUG_VCELL = 0,
136 CW2015_DEBUG_SOC,
137 CW2015_DEBUG_RRT,
138 CW2015_DEBUG_BATINFO,
139 CW2015_DEBUG_BATINFO_LAST = CW2015_DEBUG_BATINFO + 7,
140 CW2015_DEBUG_NUM_ENTRIES,
141};
142
143static int cw2015_debug_menu_cb(int action, struct gui_synclist* lists)
144{
145 (void)lists;
146
147 if(action == ACTION_NONE)
148 action = ACTION_REDRAW;
149
150 return action;
151}
152
153static const char* cw2015_debug_menu_get_name(int item, void* data,
154 char* buf, size_t buflen)
155{
156 (void)data;
157
158 /* hexdump of battery info */
159 if(item >= CW2015_DEBUG_BATINFO && item <= CW2015_DEBUG_BATINFO_LAST) {
160 int i = item - CW2015_DEBUG_BATINFO;
161 const uint8_t* batinfo = cw2015_get_bat_info();
162 snprintf(buf, buflen, "BatInfo%d: %02x %02x %02x %02x %02x %02x %02x %02x", i,
163 batinfo[8*i + 0], batinfo[8*i + 1], batinfo[8*i + 2], batinfo[8*i + 3],
164 batinfo[8*i + 4], batinfo[8*i + 5], batinfo[8*i + 6], batinfo[8*i + 7]);
165 return buf;
166 }
167
168 switch(item) {
169 case CW2015_DEBUG_VCELL:
170 snprintf(buf, buflen, "VCell: %d mV", cw2015_get_vcell());
171 return buf;
172 case CW2015_DEBUG_SOC:
173 snprintf(buf, buflen, "SOC: %d%%", cw2015_get_soc());
174 return buf;
175 case CW2015_DEBUG_RRT:
176 snprintf(buf, buflen, "Runtime: %d min", cw2015_get_rrt());
177 return buf;
178 default:
179 return "---";
180 }
181}
182
183bool cw2015_debug_menu(void)
184{
185 struct simplelist_info info;
186 simplelist_info_init(&info, "CW2015 debug", CW2015_DEBUG_NUM_ENTRIES, NULL);
187 info.action_callback = cw2015_debug_menu_cb;
188 info.get_name = cw2015_debug_menu_get_name;
189 return simplelist_show_list(&info);
190}
191#endif
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index ceafc6ebf7..5b2815149d 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -216,6 +216,8 @@ struct sound_settings_info
216#include "cs4398.h" 216#include "cs4398.h"
217#elif defined(HAVE_ES9018) 217#elif defined(HAVE_ES9018)
218#include "es9018.h" 218#include "es9018.h"
219#elif defined(HAVE_ES9218)
220#include "es9218.h"
219#elif (CONFIG_PLATFORM & (PLATFORM_ANDROID | PLATFORM_MAEMO \ 221#elif (CONFIG_PLATFORM & (PLATFORM_ANDROID | PLATFORM_MAEMO \
220 | PLATFORM_PANDORA | PLATFORM_SDL)) 222 | PLATFORM_PANDORA | PLATFORM_SDL))
221#include "hosted_codec.h" 223#include "hosted_codec.h"
diff --git a/firmware/export/config.h b/firmware/export/config.h
index fdf3bf420d..5e7b2be6e4 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -160,6 +160,7 @@
160#define FIIO_M3K_LINUX_PAD 71 160#define FIIO_M3K_LINUX_PAD 71
161#define EROSQ_PAD 72 161#define EROSQ_PAD 72
162#define FIIO_M3K_PAD 73 162#define FIIO_M3K_PAD 73
163#define SHANLING_Q1_PAD 74
163 164
164/* CONFIG_REMOTE_KEYPAD */ 165/* CONFIG_REMOTE_KEYPAD */
165#define H100_REMOTE 1 166#define H100_REMOTE 1
@@ -274,6 +275,7 @@
274#define LCD_IHIFI770C 67 /* as used by IHIFI 770C */ 275#define LCD_IHIFI770C 67 /* as used by IHIFI 770C */
275#define LCD_IHIFI800 68 /* as used by IHIFI 800 */ 276#define LCD_IHIFI800 68 /* as used by IHIFI 800 */
276#define LCD_FIIOM3K 69 /* as used by the FiiO M3K */ 277#define LCD_FIIOM3K 69 /* as used by the FiiO M3K */
278#define LCD_SHANLING_Q1 70 /* as used by the Shanling Q1 */
277 279
278/* LCD_PIXELFORMAT */ 280/* LCD_PIXELFORMAT */
279#define HORIZONTAL_PACKING 1 281#define HORIZONTAL_PACKING 1
@@ -592,6 +594,8 @@ Lyre prototype 1 */
592#include "config/fiiom3k.h" 594#include "config/fiiom3k.h"
593#elif defined(EROS_Q) 595#elif defined(EROS_Q)
594#include "config/aigoerosq.h" 596#include "config/aigoerosq.h"
597#elif defined(SHANLING_Q1)
598#include "config/shanlingq1.h"
595#else 599#else
596//#error "unknown hwardware platform!" 600//#error "unknown hwardware platform!"
597#endif 601#endif
diff --git a/firmware/export/config/shanlingq1.h b/firmware/export/config/shanlingq1.h
new file mode 100644
index 0000000000..88175b9160
--- /dev/null
+++ b/firmware/export/config/shanlingq1.h
@@ -0,0 +1,119 @@
1/* RoLo-related defines */
2#define MODEL_NAME "Shanling Q1"
3#define MODEL_NUMBER 115
4#define BOOTFILE_EXT "q1"
5#define BOOTFILE "rockbox." BOOTFILE_EXT
6#define BOOTDIR "/.rockbox"
7#define FIRMWARE_OFFSET_FILE_CRC 0
8#define FIRMWARE_OFFSET_FILE_DATA 8
9
10/* CPU defines */
11#define CONFIG_CPU X1000
12#define X1000_EXCLK_FREQ 24000000
13#define CPU_FREQ 1008000000
14
15#ifndef SIMULATOR
16#define TIMER_FREQ X1000_EXCLK_FREQ
17#endif
18
19/* Kernel defines */
20#define INCLUDE_TIMEOUT_API
21#define HAVE_SEMAPHORE_OBJECTS
22
23/* Drivers */
24#define HAVE_I2C_ASYNC
25
26/* Buffer for plugins and codecs. */
27#define PLUGIN_BUFFER_SIZE 0x200000 /* 2 MiB */
28#define CODEC_SIZE 0x100000 /* 1 MiB */
29
30/* LCD defines */
31#define CONFIG_LCD LCD_SHANLING_Q1
32#define LCD_WIDTH 360
33#define LCD_HEIGHT 400
34#define LCD_DEPTH 16
35#define LCD_PIXELFORMAT RGB565
36#define LCD_DPI 200
37#define HAVE_LCD_COLOR
38#define HAVE_LCD_BITMAP
39#define HAVE_LCD_ENABLE
40#define LCD_X1000_FASTSLEEP
41#define LCD_X1000_DMA_WAIT_FOR_FRAME
42
43/* Backlight defines */
44#define HAVE_BACKLIGHT
45#define HAVE_BACKLIGHT_BRIGHTNESS
46#define MIN_BRIGHTNESS_SETTING 1
47#define MAX_BRIGHTNESS_SETTING 100
48#define BRIGHTNESS_STEP 5
49#define DEFAULT_BRIGHTNESS_SETTING 70
50#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
51
52/* Codec / audio hardware defines */
53#define HW_SAMPR_CAPS SAMPR_CAP_ALL_192
54#define HAVE_ES9218
55#define HAVE_SW_TONE_CONTROLS
56
57/* Button defines */
58#define CONFIG_KEYPAD SHANLING_Q1_PAD
59#define HAVE_TOUCHSCREEN
60#define HAVE_BUTTON_DATA
61#define HAVE_FT6x06
62#define HAVE_HEADPHONE_DETECTION
63
64/* Storage defines */
65#define CONFIG_STORAGE STORAGE_SD
66#define HAVE_HOTSWAP
67#define HAVE_HOTSWAP_STORAGE_AS_MAIN
68#define HAVE_MULTIDRIVE
69#define NUM_DRIVES 1
70#define STORAGE_WANTS_ALIGN
71#define STORAGE_NEEDS_BOUNCE_BUFFER
72
73/* RTC settings */
74#define CONFIG_RTC RTC_X1000
75/* TODO: implement HAVE_RTC_ALARM */
76
77/* Power management */
78#define CONFIG_BATTERY_MEASURE (VOLTAGE_MEASURE)
79#define CONFIG_CHARGING CHARGING_MONITOR
80#define HAVE_SW_POWEROFF
81
82#ifndef SIMULATOR
83/* TODO: get the CW2015 driver working correctly */
84/* #define HAVE_CW2015 */
85#define HAVE_AXP_PMU 192 /* Presumed */
86#define HAVE_POWEROFF_WHILE_CHARGING
87#endif
88
89/* Only one battery type */
90#define BATTERY_CAPACITY_DEFAULT 1100
91#define BATTERY_CAPACITY_MIN 1100
92#define BATTERY_CAPACITY_MAX 1100
93#define BATTERY_CAPACITY_INC 0
94#define BATTERY_TYPES_COUNT 1
95
96/* USB support */
97#ifndef SIMULATOR
98#define CONFIG_USBOTG USBOTG_DESIGNWARE
99#define USB_DW_ARCH_SLAVE
100#define USB_DW_TURNAROUND 5
101#define HAVE_USBSTACK
102#define USB_VENDOR_ID 0x0525 /* Same as the xDuuo X3, for some reason. */
103#define USB_PRODUCT_ID 0xa4a5 /* Nb. DAC mode uses 20b1:301f 'XMOS Ltd' */
104#define USB_DEVBSS_ATTR __attribute__((aligned(32)))
105#define HAVE_USB_POWER
106#define HAVE_USB_CHARGING_ENABLE
107#define HAVE_BOOTLOADER_USB_MODE
108#endif
109
110/* Rockbox capabilities */
111#define HAVE_FAT16SUPPORT
112#define HAVE_ALBUMART
113#define HAVE_BMP_SCALING
114#define HAVE_JPEG
115#define HAVE_TAGCACHE
116#define HAVE_VOLUME_IN_LIST
117#define HAVE_QUICKSCREEN
118#define HAVE_HOTKEY
119#define AB_REPEAT_ENABLE
diff --git a/firmware/export/cw2015.h b/firmware/export/cw2015.h
new file mode 100644
index 0000000000..c810d1b7b5
--- /dev/null
+++ b/firmware/export/cw2015.h
@@ -0,0 +1,57 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __CW2015_H__
23#define __CW2015_H__
24
25#include <stdint.h>
26#include <stdbool.h>
27
28/* Driver for I2C battery fuel gauge IC CW2015. */
29
30#define CW2015_REG_VERSION 0x00
31#define CW2015_REG_VCELL 0x02 /* 14 bits, registers 0x02 - 0x03 */
32#define CW2015_REG_SOC 0x04 /* 16 bits, registers 0x04 - 0x05 */
33#define CW2015_REG_RRT_ALERT 0x06 /* 13 bit RRT + alert flag, 0x06-0x07 */
34#define CW2015_REG_CONFIG 0x08
35#define CW2015_REG_MODE 0x0a
36#define CW2015_REG_BATINFO 0x10 /* cf. mainline Linux CW2015 driver */
37#define CW2015_SIZE_BATINFO 64
38
39extern void cw2015_init(void);
40
41/* Read the battery terminal voltage, converted to millivolts. */
42extern int cw2015_get_vcell(void);
43
44/* Read the SOC, in percent (0-100%). */
45extern int cw2015_get_soc(void);
46
47/* Get the estimated remaining run time, in minutes.
48 * Not a linearly varying quantity, according to the datasheet. */
49extern int cw2015_get_rrt(void);
50
51/* Read the current battery profile */
52extern const uint8_t* cw2015_get_bat_info(void);
53
54/* Debug screen */
55extern bool cw2015_debug_menu(void);
56
57#endif /* __CW2015_H__ */
diff --git a/firmware/export/es9218.h b/firmware/export/es9218.h
new file mode 100644
index 0000000000..1492304c67
--- /dev/null
+++ b/firmware/export/es9218.h
@@ -0,0 +1,230 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __ES9218_H__
23#define __ES9218_H__
24
25#include <stdbool.h>
26#include <stdint.h>
27
28#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP|POWER_MODE_CAP)
29#define AUDIOHW_HAVE_ES9218_ROLL_OFF
30
31#define ES9218_DIG_VOLUME_MIN (-1275)
32#define ES9218_DIG_VOLUME_MAX 0
33#define ES9218_DIG_VOLUME_STEP 5
34
35#define ES9218_AMP_VOLUME_MIN (-240)
36#define ES9218_AMP_VOLUME_MAX 0
37#define ES9218_AMP_VOLUME_STEP 10
38
39AUDIOHW_SETTING(VOLUME, "dB", 1, ES9218_DIG_VOLUME_STEP,
40 ES9218_DIG_VOLUME_MIN, ES9218_DIG_VOLUME_MAX, -200)
41AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 7, 0)
42AUDIOHW_SETTING(POWER_MODE, "", 0, 1, 0, 1, 0)
43
44/* Register addresses */
45#define ES9218_REG_SYSTEM 0x00
46#define ES9218_REG_INPUT_SEL 0x01
47#define ES9218_REG_MIX_AUTOMUTE 0x02
48#define ES9218_REG_ANALOG_VOL 0x03
49#define ES9218_REG_AUTOMUTE_TIME 0x04
50#define ES9218_REG_AUTOMUTE_LEVEL 0x05
51#define ES9218_REG_DOP_VOLUME_RAMP 0x06
52#define ES9218_REG_FILTER_SYS_MUTE 0x07
53#define ES9218_REG_GPIO1_2_CONFIG 0x08
54#define ES9218_REG_RESERVED_1 0x09
55#define ES9218_REG_MASTER_MODE_CONFIG 0x0a
56#define ES9218_REG_OVERCURRENT_PROT 0x0b
57#define ES9218_REG_ASRC_DPLL_BANDWIDTH 0x0c
58#define ES9218_REG_THD_COMP_BYPASS 0x0d
59#define ES9218_REG_SOFT_START_CONFIG 0x0e
60#define ES9218_REG_VOLUME_LEFT 0x0f
61#define ES9218_REG_VOLUME_RIGHT 0x10
62#define ES9218_REG_MASTER_TRIM_BIT0_7 0x11
63#define ES9218_REG_MASTER_TRIM_BIT8_15 0x12
64#define ES9218_REG_MASTER_TRIM_BIT16_23 0x13
65#define ES9218_REG_MASTER_TRIM_BIT24_31 0x14
66#define ES9218_REG_GPIO_INPUT_SEL 0x15
67#define ES9218_REG_THD_COMP_C2_LO 0x16
68#define ES9218_REG_THD_COMP_C2_HI 0x17
69#define ES9218_REG_THD_COMP_C3_LO 0x18
70#define ES9218_REG_THD_COMP_C3_HI 0x19
71#define ES9218_REG_CHARGE_PUMP_SS_DELAY 0x1a
72#define ES9218_REG_GENERAL_CONFIG 0x1b
73#define ES9218_REG_RESERVED_2 0x1c
74#define ES9218_REG_GPIO_INV_CLOCK_GEAR 0x1d
75#define ES9218_REG_CHARGE_PUMP_CLK_LO 0x1e
76#define ES9218_REG_CHARGE_PUMP_CLK_HI 0x1f
77#define ES9218_REG_AMP_CONFIG 0x20
78#define ES9218_REG_INTERRUPT_MASK 0x21
79#define ES9218_REG_PROG_NCO_BIT0_7 0x22
80#define ES9218_REG_PROG_NCO_BIT8_15 0x23
81#define ES9218_REG_PROG_NCO_BIT16_23 0x24
82#define ES9218_REG_PROG_NCO_BIT24_31 0x25
83#define ES9218_REG_RESERVED_3 0x27
84#define ES9218_REG_FIR_RAM_ADDR 0x28
85#define ES9218_REG_FIR_DATA_BIT0_7 0x29
86#define ES9218_REG_FIR_DATA_BIT8_15 0x2a
87#define ES9218_REG_FIR_DATA_BIT16_23 0x2b
88#define ES9218_REG_PROG_FIR_CONFIG 0x2c
89#define ES9218_REG_ANALOG_OVERRIDE_1 0x2d
90#define ES9218_REG_ANALOG_OVERRIDE_2 0x2e
91#define ES9218_REG_ANALOG_OVERRIDE_3 0x2f
92#define ES9218_REG_ANALOG_CTRL 0x30
93#define ES9218_REG_CLKGEAR_CFG_BIT0_7 0x31
94#define ES9218_REG_CLKGEAR_CFG_BIT8_15 0x32
95#define ES9218_REG_CLKGEAR_CFG_BIT16_23 0x33
96#define ES9218_REG_RESERVED_4 0x34
97#define ES9218_REG_THD_COMP_C2_CH2_LO 0x35
98#define ES9218_REG_THD_COMP_C2_CH2_HI 0x36
99#define ES9218_REG_THD_COMP_C3_CH2_LO 0x37
100#define ES9218_REG_THD_COMP_C3_CH2_HI 0x38
101#define ES9218_REG_RESERVED_5 0x39
102#define ES9218_REG_RESERVED_6 0x3a
103#define ES9218_REG_RESERVED_7 0x3b
104#define ES9218_REG_RESERVED_8 0x3c
105#define ES9218_REG_CHIP_ID_AND_STATUS 0x40
106#define ES9218_REG_GPIO_AND_CLOCK_GEAR 0x41
107#define ES9218_REG_DPLL_NUMBER_BIT0_7 0x42
108#define ES9218_REG_DPLL_NUMBER_BIT8_15 0x43
109#define ES9218_REG_DPLL_NUMBER_BIT16_23 0x44
110#define ES9218_REG_DPLL_NUMBER_BIT24_31 0x45
111#define ES9218_REG_INPUT_MUTE_STATUS 0x48
112#define ES9218_REG_FIR_READ_BIT0_7 0x49
113#define ES9218_REG_FIR_READ_BIT8_15 0x4a
114#define ES9218_REG_FIR_READ_BIT16_23 0x4b
115
116enum es9218_clock_gear {
117 ES9218_CLK_GEAR_1 = 0, /* CLK = XI/1 */
118 ES9218_CLK_GEAR_2 = 1, /* CLK = XI/2 */
119 ES9218_CLK_GEAR_4 = 2, /* CLK = XI/4 */
120 ES9218_CLK_GEAR_8 = 3, /* CLK = XI/8 */
121};
122
123enum es9218_amp_mode {
124 ES9218_AMP_MODE_CORE_ON = 0,
125 ES9218_AMP_MODE_LOWFI = 1,
126 ES9218_AMP_MODE_1VRMS = 2,
127 ES9218_AMP_MODE_2VRMS = 3,
128};
129
130enum es9218_iface_role {
131 ES9218_IFACE_ROLE_SLAVE = 0,
132 ES9218_IFACE_ROLE_MASTER = 1,
133};
134
135enum es9218_iface_format {
136 ES9218_IFACE_FORMAT_I2S = 0,
137 ES9218_IFACE_FORMAT_LJUST = 1,
138 ES9218_IFACE_FORMAT_RJUST = 2,
139};
140
141enum es9218_iface_bits {
142 ES9218_IFACE_BITS_16 = 0,
143 ES9218_IFACE_BITS_24 = 1,
144 ES9218_IFACE_BITS_32 = 2,
145};
146
147enum es9218_filter_type {
148 ES9218_FILTER_LINEAR_FAST = 0,
149 ES9218_FILTER_LINEAR_SLOW = 1,
150 ES9218_FILTER_MINIMUM_FAST = 2,
151 ES9218_FILTER_MINIMUM_SLOW = 3,
152 ES9218_FILTER_APODIZING_1 = 4,
153 ES9218_FILTER_APODIZING_2 = 5,
154 ES9218_FILTER_HYBRID_FAST = 6,
155 ES9218_FILTER_BRICK_WALL = 7,
156};
157
158/* Power DAC on or off */
159extern void es9218_open(void);
160extern void es9218_close(void);
161
162/* Clock controls
163 *
164 * - Clock gear divides the input master clock to produce the DAC's clock.
165 * Frequency can be lowered to save power when using lower sample rates.
166 *
167 * - NCO (numerically controller oscillator), according to the datasheet,
168 * defines the ratio between the DAC's clock and the FSR (for PCM modes,
169 * this is I2S frame clock = sample rate). In master mode it effectively
170 * controls the sampling frequency by setting the I2S frame clock output.
171 * It can also be used in slave mode, but other parts of the datasheet
172 * say contradictory things about synchronous operation in slave mode.
173 *
174 * - If using NCO mode and a varying MCLK input (eg. input from the SoC) then
175 * you will need to call es9218_recompute_nco() when changing MCLK in order
176 * to refresh the NCO setting.
177 */
178extern void es9218_set_clock_gear(enum es9218_clock_gear gear);
179extern void es9218_set_nco_frequency(uint32_t fsr);
180extern void es9218_recompute_nco(void);
181
182/* Amplifier controls */
183extern void es9218_set_amp_mode(enum es9218_amp_mode mode);
184extern void es9218_set_amp_powered(bool en);
185
186/* Interface selection */
187extern void es9218_set_iface_role(enum es9218_iface_role role);
188extern void es9218_set_iface_format(enum es9218_iface_format fmt,
189 enum es9218_iface_bits bits);
190
191/* Volume controls, all volumes given in units of dB/10 */
192extern void es9218_set_dig_volume(int vol_l, int vol_r);
193extern void es9218_set_amp_volume(int vol);
194
195/* System mute */
196extern void es9218_mute(bool muted);
197
198/* Oversampling filter */
199extern void es9218_set_filter(enum es9218_filter_type filt);
200
201/* Automute settings */
202extern void es9218_set_automute_time(int time);
203extern void es9218_set_automute_level(int dB);
204extern void es9218_set_automute_fast_mode(bool en);
205
206/* DPLL bandwidth setting (knob = 0-15) */
207extern void es9218_set_dpll_bandwidth(int knob);
208
209/* THD compensation */
210extern void es9218_set_thd_compensation(bool en);
211extern void es9218_set_thd_coeffs(uint16_t c2, uint16_t c3);
212
213/* Direct register read/write/update operations */
214extern int es9218_read(int reg);
215extern void es9218_write(int reg, uint8_t val);
216extern void es9218_update(int reg, uint8_t msk, uint8_t val);
217
218/* GPIO pin setting callbacks */
219extern void es9218_set_power_pin(int level);
220extern void es9218_set_reset_pin(int level);
221
222/* XI(MCLK) getter -- supplied by the target.
223 *
224 * Note: when changing the supplied MCLK frequency, the NCO will need to be
225 * reprogrammed for the new master clock. Call es9218_recompute_nco() to
226 * force this. Not necessary if you're not using NCO mode.
227 */
228extern uint32_t es9218_get_mclk(void);
229
230#endif /* __ES9218_H__ */
diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h
index 5b4030bd37..5b83c1bf12 100644
--- a/firmware/target/hosted/sdl/sim-ui-defines.h
+++ b/firmware/target/hosted/sdl/sim-ui-defines.h
@@ -529,6 +529,14 @@
529#define UI_LCD_POSY 15 529#define UI_LCD_POSY 15
530 530
531 531
532#elif defined(SHANLING_Q1)
533#define UI_TITLE "Shanling Q1"
534#define UI_WIDTH 466
535#define UI_HEIGHT 526
536#define UI_LCD_POSX 46
537#define UI_LCD_POSY 61
538
539
532#elif defined(SIMULATOR) 540#elif defined(SIMULATOR)
533#error no UI defines 541#error no UI defines
534#endif 542#endif
diff --git a/firmware/target/mips/ingenic_x1000/debug-x1000.c b/firmware/target/mips/ingenic_x1000/debug-x1000.c
index fe469b1a72..1965b0b74e 100644
--- a/firmware/target/mips/ingenic_x1000/debug-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/debug-x1000.c
@@ -152,6 +152,9 @@ extern bool dbg_fiiom3k_touchpad(void);
152#ifdef HAVE_AXP_PMU 152#ifdef HAVE_AXP_PMU
153extern bool axp_debug_menu(void); 153extern bool axp_debug_menu(void);
154#endif 154#endif
155#ifdef HAVE_CW2015
156extern bool cw2015_debug_menu(void);
157#endif
155 158
156/* Menu definition */ 159/* Menu definition */
157static const struct { 160static const struct {
@@ -170,6 +173,9 @@ static const struct {
170#ifdef HAVE_AXP_PMU 173#ifdef HAVE_AXP_PMU
171 {"Power stats", &axp_debug_menu}, 174 {"Power stats", &axp_debug_menu},
172#endif 175#endif
176#ifdef HAVE_CW2015
177 {"CW2015 debug", &cw2015_debug_menu},
178#endif
173}; 179};
174 180
175static int hw_info_menu_action_cb(int btn, struct gui_synclist* lists) 181static int hw_info_menu_action_cb(int btn, struct gui_synclist* lists)
diff --git a/firmware/target/mips/ingenic_x1000/msc-x1000.c b/firmware/target/mips/ingenic_x1000/msc-x1000.c
index 3b7df1dd01..d0359a53e2 100644
--- a/firmware/target/mips/ingenic_x1000/msc-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/msc-x1000.c
@@ -42,7 +42,7 @@
42#define DEBOUNCE_TIME (HZ/10) 42#define DEBOUNCE_TIME (HZ/10)
43 43
44static const msc_config msc_configs[] = { 44static const msc_config msc_configs[] = {
45#ifdef FIIO_M3K 45#if defined(FIIO_M3K)
46#define MSC_CLOCK_SOURCE X1000_CLK_SCLK_A 46#define MSC_CLOCK_SOURCE X1000_CLK_SCLK_A
47 { 47 {
48 .msc_nr = 0, 48 .msc_nr = 0,
@@ -52,6 +52,17 @@ static const msc_config msc_configs[] = {
52 .cd_gpio = GPIO_MSC0_CD, 52 .cd_gpio = GPIO_MSC0_CD,
53 .cd_active_level = 0, 53 .cd_active_level = 0,
54 }, 54 },
55#elif defined(SHANLING_Q1)
56#define MSC_CLOCK_SOURCE X1000_CLK_MPLL
57 {
58 .msc_nr = 0,
59 .msc_type = MSC_TYPE_SD,
60 .bus_width = 4,
61 .label = "microSD",
62 .cd_gpio = GPIO_MSC0_CD,
63 .cd_active_level = 0,
64 },
65 /* NOTE: SDIO wifi card is on msc1 */
55#else 66#else
56# error "Please add X1000 MSC config" 67# error "Please add X1000 MSC config"
57#endif 68#endif
diff --git a/firmware/target/mips/ingenic_x1000/nand-x1000.c b/firmware/target/mips/ingenic_x1000/nand-x1000.c
index b76efe65e5..de6eb2fb67 100644
--- a/firmware/target/mips/ingenic_x1000/nand-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/nand-x1000.c
@@ -58,7 +58,7 @@
58#define FREG_STATUS_ECC_UNCOR_ERR (2 << 4) 58#define FREG_STATUS_ECC_UNCOR_ERR (2 << 4)
59 59
60const nand_chip supported_nand_chips[] = { 60const nand_chip supported_nand_chips[] = {
61#if defined(FIIO_M3K) 61#if defined(FIIO_M3K) || defined(SHANLING_Q1)
62 { 62 {
63 /* ATO25D1GA */ 63 /* ATO25D1GA */
64 .mf_id = 0x9b, 64 .mf_id = 0x9b,
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/adc-target.h b/firmware/target/mips/ingenic_x1000/shanlingq1/adc-target.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/adc-target.h
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c
new file mode 100644
index 0000000000..7314f20412
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/audiohw-shanlingq1.c
@@ -0,0 +1,191 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "audiohw.h"
23#include "system.h"
24#include "pcm_sampr.h"
25#include "aic-x1000.h"
26#include "i2c-x1000.h"
27#include "gpio-x1000.h"
28#include "x1000/aic.h"
29#include "x1000/cpm.h"
30
31/* Codec has an dedicated oscillator connected, so it can operate
32 * as i2s master or slave. I can't distinguish any difference in
33 * terms of audio quality or power consumption. Code is left here
34 * for reference in case it proves useful to change it. */
35#define CODEC_MASTER_MODE 0
36
37static int cur_fsel = HW_FREQ_48;
38static int cur_vol_l = 0, cur_vol_r = 0;
39static int cur_filter = 0;
40static enum es9218_amp_mode cur_amp_mode = ES9218_AMP_MODE_1VRMS;
41
42static void codec_start(void)
43{
44 es9218_open();
45 es9218_mute(true);
46 es9218_set_iface_role(CODEC_MASTER_MODE ? ES9218_IFACE_ROLE_MASTER
47 : ES9218_IFACE_ROLE_SLAVE);
48 es9218_set_iface_format(ES9218_IFACE_FORMAT_I2S, ES9218_IFACE_BITS_32);
49 es9218_set_dpll_bandwidth(10);
50 es9218_set_thd_compensation(true);
51 es9218_set_thd_coeffs(0, 0);
52 audiohw_set_filter_roll_off(cur_filter);
53 audiohw_set_frequency(cur_fsel);
54 audiohw_set_volume(cur_vol_l, cur_vol_r);
55 es9218_set_amp_mode(cur_amp_mode);
56}
57
58static void codec_stop(void)
59{
60 es9218_mute(true);
61 es9218_close();
62 mdelay(1);
63}
64
65void audiohw_init(void)
66{
67 /* Configure AIC */
68 aic_set_external_codec(true);
69 aic_set_i2s_mode(CODEC_MASTER_MODE ? AIC_I2S_SLAVE_MODE
70 : AIC_I2S_MASTER_MODE);
71 aic_enable_i2s_bit_clock(true);
72
73 /* Open DAC driver */
74 i2c_x1000_set_freq(1, I2C_FREQ_400K);
75 codec_start();
76}
77
78void audiohw_postinit(void)
79{
80 es9218_mute(false);
81}
82
83void audiohw_close(void)
84{
85 codec_stop();
86}
87
88void audiohw_set_frequency(int fsel)
89{
90 int sampr = hw_freq_sampr[fsel];
91
92 /* choose clock gear setting, in line with the OF */
93 enum es9218_clock_gear clkgear;
94 if(sampr <= 48000)
95 clkgear = ES9218_CLK_GEAR_4;
96 else if(sampr <= 96000)
97 clkgear = ES9218_CLK_GEAR_2;
98 else
99 clkgear = ES9218_CLK_GEAR_1;
100
101 aic_enable_i2s_bit_clock(false);
102 es9218_set_clock_gear(clkgear);
103
104 if(CODEC_MASTER_MODE)
105 es9218_set_nco_frequency(sampr);
106 else
107 aic_set_i2s_clock(X1000_CLK_SCLK_A, sampr, 64);
108
109 aic_enable_i2s_bit_clock(true);
110
111 /* save frequency selection */
112 cur_fsel = fsel;
113}
114
115static int round_step_up(int x, int step)
116{
117 int rem = x % step;
118 if(rem > 0)
119 rem -= step;
120 return x - rem;
121}
122
123void audiohw_set_volume(int vol_l, int vol_r)
124{
125 /* save volume */
126 cur_vol_l = vol_l;
127 cur_vol_r = vol_r;
128
129 /* adjust the amp setting first */
130 int amp = round_step_up(MAX(vol_l, vol_r), ES9218_AMP_VOLUME_STEP);
131 amp = MIN(amp, ES9218_AMP_VOLUME_MAX);
132 amp = MAX(amp, ES9218_AMP_VOLUME_MIN);
133
134 /* adjust digital volumes */
135 vol_l -= amp;
136 vol_l = MIN(vol_l, ES9218_DIG_VOLUME_MAX);
137 vol_l = MAX(vol_l, ES9218_DIG_VOLUME_MIN);
138
139 vol_r -= amp;
140 vol_r = MIN(vol_r, ES9218_DIG_VOLUME_MAX);
141 vol_r = MAX(vol_r, ES9218_DIG_VOLUME_MIN);
142
143 /* program DAC */
144 es9218_set_amp_volume(amp);
145 es9218_set_dig_volume(vol_l, vol_r);
146}
147
148void audiohw_set_filter_roll_off(int value)
149{
150 cur_filter = value;
151 es9218_set_filter(value);
152}
153
154void audiohw_set_power_mode(int mode)
155{
156 enum es9218_amp_mode new_amp_mode;
157 if(mode == 0)
158 new_amp_mode = ES9218_AMP_MODE_2VRMS;
159 else
160 new_amp_mode = ES9218_AMP_MODE_1VRMS;
161
162 if(new_amp_mode != cur_amp_mode) {
163 codec_stop();
164 cur_amp_mode = new_amp_mode;
165 codec_start();
166 es9218_mute(false);
167 }
168}
169
170void es9218_set_power_pin(int level)
171{
172 gpio_set_level(GPIO_ES9218_POWER, level ? 1 : 0);
173}
174
175void es9218_set_reset_pin(int level)
176{
177 gpio_set_level(GPIO_ES9218_RESET, level ? 1 : 0);
178}
179
180uint32_t es9218_get_mclk(void)
181{
182 /* Measured by running the DAC in asynchronous I2S slave mode,
183 * and reading back the DPLL number from regs 0x42-0x45 while
184 * playing back 44.1 KHz audio.
185 *
186 * CLK = (44_100 * 2**32) / 0x4b46e5
187 * = 38_393_403.29532737
188 * ~ 38.4 Mhz
189 */
190 return 38400000;
191}
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/backlight-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/backlight-shanlingq1.c
new file mode 100644
index 0000000000..32c1b902aa
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/backlight-shanlingq1.c
@@ -0,0 +1,63 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "backlight.h"
23#include "backlight-target.h"
24#include "lcd.h"
25#include "pwm-x1000.h"
26
27#define BL_LCD_CHN 0
28#define BL_LCD_PERIOD 10000
29
30static int backlight_calc_duty(int period, int min_duty, int brightness)
31{
32 return min_duty + (period - min_duty) * brightness / MAX_BRIGHTNESS_SETTING;
33}
34
35bool backlight_hw_init(void)
36{
37 pwm_init(BL_LCD_CHN);
38 pwm_enable(BL_LCD_CHN);
39 backlight_hw_brightness(MAX_BRIGHTNESS_SETTING);
40 return true;
41}
42
43void backlight_hw_on(void)
44{
45 pwm_enable(BL_LCD_CHN);
46#ifdef HAVE_LCD_ENABLE
47 lcd_enable(true);
48#endif
49}
50
51void backlight_hw_off(void)
52{
53 pwm_disable(BL_LCD_CHN);
54#ifdef HAVE_LCD_ENABLE
55 lcd_enable(false);
56#endif
57}
58
59void backlight_hw_brightness(int brightness)
60{
61 int duty_ns = backlight_calc_duty(BL_LCD_PERIOD, 0, brightness);
62 pwm_set_period(BL_LCD_CHN, BL_LCD_PERIOD, duty_ns);
63}
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/backlight-target.h b/firmware/target/mips/ingenic_x1000/shanlingq1/backlight-target.h
new file mode 100644
index 0000000000..7298c1c06a
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/backlight-target.h
@@ -0,0 +1,33 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __BACKLIGHT_TARGET_H__
23#define __BACKLIGHT_TARGET_H__
24
25#include <stdbool.h>
26
27extern bool backlight_hw_init(void);
28
29extern void backlight_hw_on(void);
30extern void backlight_hw_off(void);
31extern void backlight_hw_brightness(int brightness);
32
33#endif /* __BACKLIGHT_TARGET_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/boot.make b/firmware/target/mips/ingenic_x1000/shanlingq1/boot.make
new file mode 100644
index 0000000000..639f570ea3
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/boot.make
@@ -0,0 +1,31 @@
1# __________ __ ___.
2# Open \______ \ ____ ____ | | _\_ |__ _______ ___
3# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
4# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
5# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
6# \/ \/ \/ \/ \/
7# $Id$
8#
9
10include $(ROOTDIR)/lib/microtar/microtar.make
11
12.SECONDEXPANSION:
13
14# FIXME(q1): verify NAND parameters
15$(BUILDDIR)/spl.q1: $(BUILDDIR)/spl.bin
16 $(call PRINTS,MKSPL $(@F))$(TOOLSDIR)/mkspl-x1000 -type=nand -ppb=2 -bpp=2 $< $@
17
18$(BUILDDIR)/bootloader.ucl: $(BUILDDIR)/bootloader.bin
19 $(call PRINTS,UCLPACK $(@F))$(TOOLSDIR)/uclpack --nrv2e -9 $< $@ >/dev/null
20
21.PHONY: $(BUILDDIR)/bootloader-info.txt
22$(BUILDDIR)/bootloader-info.txt:
23 $(call PRINTS,GEN $(@F))echo $(SVNVERSION) > $@
24
25$(BUILDDIR)/$(BINARY): $(BUILDDIR)/spl.q1 \
26 $(BUILDDIR)/bootloader.ucl \
27 $(BUILDDIR)/bootloader-info.txt
28 $(call PRINTS,TAR $(@F))tar -C $(BUILDDIR) \
29 --numeric-owner --no-acls --no-xattrs --no-selinux \
30 --mode=0644 --owner=0 --group=0 \
31 -cf $@ $(call full_path_subst,$(BUILDDIR)/%,%,$^)
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
new file mode 100644
index 0000000000..27c49a7bd7
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/button-shanlingq1.c
@@ -0,0 +1,195 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 * Copyright (C) 2021 Dana Conrad
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
23#include "button.h"
24#include "touchscreen.h"
25#include "ft6x06.h"
26#include "axp-pmu.h"
27#include "kernel.h"
28#include "backlight.h"
29#include "powermgmt.h"
30#include "gpio-x1000.h"
31#include "irq-x1000.h"
32#include "i2c-x1000.h"
33#include <stdbool.h>
34
35/* Volume wheel rotation */
36static volatile int wheel_pos = 0;
37
38/* Value of headphone detect register */
39static uint8_t hp_detect_reg = 0x00;
40
41/* Interval to poll the register */
42#define HPD_POLL_TIME (HZ/2)
43
44static int hp_detect_tmo_cb(struct timeout* tmo)
45{
46 i2c_descriptor* d = (i2c_descriptor*)tmo->data;
47 i2c_async_queue(AXP_PMU_BUS, TIMEOUT_NOBLOCK, I2C_Q_ADD, 0, d);
48 return HPD_POLL_TIME;
49}
50
51static void hp_detect_init(void)
52{
53 /* TODO: replace this copy paste cruft with an API in axp-pmu */
54 static struct timeout tmo;
55 static const uint8_t gpio_reg = AXP192_REG_GPIOSTATE1;
56 static i2c_descriptor desc = {
57 .slave_addr = AXP_PMU_ADDR,
58 .bus_cond = I2C_START | I2C_STOP,
59 .tran_mode = I2C_READ,
60 .buffer[0] = (void*)&gpio_reg,
61 .count[0] = 1,
62 .buffer[1] = &hp_detect_reg,
63 .count[1] = 1,
64 .callback = NULL,
65 .arg = 0,
66 .next = NULL,
67 };
68
69 /* Headphone detect is wired to AXP192 GPIO: set it to input state */
70 i2c_reg_write1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP192_REG_GPIO1FUNCTION, 0x01);
71
72 /* Get an initial reading before startup */
73 int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, gpio_reg);
74 if(r >= 0)
75 hp_detect_reg = r;
76
77 /* Poll the register every second */
78 timeout_register(&tmo, &hp_detect_tmo_cb, HPD_POLL_TIME, (intptr_t)&desc);
79}
80
81void button_init_device(void)
82{
83 /* Setup interrupts for the volume wheel */
84 gpio_set_function(GPIO_WHEEL1, GPIOF_IRQ_EDGE(0));
85 gpio_set_function(GPIO_WHEEL2, GPIOF_IRQ_EDGE(0));
86 gpio_flip_edge_irq(GPIO_WHEEL1);
87 gpio_flip_edge_irq(GPIO_WHEEL2);
88 gpio_enable_irq(GPIO_WHEEL1);
89 gpio_enable_irq(GPIO_WHEEL2);
90
91 /* Init touchscreen driver */
92 i2c_x1000_set_freq(FT6x06_BUS, I2C_FREQ_400K);
93 ft6x06_init();
94
95 /* Reset touch controller */
96 gpio_set_level(GPIO_FT6x06_POWER, 1);
97 gpio_set_level(GPIO_FT6x06_RESET, 0);
98 mdelay(5);
99 gpio_set_level(GPIO_FT6x06_RESET, 1);
100
101 /* Enable ft6x06 interrupt */
102 system_set_irq_handler(GPIO_TO_IRQ(GPIO_FT6x06_INTERRUPT), ft6x06_irq_handler);
103 gpio_set_function(GPIO_FT6x06_INTERRUPT, GPIOF_IRQ_EDGE(0));
104 gpio_enable_irq(GPIO_FT6x06_INTERRUPT);
105
106 /* Headphone detection */
107 hp_detect_init();
108}
109
110int button_read_device(int* data)
111{
112 int r = 0;
113
114 /* Read GPIO buttons, these are all active low */
115 uint32_t b = REG_GPIO_PIN(GPIO_B);
116 if((b & (1 << 21)) == 0) r |= BUTTON_PREV;
117 if((b & (1 << 22)) == 0) r |= BUTTON_NEXT;
118 if((b & (1 << 28)) == 0) r |= BUTTON_PLAY;
119 if((b & (1 << 31)) == 0) r |= BUTTON_POWER;
120
121 /* Check the wheel */
122 int wheel_btn = 0;
123 int whpos = wheel_pos;
124 if(whpos > 3)
125 wheel_btn = BUTTON_VOL_DOWN;
126 else if(whpos < -3)
127 wheel_btn = BUTTON_VOL_UP;
128
129 if(wheel_btn) {
130 wheel_pos = 0;
131
132 /* Post the event (rapid motion is more reliable this way) */
133 queue_post(&button_queue, wheel_btn, 0);
134 queue_post(&button_queue, wheel_btn|BUTTON_REL, 0);
135
136 /* Poke the backlight */
137 backlight_on();
138 reset_poweroff_timer();
139 }
140
141 /* Handle touchscreen
142 *
143 * TODO: Support 2-point multitouch (useful for 3x3 grid mode)
144 * TODO: Support simple gestures by converting them to fake buttons
145 */
146 int t = touchscreen_to_pixels(ft6x06_state.pos_x, ft6x06_state.pos_y, data);
147 if(ft6x06_state.event == FT6x06_EVT_PRESS ||
148 ft6x06_state.event == FT6x06_EVT_CONTACT) {
149 /* Only set the button bit if the screen is being touched. */
150 r |= t;
151 }
152
153 return r;
154}
155
156void touchscreen_enable_device(bool en)
157{
158 ft6x06_enable(en);
159 /* TODO: check if it's worth shutting off the power pin */
160}
161
162bool headphones_inserted(void)
163{
164 /* TODO: Also check if the headset button is detectable via an ADC.
165 * The AXP driver should probably get proper interrupt handling,
166 * that would be useful for more things than just GPIO polling. */
167 return hp_detect_reg & 0x20 ? true : false;
168}
169
170static void handle_wheel_irq(void)
171{
172 /* Wheel stuff adapted from button-erosqnative.c */
173 static const int delta[16] = { 0, -1, 1, 0,
174 1, 0, 0, -1,
175 -1, 0, 0, 1,
176 0, 1, -1, 0 };
177 static uint32_t state = 0;
178 state <<= 2;
179 state |= (REG_GPIO_PIN(GPIO_D) >> 2) & 3;
180 state &= 0xf;
181
182 wheel_pos += delta[state];
183}
184
185void GPIOD02(void)
186{
187 handle_wheel_irq();
188 gpio_flip_edge_irq(GPIO_WHEEL1);
189}
190
191void GPIOD03(void)
192{
193 handle_wheel_irq();
194 gpio_flip_edge_irq(GPIO_WHEEL2);
195}
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/button-target.h b/firmware/target/mips/ingenic_x1000/shanlingq1/button-target.h
new file mode 100644
index 0000000000..905d148afa
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/button-target.h
@@ -0,0 +1,56 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __BUTTON_TARGET_H__
23#define __BUTTON_TARGET_H__
24
25#include <stdbool.h>
26
27/* physical buttons */
28#define BUTTON_POWER 0x00000001
29#define BUTTON_VOL_UP 0x00000002 /* up = wheel clockwise */
30#define BUTTON_VOL_DOWN 0x00000004
31#define BUTTON_PLAY 0x00000008 /* circle */
32#define BUTTON_NEXT 0x00000010 /* down */
33#define BUTTON_PREV 0x00000020 /* up */
34
35/* compatibility hacks */
36#define BUTTON_LEFT BUTTON_MIDLEFT
37#define BUTTON_RIGHT BUTTON_MIDRIGHT
38
39/* touchscreen "buttons" */
40#define BUTTON_TOPLEFT 0x00000040
41#define BUTTON_TOPMIDDLE 0x00000080
42#define BUTTON_TOPRIGHT 0x00000100
43#define BUTTON_MIDLEFT 0x00000200
44#define BUTTON_CENTER 0x00000400
45#define BUTTON_MIDRIGHT 0x00000800
46#define BUTTON_BOTTOMLEFT 0x00001000
47#define BUTTON_BOTTOMMIDDLE 0x00002000
48#define BUTTON_BOTTOMRIGHT 0x00004000
49
50#define BUTTON_MAIN (BUTTON_POWER|BUTTON_VOL_UP|BUTTON_VOL_DOWN|\
51 BUTTON_PLAY|BUTTON_NEXT|BUTTON_PREV)
52
53#define POWEROFF_BUTTON BUTTON_POWER
54#define POWEROFF_COUNT 30
55
56#endif /* __BUTTON_TARGET_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/gpio-target.h b/firmware/target/mips/ingenic_x1000/shanlingq1/gpio-target.h
new file mode 100644
index 0000000000..7c71d12888
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/gpio-target.h
@@ -0,0 +1,32 @@
1/* Name Port Pins Function */
2DEFINE_PINGROUP(LCD_DATA, GPIO_A, 0xffff << 0, GPIOF_DEVICE(1))
3DEFINE_PINGROUP(LCD_CONTROL, GPIO_B, 0x1a << 16, GPIOF_DEVICE(1))
4DEFINE_PINGROUP(MSC0, GPIO_A, 0x3f << 20, GPIOF_DEVICE(1))
5DEFINE_PINGROUP(SFC, GPIO_A, 0x3f << 26, GPIOF_DEVICE(1))
6DEFINE_PINGROUP(I2S, GPIO_B, 0x1f << 0, GPIOF_DEVICE(1))
7DEFINE_PINGROUP(I2C0, GPIO_B, 3 << 23, GPIOF_DEVICE(0))
8DEFINE_PINGROUP(I2C1, GPIO_C, 3 << 26, GPIOF_DEVICE(0))
9DEFINE_PINGROUP(I2C2, GPIO_D, 3 << 0, GPIOF_DEVICE(1))
10
11/* Name Pin Function */
12DEFINE_GPIO(FT6x06_INTERRUPT, GPIO_PA(16), GPIOF_INPUT)
13DEFINE_GPIO(USB_DETECT, GPIO_PA(17), GPIOF_INPUT)
14DEFINE_GPIO(FT6x06_RESET, GPIO_PA(19), GPIOF_OUTPUT(0))
15DEFINE_GPIO(LCD_PWR, GPIO_PB(6), GPIOF_OUTPUT(1))
16DEFINE_GPIO(FT6x06_POWER, GPIO_PB(8), GPIOF_OUTPUT(0))
17DEFINE_GPIO(MSC0_CD, GPIO_PB(9), GPIOF_INPUT)
18DEFINE_GPIO(ES9218_POWER, GPIO_PB(13), GPIOF_OUTPUT(0))
19DEFINE_GPIO(LCD_RST, GPIO_PB(15), GPIOF_OUTPUT(1))
20DEFINE_GPIO(LCD_RD, GPIO_PB(16), GPIOF_OUTPUT(1))
21DEFINE_GPIO(LCD_CE, GPIO_PB(18), GPIOF_OUTPUT(1))
22DEFINE_GPIO(BTN_PREV, GPIO_PB(21), GPIOF_INPUT)
23DEFINE_GPIO(BTN_NEXT, GPIO_PB(22), GPIOF_INPUT)
24DEFINE_GPIO(USB_DRVVBUS, GPIO_PB(25), GPIOF_OUTPUT(0))
25DEFINE_GPIO(BTN_PLAY, GPIO_PB(28), GPIOF_INPUT)
26DEFINE_GPIO(BTN_POWER, GPIO_PB(31), GPIOF_INPUT)
27DEFINE_GPIO(AXP_IRQ, GPIO_PC(21), GPIOF_INPUT)
28DEFINE_GPIO(USB_ID, GPIO_PC(23), GPIOF_INPUT)
29DEFINE_GPIO(WHEEL1, GPIO_PD(2), GPIOF_INPUT)
30DEFINE_GPIO(WHEEL2, GPIO_PD(3), GPIOF_INPUT)
31DEFINE_GPIO(ES9218_GPIO2, GPIO_PD(4), GPIOF_OUTPUT(0))
32DEFINE_GPIO(ES9218_RESET, GPIO_PD(5), GPIOF_OUTPUT(0))
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/i2c-target.h b/firmware/target/mips/ingenic_x1000/shanlingq1/i2c-target.h
new file mode 100644
index 0000000000..af19aeb28c
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/i2c-target.h
@@ -0,0 +1,40 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#ifndef __I2C_TARGET_H__
23#define __I2C_TARGET_H__
24
25#define I2C_ASYNC_BUS_COUNT 3
26#define I2C_ASYNC_QUEUE_SIZE 4
27
28#define FT6x06_BUS 0
29#define FT6x06_ADDR 0x38
30
31#define ES9218_BUS 1
32#define ES9218_ADDR 0x48
33
34#define AXP_PMU_BUS 2
35#define AXP_PMU_ADDR 0x34
36
37#define CW2015_BUS 2
38#define CW2015_ADDR 0x62
39
40#endif /* __I2C_TARGET_H__ */
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c
new file mode 100644
index 0000000000..532a149185
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/lcd-shanlingq1.c
@@ -0,0 +1,399 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "lcd.h"
23#include "system.h"
24#include "lcd-x1000.h"
25#include "gpio-x1000.h"
26
27/* LCD controller is probably an RM68090.
28 */
29
30static const uint32_t q1_lcd_cmd_enable[] = {
31 LCD_INSTR_CMD, 0x00,
32 LCD_INSTR_CMD, 0xbe,
33 LCD_INSTR_DAT, 0xc3,
34 LCD_INSTR_DAT, 0x29,
35
36 LCD_INSTR_CMD, 0x00,
37 LCD_INSTR_CMD, 0x01,
38 LCD_INSTR_DAT, 0x01,
39 LCD_INSTR_DAT, 0x04,
40
41 LCD_INSTR_CMD, 0x00,
42 LCD_INSTR_CMD, 0x02,
43 LCD_INSTR_DAT, 0x01,
44 LCD_INSTR_DAT, 0x00,
45
46 LCD_INSTR_CMD, 0x00,
47 LCD_INSTR_CMD, 0x03,
48 LCD_INSTR_DAT, 0x00,
49 LCD_INSTR_DAT, 0x10,
50
51 LCD_INSTR_CMD, 0x00,
52 LCD_INSTR_CMD, 0x05,
53 LCD_INSTR_DAT, 0x00,
54 LCD_INSTR_DAT, 0x00,
55
56 LCD_INSTR_CMD, 0x00,
57 LCD_INSTR_CMD, 0x06,
58 LCD_INSTR_DAT, 0x00,
59 LCD_INSTR_DAT, 0x00,
60
61 LCD_INSTR_CMD, 0x00,
62 LCD_INSTR_CMD, 0x07,
63 LCD_INSTR_DAT, 0x01,
64 LCD_INSTR_DAT, 0x03,
65
66 LCD_INSTR_CMD, 0x00,
67 LCD_INSTR_CMD, 0x08,
68 LCD_INSTR_DAT, 0x03,
69 LCD_INSTR_DAT, 0x03,
70
71 LCD_INSTR_CMD, 0x00,
72 LCD_INSTR_CMD, 0x0d,
73 LCD_INSTR_DAT, 0x00,
74 LCD_INSTR_DAT, 0x00,
75
76 LCD_INSTR_CMD, 0x00,
77 LCD_INSTR_CMD, 0x10,
78 LCD_INSTR_DAT, 0x00,
79 LCD_INSTR_DAT, 0xc1,
80
81 LCD_INSTR_CMD, 0x00,
82 LCD_INSTR_CMD, 0x11,
83 LCD_INSTR_DAT, 0xb1,
84 LCD_INSTR_DAT, 0x08,
85
86 LCD_INSTR_CMD, 0x00,
87 LCD_INSTR_CMD, 0x12,
88 LCD_INSTR_DAT, 0xb1,
89 LCD_INSTR_DAT, 0x08,
90
91 LCD_INSTR_CMD, 0x00,
92 LCD_INSTR_CMD, 0x13,
93 LCD_INSTR_DAT, 0x00,
94 LCD_INSTR_DAT, 0x0f,
95
96 LCD_INSTR_CMD, 0x00,
97 LCD_INSTR_CMD, 0x14,
98 LCD_INSTR_DAT, 0x00,
99 LCD_INSTR_DAT, 0x14,
100
101 LCD_INSTR_CMD, 0x00,
102 LCD_INSTR_CMD, 0x15,
103 LCD_INSTR_DAT, 0x00,
104 LCD_INSTR_DAT, 0x04,
105
106 LCD_INSTR_CMD, 0x00,
107 LCD_INSTR_CMD, 0x16,
108 LCD_INSTR_DAT, 0x00,
109 LCD_INSTR_DAT, 0x00,
110
111 LCD_INSTR_CMD, 0x00,
112 LCD_INSTR_CMD, 0x22,
113 LCD_INSTR_DAT, 0x00,
114 LCD_INSTR_DAT, 0x00,
115
116 LCD_INSTR_CMD, 0x00,
117 LCD_INSTR_CMD, 0x23,
118 LCD_INSTR_DAT, 0x00,
119 LCD_INSTR_DAT, 0x00,
120
121 LCD_INSTR_CMD, 0x00,
122 LCD_INSTR_CMD, 0x30,
123 LCD_INSTR_DAT, 0x7c,
124 LCD_INSTR_DAT, 0x3f,
125
126 LCD_INSTR_CMD, 0x00,
127 LCD_INSTR_CMD, 0x32,
128 LCD_INSTR_DAT, 0x00,
129 LCD_INSTR_DAT, 0x00,
130
131 LCD_INSTR_CMD, 0x00,
132 LCD_INSTR_CMD, 0x70,
133 LCD_INSTR_DAT, 0x00,
134 LCD_INSTR_DAT, 0x01,
135
136 LCD_INSTR_CMD, 0x00,
137 LCD_INSTR_CMD, 0x91,
138 LCD_INSTR_DAT, 0x01,
139 LCD_INSTR_DAT, 0x00,
140
141 LCD_INSTR_CMD, 0x00,
142 LCD_INSTR_CMD, 0xe0,
143 LCD_INSTR_DAT, 0x00,
144 LCD_INSTR_DAT, 0x01,
145
146 LCD_INSTR_CMD, 0x00,
147 LCD_INSTR_CMD, 0xe1,
148 LCD_INSTR_DAT, 0x00,
149 LCD_INSTR_DAT, 0x61,
150
151 LCD_INSTR_CMD, 0x01,
152 LCD_INSTR_CMD, 0x00,
153 LCD_INSTR_DAT, 0x10,
154 LCD_INSTR_DAT, 0x30,
155
156 LCD_INSTR_CMD, 0x01,
157 LCD_INSTR_CMD, 0x01,
158 LCD_INSTR_DAT, 0xf6,
159 LCD_INSTR_DAT, 0x3f,
160
161 LCD_INSTR_CMD, 0x01,
162 LCD_INSTR_CMD, 0x02,
163 LCD_INSTR_DAT, 0x50,
164 LCD_INSTR_DAT, 0x1f,
165
166 LCD_INSTR_CMD, 0x01,
167 LCD_INSTR_CMD, 0x03,
168 LCD_INSTR_DAT, 0x00,
169 LCD_INSTR_DAT, 0x30,
170
171 LCD_INSTR_CMD, 0x01,
172 LCD_INSTR_CMD, 0x08,
173 LCD_INSTR_DAT, 0x03,
174 LCD_INSTR_DAT, 0x00,
175
176 LCD_INSTR_CMD, 0x01,
177 LCD_INSTR_CMD, 0x11,
178 LCD_INSTR_DAT, 0x00,
179 LCD_INSTR_DAT, 0x01,
180
181 LCD_INSTR_CMD, 0x01,
182 LCD_INSTR_CMD, 0x35,
183 LCD_INSTR_DAT, 0x76,
184 LCD_INSTR_DAT, 0x66,
185
186 LCD_INSTR_CMD, 0x01,
187 LCD_INSTR_CMD, 0x39,
188 LCD_INSTR_DAT, 0x00,
189 LCD_INSTR_DAT, 0x26,
190
191 LCD_INSTR_CMD, 0x04,
192 LCD_INSTR_CMD, 0x00,
193 LCD_INSTR_DAT, 0x00,
194 LCD_INSTR_DAT, 0xc7,
195
196 LCD_INSTR_CMD, 0x04,
197 LCD_INSTR_CMD, 0x01,
198 LCD_INSTR_DAT, 0x00,
199 LCD_INSTR_DAT, 0x00,
200
201 LCD_INSTR_CMD, 0x06,
202 LCD_INSTR_CMD, 0x06,
203 LCD_INSTR_DAT, 0x00,
204 LCD_INSTR_DAT, 0x00,
205
206 LCD_INSTR_CMD, 0x03,
207 LCD_INSTR_CMD, 0x00,
208 LCD_INSTR_DAT, 0x0d,
209 LCD_INSTR_DAT, 0x0e,
210
211 LCD_INSTR_CMD, 0x03,
212 LCD_INSTR_CMD, 0x01,
213 LCD_INSTR_DAT, 0x00,
214 LCD_INSTR_DAT, 0x03,
215
216 LCD_INSTR_CMD, 0x03,
217 LCD_INSTR_CMD, 0x02,
218 LCD_INSTR_DAT, 0x08,
219 LCD_INSTR_DAT, 0x08,
220
221 LCD_INSTR_CMD, 0x03,
222 LCD_INSTR_CMD, 0x03,
223 LCD_INSTR_DAT, 0x02,
224 LCD_INSTR_DAT, 0x01,
225
226 LCD_INSTR_CMD, 0x03,
227 LCD_INSTR_CMD, 0x04,
228 LCD_INSTR_DAT, 0x03,
229 LCD_INSTR_DAT, 0x01,
230
231 LCD_INSTR_CMD, 0x03,
232 LCD_INSTR_CMD, 0x05,
233 LCD_INSTR_DAT, 0x00,
234 LCD_INSTR_DAT, 0x04,
235
236 LCD_INSTR_CMD, 0x03,
237 LCD_INSTR_CMD, 0x06,
238 LCD_INSTR_DAT, 0x1b,
239 LCD_INSTR_DAT, 0x21,
240
241 LCD_INSTR_CMD, 0x03,
242 LCD_INSTR_CMD, 0x07,
243 LCD_INSTR_DAT, 0x0f,
244 LCD_INSTR_DAT, 0x0e,
245
246 LCD_INSTR_CMD, 0x03,
247 LCD_INSTR_CMD, 0x08,
248 LCD_INSTR_DAT, 0x01,
249 LCD_INSTR_DAT, 0x04,
250
251 LCD_INSTR_CMD, 0x03,
252 LCD_INSTR_CMD, 0x09,
253 LCD_INSTR_DAT, 0x08,
254 LCD_INSTR_DAT, 0x08,
255
256 LCD_INSTR_CMD, 0x03,
257 LCD_INSTR_CMD, 0x0a,
258 LCD_INSTR_DAT, 0x02,
259 LCD_INSTR_DAT, 0x01,
260
261 LCD_INSTR_CMD, 0x03,
262 LCD_INSTR_CMD, 0x0b,
263 LCD_INSTR_DAT, 0x03,
264 LCD_INSTR_DAT, 0x01,
265
266 LCD_INSTR_CMD, 0x03,
267 LCD_INSTR_CMD, 0x0c,
268 LCD_INSTR_DAT, 0x00,
269 LCD_INSTR_DAT, 0x03,
270
271 LCD_INSTR_CMD, 0x03,
272 LCD_INSTR_CMD, 0x0d,
273 LCD_INSTR_DAT, 0x31,
274 LCD_INSTR_DAT, 0x34,
275
276 /* X start */
277 LCD_INSTR_CMD, 0x02,
278 LCD_INSTR_CMD, 0x10,
279 LCD_INSTR_DAT, 0x00,
280 LCD_INSTR_DAT, 0x1e, /* 30 */
281
282 /* X end */
283 LCD_INSTR_CMD, 0x02,
284 LCD_INSTR_CMD, 0x11,
285 LCD_INSTR_DAT, 0x01,
286 LCD_INSTR_DAT, 0x85, /* 389 */
287
288 /* Y start */
289 LCD_INSTR_CMD, 0x02,
290 LCD_INSTR_CMD, 0x12,
291 LCD_INSTR_DAT, 0x00,
292 LCD_INSTR_DAT, 0x00, /* 0 */
293
294 /* Y end */
295 LCD_INSTR_CMD, 0x02,
296 LCD_INSTR_CMD, 0x13,
297 LCD_INSTR_DAT, 0x01,
298 LCD_INSTR_DAT, 0x8f, /* 399 */
299
300 /* RAM write start X? */
301 LCD_INSTR_CMD, 0x02,
302 LCD_INSTR_CMD, 0x00,
303 LCD_INSTR_DAT, 0x00,
304 LCD_INSTR_DAT, 0x1e,
305
306 /* RAM write start Y? */
307 LCD_INSTR_CMD, 0x02,
308 LCD_INSTR_CMD, 0x01,
309 LCD_INSTR_DAT, 0x00,
310 LCD_INSTR_DAT, 0x00,
311
312 LCD_INSTR_CMD, 0x00,
313 LCD_INSTR_CMD, 0x03,
314 LCD_INSTR_DAT, 0x00,
315 LCD_INSTR_DAT, 0x30,
316
317 LCD_INSTR_CMD, 0x02,
318 LCD_INSTR_CMD, 0x02,
319 LCD_INSTR_END,
320};
321
322/* NOTE this sleep mode may not be saving power, but it gets rid of the
323 * ghost image that would otherwise remain on the display */
324static const uint32_t q1_lcd_cmd_sleep[] = {
325 LCD_INSTR_CMD, 0x00,
326 LCD_INSTR_CMD, 0x10,
327 LCD_INSTR_DAT, 0x00,
328 LCD_INSTR_DAT, 0x03,
329
330 LCD_INSTR_CMD, 0x00,
331 LCD_INSTR_CMD, 0x07,
332 LCD_INSTR_DAT, 0x01,
333 LCD_INSTR_DAT, 0x01,
334
335 LCD_INSTR_END,
336};
337
338static const uint32_t q1_lcd_cmd_wake[] = {
339 LCD_INSTR_CMD, 0x00,
340 LCD_INSTR_CMD, 0x07,
341 LCD_INSTR_DAT, 0x01,
342 LCD_INSTR_DAT, 0x03,
343
344 LCD_INSTR_CMD, 0x00,
345 LCD_INSTR_CMD, 0x10,
346 LCD_INSTR_DAT, 0x00,
347 LCD_INSTR_DAT, 0xc1,
348
349 LCD_INSTR_END,
350};
351
352static const uint8_t __attribute__((aligned(64)))
353 q1_lcd_dma_wr_cmd[] = {0x02, 0x02, 0x02, 0x02};
354
355const struct lcd_tgt_config lcd_tgt_config = {
356 .bus_width = 8,
357 .cmd_width = 8,
358 .use_6800_mode = 0,
359 .use_serial = 0,
360 .clk_polarity = 0,
361 .dc_polarity = 0,
362 .wr_polarity = 1,
363 .te_enable = 0,
364 .big_endian = 1,
365 .dma_wr_cmd_buf = &q1_lcd_dma_wr_cmd,
366 .dma_wr_cmd_size = sizeof(q1_lcd_dma_wr_cmd),
367};
368
369void lcd_tgt_enable(bool enable)
370{
371 if(enable) {
372 /* power on the panel */
373 gpio_set_level(GPIO_LCD_PWR, 1);
374 gpio_set_level(GPIO_LCD_RST, 1);
375 gpio_set_level(GPIO_LCD_CE, 1);
376 gpio_set_level(GPIO_LCD_RD, 1);
377 mdelay(50);
378 gpio_set_level(GPIO_LCD_RST, 0);
379 mdelay(100);
380 gpio_set_level(GPIO_LCD_RST, 1);
381 mdelay(50);
382 gpio_set_level(GPIO_LCD_CE, 0);
383
384 /* Start the controller */
385 lcd_set_clock(X1000_CLK_MPLL, 50000000);
386 lcd_exec_commands(q1_lcd_cmd_enable);
387 } else {
388 /* FIXME: Shanling Q1 LCD power down sequence
389 * not important because we don't use it but it'd be nice to know */
390 }
391}
392
393void lcd_tgt_sleep(bool sleep)
394{
395 if(sleep)
396 lcd_exec_commands(q1_lcd_cmd_sleep);
397 else
398 lcd_exec_commands(q1_lcd_cmd_wake);
399}
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
new file mode 100644
index 0000000000..17fbe1cede
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/power-shanlingq1.c
@@ -0,0 +1,140 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "power.h"
23#include "adc.h"
24#include "system.h"
25#include "axp-pmu.h"
26#ifdef HAVE_CW2015
27# include "cw2015.h"
28#endif
29#ifdef HAVE_USB_CHARGING_ENABLE
30# include "usb_core.h"
31#endif
32
33#include "i2c-x1000.h"
34
35/* TODO: Better(?) battery reporting for Q1 using CW2015 driver
36 *
37 * The CW2015 has its own quirks so the driver has to be more complicated
38 * than "read stuff from I2C," unfortunately. Without fixing the quirks it
39 * is probably worse than the simple voltage-based method.
40 *
41 * A bigger problem is that it shares an I2C bus with the AXP192, but when
42 * we attempt to communicate with both chips, they start returning bogus
43 * data intermittently. Ususally, reads will return 0 but sometimes they
44 * can return other nonzero bogus data. It could be that one or the other is
45 * pulling the bus line down inappropriately, or maybe the hardware does not
46 * respect the bus free time between start/stop conditions and one of the
47 * devices is getting confused.
48 */
49
50const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
51{
52 3470
53};
54
55/* the OF shuts down at this voltage */
56const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
57{
58 3400
59};
60
61/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
62const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
63{
64 { 3400, 3639, 3697, 3723, 3757, 3786, 3836, 3906, 3980, 4050, 4159 }
65};
66
67/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
68const unsigned short percent_to_volt_charge[11] =
69{
70 3485, 3780, 3836, 3857, 3890, 3930, 3986, 4062, 4158, 4185, 4196
71};
72
73void power_init(void)
74{
75 i2c_x1000_set_freq(AXP_PMU_BUS, I2C_FREQ_400K);
76 axp_init();
77#ifdef HAVE_CW2015
78 cw2015_init();
79#endif
80
81 /* Change supply voltage from the default of 1250 mV to 1200 mV,
82 * this matches the original firmware's settings. Didn't observe
83 * any obviously bad behavior at 1250 mV, but better to be safe. */
84 axp_supply_set_voltage(AXP_SUPPLY_DCDC2, 1200);
85
86 /* For now, just turn everything on... definitely the touchscreen
87 * is powered by one of the outputs */
88 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
89 AXP_REG_PWROUTPUTCTRL1, 0, 0x05, NULL);
90 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
91 AXP_REG_PWROUTPUTCTRL2, 0, 0x0f, NULL);
92 i2c_reg_modify1(AXP_PMU_BUS, AXP_PMU_ADDR,
93 AXP_REG_DCDCWORKINGMODE, 0, 0xc0, NULL);
94
95 /* Delay to give power output time to stabilize */
96 mdelay(20);
97}
98
99#ifdef HAVE_USB_CHARGING_ENABLE
100void usb_charging_maxcurrent_change(int maxcurrent)
101{
102 axp_set_charge_current(maxcurrent);
103}
104#endif
105
106void power_off(void)
107{
108 axp_power_off();
109 while(1);
110}
111
112bool charging_state(void)
113{
114 return axp_battery_status() == AXP_BATT_CHARGING;
115}
116
117int _battery_voltage(void)
118{
119 /* CW2015 can also read battery voltage, but the AXP consistently
120 * reads ~20-30 mV higher so I suspect it's the "real" voltage. */
121 return axp_adc_read(ADC_BATTERY_VOLTAGE);
122}
123
124#if defined(HAVE_CW2015) && (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) != 0
125int _battery_level(void)
126{
127 return cw2015_get_soc();
128}
129#endif
130
131#if defined(HAVE_CW2015) && (CONFIG_BATTERY_MEASURE & TIME_MEASURE) != 0
132int _battery_time(void)
133{
134 return cw2015_get_rrt();
135}
136#endif
137
138void adc_init(void)
139{
140}
diff --git a/firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c b/firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c
new file mode 100644
index 0000000000..33303c5e6b
--- /dev/null
+++ b/firmware/target/mips/ingenic_x1000/shanlingq1/spl-shanlingq1.c
@@ -0,0 +1,116 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "system.h"
23#include "clk-x1000.h"
24#include "spl-x1000.h"
25#include "gpio-x1000.h"
26
27#define CMDLINE_COMMON \
28 "mem=64M@0x0 no_console_suspend console=ttyS2,115200n8 lpj=5009408 ip=off"
29#define CMDLINE_NORMAL \
30 " init=/linuxrc ubi.mtd=5 root=ubi0:rootfs ubi.mtd=6 rootfstype=ubifs rw"
31
32static int dualboot_setup(void)
33{
34 spl_dualboot_init_clocktree();
35 spl_dualboot_init_uart2();
36
37 /* load PDMA MCU firmware */
38 jz_writef(CPM_CLKGR, PDMA(0));
39 return spl_storage_read(0x4000, 0x2000, (void*)0xb3422000);
40}
41
42const struct spl_boot_option spl_boot_options[] = {
43 [BOOT_OPTION_ROCKBOX] = {
44 .storage_addr = 0x6800,
45 .storage_size = 102 * 1024,
46 .load_addr = X1000_DRAM_BASE,
47 .exec_addr = X1000_DRAM_BASE,
48 .flags = BOOTFLAG_UCLPACK,
49 },
50 [BOOT_OPTION_OFW_PLAYER] = {
51 .storage_addr = 0x140000,
52 .storage_size = 8 * 1024 * 1024,
53 .load_addr = 0x80efffc0,
54 .exec_addr = 0x80f00000,
55 .cmdline = CMDLINE_COMMON CMDLINE_NORMAL,
56 .cmdline_addr = 0x80004000,
57 .setup = dualboot_setup,
58 },
59 [BOOT_OPTION_OFW_RECOVERY] = {
60 .storage_addr = 0x940000,
61 .storage_size = 10 * 1024 * 1024,
62 .load_addr = 0x80efffc0,
63 .exec_addr = 0x80f00000,
64 .cmdline = CMDLINE_COMMON,
65 .cmdline_addr = 0x80004000,
66 .setup = dualboot_setup,
67 },
68};
69
70int spl_get_boot_option(void)
71{
72 /* Button debounce time in OST clock cycles */
73 const uint32_t btn_stable_time = 100 * (X1000_EXCLK_FREQ / 4000);
74
75 /* Buttons to poll */
76 const unsigned port = GPIO_B;
77 const uint32_t recov_pin = (1 << 22); /* Next */
78 const uint32_t orig_fw_pin = (1 << 21); /* Prev */
79
80 uint32_t pin = -1, lastpin = 0;
81 uint32_t deadline = 0;
82 int iter_count = 30; /* to avoid an infinite loop */
83
84 /* set GPIOs to input state */
85 gpioz_configure(port, recov_pin|orig_fw_pin, GPIOF_INPUT);
86
87 /* Poll until we get a stable reading */
88 do {
89 lastpin = pin;
90 pin = ~REG_GPIO_PIN(port) & (recov_pin|orig_fw_pin);
91 if(pin != lastpin) {
92 deadline = __ost_read32() + btn_stable_time;
93 iter_count -= 1;
94 }
95 } while(iter_count > 0 && __ost_read32() < deadline);
96
97 if(iter_count >= 0 && (pin & orig_fw_pin)) {
98 if(pin & recov_pin)
99 return BOOT_OPTION_OFW_RECOVERY;
100 else
101 return BOOT_OPTION_OFW_PLAYER;
102 }
103
104 return BOOT_OPTION_ROCKBOX;
105}
106
107void spl_error(void)
108{
109 /* Flash the backlight */
110 int level = 0;
111 while(1) {
112 gpio_set_function(GPIO_PC(25), GPIOF_OUTPUT(level));
113 mdelay(100);
114 level = 1 - level;
115 }
116}
diff --git a/firmware/target/mips/ingenic_x1000/spl-x1000.c b/firmware/target/mips/ingenic_x1000/spl-x1000.c
index 284b963e97..72dc53b2b7 100644
--- a/firmware/target/mips/ingenic_x1000/spl-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/spl-x1000.c
@@ -34,7 +34,7 @@
34#include "ucl_decompress.h" 34#include "ucl_decompress.h"
35#include <string.h> 35#include <string.h>
36 36
37#ifdef FIIO_M3K 37#if defined(FIIO_M3K) || defined(SHANLING_Q1)
38# define SPL_DDR_MEMORYSIZE 64 38# define SPL_DDR_MEMORYSIZE 64
39# define SPL_DDR_AUTOSR_EN 1 39# define SPL_DDR_AUTOSR_EN 1
40# define SPL_DDR_NEED_BYPASS 1 40# define SPL_DDR_NEED_BYPASS 1
diff --git a/tools/configure b/tools/configure
index 2e06b03717..f32c5d514d 100755
--- a/tools/configure
+++ b/tools/configure
@@ -1597,7 +1597,8 @@ cat <<EOF
1597 240) Rocker 228) NWZ-A860 series 1597 240) Rocker 228) NWZ-A860 series
1598 ==FiiO== 229) NWZ-S750 series 1598 ==FiiO== 229) NWZ-S750 series
1599 ==AIGO== 244) M3K Linux 1599 ==AIGO== 244) M3K Linux
1600 245) Eros Q / K 246) M3K baremetal 1600 245) Eros Q / K 246) M3K baremetal ==Shanling==
1601 260) Q1
1601EOF 1602EOF
1602 1603
1603 buildfor=`input`; 1604 buildfor=`input`;
@@ -4108,6 +4109,30 @@ fi
4108 t_model="fiiom3k" 4109 t_model="fiiom3k"
4109 ;; 4110 ;;
4110 4111
4112 260|shanlingq1)
4113 target_id=115
4114 modelname="shanlingq1"
4115 target="SHANLING_Q1"
4116 memory=64
4117 mipsr2elcc
4118 appextra="recorder:gui"
4119 plugins="yes"
4120 tool="$rootdir/tools/scramble -add=shq1 "
4121 boottool="" # not used
4122 output="rockbox.q1"
4123 bootoutput="bootloader.q1"
4124 sysfontbl="16-Terminus"
4125 # toolset is the tools within the tools directory that we build for
4126 # this particular target.
4127 toolset="$x1000tools"
4128 bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
4129 bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
4130 # architecture, manufacturer and model for the target-tree build
4131 t_cpu="mips"
4132 t_manufacturer="ingenic_x1000"
4133 t_model="shanlingq1"
4134 ;;
4135
4111 *) 4136 *)
4112 echo "Please select a supported target platform!" 4137 echo "Please select a supported target platform!"
4113 exit 7 4138 exit 7
diff --git a/tools/scramble.c b/tools/scramble.c
index 24ed4ba0e6..a75d6df528 100644
--- a/tools/scramble.c
+++ b/tools/scramble.c
@@ -333,6 +333,8 @@ int main (int argc, char** argv)
333 modelnum = 109; 333 modelnum = 109;
334 else if (!strcmp(&argv[1][5], "fiiom3k")) /* FiiO M3K */ 334 else if (!strcmp(&argv[1][5], "fiiom3k")) /* FiiO M3K */
335 modelnum = 114; 335 modelnum = 114;
336 else if (!strcmp(&argv[1][5], "shq1")) /* Shanling Q1 */
337 modelnum = 115;
336 else { 338 else {
337 fprintf(stderr, "unsupported model: %s\n", &argv[1][5]); 339 fprintf(stderr, "unsupported model: %s\n", &argv[1][5]);
338 return 2; 340 return 2;
diff --git a/uisimulator/bitmaps/UI-shanlingq1.bmp b/uisimulator/bitmaps/UI-shanlingq1.bmp
new file mode 100644
index 0000000000..33b86cba2c
--- /dev/null
+++ b/uisimulator/bitmaps/UI-shanlingq1.bmp
Binary files differ
diff --git a/uisimulator/buttonmap/SOURCES b/uisimulator/buttonmap/SOURCES
index 03d4d7caff..8ba566150a 100644
--- a/uisimulator/buttonmap/SOURCES
+++ b/uisimulator/buttonmap/SOURCES
@@ -85,5 +85,7 @@ ihifi2.c
85erosq.c 85erosq.c
86#elif CONFIG_KEYPAD == FIIO_M3K_PAD 86#elif CONFIG_KEYPAD == FIIO_M3K_PAD
87fiio-m3k.c 87fiio-m3k.c
88#elif CONFIG_KEYPAD == SHANLING_Q1_PAD
89shanling-q1.c
88#endif 90#endif
89#endif /* SIMULATOR */ 91#endif /* SIMULATOR */
diff --git a/uisimulator/buttonmap/shanling-q1.c b/uisimulator/buttonmap/shanling-q1.c
new file mode 100644
index 0000000000..da9787ba2e
--- /dev/null
+++ b/uisimulator/buttonmap/shanling-q1.c
@@ -0,0 +1,72 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 by Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#include <SDL.h>
24#include "button.h"
25#include "buttonmap.h"
26
27int key_to_button(int keyboard_button)
28{
29 int new_btn = BUTTON_NONE;
30 switch (keyboard_button)
31 {
32 case SDLK_KP8:
33 case SDLK_UP:
34 new_btn = BUTTON_PREV;
35 break;
36
37 case SDLK_KP2:
38 case SDLK_DOWN:
39 new_btn = BUTTON_NEXT;
40 break;
41
42 case SDLK_KP5:
43 case SDLK_RETURN:
44 case SDLK_SPACE:
45 new_btn = BUTTON_PLAY;
46 break;
47
48 case SDLK_ESCAPE:
49 new_btn = BUTTON_POWER;
50 break;
51
52 case SDLK_KP_PLUS:
53 case SDLK_EQUALS:
54 new_btn = BUTTON_VOL_UP;
55 break;
56
57 case SDLK_KP_MINUS:
58 case SDLK_MINUS:
59 new_btn = BUTTON_VOL_DOWN;
60 break;
61 }
62 return new_btn;
63}
64
65struct button_map bm[] = {
66 { SDLK_KP_PLUS, 426, 140, 40, "Volume +" },
67 { SDLK_KP_MINUS, 426, 180, 40, "Volume -" },
68 { SDLK_SPACE, 0, 244, 40, "Play" },
69 { SDLK_UP, 0, 133, 40, "Previous" },
70 { SDLK_DOWN, 0, 357, 40, "Next" },
71 { 0, 0, 0, 0, "None" }
72};
diff --git a/wps/AUTHORS b/wps/AUTHORS
index 4f0d852286..0afa5b9896 100644
--- a/wps/AUTHORS
+++ b/wps/AUTHORS
@@ -16,6 +16,7 @@ Cabbie v2.0:
16 Johannes Voggenthaler 16 Johannes Voggenthaler
17 Jonathan Gordon 17 Jonathan Gordon
18 Keith Perri 18 Keith Perri
19 Marc Aarts
19 Marc Guay 20 Marc Guay
20 Marcin Bukat 21 Marcin Bukat
21 Marianne Arnold 22 Marianne Arnold
diff --git a/wps/WPSLIST b/wps/WPSLIST
index 70970dee58..efb1030585 100644
--- a/wps/WPSLIST
+++ b/wps/WPSLIST
@@ -82,6 +82,7 @@ RSBS: no
82wps.800x480x(16|24): cabbiev2.800x480x16.wps 82wps.800x480x(16|24): cabbiev2.800x480x16.wps
83wps.480x800x(16|24): cabbiev2.480x800x16.wps 83wps.480x800x(16|24): cabbiev2.480x800x16.wps
84wps.400x240x(16|24): cabbiev2.400x240x16.wps 84wps.400x240x(16|24): cabbiev2.400x240x16.wps
85wps.360x400x16: cabbiev2.360x400x16.wps
85wps.320x480x(16|24): cabbiev2.320x480x16.wps 86wps.320x480x(16|24): cabbiev2.320x480x16.wps
86wps.320x240x(16|24|32): cabbiev2.320x240x16.wps 87wps.320x240x(16|24|32): cabbiev2.320x240x16.wps
87wps.240x400x(16|24): cabbiev2.240x400x16.wps 88wps.240x400x(16|24): cabbiev2.240x400x16.wps
@@ -111,6 +112,7 @@ fms.128x128x2: cabbiev2-128x128x2.fms
111Font.800x480x(16|24): 35-Adobe-Helvetica.fnt 112Font.800x480x(16|24): 35-Adobe-Helvetica.fnt
112Font.480x800x(16|24): 35-Adobe-Helvetica.fnt 113Font.480x800x(16|24): 35-Adobe-Helvetica.fnt
113Font.400x240x(16|24): 15-Adobe-Helvetica.fnt 114Font.400x240x(16|24): 15-Adobe-Helvetica.fnt
115Font.360x400x16: 18-Adobe-Helvetica.fnt
114Font.320x480x(16|24): 27-Adobe-Helvetica.fnt 116Font.320x480x(16|24): 27-Adobe-Helvetica.fnt
115Font.320x240x(16|24): 15-Adobe-Helvetica.fnt 117Font.320x240x(16|24): 15-Adobe-Helvetica.fnt
116Font.240x400x(16|24): 16-Adobe-Helvetica.fnt 118Font.240x400x(16|24): 16-Adobe-Helvetica.fnt
@@ -144,6 +146,7 @@ filetype colours: -
144backdrop.800x480x(16|24): backdrops/cabbiev2.800x480x16.bmp 146backdrop.800x480x(16|24): backdrops/cabbiev2.800x480x16.bmp
145backdrop.480x800x(16|24): backdrops/cabbiev2.480x800x16.bmp 147backdrop.480x800x(16|24): backdrops/cabbiev2.480x800x16.bmp
146backdrop.400x240x(16|24): backdrops/cabbiev2.400x240x16.bmp 148backdrop.400x240x(16|24): backdrops/cabbiev2.400x240x16.bmp
149backdrop.360x400x16: backdrops/cabbiev2.360x400x16.bmp
147backdrop.320x480x(16|24): backdrops/cabbiev2.320x480x16.bmp 150backdrop.320x480x(16|24): backdrops/cabbiev2.320x480x16.bmp
148backdrop.320x240x(16|24): backdrops/cabbiev2.320x240x16.bmp 151backdrop.320x240x(16|24): backdrops/cabbiev2.320x240x16.bmp
149backdrop.128x128x(16|24): backdrops/cabbiev2.128x128x16.bmp 152backdrop.128x128x(16|24): backdrops/cabbiev2.128x128x16.bmp
@@ -170,6 +173,7 @@ selector type..+x2: bar (inverse)
170iconset.800x480x(16|24): icons/tango_icons.32x32.bmp 173iconset.800x480x(16|24): icons/tango_icons.32x32.bmp
171iconset.480x800x(16|24): icons/tango_icons.32x32.bmp 174iconset.480x800x(16|24): icons/tango_icons.32x32.bmp
172iconset.400x240x(16|24): icons/tango_icons.16x16.bmp 175iconset.400x240x(16|24): icons/tango_icons.16x16.bmp
176iconset.360x400x16: icons/tango_icons.32x32.bmp
173iconset.320x480x(16|24): icons/tango_icons.24x24.bmp 177iconset.320x480x(16|24): icons/tango_icons.24x24.bmp
174iconset.320x240x(16|24|32): icons/tango_icons.16x16.bmp 178iconset.320x240x(16|24|32): icons/tango_icons.16x16.bmp
175iconset.128x128x(16|24): icons/tango_icons.12x12.bmp 179iconset.128x128x(16|24): icons/tango_icons.12x12.bmp
@@ -189,6 +193,7 @@ iconset..+x2: icons/tango_small_mono.bmp
189viewers iconset.800x480x(16|24): icons/tango_icons_viewers.32x32.bmp 193viewers iconset.800x480x(16|24): icons/tango_icons_viewers.32x32.bmp
190viewers iconset.480x800x(16|24): icons/tango_icons_viewers.32x32.bmp 194viewers iconset.480x800x(16|24): icons/tango_icons_viewers.32x32.bmp
191viewers iconset.400x240x(16|24): icons/tango_icons_viewers.16x16.bmp 195viewers iconset.400x240x(16|24): icons/tango_icons_viewers.16x16.bmp
196viewers iconset.360x400x16: icons/tango_icons_viewers.32x32.bmp
192viewers iconset.320x480x(16|24): icons/tango_icons_viewers.24x24.bmp 197viewers iconset.320x480x(16|24): icons/tango_icons_viewers.24x24.bmp
193viewers iconset.320x240x(16|24): icons/tango_icons_viewers.16x16.bmp 198viewers iconset.320x240x(16|24): icons/tango_icons_viewers.16x16.bmp
194viewers iconset.128x128x(16|24): icons/tango_icons_viewers.12x12.bmp 199viewers iconset.128x128x(16|24): icons/tango_icons_viewers.12x12.bmp
diff --git a/wps/cabbiev2.360x400x16.wps b/wps/cabbiev2.360x400x16.wps
new file mode 100644
index 0000000000..163d749e50
--- /dev/null
+++ b/wps/cabbiev2.360x400x16.wps
@@ -0,0 +1,81 @@
1# Cabbie v2.0
2# (C) 2007-2012 The Authors (see /rockbox/wps/AUTHORS)
3# Derived from "cabbie" (C) Yohann Misquitta
4#
5# Disable Status Bar
6%wd
7#
8# Load Backdrop
9%X(wpsbackdrop-360x400x16.bmp)
10#
11# Preload Images
12%xl(A,lock-360x400x16.bmp,0,0,2)
13%xl(B,battery-360x400x16.bmp,0,0,10)
14%xl(C,volume-360x400x16.bmp,0,0,10)
15%xl(D,shuffle-360x400x16.bmp,0,0)
16%xl(E,repeat-360x400x16.bmp,0,0,4)
17%xl(F,playmode-360x400x16.bmp,0,0,5)
18#
19# Album Art/Info Viewport Conditional
20%?C<%Vd(a)|%Vd(b)>
21#
22# Progress Bar
23%V(33,316,300,20,-)
24%pb(0,0,-,20,pb-360x400x16.bmp)
25#
26# Hold
27%V(16,365,38,29,-)
28%?mh<%xd(Aa)|%xd(Ab)>
29#
30# Battery
31%V(69,365,66,29,-)
32%?bp<%?bc<%xd(Ba)|%xd(Bb)>|%?bl<|%xd(Bc)|%xd(Bd)|%xd(Be)|%xd(Bf)|%xd(Bg)|%xd(Bh)|%xd(Bi)|%xd(Bj)>>
33#
34# Volume
35%V(147,365,50,29,-)
36%?pv<%xd(Ca)|%xd(Cb)|%xd(Cc)|%xd(Cd)|%xd(Ce)|%xd(Cf)|%xd(Cg)|%xd(Ch)|%xd(Ci)|%xd(Cj)>
37#
38# Shuffle
39%V(208,365,55,29,-)
40%?ps<%xd(D)>
41#
42# Repeat
43%V(273,365,27,29,-)
44%?mm<|%xd(Ea)|%xd(Eb)|%xd(Ec)|%xd(Ed)>
45#
46# Playmode
47%V(309,365,36,29,-)
48%?mp<%xd(Fa)|%xd(Fb)|%xd(Fc)|%xd(Fd)|%xd(Fe)>
49#
50# Time Elapsed/Remaining
51%V(32,339,300,20,-)
52%al%pc%ac%?Sr<%pe %Sx(of) %pp|%pp %Sx(of) %pe>%ar%pr
53#
54# Album Art
55%ax%Vl(a,82,38,195,161,-)
56%Cl(0,0,195,161,c,c)
57%Cd
58#
59# Track Info - Album Art
60%ax%Vl(a,0,206,-,98,1)
61%s%ac%?it<%it|%fn>
62%s%ac%?ia<%ia|%?iA<%iA|%?d(2)<%d(2)|%(root%)>>>
63%s%ac%?id<%id|%?d(1)<%d(1)|%(root%)>>
64
65%s%ac%Sx(Next:) %?Ia<%Ia|%?IA<%IA|%?D(2)<%D(2)|%(root%)>>> - %?It<%It|%Fn>
66#
67# Track Info - No Album Art
68%Vl(b,0,56,-,247,1)
69%s%ac%?it<%it|%fn>
70%s%ac%?ia<%ia|%?iA<%iA|%?d(2)<%d(2)|%(root%)>>>
71%s%ac%?id<%id|%?d(1)<%d(1)|%(root%)>>
72%ac%?iy<%iy|>
73
74%ac%?ig<%ig|>
75%ac%?fv<%(vbr%) |>%fb kbit/s %fc
76
77
78%ac%Sx(Next Track:)
79%ac%s%?It<%It|%Fn>
80%s%ac%?Ia<%Ia|%?IA<%IA|%?D(2)<%D(2)|%(root%)>>>
81%s%ac%?Id<%Id|%?D(1)<%D(1)|%(root%)>>
diff --git a/wps/cabbiev2/battery-360x400x16.bmp b/wps/cabbiev2/battery-360x400x16.bmp
new file mode 100644
index 0000000000..d00b4c1c5d
--- /dev/null
+++ b/wps/cabbiev2/battery-360x400x16.bmp
Binary files differ
diff --git a/wps/cabbiev2/lock-360x400x16.bmp b/wps/cabbiev2/lock-360x400x16.bmp
new file mode 100644
index 0000000000..70c419e875
--- /dev/null
+++ b/wps/cabbiev2/lock-360x400x16.bmp
Binary files differ
diff --git a/wps/cabbiev2/pb-360x400x16.bmp b/wps/cabbiev2/pb-360x400x16.bmp
new file mode 100644
index 0000000000..6b5884d059
--- /dev/null
+++ b/wps/cabbiev2/pb-360x400x16.bmp
Binary files differ
diff --git a/wps/cabbiev2/playmode-360x400x16.bmp b/wps/cabbiev2/playmode-360x400x16.bmp
new file mode 100644
index 0000000000..148376b127
--- /dev/null
+++ b/wps/cabbiev2/playmode-360x400x16.bmp
Binary files differ
diff --git a/wps/cabbiev2/repeat-360x400x16.bmp b/wps/cabbiev2/repeat-360x400x16.bmp
new file mode 100644
index 0000000000..f6fb08d909
--- /dev/null
+++ b/wps/cabbiev2/repeat-360x400x16.bmp
Binary files differ
diff --git a/wps/cabbiev2/shuffle-360x400x16.bmp b/wps/cabbiev2/shuffle-360x400x16.bmp
new file mode 100644
index 0000000000..1b16153176
--- /dev/null
+++ b/wps/cabbiev2/shuffle-360x400x16.bmp
Binary files differ
diff --git a/wps/cabbiev2/volume-360x400x16.bmp b/wps/cabbiev2/volume-360x400x16.bmp
new file mode 100644
index 0000000000..7d8b8e40e8
--- /dev/null
+++ b/wps/cabbiev2/volume-360x400x16.bmp
Binary files differ
diff --git a/wps/cabbiev2/wpsbackdrop-360x400x16.bmp b/wps/cabbiev2/wpsbackdrop-360x400x16.bmp
new file mode 100644
index 0000000000..aa7399bd53
--- /dev/null
+++ b/wps/cabbiev2/wpsbackdrop-360x400x16.bmp
Binary files differ