Make h/w SPI still better and some cosmetic fixes

pull/18/head^2
Thierry Frenkel 4 years ago
parent 7197da8055
commit 07e09fcfaf
  1. 6
      Open_Theremin_V3/Open_Theremin_V3.ino
  2. 18
      Open_Theremin_V3/SPImcpDAC.h
  3. 23
      Open_Theremin_V3/ihandlers.cpp

@ -1,7 +1,7 @@
/*
* Open.Theremin control software for Arduino UNO
* Version 3.0
* Copyright (C) 2010-2016 by Urs Gaudenz
* Version 3.1
* Copyright (C) 2010-2020 by Urs Gaudenz
*
* Open.Theremin control software is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@ -19,6 +19,7 @@
* With important contributions by
* David Harvey
* Michael Margolis
* "Theremingenieur" Thierry Frenkel
*/
/**
@ -76,4 +77,3 @@ void setup() {
void loop() {
app.loop();
}

@ -45,18 +45,20 @@ static inline void SPImcpDACinit()
HW_SPI_DDR |= _BV(HW_SPI_MOSI_BIT);
// initialize the hardware SPI registers
SPCR = _BV(SPE) | _BV(MSTR); // no interrupt, SPI enable, MSB first, SPI master, SPI mode 0, clock = f_osc/4 (maximum)
SPSR |= SPI2X; // double the SPI clock, ideally we get 8 MHz, so that a 16bit word goes out in 2us plus only a small overhead
SPSR = _BV(SPI2X); // double the SPI clock, ideally we get 8 MHz, so that a 16bit word goes out in 3.5us (5.6us when called from an interrupt) including CS asserting/deasserting
}
static inline void SPImcpDACtransmit(uint16_t data)
{
// Send highbyte and wait for complete
SPDR = highByte(data);
while (!(SPSR && _BV(SPIF)))
asm("nop");
while (!(SPSR & _BV(SPIF)))
;
// Send lowbyte and wait for complete
SPDR = lowByte(data);
while (!(SPSR && _BV(SPIF)))
asm("nop");
while (!(SPSR & _BV(SPIF)))
;
}
@ -69,12 +71,12 @@ static inline void SPImcpDAClatch()
static inline void SPImcpDACsend(uint16_t data)
{
MCP_DAC_CS_PORT &= ~_BV(MCP_DAC_CS_BIT);
// Sanitize input data and add DAC config MSBs
data &= 0x0FFF;
data |= 0x7000;
// Sanitize input data and add DAC config MSBs
data &= 0x0FFF;
data |= 0x7000;
SPImcpDACtransmit(data);
MCP_DAC_CS_PORT |= _BV(MCP_DAC_CS_BIT);
// Do not latch immpediately, let's do it at the beginning of the next interrupt to get consistent timing
// Do not latch immpediately, let's do it at the very beginning of the next interrupt to get consistent timing
}
static inline void SPImcpDAC2Asend(uint16_t data)
@ -99,4 +101,4 @@ static inline void SPImcpDAC2Bsend(uint16_t data)
SPImcpDAClatch();
}
#endif
#endif

@ -106,14 +106,15 @@ void ihInitialiseVolumeMeasurement() //Measurement of variable frequency oscilla
/* Externaly generated 31250 Hz Interrupt for WAVE generator (32us) */
ISR (INT1_vect) {
// Interrupt takes up a total of 16us plus overhead when interrupted itself.
// Added by ThF 20200419
#ifdef TH_DEBUG
HW_LED2_ON;
#endif
// Interrupt takes up normally 14us but can take up to 22us when interrupted by another interrupt.
// Added by ThF 20200419
#ifdef TH_DEBUG
HW_LED2_ON;
#endif
// Latch previously written DAC value:
SPImcpDAClatch();
// Latch previously written DAC value:
SPImcpDAClatch();
disableInt1(); // Disable External Interrupt INT1 to avoid recursive interrupts
// Enable Interrupts to allow counter 1 interrupts
@ -126,18 +127,18 @@ ISR (INT1_vect) {
#if CV_ENABLED // Generator for CV output
vPointerIncrement = min(vPointerIncrement, 4095);
mcpDacSend(vPointerIncrement); //Send result to Digital to Analogue Converter (audio out) (9.6 us)
mcpDacSend(vPointerIncrement); //Send result to Digital to Analogue Converter (audio out) (5.5 us)
#else //Play sound
// Read next wave table value
waveSample = (int16_t)pgm_read_word_near(wavetables[vWavetableSelector] + offset);
scaledSample = ((int32_t)waveSample * (uint32_t)vScaledVolume) >> 16;
scaledSample = ((int32_t)waveSample * (uint32_t)vScaledVolume) >> 16; // The compiler optimizes this better than any assembly written by hand !!!
SPImcpDACsend(scaledSample + MCP_DAC_BASE); //Send result to Digital to Analogue Converter (audio out) (6 us)
SPImcpDACsend(scaledSample + MCP_DAC_BASE); //Send result to Digital to Analogue Converter (audio out) (5.5 us)
pointer += vPointerIncrement; // increment table pointer (ca. 2us)
pointer += vPointerIncrement; // increment table pointer
#endif //CV play sound
incrementTimer(); // update 32us timer

Loading…
Cancel
Save