first commit
This commit is contained in:
113
examples/nrf51/nrf51_audio_rx/nrf51_audio_rx.ino
Normal file
113
examples/nrf51/nrf51_audio_rx/nrf51_audio_rx.ino
Normal file
@@ -0,0 +1,113 @@
|
||||
// nrf51_audio_rx.pde
|
||||
// Sample sketch for nRF51822 and RadioHead
|
||||
//
|
||||
// Plays audio samples received in the radio receiver
|
||||
// through a MCP4725 DAC such as on a SparkFun I2C DAC Breakout - MCP4725 (BOB-12918)
|
||||
// works with matching transmitter (see nrf51_audio_tx.pde)
|
||||
// Works with RedBear nRF51822 board.
|
||||
// See examples/nrf51_audiotx/nrf51_audio.pdf for connection details
|
||||
|
||||
#include <nrf51.h>
|
||||
#include <nrf51_bitfields.h>
|
||||
#include <esb/nrf_esb.h>
|
||||
#include <RH_NRF51.h>
|
||||
#include <Wire.h>
|
||||
|
||||
// Number of samples per second to play at.
|
||||
// Should match SAMPLE_RATE in nrf51_audio_tx
|
||||
// The limiting factor is the time it takes to output a new sample through the DAC
|
||||
#define SAMPLE_RATE 5000
|
||||
|
||||
// Number of 8 bit samples per packet
|
||||
// Should equal or exceed the PACKET_SIZE in nrf51_audio_tx
|
||||
#define MAX_PACKET_SIZE 255
|
||||
|
||||
// Singleton instance of the radio driver
|
||||
RH_NRF51 driver;
|
||||
|
||||
void setup()
|
||||
{
|
||||
delay(1000);
|
||||
Serial.begin(9600);
|
||||
while (!Serial)
|
||||
; // wait for serial port to connect.
|
||||
|
||||
if (!driver.init())
|
||||
Serial.println("init failed");
|
||||
// Defaults after init are 2.402 GHz (channel 2), 2Mbps, 0dBm
|
||||
|
||||
// Set up TIMER
|
||||
// Use TIMER0
|
||||
// Timer freq before prescaling is 16MHz (VARIANT_MCK)
|
||||
// We set up a 32 bit timer that restarts every 100us and outputs a new sample
|
||||
NRF_TIMER0->PRESCALER = 0 << TIMER_PRESCALER_PRESCALER_Pos;
|
||||
NRF_TIMER0->MODE = TIMER_MODE_MODE_Timer << TIMER_BITMODE_BITMODE_Pos;
|
||||
NRF_TIMER0->BITMODE = TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos;
|
||||
NRF_TIMER0->CC[0] = VARIANT_MCK / SAMPLE_RATE; // Counts per cycle
|
||||
// When timer count expires, its cleared and restarts
|
||||
NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk;
|
||||
NRF_TIMER0->TASKS_START = 1;
|
||||
// Enable an interrupt when timer completes
|
||||
NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
|
||||
|
||||
// Enable the TIMER0 interrupt, and set the priority
|
||||
// TIMER0_IRQHandler() will be called after each sample is available
|
||||
NVIC_SetPriority(TIMER0_IRQn, 1);
|
||||
NVIC_EnableIRQ(TIMER0_IRQn);
|
||||
|
||||
// Initialise comms with the I2C DAC as fast as we can
|
||||
// Shame the 51822 does not suport the high speed I2C mode that the DAC does
|
||||
Wire.begin(TWI_SCL, TWI_SDA, TWI_FREQUENCY_400K);
|
||||
}
|
||||
|
||||
volatile uint32_t count = 0;
|
||||
|
||||
uint8_t buffer_length = 0;
|
||||
uint8_t buffer[MAX_PACKET_SIZE];
|
||||
uint16_t buffer_play_index = 0;
|
||||
|
||||
// Write this sample to analog out
|
||||
void analog_out(uint8_t val)
|
||||
{
|
||||
// This takes about 120usecs, which
|
||||
// is the limiting factor for our sample rate of 5kHz
|
||||
// Writes to MCP4725 DAC over I2C using the Wire library
|
||||
Wire.beginTransmission(0x60); // 7 bit addressing
|
||||
Wire.write((val >> 4) & 0x0f);
|
||||
Wire.write((val << 4) & 0xf0);
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
// Called by timer interrupt
|
||||
// Output the next available sample
|
||||
void output_next_sample()
|
||||
{
|
||||
if (buffer_play_index < buffer_length)
|
||||
{
|
||||
analog_out(buffer[buffer_play_index++]);
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Look for a new packet of samples
|
||||
if (driver.available())
|
||||
{
|
||||
// expect one of these every 40ms = 25Hz
|
||||
// This takes about 400us:
|
||||
buffer_length = sizeof(buffer);
|
||||
driver.recv(buffer, &buffer_length);
|
||||
buffer_play_index = 0; // Trigger the interrupt playing of this buffer from the start
|
||||
}
|
||||
}
|
||||
|
||||
// This interrupt handler called when the timer interrupt fires
|
||||
// Time to output the next sample
|
||||
void TIMER0_IRQHandler(void)
|
||||
{
|
||||
// It is vitally important that analog output completes before
|
||||
// the next interrupt becomes due!
|
||||
output_next_sample();
|
||||
NRF_TIMER0->EVENTS_COMPARE[0] = 0; // Clear the COMPARE[0] event and the interrupt
|
||||
}
|
||||
|
Reference in New Issue
Block a user