summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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}