Skip to content

Instantly share code, notes, and snippets.

@ericmigi
Created December 19, 2024 07:24
Show Gist options
  • Select an option

  • Save ericmigi/2f264a9b1635e02030f13df7df8e6df1 to your computer and use it in GitHub Desktop.

Select an option

Save ericmigi/2f264a9b1635e02030f13df7df8e6df1 to your computer and use it in GitHub Desktop.
nrf52840 (xiao) + PCM5102A
class SimpleI2S {
private:
uint32_t buffer[2];
public:
void begin(uint32_t bck, uint32_t lrck, uint32_t din) {
NRF_I2S->ENABLE = 0;
NRF_I2S->PSEL.SCK = bck;
NRF_I2S->PSEL.LRCK = lrck;
NRF_I2S->PSEL.SDOUT = din;
NRF_I2S->PSEL.MCK = 0xFFFFFFFF;
NRF_I2S->PSEL.SDIN = 0xFFFFFFFF;
NRF_I2S->CONFIG.MCKEN = 1;
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV11;
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_32X;
NRF_I2S->CONFIG.MODE = I2S_CONFIG_MODE_MODE_MASTER;
NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_16BIT;
NRF_I2S->CONFIG.ALIGN = I2S_CONFIG_ALIGN_ALIGN_LEFT;
NRF_I2S->CONFIG.FORMAT = I2S_CONFIG_FORMAT_FORMAT_I2S;
NRF_I2S->CONFIG.CHANNELS = I2S_CONFIG_CHANNELS_CHANNELS_STEREO;
NRF_I2S->ENABLE = 1;
NRF_I2S->TASKS_START = 1;
}
void write(int16_t left, int16_t right) {
while (!NRF_I2S->EVENTS_TXPTRUPD);
buffer[0] = left;
buffer[1] = right;
NRF_I2S->TXD.PTR = (uint32_t)buffer;
NRF_I2S->RXTXD.MAXCNT = 2;
NRF_I2S->EVENTS_TXPTRUPD = 0;
}
};
SimpleI2S i2s;
const float FREQ = 440.0; // A440 concert pitch
const float SAMPLE_RATE = 44100.0;
const float ENVELOPE_FREQ = 2.0; // 2Hz amplitude modulation
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
i2s.begin(3, 29, 4);
}
void loop() {
static float phase = 0.0;
static float envelope_phase = 0.0;
// Generate sine wave with smooth amplitude modulation
float envelope = (sin(envelope_phase) + 1.0) * 0.5; // 0 to 1 smooth envelope
float sample = sin(phase) * envelope * 16384.0; // Reduced amplitude for less harshness
i2s.write((int16_t)sample, (int16_t)sample);
// Update phases
phase += 2 * PI * FREQ / SAMPLE_RATE;
if (phase >= 2 * PI) phase -= 2 * PI;
envelope_phase += 2 * PI * ENVELOPE_FREQ / SAMPLE_RATE;
if (envelope_phase >= 2 * PI) envelope_phase -= 2 * PI;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment