Jelajahi Sumber

fix bug (wrong logic) with osal_task_delay in non OS configure
complete keyboard app with key state & event TODO handle & check for non-printable(control) keycode
add unit test for osal_task_delay for non OS

hathach 13 tahun lalu
induk
melakukan
8bd077fa5c

+ 64 - 22
demos/host/src/keyboard_app.c

@@ -45,20 +45,30 @@
 //--------------------------------------------------------------------+
 // MACRO CONSTANT TYPEDEF
 //--------------------------------------------------------------------+
-#define QUEUE_KEYBOARD_REPORT_DEPTH   5
+#define QUEUE_KEYBOARD_REPORT_DEPTH   4
 
 //--------------------------------------------------------------------+
 // INTERNAL OBJECT & FUNCTION DECLARATION
 //--------------------------------------------------------------------+
-OSAL_TASK_DEF(keyboard_task_def, "keyboard app", keyboard_app_task, 128, KEYBOARD_APP_TASK_PRIO);
+typedef enum {
+  KEY_STATE_PRESSED = 1,
+  KEY_STATE_HOLDING,
+  KEY_STATE_RELEASED
+}key_state_t;
+
+typedef struct {
+  tusb_keyboard_report_t report;
+  key_state_t state[6];
+} kbd_data_t;
 
-OSAL_QUEUE_DEF(queue_kbd_report, QUEUE_KEYBOARD_REPORT_DEPTH, tusb_keyboard_report_t);
-static osal_queue_handle_t q_kbd_report_hdl;
+OSAL_TASK_DEF(keyboard_task_def, "keyboard app", keyboard_app_task, 128, KEYBOARD_APP_TASK_PRIO);
+OSAL_QUEUE_DEF(queue_kbd_def, QUEUE_KEYBOARD_REPORT_DEPTH, kbd_data_t);
 
+static osal_queue_handle_t queue_kbd_hdl;
 static tusb_keyboard_report_t usb_keyboard_report TUSB_CFG_ATTR_USBRAM;
 
-// only convert a-z (case insensitive) +  0-9
 static inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode) ATTR_CONST ATTR_ALWAYS_INLINE;
+static inline void process_kbd_report_isr(tusb_keyboard_report_t const * report);
 
 //--------------------------------------------------------------------+
 // tinyusb callback (ISR context)
@@ -68,7 +78,7 @@ void tusbh_hid_keyboard_isr(uint8_t dev_addr, uint8_t instance_num, tusb_event_t
   switch(event)
   {
     case TUSB_EVENT_INTERFACE_OPEN: // application set-up
-      osal_queue_flush(q_kbd_report_hdl);
+      osal_queue_flush(queue_kbd_hdl);
       tusbh_hid_keyboard_get_report(dev_addr, instance_num, (uint8_t*) &usb_keyboard_report); // first report
     break;
 
@@ -77,7 +87,7 @@ void tusbh_hid_keyboard_isr(uint8_t dev_addr, uint8_t instance_num, tusb_event_t
     break;
 
     case TUSB_EVENT_XFER_COMPLETE:
-      osal_queue_send(q_kbd_report_hdl, &usb_keyboard_report);
+      process_kbd_report_isr(&usb_keyboard_report);
       tusbh_hid_keyboard_get_report(dev_addr, instance_num, (uint8_t*) &usb_keyboard_report);
     break;
 
@@ -98,43 +108,75 @@ void keyboard_app_init(void)
   memclr_(&usb_keyboard_report, sizeof(tusb_keyboard_report_t));
 
   ASSERT( TUSB_ERROR_NONE == osal_task_create(&keyboard_task_def), (void) 0 );
-  q_kbd_report_hdl = osal_queue_create(&queue_kbd_report);
-  ASSERT_PTR( q_kbd_report_hdl, (void) 0 );
+  queue_kbd_hdl = osal_queue_create(&queue_kbd_def);
+  ASSERT_PTR( queue_kbd_hdl, (void) 0 );
 }
 
 //------------- main task -------------//
 OSAL_TASK_FUNCTION( keyboard_app_task ) (void* p_task_para)
 {
   tusb_error_t error;
-  static tusb_keyboard_report_t prev_kbd_report = { 0 }; // previous report to check key released
-  tusb_keyboard_report_t kbd_report;
+  kbd_data_t kbd_data;
 
   OSAL_TASK_LOOP_BEGIN
 
-  osal_queue_receive(q_kbd_report_hdl, &kbd_report, OSAL_TIMEOUT_WAIT_FOREVER, &error);
+  osal_queue_receive(queue_kbd_hdl, &kbd_data, OSAL_TIMEOUT_WAIT_FOREVER, &error);
+
+  //------------- example code ignore control (non-printable) key affects -------------//
+  for(uint8_t i = 0; i < 6; i++)
+  {
+    if ( kbd_data.state[i] == KEY_STATE_PRESSED )
+    {
+      printf("%c", keycode_to_ascii(kbd_data.report.modifier, kbd_data.report.keycode[i]) );
+    }
+  }
+
+  OSAL_TASK_LOOP_END
+}
+
+//--------------------------------------------------------------------+
+// HELPER
+//--------------------------------------------------------------------+
+
+// look up new key in previous keys
+static inline bool is_key_in_report_isr(tusb_keyboard_report_t const *p_report, uint8_t keycode, uint8_t modifier)
+{
+  for(uint8_t i=0; i<6; i++)
+  {
+    if (p_report->keycode[i] == keycode)
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+static inline void process_kbd_report_isr(tusb_keyboard_report_t const *p_new_report)
+{
+  static tusb_keyboard_report_t prev_report = { 0 }; // previous report to check key released
+  kbd_data_t kbd_data = { 0 };
 
-  //------------- example code ignore modifier key -------------//
   for(uint8_t i=0; i<6; i++)
   {
-    if ( kbd_report.keycode[i] != prev_kbd_report.keycode[i] )
+    if ( p_new_report->keycode[i] )
     {
-      if ( 0 != kbd_report.keycode[i]) // key pressed
+      if ( is_key_in_report_isr(&prev_report, p_new_report->keycode[i], p_new_report->modifier) )
       {
-        printf("%c", keycode_to_ascii(kbd_report.modifier, kbd_report.keycode[i]) );
+        kbd_data.state[i] =  KEY_STATE_HOLDING; // previously existed means holding
       }else
       {
-        // key released
+        kbd_data.state[i] = KEY_STATE_PRESSED;  // previously non-existed means released
       }
     }
-    prev_kbd_report.keycode[i] = kbd_report.keycode[i];
+    // TODO example skips key released
   }
 
-  OSAL_TASK_LOOP_END
+  prev_report = *p_new_report;
+  kbd_data.report = *p_new_report;
+  osal_queue_send(queue_kbd_hdl, &kbd_data);
 }
 
-//--------------------------------------------------------------------+
-// HELPER
-//--------------------------------------------------------------------+
 static inline uint8_t keycode_to_ascii(uint8_t modifier, uint8_t keycode)
 {
   // TODO max of keycode_ascii_tbl

+ 2 - 2
tests/test/host/hid/test_hidh_keyboard.c

@@ -53,11 +53,11 @@ tusb_keyboard_report_t sample_key[2] =
 {
     {
         .modifier = KEYBOARD_MODIFIER_LEFTCTRL,
-        .keycode = {KEYBOARD_KEYCODE_a}
+        .keycode = {4}//{KEYBOARD_KEYCODE_a} TODO ascii to key code table
     },
     {
         .modifier = KEYBOARD_MODIFIER_RIGHTALT,
-        .keycode = {KEYBOARD_KEYCODE_z}
+        .keycode = {5}//{KEYBOARD_KEYCODE_z}
     }
 };
 

+ 29 - 1
tests/test/test_osal_none.c

@@ -163,7 +163,7 @@ void test_task_with_semaphore(void)
 }
 
 //--------------------------------------------------------------------+
-// TASK SEMAPHORE
+// TASK QUEUE
 //--------------------------------------------------------------------+
 tusb_error_t sample_task_with_queue(void)
 {
@@ -233,6 +233,34 @@ void test_task_with_queue(void)
   TEST_ASSERT_EQUAL(2, statements[0]);
 }
 
+//--------------------------------------------------------------------+
+// TASK DELAY
+//--------------------------------------------------------------------+
+tusb_error_t sample_task_with_delay(void)
+{
+  tusb_error_t error;
+
+  OSAL_TASK_LOOP_BEGIN
+
+  osal_task_delay(1000);
+
+  statements[0]++;
+
+  OSAL_TASK_LOOP_END
+}
+
+void test_task_with_delay(void)
+{
+  sample_task_with_delay();
+  TEST_ASSERT_EQUAL(0, statements[0]);
+
+  for(uint32_t i=0; i<TUSB_CFG_OS_TICKS_PER_SECOND*1000; i++) // not enough time
+    osal_tick_tock();
+
+  sample_task_with_delay();
+  TEST_ASSERT_EQUAL(1, statements[0]);
+}
+
 //--------------------------------------------------------------------+
 // TASK FLOW CONTROL
 //--------------------------------------------------------------------+

+ 2 - 2
tinyusb/osal/osal_freeRTOS.h

@@ -186,8 +186,8 @@ static inline void osal_queue_receive (osal_queue_handle_t const queue_hdl, void
   (*p_error) = ( xQueueReceive(queue_hdl, p_data, osal_tick_from_msec(msec)) == pdPASS ) ? TUSB_ERROR_NONE : TUSB_ERROR_OSAL_TIMEOUT;
 }
 
-static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, const void * data) ATTR_ALWAYS_INLINE;
-static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, const void * data)
+static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, void const * data) ATTR_ALWAYS_INLINE;
+static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, void const * data)
 {
   portBASE_TYPE taskWaken;
   return ( xQueueSendFromISR(queue_hdl, data, &taskWaken) == pdTRUE ) ? TUSB_ERROR_NONE : TUSB_ERROR_OSAL_QUEUE_FAILED;

+ 3 - 3
tinyusb/osal/osal_none.h

@@ -112,7 +112,7 @@ static inline volatile uint32_t osal_tick_get(void)
   do {\
     timeout = osal_tick_get();\
     state = __LINE__; case __LINE__:\
-      if ( timeout + osal_tick_from_msec(msec) < osal_tick_get() ) /* time out */ \
+      if ( timeout + osal_tick_from_msec(msec) > osal_tick_get() ) /* time out */ \
         return TUSB_ERROR_OSAL_WAITING;\
   }while(0)
 
@@ -230,8 +230,8 @@ static inline osal_queue_handle_t osal_queue_create(osal_queue_t * const p_queue
 }
 
 // when queue is full, it will overwrite the oldest data in the queue
-static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, const void * data) ATTR_ALWAYS_INLINE;
-static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, const void * data)
+static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, void const * data) ATTR_ALWAYS_INLINE;
+static inline tusb_error_t osal_queue_send(osal_queue_handle_t const queue_hdl, void const * data)
 {
   //TODO mutex lock hal_interrupt_disable