qmk_firmware

QMK firmware for my keyboards (Corne, Sweep Ferris) and trackball (Ploopy Adept)
Log | Files | Refs | Submodules | LICENSE

v3.c (3457B)


      1 #include "quantum.h"
      2 
      3 #if defined(__AVR__)
      4 #    include <avr/io.h>
      5 #    include <avr/interrupt.h>
      6 #endif
      7 
      8 #define ROWS_PER_HAND (MATRIX_ROWS / 2)
      9 #define SLAVE_MATRIX_SYNC_ADDR (0x01)
     10 
     11 typedef struct {
     12     char*  buffer;
     13     size_t count;
     14     bool*  flag;
     15 } transmit_status;
     16 
     17 transmit_status irx = {}, itx = {};
     18 
     19 // Buffer for master/slave matrix scan transmit.
     20 // Master: receive buffer.
     21 // Slave: transmit buffer.
     22 matrix_row_t sync_matrix[ROWS_PER_HAND];
     23 bool         matrix_synced = false;
     24 
     25 void USART_init(uint16_t baud) {
     26     cli();
     27 
     28     // UBRR1H = (unsigned char)(baud >>8);
     29     // UBRR1L = (unsigned char)(baud);
     30     UBRR1 = baud;
     31     // Enable U2X1 for double speed.
     32     UCSR1A = (1 << U2X1);
     33     // Enable RX/TX, 9N1 mode
     34     UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1) | (1 << TXCIE1) | (1 << UCSZ12);
     35     UCSR1C = (1 << UCSZ10) | (1 << UCSZ11);
     36     sei();
     37 }
     38 
     39 ISR(USART1_RX_vect) {
     40     // read data from reg.
     41     uint8_t status   = UCSR1A;
     42     uint8_t high_bit = UCSR1B;
     43     uint8_t low_data = UDR1;
     44     if (status & ((1 << FE1) | (1 << DOR1) | (1 << UPE1))) {
     45         // Something error happen, ignore this package.
     46         irx.count = 0;
     47         return;
     48     }
     49 
     50     // Is it a addr? (9th bit is one/zero?)
     51     if (high_bit & (1 << RXB81)) {
     52         // data is addr. prepend for receive.
     53         switch (low_data) {
     54             case SLAVE_MATRIX_SYNC_ADDR:
     55                 irx.buffer = (char *)sync_matrix;
     56                 irx.count = sizeof(sync_matrix) * sizeof(matrix_row_t);
     57                 irx.flag = &matrix_synced;
     58                 break;
     59 
     60             default:
     61                 // ignore this package.
     62                 irx.count = 0;
     63                 break;
     64         }
     65 
     66     } else if (irx.count > 0) {
     67         *irx.buffer = low_data;
     68         ++irx.buffer;
     69         if (--irx.count == 0 && irx.flag != NULL) {
     70             *irx.flag = true;
     71         }
     72     }
     73 }
     74 
     75 // TX complete
     76 ISR(USART1_TX_vect) {
     77     // Is in transmit?
     78     if (itx.count > 0) {
     79         // Send data.
     80         UCSR1B &= ~(1 << TXB81);
     81         UDR1 = *itx.buffer;
     82 
     83         // Move to next char.
     84         ++itx.buffer;
     85         if (--itx.count == 0) {
     86             *itx.flag = true;
     87         }
     88     }
     89     // TODO: read queue/register for next message.
     90 }
     91 
     92 // return: queue depth.
     93 int send_packet(uint8_t addr, char* buffer, size_t length, bool* flag) {
     94     // See if we can start transmit right now.
     95     if ((itx.count == 0) && (UCSR1A & (1 << UDRE1))) {
     96         // Ready to write.
     97         // Prepend registers.
     98         itx.buffer = buffer;
     99         itx.count  = length;
    100         itx.flag   = flag;
    101 
    102         // Write addr to kick start transmit.
    103         UCSR1B |= (1 << TXB81);
    104         UDR1 = addr;
    105         // TODO: put request in queue;
    106         // }else{
    107     }
    108 
    109     return 0;
    110 }
    111 
    112 void transport_master_init(void) { USART_init(0); }
    113 
    114 void transport_slave_init(void) { USART_init(0); }
    115 
    116 // returns false if valid data not received from slave
    117 bool transport_master(matrix_row_t matrix[]) {
    118     if (matrix_synced) {
    119         for (uint8_t i = 0; i < ROWS_PER_HAND; ++i) {
    120             matrix[i] = sync_matrix[i];
    121         }
    122         matrix_synced = false;
    123         return true;
    124     }
    125     return false;
    126 }
    127 
    128 void transport_slave(matrix_row_t matrix[]) {
    129     for (uint8_t i = 0; i < ROWS_PER_HAND; ++i) {
    130         sync_matrix[i] = matrix[i];
    131     }
    132     matrix_synced = false;
    133     send_packet(SLAVE_MATRIX_SYNC_ADDR, (char*)sync_matrix, sizeof(sync_matrix) * sizeof(matrix_row_t), &matrix_synced);
    134 }