parent
ad0c37b16e
commit
250bd4dc21
@ -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 |
Loading…
Reference in new issue