You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.2 KiB
105 lines
3.2 KiB
5 years ago
|
/* 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
|