Skip to content

Commit

Permalink
Added MCP3208 object.
Browse files Browse the repository at this point in the history
  • Loading branch information
srlm-io committed Jul 18, 2013
1 parent 73d388f commit d9e13e0
Show file tree
Hide file tree
Showing 11 changed files with 399 additions and 6 deletions.
6 changes: 3 additions & 3 deletions propgcc/fullduplexserial/full_duplex_serial.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef libpropeller_full_duplex_serial__
#define libpropeller_full_duplex_serial__
#ifndef libpropeller_full_duplex_serial_h_
#define libpropeller_full_duplex_serial_h_


//Warning: To change the buffer size you must change it here and in the .S file
Expand Down Expand Up @@ -99,4 +99,4 @@ class FullDuplexSerial {
int CheckBuffer(void);
};

#endif // libpropeller_full_duplex_serial__
#endif // libpropeller_full_duplex_serial_h_
8 changes: 5 additions & 3 deletions propgcc/gccutilities/boards/board_unit_tester.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#ifndef __LIBPROPELLER_BOARD_H__
#define __LIBPROPELLER_BOARD_H__
#ifndef libpropeller_board_h_
#define libpropeller_board_h_

namespace Board{

Expand All @@ -11,6 +11,8 @@ namespace Board{
const int kPinMCP3208Select = 4;

const int kPinSqw = 5;

const int kPinDac = 6;

const int kPinSDDo = 10;
const int kPinSDClk = 11;
Expand All @@ -29,4 +31,4 @@ namespace Board{
const int kPinUsbRx = 31;
}

#endif // __LIBPROPELLER_BOARD_H__
#endif // libpropeller_board_h_
1 change: 1 addition & 0 deletions propgcc/mcp3208/Makefile
1 change: 1 addition & 0 deletions propgcc/mcp3208/board_unit_tester.h
Binary file added propgcc/mcp3208/main.elf
Binary file not shown.
130 changes: 130 additions & 0 deletions propgcc/mcp3208/mcp3208.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
.section .mcp3208.cog, "ax"
.global MCP3208_Entry
.compress off

MCP3208_Entry
..start
.org 0
mov T1, PAR // Read parameters

call #Param // Setup DIN/DOUT pin
mov Dmask, T2

call #Param // Setup CLK pin
mov Cmask, T2

call #Param // Setup CS Pin
mov Smask, T2

call #Param // Set mode
mov Enables, T3

call #Param // Setup DAC configuration
if_c or DIRA, T2
if_c movs CTRA, T3
if_c movi CTRA, #0b00110000

shr T3, #8
call #Param2
if_c or DIRA, T2
if_c movs CTRB, T3
if_c movi CTRB, #0b0011000


//
//
// Perform Conversions Continuously
//
or DIRA, Cmask // Output CLK
or DIRA, Smask // Output CS

Main_loop
mov Command, #$10 // Init command
mov T1, PAR // Reset sample pointer
mov T2, Enables // Get enables
mov T3, #8 // Ready 8 channels

Cloop
shr T2, #1 wc // If channel disabled, skip
if_nc jmp #Skip

test T2, #$80 wc // Channel enabled, get single/diff mode
muxnc Command, #8
mov Stream, Command

or OUTA, Smask // CS high
or DIRA, Dmask // make DIN/DOUT output
mov Bits, #20 // ready 20 bits (cs+1+diff+ch[3]+0+0+data[12])

Bloop
test Stream, #$20 wc // update DIN/DOUT
muxc OUTA, Dmask

cmp Bits, #$e wz // if command done, input DIN/DOUT
if_z andn DIRA, Dmask

andn OUTA, Cmask // CLK low
mov T4, PAR // update DACs between clock transitions
add T4, #$14
rdlong FRQA, T4
add T4, #4
rdlong FRQB, T4
or OUTA, Cmask // CLK high

test Dmask, INA wc // Sample DIN/DOUT
rcl Stream, #1

andn OUTA, Smask // CS Low

djnz Bits, #Bloop // Next data bit


and Stream, Mask12 // Trim and write sample
wrword Stream, T1

Skip
add T1, #2 // Advance sample pointer
add Command, #1 // Advance command
djnz T3, #Cloop // more channels?

wrlong Counter, T1 // Channels done, update counter
add Counter, #1

jmp #Main_loop // perform conversions again


//
//
// Get parameter
//
Param
rdlong T3, T1 // Get parameter into T3
add T1, #4 // Point to next parameter

Param2
mov T2, #1 // Make pin mask in T2
shl T2, T3

test T3, #$80 wc // Get DAC flag into c

Param2_ret
Param_ret
ret


Dlsb .long (1 << 9)
Mask12 .long $fff
T1 .res 1
T2 .res 1
T3 .res 1
T4 .res 1
Dmask .res 1
Cmask .res 1
Smask .res 1
Enables .res 1
Command .res 1
Stream .res 1
Bits .res 1
Counter .res 1

.compress default
79 changes: 79 additions & 0 deletions propgcc/mcp3208/mcp3208.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include <propeller.h>
#include "mcp3208.h"

extern char _load_start_mcp3208_cog[];

void MCP3208::Start(const int dataPin, const int clockPin,
const int selectPin, const int mode, const int Xpin, const int Ypin) {

if (Xpin == -1 && Ypin == -1) {
//No DACs
Startx(dataPin, clockPin, selectPin, mode, 0);
} else if (Xpin != -1 && Ypin == -1) {
//One DAC
Startx(dataPin, clockPin, selectPin, mode, (Xpin & 0x1f) | 0x80);
} else {
//Two DACs
Startx(dataPin, clockPin, selectPin, mode,
(((Ypin & 0x1f) | 0x80) << 8) + ((Xpin & 0x1f) | 0x80));
}
}

void MCP3208::Startx(const int dataPin, const int clockPin,
const int selectPin, const int mode, const int Dacmode) {

volatile void * asm_reference = NULL;
__asm__ volatile ("mov %[asm_reference], #MCP3208_Entry\n\t"
: [asm_reference] "+r" (asm_reference));

Stop();

Ins[0] = dataPin;
Ins[1] = clockPin;
Ins[2] = selectPin;
Ins[3] = mode;

Count = Dacmode;

Cog = cognew(_load_start_mcp3208_cog, Ins) + 1;
}

void MCP3208::Stop(void) {
if (Cog) {
cogstop(Cog - 1);
Cog = 0;
}
}

int MCP3208::In(const int channel) {

// Get pull the 16 bit word out of the 32 byte word.
int result = Ins[channel / 2];

// If index is odd then pull the upper word, if even pull the lower word.
result = channel & 0x1 ? result >> 16 : result;

// Make sure that we get just what we are interested in.
return result & 0xFFFF;
}

int MCP3208::Average(const int channel, const int sampleCount) {
//TODO(SRLM): What is C and Count?
int sampleTotal = 0;
int C = Count;
for (int i = 0; i < sampleCount; i++) {
while (C == Count) {
}
sampleTotal += In(channel);
C++;

}

return sampleTotal / sampleCount;
}

void MCP3208::Out(const short X, const short Y) {
Dacx = X << 16;
Dacy = Y << 16;
}

84 changes: 84 additions & 0 deletions propgcc/mcp3208/mcp3208.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#ifndef libpropeller_mcp3208_h_
#define libpropeller_mcp3208_h_

/** MCP3208 8 channel ADC Class.
*
* When the MCP3208 is configured for 3.3v operation each bit represents 0.00080566406v.
*
* The MCP3208 requires three connections to the Propeller: clock, chip select,
* and data (tie together Dout and Din).
*
* This object optionally provides two DACs as well. To enable these you need to
* have one or two Propeller I/O pins available. Each DAC I/O pin needs to have
* a low pass RC filter. I reccommend R = 1k and C = 0.1uF. With this
* configuration you should avoid changing the DAC more than once a millisecond
* (the cut off frequency is 1591Hz).
*
* This driver does continuous sampling in the background.
*
* This object is based on MCP3208.spin v1.0 written by Chip Gracey. Thanks!
*
* @author srlm (srlm@srlmproductions.com)
*/

class MCP3208 {
public:
/** Start the ADC driver in a new cog.
*
* Be sure to give the driver sufficient time to start up.
*
* @param dataPin The data in and data out pins on the MCP3208
* @param clockPin The clock pin on the MCP3208
* @param selectPin The select pin on the MCP3208
* @param Mode Channel enables in bits [0..7], differential mode enable in
* bits [8..15]. Most applications should set this to 0xFF
* @param dacAPin If desired, the pin number for a DAC (see discussion above)
* @param dacBPin If desired, the pin number for a DAC (see discussion above)
*/
void Start(const int dataPin, const int clockPin,
const int selectPin, const int Mode = 0xFF,
const int dacAPin = -1, const int dacBPin = -1);


/** Stop the driver and free a cog.
*/
void Stop(void);

/** Read a channel input.
*
* @param Channel The channel [0..7] to read
* @return The ADC reading in the range [0..4096]
*/
int In(const int Channel);

/** Sample a channel n times and average the results.
*
* This function is useful for reducing noisy readings.
*
* @param Channel The channel [0..7] to read
* @param N The number of samples to average
*/
int Average(const int Channel, const int N);


/** Output analog values (if enabled during Start)
*
* The range is 0 (ground) to 65535 (3.3v) for the output.
*
* @param aOutput The output value for channel a
* @param bOutput The output value for channel b
*/
void Out(const short aOutput, const short bOutput = -1);
private:
int Cog;

//Warning: do not rearrange these variables. The assembly relies on the order.
int volatile Ins[4];
int volatile Count;
int volatile Dacx, Dacy;

void Startx(const int dataPin, const int clockPin,
const int selectPin, const int mode, const int Dacmode);
};

#endif // libpropeller_mcp3208_h_
Loading

0 comments on commit d9e13e0

Please sign in to comment.