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
This commit is contained in:
parent
c64b59fc5e
commit
669fa9a130
1 changed files with 51 additions and 78 deletions
|
@ -31,87 +31,65 @@
|
||||||
|
|
||||||
static struct semaphore headphone_wakeup;
|
static struct semaphore headphone_wakeup;
|
||||||
static unsigned int headphone_thread_id;
|
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 const char * const headphone_thread_name = "headphone";
|
||||||
static bool headphones_detect = false;
|
static bool headphones_detect = false;
|
||||||
|
|
||||||
/* Convert ADC reading into a button value. */
|
/* Convert ADC reading into a button value. */
|
||||||
static int adc_data_to_button(unsigned int data)
|
static int adc_data_to_button(unsigned int data)
|
||||||
{
|
{
|
||||||
int btn = BUTTON_NONE;
|
/* _______370_______
|
||||||
|
* ___149___ ___675___
|
||||||
if (data < 505)
|
* ___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 < 252)
|
[ 0] = 0,
|
||||||
{
|
[ 1] = 370,
|
||||||
if (data < 149)
|
[ 2] = 149,
|
||||||
{
|
[ 3] = 675,
|
||||||
if (data >= 64)
|
[ 4] = 64,
|
||||||
{
|
[ 5] = 252,
|
||||||
/* Play/Pause */
|
[ 6] = 505,
|
||||||
btn = BUTTON_RC_PLAY;
|
[ 7] = 870,
|
||||||
}
|
[ 8] = BUTTON_NONE,
|
||||||
/* else headphone direct */
|
[ 9] = BUTTON_RC_PLAY,
|
||||||
}
|
[10] = BUTTON_RC_DSP,
|
||||||
else
|
[11] = BUTTON_RC_REW,
|
||||||
{
|
[12] = BUTTON_RC_FF,
|
||||||
/* DSP */
|
[13] = BUTTON_RC_VOL_UP,
|
||||||
btn = BUTTON_RC_DSP;
|
[14] = BUTTON_RC_VOL_DOWN,
|
||||||
}
|
[15] = BUTTON_NONE,
|
||||||
}
|
};
|
||||||
else
|
|
||||||
{
|
|
||||||
if (data < 370)
|
|
||||||
{
|
|
||||||
/* RW */
|
|
||||||
btn = BUTTON_RC_REW;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* FF */
|
|
||||||
btn = BUTTON_RC_FF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
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)
|
int i, button;
|
||||||
{
|
|
||||||
/* No buttons */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Not inserted */
|
|
||||||
|
|
||||||
}
|
asm volatile (
|
||||||
}
|
"ldr %0, [%2, #1*4] \n" /* button = button_tree[1] */
|
||||||
#endif
|
"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 btn;
|
return button;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void headphone_thread(void)
|
static void NORETURN_ATTR headphone_thread(void)
|
||||||
{
|
{
|
||||||
int headphone_sleep_countdown = 0;
|
int headphone_sleep_countdown = 0;
|
||||||
int headphone_wait_timeout = TIMEOUT_BLOCK;
|
int headphone_wait_timeout = TIMEOUT_BLOCK;
|
||||||
|
int last_btn = BUTTON_NONE;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
@ -123,15 +101,10 @@ static void headphone_thread(void)
|
||||||
if (headphone_sleep_countdown <= 0)
|
if (headphone_sleep_countdown <= 0)
|
||||||
{
|
{
|
||||||
/* Polling ADC */
|
/* Polling ADC */
|
||||||
int btn, btn2;
|
int btn = adc_data_to_button(data);
|
||||||
|
if (btn != last_btn)
|
||||||
btn = adc_data_to_button(data);
|
|
||||||
sleep(HZ/50);
|
|
||||||
data = adc_read(ADC_HPREMOTE);
|
|
||||||
btn2 = adc_data_to_button(data);
|
|
||||||
|
|
||||||
if (btn != btn2)
|
|
||||||
{
|
{
|
||||||
|
last_btn = btn;
|
||||||
/* If the buttons dont agree twice in a row, then it's
|
/* If the buttons dont agree twice in a row, then it's
|
||||||
* none (from meg-fx remote reader). */
|
* none (from meg-fx remote reader). */
|
||||||
btn = BUTTON_NONE;
|
btn = BUTTON_NONE;
|
||||||
|
@ -154,11 +127,12 @@ static void headphone_thread(void)
|
||||||
|
|
||||||
/* Cancel any buttons if jack readings are unstable. */
|
/* Cancel any buttons if jack readings are unstable. */
|
||||||
button_headphone_set(BUTTON_NONE);
|
button_headphone_set(BUTTON_NONE);
|
||||||
|
last_btn = BUTTON_NONE;
|
||||||
|
|
||||||
if (data >= 64 && data <= 951)
|
if (data >= 64 && data <= 951)
|
||||||
{
|
{
|
||||||
/* Should be a remote control - accelerate */
|
/* Should be a remote control - accelerate */
|
||||||
headphone_wait_timeout = HZ/20-HZ/50;
|
headphone_wait_timeout = HZ/25;
|
||||||
headphone_sleep_countdown = 0;
|
headphone_sleep_countdown = 0;
|
||||||
}
|
}
|
||||||
else if (rc == OBJ_WAIT_SUCCEEDED)
|
else if (rc == OBJ_WAIT_SUCCEEDED)
|
||||||
|
@ -187,7 +161,7 @@ bool headphones_inserted(void)
|
||||||
void INIT_ATTR headphone_init(void)
|
void INIT_ATTR headphone_init(void)
|
||||||
{
|
{
|
||||||
/* A thread is required to monitor the remote ADC and jack state. */
|
/* 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_thread_id = create_thread(headphone_thread,
|
||||||
headphone_stack,
|
headphone_stack,
|
||||||
sizeof(headphone_stack),
|
sizeof(headphone_stack),
|
||||||
|
@ -195,7 +169,6 @@ void INIT_ATTR headphone_init(void)
|
||||||
IF_PRIO(, PRIORITY_REALTIME)
|
IF_PRIO(, PRIORITY_REALTIME)
|
||||||
IF_COP(, CPU));
|
IF_COP(, CPU));
|
||||||
|
|
||||||
/* Initially poll and then enable PMIC event */
|
/* Enable PMIC event */
|
||||||
headphone_detect_event();
|
|
||||||
mc13783_enable_event(MC13783_ONOFD2_EVENT, true);
|
mc13783_enable_event(MC13783_ONOFD2_EVENT, true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue