Guest User

hhkb lift distance (devoi)

a guest
Aug 1st, 2020
38
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #define F_CPU 16000000
  2. #include <avr/io.h>
  3. #include <util/delay.h>
  4.  
  5. #define CSBAR 0 //PC0 for CS
  6. #define SKBAR 1 //PC1 for SK
  7. #define DIO 2   //PC2 for DIO
  8. #define Tclk 2  // clock period 4us
  9.  
  10. //ASSUMES PORTC USED FOR ALL CSBAR, SKBAR, DIO
  11. //REQUIRES MODIFICATION
  12.  
  13.  
  14. void write16bit(uint16_t data){
  15.  
  16.     for(uint8_t i = 0; i < 16; i++){    // write out data onto DIO
  17.  
  18.         if(data & (0x8000)){    // set DIO pin to data MSB
  19.             PORTC |= (1 << DIO);
  20.         }else{
  21.             PORTC &= ~(1 << DIO);
  22.         }
  23.         data = data << 1;   // shift MSB next in line
  24.  
  25.         PORTC |= (1 << SKBAR);  // pulse clock high
  26.         _delay_us(Tclk);
  27.         PORTC &= ~(1 << SKBAR); // set clock low
  28.         _delay_us(Tclk);
  29.     }
  30. }
  31.  
  32. void WriteEnable(uint8_t status){   // status = 1 for write, 0 for read
  33.  
  34.     PORTC &= ~(1 << CSBAR); // enable chip
  35.  
  36.     PORTC &= ~(1 << SKBAR); // clock must start low
  37.     _delay_us(Tclk);
  38.  
  39.     write16bit(status ? 0xA300 : 0xA000);   // 1010 0011 XXXX XXXX per datasheet is write
  40.                                             // 1010 0000 XXXX XXXX per datasheet is read
  41.  
  42.     PORTC |= (1 << SKBAR);  // end clock high
  43.     _delay_us(Tclk);
  44.  
  45.     PORTC |= (1 << CSBAR); // set CS off
  46.    
  47.     _delay_us(5*Tclk);  // short delay to keep CS high for a required amount of time, can likely be lessened
  48. }
  49.  
  50. uint8_t WCRead(){   // return wiper position 0-127
  51.  
  52.     PORTC &= ~(1 << CSBAR); // enable chip
  53.  
  54.     PORTC &= ~(1 << SKBAR); // clock must start low
  55.     _delay_us(Tclk);
  56.  
  57.     write16bit(0xAB00);     // 1010 1011 XXXX XXXX per datasheet
  58.  
  59.     DDRC &= ~(1 << DIO);    // set DIO for reading
  60.  
  61.     uint8_t buf = 0;        // output buffer
  62.     for(uint8_t i = 0; i < 8; i++){ // read 8 bits in via DIO
  63.  
  64.         if(PINC & (1 << DIO)){ // read bit is a 1
  65.             buf |= (1 << i);
  66.         }
  67.  
  68.         PORTC |= (1 << SKBAR);  // set clock high
  69.         _delay_us(Tclk);
  70.  
  71.         PORTC &= ~(1 << SKBAR); // set clock low
  72.         _delay_us(Tclk);
  73.     }
  74.  
  75.     DDRC |= (1 << DIO);     // set DIO for writing (rest of commands)
  76.     PORTC |= (1 << SKBAR) | (1 << CSBAR);   // end clock high and turn chip off
  77.     return buf;
  78. }
  79.  
  80. uint8_t WCWrite(uint8_t step){  // write wiper, step 0 to 127
  81.    
  82.     step = (step & 0xF0) >> 4 | (step & 0x0F) << 4; // byte indicating step count is sent out LSB-first
  83.     step = (step & 0xCC) >> 2 | (step & 0x33) << 2; // meaning it must be reversed as commands are sent MSB-first
  84.     step = (step & 0xAA) >> 1 | (step & 0x55) << 1;
  85.    
  86.     uint16_t data_fix = step << 8;  // needs empty byte afterward
  87.    
  88.     PORTC &= ~(1 << CSBAR); // enable chip
  89.     PORTC &= ~(1 << SKBAR); // set clock low
  90.     _delay_us(Tclk);
  91.  
  92.     write16bit(0xA600); // send write command then empty address byte
  93.     write16bit(data_fix); // send wiper value then empty unused byte
  94.  
  95.     PORTC |= (1 << SKBAR);  // datasheet shows two extra empty clock pulses
  96.     _delay_us(Tclk);        // seem to be ignored, but kept just in case
  97.     PORTC &= ~(1 << SKBAR);
  98.     _delay_us(Tclk);
  99.     PORTC |= (1 << SKBAR);  // end clock high
  100.     _delay_us(Tclk);
  101.  
  102.     PORTC |= (1 << CSBAR);  // disable chip
  103. }
  104.  
  105. int main(){
  106.    
  107.     DDRC = (1 << CSBAR) | (1 << SKBAR) | (1 << DIO);
  108.     PORTC = (1 << CSBAR) | (1 << SKBAR);
  109.    
  110.     // example read
  111.     uint8_t read_wiper = WCRead();  // chip starts in read-mode so this is okay
  112.                                     // can use tmk/qmk to write value as keystrokes to screen
  113.                                     // is good to know default value
  114.                                    
  115.     // example write
  116.     WriteEnable(1);     // put chip into write mode
  117.     _delay_us(Tclk*5);  // let settle, just in case, likely not needed
  118.     WCWrite(0x40);      // uses example value 0x40, my "default" value was 0x27 but it likely differs per-board
  119.     _delay_us(Tclk*5);  // let settle, likely not needed
  120.     WriteEnable(0);     // put back in read_mode
  121.    
  122.     // here would be a good place to verify that it wrote correctly with WCRead()
  123.    
  124. }
  125.  
RAW Paste Data