From b59e92da9d7bb39f0e24ca402313d13ed68f93ab Mon Sep 17 00:00:00 2001 From: Thierry Frenkel Date: Sun, 19 Apr 2020 22:18:21 +0200 Subject: [PATCH] Revert "Hardware SPI" This reverts commit d17ded142fc0c6143bc033ac82c1477579eaad65. --- Open_Theremin_V3/OTPinDefs.h | 56 ++++++++++++ Open_Theremin_V3/SPImcpDAC.h | 102 --------------------- Open_Theremin_V3/application.cpp | 36 ++++---- Open_Theremin_V3/ihandlers.cpp | 31 +++---- Open_Theremin_V3/mcpDac.h | 151 +++++++++++++++++++++++++++++++ 5 files changed, 241 insertions(+), 135 deletions(-) create mode 100644 Open_Theremin_V3/OTPinDefs.h delete mode 100644 Open_Theremin_V3/SPImcpDAC.h create mode 100644 Open_Theremin_V3/mcpDac.h diff --git a/Open_Theremin_V3/OTPinDefs.h b/Open_Theremin_V3/OTPinDefs.h new file mode 100644 index 0000000..cdd9996 --- /dev/null +++ b/Open_Theremin_V3/OTPinDefs.h @@ -0,0 +1,56 @@ +/** + * \file + * Pin definitions + */ + +#ifndef WavePinDefs_h +#define WavePinDefs_h + +//------------------------------------------------------------------------------ +// DAC pin definitions + +// LDAC may be connected to ground to save a pin +/** Set USE_MCP_DAC_LDAC to 0 if LDAC is grounded. */ +#define USE_MCP_DAC_LDAC 1 + +// use arduino pins 2, 3, 4, 5 for DAC + +// pin 2 is DAC chip select + +/** Data direction register for DAC chip select. */ +#define MCP_DAC_CS_DDR DDRB +#define MCP_DAC2_CS_DDR DDRB +/** Port register for DAC chip select. */ +#define MCP_DAC_CS_PORT PORTB +/** Port bit number for DAC chip select. */ +#define MCP_DAC_CS_BIT 2 +#define MCP_DAC2_CS_BIT 1 + +// pin 3 is DAC serial clock +/** Data direction register for DAC clock. */ +#define MCP_DAC_SCK_DDR DDRB +/** Port register for DAC clock. */ +#define MCP_DAC_SCK_PORT PORTB +/** Port bit number for DAC clock. */ +#define MCP_DAC_SCK_BIT 5 + +// pin 4 is DAC serial data in + +/** Data direction register for DAC serial in. */ +#define MCP_DAC_SDI_DDR DDRB +/** Port register for DAC clock. */ +#define MCP_DAC_SDI_PORT PORTB +/** Port bit number for DAC clock. */ +#define MCP_DAC_SDI_BIT 3 + +// pin 5 is LDAC if used +#if USE_MCP_DAC_LDAC +/** Data direction register for Latch DAC Input. */ +#define MCP_DAC_LDAC_DDR DDRD +/** Port register for Latch DAC Input. */ +#define MCP_DAC_LDAC_PORT PORTD +/** Port bit number for Latch DAC Input. */ +#define MCP_DAC_LDAC_BIT 7 +#endif // USE_MCP_DAC_LDAC + +#endif // WavePinDefs_h diff --git a/Open_Theremin_V3/SPImcpDAC.h b/Open_Theremin_V3/SPImcpDAC.h deleted file mode 100644 index 57ab867..0000000 --- a/Open_Theremin_V3/SPImcpDAC.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Control the mcp 4921/4922 DACs with hardware SPI of the Arduino UNO - * ...without all the overhead of the Arduino SPI lib... - * Just the needed functions in a runtime optimized way by "Theremingenieur" Thierry Frenkel - * This file is free software: you can redistribute it and/or - * modify it under the terms of the GNU General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - */ - -#ifndef SPImcpDac_h -#define SPImcpDac_h - -#include - -// Data direction & Port register & Bit number for DAC Latch: -#define MCP_DAC_LDAC_DDR DDRD -#define MCP_DAC_LDAC_PORT PORTD -#define MCP_DAC_LDAC_BIT 7 -// Data direction & Port register & Bit number for DAC CS -#define MCP_DAC_CS_DDR DDRB -#define MCP_DAC_CS_PORT PORTB -#define MCP_DAC_CS_BIT 2 -// Data direction & Port register & Bit number for DAC2 CS -#define MCP_DAC2_CS_DDR DDRB -#define MCP_DAC2_CS_PORT PORTB -#define MCP_DAC2_CS_BIT 1 -// Data direction & Port registers & Bit numbers for Hardware SPI -#define HW_SPI_DDR DDRB -#define HW_SPI_SCK_BIT 5 -#define HW_SPI_MISO_BIT 4 // unused in this configuration -#define HW_SPI_MOSI_BIT 3 - -static inline void SPImcpDACinit() -{ - // initialize the latch pin: - MCP_DAC_LDAC_DDR |= _BV(MCP_DAC_LDAC_BIT); - MCP_DAC_LDAC_PORT |= _BV(MCP_DAC_LDAC_BIT); - // initialize the CS pins: - MCP_DAC_CS_DDR |= _BV(MCP_DAC_CS_BIT); - MCP_DAC_CS_PORT |= _BV(MCP_DAC_CS_BIT); - MCP_DAC2_CS_DDR |= _BV(MCP_DAC2_CS_BIT); - MCP_DAC2_CS_PORT |= _BV(MCP_DAC2_CS_BIT); - // initialize the hardware SPI pins: - HW_SPI_DDR |= _BV(HW_SPI_SCK_BIT); - 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 -} - -static inline void SPImcpDACtransmit(uint16_t data) -{ - // Send highbyte and wait for complete - SPDR = highByte(data); - while (!(SPSR && _BV(SPIF))) - ; - // Send lowbyte and wait for complete - SPDR = lowByte(data); - while (!(SPSR && _BV(SPIF))) - ; -} - -static inline void SPImcpDAClatch() -{ - MCP_DAC_LDAC_PORT &= ~_BV(MCP_DAC_LDAC_BIT); - MCP_DAC_LDAC_PORT |= _BV(MCP_DAC_LDAC_BIT); -} - -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; - 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 -} - -static inline void SPImcpDAC2Asend(uint16_t data) -{ - MCP_DAC2_CS_PORT &= ~_BV(MCP_DAC2_CS_BIT); - // Sanitize input data and add DAC config MSBs - data &= 0x0FFF; - data |= 0x7000; - SPImcpDACtransmit(data); - MCP_DAC2_CS_PORT |= _BV(MCP_DAC2_CS_BIT); - SPImcpDAClatch(); -} - -static inline void SPImcpDAC2Bsend(uint16_t data) -{ - MCP_DAC2_CS_PORT &= ~_BV(MCP_DAC2_CS_BIT); - // Sanitize input data and add DAC config MSBs - data &= 0x0FFF; - data |= 0xF000; - SPImcpDACtransmit(data); - MCP_DAC2_CS_PORT |= _BV(MCP_DAC2_CS_BIT); - SPImcpDAClatch(); -} - -#endif diff --git a/Open_Theremin_V3/application.cpp b/Open_Theremin_V3/application.cpp index c0c3c3f..80dc893 100644 --- a/Open_Theremin_V3/application.cpp +++ b/Open_Theremin_V3/application.cpp @@ -3,7 +3,7 @@ #include "application.h" #include "hw.h" -#include "SPImcpDAC.h" +#include "mcpDac.h" #include "ihandlers.h" #include "timer.h" #include "EEPROM.h" @@ -42,13 +42,13 @@ void Application::setup() { digitalWrite(Application::LED_PIN_1, HIGH); // turn the LED off by making the voltage LOW - SPImcpDACinit(); + mcpDacInit(); EEPROM.get(0,pitchDAC); EEPROM.get(2,volumeDAC); -SPImcpDAC2Asend(pitchDAC); -SPImcpDAC2Bsend(volumeDAC); +mcpDac2ASend(pitchDAC); +mcpDac2BSend(volumeDAC); initialiseTimer(); @@ -327,7 +327,7 @@ static long pitchfn = 0; InitialisePitchMeasurement(); interrupts(); - SPImcpDACinit(); + mcpDacInit(); qMeasurement = GetQMeasurement(); // Measure Arudino clock frequency Serial.print("Arudino Freq: "); @@ -344,13 +344,13 @@ Serial.print("\nPitch Set Frequency: "); Serial.println(pitchfn); -SPImcpDAC2Bsend(1600); +mcpDac2BSend(1600); -SPImcpDAC2Asend(pitchXn0); +mcpDac2ASend(pitchXn0); delay(100); pitchfn0 = GetPitchMeasurement(); -SPImcpDAC2Asend(pitchXn1); +mcpDac2ASend(pitchXn1); delay(100); pitchfn1 = GetPitchMeasurement(); @@ -362,11 +362,11 @@ Serial.println(pitchfn1); while(abs(pitchfn0-pitchfn1)>CalibrationTolerance){ // max allowed pitch frequency offset -SPImcpDAC2Asend(pitchXn0); +mcpDac2ASend(pitchXn0); delay(100); pitchfn0 = GetPitchMeasurement()-pitchfn; -SPImcpDAC2Asend(pitchXn1); +mcpDac2ASend(pitchXn1); delay(100); pitchfn1 = GetPitchMeasurement()-pitchfn; @@ -411,7 +411,7 @@ static long volumefn = 0; InitialiseVolumeMeasurement(); interrupts(); - SPImcpDACinit(); + mcpDacInit(); volumeXn0 = 0; @@ -424,12 +424,12 @@ Serial.print("\nVolume Set Frequency: "); Serial.println(volumefn); -SPImcpDAC2Bsend(volumeXn0); +mcpDac2BSend(volumeXn0); delay_NOP(44316);//44316=100ms volumefn0 = GetVolumeMeasurement(); -SPImcpDAC2Bsend(volumeXn1); +mcpDac2BSend(volumeXn1); delay_NOP(44316);//44316=100ms volumefn1 = GetVolumeMeasurement(); @@ -443,11 +443,11 @@ Serial.println(volumefn1); while(abs(volumefn0-volumefn1)>CalibrationTolerance){ -SPImcpDAC2Bsend(volumeXn0); +mcpDac2BSend(volumeXn0); delay_NOP(44316);//44316=100ms volumefn0 = GetVolumeMeasurement()-volumefn; -SPImcpDAC2Bsend(volumeXn1); +mcpDac2BSend(volumeXn1); delay_NOP(44316);//44316=100ms volumefn1 = GetVolumeMeasurement()-volumefn; @@ -474,7 +474,7 @@ EEPROM.put(2,volumeXn0); HW_LED2_OFF; HW_LED1_ON; - Serial.println("\nCALIBRATION COMPLETED\n"); + Serial.println("\nCALIBRATION COMPTLETED\n"); } void Application::hzToAddVal(float hz) { @@ -512,3 +512,7 @@ void Application::delay_NOP(unsigned long time) { __asm__ __volatile__ ("nop"); } } + + + + diff --git a/Open_Theremin_V3/ihandlers.cpp b/Open_Theremin_V3/ihandlers.cpp index 4da4830..8025fa8 100644 --- a/Open_Theremin_V3/ihandlers.cpp +++ b/Open_Theremin_V3/ihandlers.cpp @@ -1,9 +1,8 @@ #include "Arduino.h" #include "ihandlers.h" -#include "SPImcpDAC.h" +#include "mcpDac.h" #include "timer.h" -#include "hw.h" #include "build.h" #include "theremin_sintable.c" @@ -32,7 +31,7 @@ static const uint32_t MCP_DAC_BASE = 2047; #define PC_STATE (PINB & (1<> 8); + mcpDacSend(scaledSample); //Send result to Digital to Analogue Converter (audio out) (9.6 us) - SPImcpDACsend(scaledSample); //Send result to Digital to Analogue Converter (audio out) (6 us) - - - pointer = pointer + vPointerIncrement; // increment table pointer (ca. 2us) + pointer = pointer + vPointerIncrement; // increment table pointer (ca. 2us) #endif //CV play sound incrementTimer(); // update 32us timer @@ -192,8 +187,10 @@ ISR (INT1_vect) { noInterrupts(); enableInt1(); -#ifdef TH_DEBUG - HW_LED2_OFF; + + // Added by ThF 20200419 + #ifdef TH_DEBUG + HW_LED2_OFF; #endif } diff --git a/Open_Theremin_V3/mcpDac.h b/Open_Theremin_V3/mcpDac.h new file mode 100644 index 0000000..ddbb1ce --- /dev/null +++ b/Open_Theremin_V3/mcpDac.h @@ -0,0 +1,151 @@ +/* Arduino WaveHC Library + * Copyright (C) 2009 by William Greiman + * + * This file is part of the Arduino WaveHC Library + * + * This Library is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Arduino WaveHC Library. If not, see + * . + */ +/** + * Macros and inline functions for MCP4921 DAC + */ +#ifndef mcpDac_h +#define mcpDac_h + +#include +#include "OTPinDefs.h" + + +//------------------------------------------------------------------------------ +#define mcpDacCsLow() MCP_DAC_CS_PORT &= ~_BV(MCP_DAC_CS_BIT) +#define mcpDacCsHigh() MCP_DAC_CS_PORT |= _BV(MCP_DAC_CS_BIT) + +#define mcpDac2CsLow() MCP_DAC_CS_PORT &= ~_BV(MCP_DAC2_CS_BIT) +#define mcpDac2CsHigh() MCP_DAC_CS_PORT |= _BV(MCP_DAC2_CS_BIT) + +#define mcpDacSckLow() MCP_DAC_SCK_PORT &= ~_BV(MCP_DAC_SCK_BIT) +#define mcpDacSckHigh() MCP_DAC_SCK_PORT |= _BV(MCP_DAC_SCK_BIT) +#define mcpDacSckPulse() {mcpDacSckHigh();mcpDacSckLow();} + +#define mcpDacSdiLow() MCP_DAC_SDI_PORT &= ~_BV(MCP_DAC_SDI_BIT) +#define mcpDacSdiHigh() MCP_DAC_SDI_PORT |= _BV(MCP_DAC_SDI_BIT) +#define mcpDacSdiSet(v) if(v){mcpDacSdiHigh();}else{mcpDacSdiLow();} + +// send bit b of d +#define mcpDacSendBit(d, b) {mcpDacSdiSet(d&_BV(b));mcpDacSckPulse();} + +//------------------------------------------------------------------------------ +// init dac I/O ports +inline void mcpDacInit(void) { + // set all to output mode + MCP_DAC_CS_DDR |= _BV(MCP_DAC_CS_BIT); + MCP_DAC2_CS_DDR |= _BV(MCP_DAC2_CS_BIT); + + MCP_DAC_SCK_DDR |= _BV(MCP_DAC_SCK_BIT); + MCP_DAC_SDI_DDR |= _BV(MCP_DAC_SDI_BIT); + // chip select high + mcpDacCsHigh(); + mcpDac2CsHigh(); + +#if USE_MCP_DAC_LDAC + // LDAC low always - use unbuffered mode + MCP_DAC_LDAC_DDR |= _BV(MCP_DAC_LDAC_BIT); + MCP_DAC_LDAC_PORT &= ~_BV(MCP_DAC_LDAC_BIT); +#endif // USE_MCP_DAC_LDAC +} +//------------------------------------------------------------------------------ +// send 12 bits to dac +// trusted compiler to optimize and it does +// csLow to csHigh takes 8 - 9 usec on a 16 MHz Arduino +inline void mcpDacSend(uint16_t data) { + mcpDacCsLow(); + // send DAC config bits + mcpDacSdiLow(); + mcpDacSckPulse(); // DAC A + mcpDacSdiHigh(); + mcpDacSckPulse(); // buffered REF + + mcpDacSckPulse(); // 1X gain + mcpDacSckPulse(); // no SHDN + // send 12 data bits + mcpDacSendBit(data, 11); + mcpDacSendBit(data, 10); + mcpDacSendBit(data, 9); + mcpDacSendBit(data, 8); + mcpDacSendBit(data, 7); + mcpDacSendBit(data, 6); + mcpDacSendBit(data, 5); + mcpDacSendBit(data, 4); + mcpDacSendBit(data, 3); + mcpDacSendBit(data, 2); + mcpDacSendBit(data, 1); + mcpDacSendBit(data, 0); + mcpDacCsHigh(); +} + +inline void mcpDac2ASend(uint16_t data) { + mcpDac2CsLow(); + // send DAC config bits + mcpDacSdiLow(); + mcpDacSckPulse(); // DAC A + mcpDacSdiHigh(); + mcpDacSckPulse(); // buffered REF + + mcpDacSckPulse(); // 1X gain + mcpDacSckPulse(); // no SHDN + // send 12 data bits + mcpDacSendBit(data, 11); + mcpDacSendBit(data, 10); + mcpDacSendBit(data, 9); + mcpDacSendBit(data, 8); + mcpDacSendBit(data, 7); + mcpDacSendBit(data, 6); + mcpDacSendBit(data, 5); + mcpDacSendBit(data, 4); + mcpDacSendBit(data, 3); + mcpDacSendBit(data, 2); + mcpDacSendBit(data, 1); + mcpDacSendBit(data, 0); + mcpDac2CsHigh(); +} + +inline void mcpDac2BSend(uint16_t data) { + mcpDac2CsLow(); + // send DAC config bits + mcpDacSdiHigh(); + mcpDacSckPulse(); // DAC A + mcpDacSdiHigh(); + mcpDacSckPulse(); // buffered REF + + mcpDacSckPulse(); // 1X gain + mcpDacSckPulse(); // no SHDN + // send 12 data bits + mcpDacSendBit(data, 11); + mcpDacSendBit(data, 10); + mcpDacSendBit(data, 9); + mcpDacSendBit(data, 8); + mcpDacSendBit(data, 7); + mcpDacSendBit(data, 6); + mcpDacSendBit(data, 5); + mcpDacSendBit(data, 4); + mcpDacSendBit(data, 3); + mcpDacSendBit(data, 2); + mcpDacSendBit(data, 1); + mcpDacSendBit(data, 0); + mcpDac2CsHigh(); +} + + + +#endif //mcpDac_h