CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

USB keyboard with 18f14k50

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kurtzweber



Joined: 18 Oct 2012
Posts: 4

View user's profile Send private message

USB keyboard with 18f14k50
PostPosted: Mon Oct 22, 2012 6:24 am     Reply with quote

Hello!

I'm working on a project with a 18f14k50 PIC. I need to implement a keyboard HID device and I'm working with the provided examples.

My first attempt is to simply send "Hello" string every 10sec, here's my code:

Code:
#include "PwdHID.h"
#include "PwdHID_desc.h"

#include <pic18_usb.h>
#include <usb_bootloader.h>
#include <usb.c>

#define KB_MODIFIER_LEFT_SHIFT 2

void main() {
   
   set_tris_c(0x00); 
   output_low(LED_RED);
   output_low(LED_YELLOW);
   output_low(LED_GREEN);
       
   usb_init_cs();

   while(TRUE) {
     
      usb_task();
     
      if(usb_enumerated()) {

         output_high(LED_GREEN);
         sendChar('H');
         sendChar('e');
         sendChar('l');
         sendChar('l');
         sendChar('o');
         sendChar('\n');
         delay_ms(10000);
      }
   }
}

void sendChar(char c) {

   unsigned int8 tx_msg[7];
   unsigned int8 leds;
   unsigned int16 scancode;
   
   if (usb_tbe(1)) {
     
      memset(tx_msg, 0x00, sizeof(tx_msg));
     
      scancode = ToHidKeyboardScancode(c);
      if(bit_test(scancode, 8)) tx_msg[0] = KB_MODIFIER_LEFT_SHIFT;
      tx_msg[2] = scancode;
     
      usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
   }
   
   if(usb_kbhit(1)) usb_get_packet(1, &leds, 1);
}

unsigned int16 ToHidKeyboardScancode(char c)
{
   unsigned int16 shift = 0;
   
   if ((c>='A')&&(c<='Z'))
   {
      c = tolower(c);
      shift = 0x100;
   }
   if ((c>='a')&&(c<='z'))
   {
      return(((c-='a')+4)|shift);
   }
   if ((c>='1')&&(c<='9'))
   {
      return((c-='0')+0x1D);
   }
   switch(c)
   {
      case '!':   return(0x11E);
      case '@':   return(0x11F);
      case '#':   return(0x120);
      case '$':   return(0x121);
      case '%':   return(0x122);
      case '^':   return(0x123);
      case '&':   return(0x124);
      case '*':   return(0x125);
      case '(':   return(0x126);
      case ')':   return(0x127);
      case '0':   return(0x27);
      case '\n':  return(0x28);  //enter
      case '\r':  return(0x28);  //enter
      case '\b':  return(0x2A);  //backspace
      case '\t':  return(0x2B);  //tab
      case ' ':   return(0x2C);  //space
      case '_':   return(0x12D);
      case '-':   return(0x2D);
      case '+':   return(0x12E);
      case '=':   return(0x2E);
      case '{':   return(0x12F);
      case '[':   return(0x2F);
      case '}':   return(0x130);
      case ']':   return(0x30);
      case '|':   return(0x131);
      case '\\':   return(0x31);
      case ':':   return(0x133);
      case ';':   return(0x33);
      case '"':   return(0x134);
      case '\'':   return(0x34);
      case '~':   return(0x135);
      case '`':   return(0x35);
      case '<':   return(0x136);
      case ',':   return(0x36);
      case '>':   return(0x137);
      case '.':   return(0x37);
      case '?':   return(0x138);
      case '/':   return(0x38);
   }
}


When I run it, my PC correctly detect the new device but it starts to send only 'H':



Where am I wrong?

Thanks!
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Mon Oct 22, 2012 7:08 am     Reply with quote

Several little things.

First, rethink having a 10 second delay in the main loop. Have a timer interrupt 'ticking' at some convenient interval, and use this to do a countdown. USB, may run into problems if you pause this long between calling the task handler.

Big one though is that the key needs to release. You are sending a packet for the first key being pressed, and it is never released. Hence the computer will see it continuously repeating. To send a character, you need to send a key (with the required modifiers), and then release the key.

Best Wishes
kurtzweber



Joined: 18 Oct 2012
Posts: 4

View user's profile Send private message

PostPosted: Mon Oct 22, 2012 8:32 am     Reply with quote

Thanks for your reply!

To release the key, I thought to send a message with all 0x00 but nothing changes:

Quote:
// tx_msg[2:6] = an array of held down keys. a=4, b=5, etc.
// if msg[2:7]={0} then no keys are held down


Code:
void send_char(char c) {

   unsigned int8 tx_msg[7];
   unsigned int8 leds;
   unsigned int16 scancode;
   
   if (usb_tbe(1)) {
     
      memset(tx_msg, 0x00, sizeof(tx_msg));
     
      scancode = ToHidKeyboardScancode(c);
      if(bit_test(scancode, 8)) tx_msg[0] = KB_MODIFIER_LEFT_SHIFT;
      tx_msg[2] = scancode;
     
      usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
           
      // release key
      memset(tx_msg, 0x00, sizeof(tx_msg));
      usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
   }
}
kurtzweber



Joined: 18 Oct 2012
Posts: 4

View user's profile Send private message

PostPosted: Mon Oct 22, 2012 9:36 am     Reply with quote

Hello!

I added a small delay (100ms) between the two "usb_put_packet" and now it sends the key, but just the first one ('H'), both using printf() or calling the sub manually... very strange!

I changed also the delay function:

Code:
#include "PwdHID.h"
#include "PwdHID_desc.h"

#include <pic18_usb.h>
#include <usb_bootloader.h>
#include <usb.c>

#define KB_MODIFIER_LEFT_SHIFT 2

int1 time_expired = FALSE;
unsigned int8 timer0_count;

#int_timer0
void int_timer0_handler() {

   set_timer0(28036);
   
   timer0_count++;
   if(timer0_count == 100) {
      time_expired = TRUE;
      timer0_count = 0;
   }
}

void main() {
   
   set_tris_c(0x00); 
   output_low(LED_RED);
   output_low(LED_YELLOW);
   output_low(LED_GREEN);

   setup_timer_0(T0_INTERNAL | T0_DIV_32);
   set_timer0(28036);
     
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   
   usb_init_cs();

   while(TRUE) {
     
      usb_task();
     
      if(usb_enumerated()) {

         output_high(LED_GREEN);
     
         if(time_expired) {
            //printf(send_char, "Hello World!\n");
            send_char('H');
            send_char('e');
            send_char('l');
            send_char('l');
            send_char('o');
            time_expired = FALSE;
         }         
      }
   }
}

void send_char(char c) {

   unsigned int8 tx_msg[7];
   unsigned int8 leds;
   unsigned int16 scancode;
   
   if (usb_tbe(1)) {
     
      memset(tx_msg, 0x00, sizeof(tx_msg));
     
      scancode = ToHidKeyboardScancode(c);
      if(bit_test(scancode, 8)) tx_msg[0] = KB_MODIFIER_LEFT_SHIFT;
      tx_msg[2] = scancode;
      usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
           
      // release key
      delay_ms(100);
      memset(tx_msg, 0x00, sizeof(tx_msg));
      usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
   }
}

unsigned int16 ToHidKeyboardScancode(char c)
{
   unsigned int16 shift = 0;
   
   if ((c>='A')&&(c<='Z'))
   {
      c = tolower(c);
      shift = 0x100;
   }
   if ((c>='a')&&(c<='z'))
   {
      return(((c-='a')+4)|shift);
   }
   if ((c>='1')&&(c<='9'))
   {
      return((c-='0')+0x1D);
   }
   switch(c)
   {
      case '!':   return(0x11E);
      case '@':   return(0x11F);
      case '#':   return(0x120);
      case '$':   return(0x121);
      case '%':   return(0x122);
      case '^':   return(0x123);
      case '&':   return(0x124);
      case '*':   return(0x125);
      case '(':   return(0x126);
      case ')':   return(0x127);
      case '0':   return(0x27);
      case '\n':  return(0x28);  //enter
      case '\r':  return(0x28);  //enter
      case '\b':  return(0x2A);  //backspace
      case '\t':  return(0x2B);  //tab
      case ' ':   return(0x2C);  //space
      case '_':   return(0x12D);
      case '-':   return(0x2D);
      case '+':   return(0x12E);
      case '=':   return(0x2E);
      case '{':   return(0x12F);
      case '[':   return(0x2F);
      case '}':   return(0x130);
      case ']':   return(0x30);
      case '|':   return(0x131);
      case '\\':   return(0x31);
      case ':':   return(0x133);
      case ';':   return(0x33);
      case '"':   return(0x134);
      case '\'':   return(0x34);
      case '~':   return(0x135);
      case '`':   return(0x35);
      case '<':   return(0x136);
      case ',':   return(0x36);
      case '>':   return(0x137);
      case '.':   return(0x37);
      case '?':   return(0x138);
      case '/':   return(0x38);
   }
}


thanks again!
kurtzweber



Joined: 18 Oct 2012
Posts: 4

View user's profile Send private message

PostPosted: Mon Oct 22, 2012 11:32 am     Reply with quote

Ok solved Wink

you need a delay after each send... now I'm using 100ms but from the examples provided it seems you can use 10ms:

Code:
      // release key
      delay_ms(100);
      memset(tx_msg, 0x00, sizeof(tx_msg));
      usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
      delay_ms(100);
egemenakbas



Joined: 10 Mar 2021
Posts: 2

View user's profile Send private message

PostPosted: Wed Mar 10, 2021 9:56 am     Reply with quote

kurtzweber wrote:
Ok solved Wink

you need a delay after each send... now I'm using 100ms but from the examples provided it seems you can use 10ms:

Code:
      // release key
      delay_ms(100);
      memset(tx_msg, 0x00, sizeof(tx_msg));
      usb_put_packet(1, tx_msg, sizeof(tx_msg), USB_DTS_TOGGLE);
      delay_ms(100);


Hi, can you share ccs c project files to me?

thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 11, 2021 12:50 am     Reply with quote

kurtzweber's last post was on Oct 22, 2012. That was many years ago.
Don't expect a reply.
egemenakbas



Joined: 10 Mar 2021
Posts: 2

View user's profile Send private message

PostPosted: Thu Mar 11, 2021 2:27 am     Reply with quote

PCM programmer wrote:
kurtzweber's last post was on Oct 22, 2012. That was many years ago.
Don't expect a reply.


Hi, I noticed but wanted to take a chance Smile I need such a project. Thanks for the return.
temtronic



Joined: 01 Jul 2010
Posts: 9228
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 11, 2021 6:18 am     Reply with quote

You could take any PIC,add a TTL-USB module to do the same 'task'.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Mar 11, 2021 7:38 am     Reply with quote

No, Jay. Most of these modules would be CDC devices, not HID devices.

He wants data as if it comes from a keyboard.

The original posted code sounds as if it was working with the changes
implemented, so it should only be a couple of seconds work to test it.

The reason he was having to add a delay, is a common 'misunderstanding' of
how key scan codes work. To actually simulate a key being typed, you have
to send the 'key scan code', and then a 'key released' code. By sending just
the scan code, the system instead waits for the key repeat interval, and
then 'sees' the key. Hence the delay being needed.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group