HID-USB  (Bascom-AVR)




    HID-USB is a software based usb connectivity, that require only a few passive parts and it can be implemented on most AVR microcontroller. Unused I/O pins can be use to drive sensors, joystick to transmit and receive data over USB. D1 and D2 make up a very lost cost 3V3 voltage supply regulator. Bascom programmed files consist of 3 parts Main.bas , Const_swusb-includes.bas and swusb.lbx.

  • I'm not the original author for this firmware and is still under development , there are still partial incomplete code.
  • mcHID.dll libary.
  • Full document on USB at  http://www.usb.org/home




 If you need 5V to your micro, remove and replace D1 - D2 with a 3V6 zener to limit the voltage for the D+/D- line.


Main.bas

$noramclear

$hwstack = 40
$swstack = 40
$framesize = 50                                            
$regfile = "m88pdef.dat"
$crystal = 12000000
$lib "swusb.lbx"
$external _swusb

Declare Sub Usb_reset()
Declare Sub Usb_processsetup(txstate As Byte)
Declare Sub Usb_send(txstate As Byte , Byval Count As Byte)
Declare Sub Usb_senddescriptor(txstate As Byte , Maxlen As Byte)

_usb_port Alias PORTD
_usb_pin Alias PIND
_usb_ddr Alias DDRD

Const _usb_dplus = 2
Const _usb_dminus = 3

Config PIND.= Input
Config PIND.= Input

_usb_port._usb_dplus = 0
_usb_port._usb_dminus = 0

Const _usb_use_eeprom = 0
Const _usb_assume_ack = 0
Const _usb_vid = &HAAAA
Const _usb_pid = &HEF04
Const _usb_devrel = &H0001
Const _usb_spec = &H0110
Const _usb_devclass = 0
Const _usb_devsubclass = 0
Const _usb_devprot = 0
Const _usb_imanufacturer = 1
Const _usb_iproduct = 2
Const _usb_iserial = 0
Const _usb_numconfigs = 1
Const _usb_numifaces = 1
Const _usb_confignum = 1
Const _usb_iconfig = 2
Const _usb_powered = &H80
Const _usb_maxpower = 50
Const _usb_ifaces = 1
Const _usb_ifaceaddr = 0
Const _usb_alternate = 0
Const _usb_ifaceendpoints = 2
Const _usb_ifclass = 3
Const _usb_ifsubclass = 0
Const _usb_ifprotocol = 0
Const _usb_iiface = 0
Const _usb_hids = 1
Const _usb_hid_release = &H0111
Const _usb_hid_country = 0
Const _usb_hid_numdescriptors = 1
Const _usb_endp2addr = 1
Const _usb_endp2type = 3
Const _usb_endp3type = 3
Const _usb_endp2direction = 1
Const _usb_endp3direction = 0
Const _usb_endp2interval = 200
Const _usb_endp3interval = 100

$include "Const_swusb-includes.bas"

Call Usb_reset()

'  Config 1wire = Portc.5
'  Dim 1wire_array(9) As Byte
'  Dim W_1wire As Word
'  Dim Dsid1(8) As Byte
'  Dim Flaginputtermo As Byte


Config TIMER1 = Timer , Prescale = 256
On TIMER1 Setflag Nosave
Enable TIMER1

Const _usb_intf = Intf0
Config Int0 = Rising
On Int0 Usb_isr Nosave
Enable Int0

Enable Interrupts

Dim Buttons_current As Byte
Dim Buttons_last As Byte
Dim Resetcounter As Word
Dim Idlemode As Byte

'   W_1wire = 1wirecount()
'   Dsid1(1) = 1wsearchfirst()
'   1wreset
'   1wwrite &HCC
'   1wwrite &H44
'   Timer1 = 0
'   Flaginputtermo = 0


Do
   Resetcounter = 0

   While _usb_pin._usb_dminus = 0
      Incr Resetcounter
      If Resetcounter = 1000 Then
         Call Usb_reset()
      End If
   Wend

   If _usb_status._usb_rxc = 1 Then
      If _usb_status._usb_setup = 1 Then
         Call Usb_processsetup(_usb_tx_status)
      End If
      _usb_status._usb_rtr = 1
      _usb_status._usb_rxc = 0
   End If

'   If Flaginputtermo = 1 Then
'       Flaginputtermo = 0
'       1wverify Dsid1(1)
'       1wwrite &HBE
'       1wire_array(1) = 1wread(9)
'       1wreset
'       1wwrite &HCC
'       1wwrite &H44
'     If _usb_tx_status2._usb_txc = 1 Then
'       _usb_tx_buffer2(2) = 1wire_array(1)
'       _usb_tx_buffer2(3) = 1wire_array(2)
'       Call Usb_send(_usb_tx_status2 , 2)
'     End If
'   End If

Loop
End

#if _usb_use_eeprom = 1
   $eeprom
#else
   $data
#endif

_usb_devicedescriptor:
Data 18 , 18 , _usb_desc_device , _usb_specl , _usb_spech , _usb_devclass
Data _usb_devsubclass , _usb_devprot , 8 , _usb_vidl , _usb_vidh , _usb_pidl
Data _usb_pidh , _usb_devrell , _usb_devrelh , _usb_imanufacturer
Data _usb_iproduct , _usb_iserial , _usb_numconfigs

_usb_configdescriptor:
Data _usb_descr_total , 9 , _usb_desc_config , _usb_descr_totall
Data _usb_descr_totalh , _usb_numifaces , _usb_confignum , _usb_iconfig
Data _usb_powered , _usb_maxpower

Data 9 , _usb_desc_iface , _usb_ifaceaddr , _usb_alternate
Data _usb_ifaceendpoints , _usb_ifclass , _usb_ifsubclass , _usb_ifprotocol
Data _usb_iiface

#if _usb_hids > 0
Data _usb_hid_descr_len , _usb_desc_hid , _usb_hid_releasel , _usb_hid_releaseh
Data _usb_hid_country , _usb_hid_numdescriptors
Data _usb_desc_report
Data 20 , 0
#endif

#if _usb_endpoints > 1
Data 7 , _usb_desc_endpoint , _usb_endp2attr , _usb_endp2type , 8 , 0
Data _usb_endp2interval
#endif

#if _usb_endpoints > 2
Data 7 , _usb_desc_endpoint , _usb_endp3attr , _usb_endp3type , 8 , 0
Data _usb_endp3interval
#endif

#if _usb_hids > 0
_usb_hid_reportdescriptor:
Data 20
Data &H06 , &H00 , &HFF
Data &H09 , &H01
Data &HA1 , &H02
Data &H09 , &H01
Data &H15 , &H00
Data &H25 , &HFF
Data &H75 , &H08
Data &H95 , &H02
Data &H81 , &H02
Data &HC0
#endif

_usb_langdescriptor:
Data 4 , 4 , _usb_desc_string , 09 , 04

_usb_mandescriptor:
Data 40 , 40 , _usb_desc_string
Data "T" , "E" , "S" , "T" , " "
Data "T" , "E" , "S" , "T" 

_usb_proddescriptor:
Data 44 , 44 , _usb_desc_string
Data "U" , "S" , "B" , "_" 
Data "T" , "E" , "S" , "T"

Sub Usb_processsetup(txstate As Byte)
   Senddescriptor = 0
   Txstate = _usb_setup_sync

   Select Case _usb_rx_buffer(2)
      Case &B10000000:
         Select Case _usb_rx_buffer(3)
            Case _usb_req_get_descriptor:
               Select Case _usb_rx_buffer(5)
                  Case _usb_desc_device:
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_devicedescriptor
                     #else
                        Restore _usb_devicedescriptor
                     #endif
                     Senddescriptor = 1
                  Case _usb_desc_config:
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_configdescriptor
                     #else
                        Restore _usb_configdescriptor
                     #endif
                     Senddescriptor = 1
                  Case _usb_desc_string:
                     Select Case _usb_rx_buffer(4)
                        Case 0:
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_langdescriptor
                           #else
                              Restore _usb_langdescriptor
                           #endif
                           Senddescriptor = 1
                        Case 1:
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_mandescriptor
                           #else
                              Restore _usb_mandescriptor
                           #endif
                           Senddescriptor = 1
                        Case 2:
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_proddescriptor
                           #else
                              Restore _usb_proddescriptor
                           #endif
                           Senddescriptor = 1
                     End Select
               End Select
         End Select
      Case &B00000000:
         Select Case _usb_rx_buffer(3)
            Case _usb_req_set_address:
               Call Usb_send(txstate , 0)
               While Txstate._usb_txc = 0 : Wend
               _usb_deviceid = _usb_rx_buffer(4)
            Case _usb_req_set_config:
               Call Usb_send(txstate , 0)
         End Select
      Case &B10000001:
         Select Case _usb_rx_buffer(3)
            Case _usb_req_get_descriptor
               Select Case _usb_rx_buffer(5)
                  Case _usb_desc_report:
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_hid_reportdescriptor
                     #else
                        Restore _usb_hid_reportdescriptor
                     #endif
                     Senddescriptor = 1
               End Select
         End Select
      Case &B00100001:
         Select Case _usb_rx_buffer(3)
            Case _usb_req_set_idle:
               Idlemode = 1
               Call Usb_send(txstate , 0)
         End Select
   End Select

   If Senddescriptor = 1 Then
      Call Usb_senddescriptor(txstate , _usb_rx_buffer(8))
   End If
End Sub

Sub Usb_senddescriptor(txstate As Byte , Maxlen As Byte)

   Local Size As Byte
   Local I As Byte
   Local J As Byte
   Local Timeout As Word

   #if _usb_use_eeprom = 1
      Size = _usb_eepromaddrl

      push R24
      in R24, EEARL
      sts {_USB_EEPROMADDRL}, R24
      in R24, EEARH
      sts {_USB_EEPROMADDRH}, R24
      pop R24
   #else
      Read Size
   #endif


   If Maxlen < Size Then Size = Maxlen
   I = 2
   For J = 1 To Size
      Incr I
      #if _usb_use_eeprom = 1
         Incr _usb_eepromaddr
         Readeeprom Txstate(i) , _usb_eepromaddr
      #else
         Read Txstate(i)
      #endif

      If I = 10 Or J = Size Then
         I = I - 2
         Call Usb_send(txstate , I)
         While Txstate._usb_txc = 0
            Timeout = 0
            While _usb_pin._usb_dminus = 0
               Incr Timeout
               If Timeout = 1000 Then                       '
                  Call Usb_reset()
                  Exit Sub
               End If
            Wend
         Wend
         I = 2
      End If
   Next
End Sub

Sub Usb_send(txstate As Byte , Byval Count As Byte)

   Txstate = Txstate And _usb_syncmask
   _usb_crc = 0

   If Count <> 0 Then
      _usb_crc = Crc16uni(txstate(3) , Count , &HFFFF , &H8005 , 1 , 1)
      Toggle _usb_crc
   End If
   Count = Count + 3
   Txstate = Txstate + Count
   Txstate(count) = Low(_usb_crc)
   Incr Count
   Txstate(count) = High(_usb_crc)
   Txstate(2) = _usb_pid_data1
   If Txstate._usb_txsync = 0 Then
      Txstate(2) = _usb_pid_data0
   End If
   Txstate._usb_rtt = 1
   Txstate._usb_txc = 0
End Sub

Sub Usb_reset()
   _usb_status._usb_rtr = 1
   _usb_status._usb_rxc = 0
   _usb_tx_status = _usb_endp_init
   #if Varexist( "_usb_Endp2Addr")
   _usb_tx_status2 = _usb_endp_init
   #endif
   #if Varexist( "_usb_Endp3Addr")
   _usb_tx_status3 = _usb_endp_init
   #endif
   _usb_deviceid = 0
   Idlemode = 0
End Sub

Setflag:
  Flaginputtermo = 1
Return

Const_swusb-includes.bas

$nocompile

Const _usb_rxc = 7
Const _usb_rtr = 6
Const _usb_ignore = 5
Const _usb_setup = 4
Const _usb_endp3 = 3
Const _usb_endp2 = 2
Const _usb_endp1 = 1
Const _usb_endp0 = 0
Const _usb_rxsync = 7
Const _usb_txsync = 6
Const _usb_txc = 5
Const _usb_rtt = 4
Const _usb_endp_init = 2 ^ _usb_txc
Const _usb_setup_sync = 2 ^ _usb_txc + 2 ^ _usb_txsync
Const _usb_syncmask = 2 ^ _usb_txsync + 2 ^ _usb_rxsync
Const _usb_pid_out = &B11100001
Const _usb_pid_in = &B01101001
Const _usb_pid_setup = &B00101101
Const _usb_pid_data0 = &B11000011
Const _usb_pid_data1 = &B01001011
Const _usb_pid_ack = &B11010010
Const _usb_pid_nak = &B01011010
Const _usb_pid_stall = &B00011110
Const _usb_pid_sof = &B10100101
Const _usb_pid_data2 = &B10000111
Const _usb_pid_mdata = &B00001111
Const _usb_pid_nyet = &B10010110
Const _usb_pid_pre = &B00111100
Const _usb_pid_err = &B00111100
Const _usb_pid_split = &B01111000
Const _usb_pid_ping = &B10110100
Const _usb_req_get_status = 0
Const _usb_req_clear_feature = 1
Const _usb_req_set_feature = 3
Const _usb_req_set_address = 5
Const _usb_req_get_descriptor = 6
Const _usb_req_set_descriptor = 7
Const _usb_req_get_config = 8
Const _usb_req_set_config = 9
Const _usb_req_get_iface = &H0A
Const _usb_req_set_iface = &H11
Const _usb_req_synch_frame = &H12
Const _usb_req_get_report = 1
Const _usb_req_get_idle = 2
Const _usb_req_get_protocol = 3
Const _usb_req_set_report = 9
Const _usb_req_set_idle = &H0A
Const _usb_req_set_protocol = &H0B
Const _usb_desc_device = 1
Const _usb_desc_config = 2
Const _usb_desc_string = 3
Const _usb_desc_iface = 4
Const _usb_desc_endpoint = 5
Const _usb_desc_hid = &H21
Const _usb_desc_report = &H22
Const _usb_desc_physical = &H23
Const _usb_pinmask =(^ _usb_dplus) +(^ _usb_dminus)

#if _usb_powered = &HC0
   Const _usb_devstatus = 1
#else
   Const _usb_devstatus = 0
#endif

#if Varexist( "_usb_Endp3Addr")
   #if Varexist( "_usb_Endp2Addr")
      Const _usb_endpoints = 3
   #else
      Const _usb_endpoints = 2
   #endif
#else
   #if Varexist( "_usb_Endp2Addr")
      Const _usb_endpoints = 2
   #else
      Const _usb_endpoints = 1
   #endif
#endif

#if Varexist( "_usb_Endp2Addr")
Const _usb_endp2attr = _usb_endp2addr +(_usb_endp2direction * &H80)
#endif
#if Varexist( "_usb_Endp3Addr")
Const _usb_endp3attr = _usb_endp3addr +(_usb_endp3direction * &H80)
#endif

Const _usb_descr_total =(_usb_endpoints -1) * 7 +(_usb_ifaces * 9) +(_usb_hids * 9) + 9

#if Varexist( "EIFR")
_usb_ifr Alias Eifr
#else
_usb_ifr Alias Gifr
#endif

Const _usb_spech = Hbyte(_usb_spec)
Const _usb_specl = Lbyte(_usb_spec)
Const _usb_vidh = Hbyte(_usb_vid)
Const _usb_vidl = Lbyte(_usb_vid)
Const _usb_pidh = Hbyte(_usb_pid)
Const _usb_pidl = Lbyte(_usb_pid)
Const _usb_devrelh = Hbyte(_usb_devrel)
Const _usb_devrell = Lbyte(_usb_devrel)
Const _usb_descr_totalh = Hbyte(_usb_descr_total)
Const _usb_descr_totall = Lbyte(_usb_descr_total)
Const _usb_hid_releaseh = Hbyte(_usb_hid_release)
Const _usb_hid_releasel = Lbyte(_usb_hid_release)
Const _usb_hid_descr_len =(+(* _usb_hid_numdescriptors))

#if _usb_descr_total Mod 8 = 0
Const _usb_descr_total2 = _usb_descr_total + 1
#else
Const _usb_descr_total2 = _usb_descr_total
#endif

Const _usb_packetsize = 1 + 8 + 2
Const _usb_rx_bufsize = _usb_packetsize * 2
Const _usb_tx_bufsize = _usb_packetsize + 1
Const _usb_tx_rawbufsize = _usb_tx_bufsize * _usb_endpoints

#if _usb_use_eeprom = 1
Dim _usb_eepromaddr As Word
Dim _usb_eepromaddrl As Byte At _usb_eepromaddr Overlay
Dim _usb_eepromaddrh As Byte At _usb_eepromaddr + 1 Overlay
#endif

Dim _usb_deviceid As Byte
Dim _usb_rx_buffer(_usb_rx_bufsize ) As Byte
Dim _usb_rx_count As Byte
Dim _usb_tx_rawbuffer(_usb_tx_rawbufsize) As Byte
Dim _usb_tx_status As Byte At _usb_tx_rawbuffer Overlay
Dim _usb_tx_buffer(_usb_packetsize) As Byte At _usb_tx_rawbuffer + 1 Overlay

#if Varexist( "_usb_Endp3Addr")
   #if Varexist( "_usb_Endp2Addr")
      Dim _usb_tx_status2 As Byte At _usb_tx_status + _usb_tx_bufsize Overlay
      Dim _usb_tx_status3 As Byte At _usb_tx_status2 + _usb_tx_bufsize Overlay
      Dim _usb_tx_buffer2(_usb_packetsize) As Byte At _usb_tx_buffer + _usb_tx_bufsize Overlay
      Dim _usb_tx_buffer3(_usb_packetsize) As Byte At _usb_tx_buffer2 + _usb_tx_bufsize Overlay
   #else
      Dim _usb_tx_status3 As Byte At _usb_tx_status + _usb_tx_bufsize Overlay
      Dim _usb_tx_buffer3(_usb_packetsize) As Byte At _usb_tx_buffer + _usb_tx_bufsize Overlay
   #endif
#else
   #if Varexist( "_usb_Endp2Addr")
      Dim _usb_tx_status2 As Byte At _usb_tx_status + _usb_tx_bufsize Overlay
      Dim _usb_tx_buffer2(_usb_packetsize) As Byte At _usb_tx_buffer + _usb_tx_bufsize Overlay
   #endif
#endif

Dim _usb_crc As Word
Dim _usb_crcl As Byte At _usb_crc Overlay
Dim _usb_crch As Byte At _usb_crc + 1 Overlay
Dim _usb_status As Byte
Dim _usb_status2 As Byte
Dim Senddescriptor As Byte




Installing libusb-win32 USB Driver

USB filter driver downloaded from:   http://sourceforge.net/projects/libusb-win32/

External connected device like usb mouse and keyboard fails on my Win7 x64 and x86 after a software installation reboot, so I've search the net for driver fix or a custom complied driver for x64, some forum user had suggested the following installation procedure (Right Click and select Properties on the "libusb-win32-filter-bin-x.x.xx.x.exe" installation file, check the compatibility mode and select WinXP SP2 and  Run as Administrator, but don't seems to work too) while most had mention about Signature issue on both Vista and Win7. libusb-win32 usb driver only works upto WinXP x86.

WinUSB (Microsoft)

 

 

 


FT232B

 
FT232B (MOUSER: 895-FT232BL S$8.86 LQFP-32) Hardware base USB-UART converter IC.





FT232R

 FT232R (MOUSER: 895-FT232RL S$6.93 SSOP-28) reduce B.O.M. cost for USB interface designs compared to its FT232B predecessor.
  • CBUS0..4 pin can be configured as TXDEN, SLEEP#, PWREN#, TXLED#, RXLED#, TX&RXLED# or 6/12/24/48Mhz Clock generated output through FT_PROG EEPROM programming utility.
  • Integrated  USB resistor, AVCC filter, Crystal and EEPROM to store the VID / PID and various USB chip configuration.
  • D2XX and VCP Drivers support most operating system including WinXP, Vista and Win7 x86 and x64.






FT_PROG 1.3.x - EEPROM Programming Utility

Install D2XX Direct Drivers - here.
Download VCP drivers - here.
CDM uninstaller - here.
D2XX driver Win7 installation guide -
here.
D2XX driver WinXP installation guide -
here.

FT_PROG v1.3.x download
here
.
FT_PROG User Guide can be downloaded here
.



 Click 'Open Template' icon browse to Template folder and select default 'template.xml'.

 

Go to Chip_Details, on Property Type and select 'FT232R' from drop down menu.

 

Go to USB_Config_Descriptor ,select 'Self Powered' and Max Bus Power = 0mA

 

Go to Hardware_Specific -> IO_Controls, drop down menu select C0 -> TX&RXLED# , C1-3 -> I/O MODE and C4 -> CLK12, leave the rest at default setting and save FT232R.xml as new template. You are ready to program the FT232 chip using the existing usb cable.


PureBasic Program

http://www.purebasic.com

I've wrote a small application using Purebasic to test the comm between PC < > micro.

This page is under construction.. I'll add more as I go!