qmk / qmk_firmware

Open-source keyboard firmware for Atmel AVR and Arm USB families
https://qmk.fm
GNU General Public License v2.0
18.22k stars 39.23k forks source link

Audio not working on Alps64 (atmega32u2) #5339

Closed gabriel-wilkes closed 2 years ago

gabriel-wilkes commented 5 years ago

Describe the Bug

If add AUDIO_ENABLE = yes to my rules.mk file the firmware will compile and flash with no issue but the keyboard never starts working, for example it will say this in the console after flashing:

DFU device disconnected TMK - Alps64 connected -- 0xFEED:0x6464 TMK - Alps64 disconnected -- 0xFEED:0x6464 TMK - Alps64 connected -- 0xFEED:0x6464 TMK - Alps64 disconnected -- 0xFEED:0x6464 TMK - Alps64 connected -- 0xFEED:0x6464 TMK - Alps64 disconnected -- 0xFEED:0x6464 TMK - Alps64 connected -- 0xFEED:0x6464

None of the keys work or do anything, but if I set AUDIO_ENABLE = no and reflash then the keyboard then it works normally (all keys are working) and shows this in console:

DFU device disconnected TMK - Alps64 connected -- 0xFEED:0x6464 done. Keyboard start.

System Information

Additional Context

The microcontroller is a atmega32u2 which is less common and I think could be a source of the issue I have wired up a piezoelectric speaker to C6 and GND on breakout pins that are on later revisions of the Alps64

If I add #define C6_AUDIO to the config.h file I get the following compilation error:

Compiling: quantum/audio/audio.c                                                                   quantum/audio/audio.c: In function 'audio_init':
quantum/audio/audio.c:45:41: error: 'TIMSK3' undeclared (first use in this function); did you mean 'TIMSK0'?
     #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
                                         ^
quantum/audio/audio.c:190:11: note: in expansion of macro 'DISABLE_AUDIO_COUNTER_3_ISR'
           DISABLE_AUDIO_COUNTER_3_ISR;
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
quantum/audio/audio.c:45:41: note: each undeclared identifier is reported only once for each function it appears in
     #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
                                         ^
quantum/audio/audio.c:190:11: note: in expansion of macro 'DISABLE_AUDIO_COUNTER_3_ISR'
           DISABLE_AUDIO_COUNTER_3_ISR;
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/Cellar/avr-gcc@7/7.3.0/avr/include/avr/io.h:99:0,
                 from quantum/config_common.h:29,
                 from ./keyboards/alps64/config.h:21,
                 from <command-line>:0:
quantum/audio/audio.c:45:56: error: 'OCIE3A' undeclared (first use in this function); did you mean 'OCIE0A'?
     #define DISABLE_AUDIO_COUNTER_3_ISR TIMSK3 &= ~_BV(OCIE3A)
                                                        ^
quantum/audio/audio.c:190:11: note: in expansion of macro 'DISABLE_AUDIO_COUNTER_3_ISR'
           DISABLE_AUDIO_COUNTER_3_ISR;
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~
quantum/audio/audio.c:43:34: error: 'TCCR3A' undeclared (first use in this function); did you mean 'TCCR0A'?
     #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);
                                  ^
quantum/audio/audio.c:216:13: note: in expansion of macro 'INIT_AUDIO_COUNTER_3'
             INIT_AUDIO_COUNTER_3
             ^~~~~~~~~~~~~~~~~~~~
quantum/audio/audio.c:43:49: error: 'COM3A1' undeclared (first use in this function); did you mean 'COM0A1'?
     #define INIT_AUDIO_COUNTER_3 TCCR3A = (0 << COM3A1) | (0 << COM3A0) | (1 << WGM31) | (0 << WGM30);

This continues on but I think this is probably enough of the error log to understand the issue

gabriel-wilkes commented 5 years ago

I was able to resolve the build errors and get a very small chirp out of the speaker by changing the quantum/audio/audio.c file (as seen below), I took some values from the B5_AUDIO section and put them in the C6_AUDIO section as C6 pin on the atmega32u2 seemed to more closely look like the atmega32u4 B5 which this seems designed for. However, when flashing the firmware all that happens is that the firmware flashes it exits DFU, chirps and then renters DFU immediately. So the keyboard basically doesn't work.

#if defined(C6_AUDIO)
    #define BPIN_AUDIO
    #define CPIN_SET_DIRECTION DDRC |= _BV(PORTC6);
    #define INIT_AUDIO_COUNTER_1 TCCR1A = (0 << COM1A1) | (0 << COM1A0) | (1 << WGM11) | (0 << WGM10);
    #define ENABLE_AUDIO_COUNTER_1_ISR TIMSK1 |= _BV(OCIE1A)
    #define DISABLE_AUDIO_COUNTER_1_ISR TIMSK1 &= ~_BV(OCIE1A)
    #define ENABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A |= _BV(COM1A1);
    #define DISABLE_AUDIO_COUNTER_1_OUTPUT TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0));
    #define TIMER_1_PERIOD     ICR1
    #define TIMER_1_DUTY_CYCLE OCR1A
    #define TIMER1_AUDIO_vect TIMER1_COMPA_vect
gabriel-wilkes commented 5 years ago

Getting closer, put a 100 ohm resistor between GND and the piezo. It now makes real sound, a two tone sound on a repeating loop, it no longer re-enters DFU mode after flashing but it just loops the sound forever and never starts acting as a keyboard

gabriel-wilkes commented 5 years ago

More progress, if I set AUDIO_ENABLE = no and I put the following code in the startup of the keyboard, I can get some little chirps at startup and it continues to startup and function normally:

    setPinOutput(C6);
    writePinHigh(C6);
    _delay_ms(125);
    writePinLow(C6);
    _delay_ms(125);
    writePinHigh(C6);
    _delay_ms(125);
    writePinLow(C6);
    _delay_ms(125);

Something about the audio feature is causing the keyboard to continually crash or reboot but sound does work

gabriel-wilkes commented 5 years ago

Maybe not enough RAM on the atmega32u2? It only has 2.5k vs. 1k on the atmega32u4

gabriel-wilkes commented 5 years ago

I found a solution coding basic audio without using the QMK audio feature, it it helps anyone here is some sample code:

#include <avr/io.h>
#include <util/delay.h>
#define SPEAKER_PORT    PORTC
#define SPEAKER_DDR     DDRC
#define SPEAKER_PIN     6

void delay_10_us(uint16_t count) {
  while(count--) {
    _delay_us(10);
  }
}

void PLAYNOTE(float duration, float frequency)
{
    long int i,cycles;
    float half_period;
    float wavelength;
    wavelength=(1/frequency)*1000;
    cycles=duration/wavelength;
    half_period = (wavelength/2)*34;

    SPEAKER_DDR |= (1 << SPEAKER_PIN);
    for (i=0;i<cycles;i++)
    {
        delay_10_us(half_period);
        SPEAKER_PORT |= (1 << SPEAKER_PIN);
        delay_10_us(half_period);
        SPEAKER_PORT &= ~(1 << SPEAKER_PIN);
    }
    return;
}

    PLAYNOTE(400,880);
    PLAYNOTE(400,932);
    PLAYNOTE(400,988);
    PLAYNOTE(400,1047);
    PLAYNOTE(400,1109);
drashna commented 5 years ago

I'm reopening this, because yeah, the current audio stuff does not work on the ATMega32u2 chip.

I ran into this myself with a different board. And this is a bug, and needs to be fixed.

github-actions[bot] commented 2 years ago

This issue has been automatically marked as stale because it has not had activity in the last 90 days. It will be closed in the next 30 days unless it is tagged properly or other activity occurs. For maintainers: Please label with bug, in progress, on hold, discussion or to do to prevent the issue from being re-flagged.

tzarc commented 2 years ago

Closing due to inactivity.