logo elektroda
logo elektroda
X
logo elektroda

PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard

p.kaczmarek2 195 0

TL;DR

  • Builds USB HID support for the PIC16LF1459 using the free SDCC compiler, then turns it into LED control, a calculator, a mouse, and a keyboard.
  • Uses the PIC’s built-in USB module, internal oscillator, and Active Clock Tuning, with custom HID descriptors and EP0 SET_REPORT handling instead of external libraries.
  • The chip offers 14 KB of Flash, 1 KB of RAM, and hardware USB up to 12 Mbps through a 512-byte shared memory buffer.
  • A Python HID script can switch the LED, exchange 2+2-style messages, and send mouse and keyboard reports successfully.
  • The hardest parts are descriptor setup and basic USB state handling; the keyboard also needs a HID_SET_PROTOCOL response or the host may reject it.
Generated by the language model.
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
📢 Listen (AI):
  • PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    I invite you to a little adventure with the PIC16LF1459, an 8-bit microcontroller made by Microchip, distinguished by its hardware USB support with a minimum of external components. You don't even need an external oscillator - the built-in one has enough precision. Here I will run USB communication on it using the free SDCC compiler, all without external libraries. I will show here examples of HID applications, such as simple LED control, data exchange using a simple 'maths coprocessor' as an example, and then show how to realise practical HID-compatible devices - a mouse and a keyboard.


    A proper tutorial on SDCC:
    Tutorial PIC18F2550 + SDCC - Part 1 - Setting up the operating environment

    A few words about the PIC16LF1459
    The PIC16(L)F1459 is an 8-bit microcontroller based on a RISC core by Microchip. It has 14 KB of Flash memory and 1 KB of RAM. Depending on the version, it can operate at 1.8 - 3.6 V (L version), and at 2.3 to 5.5 V. It is distinguished by hardware USB (compatible with USB Low and Full Speed - up to 12 Mbps) based on a 512-byte shared memory buffer. Among other things, the PIC16LF1459 is available in a hobbyist-friendly DIP package.
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard


    Connecting to the PIC
    The PIC shown requires a very small number of components to run. Basically you need to give a 100 nF decoupling capacitor between the power supply pins, this is for the principle, as in any microcontroller, and a 10 kΩ resistor between the MCLR pin and the power supply - this to get the PIC to boot, shorting MCLR to ground resets the circuit.
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    The PICKIT3 is suitable for programming, although with the new Device File even the PICKIT2 can handle it. We program via ICSP:
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    I posted the Device File for PICKIT2 in my older topic about this PIC. There I was still running it with a commercial microC, for that reason I think the solution presented today is a big step forward.
    PIC16F1459 boot board with USB
    PICKIT2 handled this PIC with no problems at my place:
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard

    Hello World - Blink LED
    Blink LED is often the first program I run on microcontrollers. It allows me to check that the batch starts at all and that it works at least somewhat stably.
    Code: C / C++
    Log in, to see the code

    The program starts the PIC with the built-in resonator, the OSCCON register is used to configure it. I then configure the entire C port as an output, and flip its state to the opposite state in a loop. The function waiting 1000 ms is a simple blocking loop. In the target program this shouldn't be there, as it just wastes CPU cycles, but for a test it's acceptable.
    Now just connect the LED and resistor to any pin from port C:
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    Basically that's it - the LED flashes:
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard


    Simple USB - LED control via HID
    Now we come to the actual USB part. I'll start with the LED control. I'll put all the code in the appendices, although I won't go quite into the theory that is "under the hood". Still first the connection - I used the USB breakout board for this:
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    Overall, running USB on the PIC16LF1459 in the SDCC compiler requires proper configuration of the registers responsible for this module and defining basic descriptors for the device, configuration and interface in the HID class. Hardware-wise, the PIC relieves us to a large extent, e.g. with the Active Clock Tuning (ACT) function, which, through continuous synchronisation to USB frames (SOF), allows a stable 48 MHz from the built-in internal oscillator, but we have to program the descriptors ourselves. In the C code itself, handling the diode control is reduced to intercepting SET_REPORT requests on the control endpoint (EP0) and reading the sent data byte. To connect to such a configured device on the computer side, we can use a short script in the system Python based on the HID library, which, due to the use of the standard HID class, works "out of the box" and does not require the installation of any additional drivers in the operating system.
    The most important parts - the descriptors, let's pay attention to Vendor and Product, by this we will know our device:
    Code: C / C++
    Log in, to see the code

    Transaction handling - state machine. The user is basically concerned here with parsing ep0out_buf, which is the HID frame buffer, it can contain more than one byte. We have simplified it for now.
    Code: C / C++
    Log in, to see the code

    Hardware-wise we still need to remember the extra capacitor on Vusb (depending on the PIC version):
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    In the LF version we connect it to the power supply, otherwise a capacitor is needed.
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    This is enough for the PC to see the PIC:
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    Now the PC program - for convenience in Python. A short script that finds the device by the entered Vendor/Product and sends this one byte over the HID to switch the LED:
    Code: Python
    Log in, to see the code

    The program works and the LED can be controlled.
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard


    Packages USB HID - calculator
    Let's further demonstrate for completeness the sending of a byte string. We can base this on the calculator example, the script sends a 2+2 style request and the PIC calculates this equation and returns the result. Such a mechanism requires two-way communication - the PIC has to receive the data, process it and then send back the result. A one-way message is not enough here, as with LED control.
    So, receiving the data - processing it will be realised by the processIncoming function:
    Code: C / C++
    Log in, to see the code

    Sending the response - with the readiness flag attached (the program will then detect it and send the data on):
    Code: C / C++
    Log in, to see the code

    The heart of the calculator, i.e. parsing and calculations - the least important here, but for reference:
    Code: C / C++
    Log in, to see the code




    Result:

    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard


    USB HID device - mouse
    A standard USB mouse is an HID device these days. This means that the code from the previous example, with very little change, can control the movement of the cursor on the computer screen. The first thing that is missing to fully simulate a mouse is device identification - the device must report in the descriptors as a mouse. You can at least look up the ID values in the documentation at Microsoft:
    https://learn.microsoft.com/en-us/windows-har...dclass-hardware-ids-for-top-level-collections
    I have therefore completed the identifiers:
    Code: C / C++
    Log in, to see the code

    Code: C / C++
    Log in, to see the code

    Windows has since recognised the PIC as a mouse:

    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard
    Now the report still has to be sent. Windows rigidly expects the mouse to report, among other things, two bytes representing the cursor offset. All you need to do is send this via the HID, as in the previous example. For the example, I send the data resulting in a circular movement of the cursor. I didn't want to count trigonometry, so I generated an array resulting in circular movement:
    Code: C / C++
    Log in, to see the code

    Sending reports - looped index:
    Code: C / C++
    Log in, to see the code

    Generation of HID packet for mouse - format as expected by computer.
    Code: C / C++
    Log in, to see the code

    The result - the mouse does circles under any system, practical use is not there, but you can make a joke for someone.
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard


    USB HID device - keyboard
    Similarly - we look at the documentation and change the descriptors, the format of the data to be sent. In the HID Report Descriptor I changed the Usage Page to 0x01 (Generic Desktop) and Usage to 0x06 (Keyboard):
    https://learn.microsoft.com/en-us/windows-har...dclass-hardware-ids-for-top-level-collections
    In the Interface Descriptor I changed the protocol byte from 0x02 (Mouse) to 0x01 (Keyboard) - this tells the host at the interface level which device it is dealing with.
    The format of the report also changed - the mouse used to send 3 bytes (buttons, deltaX, deltaY), the keyboard sends 8 bytes in the standard Boot Keyboard format:
    Code: C / C++
    Log in, to see the code

    Apart from this, under the hood I had to do a small fix - as the HID support is done without an external library, the response to the HID_SET_PROTOCOL request (0x08) was missing. The host sends this request to the boot protocol keypads to switch between boot and report mode - without a valid response (ZLP), the host could declare the device inoperable.
    This leaves the main loop where I send the message:
    Code: C / C++
    Log in, to see the code

    Result:
    PIC16LF1459 tutorial - USB HID support in the free SDCC compiler - LED, mouse and keyboard

    Summary
    In summary, even a microcontroller as small as the PIC16LF1459 allows you to run functional USB communication without the use of heavy external libraries. Thanks to the built-in USB module, the ability to work with an internal oscillator and the Active Clock Tuning mechanism, it is possible to build a working device with a minimum of external components. The examples shown - from simple LED control, to data exchange in the form of a simple 'maths coprocessor', to mouse and keyboard emulation - show that implementing the HID class is relatively affordable, even when you implement most of the protocol handling yourself in code.
    At the same time, it can be seen that the most work is required to prepare the correct descriptors and to handle the basic states of the USB protocol. Once this foundation is correctly implemented, however, further experimentation mainly boils down to processing the transmitted data and defining custom HID reports. This opens the way to building all sorts of simple USB peripherals - controllers, service tools or interfaces to communicate with your own projects.
    Of course, you could also make a gamepad or joystick with multiple buttons and axes - maybe that's your next project?
    The whole thing also shows that the free SDCC compiler is completely sufficient for working with this microcontroller and avoids closed, commercial environments. So, with a bit of patience, it is possible to create a fully working USB stack 'from scratch' and, in the process, get a good understanding of what actually happens under the hood of USB communication. This gives you a lot of freedom in designing your own HID devices and the ability to tailor the implementation exactly to the needs of the project.
    Do you use HID communication in your own projects?
    I attach the developed codes together with the compiled hex files.
    Attachments:
    • pic16lf1459_usb_mouse_jiggler.zip (59.65 KB) You must be logged in to download this attachment.
    • pic16lf1459_usb_led.zip (63.18 KB) You must be logged in to download this attachment.
    • pic16lf1459_usb_keyboard_typer.zip (71.73 KB) You must be logged in to download this attachment.
    • pic16lf1459_usb_calculator.zip (74.79 KB) You must be logged in to download this attachment.

    Cool? Ranking DIY
    Helpful post? Buy me a coffee.
    About Author
    p.kaczmarek2
    Moderator Smart Home
    Offline 
    p.kaczmarek2 wrote 14330 posts with rating 12232, helped 648 times. Been with us since 2014 year.
  • ADVERTISEMENT
📢 Listen (AI):
ADVERTISEMENT