Dave,
Thanks I see that now. How do you keep track of instruction bits?
Tom
I'm not sure I understand the question but the S field of an instructionis bits 8:0 and the D field is bits 17:9. The MOVS instruction will store the low order 9 bits of the source into bits 8:0 of the destination and MOVD will store the low order 9 bits of the source into bits 17:9 of the destination. Adding $200 to an instruction increments the D field since $200 is a constant with only bit 9 set which is the low order bit of the D field. After modifying an instruction, you must execute at least one other instruction before you can execute the modified instruction.
I'm thinking that the easiest way to make this work more generally is to modify the pasm to store ClockDelay and ClockState.
At the beginning of the pasm it tests for nonzero command.
So right after the "if_z jmp #loop" I would add the following.
mov t7, t1 '' move 'command' to new variable t7
mov t8, t1 '' make a copy
and t7, #$40000 wz '' C program defines command 4 <<16 for start up
If_nz jmp #startup
Put startup at end of current code (but before 'done').
startup mov t7, t8 '' make t7 whole
and t7 , #1 " first bit of command is Clockstate
mov ClockState, t7
mov t7, t8
shr t7, #2 " C packed ClockDelay in command by shifting ClockDelay << 2
and t7, #$FF
mov ClockDelay, t7
wrlong zero, par ''set command back to zero
jmp #loop
define after arg4 the following
t7 long 0
t8 long 0
In the C program, in the start function, after starting the cog, but before the return I would add the following
This isn't the same PASM code but you could do something like this:
dat
org 0
ws2812 jmp #ws2812_cont
resettix long 0 ' frame reset timing
bit0hi long 0 ' bit0 high timing
bit0lo long 0 ' bit0 low timing
bit1hi long 0 ' bit1 high timing
bit1lo long 0 ' bit1 low timing
ws2812_cont mov t1, par ' get the pin number
rdlong t2, t1
mov txmask, #1 ' create mask for tx
shl txmask, t2
andn outa, txmask ' set to output low
or dira, txmask
add t1, #4
rdlong hubpntr, t1 ' get the buffer address
add t1, #4
rdlong ledcount, t1 ' get the led count
mov t2, #0 ' init is done
wrlong t2, t1
You then access the fields of the PASM code using a structure like this:
Dave,
I had already modified the spin file's pasm and once I fixed a couple of things, (like trying to use $40000 as an immediate), I tried it and it did work. I am thinking about trying to write a version, and would use your suggestion.
It is very fast getting 14+ blocks of Pixy data per frame, which is much faster than the spin or simpleIDE library versions.
My next step in this exercise is to put all of the spi constants (MSPRE, etc.) into the program. (The pixy only used MSPRE which = 2 in the original spin program), and the separate the parts into a library.
The revised C program and pasm are listed below, and the spin file is attached.
/* spipasm 3 - a fast spin interface library project
Updated to use pasm to set ClockDelay and ClockState
Use pasm modified from SPI_Asm.spin propeller tool library object.
T Montemarano (with a lot of help)
NOTES:
Uses spin file xSPIAsm.spin,
This version does run correctly.
The SPI device called in main() is a Pixy CMUCAM5. It does not required a start command
since it always transmits data at 1usec.
It should be possible to change main to use other spi devices
like the DS1620 used in the spi spin demo.
This version uses the same calls as the SPI_Asm.spin library object.
device->command is either 0 or packed with 2 or 3 numbers to be used by pasm.
command = 0 -- pasm in idle loop
in spipasm_start, the number 4 is shifted left 16 bits to indicate 'startup'
the ClockDelay value is shifted left 2 bits
the ClockState value is in bit 0. All 3 values are or'd.
in spipasm_SHIFTIN the number 2 is shifted left 16 bits, this is or'd with the address of the Dpin
in spipasm_SHIFTOUT, the number 1 is shifted left 16 bits, and or'd with the address of the Dpin
*/
#include "simpletools.h" // Library includes
typedef struct spipasm_struct // Structure contains varaibles
{ // for cogs to share + cog & stack
volatile int command;
int Dpin;
int Cpin;
volatile int Mode;
volatile int Bits;
volatile int Value;
volatile int Flag;
int cog; // Remembers cog for spiasm_stop
} spia_t; // Data type for struct
int pixydata[400];
int clkst = 0; // 0 = start clock low, 1 = start clock high
int clkdly = 15; // ClockDelay, actual clock delay = 300ns + (clkdly-1) * 50ns
// clkdly = 15 gives clock delay = 1 usec
// function prototypes
spia_t *spipasm_start(int clkdly, int clkst);
void spipasm_stop(spia_t *device);
void spipasm_SHIFTOUT(spia_t *device,
int DQ, int CLK, int MD, int BIT, int VLU);
int spipasm_SHIFTIN(spia_t *device,int DQ, int CLK, int MD, int BIT);
void spipasm_setcommand(spia_t *device, int cmd, int *argptr);
/*
libblinkpasm.c
Test harness for the spipasm library.
*/
// #include "spipasm.h"
spia_t *spia;
int main() // Main function
{
int px;
// Put demo code here
spia = spipasm_start(clkdly, clkst); // Launch, get handles
int i = 1;
while(i<398) // fill pixydata array with spi bytes
{
// Pixy SPI interface continuously transmits data (no starting or stopping it)
// Pixy data out rate is 1usec
// Pixy SPI data out -> Prop P0, Pixy Clock -> Prop P2
// spipasm_shiftin(Dpin, Cpin, Mode, Bits)
pixydata[i] = spipasm_SHIFTIN(spia, 0, 2, 0, 8); // Mode 0 = MSBPRE
i++;
}
i = 1;
while(i<398) // write pixydata array
{
// printi(" i = %d color = %x\n", i, pixydata[i]);
printi("%d\n", pixydata[i]);
i++;
}
spipasm_stop(spia);
}
// These are the actual functions
// ****************************************
spia_t *spipasm_start(int clkd, int clks)
{
spia_t *device; // Declare spipasm pointer
device = (void *) malloc(sizeof(spia_t)); // Allocate memory for it
if(device->cog == 0)
{
device->command = 0; // pasm stays in waiting loop till non zero
extern int binary_xSPIAsm_dat_start[];
device->cog = 1 + cognew((void*)binary_xSPIAsm_dat_start, (void*)device);
}
device->command = (4 << 16) | (clkd << 2) | clks ; // pasm reads command, sets ClockDelay, ClockState
while(device->command); // wait till pasm resets command to zero
return device; // Return pointer to structure
}
// ************************************
void spipasm_stop(spia_t *device)
{
if(device->cog > 0) // If cog running
{
cogstop(device->cog - 1); // Shut down cog
device->cog = 0; // Clear cog varaible
free(device); // Release allocated memory
}
}
// ************************************
void spipasm_SHIFTOUT(spia_t *device, int DQ, int CLK, int MD, int BIT, int VLU)
{
device->Dpin = DQ; // load variable values for pasm
device->Cpin = CLK;
device->Mode = MD;
device->Bits = BIT;
device->Value = VLU;
spipasm_setcommand(spia,1, &device->Dpin);
}
// ************************************
int spipasm_SHIFTIN(spia_t *device,
int DQ, int CLK, int MD, int BIT)
{
device->Dpin = DQ;
device->Cpin = CLK;
device->Mode = MD;
device->Bits = BIT;
device->Flag = 1;
spipasm_setcommand(spia, 2, &device->Dpin);
while(device->Flag); // pasm sets Flag =0 when finished reading all bits in Value
return device->Value;
}
// ************************************
void spipasm_setcommand(spia_t *device, int cmd, int *argptr)
{
device->command = (int) argptr | (cmd << 16);
while(device->command);
}
DAT org
'
'' SPI Engine - main loop
'
loop rdlong t1,par wz ''wait for command
if_z jmp #loop
mov t7, t1 '' command to t7
mov t8, t7 '' copy command
and t7, stconst wz '' test for startup
if_nz jmp #startup
movd :arg,#arg0 ''get 5 arguments ; arg0 to arg4
mov t2,t1 '' │
mov t3,#5 ''───┘
:arg rdlong arg0,t2
add :arg,d0
add t2,#4
djnz t3,#:arg
mov address,t1 ''preserve address location for passing
''variables back to Spin language.
wrlong zero,par ''zero command to signify command received
ror t1,#16+2 ''lookup command address
add t1,#jumps
movs :table,t1
rol t1,#2
shl t1,#3
:table mov t2,0
shr t2,t1
and t2,#$FF
jmp t2 ''jump to command
jumps byte 0 ''0
byte SHIFTOUT_ ''1
byte SHIFTIN_ ''2
byte NotUsed_ ''3
NotUsed_ jmp #loop
'################################################################################################################
'tested OK
SHIFTOUT_ ''SHIFTOUT Entry
mov t4, arg3 wz '' Load number of data bits
if_z jmp #Done '' '0' number of Bits = Done
mov t1, #1 wz '' Configure DataPin
shl t1, arg0
muxz outa, t1 '' PreSet DataPin LOW
muxnz dira, t1 '' Set DataPin to an OUTPUT
mov t2, #1 wz '' Configure ClockPin
shl t2, arg1 '' Set Mask
test ClockState, #1 wc '' Determine Starting State
if_nc muxz outa, t2 '' PreSet ClockPin LOW
if_c muxnz outa, t2 '' PreSet ClockPin HIGH
muxnz dira, t2 '' Set ClockPin to an OUTPUT
sub _LSBFIRST, arg2 wz,nr '' Detect LSBFIRST mode for SHIFTOUT
if_z jmp #LSBFIRST_
sub _MSBFIRST, arg2 wz,nr '' Detect MSBFIRST mode for SHIFTOUT
if_z jmp #MSBFIRST_
jmp #loop '' Go wait for next command
'------------------------------------------------------------------------------------------------------------------------------
SHIFTIN_ ''SHIFTIN Entry
mov t4, arg3 wz '' Load number of data bits
if_z jmp #Done '' '0' number of Bits = Done
mov t1, #1 wz '' Configure DataPin
shl t1, arg0
muxz dira, t1 '' Set DataPin to an INPUT
mov t2, #1 wz '' Configure ClockPin
shl t2, arg1 '' Set Mask
test ClockState, #1 wc '' Determine Starting State
if_nc muxz outa, t2 '' PreSet ClockPin LOW
if_c muxnz outa, t2 '' PreSet ClockPin HIGH
muxnz dira, t2 '' Set ClockPin to an OUTPUT
sub _MSBPRE, arg2 wz,nr '' Detect MSBPRE mode for SHIFTIN
if_z jmp #MSBPRE_
sub _LSBPRE, arg2 wz,nr '' Detect LSBPRE mode for SHIFTIN
if_z jmp #LSBPRE_
sub _MSBPOST, arg2 wz,nr '' Detect MSBPOST mode for SHIFTIN
if_z jmp #MSBPOST_
sub _LSBPOST, arg2 wz,nr '' Detect LSBPOST mode for SHIFTIN
if_z jmp #LSBPOST_
jmp #loop '' Go wait for next command
'------------------------------------------------------------------------------------------------------------------------------
MSBPRE_ '' Receive Data MSBPRE
MSBPRE_Sin test t1, ina wc '' Read Data Bit into 'C' flag
rcl t3, #1 '' rotate "C" flag into return value
call #PreClock '' Send clock pulse
djnz t4, #MSBPRE_Sin '' Decrement t4 ; jump if not Zero
jmp #Update_SHIFTIN '' Pass received data to SHIFTIN receive variable
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
LSBPRE_ '' Receive Data LSBPRE
add t4, #1
LSBPRE_Sin test t1, ina wc '' Read Data Bit into 'C' flag
rcr t3, #1 '' rotate "C" flag into return value
call #PreClock '' Send clock pulse
djnz t4, #LSBPRE_Sin '' Decrement t4 ; jump if not Zero
mov t4, #32 '' For LSB shift data right 32 - #Bits when done
sub t4, arg3
shr t3, t4
jmp #Update_SHIFTIN '' Pass received data to SHIFTIN receive variable
'------------------------------------------------------------------------------------------------------------------------------
MSBPOST_ '' Receive Data MSBPOST
MSBPOST_Sin call #PostClock '' Send clock pulse
test t1, ina wc '' Read Data Bit into 'C' flag
rcl t3, #1 '' rotate "C" flag into return value
djnz t4, #MSBPOST_Sin '' Decrement t4 ; jump if not Zero
jmp #Update_SHIFTIN '' Pass received data to SHIFTIN receive variable
'------------------------------------------------------------------------------------------------------------------------------
LSBPOST_ '' Receive Data LSBPOST
add t4, #1
LSBPOST_Sin call #PostClock '' Send clock pulse
test t1, ina wc '' Read Data Bit into 'C' flag
rcr t3, #1 '' rotate "C" flag into return value
djnz t4, #LSBPOST_Sin '' Decrement t4 ; jump if not Zero
mov t4, #32 '' For LSB shift data right 32 - #Bits when done
sub t4, arg3
shr t3, t4
jmp #Update_SHIFTIN '' Pass received data to SHIFTIN receive variable
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
LSBFIRST_ '' Send Data LSBFIRST
mov t3, arg4 '' Load t3 with DataValue
LSB_Sout test t3, #1 wc '' Test LSB of DataValue
muxc outa, t1 '' Set DataBit HIGH or LOW
shr t3, #1 '' Prepare for next DataBit
call #PostClock '' Send clock pulse
djnz t4, #LSB_Sout '' Decrement t4 ; jump if not Zero
mov t3, #0 wz '' Force DataBit LOW
muxnz outa, t1
jmp #loop '' Go wait for next command
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
MSBFIRST_ '' Send Data MSBFIRST
mov t3, arg4 '' Load t3 with DataValue
mov t5, #%1 '' Create MSB mask ; load t5 with "1"
shl t5, arg3 '' Shift "1" N number of bits to the left.
shr t5, #1 '' Shifting the number of bits left actually puts
'' us one more place to the left than we want. To
'' compensate we'll shift one position right.
MSB_Sout test t3, t5 wc '' Test MSB of DataValue
muxc outa, t1 '' Set DataBit HIGH or LOW
shr t5, #1 '' Prepare for next DataBit
call #PostClock '' Send clock pulse
djnz t4, #MSB_Sout '' Decrement t4 ; jump if not Zero
mov t3, #0 wz '' Force DataBit LOW
muxnz outa, t1
jmp #loop '' Go wait for next command
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
Update_SHIFTIN
mov t1, address '' Write data back to Arg4
add t1, #16 '' Arg0 = #0 ; Arg1 = #4 ; Arg2 = #8 ; Arg3 = #12 ; Arg4 = #16
wrlong t3, t1
add t1, #4 '' Point t1 to Flag ... Arg4 + #4
wrlong zero, t1 '' Clear Flag ... indicates SHIFTIN data is ready
jmp #loop '' Go wait for next command
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
PreClock
mov t2, #0 nr '' Clock Pin
test t2, ina wz '' Read ClockPin
muxz outa, t2 '' Set ClockPin to opposite of read value
call #ClkDly
muxnz outa, t2 '' Restore ClockPin to original read value
call #ClkDly
PreClock_ret ret '' return
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
PostClock
mov t2, #0 nr '' Clock Pin
test t2, ina wz '' Read ClockPin
call #ClkDly
muxz outa, t2 '' Set ClockPin to opposite of read value
call #ClkDly
muxnz outa, t2 '' Restore ClockPin to original read value
PostClock_ret ret '' return
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
ClkDly
mov t6, ClockDelay
ClkPause djnz t6, #ClkPause
ClkDly_ret ret
'------------------------------------------------------------------------------------------------------------------------------
'tested OK
startup mov t7, t8 '' t7 = command
and t7, #1 '' clockstate in bit 0
mov ClockState, t7
mov t7, t8
shr t7, #2 '' clockdelay was stored lsb bit 2
and t7, #$FF
mov ClockDelay, t7
wrlong zero, par '' zero command
jmp #loop
' --------------------------------------------------
Done '' Shut COG down
mov t2, #0 '' Preset temp variable to Zero
mov t1, par '' Read the address of the first perimeter
add t1, #4 '' Add offset for the second perimeter ; The 'Flag' variable
wrlong t2, t1 '' Reset the 'Flag' variable to Zero
CogID t1 '' Read CogID
COGSTOP t1 '' Stop this Cog!
'------------------------------------------------------------------------------------------------------------------------------
{
########################### Assembly variables ###########################
}
zero long 0 ''constants
d0 long $200
_MSBPRE long $0 '' Applies to SHIFTIN
_LSBPRE long $1 '' Applies to SHIFTIN
_MSBPOST long $2 '' Applies to SHIFTIN
_LSBPOST long $3 '' Applies to SHIFTIN
_LSBFIRST long $4 '' Applies to SHIFTOUT
_MSBFIRST long $5 '' Applies to SHIFTOUT
ClockDelay long 0
ClockState long 0
''temp variables
t1 long 0 '' Used for DataPin mask and COG shutdown
t2 long 0 '' Used for CLockPin mask and COG shutdown
t3 long 0 '' Used to hold DataValue SHIFTIN/SHIFTOUT
t4 long 0 '' Used to hold # of Bits
t5 long 0 '' Used for temporary data mask
t6 long 0 '' Used for Clock Delay
address long 0 '' Used to hold return address of first Argument passed
t7 long 0
t8 long 0
stconst long $40000
arg0 long 0 ''arguments passed to/from high-level Spin
arg1 long 0
arg2 long 0
arg3 long 0
arg4 long 0
I've completed the code and compile (Make Project Library) part of making an SPI library that uses modified PASM from the Spin Library object SPI_Asm.spin. I still have to do the documentation and clean up (add the MIT license info).
I originally got the library working to receive data from the CMUCAM5 pixy.
The pixy does not require any SHIFTOUTs from the prop, so it is just a matter of shifting in the data as fast as possible. (and the library functions are very fast).
But I also wanted to make the library more general. I just bought the DS1620 digital thermometer that was used in the spin demo, and that is the "test harness" in the library folder. That does require sending commands to the SPI device to configure it and to get the data. I did find that I had to add some pauses between sending commands and setting the "RESET" pin to low that were not in the spin program.
Until I get the documentation done, to run the demo (libspiasm.c) use the same connections for the DS1620 as are in the SPI_Spin_demo.spin file that comes with the Prop Tool. The pin numbers are also in the c file.
I haven't had a chance to add new devices to the SPI library, but I noticed that the library attached to the previous post contained a buggy version of xSPIAsm.spin, and that it did not include my program for the MMA7455 3 axis accelerometer. So I have attached the updated library below.
It contains:
- the SPI library code and header -- spiasm.c and spiasm.h (#INCLUDE spiasm.h in the main program)
- the ASM code in -- xSPIAsm.spin (this file has to be added to each SimpleIDE Project that calls the SPI functions. This version has the MSBFIRST_ code correction.)
- the program for the DS1600 digital thermometer chip -- libspiasm.c (it was the "test harness for the library, and I need to change the name to be more descriptive).
- the program for reading the MMA7455 3 axis accelerometer -- mma7455-spi.c
- the documentation for the library
- supporting files.
I hope to find time to write the code (convert from SPIN sources) for the SCP1000 pressure sensor module. That one will be interesting since it uses one pin for Rx and one for Tx, and seems a bit more complex (different). But I haven't had a lot of quiet time lately.
I've made a function version of the MPC3208 code where main() is a demo calling the function "get3208se(channel_number)" Use Run with Terminal.
/* 3208-spi-function.c MPC3208 ADC interface using spiasm library
Function version with main() as demo
Uses pasm in xspiasm.spin, modified from SPI_Asm.spin propeller tool library object.
T Montemarano (MIT License)
The SPI device called in main() is a MPC3208 ADC.
Used wiring from Programming & Customizing the Multicore Propeller Microcontroller
page 158, but using MPC3208 ADC instead of MPC3204. (16 pin vs 14 pin device).
Note there are different device pin definitions.
*/
#include "simpletools.h" // Library includes
#include "spiasm.h"
/* ******************************************************
Uses MPC3208 ADC as SPI device
MPC3208 pin Prop pin
CS <- Prop P2 low starts transfer, high terminates
DATA in/out <-> Prop P1 Prop out (MFIRST), Prop in (MPOST)
Clock <- Prop P0 rise then fall State = 0
*/
#define cstate 0 // 0 = start clock low, 1 = start clock high
#define clockd_ns 1000 // Actual delay in nanoseconds (1000ns = 1 usec), not less than 300ns
// ClockDelay, actual clock delay = 300ns + (cdelay-1) * 50ns
// e.g. cdelay of 15 gives actual clock delay = 1 usec
// cdelay = ((clockd_ns) - 250ns)) / 50ns
// e.g. for 2 usec (i.e. 2000 ns): cdelay = 35
// ** Propeller pins
#define CS 2
#define IOPIN 1
#define CLKPIN 0
#define VREF 5 // for 5 volt Vdd and Vref For lower Vdd voltage may have to set clock_ns slower
#define MAXCHAN 3 // max channel number 0 to 7 (ch 0 & 1 = pots, 2 = 3.3v buss, 3 = Vss)
int get3208se(int chnum); // function prototype for single ended 3208 read
spia_t *spia;
int main() // Main function
{
int i;
int adcraw;
int voltsin;
high(CS); // disable 3208 data transfer
spia = spi_start(clockd_ns, cstate); // Launch, get handles, set ClockDelay & ClockState
while(1) // bb
{
for(i = 0; i <= MAXCHAN; i++) // aa
{
int adcraw = get3208se(i); // read channel i
// data handling & printout
voltsin = (adcraw * VREF * 1000) / 4095;
printi("Channel %d: raw = %d, %d.%d volts\n", i, adcraw, (voltsin/1000), voltsin - (voltsin/1000) *1000);
pause(10);
} // end aa
printi("\n");
pause(800);
} // end bb
} // end main
int get3208se(int chnum)
{
// ** declare 3208 Command values here - start bit, mode
int startbit = 0b10000;
int mode_se = 0b01000;
// channel number = 0 to 7 in chnum
// ** end of command values
int cmd3208 = 0;
int rawval = 0;
high(CS);
pause(5);
cmd3208 = (startbit | mode_se | chnum) & 0b11111; // build 5 bit 3208 command
low(CS); // activate 3208 ADC
pause(1);
spi_out(spia, IOPIN, CLKPIN, MFIRST, 5, cmd3208); // start conversion hi, mode, channel(3bits)
spi_out(spia, IOPIN, CLKPIN, MFIRST, 1, 0); // send don't care bit
rawval = spi_in(spia, IOPIN, CLKPIN, MPOST, 13); // read null & 12 bit value
pause(5);
high(CS); // release 3208
return rawval;
}
I’ve made significant changes to the LIBSPIASM library.
Note that programs that used the libraries in the LIBSPIASM.ZIP file of post 67 will NOT work with the new version.
Originally, I trasferred parameters like pin numbers to the functions using Globals. (Note in the post above that the main 3208 program gets the data into adcraw by:
int adcraw = get3208se(i); // read channel i
The only parameter directly passed in the function call is the ADC channel number.
But then I realized that one of the purposes of an SPI bus is to attach a number of devices and select each one using its chip select protocol. And sometimes there will be a number of the same type of devices (for example DS1620 digital thermometers) connected to the bus. Passing parameters using globals won’t work.
To enable the use of multiple devices, it was necessary to pass all the needed parameters to the library function in the call to the function.
For example the code above becomes:
int adcraw = get_3208se(spia_1, IOPIN3208, CLKPIN3208, CS3208, i); // read channel i
The parameters needed and the returned values are listed in the library documentation.
Note that a number of the same or different types of devices can be used with only one call to the "start" function. The advantage of doing that is that only one extra cog is used. (Each call to "start" starts a new cog.) One limitation is that all the devices used with that "start" (spia_t variable) need to have the same timing characteristics (clock delay timing and clock state).
In addition I changed the names of the functions to be in accordance with the guidelines in the Simple Libraries Tutorial.
libspiasm v2.zip contains the library and documentation. It should be unzipped into a Learn Simple libraries folder
(for example: SimpleIDE\Learn\Simple Libraries\My Libraries\libspiasm)
There is a documentation file and the libraries:
libspiasm – the test harness for the library, and used to build libraries for new devices
libSPI-DS1620.c -- for DS1620 digital thermometer
libSPI-MCP3208.c -- for MCP 3208, 8 channel 12 bit ADC used in SE mode
libSPI-MMA7455.c -- for MMA7455 accelerometer – just basic for reading the 3 axes
libSPI-SCP1000.c -- for SCP1000 absolute pressure sensor
The basic library functions (spi_start, spi_stop, spi_out, and spi_in) were not changed and can be called directly rather than using the device functions for other devices or for using the advanced features of the devices.
The other zip is a group of 6 simple demo programs that use the libraries.
They include:
the MCP3208,
the DS1620,
the MCP3208 and DS1620 using the same cog (only 1 call to “start”) and different I/O pins
the MCP3208 and DS1620 using common I/O pins with separate Chip Select pins
the MMA7455 accelerometer
the SCP1000 absolute pressure sensor.
When you load the demos into SimpleIDE, if it doesn't build, you may need to use the project command to add the library.
Since this is a learning experience for me, I'd appreciate any comments.
I am not sure if the SCP1000 code works. I get one reading from the sensor, but the as I change the height of the sensor, the pressure reading stays the same.
Comments
At the beginning of the pasm it tests for nonzero command.
So right after the "if_z jmp #loop" I would add the following. Put startup at end of current code (but before 'done'). define after arg4 the following In the C program, in the start function, after starting the cog, but before the return I would add the following and all of the needed declarations.
Sorry for the poor spacing, but I'm doing this on a tablet.
Comment please.
Thanks
Tom
I had already modified the spin file's pasm and once I fixed a couple of things, (like trying to use $40000 as an immediate), I tried it and it did work. I am thinking about trying to write a version, and would use your suggestion.
It is very fast getting 14+ blocks of Pixy data per frame, which is much faster than the spin or simpleIDE library versions.
My next step in this exercise is to put all of the spi constants (MSPRE, etc.) into the program. (The pixy only used MSPRE which = 2 in the original spin program), and the separate the parts into a library.
The revised C program and pasm are listed below, and the spin file is attached.
xSPIAsm - Archive [Date 2014.09.28 Time 15.46].zip
I originally got the library working to receive data from the CMUCAM5 pixy.
The pixy does not require any SHIFTOUTs from the prop, so it is just a matter of shifting in the data as fast as possible. (and the library functions are very fast).
But I also wanted to make the library more general. I just bought the DS1620 digital thermometer that was used in the spin demo, and that is the "test harness" in the library folder. That does require sending commands to the SPI device to configure it and to get the data. I did find that I had to add some pauses between sending commands and setting the "RESET" pin to low that were not in the spin program.
Until I get the documentation done, to run the demo (libspiasm.c) use the same connections for the DS1620 as are in the SPI_Spin_demo.spin file that comes with the Prop Tool. The pin numbers are also in the c file.
The zipped library is attached.
Tom
It contains:
- the SPI library code and header -- spiasm.c and spiasm.h (#INCLUDE spiasm.h in the main program)
- the ASM code in -- xSPIAsm.spin (this file has to be added to each SimpleIDE Project that calls the SPI functions. This version has the MSBFIRST_ code correction.)
- the program for the DS1600 digital thermometer chip -- libspiasm.c (it was the "test harness for the library, and I need to change the name to be more descriptive).
- the program for reading the MMA7455 3 axis accelerometer -- mma7455-spi.c
- the documentation for the library
- supporting files.
I hope to find time to write the code (convert from SPIN sources) for the SCP1000 pressure sensor module. That one will be interesting since it uses one pin for Rx and one for Tx, and seems a bit more complex (different). But I haven't had a lot of quiet time lately.
Tom
libspiasm.zip
Tom
Note that programs that used the libraries in the LIBSPIASM.ZIP file of post 67 will NOT work with the new version.
Originally, I trasferred parameters like pin numbers to the functions using Globals. (Note in the post above that the main 3208 program gets the data into adcraw by:
The only parameter directly passed in the function call is the ADC channel number.
But then I realized that one of the purposes of an SPI bus is to attach a number of devices and select each one using its chip select protocol. And sometimes there will be a number of the same type of devices (for example DS1620 digital thermometers) connected to the bus. Passing parameters using globals won’t work.
To enable the use of multiple devices, it was necessary to pass all the needed parameters to the library function in the call to the function.
For example the code above becomes:
The parameters needed and the returned values are listed in the library documentation.
Note that a number of the same or different types of devices can be used with only one call to the "start" function. The advantage of doing that is that only one extra cog is used. (Each call to "start" starts a new cog.) One limitation is that all the devices used with that "start" (spia_t variable) need to have the same timing characteristics (clock delay timing and clock state).
In addition I changed the names of the functions to be in accordance with the guidelines in the Simple Libraries Tutorial.
I have attached 2 zips.
demo-spi lib functions.zip
libspiasm v2.zip
libspiasm v2.zip contains the library and documentation. It should be unzipped into a Learn Simple libraries folder
(for example: SimpleIDE\Learn\Simple Libraries\My Libraries\libspiasm)
There is a documentation file and the libraries:
libspiasm – the test harness for the library, and used to build libraries for new devices
libSPI-DS1620.c -- for DS1620 digital thermometer
libSPI-MCP3208.c -- for MCP 3208, 8 channel 12 bit ADC used in SE mode
libSPI-MMA7455.c -- for MMA7455 accelerometer – just basic for reading the 3 axes
libSPI-SCP1000.c -- for SCP1000 absolute pressure sensor
The basic library functions (spi_start, spi_stop, spi_out, and spi_in) were not changed and can be called directly rather than using the device functions for other devices or for using the advanced features of the devices.
The other zip is a group of 6 simple demo programs that use the libraries.
They include:
the MCP3208,
the DS1620,
the MCP3208 and DS1620 using the same cog (only 1 call to “start”) and different I/O pins
the MCP3208 and DS1620 using common I/O pins with separate Chip Select pins
the MMA7455 accelerometer
the SCP1000 absolute pressure sensor.
When you load the demos into SimpleIDE, if it doesn't build, you may need to use the project command to add the library.
Since this is a learning experience for me, I'd appreciate any comments.
Tom
Tom