= Encoders = On the [http://www.e39-forum.de E39-forum.de] somebody found out the manufacturer of compatible rotating knobs for the 4:3 monitor. I think for the 16:9 it could be the same. The original knobs where a special development for Alpina. The compatible one is that one: Grayhill 61C22-01-04-02, [http://datasheet.octopart.com/61C22-01-04-02-Grayhill-datasheet-67218.pdf data sheet]. == Two types == In the original bord monitor there are two types of rotary knobs. The left one, is responsible for volume setting, which is also called RADIO knob. The right one, responsible for menu navigation, which is also called BMBT knob. The interesting part about both of them, they are of different hardware types. The right one, is mainly hall-effect based type, which gives a grey code sequence on its both ends: 00-01-11-10-00. The sequence depends on the direction of the rotation. The output is changed step-by-step. The left one, is optically based and gives a sequence: 00-11-00 on each rotation step. However, inbetween this output the bits 01 or 11 are also triggered, to indicate the direction. In the internet there is tons of codes which show how to interface such encoders. Here is a simplified example of how I am interfacing these both encoders: {{{ #!div style="font-size: 0.75em;" {{{ #!c // definitions #define ENC_BMBT_OUT1 (1 << 1) #define ENC_BMBT_OUT2 (1 << 2) #define ENC_BMBT 0 #define ENC_RADIO_OUT1 (1 << 6) #define ENC_RADIO_OUT2 (1 << 5) #define ENC_RADIO 1 // global variables to remember current states uint8_t g_enc_last[2]; uint8_t g_enc_delta[2]; // special tracking of radio encoders, since they have intermediate states int8_t g_enc_last_radioRotaryStateCW; int8_t g_enc_last_radioRotaryStateCCW; ... void check_encoders() { // poll current state of both encoders uint8_t state = get_encoder_state(); // get value for BMBT encoder int8_t new = 0; if( (state & ENC_BMBT_OUT1) ) new = 0b11; if( (state & ENC_BMBT_OUT2) ) new ^= 0b01; int8_t diff = g_enc_last[ENC_BMBT] - new; if( diff & 1 ) { g_enc_last[ENC_BMBT] = new; g_enc_delta[ENC_BMBT] += (diff & 2) - 1; // bit 1 = direction (+/-) } if (g_enc_delta[ENC_BMBT] < 0) { set_active(BMBT_CCW); set_not_active(BMBT_CW); }else if (g_enc_delta[ENC_BMBT] > 0) { set_active(BMBT_CW); set_not_active(BMBT_CCW); } g_enc_delta[ENC_BMBT] = 0; // check state of RADIO encoder new = 0; if( (state & ENC_RADIO_OUT1) ) new = 0b11; if( (state & ENC_RADIO_OUT2) ) new ^= 0b01; diff = g_enc_last[ENC_RADIO] - new; if( diff & 1 ) { g_enc_last[ENC_RADIO] = new; g_enc_delta[ENC_RADIO] += (diff & 2) - 1; // bit 1 = direction (+/-) } if (g_enc_delta[ENC_RADIO] < 0 && !g_enc_last_radioRotaryStateCCW) { set_active(RADIO_CCW); set_not_active(RADIO_CW); }else if (g_enc_delta[ENC_RADIO] > 0 && !g_enc_last_radioRotaryStateCW) { set_active(RADIO_CW); set_not_active(RADIO_CCW); } g_enc_delta[ENC_RADIO] = 0; } }}} }}}