Controlador de volume multimídia baseado em Atmega 32u4 (parte 11/25)

Atmega 32u4 based multimedia volume controller (part 11/25)

How a multimedia keyboard is made has already been explained in the Atmega 32u4-based multimedia keyboard project . In this project, a keyboard has been designed to control the media functions of the window media player in the Windows operating system. A set of tactile switches was used to receive user input in that project. This project – Multimedia Volume Control will control the main volume of the Windows operating system. Furthermore, in the project, instead of using tactile switches, LDR sensors are used for user inputs to demonstrate a gesture recognition application. As with the multimedia keyboard project, in this project too the device will be configured for a consumer device rather than a generic desktop control device. In the USB protocol, when the usage page report item for an HID device is configured for consumer type, the device is configured for application-specific controls.

The 8-bit USB AVR – Atmega 32u4 is used as the device controller chip in the project. The project uses AVR-based Lightweight USB Framework (LUFA) as firmware which is modified to function as a gesture-controlled volume controller.

Protótipo de controlador de volume USB para PC baseado em Arduino

Fig. 1: Arduino-based PC USB volume controller prototype

The LUFA firmware is used to implement the USB protocol and its HID device driver class for Consumer controls is modified to program the project. With the use of LUFA firmware, the device driver code to implement the USB protocol does not need to be written explicitly. Modifying the firmware code to implement multimedia functionality corresponding to the operating system is just one challenge in the project. The volume controller will have four LDR sensors connected to the Arduino board vertically. When the finger is swiped from the bottom to the top, the main (master) volume of the operating system (Windows) will increase, while when the finger is swiped from the top to the bottom, the main (master) volume of the operating system (Windows) will decrease.

The project uses LDR sensors with transistorized circuits for user inputs, Atmega 32u4 as a USB controller chip (onboard Arduino Pro Micro) and USB cable for connection to the personal computer.

PREREQUISITES

This project is based on the Arduino Pro Micro which has the USB AVR – Atmega 32u4 as the sitting MCU. To understand this project, it is necessary to have basic knowledge of AVR microcontrollers and embedded C programming for AVRs. WinAVR Studio is used to write, edit, and compile project code, so closely following the project will also require familiarity with the IDE mentioned above. Although the LUFA framework takes care of implementing the USB protocol and has APIs to abstract the lower-level codes, understanding the USB protocol is recommended to understand how the project is actually working. In fact, if anyone has worked on some other microcontroller, it won't be very difficult to understand and follow this project as the project code is more or less about taking input from the GPIO pins of the AVR MCU and modifying the LUFA device driver to work as volume controller appropriately.

Controlador de volume multimídia baseado em Atmega 32u4

Fig. 2: Image showing PC volume control via Arduino-based USB device

REQUIRED COMPONENTS

1. Arduino Pro Micro

2. Test board

3. Connecting wires

4. LDR

5. BC547 Transistors

6. Micro USB cable

7. 10K Resistors

REQUIRED SOFTWARE TOOLS

1. WinAVR Studio

2. AVR Guy

3. LUFA Firmware

Diagrama de blocos do controlador de volume USB PC baseado em Arduino

Fig. 3: Block diagram of Arduino based USB PC volume controller

CIRCUIT CONNECTIONS

The project uses Arduino Pro Micro as the USB controller chip. A set of LDR sensors are connected to port B of the Arduino. The sensors are connected to pins 2, 4, 5 and 6 of port B. LDR sensors have an analog output that is converted into a digital output by the transistor circuit. BC547 switching transistors are used for analog to digital signal conversion. The transistors are connected in the circuit in a common base configuration with the emitter terminal connected to ground and the collector connected to VCC. The output is taken from the collector of the transistors and passed to the port B pins. The LDR sensors are connected between the VCC and the base of the transistor.

When the LDR sensor is receiving light, if the finger is not obstructing the light, its resistance remains low and a high signal is received at the base of the transistor. Thus, the transistor is biased to remain completely ON and the HIGH signal is shunted through the emitter and a logic LOW is received at the respective port B pin. When the LDR sensor is not receiving light in case the finger is obstructing the light to it, its resistance remains high and the low signal is received at the base of the transistor. Thus, the transistor is biased to remain completely off and the HIGH signal is not bypassed by the emitter and a logic HIGH is received at the respective port B pin.

Finger movement is detected from top to bottom or bottom to top by checking the HIGH logic sequence on the Port B pins and consequently the volume is controlled.

The program code for the project is written on the Arduino Pro Micro using AVR Dude. The Arduino board is connected to a PC's USB port via a USB cable.

HOW THE PROJECT WORKS

In this project, the USB protocol is implemented by the LUFA framework. To configure the controller chip to function as a multimedia controller, the HID Class Driver from the LUFA framework is used. The Human Interface Device (HID) class handles transfers between the host device and human-controlled USB peripherals. Any device using the HID class sends two reports – usage report and data report to the host device. Reports are a means at the application layer according to the USB protocol to facilitate enumeration and communication between the host and peripheral device.

In the USB protocol, device types are referenced by configuring the device for specific controls. The type of controls is defined by the Usage Report Usage page report item. To configure a specific control type, the predefined byte code(s) needs to be passed to the usage page report item from the usage page. The different types of controls/device types and the respective byte code(s) that need to be passed in the usage page report item for their configuration are already described in a table in Atmega 32u4 based multimedia keyboard design . After the usage page report item is defined in the usage report, predefined usage report items are defined in the usage report to configure the device for specific controls corresponding to that usage page or control type.

Imagem mostrando a função Diminuir volume do controlador de volume USB PC baseado em Arduino

Fig. 4: Image showing the Volume Down function of the Arduino-based USB PC volume controller

In the LUFA framework, the usage page report item is defined by the HID_RI_USAGE_PAGE macro and the usage report items were defined by the HID_RI_USAGE macros.

For this project the device is configured to be a consumer device passing 0x0C in HID_RI_USAGE_PAGE. When configuring the consumer usage page type, the device is configured for application-specific communication over USB. The volume increase and decrease controls used in the project are configured by the HID_RI_USAGE macros in the LUFA structure usage report, where the following codes defined by the USB protocol are passed in the macros -:

Tabela listando os controles do controlador de volume USB PC e respectivos códigos de uso

Fig. 5: Table listing the USB PC volume controller controls and respective usage codes

Check the HID usage table provided by the USB Implementers Forum to verify the correctness of the codes mentioned here. Check the consumer usage page code, it is 0x0C and check the usage codes in the consumer usage page section.

In the LUFA framework, modules related to the HID class are in the LUFA-Source-Folder/LUFA/Drivers/USB/Class/Device folder. These are the modules related to the device class. Application-specific device drivers are in the LUFA-Source-FolderProjects folders. To implement this project, the media controller project in the LUFA project folder will be modified and made compatible. The folder contains the MediaController.c file that will be modified to implement the project.

How MediaController.c identifies HID device as consumer device

MediaController.c uses the MediaControl_HID_Interface interface in the HID_Device_USBTask function being imported from HIDDeviceClass.c (from the LUFA-Source-Folder LUFADriversUSBClassDevice) to configure the device as a media controller. The interface abstracts the low-level descriptor codes and identifies the device as a media control application through an InterfaceNumber variable.

Multimedia specific report descriptors

Any HID device must exchange data with the host that must be structured in the form of reports. The report descriptor defines the structure of the report. A report descriptor contains the information needed by the host to determine the format of the data and how the data should be processed by the host. Therefore, a report descriptor basically structures the data that needs to be exchanged with the host according to the USB protocol.

As mentioned before, any HID device needs to send usage reports and data reporting descriptors specific to the device type to the host for USB communication. Usage Report informs the Host about the features or functionalities of the USB device, while Data Report (input) is used to transmit the data to the Host.

Where does MediaController.C get the usage and data reporting descriptors from?

In the LUFA framework, application-specific drivers are assigned the Projects folder. The Multimedia Controller Project is in the LUFA-Source-Folder/Projects/MediaController folder. MediaController.c imports the MediaController.h file in which the data report for media control application is defined in the form of a structure as follows -:

Captura de tela da estrutura definida em MediaController.h

Figure 6: Screenshot of the structure defined in MediaController.h

In MediaController.c, a MediaReport structure is used in the CALLBACK_HID_Device_CreateHIDReport function to generate data reporting descriptors and specific media control usage. The project also imports the descriptor.c file, which is provided in the same folder. Within descriptor.ca MediaReport structure are assigned the macros used to define the usage report items. Therefore the usage report for media control application is defined in descriptor.c as follows -:

Captura de tela da função CALLBACK_HID_Device_CreateHIDReport da biblioteca LUFA

Figure 7: Screenshot of the CALLBACK_HID_Device_CreateHIDReport function from the LUFA library

Check whether the HID_RI_USAGE_PAGE and HID_RI_USAGE macros have received the codes mentioned in the HID usage table.

For the implementation of this project, only the Volume Up and Volume Down functions are used.

USAGE REPORT

The usage report used in the project has the following report items –:

• USAGE_PAGE (CONSUMER) – the consumer control resources

• USAGE (VOLUME_UP) – the feature to increase the volume

• USAGE (VOLUME_DOWN) – the feature to decrease volume

• USE (PLAY) – playback feature

• USE (PAUSE) – pause feature

• USE (STOP) – stop feature

• USAGE (MUTE) – mute feature

• USAGE (NEXT_TRACK) – next track resource

• USAGE (PREVIOUS_TRACK) – previous track feature

• LOGICAL_MINIMUM (0) – logical zero means no keys were pressed

• LOGICAL_MAXIMUM (1) – logical will mean key pressed

These report items are set to the following values ​​in the descriptor.c file as mentioned previously.

Captura de tela dos valores dos itens do relatório definidos em descriptor.c

Fig. 8: Screenshot of report item values ​​defined in descriptor.c

The usage or resource report contains information about the device's capabilities. In other words, this report informs the Host about the resources required on the device. The Host can access this report by requesting the device using the GET_REPORT request. This report is transmitted using the Control Transfer Type of the USB protocol.

DATA REPORT (INPUT)

The Data Report (Input) contains the data that needs to be transmitted to the Host. It contains data related to the features selected through the Usage Report. In MediaController.ha the structure for media control application data reporting is defined as follows, as mentioned previously.

Captura de tela da estrutura definida em MediaController.h

Fig. 9: Screenshot of the structure defined in MediaController.h

The data report sends 11 bytes where each byte goes to define the logical maximum or logical minimum for the Play, Pause, Fast Forward, Rewind, Next Track, Previous Track, Stop, Play or Pause, Mute, Volume Up and Volume functions Down. It can also be seen from the usage report that the Report Count item is set to 0x0B (decimal 11) by the HID_RI_REPORT_COUNT macro.

HOW THE DEVICE WORKS

The AVR microcontroller is programmed to detect HIGH logic in specific sequences (bottom to top or top to bottom) according to the circuit connections of the LDR sensors. The main function and the CALLBACK_HID_Device_CreateHIDReport function of MediaController.c are modified to detect the HIGH logic sequence on the port B pins and change the Volume Up or Volume Down report item in the previous data report to the host on USB. Check the program code to see the modifications made to the MediaController.c file to implement the project.

PROGRAMMING GUIDE

To build the project, download the LUFA framework from github.com. The application project provided with the LUFA framework is modified to create this project. In the extracted LUFA zip file, open the LUFA-Source-Folder/Projects/MediaController folder. The folder contains the following files and folders.

Captura de tela da pasta da biblioteca LUFA no Windows

Fig. 10: Screenshot of the LUFA library folder on Windows

Of these, MediaController.h, MediaController.c and Makefile need to be modified for this project. The modified files (provided at the end of the article in zip format) can also be downloaded from the engineers' garage and replaced with the original files. Open the files in WinAVR Studio or Notepad++ and modify the original files or replace the files with already modified ones. The modified or replaced MediaController.c needs to be compiled into the LUFA Source folder to obtain the object code.

Modifying MediaController.h

The MediaController.h library file is imported into the MediaController.c file and includes a set of additional libraries and definitions of constants and functions for the media control application. This includes additional libraries for joystick, button, and LEDs that must be commented out as the project is not using these HID features. So, open MediaController.h and make the following changes –:

• Comment out the #include library statements for Joystick.h, LEDS.h, and Buttons.h (These libraries are commented because any joystick, button board, and LED board are not used in the project)

• Comment out the #define statements for LEDMASK_USB_NOTREADY, LEDMASK_USB_ENUMERATING, LEDMASK_USB_READY, LEDMASK_USB_ERROR

Save the file with changes.

Modifying the MediaController.C file

Again in MediaController.c, the code sections for Joystick, Button Board and LEDs need to be commented out. So open MediaController.c and make the following changes -:

• In the main loop, comment out LEDs_SetAllLEDs

• In the SetupHardware function, comment out Joystick_Init, LEDs_Init, Buttons_Init

• In the EVENT_USB_Device_Connect function, comment out LEDs_SetAllLEDs

• In the EVENT_USB_Device_Disconnect function, comment out LEDs_SetAllLEDs

• In the EVENT_USB_Device_ConfigurationChanged function, comment out LEDs_SetAllLEDs

In MediaController.ca the main function runs the application. Within the main function, port B where the LDR sensors have been connected needs to be set as input and all port B pins must be raised to logic LOW by default as the microcontroller will need to detect logic HIGH as user input. Therefore, add the following statements at the beginning of the main – function:

int main(empty) { ConfigurationHardware; DDRB = 0x00; PORTB = 0x00; //LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); GlobalInterruptEnable; for (;;) { HID_Device_USBTask(&MediaControl_HID_Interface); USB_USBTask; } }

Inside the infinite for loop the HID_Device_USBTask function is called where the MediaControl_HID_Interface interface is passed as a parameter. The interface identifies the device as a Media Control Application and abstracts the low-level program code specific to the Consumer HID class. The HID_Device_USBTask function comes from the HIDClassDevice.c module (located in LUFA/Drivers/USB/Class/Device/HIDClassDevice.c) and is used for general management tasks for a given HID class interface, necessary for the correct functioning of the interface . It must be called in the main program loop, before the USB management master task USB_USBTask . USB_USBTask is the main USB management task. The USB driver requires this task to be performed continuously when the USB system is active (device connected in host mode or connected to a host in device mode) to manage USB communications. The USB_USBTask function is defined in USBTask.c (located in the LUFA-Source-FolderLUFADriversUSBCore folder).

To send the required data (input) reports, CALLBACK_HID_Device_CreateHIDReport needs to be modified. The default file also has the function body for detecting joystick movement.

Captura de tela da função CALLBACK_HID_Device_CreateHIDReport na biblioteca LUFA

Fig. 11: Screenshot of the CALLBACK_HID_Device_CreateHIDReport function in the LUFA library

This design is a sequence of HIGH logic on the Port B pins to decide whether the volume should be increased or decreased. Therefore, the HIGH bit on each pin is detected by a sequence, and the volume increase or decrease report item of the data report is modified accordingly. So replace the function body with the following code -:

bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, uint8_t* const ReportID, const uint8_t ReportType, void* Report data, uint16_t* const ReportSize) { USB_MediaReport_Data_t* MediaReport = (USB_MediaReport_Data_t*)ReportData; /* Flags to indicate that the LDR has been blocked *or the finger was placed on it */ static bool LDR1_obstruct_flag; static bool LDR2_obstruct_flag; static bool LDR3_obstruct_flag; static bool LDR4_obstruct_flag; /* checks if LDR 1 is blocked * if obstructed, check other LDR flags * if other flags are set then it is the case of upward movement * modify data report for volume up command *otherwise set the LDR1 flag, it may be the start of the downward movement */ if(PINB & _BV(PB4)) { if(LDR4_obstruct_flag && LDR3_obstruct_flag && LDR2_obstruct_flag) { MediaReport->Increase Volume = 1; //update the report with VolumeUp //reset all flags LDR1_obstruct_flag = 0; LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; LDR4_obstruct_flag = 0; } other { LDR1_obstruct_flag = 1; // set the flag //reset all other flags LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; LDR4_obstruct_flag = 0; } } /* checks if LDR 2 is blocked * if obstructed, place the flag */ if(PINB & _BV(PB5)) { LDR2_obstruct_flag = 1; // set the flag } /* checks if LDR 3 is blocked * if obstructed, place the flag */ if(PINB & _BV(PB6)) { LDR3_obstruct_flag = 1; // set the flag } /* checks if LDR 3 is blocked * if obstructed, check other LDR flags * if other flags are set then it is the case of downward movement * modify data report for volume down command *otherwise set the LDR4 flag, it may be the start of upward movement */ if(PINB & _BV(PB2)) { if(LDR3_obstruct_flag && LDR2_obstruct_flag && LDR1_obstruct_flag) { MediaReport->VolumeDown = 1; //update the report with VolumeDown //reset all flags LDR1_obstruct_flag = 0; LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; LDR4_obstruct_flag = 0; } other { LDR4_obstruct_flag = 1; // set the flag //reset all other flags LDR1_obstruct_flag = 0; LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; } } *ReportSize = sizeof(USB_MediaReport_Data_t); returns false; }

In the body, Boolean variables are declared to detect HIGH or LOW logic on the pins. The _BV function is used to map the respective bit as a byte with only the respective bit changed in the returned byte.

HIGH logic is detected in specific sequences on the Port B pins and the volume increase or decrease data report item is modified to perform the main volume increase or decrease functions respectively.

Save the file and create the Make file for the project.

Modifying Create File

In the MediaController folder there is a make file that needs to be edited. The file can be edited using Notepad++. The following information needs to be edited.

• MCU = atmega32u4

• ARC = AVR8

• FRAMEWORK = LEONARDO

• F_CPU = 16000000

Save the file and exit. Now all files are completely edited for volume controller app.

Compiling MediaController.c

To compile the source code, you can use WinAVR Programmers Notepad or Arduino IDE. Open the modified MediaController.c file and compile the code.

BURNING HEX CODE

The hexadecimal file is generated when compiling the MediaController.c file. To write the object code to the microcontroller, open Command Prompt, change the current directory to the directory containing the Hex file. This can be done using the command: CD . Now restart the Arduino and instantly execute the command: : : avrdude -v -p atmega32u4 -c avr109 -P COM20 -b 57600 -D -Uflash:w:MediaController.hex:i after replacing the COM port with the recognized one.

If the upload process is successful, the Arduino will be shown as HID Consumer Control Device in Device Manager. There is no need to install any driver on the computer, as the generic HID driver is used to implement the project.

Connect the device to a Windows PC and swipe from top to bottom or bottom to top to check whether the system volume is decreasing or increasing in respective actions.

In the next project – UART to USB Converter based on Atmega 32u4 learn how to make a UART to USB converter on Arduino Pro Micro.

Project source code

###


 /*

 LUFA Library

 Copyright (C) Dean Camera, 2015.


 dean (at) fourwalledcubicle (dot) com

 www.lufa-lib.org

 */


 /*

 Copyright 2015 Dean Camera (dean (at) fourwalledcubicle (dot) com)
 Permission to use, copy, modify, distribute, and sell this
 software and its documentation for any purpose is hereby granted 
without fee, provided that the above copyright notice appears in
 all copies and that both that the copyright notice and this
 permission notice and warranty disclaimer appear in supporting
 documentation, and that the name of the author will not be used in
 advertising or publicity pertaining to distribution of the
 software without specific, written prior permission.


 The author disclaims all warranties with regard to this
 software, including all implied warranties of merchantability
 and fitness. In no event shall the author be responsible for any
 special, indirect or consequential damages or any damages
 either resulting from loss of use, data or profits, whether
 in an action of contract, negligence or other tortious action,
 arising out of or in connection with the use or performance of
 this software.

 */


 /** filet

 *

 * Main source file for the MediaControl project. This file contains the main tasks of

 * the demo and is responsible for the initial application hardware configuration.

 */

 
#include "MediaController.h"


 /** Buffer to hold the previously generated Media Control HID report,
 for comparison purposes inside the HID class driver. */

 static uint8_t PrevMediaControlHIDReportBuffer(sizeof(USB_MediaReport_Data_t));


 /** LUFA HID Class driver interface configuration and state information. This structure is

 * passed to all HID Class driver functions, so that multiple instances of the same class

 * within a device can be differentiated from one another.

 */

 USB_ClassInfo_HID_Device_t MediaControl_HID_Interface =

 {

 .Config =

 {

 .InterfaceNumber = INTERFACE_ID_HID,

 .ReportINendpoint =

 {

 .Address = MEDIACONTROL_HID_EPADDR,

 .Size = MEDIACONTROL_HID_EPSIZE,

 .Banks = 1,

 },

 .PrevReportINBuffer = PrevMediaControlHIDReportBuffer,

 .PrevReportINBufferSize = sizeof(PrevMediaControlHIDReportBuffer),

 },

 };



 /** Main program entry point. This routine contains the overall program flow, including initial
 
* setup of all components and the main program loop.

 */

 int main(void)

 {

 SetupHardware;

 DDRB = 0x00;

 DDRF = 0x00;

 //LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);

 GlobalInterruptEnable;


 for (;;)

 {

 HID_Device_USBTask(&MediaControl_HID_Interface);

 USB_USBTask;

 }

 }


 /** Configures the board hardware and chip peripherals for the demo's functionality. */

 void SetupHardware

 {

 #if (ARCH == ARCH_AVR8)

 /* Disable watchdog if enabled by bootloader/fuses */

 MCUSR &= ~(1 << WDRF);

 wdt_disable;


 /* Disable clock division */

 clock_prescale_set(clock_div_1);

 #endif


 /* Hardware Initialization */

 //Joystick_Init;

 //LEDs_Init;

 //Buttons_Init;

 USB_Init ;

 }


 /** Event handler for the library USB Connection event. */

 void EVENT_USB_Device_Connect(void)

 {

 //LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);

 }


 /** Event handler for the library USB Disconnection event. */

 void EVENT_USB_Device_Disconnect(void)

 {

 //LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);

 }


 /** Event handler for the library USB Configuration Changed event. */
 
void EVENT_USB_Device_ConfigurationChanged(void)

 {

 bool ConfigSuccess = true;


 ConfigSuccess &= HID_Device_ConfigureEndpoints(&MediaControl_HID_Interface);


 USB_Device_EnableSOFEvents ;


 //LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);

 }


 /** Event handler for the library USB Control Request reception event. */

 void EVENT_USB_Device_ControlRequest(void)

 {

 HID_Device_ProcessControlRequest(&MediaControl_HID_Interface);

 }


 /** Event handler for the USB device Start Of Frame event. */

 void EVENT_USB_Device_StartOfFrame(void)

 {

 HID_Device_MillisecondElapsed(&MediaControl_HID_Interface);

 }


 /** HID class driver callback function for the creation of HID reports to the host.

 *

 * param(in) HIDInterfaceInfo Pointer to the HID class
 interface configuration structure being referenced

 * param(in,out) ReportID Report ID requested by the host if non-zero,
 otherwise callback should set to the generated report ID

 * param(in) ReportType Type of the report to create,  
either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature

 * param(out) ReportData Pointer to a buffer where the created report should be stored

 * param(out) ReportSize Number of bytes written in the report (or zero if no report is to be sent)

 *

 * return Boolean c true to force the sending of the report, c false to let
 the library determines if it needs to be sent

 */

 bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,

 uint8_t* const ReportID,

 const uint8_t ReportType,

 void* ReportData,

 uint16_t* const ReportSize)

 {

 USB_MediaReport_Data_t* MediaReport = (USB_MediaReport_Data_t*)ReportData;


 /* Flags to indicate LDR has been obstructed

 * or finger has been placed over it

 */


 static bool LDR1_obstruct_flag;

 static bool LDR2_obstruct_flag;

 static bool LDR3_obstruct_flag;

 static bool LDR4_obstruct_flag;

 
/* check if LDR 1 is obstructed

 * if obstructed, check for other LDR flags

 * if other flags are set, then it is the case of up motion

 * modify the data report for volume up command

 * else set the LDR1 flag, it may be the starting of down motion 

*/

 if(PINB & _BV(PB4)) {


 if(LDR4_obstruct_flag && LDR3_obstruct_flag && LDR2_obstruct_flag)

 {

 MediaReport->VolumeUp = 1; // update report with VolumeUp

 // reset all flags

 LDR1_obstruct_flag = 0;

 LDR2_obstruct_flag = 0;

 LDR3_obstruct_flag = 0;

 LDR4_obstruct_flag = 0;

 }

 else

 {

 LDR1_obstruct_flag = 1; // set the flag

 // reset all other flags

 LDR2_obstruct_flag = 0;

 LDR3_obstruct_flag = 0;

 LDR4_obstruct_flag = 0;

 }

 }


 /* check if LDR 2 is obstructed

 * if obstructed, set the flag

 */

 if(PINB & _BV(PB5)) {

 LDR2_obstruct_flag = 1; // set the flag

 }


 /* check if LDR 3 is obstructed

 * if obstructed, set the flag

 */

 if(PINB & _BV(PB6)) {

 LDR3_obstruct_flag = 1; // set the flag

 }


 /* check if LDR 3 is obstructed
 
* if obstructed, check for other LDR flags

 * if other flags are set, then it is the case of down motion

 * modify the data report for volume down command

 * else set the LDR4 flag, it may be the starting of up motion 

*/

 if(PINB & _BV(PB2)) {


 if(LDR3_obstruct_flag && LDR2_obstruct_flag && LDR1_obstruct_flag)

 {

 MediaReport->VolumeDown = 1; // update report with VolumeDown

 // reset all flags

 LDR1_obstruct_flag = 0;

 LDR2_obstruct_flag = 0;

 LDR3_obstruct_flag = 0;

 LDR4_obstruct_flag = 0;

 }

 else

 {

 LDR4_obstruct_flag = 1; // set the flag

 // reset all other flags

 LDR1_obstruct_flag = 0;

 LDR2_obstruct_flag = 0;

 LDR3_obstruct_flag = 0;

 }

 }



 *ReportSize = sizeof(USB_MediaReport_Data_t);

 return false;

 }


 /** HID class driver callback function for the processing of HID reports from the host.

 *

 * param(in) HIDInterfaceInfo Pointer to the HID class
 interface configuration structure being referenced

 * param(in) ReportID Report ID of the received report from the host
 
* param(in) ReportType The type of report that the host has sent,
 either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature

 * param(in) ReportData Pointer to a buffer where the received report has been stored

 * param(in) ReportSize Size in bytes of the received HID report

 */

 void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo,

 const uint8_t ReportID,

 const uint8_t ReportType,

 const void* ReportData,

 const uint16_t ReportSize)

 {

 // Unused (but mandatory for the HID class driver) in this demo, since there are no Host->Device reports

 }

###

Circuit diagrams

Circuit diagram based on Arduino USB-PC volume controller

Project Technical Sheet

https://www.engineersgarage.com/wp-content/uploads/2019/10/makefile.zip



Back to the blog

Leave a comment

Comments need to be approved before publication.