Wednesday, December 11, 2013

USB HID CCS DEMO

Well, some weeks ago I was thinking about, what can I post?, so I saw around my study room and I saw my old toolbox with my old development boards, for example my Pinguino32, Arduino, Stellaris and other boards that I made when I was studying my career, and among these things, I found Microchip's microcontrollers PIC16fxx and PIC18Fxx. Of all my microcontrollers that I found and I had one with USB interface, and this it's the reason why I made this post talking about USB HID.

Some years ago it was very common to use the RS232 communication between our boards and computers, but at this time you seldom can see that technology again in new boards, because it's old,in its moments it was a good technology with high functionalities but the time is changing, and always is necessary more speed when we talk about communication and performance. So, most microcontrollers have a USB interfaces or compatibility to adapt USB interfaces, and these adaptability improve the communication versatility between humans and computers, and finally our design will be better, stronger and complex for resolve any problem.

Finally in this post I try to make a simple program toggling leds, sending and receiving messages from computer to microcontroller and viceversa, in essence this means that you can rapidly develop and test a USB device and the Windows host-application with a minimum of USB Generic HID protocol knowledge. The class library gives you a very simple interface to the USB device from C# and the firmware serves as an example of how to create the specific software needed on the PIC for your device design. I used the CyUSB library from Cypress Company, this library has either a lot of function for USB Cypress HID or USB HID generic and that it's awesome. there are a lot of APIs to achieve communication between our microcontroller and computer, for example "Florian Project", "Easy PIC Project", "LVR Project",etc... and I chose this because it's new or more less, you can prove with other that's the challenge. So, below I put schematics, codes and videos about this post talking about USB HID Demo, enjoy it!!

Schematic

Concrete

USB HID CCS[Microcontroller Firmware "USB_HID.h"]

#include <18F4550.h>
#device adc=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES HSPLL                    //High Speed Crystal/Resonator with PLL enabled
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT               //No brownout reset
#FUSES BORV46                   //Brownout reset at 4.6V
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES NOLPT1OSC                //Timer1 configured for higher power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL5                     //Divide By 5(20MHz oscillator input)
#FUSES CPUDIV1                  //No System Clock Postscaler
#FUSES USBDIV                   //USB clock source comes from PLL divide by 2
#FUSES VREGEN                   //USB voltage regulator enabled

#use delay(clock=20000000)

/*-- Transmit and Receive Packet Size --*/
#define USB_CONFIG_HID_TX_SIZE 64 
#define USB_CONFIG_HID_RX_SIZE 64

/*---------- VENDOR ID AND PRODUCT ID -----------*/
#define USB_CONFIG_PID 66        //Chnage Vendor Id and Product Id
#define USB_CONFIG_VID 1240        //So that they will work with my Application
/*-----------------------------------------------*/

#define HID_USB_ON PIN_B0
int8 Pin_Table[] = {PIN_C0, PIN_C1, PIN_C2}; 

/*---- LCD Pin definition ----*/
#define LCD_ENABLE_PIN  PIN_B3                                    
#define LCD_RS_PIN      PIN_B2                                    
#define LCD_RW_PIN      PIN_B1                                    
#define LCD_DATA4       PIN_B4                                    
#define LCD_DATA5       PIN_B5                                    
#define LCD_DATA6       PIN_B6                                    
#define LCD_DATA7       PIN_B7 

USB HID CCS [Microcontroller Firmware "USB_HID.c"]

#include "USB_HID.h"

/*---- Include the LCD include file ----*/
#include  

/*---- USB Libraries ----*/
#include 
#include "usb_desc_hid.h"
#include 

//Declare Variables
unsigned char HID_InData[64];
unsigned char HID_OutData[64];

char LED[3] = {'A','B','C'};
int i = 0;

void Message(){
//Welcome Text
printf(lcd_putc,"\f");
printf(lcd_putc,"Welcome to..\n Jeal's Blog!!");
}

void Buttons_Options(){
int Counter = 0;
while(TRUE){
   if(Counter < 100){  
      if (!input(PIN_A5)){    
         while((!input(PIN_A5)));         
         output_toggle(Pin_Table[i]);
         printf(lcd_putc,"\f");
         printf(lcd_putc,"Toggling LED %d \nwith buttons",i);
      }
      if (!input(PIN_E0)){    
         while((!input(PIN_E0)));
         output_toggle(Pin_Table[i]);
         printf(lcd_putc,"\f");
         printf(lcd_putc,"Toggling LED %d \nwith buttons",i);
      } 
   }
   else if(Counter == 100){
      break;
   }
   Counter ++;
   delay_ms(5);
}
}

void Reading_Buttons1(){
   if (!input(PIN_E1)){    
   delay_ms(100);             
      while((!input(PIN_E1))){        
/*--------------- MENU --------------------*/
         switch(LED[i]){
            case 'A':
            //Something        
            printf(lcd_putc,"\f");
            printf(lcd_putc,"Case 'A'");
            Buttons_Options();
            break;
            case 'B':
            //Something
            printf(lcd_putc,"\f");
            printf(lcd_putc,"Case 'B'");  
            Buttons_Options();
            break;
            case 'C':
            //Something
            printf(lcd_putc,"\f");
            printf(lcd_putc,"Case 'C'");
            Buttons_Options();
            break; 
            default:
            printf(lcd_putc,"\f");
            printf(lcd_putc,"Default"); 
            break;         
            }
      }
      i++;
      if(i>2) i = 0;
   }
}

void Setup_USB_HID(){
   usb_init();                      
   usb_task();                     
   usb_wait_for_enumeration();      
}

void Status_USB_HID(){
   int1 Attached_HID = 0; 
   int1 Enumerated_HID = 0;
   Attached_HID = usb_attached();
   Enumerated_HID = usb_enumerated();
   
      if(Attached_HID && Enumerated_HID){
         output_high(HID_USB_ON);
      }
      else{
         output_toggle(HID_USB_ON);
         delay_ms(100);
      }
}
 
void Clear_HID_Bus(char *var) {
    int i = 0;
    while(var[i] != '\0') {
        var[i] = '\0';
        i++;
    }
} 

void Toggling_LEDs(){
switch(HID_InData[1])
      {
      case 0:  //LED # 1
         output_toggle(Pin_Table[HID_InData[1]]);
         printf(lcd_putc,"\f");
         printf(lcd_putc,"Toggling LED %d \nby USB",HID_InData[1]);
         break;
      case 1:  //LED # 2
         output_toggle(Pin_Table[HID_InData[1]]);
         printf(lcd_putc,"\f");
         printf(lcd_putc,"Toggling LED %d \nby USB",HID_InData[1]);         
         break;
      case 2:  //LED # 3
         output_toggle(Pin_Table[HID_InData[1]]);
         printf(lcd_putc,"\f");
         printf(lcd_putc,"Toggling LED %d \nby USB",HID_InData[1]);         
         break;
      }

}

void Writitng_Messages(){
int j = 0,k= 0,x=1;
char Buffer[64];
printf(lcd_putc,"\f");
   for(j = 1; j<=sizeof(HID_InData); j++){   
   Buffer[k] = (HID_InData[j]);
   if(Buffer[k] == '\0'){
   break;
   }
   else{
      if(x > 16){
         lcd_gotoxy(x-16,2);
         printf(lcd_putc,"%c",Buffer[k]);
         }
      if(x > 32){
         printf(lcd_putc,"\f");  
         printf(lcd_putc,"Overflow!!\n Lack of space");      
      }
      else{
         lcd_gotoxy(x,1);
         printf(lcd_putc,"%c",Buffer[k]);
         }
   }
   k++;
   x++;
   }  
}

Reading_ADC(){
int i= 0;
for (i=0;i<64;i++){
HID_OutData[i]=read_adc();
delay_us(20);
}
usb_put_packet(1,HID_OutData,64,USB_DTS_TOGGLE);
}

void Reading_HID(){
   usb_get_packet(1,HID_InData,64);
    switch(HID_InData[0])
      {
      case 1:  //Toggle LEDS
         Toggling_LEDs();
         break;
      case 2:  //Message.
         Writitng_Messages();
         break;
      case 3:  //Reading ADCs.
         Reading_ADC();
         break;
      }
}

void main()
{
   setup_adc_ports(AN0|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
/*
   setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_2);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_ccp1(CCP_OFF);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
*/

   //TODO: User Code
   lcd_init(); 
   Message();
      
   //Init the USB
   Setup_USB_HID();
    
   while(TRUE)
   {        
   Reading_Buttons1();        
   
        usb_task();
        Status_USB_HID();
        if(usb_enumerated())
        {
            if(usb_kbhit(1))
            {    
                //Clean array for fixing problems
                Clear_HID_Bus(HID_InData);
                Clear_HID_Bus(HID_OutData);
                
                //Get the Data
                Reading_HID();               
           }
        }         
    }
} 

C# Software [USB HID Demo]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CyUSB;

namespace USB_HID_Project
{
    public partial class Form1 : Form
    {
        public static int[] PID_USB = new int[10];
        public static int[] VID_USB = new int[10];
        bool Led1_state = false;
        bool Led2_state = false;
        bool Led3_state = false;
        public static Int64 ticks = 0;
        int My_Device;
        bool Status_HID = false;        
        USBDeviceList USB_Devices;
        CyHidDevice USB_Host;

        public Form1()
        {
            InitializeComponent();
            USB_Devices = new USBDeviceList(CyConst.DEVICES_HID);

            USB_Devices.DeviceAttached += new EventHandler(USB_Devices_DeviceAttached);
            USB_Devices.DeviceRemoved += new EventHandler(USB_Devices_DeviceRemoved);
        }

        void Read_HID()
        {
            if (USB_Host.ReadInput())
            {
                richTextBox2.Clear();
                byte[] rcv = USB_Host.Inputs.DataBuf;
                for (int i = 1; i < USB_Host.Inputs.RptByteLen; i++)
                {
                    richTextBox2.Text += USB_Host.Inputs.DataBuf[i].ToString();
                    richTextBox2.Text += Environment.NewLine;
                }                 
            }
             
        }

        void USB_Devices_DeviceRemoved(object sender, EventArgs e)
        {
            USBEventArgs usbEvent = e as USBEventArgs;
            //label3.Text = usbEvent.FriendlyName + " removed.";             
        }

        void USB_Devices_DeviceAttached(object sender, EventArgs e)
        {
            USBEventArgs usbEvent = e as USBEventArgs;
            //label4.Text = usbEvent.Device.FriendlyName + " connected.";
        }
        
        private void button2_Click(object sender, EventArgs e)
        {            
            string text = richTextBox1.Text;
            byte[] data = System.Text.Encoding.ASCII.GetBytes(text); 
            var NewArray = new byte[data.Length + 2];
            data.CopyTo(NewArray, 2);
            NewArray[1] = 0x02;
            data = NewArray;
            USB_Host.Outputs.DataBuf = data;
            USB_Host.WriteOutput();            
        }

        private void detectHIDDevicesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            int i;
            HID_Connected.DropDownItems.Clear();
            ToolStripMenuItem[] items = new ToolStripMenuItem[USB_Devices.Count];
            for (i = 0; i < USB_Devices.Count; i++)
            {
                USBDevice Devices = USB_Devices[i];
                PID_USB[i] = Devices.ProductID;
                VID_USB[i] = Devices.VendorID;
                items[i] = new ToolStripMenuItem();
                items[i].Name = "SubItem" + i.ToString();
                items[i].Text = Devices.Product;
                if (Devices.Product == "CCS HID Demo")
                {
                    items[i].Click += new EventHandler(MenuItemClickHandler);
                    My_Device = i;
                }                
            }
            HID_Connected.DropDownItems.AddRange(items);
        }        

        private void MenuItemClickHandler(object sender, EventArgs e)
        {
            ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender;
            // Take some action based on the data in clickedItem
            USB_Host = USB_Devices[VID_USB[My_Device], PID_USB[My_Device]] as CyHidDevice;
            if (USB_Host != null)
            {
                Status_HID = true;
                ovalShape1.FillColor = Color.GreenYellow;
                ovalShape1.FillGradientColor = Color.WhiteSmoke;
                ovalShape1.BorderColor = Color.LawnGreen;
                label1.Text = "On";
            }
            else
            {
                Status_HID = false;
                label1.Text = "Off";
            }

        }      
        
        private void Led1(object sender, EventArgs e)
        {
            if (Led1_state == false)
            {
                ovalShape2.FillColor = Color.Red;
                ovalShape2.FillGradientColor = Color.WhiteSmoke;
                var NewArray = new byte[64];
                NewArray[1] = 0x01;
                NewArray[2] = 0x00;
                USB_Host.Outputs.DataBuf = NewArray;
                USB_Host.WriteOutput();   

            }
            else
            {
                ovalShape2.FillColor = Color.Maroon;
                ovalShape2.FillGradientColor = Color.SaddleBrown;
                var NewArray = new byte[64];
                NewArray[1] = 0x01;
                NewArray[2] = 0x00;
                USB_Host.Outputs.DataBuf = NewArray;
                USB_Host.WriteOutput();  
            }
            Led1_state = !Led1_state;
        }

        private void Led2(object sender, EventArgs e)
        {
            if (Led2_state == false)
            {
                ovalShape3.FillColor = Color.CornflowerBlue;
                ovalShape3.FillGradientColor = Color.WhiteSmoke;
                var NewArray = new byte[64];
                NewArray[1] = 0x01;
                NewArray[2] = 0x01;
                USB_Host.Outputs.DataBuf = NewArray;
                USB_Host.WriteOutput();  
            }
            else
            {
                ovalShape3.FillColor = Color.MidnightBlue;
                ovalShape3.FillGradientColor = Color.DarkSlateBlue;
                var NewArray = new byte[64];
                NewArray[1] = 0x01;
                NewArray[2] = 0x01;
                USB_Host.Outputs.DataBuf = NewArray;
                USB_Host.WriteOutput();  
            }
            Led2_state = !Led2_state;
        }

        private void Led3(object sender, EventArgs e)
        {
            if (Led3_state == false)
            {
                ovalShape4.FillColor = Color.GreenYellow;
                ovalShape4.FillGradientColor = Color.WhiteSmoke;
                var NewArray = new byte[64];
                NewArray[1] = 0x01;
                NewArray[2] = 0x02;
                USB_Host.Outputs.DataBuf = NewArray;
                USB_Host.WriteOutput();  
            }
            else
            {
                ovalShape4.FillColor = Color.DarkGreen;
                ovalShape4.FillGradientColor = Color.DimGray;
                var NewArray = new byte[64];
                NewArray[1] = 0x01;
                NewArray[2] = 0x02;
                USB_Host.Outputs.DataBuf = NewArray;
                USB_Host.WriteOutput();  
            }
                Led3_state = !Led3_state;
        }

        private void button2_Click_1(object sender, EventArgs e)
        {
            richTextBox1.Clear();
        }      

        private void button4_Click(object sender, EventArgs e)
        {
            var NewArray = new byte[64];
            NewArray[1] = 0x03;
            USB_Host.Outputs.DataBuf = NewArray;
            USB_Host.WriteOutput();
            Read_HID();
        }

        private void TimerTicks(object sender, EventArgs e)
        {
            var NewArray = new byte[64];
            NewArray[1] = 0x03;
            USB_Host.Outputs.DataBuf = NewArray;
            USB_Host.WriteOutput();
            Read_HID();
        }

        private void Switch(object sender, EventArgs e)
        {
            int value = 0;
            if (trackBar1.Value == 0)
            {
                textBox1.Clear();
                timer1.Stop();
                timer1.Enabled = false;
            }
            else
            {
                value = Int16.Parse(textBox1.Text);
                timer1.Interval = value;
                timer1.Start();
                timer1.Enabled = true;
            }
        }          
    }
     
}
If you like our work in Jeal's Blog just subscribe yourself. Get our posts in your RSS reader or by email.
Written by Jefferson GoVa

Ingeniero en electronica con aficiones a escribir y compartir todo aquello que le llama la atencion o que su curiosidad atrapa..

#Curioseando #Perdiendoeltiempo #sinnadamejorquehacer.

2 comments: