Slower ShiftOut()?

Started by Don Kinzer April 15, 2004
I have an application where I need to shift out some data at a
maximum rate of 50KHz (20us clock period). The ShiftOut() routine's
clock has a period of about 3.5us so I can't use it. I have
implemented an alternative shifting routine but it's fairly slow.
Even with the loop unrolled, the fastest that I can get is a 130us
clock period (see code below). I've tried other variations of the
code but can't get it done any faster.

Does anyone know how ShiftOut() is implemented internally? Does it
use one of the timers or does it use the AVR's SPI functionality? Is
there any way get ShiftOut() to go slower?

Any ideas would be appreciated.

Private Sub shiftOutSlowly(ByVal dataPin as Byte, ByVal clkPin as
Byte, ByVal b as Byte)
Call PutPin(dataPin, GetBit(b, 7))
Call PulseOut(clkPin, 1, 0)
Call PutPin(dataPin, GetBit(b, 6))
Call PulseOut(clkPin, 1, 0)
Call PutPin(dataPin, GetBit(b, 5))
Call PulseOut(clkPin, 1, 0)
Call PutPin(dataPin, GetBit(b, 4))
Call PulseOut(clkPin, 1, 0)
Call PutPin(dataPin, GetBit(b, 3))
Call PulseOut(clkPin, 1, 0)
Call PutPin(dataPin, GetBit(b, 2))
Call PulseOut(clkPin, 1, 0)
Call PutPin(dataPin, GetBit(b, 1))
Call PulseOut(clkPin, 1, 0)
Call PutPin(dataPin, GetBit(b, 0))
Call PulseOut(clkPin, 1, 0)
End Sub



This probably won't help much (and it'll use up a lot of ram) but you could
loop the GetBit routines into a byte array and then use the byte array in
your PutPin loop. That would eliminate the call to GetBit during the PutPin
loop. Probably not much help but I don't know how much you need.

dim a(0 to 7) as byte, ctr as byte

for i = 0 to 7 do
a(i) = GetBit(b, i)
next

for i = 7 to 0 step -1
Call PutPin(dataPin, a(i))
Call PulseOut(clkPin, 1, 0)
next

Paul At 11:05 AM 4/15/2004, you wrote:

>I have an application where I need to shift out some data at a
>maximum rate of 50KHz (20us clock period). The ShiftOut() routine's
>clock has a period of about 3.5us so I can't use it. I have
>implemented an alternative shifting routine but it's fairly slow.
>Even with the loop unrolled, the fastest that I can get is a 130us
>clock period (see code below). I've tried other variations of the
>code but can't get it done any faster.
>
>Does anyone know how ShiftOut() is implemented internally? Does it
>use one of the timers or does it use the AVR's SPI functionality? Is
>there any way get ShiftOut() to go slower?
>
>Any ideas would be appreciated.
>
>Private Sub shiftOutSlowly(ByVal dataPin as Byte, ByVal clkPin as
>Byte, ByVal b as Byte)
> Call PutPin(dataPin, GetBit(b, 7))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 6))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 5))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 4))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 3))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 2))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 1))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 0))
> Call PulseOut(clkPin, 1, 0)
>End Sub >
>Yahoo! Groups Links >
>
>---
>Incoming mail is certified Virus Free.
>Checked by AVG anti-virus system (http://www.grisoft.com).
>Version: 6.0.656 / Virus Database: 421 - Release Date: 4/9/2004

===========================================================
"We have the power to do any damn fool thing we want to do,
and we seem to do it about every ten minutes."
J. William Fulbright , quoted in Time (New York, Feb. 4, 1952).
===========================================================

---------- ---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.656 / Virus Database: 421 - Release Date: 4/9/2004


Hi Don. Here's what I did to read an AD chip awhile back. I cant see it
being that much different from what you did but it did work for me:

Public Sub GetADchip(ByRef AnaArrayPointer As Integer, ByVal ConfigAD As
Byte)
Dim Value12Bit As Integer
Dim Bits As Byte
Dim BitValue As Byte
Dim sTemp As Single Value12Bit = 0 'Reset all bits

Call PutPin(PinClock, 1) 'Start with clock high. clock going low
brings in data
Call PutPin(PinChipSelect, 0) 'Set the chip ready - Reset Pin

For Bits = 0 To 3
BitValue = GetBit(ConfigAD, Bits) 'get 1 bit of the
config byte
Call PutPin(PinData, BitValue) 'Set the data pin to this
value
Call PutPin(PinClock, 0) 'Toggle the clock
Call PutPin(PinClock, 1) 'to send data
Next 'Bits

Call PutPin(PinClock, 0) 'Toggle the clock to ready the
Call PutPin(PinClock, 1) 'AD chip for a send
Call PutPin(PinData, 2) 'Change Datapin to an input.

For Bits = 12 To 1 Step -1 'store bits from MSB to LSB
Call PutPin(PinClock, 0) 'Toggle the clock
Call PutPin(PinClock, 1) 'to receive data.
Call Sleep(2)
BitValue = GetPin(PinData) 'Read the data
Call PutBit(Value12Bit, (Bits - 1), BitValue) 'store it
Next 'Bits

Call PutPin(PinChipSelect, 1) 'disable chip
Call PutPin(PinClock, 0) 'turn off the clock

'convert to 0~1000 reading
sTemp = CSng(Value12Bit)
Value12Bit = CInt((sTemp / 4095#) * 1000#)

Analogs(AnaArrayPointer) = Value12Bit 'store new value
in array element

'Debug.Print ""
'Debug.Print "Value12Bit :"; CStr(Value12Bit)
'Debug.Print "Analog array :";
CStr(Analogs(AnaArrayPointer))

End Sub



Don,

How much data do you need to shift and how often ?. If only a few
bytes I am thinking that you could store them externally (serial
in/out shift registers) and read at leisure. BX24 could still be
used as a clock source for both systems. Not very elegant but just a
thought.

Cheers

Pat
--- In , "Don Kinzer" <dkinzer@e...> wrote:
> I have an application where I need to shift out some data at a
> maximum rate of 50KHz (20us clock period). The ShiftOut()
routine's
> clock has a period of about 3.5us so I can't use it. I have
> implemented an alternative shifting routine but it's fairly slow.
> Even with the loop unrolled, the fastest that I can get is a 130us
> clock period (see code below). I've tried other variations of the
> code but can't get it done any faster.
>
> Does anyone know how ShiftOut() is implemented internally? Does
it
> use one of the timers or does it use the AVR's SPI functionality?
Is
> there any way get ShiftOut() to go slower?
>
> Any ideas would be appreciated.
>
> Private Sub shiftOutSlowly(ByVal dataPin as Byte, ByVal clkPin as
> Byte, ByVal b as Byte)
> Call PutPin(dataPin, GetBit(b, 7))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 6))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 5))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 4))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 3))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 2))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 1))
> Call PulseOut(clkPin, 1, 0)
> Call PutPin(dataPin, GetBit(b, 0))
> Call PulseOut(clkPin, 1, 0)
> End Sub





--- In , "Brad Watts" <bradwatts@a...> wrote:
> Call PutPin(PinClock, 0) 'Toggle the clock
> Call PutPin(PinClock, 1) 'to send data

I did some timing measurement on sequences like this. The one above
takes about 90us to execute, producing a pulse from 44us to 55us long.

Alternately, the sequence below takes about 55us to execute with a
pulse width of 1.2us. The negative aspect is that multitasking,
network traffic and RTC updates are halted for the duration according
to the documentation.

Call PulseOut(PinClock 1, 0)


--- In , "dongle241" <patcooper@m...> wrote:
> How much data do you need to shift and how often ?. If only a few
> bytes I am thinking that you could store them externally (serial
> in/out shift registers) and read at leisure.

The data is going to an LCD. It's 8 bits at a time and it varies a
lot.

This is for one of the Hyundai 8x24 LCD panels. It has an RS-232
interface but I wanted to connect to it using clocked data. I
modified the firmware on the display unit to support the additional
interface mode.

As it stands, the 130us bit time gives me about 1ms per byte. This
is equivalent to an RS-232 bit rate of about 9600 baud (assuming 8
data bits, no parity, 1 stop bit). That's probably fast enough not
to warrant adding additional hardware as you suggested (good idea!).
But if I could push the data out at the maximum rate that the display
can accept it I could get a data rate equivalent to RS-232 at 62.5K
baud.

I put together a page with information about the panel including the
firmware changes that I made.
http://www.kinzers.com/don/LCD_Panel