1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
diff --git a/firmware/export/config/samsungypr0.h b/firmware/export/config/samsungypr0.h
index e97dabc..debe9a3 100644
--- a/firmware/export/config/samsungypr0.h
+++ b/firmware/export/config/samsungypr0.h
@@ -18,9 +18,6 @@
 /*TODO: implement USB data transfer management -> see safe mode script and think a way to implemtent it in the code */
 #define USB_NONE
 
-/* There is only USB charging */
-//#define HAVE_USB_POWER
-
 /* define this if you have a bitmap LCD display */
 #define HAVE_LCD_BITMAP
 
@@ -28,7 +25,6 @@
 #define HAVE_LCD_COLOR
 
 /* define this if the LCD needs to be shutdown */
-/* TODO: Our framebuffer must be closed... */
 #define HAVE_LCD_SHUTDOWN
 
 /* define this if you want album art for this target */
@@ -84,7 +80,6 @@
 /* The number of bytes reserved for loadable plugins */
 #define PLUGIN_BUFFER_SIZE 0x100000
 
-/* We can do AB-repeat -> we use User key, our hotkey */
 #define AB_REPEAT_ENABLE
 #define ACTION_WPSAB_SINGLE ACTION_WPS_HOTKEY
 
@@ -93,10 +88,9 @@
 
 /* R0 KeyPad configuration for plugins */
 #define CONFIG_KEYPAD SAMSUNG_YPR0_PAD
-/* It's better to close /dev/r0Btn at shutdown */
 #define BUTTON_DRIVER_CLOSE
 
-/* The YPR0 has a as3534 codec and we use that to control the volume */
+/* The YPR0 has a as3534 codec */
 #define HAVE_AS3514
 #define HAVE_AS3543
 
@@ -105,10 +99,7 @@
 #define CONFIG_TUNER SI4700
 #define HAVE_TUNER_PWR_CTRL
 
-/* TODO: next step: enable RDS
 #define HAVE_RDS_CAP
-#define RDS_ISR_PROCESSING
-*/
 
 /* Define this for FM radio input available */
 #define HAVE_FMRADIO_IN
@@ -154,5 +145,5 @@
 /* Max IMX37 Cpu Frequency */
 /* #define CPUFREQ_MAX         CPU_FREQ */
 
-/* TODO: my idea is to create a folder in the cramfs [/.rockbox], mounting it by the starter script as the current working directory, so no issues of any type keeping the rockbox folder as in all other players */
+/* This folder resides in the ReadOnly CRAMFS. It is binded to /mnt/media0/.rockbox */
 #define BOOTDIR "/.rockbox"
diff --git a/firmware/target/hosted/ypr0/gpio_ypr0.c b/firmware/target/hosted/ypr0/gpio_ypr0.c
index 3ee371d..f610899 100644
--- a/firmware/target/hosted/ypr0/gpio_ypr0.c
+++ b/firmware/target/hosted/ypr0/gpio_ypr0.c
@@ -37,17 +37,27 @@ void gpio_init(void)
 
 void gpio_close(void)
 {
-    if (r0_gpio_dev < 0)
+    if (r0_gpio_dev >= 0)
         close(r0_gpio_dev);
 }
 
 int gpio_control_struct(int request, R0GPIOInfo r)
 {
-    return ioctl(r0_gpio_dev, request, &r);
+    if (r0_gpio_dev < 0) {
+        return -1;
+    }
+    else {
+        return ioctl(r0_gpio_dev, request, &r);
+    }
 }
 
 int gpio_control(int request, int num, int mode, int val)
 {
-    R0GPIOInfo r = { .num = num, .mode = mode, .val = val, };
-    return ioctl(r0_gpio_dev, request, &r);
-}
+    if (r0_gpio_dev < 0) {
+        return -1;
+    }
+    else {
+        R0GPIOInfo r = { .num = num, .mode = mode, .val = val, };
+        return ioctl(r0_gpio_dev, request, &r);
+    }
+}
\ No newline at end of file
diff --git a/firmware/target/hosted/ypr0/radio-ypr0.c b/firmware/target/hosted/ypr0/radio-ypr0.c
index c3597bd..199b839 100644
--- a/firmware/target/hosted/ypr0/radio-ypr0.c
+++ b/firmware/target/hosted/ypr0/radio-ypr0.c
@@ -25,8 +25,12 @@
 #include <sys/ioctl.h>
 #include "stdint.h"
 #include "string.h"
+#include "kernel.h"
 
 #include "radio-ypr0.h"
+#include "rds.h"
+#include "si4700.h"
+#include "power.h"
 
 static int radio_dev = -1;
 
@@ -63,4 +67,51 @@ int fmradio_i2c_read(unsigned char address, unsigned char* buf, int count)
     (void)address;
     sSi4709_i2c_t r = { .size = count, .buf = buf };
     return ioctl(radio_dev, IOCTL_SI4709_I2C_READ, &r);
-}
\ No newline at end of file
+}
+
+#ifdef HAVE_RDS_CAP
+
+/* Register we are going to poll */
+#define STATUSRSSI  0xA
+#define STATUSRSSI_RDSR     (0x1 << 15)
+
+/* Low-level RDS Support */
+static uint32_t rds_stack[DEFAULT_STACK_SIZE / sizeof(uint32_t)];
+static uint16_t rds_data[4];
+
+/* Captures RDS data and processes it */
+static inline void rds_polling(void)
+{
+    if (tuner_powered()) {
+        if ((si4709_read_reg(STATUSRSSI) & STATUSRSSI_RDSR) >> 8) {
+            if (si4700_rds_read_raw(rds_data) && rds_process(rds_data))
+                si4700_rds_set_event();
+        }
+        sleep(2);
+    }
+    else {
+        sleep(50);
+    }
+}
+
+static void NORETURN_ATTR rds_thread(void)
+{
+    while (true)
+        rds_polling();
+}
+
+/* true after full radio power up, and false before powering down */
+void si4700_rds_powerup(bool on)
+{
+    (void)on;
+}
+
+/* One-time RDS init at startup */
+void si4700_rds_init(void)
+{
+    rds_init();
+    create_thread(rds_thread, rds_stack, sizeof(rds_stack), 0, "rds"
+        IF_PRIO(, PRIORITY_REALTIME) IF_COP(, CPU));
+
+}
+#endif /* HAVE_RDS_CAP */
\ No newline at end of file