summaryrefslogtreecommitdiffstats
path: root/firmware/target
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
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')
-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 @@
static struct semaphore headphone_wakeup;
static unsigned int headphone_thread_id;
-static int headphone_stack[200/sizeof(int)]; /* Not much stack needed */
+static unsigned int headphone_stack[176/sizeof(int)]; /* Little stack needed */
static const char * const headphone_thread_name = "headphone";
static bool headphones_detect = false;
/* Convert ADC reading into a button value. */
static int adc_data_to_button(unsigned int data)
{
- int btn = BUTTON_NONE;
-
- if (data < 505)
- {
- if (data < 252)
- {
- if (data < 149)
- {
- if (data >= 64)
- {
- /* Play/Pause */
- btn = BUTTON_RC_PLAY;
- }
- /* else headphone direct */
- }
- else
- {
- /* DSP */
- btn = BUTTON_RC_DSP;
- }
- }
- else
- {
- if (data < 370)
- {
- /* RW */
- btn = BUTTON_RC_REW;
- }
- else
- {
- /* FF */
- btn = BUTTON_RC_FF;
- }
- }
- }
- else
+ /* _______370_______
+ * ___149___ ___675___
+ * ___64__ __252__ __505__ __870__
+ * x PLAY DSP REW FF VOL+ VOL- x
+ *
+ * Child nodes are at 2*n and 2*n+1 per usual bintree array representation
+ */
+ static const unsigned int button_tree[16] =
{
- if (data < 870)
- {
- if (data < 675)
- {
- /* Vol + */
- btn = BUTTON_RC_VOL_UP;
- }
- else
- {
- /* Vol - */
- btn = BUTTON_RC_VOL_DOWN;
- }
- }
-#if 0
- else
- {
-
- if (data < 951)
- {
- /* No buttons */
- }
- else
- {
- /* Not inserted */
-
- }
- }
-#endif
- }
-
- return btn;
+ [ 0] = 0,
+ [ 1] = 370,
+ [ 2] = 149,
+ [ 3] = 675,
+ [ 4] = 64,
+ [ 5] = 252,
+ [ 6] = 505,
+ [ 7] = 870,
+ [ 8] = BUTTON_NONE,
+ [ 9] = BUTTON_RC_PLAY,
+ [10] = BUTTON_RC_DSP,
+ [11] = BUTTON_RC_REW,
+ [12] = BUTTON_RC_FF,
+ [13] = BUTTON_RC_VOL_UP,
+ [14] = BUTTON_RC_VOL_DOWN,
+ [15] = BUTTON_NONE,
+ };
+
+ int i, button;
+
+ asm volatile (
+ "ldr %0, [%2, #1*4] \n" /* button = button_tree[1] */
+ "mov %1, #1 \n" /* i = 1 */
+ "cmp %3, %0 \n" /* C=1 if data > button */
+ "adc %1, %1, %1 \n" /* i = 2*n + C */
+ "ldr %0, [%2, %1, lsl #2] \n" /* button = button_tree[i] */
+ "cmp %3, %0 \n" /* C=1 if data > button */
+ "adc %1, %1, %1 \n" /* i = 2*n + C */
+ "ldr %0, [%2, %1, lsl #2] \n" /* button = button_tree[i] */
+ "cmp %3, %0 \n" /* C=1 if data > button */
+ "adc %1, %1, %1 \n" /* i = 2*n + C */
+ "ldr %0, [%2, %1, lsl #2] \n" /* button = button_tree[i] */
+ : "=&r"(button), "=&r"(i)
+ : "r"(button_tree), "r"(data));
+
+ return button;
}
-static void headphone_thread(void)
+static void NORETURN_ATTR headphone_thread(void)
{
int headphone_sleep_countdown = 0;
int headphone_wait_timeout = TIMEOUT_BLOCK;
+ int last_btn = BUTTON_NONE;
while (1)
{
@@ -123,15 +101,10 @@ static void headphone_thread(void)
if (headphone_sleep_countdown <= 0)
{
/* Polling ADC */
- int btn, btn2;
-
- btn = adc_data_to_button(data);
- sleep(HZ/50);
- data = adc_read(ADC_HPREMOTE);
- btn2 = adc_data_to_button(data);
-
- if (btn != btn2)
+ int btn = adc_data_to_button(data);
+ if (btn != last_btn)
{
+ last_btn = btn;
/* If the buttons dont agree twice in a row, then it's
* none (from meg-fx remote reader). */
btn = BUTTON_NONE;
@@ -154,11 +127,12 @@ static void headphone_thread(void)
/* Cancel any buttons if jack readings are unstable. */
button_headphone_set(BUTTON_NONE);
+ last_btn = BUTTON_NONE;
if (data >= 64 && data <= 951)
{
/* Should be a remote control - accelerate */
- headphone_wait_timeout = HZ/20-HZ/50;
+ headphone_wait_timeout = HZ/25;
headphone_sleep_countdown = 0;
}
else if (rc == OBJ_WAIT_SUCCEEDED)
@@ -187,7 +161,7 @@ bool headphones_inserted(void)
void INIT_ATTR headphone_init(void)
{
/* A thread is required to monitor the remote ADC and jack state. */
- semaphore_init(&headphone_wakeup, 1, 0);
+ semaphore_init(&headphone_wakeup, 1, 1);
headphone_thread_id = create_thread(headphone_thread,
headphone_stack,
sizeof(headphone_stack),
@@ -195,7 +169,6 @@ void INIT_ATTR headphone_init(void)
IF_PRIO(, PRIORITY_REALTIME)
IF_COP(, CPU));
- /* Initially poll and then enable PMIC event */
- headphone_detect_event();
+ /* Enable PMIC event */
mc13783_enable_event(MC13783_ONOFD2_EVENT, true);
}