+static
+void shiftreg(uint8_t* d){
+ uint8_t c, c2;
+ c=d[0]>>7;
+ d[0] <<= 1;
+ c2=d[1]>>7;
+ d[1] = (d[1]<<1) | c;
+ d[2] = (d[2]<<1) | c2;
+}
+
+ uint8_t parity3_lut[] PROGMEM = {0, 1, 1, 0,
+ 1, 0, 0, 1};
+ uint8_t clock_lut[] PROGMEM = {0x7, 0x6, 0x5, 0x3,
+ 0x3, 0x5, 0x6, 0x7};
+
+uint8_t a5_1_clock_core(a5_1_ctx_t *c, uint8_t clockoverride){
+ uint8_t ret,clk,fb;
+ ret = (0x04&c->r1[2]) | (0x20&c->r2[2]) | (0x40&c->r3[2]);
+ ret = ret^(ret>>6);
+ ret &= 0x7;
+ ret = pgm_read_byte(parity3_lut+ret);
+ clk = (0x08&c->r1[1]) | (0x10&c->r2[1]) | (0x20&c->r3[1]);
+ clk >>= 3;
+ clk = pgm_read_byte(clock_lut+clk);
+ clk |= clockoverride;
+
+ if(clk&1){
+ fb = c->r1[2] ^ (1&((c->r1[1])>>5));
+ fb &= 0x7;
+ fb = pgm_read_byte(parity3_lut+fb);
+ shiftreg(c->r1);
+ c->r1[0] |= fb;
+ c->r1[2] &= 0x07;
+ }
+ clk>>=1;
+ if(clk&1){
+ fb = c->r2[2]>>4 ;
+ fb &= 0x7;
+ fb = pgm_read_byte(parity3_lut+fb);
+ shiftreg(c->r2);
+ c->r2[0] |= fb;
+ c->r2[2] &= 0x3F;
+
+ }
+ clk>>=1;
+ if(clk&1){
+ fb = (c->r3[2]>>4) ^ (1&((c->r3[0])>>7));
+ fb &= 0x7;
+ fb = pgm_read_byte(parity3_lut+fb);
+ shiftreg(c->r3);
+ c->r3[0] |= fb;
+ c->r3[2] &= 0x7F;
+ }
+ return ret;
+}
+
+uint8_t a5_1_clock(a5_1_ctx_t *c){
+ return a5_1_clock_core(c, 0);
+}
+
+
+uint8_t a5_1_gen(a5_1_ctx_t *c){