From 925d1cfb19da373249af716a6d7adc6d7450ec25 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 8 Nov 2022 16:16:40 -0800 Subject: [PATCH] samd21: Get beep code working Only supports TCC currently. Signed-off-by: Keith Packard --- src/samd21/ao_beep_samd21.c | 59 ++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/samd21/ao_beep_samd21.c b/src/samd21/ao_beep_samd21.c index eabe8a16..7fbbcba1 100644 --- a/src/samd21/ao_beep_samd21.c +++ b/src/samd21/ao_beep_samd21.c @@ -19,10 +19,18 @@ #include "ao.h" #include "ao_beep.h" +#define BEEP_SCALE (AO_SYSCLK / 750000) + void ao_beep(uint8_t beep) { - (void) beep; + struct samd21_tcc *tcc = AO_BEEP_TCC; + if (beep) { + tcc->per = (beep * BEEP_SCALE); + tcc->ctrla = (1 << SAMD21_TCC_CTRLA_ENABLE); + } else { + tcc->ctrla = (0 << SAMD21_TCC_CTRLA_ENABLE); + } } void @@ -33,7 +41,56 @@ ao_beep_for(uint8_t beep, AO_TICK_TYPE ticks) ao_beep(0); } +static void +ao_tcc_init(struct samd21_tcc *tcc, uint32_t apbcmask) +{ + samd21_pm.apbcmask |= apbcmask; + + /* Reset the device */ + tcc->ctrla = (1 << SAMD21_TCC_CTRLA_SWRST); + + while ((tcc->ctrla & (1 << SAMD21_TCC_CTRLA_SWRST)) != 0 || + (tcc->syncbusy & (1 << SAMD21_TCC_SYNCBUSY_SWRST)) != 0) + ; + + tcc->per = 94 * BEEP_SCALE; + + tcc->wave = ((SAMD21_TCC_WAVE_WAVEGEN_NFRQ << SAMD21_TCC_WAVE_WAVEGEN) | + (0 << SAMD21_TCC_WAVE_RAMP) | + (0 << SAMD21_TCC_WAVE_CIPEREN) | + (0 << SAMD21_TCC_WAVE_CCCEN(0)) | + (0 << SAMD21_TCC_WAVE_CCCEN(1)) | + (0 << SAMD21_TCC_WAVE_CCCEN(2)) | + (0 << SAMD21_TCC_WAVE_CCCEN(3)) | + (0 << SAMD21_TCC_WAVE_POL(0)) | + (0 << SAMD21_TCC_WAVE_POL(1)) | + (0 << SAMD21_TCC_WAVE_POL(1)) | + (0 << SAMD21_TCC_WAVE_POL(3)) | + (0 << SAMD21_TCC_WAVE_SWAP(0)) | + (0 << SAMD21_TCC_WAVE_SWAP(1)) | + (0 << SAMD21_TCC_WAVE_SWAP(1)) | + (0 << SAMD21_TCC_WAVE_SWAP(3))); + + tcc->dbgctrl = (1 << SAMD21_TCC_DBGCTRL_DBGRUN); +} + void ao_beep_init(void) { + struct samd21_port *port = AO_BEEP_PORT; + uint8_t pin = AO_BEEP_PIN; + struct samd21_tcc *tcc = AO_BEEP_TCC; + uint32_t apbc_mask = 1UL << AO_BEEP_TCC_APBC_MASK; + + if (tcc == &samd21_tcc0 || tcc == &samd21_tcc1) { + samd21_gclk_clkctrl(0, SAMD21_GCLK_CLKCTRL_ID_TCC0_TCC1); + } else { + samd21_gclk_clkctrl(0, SAMD21_GCLK_CLKCTRL_ID_TCC2_TC3); + } + + ao_tcc_init(tcc, apbc_mask); + + ao_enable_output(port, pin, 0); + + samd21_port_pmux_set(port, pin, AO_BEEP_FUNC); } -- 2.30.2