/* KC85 Keyboard changes to make consistent output - "A" is now 0x03 like in my chart - debounce - happiness version 26.07.2025 V0: USB-keyboard function: ********************************************* FOR EASIER FLASHING: pin 9 is inputpullup: wen tied to ground the pro micro does not act like a keyboard ********************************************* * * */ /* * scannumber * * * * */ #include #define Serialbaudrate 115200 #define jumperin 9 // Times, wir bleiben daruntger, weil wir nachher der größe nach abfragen, ob größer als #define TIME_MINIMUM 1000 #define TIME_ZERO 4800//unter 5000 //tD0 = 5 tu = 5,12 ms Pulsabstand für logische Null #define TIME_ONE 6900//unter 7100 //tD1 = 7 tu = 7,168 ms Pulsabstand für logische Eins #define TIME_WORD 13500//10% unter 14300 //tDW = 14 tu = 14,336 ms Wortabstand #define TIME_DOUBLEWORD 185000 //tDS = 13 tu = 19,456 ms Doppelwortabstand //?? keine doku dazu gefunden #define TIME_MAXIMUM 200000 #define TIME_AUTORESET_LOOP 10000 //milliseconds #define DEBOUNCE_TIME 70 //milliseconds /* * //original #define TIME_MINIMUM 1000 #define TIME_ZERO 4500 //tD0 = 5 tu = 5,12 ms Pulsabstand für lohgische Null #define TIME_ONE 6500 //tD1 = 7 tu = 7,168 ms Pulsabstand für lohgische Eins #define TIME_WORD 13500 //tDW = 14 tu = 14,336 ms Wortabstand #define TIME_DOUBLEWORD 18500 //tDS = 13 tu = 19,456 ms Doppelwortabstand #define TIME_MAXIMUM 70000 */ // States volatile boolean triggered; boolean key_hold = false; boolean key_pressed = false; unsigned long last_time = 0; unsigned long current_time= 0; unsigned long signal_time= 0; unsigned long signal_count = 0; unsigned long last_reset_time = 0; unsigned long last_key_time = 0; // Buffer byte keybuffer = 0; byte keylast = 0; //new scancodes char scancodes[125];//125 is the largest scancode boolean jumperisset = false;//if pin 9 tied to ground, then no keyboard function //ISR routine ISR (ANALOG_COMP_vect) { cli(); //Serial.println ("ISR"); triggered = true; sei(); } void setup() { //scancodes[7]='KEY_LEFT_ARROW'; scancodes[21]='-'; scancodes[22]='-'; scancodes[26]='-'; scancodes[28]='-'; scancodes[27]='-'; scancodes[29]='-'; scancodes[30]='-'; scancodes[35]='-'; scancodes[37]='-'; scancodes[34]='-'; scancodes[33]='-'; scancodes[36]='-'; scancodes[39]='P'; scancodes[41]='-'; scancodes[42]='-'; scancodes[43]='-'; scancodes[45]='-'; scancodes[44]='-'; scancodes[46]='-'; scancodes[49]='-'; scancodes[52]='-'; scancodes[51]='-'; scancodes[50]='-'; scancodes[53]='-'; scancodes[58]='-'; scancodes[59]='-'; scancodes[54]='-'; scancodes[61]='-'; scancodes[62]='-'; scancodes[69]='-'; scancodes[60]='-'; scancodes[66]='-'; scancodes[65]='-'; scancodes[67]='-'; scancodes[68]='-'; scancodes[71]=' '; scancodes[77]='-'; scancodes[73]='-'; scancodes[74]='-'; scancodes[75]='-'; scancodes[108]='-'; scancodes[107]='-'; scancodes[105]='-'; scancodes[114]='-'; scancodes[112]='-'; scancodes[113]='-';//??? delete has same code scancodes[115]='-'; scancodes[116]='-'; scancodes[117]='-'; //ARROW KEYS: scancodes[7]=KEY_LEFT_ARROW; scancodes[119]=KEY_DOWN_ARROW; scancodes[121]=KEY_UP_ARROW; scancodes[122]='-'; scancodes[123]=KEY_RIGHT_ARROW; scancodes[125]='-'; pinMode(jumperin, INPUT_PULLUP); /* * in pro micro: (cmp. datasheet ch 23 p 293 * * */ //Serial.println ("Started."); ADCSRB = ADCSRB & ! bit(ACME); // disable Analog Comparator Multiplexer Enable, //cmp. attiny datasheet: clearing ACME = AIN1=PB1=neg input comp, AIN0 = PB0 = pos input comp //in atemega32u4 // * we have bandgap instead of AIN1 ~ 1V // * AIN0 = 7 = comparator pos input // * now we listen to ACSR = bit(ACI) // clear Analog Comparator Interrupt Flag | bit(ACIE) // set Analog Comparator Interrupt Enable //| bit(ACIS1) | bit(ACIS0) // select rising edge: ACIS1/ACIS0 Analog Comparator Interrupt Mode Select | bit(ACIS1) | ! bit(ACIS0) // select rising edge: ACIS1/ACIS0 Analog Comparator Interrupt Mode Select // 1 1 //rising edge //original attiny85 // 1 0 //falling edge, as we connect AIN0 to the signal, so it is vice versa ; last_reset_time = millis(); last_key_time = millis(); if(!digitalRead(jumperin)) jumperisset = true; if (!jumperisset) Keyboard.begin(); else Serial.begin (Serialbaudrate); } void loop() { //Serial.println ("loop."); //delay(500); if (triggered) read_signal(); if (key_pressed | key_hold){ if((millis() - last_key_time) > DEBOUNCE_TIME) { showKeyNumber(); last_key_time = millis(); } else resetBuffer(); } key_pressed = false; key_hold = false; triggered = false; //new: add timer reset, fresh data //miracle No1: why ist this working so well even with 10s??? //if not present, button presses come slow if((millis()-last_reset_time) > TIME_AUTORESET_LOOP){ resetBuffer(); last_reset_time = millis(); } } void read_signal() { current_time = micros(); signal_time = current_time - last_time; // Frequenzen ausfiltern /* * bursts ausfiltern, routine verlassen bei sehr kurzen impulsen */ if ((signal_time < TIME_MINIMUM)) { //Serial.println ("(signal_time < TIME_MINIMUM)");//do not react to the bursts return false; } else { last_time = current_time; } /* * zeiten von lang nach kurz durchklappern: */ //if ((signal_time < TIME_ZERO) | (signal_time > TIME_MAXIMUM))//??? why shorter time_zero if ((signal_time > TIME_MAXIMUM)) { //Serial.println ("resetBuffer"); resetBuffer(); } /* * I dont know why, but it works better with those two conditions */ else if ((signal_time > TIME_DOUBLEWORD) ) {//??? key_pressed = ( signal_count == 7); //Serial.println ("signal_time > TIME_DOUBLEWORD"); finishBuffer(); } /* * I dont know why, but it works better with those two conditions */ else if ((signal_time > TIME_WORD) ) {//??? key_hold = (signal_count == 7); //Serial.println ("signal_time > TIME_WORD"); finishBuffer(); } else if (signal_time > TIME_ONE) { // Serial.println ("addBuffer(1);"); addBuffer(1); } else if (signal_time > TIME_ZERO) { //Serial.println ("addBuffer(0);"); addBuffer(0); } } void addBuffer(byte state) { keybuffer = keybuffer >> 1; ////new: altes bit an stelle 7 nach stelle 6 rücken keybuffer = keybuffer | (state << 6); //Neues Bit an Position 7 setzen signal_count += 1; //NEW: if(signal_count == 7) { finishBuffer();//new //Serial.println ("yeahh, caught 7 bits"); key_pressed = 1; } //end new } void finishBuffer() { //Startbit invertieren und nach vorne schieben //"startbit": /* byte startbit = ~(keybuffer & 1) << 7; keylast = (keybuffer >> 1) | startbit; */ keylast = keybuffer;//NEW teste ohne "startbit" resetBuffer(); } void resetBuffer() { signal_count = 0; keybuffer = 0; } // Output decimal number void showKeyNumber() { /* if (key_pressed) Serial.print("PRESSED "); if (key_hold) Serial.print("HOLD "); */ if(jumperisset) Serial.println (keylast); else Keyboard.write(scancodes[keylast]); }