read_bit mov temp, ina 'read in what is in all the input lines
andn temp, inputmask wz 'mask off except Dout line. Set Z flag
shl Dat_red, #1 'roll right 1 bit to get ready for next bit
if_nz add Dat_red, #1 'if value positive add 1 to data register
call #Tog_Clk 'toggle clock to get next bit ready in Dout
sub count, #1 wz 'decrement the "bits read" counter. Set Z flag
if_nz jmp #read_bit 'go up and do it again if counter not 0
wrlong dat_red, par 'put it in PAR to share it as P.Val
call #Chip_Sel_Hi 'Put chip to sleep by del selecting it
jmp #generate 'go back to do it all again
Read_Bit mov longTmp, ina ' Read all input pin status, and store in longTmp
andn longTmp, mask26 wz ' Mask off all pins except Dout pin, and set Z flag
'' SHL (Shift Left) shifts Value left by Bits places and sets the new LSBs to 0.
'' If the WZ effect is specified, the Z flag is set (1) if the resulting Value equals zero.
'' If the WC effect is specified, the C flag is set equal to Values original bit 31. The
'' result is written to Value unless the NR effect is specified.
' %00000000_00000000_00000000_00000000
shl readData, #1 ' %00000000_00000000_00000000_0000000
if_nz add readData, #1 ' if Z clear, add 1 to readData.
call #Toggle_Clk
sub index, #1 wz
if_nz jmp #Read_Bit
mov parMem, par
wrlong readData, parMem
call #CS_Hi
jmp #Generate
' ASM_Book_ReadPot.SPIN
CON
_CLKMODE = XTAL1 + PLL16X
_XINFREQ = 5_000_000
' -------------------------------------------------------------------------------
VAR
long PVal
' -----------------------------------------------------------------------------------
OBJ
fds : "FullDuplexSerial"
' ------------------------------------------------------------------------------------
PUB
fds.start(31,30,0,115200)
cognew(@generate, @PVal)
repeat
fds.bin(P_Val, 12)
fds.tx($d)
fds.dec(P_Val)
fds.tx(" ")
fds.tx($1)
waitcnt(clkfreq / 60 + cnt)
' -----------------------------------------------------------------------------------
DAT
'' DATA IN is always read from the device
'' on the RISING EDGE of the clock.
'' DATA OUT is always read from the device
'' on the FALLING EDGE of the clock.
org 0 ' Starting point.
Generate mov dira, SetDira ' Set Direction.
'' Initiating communication with MCP3208
'' is done by bringing the CS line low.
'' If the device was powered up with the
'' CS pin low, it must be brought high
'' and back low to initiate communication.
'' The first clock received with CS low
'' and DIN high will constitute a START
'' BIT.
call #CS_Low ' Chip select, pull low.
call #Clk_Low ' In order to start, Clk must be set low.
call #Din_Hi ' In order to start, Data In must be set high.
call #Toggle_Clk ' In order for the mcp3208 to read data from the Propeller
' the, we need to toggle the clock to high and back to configure Start Bit.
' The first Toggle_clk recieved with CS_low & Din_hi will constitute
' the first START_BIT.
'' START_BIT Declared
call #Din_Hi ' Din_hi sets the single or differential mode of the data configuration,
' when set Hi the MCP3208 is set to read from 8 single ended inputs.
call #Toggle_clk ' Toggle clk from low to high and back to low to configure Data In.
'' SINGLE_END Declared
call #Din_low ' Din_low sets data configuration bit D2
' CH 0 input configuration on D2-D0 is %000
call #Toggle_Clk ' Toggle clk from low to high and back to low to configure Data In.
call #Din_Low ' Din_low sets data configuration bit D1
call #Toggle_Clk ' Toggle clk from low to high and back to low to configure Data In.
call #Din_Low ' Din_low sets data configuration bit D0
call #Toggle_Clk ' Toggle clk from low to high and back to low to configure Data In.
'' FOURTH_RISING_CLOCK
'' SAMPLE_PERIOD_BEGINS
'' The MCP3208 will begin to sample the analog
'' input on the fourth rising edge of the clock
'' after the start bit has been received.
'' Once the D0 bit is input, one more clock is required to
'' complete the sample and hold period (DIN is a dont
'' care for this clock).
'' The sample period will end on the falling
'' edge of the fifth clock following the start
'' bit.
call #Toggle_Clk ' Sample period ends
'' On the falling edge of the next clock, the MCP3208 will
'' output a low null bit.
'' The MCP3208 must shift from recieving instruction as the clock
'' rises, to supplying data on the falling edge of the clock. In
'' order to do so, it takes 1 1/2 clock cycles to make the change.
call #Toggle_Clk ' Triggers the first output as the Null Bit.
mov readData, #0 ' No real data from the MCP3208, so clear the file location. Mainly applies to the 2nd data
' read, and every data read afterwards.
mov index, #12 ' Creates an index that counts down after each Clock Cycle. (it was count)
'' The next 12 clocks will output the result of the conversion
'' with MSB first.
'' Data is always output from the device on the falling edge
'' of the clock.
'' If all 12 data bits have been transmitted and the device
'' continues to receive clocks while the CS is held low, the
'' device will output the conversion result LSB first.
'' If more clocks are provided to the MCP3208
'' while CS is still low (after the LSB first data has been
'' transmitted), the device will clock out zeros indefinitely.
Read_Bit mov longTmp, ina ' Read all input pin status, and store in longTmp
andn longTmp, mask26 wz ' Mask off all pins except Dout pin, and set Z flag
'' SHL (Shift Left) shifts Value left by Bits places and sets the new LSBs to 0.
'' If the WZ effect is specified, the Z flag is set (1) if the resulting Value equals zero.
'' If the WC effect is specified, the C flag is set equal to Values original bit 31. The
'' result is written to Value unless the NR effect is specified.
' %00000000_00000000_00000000_00000000
shl readData, #1 ' %00000000_00000000_00000000_0000000
if_nz add readData, #1 ' if Z clear, add 1 to readData.
call #Toggle_Clk
sub index, #1 wz
if_nz jmp #Read_Bit
mov parMem, par
wrlong readData, parMem
call #CS_Hi
jmp #Generate
'---------- Subroutines ----------------------------------------------------------
Clk_Hi or outa, ClkBit
Clk_Bit_ret ret
'----------------------------------------
Clk_Low andn outa, ClkBit
Clk_Low_ret ret
'-----------------------------------------
Toggle_Clk call #Clk_Hi
call #Clk_Low
Toggle_Clk_ret ret
'-------------------------------------------
Din_Hi or outa, DinBit
Din_Hi_ret ret
'------------------------------------------
Din_Low andn outa, DinBit
Din_Low_ret ret
'------------------------------------------
CS_Hi or outa, CSBit
CS_Hi_ret ret
'---------------------------------------------
CS_Low andn outa, CSBit
CS_Low_ret ret
'--------------------------------------------
Read_Next_Bit mov longTmp, ina
or longTmp, mask26
Read_Next_Bit_ret ret
' ---------- Constants -------------------------------------------------------------
SetDira long %00001011_11000000_00001111_11111111 'Set dira register
CSBit long %00000001_00000000_00000000_00000000 'Chip select bit 24
DinBit long %00000010_00000000_00000000_00000000 'Data in bit 25
DoutBit long %00000100_00000000_00000000_00000000 'Data out bit 26
ClkBit long %00001000_00000000_00000000_00000000 'Clock bit 27
Mask26 long %11111011_11111111_11111111_11111111 'Mask forDout bit only
Pin23 long %00000000_10000000_00000000_00000000 'osc line
Pin22 long %00000000_01000000_00000000_00000000 'Speaker line
' --------- Variables ------------------------------------------------------------
longTmp res 1
index res 1
readData res 1
parMem res 1
' ------------- End of Program ----------------------------------------------------------
Fit
' -------------------- Definitions ----------------------------------------------------------------
' CALL pg. 268
{{-------------------------------------------------------------------------------
PASM_Book_ReadPot.SPIN
Function of program
Makes an electronic Metronome.
Notes: Program reads a potentiometer
See details in book
Program PASM_Book_ReadPot.SPIN
Book PASM for beginners, Propeller 102
Section Outputs
Programmer Harprit Sandhu
Date Jan 10 2013
Revisions: Report errors to harprit.sandhu@gmail.com
--------------------------------------------------------------------------------}}
CON
_clkmode = xtal1 + pll16x 'set clock
_xinfreq = 5_000_000 'crystal freq
VAR
long P_Val 'declare variable
OBJ
fds : "FullDuplexSerial" 'for display to PST
PUB Main
fds.start(31,30,0,115200) 'start console at 115200 for debug output
cognew(@generate, @P_Val) 'start new Cog at "generate" and read variable into P_Val in PASM
repeat 'loop
fds.bin(P_val,12) 'print value to the PST in binary
fds.tx($d) 'new line
fds.dec(P_val) 'print value as decimal
fds.tx(" ") 'space
fds.tx($1) 'home to 0,0
waitcnt(clkfreq/60+cnt) 'flicker free wait
DAT org 0 'sets the starting point in Cog
generate mov dira, set_dira 'sets direction of the prop pins
call #chip_sel_lo 'selects chip by pulling line low
call #Clk_lo 'START. Clock needs to be low to load data
call #Din_hi 'must start with Din high to set up 3208
call #Tog_clk 'clk hi-lo to read data
call #Din_Hi 'SINGLE DIFF mode, will be made Low to load
call #Tog_Clk 'toggle clock line hi low to read data
call #Din_Lo 'D2 Low to load input line sel sequence 000 for line 0
call #Tog_Clk 'toggle clock line hi then low to read in the data
call #Din_Lo 'D1 Low to load input line sel sequence 000 for line 0
call #Tog_Clk 'toggle clock line hi then low to read in the data
call #Din_Lo 'D0 Low to load input line sel sequence 000 for line 0
call #Tog_Clk 'toggle clock line hi low to read in the data
call #Din_Lo 'blank bit needs a clock cycle, next
call #Tog_Clk 'toggle clock line hi then low to read the data
'next toggle is for the null bit, nothing read
call #Tog_Clk 'toggle clock line hi then low to read the data
mov dat_red, #0 'Clear register we will read data into
mov count, #12 'Counter for number of bits we will read
read_bit mov temp, ina 'read in what is in all the input lines
andn temp, mask26 wz 'mask off except Dout line & Set Z flag
shl Dat_red, #1 'shift register left 1 bit ready for next bit
if_nz add Dat_red, #1 'if value is positive add 1 to data register
call #Tog_Clk 'toggle clock to get next bit ready in Dout
sub count, #1 wz 'decrement "bits read" counter. Set Z flag
if_nz jmp #read_bit 'go up and do it again if counter not yet 0
mov mem, par 'get address of par into mem
wrlong dat_red, mem 'write it in HUB to share it as P.Val
call #Chip_Sel_Hi 'Put chip to sleep by de-selecting it
jmp #generate 'go back to do it all again
'Subroutines
Clk_Hi or outa, clk_bit 'OR it with the Clock Bit to make high
Clk_Hi_ret ret 'return from this subroutine
Clk_Lo andn outa , clk_bit 'ANDN it with the Clock Bi to make low
Clk_Lo_ret ret 'return from this subroutine
Tog_Clk call #Clk_hi 'make clock bit high
call #clk_lo 'make clock bit low
Tog_Clk_ret ret 'return from this subroutine
Din_Hi or outa , din_Bit 'Makes the Din high
Din_Hi_ret ret 'return from this subroutine
Din_Lo andn outa , din_Bit 'makes Din low
Din_Lo_ret ret 'return from this subroutine
Chip_Sel_Hi or outa , chs_Bit 'Makes Chip select high
Chip_Sel_Hi_ret ret 'return from this subroutine
Chip_Sel_Lo andn outa, chs_Bit 'makes chip select low
Chip_Sel_Lo_ret ret 'return from this subroutine
Read_Next_Bit mov temp, ina 'Get the INA register
or temp, mask26 'mask all but Din bit
Read_Next_Bit_ret ret 'return from this subroutine
'======================
'Constants. This is similar to the CON block in SPIN but these are not constants
'because they can be changed. These are initial values.
Set_dira long %00001011_11000000_00001111_11111111 'Set dira register
Chs_Bit long %00000001_00000000_00000000_00000000 'Chip select bit 24
Din_Bit long %00000010_00000000_00000000_00000000 'Data in bit 25
Dout_Bit long %00000100_00000000_00000000_00000000 'Data out bit 26
Clk_Bit long %00001000_00000000_00000000_00000000 'Clock bit 27
mask26 long %11111011_11111111_11111111_11111111 'Mask forDout bit only
Pin_23 long %00000000_10000000_00000000_00000000 'osc line
Pin_22 long %00000000_01000000_00000000_00000000 'Speaker line
'============================
'Variables. This section is similar to the VAR block in SPIN.
'These are blank variable space designators
temp res 1 'temporary storage variable, misc
count res 1 'read bit counter
Dat_Red res 1 'data being read
mem res 1 'par location
Fit