Clocking data - the best way to do it?

Grogster

Senior Member
I have to be able to clock 16-bit words into a SOMO sound module using the bit-banging approach. I know what the words are going to be.

Is there a more simple method then just:

Code:
start:
  pulsout 1,200  'Start bit
  high 2  'Put data on data line
  pulsout 1,50  'Clock the module
  high 2  'Put data on data line
  pulsout 1,50  'Clock the module
  low 2  'Put data on data line
  pulsout 1,50  'Clock the module
  .
  .
  .
This is long and memory intensive(although it does work), especially if you need to store several different commands - 34 lines per command(16x 2 lines for every bit + 1x start bit and 1x stop bit) - there must be a more efficent method. Can anyone offer me any alternatives?
 
Last edited:

westaust55

Moderator
Have a look at the code in PICAXE manual 2 under the SHIFTOUT command.

Starts at page 192 and there are bit-bashing examples on page 193.

You could use a word instead of a byte and change the bits value from 8 to 16
 

Grogster

Senior Member
OK, thanks, but still a little confused - where do I load the word I want to send?
I think this must be w6 in the symbols list at the start of shiftin, so do I just plop in the decimal value of the binary word I want to send at that point?

Example:
Say I want to send 65000, do I have a line which says let w6 = 65000(or let var_out = 65000), then gosub the routine?

Assume that symbol bits = 16 and symbol MSBvalue = 65535.

EDIT: Not working - all I get is sdata high all the time with the sclk pulsing away in the background, but there are no lows as their should be. 65000 = 1111110111101000 binary, so there should be some pulses where the data-LED is off. I have two LED's on the two pins - one on the sclk pin, and one on the sdata pin so I can see what is happening, but at no point in the proceedure does the sclk LED pulse while the sdata LED is off, because the sdata LED remains on from fire up until power-down. *sigh* I increased the pulsout time to 5000 to slow things down so I can see what is going on, and so it is not so fast I can't visually follow it.

Enough for tonight - 10 to one in the morning here - need sleep...
 
Last edited:

westaust55

Moderator
OK, thanks, but still a little confused - where do I load the word I want to send?
I think this must be w6 in the symbols list at the start of shiftin, so do I just plop in the decimal value of the binary word I want to send at that point?

Example:
Say I want to send FFFFh, do I have a line which says let w6 = 65535(or let var_out = 65535), then gosub the routine?

Assume that symbol bits = 16 and symbol MSBvalue = 65535.
Yes you are on the right path/track.


Code:
SYMBOL var_out = w6
SYMBOL bits = 16
SYMBOL MSBValue = $8000
var_out = 65535

gosub shiftout_MSBFirst


‘ ***** Shiftout MSB first *****
shiftout_MSBFirst:
for counter = 1 to bits ‘ number of bits
mask = var_out & MSBValue ‘ mask MSB
low sdata ‘ data low
if mask = 0 then skipMSB
high sdata ‘ data high
skipMSB: pulsout sclk,1 ‘ pulse clock for 10us
var_out = var_out * 2 ‘ shift variable left for MSB
next counter
return
 

Grogster

Senior Member
Cheers - will try that shortly and let you know.
I changed the var_out from 65535 to 65000 so there were some low's in the binary word, otherwise the LED would not change if var_out was all 1's. :D
Doing conversion of 8000h is 1000000000000000, which puts the MSB at bit-16, so this is where I was stuffing up last morning ;)
It was very late...
Sleep has recharged my brain a little, but I still need coffee. :D

EDIT1: Not working. I get ONE pulse one the sclk, then sdata stays high and there are no more pulses from sclk. More coffee...

EDIT2: Put a wait 1 before the next x in the gosub, and I can see what is happening now, but the data is inverted - what should be highs are lows and vise-versa. I checked this bit-by-bit, and it is definetly inverted. Sending 65000 decimal, which is 1111110111101000 binary, and the data line shows me 0000001000010111 - 535 decimal. Confused. :confused:

EDIT3: Swapped high sdata for low sdata and vise-versa in the gosub, and the data is almost correct now, but the last 2-bits pulse through as highs(can just visually detect a flash from the sdata LED during the clock pulse) when they should be low. The actual output binary is therefore 1111110111101011 which is 65003 so still not right. The experiment continues...
 
Last edited:

Grogster

Senior Member
I've re-written a routine to do what I want, using DATA/EEPROM statements and the READ command.

Code:
output 1	'Output 1 is the clock line
output 2	'Output 2 is the data line
low 1
low 2

symbol x = b1
symbol bit = b2


stp:
  pulsout 1,2500		'Start bit pulse
  for x = 1 to 16
    read x,bit
    bit = bit - 48
      if bit=1 then high 2
        endif
      if bit=0 then low 2
        endif
  pulsout 1,1000		'Clock the module
  pause 500
  debug bit
  next x
  wait 5
  goto stp
  
data_sub:
data 1,("1111110111101000")	'Command 65000 binary
This works extremely well, and also allows me to keep the binary "Word" within the data statements. This method also does not have the problem of the last 2-bits being high when they should not be. Plus this is easier for me to follow then the other method. :D

This needs a bit more tidying up, but it works beautifully.

If I need more then 15 commands, I will have to use external EEPROM chip, but it might be a good chance for me to play with one of those at the same time...
 
Last edited:

kewakl

Senior Member
If I need more then 15 commands, I will have to use external EEPROM chip, but it might be a good chance for me to play with one of those at the same time...
Could you use TABLE/READTABLE to store some data in PROGRAM MEMORY?
 

westaust55

Moderator
here is a version - added a few more SYMBOL statements to clarify
which does work using the method in manual 2

Code:
SYMBOL var_out = w6
SYMBOL counter = b3
SYMBOL MASK = w5
SYMBOL bits = 16
SYMBOL MSBValue = $8000
SYMBOL sdata = 2
SYMBOL sclk = 3

var_out = $5555

gosub shiftout_MSBFirst


‘ ***** Shiftout MSB first *****
shiftout_MSBFirst:
for counter = 1 to bits ‘ number of bits
mask = var_out & MSBValue ‘ mask MSB
low sdata ‘ data low
if mask = 0 then skipMSB
high sdata ‘ data high
skipMSB: pulsout sclk,1 ‘ pulse clock for 10us
var_out = var_out * 2 ‘ shift variable left for MSB
next counter
return
to use the table memory as suggested by kewakl, this is also available in the X1 PICAXE parts.
 

hippy

Technical Support
Staff member
A note on optimising code ...

if bit=1 then high 2
endif
if bit=0 then low 2
endif

This can be represented as -

If bit = 1 Then
High 2
Else
Low 2
End If

Or -

Low 2
If bit = 1 Then
High 2
End If

And best of all -

outpin2 = bit
 

Grogster

Senior Member
here is a version - added a few more SYMBOL statements to clarify
which does work using the method in manual 2

Code:
SYMBOL var_out = w6
SYMBOL counter = b3
SYMBOL MASK = w5
SYMBOL bits = 16
SYMBOL MSBValue = $8000
SYMBOL sdata = 2
SYMBOL sclk = 3

var_out = $5555

gosub shiftout_MSBFirst


‘ ***** Shiftout MSB first *****
shiftout_MSBFirst:
for counter = 1 to bits ‘ number of bits
mask = var_out & MSBValue ‘ mask MSB
low sdata ‘ data low
if mask = 0 then skipMSB
high sdata ‘ data high
skipMSB: pulsout sclk,1 ‘ pulse clock for 10us
var_out = var_out * 2 ‘ shift variable left for MSB
next counter
return
to use the table memory as suggested by kewakl, this is also available in the X1 PICAXE parts.
THIS WORKS!!! :)

I wonder if I missed something - nah coulden't have, cos I used the example code as suggested by the Picaxe manual(found in the examples folder).

For whatever reason, that did not work, but your code does - it's exactly right, I've tried with a few different numbers and my experiment number of 65000 decimal($FDE8) - probably should have chosen your even easier to remember $5555, as it is just on/off/on/off etc(but the sequence for 65000/FDE8 is now in my brain, so I kept using it!). The last two bits are correct too, not as in my previous attempt.

This time, I did not copy your code, I typed it in letter-by-letter to make 100% sure there were no typo's in it. This is the best method to use if I could get it working, as you have an unlimited number of commands this way - all you need to know is the value you need to send out via the gosub.(preaching to the choir now...)

So, thanks everyone - this has been a nice little experiment for me, and you learn from these kind of things.

Oh, and @ hippy - outpin2=bit is defintely the way to go!!!! :)
(but i won't be using "My" routine now that we have got the original to work.)

I'll stick with the 18X though, as it has lots of program space over any of the other lower chips(18A/14M/08M/08)
 

westaust55

Moderator
Great to see that it is working for you. :)


I am currently going one step further for an 8-bit LCD driver using shift-out techniques and using single bits from byte variable b0 for various flash and control bits. This has the advantage amongst other things that instead of the variable “mask” being an entire byte or as in your case a word variable it is reduced to just a 1 bit value used for testing. I am currently awaiting some 74HC4015 chips for the shift register to test my project (protoboard and code completed last night in readiness).


So, there is an option for you to contemplate if you start running out of variables in your program. . . . start using bit variables for mask, flag and status bits (you can hold 8 such status bits in b0.
 

Grogster

Senior Member
Great to see that it is working for you. :)


I am currently going one step further for an 8-bit LCD driver using shift-out techniques and using single bits from byte variable b0 for various flash and control bits. This has the advantage amongst other things that instead of the variable “mask” being an entire byte or as in your case a word variable it is reduced to just a 1 bit value used for testing. I am currently awaiting some 74HC4015 chips for the shift register to test my project (protoboard and code completed last night in readiness).


So, there is an option for you to contemplate if you start running out of variables in your program. . . . start using bit variables for mask, flag and status bits (you can hold 8 such status bits in b0.
Interesting.
I'm grateful you found the time to help me out at the same time. :)

In my case, it's the SOMO module that you linked me to in the first place that I am tinkering with, so a single word variable is really all I need for all command codes, and swapping the value of the word depending on the command, and then shifting it out via the gosub routine - IE: I can change var_out to whatever I need to tell the module prior to looping to the gosub, and this can be done whenever I need to send something to the module.
 

goom

Senior Member
SOMO-14D Embedded Audio-Sound Module

Has anyone got the SOMO-14D sound module working? I have been playing with one for a while, but have failed to get it to play sounds. Even tried the push-button mode to no avail, so have concluded that the unit is defective, and am seeking a replacement.
The SOMO requires that data be clocked quite slowly (minimum 200us clock pulses), and also needs a longer low clock at start of transmission, and high clock at the end (2ms minimum each). Grogster's code looks like it is much too fast (10us high pulses and no pause for the low clock state).
Here is part of my code, clearly untested (except in the simulator):

Code:
#Picaxe 18X
symbol Pout=20           'Set clock pulse to 200us (at 4MHz)
symbol Pout_start=200    'Set start/stop clock pulse to 2ms (at 4MHz)
symbol Dat=W0            'Data to send to SOMO-14D
 
Dat=$FFFF                '=%1111111111110111, stop SOMO-14D on startup or reset
gosub Send_Data1
Dat=$FFF7                '=%1111111111110111, set volume to max
gosub Send_Data1
Dat=1                    'Play file0001.ad4
gosub Send_Data1
 
Send_Data1:
  low 5
  pulsout 6,Pout_start   'Pause 2ms by pulsing dummy pin (needs >2ms low) start clock level)
  for Temp=1 to 15       'Loop through first 15 bits
    outpin4=bit15        'Set data to MSB
    pulsout 5,Pout       'Clock high for 200us to latch data on pin1
    pulsout 6,Pout       'Pause 200us by pulsing dummy pin (low clock)
    Dat=Dat*2            'Shift left to get next significant bit
  next Temp
  outpin4=bit15          'Set last data bit
  high 5                 'Clock idles high after last bit sent
  pulsout 6,Pout_start   'Pause 2ms by pulsing dummy pin (needs >2ms high) stop clock level)
Return
It does rely on the data being loaded into W0, and the data is not retained for further use.
I was worried about WO overflowing when shifted by multiplying by 2, but it seems to roll over quite happily.
 

westaust55

Moderator
Have a SOMO 14D but I am currently experimenting with a backlit Dick Smith 2x16LCD and an OLED display so the sound module has to wait (along with a 200step /rev stepper motor).

Happy to try and help others in the meantime get their projects to the finish line as well.

From some earlier calcs I did, it did seem that bit bashing would be slow enough. Have not investigated the duration of clock pulses.
Will have another look at the datsheets tonight (if I remember :eek:)
 

Grogster

Senior Member
Has anyone got the SOMO-14D sound module working? I have been playing with one for a while, but have failed to get it to play sounds. Even tried the push-button mode to no avail, so have concluded that the unit is defective, and am seeking a replacement.
The SOMO requires that data be clocked quite slowly (minimum 200us clock pulses), and also needs a longer low clock at start of transmission, and high clock at the end (2ms minimum each). Grogster's code looks like it is much too fast (10us high pulses and no pause for the low clock state).
Here is part of my code, clearly untested (except in the simulator):

Code:
#Picaxe 18X
symbol Pout=20           'Set clock pulse to 200us (at 4MHz)
symbol Pout_start=200    'Set start/stop clock pulse to 2ms (at 4MHz)
symbol Dat=W0            'Data to send to SOMO-14D
 
Dat=$FFFF                '=%1111111111110111, stop SOMO-14D on startup or reset
gosub Send_Data1
Dat=$FFF7                '=%1111111111110111, set volume to max
gosub Send_Data1
Dat=1                    'Play file0001.ad4
gosub Send_Data1
 
Send_Data1:
  low 5
  pulsout 6,Pout_start   'Pause 2ms by pulsing dummy pin (needs >2ms low) start clock level)
  for Temp=1 to 15       'Loop through first 15 bits
    outpin4=bit15        'Set data to MSB
    pulsout 5,Pout       'Clock high for 200us to latch data on pin1
    pulsout 6,Pout       'Pause 200us by pulsing dummy pin (low clock)
    Dat=Dat*2            'Shift left to get next significant bit
  next Temp
  outpin4=bit15          'Set last data bit
  high 5                 'Clock idles high after last bit sent
  pulsout 6,Pout_start   'Pause 2ms by pulsing dummy pin (needs >2ms high) stop clock level)
Return
It does rely on the data being loaded into W0, and the data is not retained for further use.
I was worried about WO overflowing when shifted by multiplying by 2, but it seems to roll over quite happily.
Oh God, goom, don't say that - not after all this... :eek: :(

"My" code made no allowances at all for the data timing, and completely ignores the start and stop bit requirements - it was only to see if I could make it(the main command 16-bit word) work on LED's, but having said that, if it was slow enough to visually see, then it should be way slow enough for the module. I have added the start and stop clocks to my code now, but have yet to connect a SOMO module.

I wanted to get the code right on the LED's before actually connecting up the module.
Did you convert your MP3 or WAV files? - cos it won't play normal WAV or MP3 files without conversion using the utility.(I speculate that you did convert your files)

I too wonder about your module, especially if you can't make it work even in button-mode.

I have four modules, so if the first does not work, I can try another.

Anyhoo, back to tinkering...
 
Last edited:

westaust55

Moderator
Gooms code generally seems right but the SOMO 14D must have the clock idle high.

what happens with this slight variant:

Code:
#Picaxe 18X
symbol Pout=20           'Set clock pulse to 200us (at 4MHz)
symbol Pout_start=200    'Set start/stop clock pulse to 2ms (at 4MHz)
symbol Dat=W0            'Data to send to SOMO-14D
 
Dat=$FFFF                '=%1111111111110111, stop SOMO-14D on startup or reset
gosub Send_Data1
Dat=$FFF7                '=%1111111111110111, set volume to max
gosub Send_Data1
Dat=1                    'Play file0001.ad4
gosub Send_Data1
 
Send_Data1:
  high 5   ; clock to idle high
  pulsout 5,Pout_start   'Pause 2ms by pulsing dummy pin (needs >2ms low) start clock level)
  pulsout 6,Pout_start  
for Temp=1 to 15       'Loop through first 15 bits
    outpin4=bit15        'Set data to MSB
    pulsout 5,Pout       'Clock high for 200us to latch data on pin1
    pulsout 6,Pout       'Pause 200us by pulsing dummy pin (low clock)
    Dat=Dat*2            'Shift left to get next significant bit
  next Temp
  outpin4=bit15          'Set last data bit
  pulsout 6,Pout_start   'Pause 2ms by pulsing dummy pin (needs >2ms high) stop clock level)
Return
 

Grogster

Senior Member
Instead of pulsing the dummy pin, can't you just:

Code:
start:
  high 5  'Set clock idle-high
  .
  .
  .
  low 5  'Set clock low - get ready for data!
  pause 2
  gosub shiftout
  .
  .
  .
...or is there some specific reason for pulsing a dummy pin?

The pause command might not be as accurate as the pulsout command perhaps, but surely it would be near enough - you just need long enough for the module to prepare for the data.
 
Last edited:

westaust55

Moderator
yes, a pause would work as well.
20usec (and 200usec) are minimum intervals. No reason why they cannot be a little higher.
 

goom

Senior Member
yes, a pause would work as well.
20usec (and 200usec) are minimum intervals. No reason why they cannot be a little higher.
Yes, I suspect that slower is quite acceptable. I just wanted to keep the data transmission time to a minimum for my particular application, and pause for 20uS is not possible.

Regarding idling high, I'm not sure that it really matters what the clock state is between data transmissions, as long as the 200us low start state and high stop state are respected. I avoided setting the clock high at startup in case this was interpreted as clocking the first bit. After the first data transmission, my code leaves the clock high until between transmissions. Westuas55's suggested modification leaves the clock low between transmissions.

If only I had a working unit I could just "suck it and see". Will have to wait a week or so until I get a replacement. 4DSystems agreed to ship a new one. I'll start a new thread once I have something up and running.
C'mon Grogster, connect your unit up to the PICAXE. The suspense is killing me. Don't forget that 5V will probably kill the SOMO-14D, so use one of the suggested power supply options, and the resistors on the inputs. If you study the timing diagram in the manual for an hour or two (as I did), then you will see that it is important to keep clock pulses quite slow.

Yes, I did convert sound files from .wav to .ad4, and even tried different sampling rates. I also downloaded some .ad4 files from 4D systems, just to be sure.
 

Grogster

Senior Member
C'mon Grogster, connect your unit up to the PICAXE. The suspense is killing me. Don't forget that 5V will probably kill the SOMO-14D, so use one of the suggested power supply options, and the resistors on the inputs. If you study the timing diagram in the manual for an hour or two (as I did), then you will see that it is important to keep clock pulses quite slow.
PLEASE do post back either on this thread, or one of your own - I am in suspense waiting to see what happens with YOUR new module!!! :D

Now i'm too scared to try my one!!!
:D
(only kidding - just have to MAKE the time to do it - maybe tonight...)

The manual for the SOMO shows two 1004 diodes in series to drop the 5v to 3.3v or so, but if 0.6v per diode, this is 1.2v lost across them, 5v - 1.2v = 3.8v which is above the maximum supply voltage, so I am going to use three diodes in series, which should be smack on 3.2v.

I wonder if your module was killed that way?
 
Last edited:

Grogster

Senior Member
@ Goom - My 1st attempt to use the module worked beautifully.
The sound from this little thing, and the output volume from a 3.2v supply is also impressive.
I had to put an 18-ohm half-watt resistor in series with the SP+ lead to quieten it down a bit. :D

I really must stress how impressed I am with the sound quality from this thing - albeit only in mono, but that is all you need for announciator systems in most cases.

I'm only using it it button-mode at the moment, to prove the module is working, but I will see if I get around to hooking it up to the 18X chip tonight.

One thing I did notice, is that the micro-SD card does resist inital insertion, and required a bit of a gentle ramming to get it in the slot. Overcome that, and it clicks in like many of those cards kinda like an alternate-action push-switch.

Being a CMOS device, anytime I went anywhere near it, I was wearing my anti-static wrist-strap.

I did not use the diodes, preferring to use a 3v3 regulator instead.(LM3940 - I have a box of these, so it was a way to use one!)
 
Last edited:

westaust55

Moderator
Yes, I suspect that slower is quite acceptable. I just wanted to keep the data transmission time to a minimum for my particular application, and pause for 20uS is not possible.

Regarding idling high, I'm not sure that it really matters what the clock state is between data transmissions, as long as the 200us low start state and high stop state are respected. I avoided setting the clock high at startup in case this was interpreted as clocking the first bit. After the first data transmission, my code leaves the clock high until between transmissions. Westaust55's suggested modification leaves the clock low between transmissions.
SOMO-14D datasheet (page 5 section 2.1) does indicate: "the idle state of the clock must be high".


Unless I have something wrong (not unknown :eek: ), the clock line should be normally high.
1. I changed your code to have a high 5 near the start to make the clock line high
2. The PULSOUT command briefly toggles/inverts the state of the output only for the period specified (see PICAXE Manual 2 page 136). Thus it will revert to the high state automatically after each clock pulse thereby leaving the cluock line high between data transfers.
 

Grogster

Senior Member
I have the module playing files via the 18X.
Problem is, if I send $0001, it playes file #9 instead of file #1.
Must be something wrong with the timing.
More tinkering...

EDIT: Sending $0002 plays file #10 instead of file #2.
Hmmmm. We appear to be out by a factor of 8...

I love a good mystery. :)

CRITICALLY IMPORTANT INFORMATION: Playing files from the micro-SD card only requires that you select a valid filename from the card - playback is automatic. Sending a [PLAY/PAUSE] command after selecting the file to play, results in the module going into pause mode and nothing plays. Sending the filename data ONLY results in the module playing that file immediately. THIS IS NOT MADE CLEAR IN THE MANUAL, so I thought I should post it here...
 
Last edited:

hippy

Technical Support
Staff member
From the datasheet, this code should work for sending commands ( untested ) ...


Symbol CLK = 1 ' Pin 1
Symbol DAT = pin2 ' Pin 2

High CLK
Do
:
w0 = $????
Gosub SendW0
:
Loop

SendW0:
Low CLK
Pause 2
For b2 = 0 To 15
Low CLK
DAT = bit15
w0 = w0 * 2
High CLK
Next
Pause 2
Return
 
Last edited:

Grogster

Senior Member
@ hippy - will try your code shortly - thanks for posting. :)

The original code is INTENSLY interesing.
If I send $0009, then file #1 plays, and in the reverse order:

Send $0001 to play file #1, file #9 plays.
Send $0002 to play file #2, file #8 plays
Send $0003 to play file #3, file #7 plays
Send $0004 to play file #4, file #6 plays

This is just so you can see what is happening.

BUT IT IS WORKING, IT IS PLAYING FILES, AND IT IS LISTENING TO THE 18X TALKING TO IT - all of which is a good thing. :)

Now, to try hippy's code...

EDIT: @ hippy - won't do anything. LED on the SOMO module(busy) lights breifly when this code is run, but nothing plays. Nice try, thanks for posting anyway. This thing really has peaked my interest... ;)

HOWEVER, it is 11PM here, and I think I should go and get some sleep.

Here is my code which is working with tweaks:

Code:
symbol dta=w6	'Data to module is a word(16-bit) value
symbol x=b3		'X marks the spot...
symbol mask=w5	'Mask word for the shiftout proceedure
symbol MSB=$8000	'Most Significant Bit position is bit 16
symbol sda=2	'Serial data output is on pin2
symbol scl=1	'Serial clock output is on pin1

high scl		'Set clock idle state high
low sda		'Set data idel state low

wait 5		'Allow everything to start before sending any commands

start:		'Test routine - select file 0001.ad4 and start playback
 dta=$0009		'Select file # 0001.ad4 from micro-SD card
 gosub shiftout	'Tell that to the module
 high scl		'Set clock-line idle-state high
 low sda
 end




'================================
'CLOCK DATA TO MODULE SUBROUTINE:
'================================

shiftout:
  low scl		'Pull clock-line low
  pause 5		'Start-bit time
  for x = 1 to 16	'Start of shiftout code
  mask = dta & MSB
  low sda
  if mask=0 then skipMSB
  high sda
  
 skipMSB:
  pulsout scl,200
  dta = dta * 2
  next x		'End of shiftout code
  high scl		'Pull clock-line high
  pause 5		'End-bit time
  return
 
Last edited:

hippy

Technical Support
Staff member
@ Grogster : Your code puts out 17 rising edges of SCL when there should be 16.

For my code make sure you adjust the SYMBOL definitions for your hardware, also try moving the "w0=w0/2" to just after "DAT=bit15", and adding a "Pause 2" after the NEXT. The code may be running too quickly for the SOMO.

Ideally you need to look at the output on a scope to check it matches what's shown in section 7.1 of the datasheet and that setup and hold times are okay.

Added: Bug ! My "w0=w0/2" should be "w0=w0*2"
 
Last edited:

westaust55

Moderator
Here is a version that:
1. corrects the number of pulses as identified by hippy
2. use just a 1-bit flag for the mask instead of a word variable
3. have used shorter pulse and pause periods that should still be valid.

Code:
SYMBOL control	= b0 	 	; used for control bits - DONT use for anything else 
symbol dta		= w6		'Data to module is a word(16-bit) value
symbol x		= b3		'X marks the spot...
symbol mask	= bit0		'Mask word for the shiftout proceedure

symbol MSB		= $8000	'Most Significant Bit position is bit 16

symbol sda		=2		'Serial data output is on pin2
symbol scl		=1		'Serial clock output is on pin1

init:
high scl				'Set clock idle state high
low sda				'Set data  idle state low

wait 5		'Allow everything to start before sending any commands


start:		'Test routine - select file 0001.ad4 and start playback
	 dta	= $0001	'Select file # 0009.ad4 from micro-SD card
	 gosub shiftout	'Tell that to the module
	 high scl		'Set clock-line idle-state high
	 low sda
 end





'================================
'CLOCK DATA TO MODULE SUBROUTINE:
'================================

shiftout:
  low scl		'Pull clock-line low
  pause 3		'Start-bit time
  
  for x = 1 to 16	'Start of shiftout code
  mask = dta AND MSB / MSB
  low sda
  if mask = 0 then skipMSB
  high sda
skipMSB:
  if x = 16 then skippulse
  pulsout scl,30
  dta = dta * 2
skippulse:
  next x		'End of shiftout code
  high scl		'Pull clock-line high
  pause 3		'End-bit time
  return
 
Last edited:

westaust55

Moderator
Think hippys code would also work if altered to be:


Code:
Symbol CLK = 1 ' Pin 1
Symbol DAT = pin2 ' Pin 2

High CLK
Do
:
w0 = $????
Gosub SendW0
:
Loop
'
'================================
'CLOCK DATA TO MODULE SUBROUTINE:
'================================
SendW0:
  Low CLK
  Pause 2
  For b2 = 0 To [B]14[/B]  ; corrected in line with hippys post 30 below
    DAT = bit15
    Pulsout CLK, 30
    w0 = w0 * 2
  Next
  DAT = bit 15
  High CLK
  Pause 2
  Return
 
Last edited:

hippy

Technical Support
Staff member
Think hippys code would also work if altered to be:

No, that still puts out 17 rising edges of SCL. You also have to change the FOR to "0 TO 14" or "1 TO 15". It's all very convoluted IMO through trying to use PULSOUT.

The big problem is in trying to satisfy the setup and hold time requirements of the SOMO signal lines and both versions of code rely on the intrinsic execution times of instructions which should be okay but may not be - hence ideally looking at it with a scope rather than guessing if it is right. As it's not speed critical, it would be worth adding PAUSE 1 or a PULSOUT to a dummy pin after every I/O line change and seeing if that works. Get it working reliably, then speed it up later.

If the timing is marginal then what may work on one setup may not work on another nor on the same setup every time.
 

Grogster

Senior Member
Here is a version that:
1. corrects the number of pulses as identified by hippy
2. use just a 1-bit flag for the mask instead of a word variable
3. have used shorter pulse and pause periods that should still be valid.

Code:
SYMBOL control	= b0 	 	; used for control bits - DONT use for anything else 
symbol dta		= w6		'Data to module is a word(16-bit) value
symbol x		= b3		'X marks the spot...
symbol mask	= bit0		'Mask word for the shiftout proceedure

symbol MSB		= $8000	'Most Significant Bit position is bit 16

symbol sda		=2		'Serial data output is on pin2
symbol scl		=1		'Serial clock output is on pin1

init:
high scl				'Set clock idle state high
low sda				'Set data  idle state low

wait 5		'Allow everything to start before sending any commands


start:		'Test routine - select file 0001.ad4 and start playback
	 dta	= $0001	'Select file # 0009.ad4 from micro-SD card
	 gosub shiftout	'Tell that to the module
	 high scl		'Set clock-line idle-state high
	 low sda
 end





'================================
'CLOCK DATA TO MODULE SUBROUTINE:
'================================

shiftout:
  low scl		'Pull clock-line low
  pause 3		'Start-bit time
  
  for x = 1 to 16	'Start of shiftout code
  mask = dta AND MSB / MSB
  low sda
  if mask = 0 then skipMSB
  high sda
skipMSB:
  if x = 16 then skippulse
  pulsout scl,30
  dta = dta * 2
skippulse:
  next x		'End of shiftout code
  high scl		'Pull clock-line high
  pause 3		'End-bit time
  return
Thanks for posting. :)
The code you posted plays file #9 when asked for #1 - just as in my case. :p
Will try your modified hippy code now.
 

Grogster

Senior Member
No, that still puts out 17 rising edges of SCL. You also have to change the FOR to "0 TO 14" or "1 TO 15". It's all very convoluted IMO through trying to use PULSOUT.
So is there and alternative to using pulsout - should I be considdering alternative methods?
 

Grogster

Senior Member
Think hippys code would also work if altered to be:


Code:
Symbol CLK = 1 ' Pin 1
Symbol DAT = pin2 ' Pin 2

High CLK
Do
:
w0 = $????
Gosub SendW0
:
Loop
'
'================================
'CLOCK DATA TO MODULE SUBROUTINE:
'================================
SendW0:
  Low CLK
  Pause 2
  For b2 = 0 To [B]14[/B]  ; corrected in line with hippys post 30 below
    DAT = bit15
    Pulsout CLK, 30
    w0 = w0 * 2
  Next
  DAT = bit 15
  High CLK
  Pause 2
  Return
...plays file #9 when asked for #1 - exactly the same as all the other tests.
Good fun, eh? ;)
Gotta go to work for the rest of the day - will check back here tonight(my time).
 

hippy

Technical Support
Staff member
Are you absolutely sure that file #1 doesn't have the same contents as file #9 ?

Time to start adding those pauses ...

Symbol CLK = 1 ' Pin 1
Symbol DAT = pin2 ' Pin 2

High CLK
Pause 1000
w0 = $0009
Gosub SendW0

Do : Loop

SendW0:
Low CLK
Pause 2
For b2 = 0 To 15
Pause 1 : Low CLK
Pause 1 : DAT = bit15
Pause 1 : w0 = w0 * 2
Pause 1 : High CLK
Next
Pause 2
Return
 

Grogster

Senior Member
Are you absolutely sure that file #1 doesn't have the same contents as file #9 ?
Absolutely sure.
I have them all written down on paper, in the order they are, and this is confirmed if I disconnect the SOMO data and clock lines, and restart the module then use the push-buttons to control it. There are no double-ups on music files.

Thank you for continuing to post suggestions - I am learning from all this, so I just want to say thanks to all for the on-going suggestions. :)
 

Grogster

Senior Member
Okey dokey - an update for ya all:

With respect to the code(ANY variation posted by any of us) playing the correct file

- No amount of tinkering with 0-16 for the bits of the word works
- No amount of tinkering with pauses works
- Any pause greater then 50 in my or westaust55's and the module refuses to work
- Any pause greater then 15 in hippy's last posted code and the module refuses to work
- hippy's last code in post #34 plays file #9 instead of file #1 - same old, same old... ;)

I've given up on getting this to work any time soon, except using the reverse-method I talked about in post #26, which DOES WORK, but you have to send the wrong file # data.($0009 for file #1 etc)

I'm wondering if there is a misprint in the manual, because with all of us working on it, and my trying out all code versions posted by other members here, no version or variation of ANY code posted thus far works for playing file #1 if you send binary-1 as a 16-bit word.

The next thing I am going to tinker with, is using an 18X pin to pulse the NEXT pin several times quickly to select the correct file. I'll keep you posted, but this well may be easier in the long run over trying to get this flippin' data and clock thing to work! :D

Pulsing the NEXT pin would work fine if you had less then 50 files, but any more then that and the time doing the pulses might get too long - will try it out and see.
 
Last edited:

westaust55

Moderator
Might dig my SOMO-14D module out over the weekend and see if I experience the same 'problems' or can advance the cause further . . . .

Had a look last night on the 4D systems forum for the SOMO modules. nothing there in terms of others having file address/name problems.
 

Grogster

Senior Member
Might dig my SOMO-14D module out over the weekend and see if I experience the same 'problems' or can advance the cause further . . . .

Had a look last night on the 4D systems forum for the SOMO modules. nothing there in terms of others having file address/name problems.
Perhaps they are using a different PIC range to control them.
Is there any technical reason that anyone here can think of, why PICAXE chips would NOT work with these modules?

I'm starting to get sick of this module - sounds great, but if it is going to be a pain to control it...

What is the Picaxe player thing like?
I guess, even though more expensive, is designed to be 100% compatible with the Picaxe range of chips. What was that thing called again?
 

hippy

Technical Support
Staff member
No reason that I can see that a PICAXE shouldn't be able to control the chip, it ( or anything else ) just needs to put out the right bit-banged sequence.

All hardware interfacing can be a potential pain and especially without the right tools to verify what is happening on bus lines. When something doesn't work it's hard to know why; timing error, protocol error, coding error, documentation error, faulty circuit, faulty components. The only thing you can hope for is to verify what you can and narrow it down to fewer things. Getting there can sometime take a long time. At least you've got something working which is far better than many cases when nothing happens at all.

While we know sending $0009 plays file 1, what about all the other files ? Is there any correlation and consistency between commands sent and what's played ?
 

goom

Senior Member
I understand your frustration Grogster, and am also baffled by why the correct file is not being played. Maybe you need to give it a rest for a while, and wait for westaus55 and myself to experiment and report findings. I am still a week away from that, waiting for the replacement unit.
If you are in the mood for more experimenting, hippy's suggestion of extending the range of file names seems like a good way to try and find a pattern.
If you have a file called, for example, 0450.adf, can you play it? What happens if you try to play $000C ?
What happens if you call up the same file twice in code (e.g. play file 0001, stop the play ($FFFF), then play it again? Does the PLAY/PAUSE ($FFFE), or STOP commands actually work?
Just a couple of really long shots:
I assume that $0009 is just the same as, for example, $9, %1001, 9 . I am 95% sure that it is.
Could your file names be missing a "0"? e.g. "001.ad4 instead of "0001.ad4"
 
Top