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

Como é feito um teclado multimídia já foi explicado no Projeto de teclado multimídia baseado em Atmega 32u4. Nesse projeto, um teclado foi projetado para controlar as funções de mídia do reprodutor de mídia de janela no sistema operacional Windows. Um conjunto de interruptores táteis foi usado para receber as entradas do usuário naquele projeto. Este projeto – Controle de Volume Multimídia irá controlar o volume principal do sistema operacional Windows. Além disso, no projeto, em vez de usar interruptores táteis, sensores LDR são usados ​​para entradas do usuário para demonstrar uma aplicação de reconhecimento de gestos. Assim como no projeto do teclado multimídia, também neste projeto o dispositivo será configurado para um dispositivo de consumidor, em vez de um dispositivo genérico de controle de desktop. No protocolo USB, quando o item de relatório da página de uso de um dispositivo HID é configurado para o tipo de consumidor, o dispositivo é configurado para controles específicos do aplicativo.

O USB AVR – Atmega 32u4 de 8 bits é usado como chip controlador do dispositivo no projeto. O projeto usa Lightweight USB Framework (LUFA) baseado em AVR como firmware que é modificado para funcionar como um controlador de volume controlado por gestos.

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

Fig. 1: Protótipo de controlador de volume USB para PC baseado em Arduino

O firmware LUFA é utilizado para implementar o protocolo USB e sua classe de driver de dispositivo HID para controles Consumer é modificada para programar o projeto. Com o uso do firmware LUFA, o código do driver do dispositivo para implementar o protocolo USB não precisa ser escrito explicitamente. Modificar o código do firmware para implementar o funcionamento multimídia respectivo ao sistema operacional é apenas um desafio no projeto. O controlador de volume terá quatro sensores LDR conectados à placa Arduino de forma vertical. Quando o dedo é deslizado de baixo para cima, o volume principal (mestre) do sistema operacional (windows) aumentará, enquanto quando o dedo é deslizado de cima para baixo, o volume principal (mestre) do sistema operacional (windows) irá diminuir.

O projeto utiliza sensores LDR com circuitos transistorizados para entradas do usuário, Atmega 32u4 como chip controlador USB (onboard Arduino Pro Micro) e cabo USB para conexão com o computador pessoal.

PRÉ-REQUISITOS

Este projeto é baseado no Arduino Pro Micro que possui o USB AVR – Atmega 32u4 como MCU sentado. Para entender este projeto, é necessário ter conhecimentos básicos dos microcontroladores AVR e da programação C embarcada para AVRs. WinAVR Studio é usado para escrever, editar e compilar o código do projeto, portanto, acompanhar de perto o projeto também exigirá familiarização com o IDE mencionado acima. Embora a estrutura LUFA cuide da implementação do protocolo USB e possua APIs para abstrair os códigos de nível inferior, entendendo o protocolo USB é recomendado para entender como realmente o projeto está funcionando. Na verdade, se alguém já trabalhou em algum outro microcontrolador, não será muito difícil entender e seguir este projeto, pois o código do projeto é mais ou menos sobre como obter entrada dos pinos GPIO do AVR MCU e modificar o driver do dispositivo LUFA para funcionar como controlador de volume adequadamente.

Controlador de volume multimídia baseado em Atmega 32u4

Fig. 2: Imagem mostrando o controle de volume do PC por dispositivo USB baseado em Arduino

COMPONENTES NECESSÁRIOS

1. Arduino Pro Micro

2. Tábua de ensaio

3. Conectando fios

4. LDR

5. Transistores BC547

6. Cabo micro USB

7. Resistores de 10K

FERRAMENTAS DE SOFTWARE NECESSÁRIAS

1. Estúdio WinAVR

2. Cara do AVR

3. Firmware LUFA

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

Fig. 3: Diagrama de blocos do controlador de volume USB PC baseado em Arduino

CONEXÕES DE CIRCUITO

O projeto usa Arduino Pro Micro como chip controlador USB. Um conjunto de sensores LDR está conectado na porta B do Arduino. Os sensores são conectados nos pinos 2, 4, 5 e 6 da porta B. Os sensores LDR possuem saída analógica que é convertida em saída digital pelo circuito transistor. Os transistores chaveadores BC547 são usados ​​para conversão de sinal analógico em digital. Os transistores são conectados no circuito em configuração de base comum com terminal emissor conectado ao terra e coletor conectado ao VCC. A saída é retirada do coletor dos transistores e passada para os pinos da porta B. Os sensores LDR são conectados entre o VCC e a base do transistor.

Quando o sensor LDR estiver recebendo luz, caso o dedo não esteja obstruindo a luz, sua resistência permanece baixa e um sinal alto é recebido na base do transistor. Assim, o transistor é polarizado para permanecer completamente LIGADO e o sinal HIGH é desviado através do emissor e uma lógica LOW é recebida no respectivo pino da porta B. Quando o sensor LDR não estiver recebendo luz caso o dedo esteja obstruindo a luz para ele, sua resistência permanece alta e o sinal baixo é recebido na base do transistor. Assim, o transistor é polarizado para permanecer completamente desligado e o sinal HIGH não é desviado pelo emissor e uma lógica HIGH é recebida no respectivo pino da porta B.

O movimento do dedo é detectado de cima para baixo ou de baixo para cima, verificando a sequência da lógica HIGH nos pinos da Porta B e, consequentemente, o volume é controlado.

O código do programa para o projeto é gravado no Arduino Pro Micro usando AVR Dude. A placa Arduino é conectada à porta USB de um PC por um cabo USB.

COMO FUNCIONA O PROJETO

Neste projeto o protocolo USB é implementado pelo framework LUFA. Para configurar o chip controlador para funcionar como controlador multimídia, é utilizado o HID Class Driver do framework LUFA. A classe Human Interface Device (HID) cuida das transferências entre o dispositivo host e os periféricos USB controlados por humanos. Qualquer dispositivo que use a classe HID envia dois relatórios – relatório de uso e relatório de dados para o dispositivo host. Os relatórios são um meio na camada de aplicação de acordo com o protocolo USB para facilitar a enumeração e a comunicação entre o host e o dispositivo periférico.

No protocolo USB, os tipos de dispositivos são referenciados configurando o dispositivo para controles específicos. O tipo de controles é definido pelo item de relatório da página de uso do relatório de uso. Para configurar um tipo de controle específico, o código de byte(s) predefinido precisa ser passado para o item de relatório da página de uso da página de uso. Os diferentes tipos de controles/tipos de dispositivos e o respectivo código de byte(s) que precisa ser passado no item de relatório da página de uso para sua configuração já estão descritos em uma tabela em Projeto de teclado multimídia baseado em Atmega 32u4. Depois que o item do relatório da página de uso for definido no relatório de uso, os itens predefinidos do relatório de uso serão definidos no relatório de uso para configurar o dispositivo para controles específicos correspondentes a essa página de uso ou tipo de controle.

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

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

Na estrutura LUFA, o item do relatório da página de uso é definido pela macro HID_RI_USAGE_PAGE e os itens do relatório de uso foram definidos pelas macros HID_RI_USAGE .

Para este projeto o dispositivo é configurado para ser um dispositivo consumidor passando 0x0C em HID_RI_USAGE_PAGE. Ao configurar o tipo de página de uso do consumidor, o dispositivo é configurado para comunicação específica do aplicativo em USB. Os controles de aumento e diminuição de volume usados ​​no projeto são configurados pelas macros HID_RI_USAGE no relatório de uso da estrutura LUFA, onde os seguintes códigos definidos pelo protocolo USB são passados ​​nas macros -:

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

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

Confira a tabela de uso de HID fornecida pelo Fórum de implementadores USB para verificar a correção dos códigos aqui mencionados. Verifique o código da página de uso do consumidor, é 0x0C e verifique os códigos de uso na seção da página de uso do consumidor.

Na estrutura LUFA, os módulos relacionados à classe HID estão na pasta LUFA-Source-Folder/LUFA/Drivers/USB/Class/Device. Estes são os módulos relacionados à classe de dispositivo. Os drivers de dispositivos específicos do aplicativo estão nas pastas LUFA-Source-FolderProjects. Para implementar este projeto, o projeto do controlador de mídia na pasta de projetos LUFA será modificado e compatível. A pasta contém o arquivo MediaController.c que será modificado para implementar o projeto.

Como MediaController.c identifica o dispositivo HID como dispositivo de consumo

O MediaController.c usa a interface MediaControl_HID_Interface na função HID_Device_USBTask que está sendo importada do HIDDeviceClass.c (da LUFA-Source-Folder LUFADriversUSBClassDevice) para configurar o dispositivo como controlador de mídia. A interface abstrai os códigos descritores de baixo nível e identifica o dispositivo como um aplicativo de controle de mídia por meio de uma variável InterfaceNumber.

Descritores de relatórios específicos de multimídia

Qualquer dispositivo HID deve trocar dados com o host que devem ser estruturados na forma de relatórios. O descritor do relatório define a estrutura do relatório. Um descritor de relatório contém as informações necessárias ao host para determinar o formato dos dados e como os dados devem ser processados ​​pelo host. Portanto, um descritor de relatório basicamente estrutura os dados que precisam ser trocados com o host de acordo com o protocolo USB.

Conforme mencionado antes, qualquer dispositivo HID precisa enviar relatórios de uso e descritores de relatórios de dados específicos para o tipo de dispositivo ao host para comunicação USB. O Relatório de uso informa o Host sobre os recursos ou funcionalidades do dispositivo USB, enquanto o Relatório de dados (entrada) é usado para transmitir os dados ao Host.

De onde MediaController.C obtém os descritores de relatórios de uso e dados

Na estrutura LUFA, os drivers específicos do aplicativo recebem a pasta Projetos. O Projeto do Controlador Multimídia está na pasta LUFA-Source-Folder/Projects/MediaController. O MediaController.c importa o arquivo MediaController.h no qual o relatório de dados para aplicação de controle de mídia é definido na forma de uma estrutura da seguinte maneira -:

Captura de tela da estrutura definida em MediaController.h

Figura 6: Captura de tela da estrutura definida em MediaController.h

Em MediaController.c, uma estrutura MediaReport é usada na função CALLBACK_HID_Device_CreateHIDReport para gerar descritores de relatórios de dados e uso específico de controle de mídia. O projeto também importa o arquivo descriptor.c, que é fornecido na mesma pasta. Dentro descriptor.c a estrutura MediaReport são atribuídas as macros usadas para definir os itens do relatório de uso. Portanto o relatório de uso para aplicação de controle de mídia é definido no descritor.c da seguinte maneira -:

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

Figura 7: Captura de tela da função CALLBACK_HID_Device_CreateHIDReport da biblioteca LUFA

Verifique se as macros HID_RI_USAGE_PAGE e HID_RI_USAGE receberam os códigos mencionados na tabela de uso de HID.

Para a implementação deste projeto, apenas as funções Aumentar volume e Diminuir volume são utilizadas.

RELATÓRIO DE USO

O relatório de uso usado no projeto possui os seguintes itens de relatório –:

• USAGE_PAGE (CONSUMER) – os recursos de controle do consumidor

• USAGE (VOLUME_UP) – o recurso para aumentar o volume

• USAGE (VOLUME_DOWN) – o recurso para diminuir volume

• USO (PLAY) – recurso de reprodução

• USO (PAUSA) – recurso de pausa

• USO (STOP) – recurso de parada

• USAGE (MUTE) – recurso mudo

• USAGE (NEXT_TRACK) – recurso da próxima faixa

• USAGE (PREVIOUS_TRACK) – recurso de faixa anterior

• LOGICAL_MINIMUM (0) – zero lógico significa que nenhuma tecla foi pressionada

• LOGICAL_MAXIMUM (1) – lógico significará tecla pressionada

Esses itens de relatório são definidos com os seguintes valores no arquivo descriptor.c, conforme mencionado anteriormente.

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

Fig. 8: Captura de tela dos valores dos itens do relatório definidos no descritor.c

O relatório de uso ou recurso contém informações sobre os recursos do dispositivo. Em outras palavras, este relatório informa o Host sobre os recursos necessários no dispositivo. O Host pode acessar este relatório solicitando o dispositivo usando a solicitação GET_REPORT. Este relatório é transmitido usando o Control Transfer Type do protocolo USB.

RELATÓRIO DE DADOS (ENTRADA)

O Relatório de Dados (Entrada) contém os dados que precisam ser transmitidos ao Host. Ele contém dados relacionados aos recursos selecionados por meio do Relatório de uso. Em MediaController.ha a estrutura para relatório de dados do aplicativo de controle de mídia é definida da seguinte maneira, conforme mencionado anteriormente.

Captura de tela da estrutura definida em MediaController.h

Fig. 9: Captura de tela da estrutura definida em MediaController.h

O relatório de dados envia 11 bytes onde cada byte vai para definir o máximo lógico ou o mínimo lógico para as funções Play, Pause, Fast Forward, Rewind, Next Track, Previous Track, Stop, Play ou Pause, Mute, Volume Up e Volume Down. Também pode ser visto no relatório de uso que o item Report Count está definido como 0x0B (decimal 11) pela macro HID_RI_REPORT_COUNT.

COMO FUNCIONA O DISPOSITIVO

O microcontrolador AVR é ​​programado para detectar lógica HIGH em sequências específicas (de baixo para cima ou de cima para baixo) de acordo com as conexões do circuito dos sensores LDR. A função main e a função CALLBACK_HID_Device_CreateHIDReport do MediaController.c são modificadas para detectar a sequência de lógica HIGH nos pinos da porta B e alterar o item do relatório Aumentar ou Diminuir volume no relatório de dados anterior para o host no USB. Confira o código do programa para ver as modificações feitas no arquivo MediaController.c para implementação do projeto.

GUIA DE PROGRAMAÇÃO

Para construir o projeto, baixe o framework LUFA em github.com. O projeto de aplicação fornecido com a estrutura LUFA é modificado para criar este projeto. No arquivo zip LUFA extraído, abra a pasta LUFA-Source-Folder/Projects/MediaController. A pasta contém os seguintes arquivos e pastas.

Captura de tela da pasta da biblioteca LUFA no Windows

Fig. 10: Captura de tela da pasta da biblioteca LUFA no Windows

Destes, MediaController.h, MediaController.c e Makefile precisam ser modificados para este projeto. Os arquivos modificados (fornecidos no final do artigo em formato zip) também podem ser baixados da garagem dos engenheiros e substituídos pelos arquivos originais. Abra os arquivos no WinAVR Studio ou Notepad++ e modifique os arquivos originais ou substitua os arquivos pelos já modificados. O MediaController.c modificado ou substituído precisa ser compilado na pasta Source do LUFA para obter o código do objeto.

Modificando MediaController.h

O arquivo de biblioteca MediaController.h é importado no arquivo MediaController.c e inclui um conjunto de bibliotecas adicionais e as definições de constantes e funções para o aplicativo de controle de mídia. Isso inclui bibliotecas adicionais para joystick, botão e LEDs que devem ser comentadas, pois o projeto não está usando esses recursos HID. Portanto, abra MediaController.h e faça as seguintes alterações –:

• Comente as instruções da biblioteca #include para Joystick.h, LEDS.h e Buttons.h (Essas bibliotecas são comentadas porque qualquer joystick, placa de botões e placa de LED não são usados ​​no projeto)

• Comente as instruções #define para LEDMASK_USB_NOTREADY, LEDMASK_USB_ENUMERATING, LEDMASK_USB_READY, LEDMASK_USB_ERROR

Salve o arquivo com alterações.

Modificando o arquivo MediaController.C

Novamente no MediaController.c, as seções de código para Joystick, placa de botão e LEDs precisam ser comentadas. Portanto, abra MediaController.c e faça as seguintes alterações -:

• No loop principal, comente LEDs_SetAllLEDs

• Na função SetupHardware , comente Joystick_Init , LEDs_Init , Buttons_Init

• Na função EVENT_USB_Device_Connect , comente o LEDs_SetAllLEDs

• Na função EVENT_USB_Device_Disconnect , comente LEDs_SetAllLEDs

• Na função EVENT_USB_Device_ConfigurationChanged , comente o LEDs_SetAllLEDs

Em MediaController.c a função main executa o funcionamento da aplicação. Dentro da função principal, a porta B onde os sensores LDR foram conectados precisa ser definida como entrada e todos os pinos da porta B devem ser elevados para lógica LOW por padrão, pois o microcontrolador precisará detectar a lógica HIGH como entrada do usuário. Portanto, adicione as seguintes instruções no início da função main –:

int principal(vazio) { ConfiguraçãoHardware ; DDRB = 0x00; PORTB = 0x00; //LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); GlobalInterruptEnable ; para (;;) { HID_Device_USBTask(&MediaControl_HID_Interface); USB_USBTask ; } }

Dentro do loop for infinito a função HID_Device_USBTask é chamada onde a interface MediaControl_HID_Interface é passada como parâmetro. A interface identifica o dispositivo como Aplicativo de Controle de Mídia e abstrai o código do programa de baixo nível específico para a classe Consumer HID. A função HID_Device_USBTask vem do módulo HIDClassDevice.c (localizado em LUFA/Drivers/USB/Class/Device/HIDClassDevice.c) e é usada para tarefas de gerenciamento geral para uma determinada interface de classe HID, necessária para o correto funcionamento do a interface. Deve ser chamado no loop principal do programa, antes da tarefa mestre de gerenciamento USB USB_USBTask . O USB_USBTask é a principal tarefa de gerenciamento de USB. O driver USB exige que esta tarefa seja executada continuamente quando o sistema USB estiver ativo (dispositivo conectado no modo host ou conectado a um host no modo dispositivo) para gerenciar as comunicações USB. A função USB_USBTask é definida em USBTask.c (localizado na pasta LUFA-Source-FolderLUFADriversUSBCore).

Para enviar os relatórios de dados (entrada) necessários, CALLBACK_HID_Device_CreateHIDReport precisa ser modificado. O arquivo padrão também possui o corpo da função para detectar o movimento do joystick.

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

Fig. 11: Captura de tela da função CALLBACK_HID_Device_CreateHIDReport na biblioteca LUFA

Este projeto é uma sequência de lógica HIGH nos pinos da Porta B para decidir se o volume deve ser aumentado ou diminuído. Portanto, o bit HIGH em cada pino é detectado por uma sequência e o item de relatório de aumento ou diminuição de volume do relatório de dados é modificado de acordo. Portanto, substitua o corpo da função pelo seguinte código -:

bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, uint8_t* const ReportID, const uint8_t ReportType, void* Dados do relatório, uint16_t* const ReportSize) { USB_MediaReport_Data_t* MediaReport = (USB_MediaReport_Data_t*)ReportData; /* Flags para indicar que o LDR foi obstruído *ou o dedo foi colocado sobre ele */ bool estático LDR1_obstruct_flag; bool estático LDR2_obstruct_flag; bool estático LDR3_obstruct_flag; bool estático LDR4_obstruct_flag; /* verifica se o LDR 1 está obstruído * se obstruído, verifique outros sinalizadores LDR * se outros sinalizadores estiverem definidos, então é o caso de movimento ascendente * modifique o relatório de dados para o comando de aumentar volume * caso contrário, defina o sinalizador LDR1, pode ser o início do movimento descendente */ if(PINB & _BV(PB4)) { if(LDR4_obstruct_flag && LDR3_obstruct_flag && LDR2_obstruct_flag) { MediaReport->Aumentar Volume = 1; //atualiza o relatório com VolumeUp //reinicia todas as flags LDR1_obstruct_flag = 0; LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; LDR4_obstruct_flag = 0; } outro { LDR1_obstruct_flag = 1; // define a bandeira //reset todas as outras flags LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; LDR4_obstruct_flag = 0; } } /* verifica se o LDR 2 está obstruído * se obstruído, coloque a bandeira */ if(PINB & _BV(PB5)) { LDR2_obstruct_flag = 1; // define a bandeira } /* verifica se o LDR 3 está obstruído * se obstruído, coloque a bandeira */ if(PINB & _BV(PB6)) { LDR3_obstruct_flag = 1; // define a bandeira } /* verifica se o LDR 3 está obstruído * se obstruído, verifique outros sinalizadores LDR * se outros sinalizadores estiverem definidos, então é o caso de movimento descendente * modifique o relatório de dados para o comando de diminuir volume * caso contrário, defina o sinalizador LDR4, pode ser o início do movimento ascendente */ if(PINB & _BV(PB2)) { if(LDR3_obstruct_flag && LDR2_obstruct_flag && LDR1_obstruct_flag) { MediaReport->VolumeDown = 1; //atualiza o relatório com VolumeDown //reset todas as flags LDR1_obstruct_flag = 0; LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; LDR4_obstruct_flag = 0; } outro { LDR4_obstruct_flag = 1; // define a bandeira //reset todas as outras flags LDR1_obstruct_flag = 0; LDR2_obstruct_flag = 0; LDR3_obstruct_flag = 0; } } *ReportSize = sizeof(USB_MediaReport_Data_t); retorna falso; }

No corpo, variáveis ​​booleanas são declaradas para detectar lógica HIGH ou LOW nos pinos. A função _BV é usada para mapear o respectivo bit como um byte com apenas o respectivo bit alterado no byte retornado.

A lógica HIGH é detectada em sequências específicas nos pinos da Porta B e o item de relatório de dados de aumento ou redução de volume é modificado para executar as funções de aumento ou diminuição do volume principal, respectivamente.

Salve o arquivo e crie o arquivo Make para o projeto.

Modificando Criar Arquivo

Na pasta MediaController existe um arquivo make que precisa ser editado. O arquivo pode ser editado usando o Notepad++. As informações a seguir precisam ser editadas.

• MCU = atmega32u4

• ARCO = AVR8

• QUADRO = LEONARDO

• F_CPU = 16000000

Salve o arquivo e saia. Agora todos os arquivos estão completamente editados para o aplicativo controlador de volume.

Compilando MediaController.c

Para compilar o código-fonte, pode-se usar o WinAVR Programmers Notepad ou o Arduino IDE. Abra o arquivo MediaController.c modificado e compile o código.

CÓDIGO HEX ARDENTE

O arquivo hexadecimal é gerado na compilação do arquivo MediaController.c. Para gravar o código objeto no microcontrolador, abra o Prompt de Comando, altere o diretório atual para o diretório que contém o arquivo Hex. Isso pode ser feito usando o comando: CD . Agora reinicie o Arduino e execute instantaneamente o comando: : : avrdude -v -p atmega32u4 -c avr109 -P COM20 -b 57600 -D -Uflash:w:MediaController.hex:i após substituir a porta COM pela reconhecida.

Se o processo de upload for bem-sucedido, o Arduino será mostrado como HID Consumer Control Device no Gerenciador de Dispositivos. Não há necessidade de instalação de nenhum driver no computador, pois o driver HID genérico é utilizado para a implementação do projeto.

Conecte o dispositivo a um PC com Windows e deslize o dedo de cima para baixo ou de baixo para cima para verificar se o volume do sistema está diminuindo ou aumentando nas respectivas ações.

No próximo projeto – Conversor UART para USB baseado em Atmega 32u4aprenda como fazer um conversor UART para USB no Arduino Pro Micro.

Código fonte do projeto

###


/*

             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 appear 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 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 liable for any
  special, indirect or consequential damages or any damages
  whatsoever 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.

*/


/** file

 *

 *  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 determine 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

}

###

Diagramas de circuito

Diagrama de circuito baseado em Arduino controlador de volume USB-PC

Ficha Técnica do Projeto

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



Conteúdo Relacionado

Voltar para o blog

Deixe um comentário

Os comentários precisam ser aprovados antes da publicação.