summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx31
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2013-08-31 22:18:19 -0400
committerMichael Sevakis <jethead71@rockbox.org>2014-03-06 17:28:26 -0500
commit669fa9a13002835a139b72db80a2a3ee69fa434e (patch)
tree1dcd918c147381299917db26cfd0ca1a20dd3576 /firmware/target/arm/imx31
parentc64b59fc5eea973ae82430f98046d4cd2af15160 (diff)
downloadrockbox-669fa9a13002835a139b72db80a2a3ee69fa434e.tar.gz
rockbox-669fa9a13002835a139b72db80a2a3ee69fa434e.zip
Gigabeat S: Improve headphone thread implementation.
Implement scanning as binary tree in array. Make the ADC calls fewer without compromising read quality. Declare the thread function as 'noreturn' to save some stack. Reduce stack size (regardless, % use is now a bit lower). Change-Id: I239792fd2a0a2c019d1ec4af1d6d4b466cdf0ef5
Diffstat (limited to 'firmware/target/arm/imx31')
-rw-r--r--firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c135
1 files changed, 54 insertions, 81 deletions
diff --git a/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c b/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c
index 4e1792d467..6fdde32185 100644
--- a/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c
+++ b/firmware/target/arm/imx31/gigabeat-s/headphone-gigabeat-s.c
@@ -31,87 +31,65 @@
31 31
32static struct semaphore headphone_wakeup; 32static struct semaphore headphone_wakeup;
33static unsigned int headphone_thread_id; 33static unsigned int headphone_thread_id;
34static int headphone_stack[200/sizeof(int)]; /* Not much stack needed */ 34static unsigned int headphone_stack[176/sizeof(int)]; /* Little stack needed */
35static const char * const headphone_thread_name = "headphone"; 35static const char * const headphone_thread_name = "headphone";
36static bool headphones_detect = false; 36static bool headphones_detect = false;
37 37
38/* Convert ADC reading into a button value. */ 38/* Convert ADC reading into a button value. */
39static int adc_data_to_button(unsigned int data) 39static int adc_data_to_button(unsigned int data)
40{ 40{
41 int btn = BUTTON_NONE; 41 /* _______370_______
42 42 * ___149___ ___675___
43 if (data < 505) 43 * ___64__ __252__ __505__ __870__
44 { 44 * x PLAY DSP REW FF VOL+ VOL- x
45 if (data < 252) 45 *
46 { 46 * Child nodes are at 2*n and 2*n+1 per usual bintree array representation
47 if (data < 149) 47 */
48 { 48 static const unsigned int button_tree[16] =
49 if (data >= 64)
50 {
51 /* Play/Pause */
52 btn = BUTTON_RC_PLAY;
53 }
54 /* else headphone direct */
55 }
56 else
57 {
58 /* DSP */
59 btn = BUTTON_RC_DSP;
60 }
61 }
62 else
63 {
64 if (data < 370)
65 {
66 /* RW */
67 btn = BUTTON_RC_REW;
68 }
69 else
70 {
71 /* FF */
72 btn = BUTTON_RC_FF;
73 }
74 }
75 }
76 else
77 { 49 {
78 if (data < 870) 50 [ 0] = 0,
79 { 51 [ 1] = 370,
80 if (data < 675) 52 [ 2] = 149,
81 { 53 [ 3] = 675,
82 /* Vol + */ 54 [ 4] = 64,
83 btn = BUTTON_RC_VOL_UP; 55 [ 5] = 252,
84 } 56 [ 6] = 505,
85 else 57 [ 7] = 870,
86 { 58 [ 8] = BUTTON_NONE,
87 /* Vol - */ 59 [ 9] = BUTTON_RC_PLAY,
88 btn = BUTTON_RC_VOL_DOWN; 60 [10] = BUTTON_RC_DSP,
89 } 61 [11] = BUTTON_RC_REW,
90 } 62 [12] = BUTTON_RC_FF,
91#if 0 63 [13] = BUTTON_RC_VOL_UP,
92 else 64 [14] = BUTTON_RC_VOL_DOWN,
93 { 65 [15] = BUTTON_NONE,
94 66 };
95 if (data < 951) 67
96 { 68 int i, button;
97 /* No buttons */ 69
98 } 70 asm volatile (
99 else 71 "ldr %0, [%2, #1*4] \n" /* button = button_tree[1] */
100 { 72 "mov %1, #1 \n" /* i = 1 */
101 /* Not inserted */ 73 "cmp %3, %0 \n" /* C=1 if data > button */
102 74 "adc %1, %1, %1 \n" /* i = 2*n + C */
103 } 75 "ldr %0, [%2, %1, lsl #2] \n" /* button = button_tree[i] */
104 } 76 "cmp %3, %0 \n" /* C=1 if data > button */
105#endif 77 "adc %1, %1, %1 \n" /* i = 2*n + C */
106 } 78 "ldr %0, [%2, %1, lsl #2] \n" /* button = button_tree[i] */
107 79 "cmp %3, %0 \n" /* C=1 if data > button */
108 return btn; 80 "adc %1, %1, %1 \n" /* i = 2*n + C */
81 "ldr %0, [%2, %1, lsl #2] \n" /* button = button_tree[i] */
82 : "=&r"(button), "=&r"(i)
83 : "r"(button_tree), "r"(data));
84
85 return button;
109} 86}
110 87
111static void headphone_thread(void) 88static void NORETURN_ATTR headphone_thread(void)
112{ 89{
113 int headphone_sleep_countdown = 0; 90 int headphone_sleep_countdown = 0;
114 int headphone_wait_timeout = TIMEOUT_BLOCK; 91 int headphone_wait_timeout = TIMEOUT_BLOCK;
92 int last_btn = BUTTON_NONE;
115 93
116 while (1) 94 while (1)
117 { 95 {
@@ -123,15 +101,10 @@ static void headphone_thread(void)
123 if (headphone_sleep_countdown <= 0) 101 if (headphone_sleep_countdown <= 0)
124 { 102 {
125 /* Polling ADC */ 103 /* Polling ADC */
126 int btn, btn2; 104 int btn = adc_data_to_button(data);
127 105 if (btn != last_btn)
128 btn = adc_data_to_button(data);
129 sleep(HZ/50);
130 data = adc_read(ADC_HPREMOTE);
131 btn2 = adc_data_to_button(data);
132
133 if (btn != btn2)
134 { 106 {
107 last_btn = btn;
135 /* If the buttons dont agree twice in a row, then it's 108 /* If the buttons dont agree twice in a row, then it's
136 * none (from meg-fx remote reader). */ 109 * none (from meg-fx remote reader). */
137 btn = BUTTON_NONE; 110 btn = BUTTON_NONE;
@@ -154,11 +127,12 @@ static void headphone_thread(void)
154 127
155 /* Cancel any buttons if jack readings are unstable. */ 128 /* Cancel any buttons if jack readings are unstable. */
156 button_headphone_set(BUTTON_NONE); 129 button_headphone_set(BUTTON_NONE);
130 last_btn = BUTTON_NONE;
157 131
158 if (data >= 64 && data <= 951) 132 if (data >= 64 && data <= 951)
159 { 133 {
160 /* Should be a remote control - accelerate */ 134 /* Should be a remote control - accelerate */
161 headphone_wait_timeout = HZ/20-HZ/50; 135 headphone_wait_timeout = HZ/25;
162 headphone_sleep_countdown = 0; 136 headphone_sleep_countdown = 0;
163 } 137 }
164 else if (rc == OBJ_WAIT_SUCCEEDED) 138 else if (rc == OBJ_WAIT_SUCCEEDED)
@@ -187,7 +161,7 @@ bool headphones_inserted(void)
187void INIT_ATTR headphone_init(void) 161void INIT_ATTR headphone_init(void)
188{ 162{
189 /* A thread is required to monitor the remote ADC and jack state. */ 163 /* A thread is required to monitor the remote ADC and jack state. */
190 semaphore_init(&headphone_wakeup, 1, 0); 164 semaphore_init(&headphone_wakeup, 1, 1);
191 headphone_thread_id = create_thread(headphone_thread, 165 headphone_thread_id = create_thread(headphone_thread,
192 headphone_stack, 166 headphone_stack,
193 sizeof(headphone_stack), 167 sizeof(headphone_stack),
@@ -195,7 +169,6 @@ void INIT_ATTR headphone_init(void)
195 IF_PRIO(, PRIORITY_REALTIME) 169 IF_PRIO(, PRIORITY_REALTIME)
196 IF_COP(, CPU)); 170 IF_COP(, CPU));
197 171
198 /* Initially poll and then enable PMIC event */ 172 /* Enable PMIC event */
199 headphone_detect_event();
200 mc13783_enable_event(MC13783_ONOFD2_EVENT, true); 173 mc13783_enable_event(MC13783_ONOFD2_EVENT, true);
201} 174}