Merge pull request #21 from MrDham/OpenTh-V3.1-Changes
Merge changes from Open Theremin V3 - Version 3.1 + Pitch Bend Range choice extension up to 4 ocatves.pull/23/head V2.3
commit
c69fc962eb
Before Width: | Height: | Size: 587 KiB After Width: | Height: | Size: 601 KiB |
@ -1,56 +0,0 @@ |
||||
/**
|
||||
* \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
|
@ -0,0 +1,104 @@ |
||||
/* 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 <Arduino.h> |
||||
|
||||
// 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 = _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); |
||||
asm("nop"); |
||||
while (!(SPSR & _BV(SPIF))) |
||||
; |
||||
// Send lowbyte and wait for complete
|
||||
SPDR = lowByte(data); |
||||
asm("nop"); |
||||
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 very 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 |
@ -1,151 +0,0 @@ |
||||
/* 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 |
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
/**
|
||||
* Macros and inline functions for MCP4921 DAC |
||||
*/
|
||||
#ifndef mcpDac_h |
||||
#define mcpDac_h |
||||
|
||||
#include <avr/io.h> |
||||
#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
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.6 MiB |
@ -1,22 +0,0 @@ |
||||
## Open.Theremin V3 control software |
||||
|
||||
Arduino UNO Software for the Open.Theremin |
||||
|
||||
### Don't click on the files! |
||||
Click on the "Download ZIP" Button to the right or [Click here](https://github.com/GaudiLabs/OpenTheremin_V3/archive/master.zip) |
||||
Then unpack the archive. |
||||
|
||||
### Open Source Theremin based on the Arduino Platform |
||||
|
||||
Open.Theremin is an arduino shield to build the legendary music instrument invented by Leon Theremin back in 1920. The theremin is played with two antennas, one to control the pitch and one for volume. The electronic shield with two ports to connect those antennas comprises two heterodyne oscillators to measure the distance of the hand to the antenna when playing the instrument. The resulting signal is fed into the arduino. After linearization and filtering the arduino generates the instruments sound that is then played through a high quality digital analog audio converter on the board. The characteristics of the sound can be determined by a wave table on the arduino. |
||||
|
||||
For more info on the open source project and on availability of ready made shield see: |
||||
|
||||
http://www.gaudi.ch/OpenTheremin/ |
||||
|
||||
### Installation |
||||
1. Open up the Arduino IDE |
||||
2. Open the File "Open_Theremin_V3.ino" |
||||
3. Selecting the correct usb port on Tools -> Serial Port |
||||
4. Select the correct arduino board from Tools -> Board |
||||
5. Upload the code by clicking on the upload button. |
Loading…
Reference in new issue