CSR ADK Buttons configuration

Posted on Posted in Embedded C/C++

The CSR VM gives rather limited access to the HW peripherals on the CSR chip. One of the peripherals are the GPIOs, called PIOs (Programmable IOs) in the CSR ecosystem. PIOs are typically used to connect simple HW peripherals to the CSR chip or to control external chips (using enable pins).

For inputs coming from external components to the CSR chip, the ADK provides a convenient interface to define PIO behavior. Aptly named button interface (since it is very useful to define buttons behavior), it uses a simple textual configuration file to auto-generate the PIO handler. The PIO handler will then send VM messages to the FW for every PIO event defined in the button configuration file.

The button interface uses the buttonparsepro.exe utility, which is called automatically by the ADK when a file ending in “.button” is added to the VM project. The utility itself need not be called bu the developer, except that when called without parameters it prints a very helpful example of how to configure various VM message based on HW PIO events.

The file format is divided into three parts:

  1. Configuration of the PIO
  2. General PIO configuration
  3. Configuration of the events

The file uses C++ single line comments (//) for comments.

PIO configuration

The button interface allows defining events for the PIOs (0 through 15), as well as the VREG_EN (the CSR’s wakeup pin) and the charger connection.

The typical definition defines an internal name for the PIOs which are then used in the button configuration file to define the actual button events. These names are not related to the VM messages that will be sent once the PIO event occur. In addition to the name, the PIO number is also specified to define which PIO is used.

The format for PIOs is as follows:

For the VREG_EN, one can use any other number above 15 but not 22 (to avoid overloading the regular PIOs or the charger):

The charger connection is always mapped to number 22 and is always referred to as CHG_EN. It is used to capture charger connected/disconnected:

General configuration

This section defines the debounce behavior of the button interface. The debounce mechanism is fairly simple, but is effective enough, defining the number of samples that need to be read at a specified time. The following example will want to read 2 samples that are the same in a period of 20 ms:

The charging connected/disconnected special PIO (CHG_EN above) has a separate debounce configuration:

VM Event configuration

This section is the most important one – the actual event definitions. The button interface allows for some pretty complex events, using multiple PIOs with varying timeout.

The message definition includes the name of the message that will be sent to the VM, the PIOs that will trigger the event (the button interface supports more than one PIO at a time) and the condition of the PIOs that will trigger the event.

A simple example of a single button press:

The above definition will send a BUTTON_UP_SHORT_PRESS VM message when the BUTTON_UP (defined as PIO 5 above) is released.

Long presses can also be expressed:

This will send a BUTTON_UP_LONG_PRESS VM message when the BUTTON_UP is held for more than a second and a half.

Multiple PIOs can be used to trigger an event:

Which will send the BUTTON_UP_AND_DOWN_PRESS VM message when both BUTTON_UP and BUTTON_DOWN are pressed and released together.

Multiple events can trigger the same message:

Which will send the BUTTON_UP_REPEATED VM message when the BUTTON_UP is pressed, and the every 500 milliseconds if the BUTTON_UP is kept pressed. This can be useful for volume up or fast forward behaviors.

Here’s a summary of the possible events the button interface supports:

  • enter – the event is sent when the button is pressed and before it is released
  • release – the event is sent when the button is pressed and then released
  • held timeout – the event is sent once after the button is held
  • repeat interval – the event is sent every interval milliseconds if the button is still held
  • held_release timeout – the event is sent after the button is released, but only if it was held for at least the time specified
  • double timeout – the event is sent after the button is pressed twice in the time specified

The button interface can allow for complex behaviors, but note must be taken that some event definitions may overlap, resulting in duplicate or incorrect messages being sent. For example, using both enter and held will result in the enter message firing before the the held message, which might lead to undesirable behavior. Using release together with held will typically give a better user experience.

Finally, the button interface can also be used together with special events triggered by the FW. These are referred to as external in the button interface definition, and are triggered in the FW by calling pioExternal(). The definition is simple, and from then on the external trigger can be used as any of the other button interface events:

Usage in the FW

The “.button” file needs to be added to the project, which will cause the ADK to auto-generate the C and H files for the button interface handling. The C and H files will have the same name as the “.button” file, with the extension “.c” and “.h”, respectively.

To initialize the button interface, simply include the generated H file and call pioInit. You’ll need to pass the address of an allocated PioState structure (which is also defined in the H file) and the TaskData definition that will receive the events:


Once this is done, the Task used will receive any messages that are generated from the PIOs.

7 thoughts on “CSR ADK Buttons configuration

  1. Hi thanks for the helpful post
    I am using the CSR8675 development board (H13179v2 with H13478v2) with ADK4.1
    When I download the default sink project, the buttons on the development board don’t seem to work
    Please bear with me while I describe what I mean

    I download the default sink project with no changes, and the corresponding .psr files from the configuration folder in the sink project folder, in to the development board
    I then enable debug messages in main.c, sink_buttons.c and sink_buttonmanager.c using the sink_debug.h file
    From Sink Configuration Tool -> Buttons->Translation and the development board circuit diagram, I noticed that SW5 on the bard is not used by anything in the default pskey configuration, so I changed one of the user events so that SHORT pressing SW5 (PIO8) would generate EventUsrTestModeAudio (Enter Test Mode Audio Event). I was hoping to see the debug message in the EventUsrTestModeAudio event handler section of the code
    [ MAIN_DEBUG((“HS : EventUsrTestModeAudio\n”)); ]

    However, I can see debug printf messages from sink_buttonmanager.c and sink_buttons.c when I press the button (I’m presuming this means the button press itself was detected) but I cannot see the debug printf message in the EventUsrTestModeHandler

    If I do this same thing on a different custom CSR8675 module (but the circuit is based on the CSR development board, all connections are almost identical, except that the custom board is smaller, that is, less PIO outputs available less number of LED’s, etc), the EventUsrTestModeHandler event occurs as expected.

    Is there something extra I need to do on the standard development board to enable the buttons?

    1. If the FW project is the same, and the PS configuration is the same, there shouldn’t be a difference in behavior. Any HW differences might lead to the button press not being registered by the CSR chip at all, but then you wouldn’t have the buttonmanager/buttons prints. I would advise verifying that both the FW and the PS configuration are the same on both boards.
      Also make sure that the states that the user event is enabled on are set correctly – perhaps it is a matter of the FW being in the wrong state, with the custom board having a different state management flow?

    1. The ADK can be downloaded from Qualcomm’s support site (CreatePoint), once you have the right licensing in place with them. This is not a free software you can use without association with Qualcomm (or CSR before 2016).

      1. Hello, I am trying to instrument the steps that occur when a client retrieves the list of GATT services and list of characteristics (not the values) from my GATT server on ADK6. Would you please let me know where I can hook code to (a) catch the incoming GATT requests and (b) catch the outbound response to the client? Thanks!

        1. I haven’t had the chance to work with the QCC family of chips on ADK 6. However, they should be relatively similar to the CSR chips and the older ADK 4, and that code is most likely part of the ADK library code, which you typically don’t see directly in the project. Most of these library code is open-sourced, and you also have a Makefile to recompile them if you want to modify that code.
          To find the library code, follow your regular server code until you reach a function call that you don’t have the implementation for (i.e. it’s in the ADK library), then search for that function in the ADK folder. That should point you to where the code sits (if it is present as .c files, or only have an .h file if not). If the source code (and not just the header) is available, you can start looking there to find what you are interested in.
          Do note that the more low-level handling of the Bluetooth is closed-source and you will only see header files, or messages being sent to internal implementation that you do not have access to.

Leave a Reply

Your email address will not be published. Required fields are marked *