Speeding up this SPI bit bang function in C?

Go To Last Post
37 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is my implementation of SPI master in C, I have two banks so I handle CS select as well. I would be happy to hear suggestions to speed this up without going into asm.

 

#define SPI_CLK_TGL   SPI_CLK_PORT ^= 1<<SPI_CLK
#define SPI_CSH_LO    SPI_CSH_PORT &= ~(1<<SPI_CSH)
#define SPI_CSH_HI    SPI_CSH_PORT |= 1<<SPI_CSH
#define SPI_CSL_LO    SPI_CSL_PORT &= ~(1<<SPI_CSL)
#define SPI_CSL_HI    SPI_CSL_PORT |= 1<<SPI_CSL
#define SPI_DATA_HI   SPI_DATA_PORT |= 1<<SPI_DATA
#define SPI_DATA_LO   SPI_DATA_PORT &= ~(1<<SPI_DATA)


void SPISendByte (char data, char bank)
{
	if(bank == BANK_LO)
		SPI_CSL_LO;
	else
		SPI_CSH_LO;
		
	for(char i = 0; i < 8; i++)
	{
		if(data & 0x80)
			SPI_DATA_HI;
		else
			SPI_DATA_LO;
		
		SPI_CLK_TGL;
		SPI_CLK_TGL;
		
		data <<= 1; 
	}
	
	if(bank == BANK_LO)
		SPI_CSL_HI;
	else
		SPI_CSH_HI;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what makes you think the code is the speed problem?

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ki0bk wrote:

what makes you think the code is the speed problem?

 

I did not say that. Just wondering from the code point of view if I can speed it up or this is pretty minimal? With 8Mhz CLK the SPI CLK does about 455.5 KHz

Last Edited: Sun. Jul 16, 2017 - 08:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

unroll the loop (don't shift but check bit)

make function inline

 

perhaps place data and bank in registers

 

Perhaps show the ASM code for your C code  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

slow_rider wrote:
With 8Mhz CLK the SPI CLK does about 455.5 KHz

 

For each bit you need to

- Set the  data pin. This involves isolating a bit in your byte, testing it and then either a SBI or a CBI. Let's assume (ballpark estimate) this whole lot takes five clocks.

- Wiggle the clock pin. Two clocks.

 

You need to do this for eight bits, and currently you have a loop and a shift. Lets guess that this costs you five clocks each time around.

(5+2+5) * 8 = 96 clocks. Let's call that a nice and round 100.

8 MHz / 100 = 800 KHz.

 

You're seeing about half of that. My guesstimates above looks to be off by like 100%, which is entirely possible.  To know for sure, show us the .lss file.

 

Point is, don't expect e.g. a tenfold speedup, even if you unroll the loop "and do the other things" [JFK 1962-09-12 ;-) ]. Unrolling will remove the loop overhead - I'm guessing it accounts for 40% of the running time.

 

It might be that the function already is inlined. OTOH, if not then that might account for some of  the miss in my guesstimates. Again, the .lss file will tell.

 

Same for register allocation of variables. Might already be. If not, then remember that any load or store from/to RAM is 2 clocks, while a register-register op is 1 clock. Again, the .lss file...

 

Don't get me wrong: All the advice from sparrow2 seems excellent to me. 

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I've tried the following:

  • inline the function - actually reduced the CLK freq. to about 440 KHz
  • assigning bank & data to registers using register unsigned char data asm("r3") - also slowed down CLK.
  • unrolled the loop and this got CLK up to 550 KHz which is a significant gain.
void SPISendByte (char data, char bank)
{
	if(bank == BANK_LO) SPI_CSL_LO;
	else                SPI_CSH_LO;
	
	// bit7
	if(data & 0x80) SPI_DATA_HI;
	else            SPI_DATA_LO;
		
	SPI_CLK_TGL;
	SPI_CLK_TGL;
	
	// bit6
	if(data & 0x40) SPI_DATA_HI;
	else            SPI_DATA_LO;
	
	SPI_CLK_TGL;
	SPI_CLK_TGL;
	
	// bit5
	if(data & 0x20) SPI_DATA_HI;
	else            SPI_DATA_LO;
	
	SPI_CLK_TGL;
	SPI_CLK_TGL;
	
	// bit4
	if(data & 0x10) SPI_DATA_HI;
	else            SPI_DATA_LO;
	
	SPI_CLK_TGL;
	SPI_CLK_TGL;
	
	// bit3
	if(data & 0x08) SPI_DATA_HI;
	else            SPI_DATA_LO;
	
	SPI_CLK_TGL;
	SPI_CLK_TGL;
	
	// bit2
	if(data & 0x04) SPI_DATA_HI;
	else            SPI_DATA_LO;
	
	SPI_CLK_TGL;
	SPI_CLK_TGL;
	
	// bit1
	if(data & 0x02) SPI_DATA_HI;
	else            SPI_DATA_LO;
	
	SPI_CLK_TGL;
	SPI_CLK_TGL;
	
	// bit0
	if(data & 0x01) SPI_DATA_HI;
	else            SPI_DATA_LO;
	
	SPI_CLK_TGL;
	SPI_CLK_TGL;
		
	if(bank == BANK_LO) SPI_CSL_HI;
	else                SPI_CSH_HI;
}

 

Here is the assembly code of the original function from the original question:

 

0000001E  RJMP PC+0x0017		Relative jump 
		SPI_CSH_LO;
0000001F  CBI 0x1B,6		Clear bit in I/O register 
00000020  RJMP PC+0x0015		Relative jump 
		if(data & 0x80)
00000021  TST R24		Test for Zero or Minus 
00000022  BRGE PC+0x03		Branch if greater or equal, signed 
			SPI_DATA_HI;
00000023  SBI 0x18,0		Set bit in I/O register 
00000024  RJMP PC+0x0002		Relative jump 
			SPI_DATA_LO;
00000025  CBI 0x18,0		Clear bit in I/O register 
		SPI_CLK_TGL;
00000026  IN R25,0x18		In from I/O location 
00000027  EOR R25,R19		Exclusive OR 
00000028  OUT 0x18,R25		Out to I/O location 
		SPI_CLK_TGL;
00000029  IN R25,0x18		In from I/O location 
0000002A  EOR R25,R19		Exclusive OR 
0000002B  OUT 0x18,R25		Out to I/O location 
		data <<= 1; 
0000002C  LSL R24		Logical Shift Left 
0000002D  SUBI R18,0x01		Subtract immediate 
	for(char i = 0; i < 8; i++)
0000002E  BRNE PC-0x0D		Branch if not equal 
	if(bank == BANK_LO)
0000002F  CPSE R22,R1		Compare, skip if equal 
00000030  RJMP PC+0x0003		Relative jump 
		SPI_CSL_HI;
00000031  SBI 0x1B,7		Set bit in I/O register 
00000032  RET 		Subroutine return 
		SPI_CSH_HI;
00000033  SBI 0x1B,6		Set bit in I/O register 
}
00000034  RET 		Subroutine return 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which AVR do we talk about?

 

What else happen on that PORT ?

Can the bit be set with PORT= aaa ? (no other pins change on the port doing this)

 

And for your code depending of the AVR toggle CLK could be done with a write to the PIN register for the port, it would be faster. 

 

 

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

First the obvious:

Have you tried to use hardware SPI?

(Curious: Why in software if speed is so important for you?)

 

I've used this method with success:

	uint8_t Bit;
	
	for( Bit = 0x80; Bit; Bit >>= 1) {
		if( Bit & Data )
                  SPI_DATA_HI;
		else
		  SPI_DATA_LO;
	}

A part of the opmtimisation is that checking for zero (nonzero also?) is faster in a for loop than checking for another value.

After shifting "Bit" the status flags are already set right for the for loop exit condition and no extra calculation is needed.

 

You also have the macro:

SPI_CLK_TGL;

This is translated into 3 asm instructions.

If you rewrite it into 2 macro's:

SPI_CLK_HI;
SPI_CLK_LOW;

Then the value of the bit does not have to be read and XOR'ed and it will probably be done in just a single SBI or CBI asm instruction.

Note that the clock will then likely be high for only one CPU cycle of your AVR.

You can play a bit with this by:

  for( Bit = 0x80; Bit; Bit >>= 1) {
    SPI_CLK_LOW;
    if( Bit & Data )
       SPI_DATA_HI;
    else
       SPI_DATA_LO;
    SPI_CLK_HI;
  }

In this way the shifting & testing of "Bit" is in between the setting / resetting of SPI_CLK and the pulse will be wider.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Which AVR do we talk about?

 

What else happen on that PORT ?

Can the bit be set with PORT= aaa ? (no other pins change on the port doing this)

 

And for your code depending of the AVR toggle CLK could be done with a write to the PIN register for the port, it would be faster. 

 

Add:

Remember that the speed depends of the number of bits set in data! (0xff is 8 clk slower than 0x00 so what is the speed? AVG or worst case? )

 

and in ASM at least (it will depend of the compiler), it's faster to clr data, and then check if it should be set, than a if else.

 

 

Last Edited: Sun. Jul 16, 2017 - 10:18 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:

Which AVR do we talk about?

 

What else happen on that PORT ?

Can the bit be set with PORT= aaa ? (no other pins change on the port doing this)

 

And for your code depending of the AVR toggle CLK could be done with a write to the PIN register for the port, it would be faster. 

 

The AVR is ATtiny26

The rest of the port is taken. How can you write to the PIN register? 

Last Edited: Tue. Jul 18, 2017 - 06:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The rest of the port is taken. How can you write to the PIN register? 

 

Most "modern" AVR's will in output mode toggle the portpin if you write PIN

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was interested to see what the code in #1 might originally have looked like but to build something I found I had to define all kinds of external symbols:

#define BANK_LO 	0
#define SPI_CLK_PORT	PORTA
#define SPI_CLK			4
#define SPI_DATA_PORT	PORTB
#define SPI_DATA		1
#define SPI_CSH_PORT	PORTB
#define SPI_CSH			2
#define SPI_CSL_PORT	PORTB
#define SPI_CSL			3

and then that had an effect on the generated code:

00000026 <SPISendByte>:
#define SPI_DATA_LO   SPI_DATA_PORT &= ~(1<<SPI_DATA)


void SPISendByte (char data, char bank)
{
        if(bank == BANK_LO)
  26:   61 11           cpse    r22, r1
  28:   02 c0           rjmp    .+4             ; 0x2e <SPISendByte+0x8>
                SPI_CSL_LO;
  2a:   c3 98           cbi     0x18, 3 ; 24
  2c:   01 c0           rjmp    .+2             ; 0x30 <SPISendByte+0xa>
        else
                SPI_CSH_LO;
  2e:   c2 98           cbi     0x18, 2 ; 24
#define SPI_DATA_HI   SPI_DATA_PORT |= 1<<SPI_DATA
#define SPI_DATA_LO   SPI_DATA_PORT &= ~(1<<SPI_DATA)


void SPISendByte (char data, char bank)
{
  30:   98 e0           ldi     r25, 0x08       ; 8
                if(data & 0x80)
                        SPI_DATA_HI;
                else
                        SPI_DATA_LO;

                SPI_CLK_TGL;
  32:   30 e1           ldi     r19, 0x10       ; 16
        else
                SPI_CSH_LO;

        for(char i = 0; i < 8; i++)
        {
                if(data & 0x80)
  34:   87 ff           sbrs    r24, 7
  36:   02 c0           rjmp    .+4             ; 0x3c <SPISendByte+0x16>
                        SPI_DATA_HI;
  38:   c1 9a           sbi     0x18, 1 ; 24
  3a:   01 c0           rjmp    .+2             ; 0x3e <__SP_L__+0x1>
                else
                        SPI_DATA_LO;
  3c:   c1 98           cbi     0x18, 1 ; 24

                SPI_CLK_TGL;
  3e:   2b b3           in      r18, 0x1b       ; 27
  40:   23 27           eor     r18, r19
  42:   2b bb           out     0x1b, r18       ; 27
                SPI_CLK_TGL;
  44:   2b b3           in      r18, 0x1b       ; 27
  46:   23 27           eor     r18, r19
  48:   2b bb           out     0x1b, r18       ; 27

                data <<= 1;
  4a:   88 0f           add     r24, r24
  4c:   91 50           subi    r25, 0x01       ; 1
        if(bank == BANK_LO)
                SPI_CSL_LO;
        else
                SPI_CSH_LO;

        for(char i = 0; i < 8; i++)
  4e:   91 f7           brne    .-28            ; 0x34 <SPISendByte+0xe>
                SPI_CLK_TGL;

                data <<= 1;
        }

        if(bank == BANK_LO)
  50:   61 11           cpse    r22, r1
  52:   02 c0           rjmp    .+4             ; 0x58 <__SREG__+0x19>
                SPI_CSL_HI;
  54:   c3 9a           sbi     0x18, 3 ; 24
  56:   08 95           ret
        else
                SPI_CSH_HI;
  58:   c2 9a           sbi     0x18, 2 ; 24
  5a:   08 95           ret

So I think we need to hear more about how those other symbols were defined.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

slow_rider wrote:
Just wondering from the code point of view if I can speed it up

Look at it on an oscilloscope - that should show if there's any scope (sic) for timing improvement ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
  3e:   2b b3           in      r18, 0x1b       ; 27
  40:   23 27           eor     r18, r19
  42:   2b bb           out     0x1b, r18       ; 27

My question ,(that it seemed that OP didn't get), was if any of the other IO's on the port can do things asynchronous with the rest of the port pins, if yes the toggle code (I show here from the code in #12) might not be legal!

 

Add:

And if yes (to use in and out) then OP should tell which port pins the different signals are placed (to see who is together).

 

 

  Add:

and in ASM it can be done in 82 clk worst case, (78 AVG) so about 1MHz (only using CBI and SBI), then you can see if it's worth it.

 

 

And I have to ask : do you toggle clk because then it can cover different SPI modes or just because it's easy ?

 

 

Last Edited: Mon. Jul 17, 2017 - 12:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It appears to be SPI "send only"?

 

IIRC there is an extensive (seminal?) thread on optimal bit-banging.  Some 'Freak (skeeve?) showed how to pre-process that data with XOR, and then use bit-toggle if needed.  IIRC it ended up constant-time, and fewer cycles/bit than other approaches.

 

[edit] After some digging, I found where I had dug out the thread I was thinking of...

http://www.avrfreaks.net/comment...

...which gives a link to skeeve's method ...

http://www.avrfreaks.net/comment...

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

Last Edited: Mon. Jul 17, 2017 - 02:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

slow_rider wrote:
// bit0 if(data & 0x01) SPI_DATA_HI; else SPI_DATA_LO;

In this thread, double-if came out ahead of if/else

http://www.avrfreaks.net/comment...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But a tiny26 can't toggle on PIN!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
But a tiny26 can't toggle on PIN!

1)  OP saw fit to bury that piece of info inside a quoted block.

2)  Hasn't that model been "Mature" for about a decade?

3) '261 >>does<< have the toggle feature.

 

OP was sketchy about this need.  Apparently a modification to a legacy app?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@clawson you were interested in the define macros

#define SPI_CLK_PORT  PORTB
#define SPI_CLK_DDR   DDRB
#define SPI_CLK       PB2
#define SPI_DATA_PORT PORTB
#define SPI_DATA_DDR  DDRB
#define SPI_DATA      PB0
#define SPI_CSH_PORT  PORTA
#define SPI_CSH_DDR   DDRA
#define SPI_CSH       PA6
#define SPI_CSL_PORT  PORTA
#define SPI_CSL_DDR   DDRA
#define SPI_CSL       PA7

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

why don't you answer the other quistions ?

like:

 

And I have to ask : do you toggle clk because then it can cover different SPI modes or just because it's easy ? 

 

My question ,(that it seemed that OP didn't get), was if any of the other IO's on the port can do things asynchronous with the rest of the port pins, if yes the toggle code (I show here from the code in #12) might not be legal!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Toggle the clock vs. set it low and afterwards set it high (not use XOR)?

Sorry I don't understand the 2nd question.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yes

do you know before hand if clk are high or low when you reach this code ?

 

Add:

Perhaps to make it clear shall this code always be used in the same SPI mode ?

 

 

Last Edited: Tue. Jul 18, 2017 - 09:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but more important what else can happen (on the IO's) when this code run ? 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#define SPI_CLK_TGL   SPI_CLK_PORT ^= 1<<SPI_CLK

Based on the disassembly others have provided:

		SPI_CLK_TGL;
00000026  IN R25,0x18		In from I/O location 
00000027  EOR R25,R19		Exclusive OR 
00000028  OUT 0x18,R25		Out to I/O location 
		SPI_CLK_TGL;
00000029  IN R25,0x18		In from I/O location 
0000002A  EOR R25,R19		Exclusive OR 
0000002B  OUT 0x18,R25		Out to I/O location 

An easy improvement (assuming that the CLK bit is constant, and in a "low" port) is to "know" the clock state, so that your code becomes:

    SPI_CLK_ONE;  // go high from "low" idle state

    SPI_CLK_ZERO; // and back to low.

Potentially, that's four clocks instead of 6.  You might get it down to two by caching the clock states, specially a net win if you do it for more than one byte at a time.  Assuming the compiler thinks you have enough registers.  And the databit is on a different port, I guess.

    spi_clklow = SPI_CLK_PORT;
    spi_clkhigh = spi_clklow ^ (1<<SPI_CLK);
    loop() {
       do_data_bit;
       SPI_CLK_PORT = spi_clkhigh;
       SPI_CLK_PORT = spi_clklow;
   }

The loop will be slightly faster counting down from 8 to 0 instead of counting up from 0 to 8...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

and to go a step further :

 

if you preload 4 registers (in C just 4 local variables) with :

the 4 combinations of data and clk (with the other 6 bit having the correct value)

 

the writhing of each bit then can be done in 3 clk (because data and clk are on the same port)

//0

out data_low clk_low 

out data_low clk_low 

out data_low clk_high

//1

out data_high clk_low 

out data_high clk_low 

out data_high clk_high

 

the selection then need to be added.

 

Perhaps clk has to be inverted, (OP have still not given info about SPI mode)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@sparrow2

Yes that is the reason, the start state of the clock pin set in a setup function.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So this mean that you don't know the state of the clk when you get into this function ? (That this routine has to be able to handle different SPI modes)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Exactly, however I might get around that by writing two different functions?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I had a look at the toggle clk code and something like this (sorry for absolute numbers) should work and make a ok code:

#include <avr/io.h>
volatile unsigned char data=0x55;
int main(void)
{
   unsigned char temp= PORTB;
   unsigned char datalow= temp & ~0x01;
   unsigned char datahigh= temp | 0x01;
   unsigned char datalowclk2= datalow ^0x04;
   unsigned char datahighclk2= datahigh ^0x04;
   temp=data;
   for (unsigned char i=8;i>0;i--){
	    if(temp&0x80){
		    PORTB=datahigh;
		    PORTB=datahighclk2;
		    PORTB=datahigh;
		}
		else {
		    PORTB=datalow;
		    PORTB=datalowclk2;
		    PORTB=datalow;		
		}
		temp<<=1;
   }
   
   	
}

should be faster than your code, (and then you can unroll etc.), how fast depends on the rest of the code, but about 10 clk up front and then 10 for each bit, so about 800-900 kHz

 

But remember that you can't have an ISR changing anything on PORTB or something like that (but your code have the same fault).

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just for completeness:

A long time ago I found a project which did 10Mb/s Ethernet bitbanging in software.

I believe they did it by pre calculating all bits / transitions and then shifting them out (Probably in a small asm routine).

Seems like a silly exercise, but impressive none the less.

 

And apart from that article I've never heared much about it.

Unlike the V-USB stack from obdev, with it's most famous implementation in the USBasp programmer which uses bitbanging on low-speed USB (1.5Mb/s).

Obdev has about 100+ example projects on it's website. The bit shifting is also done in asm I believe.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not sure what your point is?

 

OP want C NOT asm, clk need to toggle so the init can handle the SPI mode to use.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@ sparrow2 I quote myself:

Paulvdh wrote:
Just for completeness:

 

slow_rider wrote:
Exactly, however I might get around that by writing two different functions?

As I said before:

Your toggle macro translates to 3 asm instructions.

This is by far the most intersting part for optimisation.

Either use the hardware toggle by writing to PIN or use simple set and clear.

Both options avoid the read and the XOR asm instructions.

 

The next optimisation would be to use another processor.

A USD1.5 st32f103c8t6 for example has no problem with toggling an I/O pin @20MHz.

 

sparrow2 wrote:
why don't you answer the other quistions ? like:

OP apparently also read completely over my suggestion to use the hardware SPI interface.

You can easily transfer a few Mega bits/s over that.

It can run at F_CPU/2 while sending or F_CPU/4 when receiving.

But the biggest advantage is that the uC can do "something else" while the data is shifted out.

Such as a for loop to get the next byte or check how many bytes have to be send.

This makes it possible tho generate a continuous bit stream.

 

But going back to the big question:

What do you want to achieve?

Does it really matter if you have 500kbps or 800kbps?

What external hardware are you writing to?

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

But OP us a tiny26, and the pins in use (for clk and data are fixed to PB0 and PB2), and that chip can't toggle the port pin by writing. (so any other chip or HW spi aren't in play! only option would be tiny261 because it is a plug in replacement ) 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

@sparrow2

So this is yet another example of a designer getting himself into trouble because of a choice of too limited hardware?

Personally is quite dislike the whole tiny series. They just tend to make life for programmers harder for a small benefit of a lower price.

Also see my rant in:

http://www.avrfreaks.net/forum/a...

 

And why do you assume only a plug in replacement would be acceptable?

This might as wel be a one off  experiment on a breadboard with a processor he found in his junk box.

 

OP is giving us a very small amount of info which keeps us guessing.

Up untill now he still hasn't told us the basics such as what hardware he wants to control.

He also hasn't given feedback about the toggle versus set/clear of a bit.

You have asked the OP yourself why he isn't answering questions.

But I don't want to fight with you, I'm just trying to get a glimp at the OP's mindset to try to give him some ideas he can use.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Paulvdh wrote:
Personally is quite dislike the whole tiny series. They just tend to make life for programmers harder for a small benefit of a lower price.

 

+1 from a hobbyist or educational perspective. Unless it's for the challenge in itself. (I remember Jesper once did something with a tiny "just to see what he could cram out of it").

 

If you have manufacturing runs of many Ks or even Ms of devices the difference kicks in, I guess.

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Thu. Jul 20, 2017 - 09:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Johan

That's exactly what my rant in the other post (Link in #34 is about).

Because of your +1 I just upvoted my own #34 post :)

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Thu. Jul 20, 2017 - 11:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

from this :

 

http://www.avrfreaks.net/forum/attiny26-debugging

 

I guess that OP have moved on to a tiny261.