Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Need some hint to usb device development

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR old unsupported versions
View previous topic :: View next topic  
Author Message
krolikbest

Bascom Member



Joined: 02 Jan 2017
Posts: 118

poland.gif
PostPosted: Mon Jul 14, 2025 12:54 pm    Post subject: Need some hint to usb device development Reply with quote

Hi,
I plan to use nRF24 device along with my Windows machine. This device will play as a receiver and it should work with few of transmitters (also nRF24l01) by multiplexing channels. (theoretically do-able). Now I have to solve how connect nRF24 to Windows machine and there it comes idea of use some chip/device with 32U on board for example.. The software (I plan to build) on Windows could communicate with this 32U chip/device and allow to config some properties on it or collects infos from it.So basically saying, nRF24 is connected with 32U device via SPI and 32U is connected to PC via USB. Now question - device 32U should be discovered by Windows machine as a some device with own HID, not as a COMXX, what do I need to use to achive it? Next question - concerning my own software, is there any library that Bascom provides I could use in my application, and in case Yes, any examples how do I consume such library?

Thanks,

Martin

[b][color=red](BASCOM-AVR version : 2.0.8.5 , Latest : 2.0.8.7 )[/b][/color]
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6203
Location: Holland

blank.gif
PostPosted: Mon Jul 14, 2025 1:28 pm    Post subject: Reply with quote

The MCS Shop has an USB add on.
It is suited for the chip you use.
Here is one of the samples :
It will only work with the add on. But you can see how HID works.

Code:

'------------------------------------------------------------------------------
'                     (c) 1995-2025 MCS Electronics
'                     hid_generic-M32u4.bas
' generic HID input and output sample, based on Atmels sample
'------------------------------------------------------------------------------
$regfile = "m32u4def.dat"
$crystal = 16000000
$baud = 19200

$hwstack = 64
$swstack = 64
$framesize = 64

Const Mdbg = 1                                              ' if you want to see all USB communication turn it on but turin it off(0) for your application since it will cost space
Const Chiddevice = 1                                        ' set this on for HID devices


Config Clockdiv = 1                                         ' we let the internal clock divider divide by 1 which will result in 8 Mhz clock
Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0


Const Vendor_id = &H16D0                                    ' MCS Vendor ID
Const Product_id = &H201D                                   ' MCS product ID, you can buy a PID in the MCS shop
'specific device constants
Const Ep_control_length = 32
Const User_conf_size = 41
Const Size_of_report = 53
Const Device_class = 0
Const Device_sub_class = 0
Const Device_protocol = 0
Const Release_number = &H1000
Const Length_of_report_in = 8
Const Length_of_report_out = 8
Const Interface_nb = 0
Const Alternate = 0
Const Nb_endpoint = 2
Const Interface_class = 3                                   ' HID
Const Interface_sub_class = 0
Const Interface_protocol = 0
Const Interface_index = 0

'Config Com1 = Dummy , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Print "USB GENERIC test"

Declare Sub Usb_user_endpoint_init
Declare Sub Hid_test_hit()
Declare Sub Hid_task()
Declare Sub Hid_task_init()

Const Usb_config_attributes_reserved = &H80
Const Usb_config_buspowered = Usb_config_attributes_reserved
Const Usb_config_selfpowered = Usb_config_attributes_reserved Or &H40
Const Usb_config_remotewakeup = Usb_config_attributes_reserved Or &H20

Const Nb_interface = 1
Const Conf_nb = 1
Const Conf_index = 0
Const Usb_remote_wakeup = 0
Const Conf_attributes = Usb_config_buspowered   + Usb_config_remotewakeup

Const Max_power = 50                                        ' 100 mA


Const Interface_nb_mouse = 0
Const Alternate_mouse = 0
Const Nb_endpoint_mouse = 1
Const Interface_class_mouse = 3                             ' HID Class
Const Interface_sub_class_mouse = 1                         ' Sub Class is Mouse
Const Interface_protocol_mouse = 2                          ' Mouse
Const Interface_index_mouse = 0

Const Nb_endpoints = 2                                      ' number of endpoints in the application including control endpoint
Const Ep_kbd_in = 1                                         ' Number of the mouse interrupt IN endpoint
Const Ep_hid_in = 1
Const Ep_hid_out = 2

Const Endpoint_nb_1 = Ep_hid_in Or &H80
Const Ep_attributes_1 = 3                                   ' BULK = 0x02, INTERUPT = 0x03
Const Ep_in_length_1 = 8
Const Ep_size_1 = Ep_in_length_1
Const Ep_interval_1 = 20                                    ' Interrupt polling interval from host

Const Endpoint_nb_2 = Ep_hid_out
Const Ep_attributes_2 = 3                                   ' BULK = 0x02, INTERUPT = 0x03
Const Ep_out_length = 8
Const Ep_size_2 = Ep_out_length
Const Ep_interval_2 = 20                                    ' interrupt polling from host


Config Usb = Device , Language = &H0409 , Manufact = "MCS" , Product = "MCSHID162" , Serial = "MC0001"


'Dim some user vars
Dim Usb_kbd_state As Byte , Usb_key As Byte , Usb_data_to_send As Byte
Dim Dummy As Byte , Dummy1 As Byte , Dummy2 As Byte

Print "task init"
Usb_task_init                                               ' init the usb task
Hid_task_init                                               ' init the USB task
Do
  Usb_task                                                  'call this subroutine once in a while
  Hid_task                                                  'call this subroutine once in a while
  'you can call your sub program here
Loop

'nothing needed to init
Sub Hid_task_init()
  'nothing
End Sub


'HID task must be checked regular
Sub Hid_task()
    If Usb_connected = 1 Then                               ' Check USB HID is enumerated
       Usb_select_endpoint Ep_hid_out                       ' Get Data Repport From Host
       If Ueintx.rxouti = 1 Then                            ' Is_usb_receive_out())
          Dummy1 = Uedatx : Print "Got : " ; Dummy1         ' it is important that you read the same amount of bytes here as were sent by the host !
          Dummy2 = Uedatx : Print "Got : " ; Dummy2
          Dummy = Uedatx : Print "Got : " ; Dummy
          Dummy = Uedatx : Print "Got : " ; Dummy
          Dummy = Uedatx : Print "Got : " ; Dummy
          Dummy = Uedatx : Print "Got : " ; Dummy
          Dummy = Uedatx : Print "Got : " ; Dummy
          Dummy = Uedatx : Print "Got : " ; Dummy
          Usb_ack_receive_out
      End If

      If Dummy1 = &H55 And Dummy2 = &HAA Then               ' Check if we received DFU mode command from host
         Usb_detach                                         ' Detach Actual Generic Hid Application
         Waitms 500
         'Goto &H1FC00                                        'goto bootloader
         'here you could call the bootloader then
      End If

      Usb_select_endpoint Ep_hid_in                         ' Ready to send these information to the host application
      If Ueintx.txini = 1 Then                              ' Is_usb_in_ready())
         Uedatx = 1
         Uedatx = 2
         Uedatx = 3
         Uedatx = 4
         Uedatx = 5
         Uedatx = 6
         Uedatx = 7
         Uedatx = 8
         Usb_ack_fifocon                                    ' Send data over the USB
      End If
    End If
End Sub

'this function is called for user requests
Function Usb_user_read_request(type As Byte , Request As Byte) As Byte
  #if Mdbg
    Print "USB_USER_READ_REQ"
  #endif
  Usb_string_type = Uedatx                                  'Usb_read_byte();
  Usb_descriptor_type = Uedatx                              'Usb_read_byte();
  Usb_user_read_request = 0
  Select Case Request
     Case Get_descriptor:
        Select Case Usb_descriptor_type
           Case Report : Call Hid_get_report()
                         Usb_user_read_request = 1
           Case Hid : Call Hid_get_hid_descriptor()
                      Usb_user_read_request = 1
           Case Else
              Usb_user_read_request = 0
        End Select
    Case Set_configuration:
        Select Case Usb_descriptor_type
         Case Set_report : Call Hid_set_report()
                Usb_user_read_request = 1
         Case Else
               Usb_user_read_request = 0
        End Select
   Case Get_interface:
        '//      usb_hid_set_idle();
      Call Usb_hid_get_interface()
      Usb_user_read_request = 1
   Case Else
     Usb_user_read_request = 0
 End Select
End Function

'usb_init_device.
'This function initializes the USB device controller and
'configures the Default Control Endpoint.
Sub Usb_init_device()
   #if Usbhost
      Usb_select_device
   #endif
  #if _chip = 70 Or _chip = 71                             'if usb1287 or usb646
   If Usbsta.id = 1 Then                                    'is it an USB device?
   #endif
      Uenum = Ep_control                                    ' select USB endpoint
      If Ueconx.epen = 0 Then                               ' usb endpoint not enabled yet
         Call Usb_configure_endpoint(ep_control , Type_control , Direction_out , Size_32 , One_bank , Nyet_disabled)
      End If
 #if _chip = 70 Or _chip = 71                             'if usb1287 or usb646
     End If
 #endif
End Sub


'init the user endpoints
Sub Usb_user_endpoint_init(byval Nm As Byte)
  Call Usb_configure_endpoint(ep_hid_in , Type_interrupt , Direction_in , Size_8 , One_bank , Nyet_enabled)
  Call Usb_configure_endpoint(ep_hid_out , Type_interrupt , Direction_out , Size_8 , One_bank , Nyet_enabled)
End Sub

'the following data is all USB data
Usb_dev_desc:
Data 18 , Device_descriptor                                 ' size and device_descriptor
Data 0 , 2                                                  ' Usb_write_word_enum_struc(USB_SPECIFICATION)
Data Device_class , Device_sub_class                        ' DEVICE_CLASS  and  DEVICE_SUB_CLASS
Data Device_protocol , Ep_control_length                    ' device protol and ep_control_length
Data Vendor_id%                                             ' Usb_write_word_enum_struc(VENDOR_ID)
Data Product_id%                                            ' Usb_write_word_enum_struc(PRODUCT_ID)
Data Release_number%                                        ' Usb_write_word_enum_struc(RELEASE_NUMBER)
Data Man_index , Prod_index                                 ' MAN_INDEX and  PROD_INDEX
Data Sn_index , Nb_configuration                            ' SN_INDEX and NB_CONFIGURATION


Usb_conf_desc:
Data 9 , Configuration_descriptor                           ' length , CONFIGURATION descriptor
Data User_conf_size%                                        ' total length of data returned
Data Nb_interface , Conf_nb                                 ' number of interfaces for this conf. ,  value for SetConfiguration resquest
Data Conf_index , Conf_attributes                           ' index of string descriptor  , Configuration characteristics
Data Max_power                                              ' maximum power consumption


Data 9 , Interface_descriptor                               ' length ,  INTERFACE descriptor type
Data Interface_nb , Alternate                               ' Number of interface   ,   value to select alternate setting
Data Nb_endpoint , Interface_class                          ' Number of EP except EP 0  ,Class code assigned by the USB
Data Interface_sub_class , Interface_protocol               ' Sub-class code assigned by the USB  , Protocol code assigned by the USB
Data Interface_index                                        ' Index Of String Descriptor


Data 9 , Hid_descriptor                                     ' length  , HID descriptor type
Data Hid_bdc% , 8                                           ' Binay Coded Decimal Spec. release  , Hid_country_code
Data Hid_class_desc_nb , Hid_descriptor_type                ' Number of HID class descriptors to follow ,  Report descriptor type
Data Size_of_report%                                        ' HID KEYBOARD LENGTH

Data 7 , Endpoint_descriptor                                ' Size Of This Descriptor In Bytes    ,  ENDPOINT descriptor type
Data Endpoint_nb_1 , Ep_attributes_1                        ' Address of the endpoint   ,Endpoint's attributes
Data Ep_size_1%                                             ' Maximum packet size for this EP  ,   Interval for polling EP in ms
Data Ep_interval_1

Data 7 , Endpoint_descriptor                                ' Size Of This Descriptor In Bytes    ,  ENDPOINT descriptor type
Data Endpoint_nb_2 , Ep_attributes_2                        ' Address of the endpoint  ,  Endpoint's attributes
Data Ep_size_2%                                             ' Maximum packet size for this EP
Data Ep_interval_2                                          ' Interval for polling EP in ms


Usb_hid_report:
Data &H06 , &HFF , &HFF                                     ' 04|2   , Usage Page (vendordefined?)
Data &H09 , &H01                                            ' 08|1   , Usage      (vendordefined
Data &HA1 , &H01                                            ' A0|1   , Collection (Application)
'      // IN report
Data &H09 , &H02                                            ' 08|1   , Usage      (vendordefined)
Data &H09 , &H03                                            ' 08|1   , Usage      (vendordefined)
Data &H15 , &H00                                            ' 14|1   , Logical Minimum(0 for signed byte?)
Data &H26 , &HFF , &H00                                     ' 24|1   , Logical Maximum(255 for signed byte?)
Data &H75 , &H08                                            ' 74|1   , Report Size(Cool = field size in bits = 1 byte
Data &H95 , Length_of_report_in                             ' 94|1:ReportCount(size) = repeat count of previous item
Data &H81 , &H02                                            ' 80|1: IN report (Data,Variable, Absolute)
'      // OUT report
Data &H09 , &H04                                            ' 08|1   , Usage      (vendordefined)
Data &H09 , &H05                                            ' 08|1   , Usage      (vendordefined)
Data &H15 , &H00                                            ' 14|1   , Logical Minimum(0 for signed byte?)
Data &H26 , &HFF , &H00                                     ' 24|1   , Logical Maximum(255 for signed byte?)
Data &H75 , &H08                                            ' 74|1   , Report Size(Cool = field size in bits = 1 byte
Data &H95 , Length_of_report_out                            ' 94|1:ReportCount(size) = repeat count of previous item
Data &H91 , &H02                                            ' 90|1: OUT report (Data,Variable, Absolute)
'      // Feature report
Data &H09 , &H06                                            ' 08|1   , Usage      (vendordefined)
Data &H09 , &H07                                            ' 08|1   , Usage      (vendordefined)
Data &H15 , &H00                                            ' 14|1   , LogicalMinimum(0 for signed byte)
Data &H26 , &HFF , &H00                                     ' 24|1   , Logical Maximum(255 for signed byte)
Data &H75 , &H08                                            ' 74|1   , Report Size(Cool =field size in bits = 1 byte
Data &H95 , &H04                                            ' 94|1:ReportCount
Data &HB1 , &H02                                            ' B0|1:   Feature report
Data &HC0                                                   ' C0|0    , End Collection
 

_________________
Mark
Back to top
View user's profile Visit poster's website
JC

Bascom Member



Joined: 15 Dec 2007
Posts: 630
Location: Cleveland, OH

usa.gif
PostPosted: Mon Jul 14, 2025 7:28 pm    Post subject: Reply with quote

There are many ways to solve most projects.

The approach you mentioned is a very reasonable one.

You did not mention if this is a large scale, commercial product, with lots of devices, or if you are only building one system at the moment.

If I was going to do this, I might try what I think would be a simpler approach.

(I think there is a significant learning curve to using embedded USB)

I would take a $2 (USD), (i.e. very cheap!), Nano and plug its USB port into the PC. It will show up under Device Manager as a serial port. Then I’d write the Windows program using whatever language (C, Visual Basic, Python, etc.), that you want to use.

The data through put for a serial device exceeds that for a HID device, and the serial communications mode is also pre-embedded into Windows, so no special Windows driver is needed for either.

The Nano would interface to one of the nRF24 devices, as the Master, controlled by the PC.

You could have the PC broadcast packets to all of the remote nRF24 devices. Use a “packet”, with a Start of Packet character, Command Byte, Data, and a CheckSum byte. The remote that is being asked for data can then reply, with its data packet, (including its I.D.).

With this configuration you do not have to learn about using an embedded USB module, you have a faster data rate, you have a very low cost, and the software on the Nano is very minimal, (easy). It simply passes PC commands to the nRF, and passes the received data back to the PC. Adding ISR driven buffers is easy with Bascom. Having a Start of Packet character and a CheckSum makes it easy for the Nano to recognize good data, and pass that to the PC.

(With RF, there is always “noise”, and garbage data, etc., that the system has to recognize and ignore.).

Just my thoughts…
Good luck with your project!

JC
Back to top
View user's profile Visit poster's website
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6203
Location: Holland

blank.gif
PostPosted: Mon Jul 14, 2025 8:01 pm    Post subject: Reply with quote

The example sends and receives 8 bytes. but it can be more like 32 or 64 with some simple mods.
The advantage is that you do not need any driver and it works on all devices like PC, android, IOS , linux
The USB stack does need time from the micro so when your app must do a lot of other stuff then it might not be practicle.
I built USB LCD displays, and many other USB HID devices. But every application has it own demands.

_________________
Mark
Back to top
View user's profile Visit poster's website
krolikbest

Bascom Member



Joined: 02 Jan 2017
Posts: 118

poland.gif
PostPosted: Tue Jul 15, 2025 8:49 am    Post subject: Reply with quote

Hi,
this solution you (@JC) write about is the most convenient, I have solved tasks this way several times. I am considering using USB chip because of the lack of need to configure the COMXX port in my potential application (unless I am wrong). In other words, the application is supposed to automatically detect the 32U device and send/receive data to/from the 32U device.Regarding the amount of transmitters, no more as 7-8. The whole installation is so far for test and it will create a grid of sensors collecting data from a specific area of up to 400 m2 at most. WiFi is out, interference, need for a router, etc.
Assuming I go for a USB HID device, how should my application (I will be writing in FreePascal) communicate with the HID device? Are there any examples, e.g. in Visual Basic or another language, showing how to establish communication with the HID device; do I need, on the side of e.g. Visual basics, some special library to communicate with this device? Or am I, not yet familiar with the subject, already complicating the issue for myself?

Regards,
Martin
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 6203
Location: Holland

blank.gif
PostPosted: Tue Jul 15, 2025 9:04 am    Post subject: Reply with quote

when you google for freepascal and hid component you find lot of code. it is probably not much different than the ones i use with delphi.
usb hid can detect any plugged device. it will not the VID and PID and a serial etc. just look at the sample i shown and config usb.
it also detects when you remove it. i give all my devices a unique PID so i know which device is plugged.
when you need to transpost lots of data the CDC (com is a better alternative). while USB can also do high speed it also means less time for your other code.
USB does require that you put some time in learning it. the samples i made are translated from the atmel C code. but it is nothing to be afraid of for an experienced bascom programmer.
It is more like taking the sample and adjusting things and adding your own code.

_________________
Mark
Back to top
View user's profile Visit poster's website
krolikbest

Bascom Member



Joined: 02 Jan 2017
Posts: 118

poland.gif
PostPosted: Tue Jul 15, 2025 9:38 am    Post subject: Reply with quote

So, putting informations in order for myself, the code in Bascom will enable OS to detect the device (that's obvious), on the side of my application I need to find a solution to communicate my application with the detected device. All clear.

Regards,
Martin
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM-AVR old unsupported versions All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You can post new topics in this forum
You can 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
You cannot attach files in this forum
You cannot download files in this forum