temp-fan-control/gertboard_sw/gb_spi.c

137 lines
4.2 KiB
C

//
// Gertboard test
//
// SPI (ADC/DAC) control code
//
// This code is part of the Gertboard test suite
// These routines access the AD and DA chips
//
//
// Copyright (C) Gert Jan van Loo & Myra VanInwegen 2012
// No rights reserved
// You may treat this program as if it was in the public domain
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
// Try to strike a balance between keep code simple for
// novice programmers but still have reasonable quality code
//
#include "gb_common.h"
#include "gb_spi.h"
//
// Set-up the SPI interface
//
// Speed depends on what you talk to
// In this case use 1MHz
//
void setup_spi()
{
// Want to have 1 MHz SPI clock.
// Assume 250 Mhz system clock
// So divide 250MHz system clock by 250 to get 1MHz45
SPI0_CLKSPEED = 250;
// clear FIFOs and all status bits
SPI0_CNTLSTAT = SPI0_CS_CLRALL;
SPI0_CNTLSTAT = SPI0_CS_DONE; // make sure done bit is cleared
} // setup_spi()
//
// Read a value from one of the two ADC channels
//
// To understand this code you had better read the
// datasheet of the AD chip (MCP3002)
//
int read_adc(int chan) // 'chan' must be 0 or 1. This is not checked!
{ unsigned char v1,v2,rec_c;
int status,w;
// Set up for single ended, MS comes out first
v1 = 0xD0 | (chan<<5);
// Delay to make sure chip select is high for a short while
short_wait();
// Enable SPI interface: Use CS 0 and set activate bit
SPI0_CNTLSTAT = SPI0_CS_CHIPSEL0|SPI0_CS_ACTIVATE;
// Write the command into the FIFO so it will
// be transmitted out of the SPI interface to the ADC
// We need a 16-bit transfer so we send a command byte
// folowed by a dummy byte
SPI0_FIFO = v1;
SPI0_FIFO = 0; // dummy
// wait for SPI to be ready
// This will take about 16 micro seconds
do {
status = SPI0_CNTLSTAT;
} while ((status & SPI0_CS_DONE)==0);
SPI0_CNTLSTAT = SPI0_CS_DONE; // clear the done bit
// Data from the ADC chip should now be in the receiver
// read the received data
v1 = SPI0_FIFO;
v2 = SPI0_FIFO;
// Combine the 8-bit and 2 bit values into an 10-bit integer
// NOT!!! return ((v1<<8)|v2)&0x3FF;
// I have checked the result and it returns 3 bits in the MS byte not 2!!
// So I might have my SPI clock/data pahse wrong.
// For now its easier to dadpt the results (running out of time)
return ( (v1<<7) | (v2>>1) ) & 0x3FF;
} // read_adc
//
// Write 12 bit value to DAC channel 0 or 1
//
// To understand this code you had better read the
// datasheet of the AD chip (MCP4802/MCP4812/MCP4822)
//
void write_dac(int chan, // chan must be 0 or 1, this is not checked
int val) // chan must be max 12 bit
{ char v1,v2,dummy;
int status;
val &= 0xFFF; // force value in 12 bits
// Build the first byte: write, channel 0 or 1 bit
// and the 4 most significant data bits
v1 = 0x30 | (chan<<7) | (val>>8);
// Remain the Least Significant 8 data bits
v2 = val & 0xFF;
// Delay to have CS high for a short while
short_wait();
// Enable SPI: Use CS 1 and set activate bit
SPI0_CNTLSTAT = SPI0_CS_CHIPSEL1|SPI0_CS_ACTIVATE;
// send the values
SPI0_FIFO = v1;
SPI0_FIFO = v2;
// wait for SPI to be ready
// This will take about 16 micro seconds
do {
status = SPI0_CNTLSTAT;
} while ((status & SPI0_CS_DONE)==0);
SPI0_CNTLSTAT = SPI0_CS_DONE; // clear the done bit
// For every transmit there is also data coming back
// We MUST read that received data from the FIFO
// even if we do not use it!
dummy = SPI0_FIFO;
dummy = SPI0_FIFO;
} // write_dac