rotary_encoder: increase/decrease on both rest states
Subsystems (2)
PATCH 1/3 rotary_encoder: increase/decrease on both rest states
Replaced the armed and dir states with a single last_state field. The rotary encoder does now increase on both "00" and "11".
It also fixes the "pumping" problem. If the rotary encoder is moved forward and backwards over a single pump, it will only increase or decrease in one direction. An example for this "pumping" using gray codes
The encoder rotates one step: "11" => "10" => "00" (now it is increased)
The encoder rotates back: "00" => "10" => "11" (now it won't decrease)
Signed-off-by Jelle Martijn Kok <[email protected]>
--- drivers/input/misc/rotary_encoder.c | 77 ++++++++++++++++------------------ 1 files changed, 36 insertions(+), 41 deletions(-)
drivers/input/misc/rotary_encoder.c +36 -41
@@ -36,8 +36,7 @@ struct rotary_encoder {unsigned int irq_a;unsigned int irq_b; -bool armed; -unsigned char dir;/* 0 - clockwise, 1 - CCW */ +int last_state; };static irqreturn_t rotary_encoder_irq (int irq,void *dev_id)
@@ -52,51 +51,47 @@ static irqreturn_t rotary_encoder_irq(int irq, void *dev_id) b ^= pdata->inverted_b; state = (a <<1 ) | b; -switch (state) { - -case 0x0 : -if (!encoder->armed) -break ; - -if (pdata->relative_axis) { -input_report_rel (encoder->input, pdata->axis, - encoder->dir ?-1 :1 ); - }else { -unsigned int pos = encoder->pos; +if (((state ==0x0 ) || (state ==0x3 )) && ((encoder->last_state ==0x01 ) || (encoder->last_state ==0x02 ))) { +int state_exor = state ^ encoder->last_state; +int dir =0 ; +if (state_exor ==0x01 ) { + dir =+1 ; + } +else { + dir =-1 ; + } -if (encoder->dir) { -/* turning counter-clockwise */ -if (pdata->rollover) - pos += pdata->steps; -if (pos) - pos--; +if (dir) { +if (pdata->relative_axis) { +input_report_rel (encoder->input, pdata->axis, + dir); }else { -/* turning clockwise */ -if (pdata->rollover || pos < pdata->steps) - pos++; +unsigned int pos = encoder->pos; + +if (dir ==-1 ) { +/* turning counter-clockwise */ +if (pdata->rollover) + pos += pdata->steps; +if (pos) + pos--; + }else { +/* turning clockwise */ +if (pdata->rollover || pos < pdata->steps) + pos++; + } +if (pdata->rollover) + pos %= pdata->steps; + encoder->pos = pos; +input_report_abs (encoder->input, pdata->axis, + encoder->pos); } -if (pdata->rollover) - pos %= pdata->steps; - encoder->pos = pos; -input_report_abs (encoder->input, pdata->axis, - encoder->pos); +input_sync (encoder->input); } -input_sync (encoder->input); - - encoder->armed = false; -break ; - -case 0x1 : -case 0x2 : -if (encoder->armed) - encoder->dir = state -1 ; -break ; - -case 0x3 : - encoder->armed = true; -break ; } +/* always store the state - even on 00 or 11 */ + encoder->last_state = state; +return IRQ_HANDLED ; }
Signature · 1 line
1.7.0.4