Переглянути джерело

Add LED feature to Sun converter

tmk 12 роки тому
батько
коміт
edce1d19a6
5 змінених файлів з 74 додано та 18 видалено
  1. 7 0
      common/keyboard.c
  2. 16 1
      converter/sun_usb/config.h
  3. 9 1
      converter/sun_usb/led.c
  4. 1 0
      protocol/serial.h
  5. 41 16
      protocol/serial_soft.c

+ 7 - 0
common/keyboard.c

@@ -555,6 +555,7 @@ void keyboard_init(void)
 void keyboard_task(void)
 {
     static matrix_row_t matrix_prev[MATRIX_ROWS];
+    static uint8_t led_status = 0;
     matrix_row_t matrix_row = 0;
     matrix_row_t matrix_change = 0;
 
@@ -617,6 +618,12 @@ void keyboard_task(void)
         }
     }
 
+    // update LED
+    if (led_status != host_keyboard_leds()) {
+        led_status = host_keyboard_leds();
+        keyboard_set_leds(led_status);
+    }
+
     return;
 }
 

+ 16 - 1
converter/sun_usb/config.h

@@ -43,8 +43,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
  *     asynchronous, negative logic, 1200baud, no flow control
  *     1-start bit, 8-data bit, non parity, 1-stop bit
  */
-#define SERIAL_NEGATIVE_LOGIC
 #define SERIAL_BAUD 1200
+
 #define SERIAL_RXD_DDR  DDRD
 #define SERIAL_RXD_PORT PORTD
 #define SERIAL_RXD_PIN  PIND
@@ -63,5 +63,20 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
     /* clear interrupt  flag */     \
     EIFR = (1<<INTF2);              \
 } while (0)
+#define SERIAL_RXD_READ()    (~SERIAL_RXD_PIN&(1<<SERIAL_RXD_BIT))
+
+#define SERIAL_TXD_DDR  DDRD
+#define SERIAL_TXD_PORT PORTD
+#define SERIAL_TXD_PIN  PIND
+#define SERIAL_TXD_BIT  3
+/* negative logic */
+#define SERIAL_TXD_ON()     do { SERIAL_TXD_PORT &= ~(1<<SERIAL_TXD_BIT); } while (0)
+#define SERIAL_TXD_OFF()    do { SERIAL_TXD_PORT |=  (1<<SERIAL_TXD_BIT); } while (0)
+#define SERIAL_TXD_INIT()   do { \
+    /* pin configuration: output */         \
+    SERIAL_TXD_DDR |= (1<<SERIAL_TXD_BIT);  \
+    /* idle */                              \
+    SERIAL_TXD_ON();                        \
+} while (0)
 
 #endif

+ 9 - 1
converter/sun_usb/led.c

@@ -16,10 +16,18 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "stdint.h"
+#include "serial.h"
 #include "led.h"
 
 
 void led_set(uint8_t usb_led)
 {
-    // not supported now
+    uint8_t sun_led = 0;
+    if (usb_led & (1<<USB_LED_NUM_LOCK))    sun_led |= (1<<0);
+    if (usb_led & (1<<USB_LED_COMPOSE))     sun_led |= (1<<1);
+    if (usb_led & (1<<USB_LED_SCROLL_LOCK)) sun_led |= (1<<2);
+    if (usb_led & (1<<USB_LED_CAPS_LOCK))   sun_led |= (1<<3);
+
+    serial_send(0x0E);
+    serial_send(sun_led);
 }

+ 1 - 0
protocol/serial.h

@@ -41,5 +41,6 @@ POSSIBILITY OF SUCH DAMAGE.
 /* host role */
 void serial_init(void);
 uint8_t serial_recv(void);
+void serial_send(uint8_t data);
 
 #endif

+ 41 - 16
protocol/serial_soft.c

@@ -51,9 +51,10 @@ POSSIBILITY OF SUCH DAMAGE.
 void serial_init(void)
 {
     SERIAL_RXD_INIT();
+    SERIAL_TXD_INIT();
 }
 
-// RX ring buffer
+/* RX ring buffer */
 #define RBUF_SIZE   8
 static uint8_t rbuf[RBUF_SIZE];
 static uint8_t rbuf_head = 0;
@@ -71,39 +72,63 @@ uint8_t serial_recv(void)
     return data;
 }
 
-//ISR(INT2_vect)
+void serial_send(uint8_t data)
+{
+    /* signal state: IDLE: ON, START: OFF, STOP: ON, DATA0: OFF, DATA1: ON */
+    /* start bit */
+    SERIAL_TXD_OFF();
+    _delay_us(WAIT_US);
+
+#ifdef SERIAL_BIT_ORDER_MSB
+    uint8_t mask = 0x80;
+#else
+    uint8_t mask = 0x01;
+#endif
+    while (mask) {
+        if (data&mask) { SERIAL_TXD_ON(); } else { SERIAL_TXD_OFF(); }
+        _delay_us(WAIT_US);
+
+#ifdef SERIAL_BIT_ORDER_MSB
+        mask >>= 1;
+#else
+        mask <<= 1;
+#endif
+    }
+
+    /* stop bit */
+    SERIAL_TXD_ON();
+    _delay_us(WAIT_US);
+}
+
+/* detect edge of start bit */
 ISR(SERIAL_RXD_VECT)
 {
     SERIAL_RXD_INT_ENTER()
 
     uint8_t data = 0;
 #ifdef SERIAL_BIT_ORDER_MSB
-    uint8_t pos = 0x80;
+    uint8_t mask = 0x80;
 #else
-    uint8_t pos = 0x01;
+    uint8_t mask = 0x01;
 #endif
-    // to center of start bit
+    /* to center of start bit */
     _delay_us(WAIT_US/2);
     do {
-        // to center of next bit
+        /* to center of next bit */
         _delay_us(WAIT_US);
 
-        if (SERIAL_RXD_PIN&(1<<SERIAL_RXD_BIT)) {
-            data |= pos;
+        if (SERIAL_RXD_READ()) {
+            data |= mask;
         }
 #ifdef SERIAL_BIT_ORDER_MSB
-        pos >>= 1;
+        mask >>= 1;
 #else
-        pos <<= 1;
+        mask <<= 1;
 #endif
-    } while (pos);
-    // to center of stop bit
+    } while (mask);
+    /* to center of stop bit */
     _delay_us(WAIT_US);
 
-#ifdef SERIAL_NEGATIVE_LOGIC
-    data = ~data;
-#endif
-
     uint8_t next = (rbuf_head + 1) % RBUF_SIZE;
     if (next != rbuf_tail) {
         rbuf[rbuf_head] = data;