Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
dwb240
PostPosted: Oct 04, 2002 - 02:07 PM
Newbie


Joined: Mar 05, 2004
Posts: 0


Hi,

You can either just make a macro that uses ASM code, or just do this:

PORTB = PORTB | (1 << 4);

this would set PORTB's bit 4. It OR's the current contents of the PORTB output register with 1 shifted left 4 bits.

I'm not sure, but I assume that the C compiler will take that an optimize it so that it uses the SBR and CBR when possible so it reduces to one or two lines of ASM.

-Colin
 
 View user's profile Send private message  
Reply with quote Back to top
eltrevisor
PostPosted: Oct 04, 2002 - 02:30 PM
Newbie


Joined: Jun 14, 2002
Posts: 1


Hello Nicokiller,

I use Codevision AVR-C-Compiler (simple the best, kind regards to Pavel Haiduc). There I can write


PORTB.2 = 0;

to clear bit 0 of port B. You can also write:

dummybit = PORTC.3;

This assigns the pin level of port C, bit 3 to the variable dummybit.

Try it, I think it works on the IAR compiler too


Many greetings

Rainer
 
 View user's profile Send private message  
Reply with quote Back to top
GraemeDay (Graeme Day)
PostPosted: Oct 04, 2002 - 03:07 PM






Hi,

Try defining the bits first, it makes working with them easier.

#define BIT0 0b00000001;
#define BIT1 0b00000010;
#define BIT2 0b00000100; etc....

Then to set bit 2 you can say: PORTB = PORTB (or'ed with) 0b00000100
in ICCAVR you would write: PORTB |= BIT2;

To clear bit2 you can say: PORTB = PORTB (and with) 0b11111011
in ICC you would write: PORTB &= ~BIT2; ( The tild symbol means invert)

Hope I'm right.
Graeme
 
   
Reply with quote Back to top
geneo
PostPosted: Oct 04, 2002 - 04:11 PM
Rookie


Joined: Jun 01, 2001
Posts: 32
Location: Olney, Maryland

I use macros to simplify bit setting and I also use macros to test bits

#define BIT(x) (1 << (x))
#define SETBITS(x,y) ((x) |= (y))
#define CLEARBITS(x,y) ((x) &= (~(y)))
#define SETBIT(x,y) SETBITS((x), (BIT((y))))
#define CLEARBIT(x,y) CLEARBITS((x), (BIT((y))))
#define BITSET(x,y) ((x) & (BIT(y)))
#define BITCLEAR(x,y) !BITSET((x), (y))
#define BITSSET(x,y) (((x) & (y)) == (y))
#define BITSCLEAR(x,y) (((x) & (y)) == 0)
#define BITVAL(x,y) (((x)>>(y)) & 1)

For example, if I want to set bit 2 in portd I would simply include the followin C command:
SETBIT(PORTD,2);
 
 View user's profile Send private message  
Reply with quote Back to top
lee
PostPosted: Oct 04, 2002 - 05:26 PM
Newbie


Joined: Jun 09, 2003
Posts: 0


I agree with Richard, but be wary when extending it: Smile)

#define d 08

wouldn't work--ANSI C constants beginning with 0 are octal.

[I've been bitten by that more than once.]

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
eric
PostPosted: Oct 04, 2002 - 07:39 PM
Newbie


Joined: Oct 28, 2001
Posts: 0


Programming 101

To really understand what's going, it's best to learn C languages bit operators and about truth tables.
| bit OR
& bit AND
~ bit NOT
^ bit EXLUSIVE OR (XOR)
<< bit LEFT SHIFT
>> bit RIGHT SHIFT

These operators work on bits and not logical values. Take two 8 bit bytes, combine with any of these operators, and you will get another 8 bit byte according to the operator's function. These operators work on the individual bits inside the byte.

A truth Ttble helps to explain each operation. In a truth table, a 1 bit stands for true, and a 0 stands for false.

The OR operation truth table:
0 OR 0 = 0
0 OR 1 = 1
1 OR 0 = 1
1 OR 1 = 1

The AND operation truth table:
0 AND 0 = 0
0 AND 1 = 0
1 AND 0 = 0
1 AND 1 = 1

The XOR operation truth table:
0 XOR 0 = 0
0 XOR 1 = 1
1 XOR 0 = 1
1 XOR 1 = 0

The NOT operator inverts the sense of the bit, so a 1 becomes a 0, and a 0 becomes a 1.

So let's say I have a byte foo that is initialized to 0:
unsigned char foo = 0;

To set bit 0 in foo and then store the result back into foo:

foo = foo | 0x01;

The OR operation is used between the variable that we want to change and a constant which is called a BIT MASK or simply the MASK. The mask is used to identify the bit that we want changed.

Remember that we write the constants in hexadecimal because it's shorter than writing it in binary. It is assumed that the reader knows how to convert back and forth between hex and binary. ;-)

Usually, though the statement is made shorter in real programming practice to take advantage of C's compound assignment:

foo |= 0x01;

This is equivalent to the statement above.

To clear bit 0 in foo requires 2 bit operators:

foo = foo & ~0x01;

This uses the AND operator and the NOT operator. Why do we use the NOT operator? Most programmers find it easier to specify a mask wherein the bit that they are interested in changing, is set. However, this kind of mask can only be used in setting a bit (using the OR operator). To clear a bit, the mask must be inverted and then ANDed with the variable in question. It is up to the reader to do the math to show why this works in clearing the desired bit.

Again, the statement is made shorter with a compound assignment:

foo &= ~0x01;

To see if a bit is set or clear just requires the AND operator, but with no assignment. To see if bit 7 is set in the variable foo:

if(foo & 0x80)
{
}

The condition will be zero if the bit is clear, and the condition will be non-zero if the bit is set. NOTE! The condition will be NON-ZERO when the bit is set. But the condition will not NECESSARILY BE ONE. It is left to the reader to calculate the value of the condition to understand why this is the case.


There is another useful tool that is not often seen, and that is when you want to flip a bit, but you don't know and you don't care what state the bit is currently in. Then you would use the XOR operator:

foo = foo ^ 0x01;

Or the shorter statement:

foo ^= 0x01;

A lot of times the bit mask is built up dynamically in other statements and stored in a variable to be used in the assignment statement:

foo |= bar;

Sometimes, a programmer wants to specify the bit NUMBER that they want to change and not the bit MASK. The bit number always starts at 0 and increases by 1 for each bit. An 8 bit byte has bit numbers 0-7 inclusive. The way to build a bit mask with only a bit number is to LEFT SHIFT a bit by the bit number. To build a bit mask that has bit number 2 set:

(0x01 << 2)

To build a bit mask that has bit number 7 set:

(0x01 << 7)

To build a bit mask that has bit number 0 set:

(0x01 << 0)

Which ends up shifting the constant 0 bytes to the left, leaving it at 0x01.


MACROS

Because there are a number of programmers who don't seem to have a familiarity with bit flipping (because they weren't taught it at school, or they don't need to know it because of working on PCs), most programmers usually write macros for all of these operations. Also, it provides a fast way of understanding what is happening when reading the code, or it provides additional functionality.

Below is a set of macros that works with ANSI C to do bit operations:

#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0x01 << (x))
#define LONGBIT(x) ((unsigned long)0x00000001 << (x))


To set a bit:
bit_set(foo, 0x01);

To set bit number 5:
bit_set(foo, BIT(5));

To clear bit number 6 with a bit mask:
bit_clear(foo, 0x40);

To flip bit number 0:
bit_flip(foo, BIT(0));

To check bit number 3:
if(bit_get(foo, BIT(3)))
{
}

To set or clear a bit based on bit number 4:
if(bit_get(foo, BIT(4)))
{
bit_set(bar, BIT(0));
}
else
{
bit_clear(bar, BIT(0));
}


To do it with a macro:
bit_write(bit_get(foo, BIT(4)), bar, BIT(0));

If you are using an unsigned long (32 bit) variable foo, and have to change a bit, use the macro LONGBIT which creates un unsigned long mask. Otherwise, using the BIT() macro, the compiler will truncate the value to 16-bits.

Any questions?

Eric
 
 View user's profile Send private message  
Reply with quote Back to top
eric
PostPosted: Oct 04, 2002 - 08:07 PM
Newbie


Joined: Oct 28, 2001
Posts: 0


In addition

To do multiple bits at a time requires the use of a mask. To set bits 2 and 3 at the same time:

foo |= 0x0C;

or with the macros:

bit_set(foo, 0x0C);

Now, there are a number of people who can't quickly figure out that 0x0C corresponds to having only bits 2 and 3 set and the other bits clear. So using the BIT() macro, you can create the equivalent mask. Note that the BIT macro only works on a single bit, so you write a compound statement to create the mask:

bit_set(foo, BIT(2) | BIT(3));

This can be used with the other macros as well:

bit_clear(foo, BIT(2) | BIT(3));
bit_flip(foo, BIT(2) | BIT(3));
if(bit_get(foo, BIT(2) | BIT(3)))
{
}

And, it doesn't matter what order they are specified:

bit_set(foo, BIT(7) | BIT(0) | BIT(3));

And it shouldn't matter if it is a variable or a memory-mapped register:

bit_set(DDRB, BIT(0));
bit_set(PORTB, BIT(0));

Caveat: As long as the port definitions are defined correctly, which with all of the compilers that I know of that are discussed here, it is.

Eric
 
 View user's profile Send private message  
Reply with quote Back to top
eric
PostPosted: Oct 04, 2002 - 11:21 PM
Newbie


Joined: Oct 28, 2001
Posts: 0


Permission granted. Anybody can use those or create their own.

Eric
 
 View user's profile Send private message  
Reply with quote Back to top
sutton
PostPosted: Oct 05, 2002 - 12:40 PM
Posting Freak


Joined: Oct 30, 2001
Posts: 1563
Location: Manchester England

Eric
A question about
#define LONGBIT(x) ((unsigned long)0x00000001 << (x))

Would 1 have done instead of 0x00000001
Regards
Mike

_________________
Keep it simple it will not bite as hard
 
 View user's profile Send private message  
Reply with quote Back to top
myname
PostPosted: Oct 06, 2002 - 02:05 AM






Mike--

Not necessarily. Depending on items to the left, the phase of the Moon, and current offerings to the gods of C, "1" might be treated as an "int" constant, which is often (usually?) 16 bits on microprocessors.

A constant can be "tagged" as long by "1L".

Sometimes even the casting can fool you in complex expressions. I tend to use lots of parentheses when casting so I know next month what I intended to cast.

Lee
 
   
Reply with quote Back to top
krebs (Jakob Krebs)
PostPosted: Oct 14, 2003 - 04:08 PM






Hi,


I like the idea of these Macros, but why does this not work ??


if (bit_get(PORTA, BIT(7)))
{
bit_set(PORTB, BIT(0));
}
else
{
bit_clear(PORTB, BIT(0));
}


This works fine:

if ((PINA & (1 << 7)) != 0)
{
bit_set(PORTB, BIT(0));
}
else
{
bit_clear(PORTB, BIT(0));
}


Hope to get some help.........

Jakob
 
   
Reply with quote Back to top
lee
PostPosted: Oct 14, 2003 - 05:38 PM
Newbie


Joined: Jun 09, 2003
Posts: 0


Shouldn't you be doing a bit_get() on PINA instead of PORTA?

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
uprinz
PostPosted: Apr 14, 2004 - 09:50 PM
Rookie


Joined: Sep 05, 2001
Posts: 25
Location: Germany

May Thanks to Eric for that explanation on using macros for the bits. Makes code reading much more eazier. But I wonder if it possible to make it more eazier....

I have a pieve of software running on several board releases. So there are little differences in the port an bit definitions for one function pin.

Example: I hava an ON/OFF button called TEIN in my software. It is defined as
Code:

#define TEIN_P PORTA
#define TEIN_B 3

main()
{
  if (GETBIT(TEIN_P,TEIN_B)
  {
    do something
  }
}


Now there is the question: How could it be made more simple?
I tried
Code:

#define TEIN  PORTA,3

....
if GETBIT(TEIN)
....

Compiler Error

Is there a way to shorten that bit definitions to one line per bit?
Is it possible to #define an array of constants that should be passed to another macro?

Where is a brief documentation on that mega powerfull compiler that could be read and understood without going off business for a year?

Thanks in advance and best regards to all that people in here

Ulrich
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Apr 14, 2004 - 10:27 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Remember that on AVRs you [usually] want to read or do a getbit() on PINA, not PORTA.

The CodeVision compiler already uses direct syntax such as:
Code:

if (PINA.3)
  {
  }



Eric can clean up on this, but I believe he will say something that getbit() macro and its friends have been deprecated in favor of a direct syntax.

If this is indeed a gcc question, the experts on that Forum can probably give better answers.

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
EW
PostPosted: Apr 14, 2004 - 11:57 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

Sheesh, why dig up an old thread?......

Ok first off, for the AVR GCC compiler (and avr-libc C library), the macros: outp, inp, outb, inb, are all deprecated. These were holdovers from a Linux-type implementation that had no bearing on this type of embedded environment.

That means that "direct access" or "direct assignment", or whatever you want to call it, is the preferred method for assigning values to registers. This method is the most common method used to assign values to memory-mapped registers in embedded compilers, commercial or otherwise.

The Codevision compiler has another way of assigning bits in a register that is not Standard C syntax. But you can still use Standard C syntax with it too, and that is by using the bit-wise operators and compound assignment operators to do bit manipulation. See above in my "Programming 101" post.

Therefore if you write your C code in Standard C syntax, it becomes portable across multiple compilers. Which may, or may not, be something you care about.

Those additional macros that I mentioned in that "Programming 101" post, just make the Standard C syntax easier to read, especially for you newbies that can't tell at a glance what

Code:
PORTD ^= 0x5A;


is doing. Wink

Now, you should look at your C Preprocessor manual for why it is difficult to "shorten" those macros to something like

Code:
#define TEIN  PORTA,3


If you're using the GCC toolset, look at the CPP manual in the GCC docs.

There is also another reason why you don't want to shorten them, and that is so you can simultaneously operate on multiple, non-contiguous bits. Think about that for a moment. Someday you may want to do something like:

Code:
#define BIT(x)   (1 << (x))
#define bit_flip(v, m)   ((v) ^= (m))

bit_flip(PORTD, (BIT(4) | BIT(3) | BIT(6) | BIT(1)));


And you can't do that in Codevision's non-standard syntax.


Last edited by EW on Apr 15, 2004 - 04:28 PM; edited 1 time in total
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
ka7ehk
PostPosted: Apr 15, 2004 - 12:12 AM
10k+ Postman


Joined: Nov 22, 2002
Posts: 14060
Location: Tangent, OR, USA

There is a big difference between "shortening" your C code and reducing the resulting assembler instructions. One does not necessarily follow the other, and, in fact, sometimes the opposite occurs.

Jim
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Apr 15, 2004 - 03:07 AM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Sorry, EW, I thought it was getbit() that was somewhat passe.

I can't argue over the portability issue. I suspect, though, that there WILL be differences between architectures and even AVR compilers on exactly what is a sfrb/sfrw. In thinking, all I/O instructions would need to be examined within a platform-dependent layer--even using the portable syntax, the bits to control Timer3 may be vastly different from TCCR3's definition.

I also find that apps up to the '4433/Mega8 size usually need to be pretty well carefully crafted to fit-in desired features, and even the modest increment of a separate layer is a luxury. YMMV.

Anyway, you can ALMOST Smile do what you posted, with one more paren.

Code:

         ;     124 #define BIT(x)   (1 << (x))
         ;     125 #define bit_flip(v, m)   ((v) ^= (m))
         ;     126
         ;     127 bit_flip(PORTD, (BIT(4) | BIT(3) | BIT(6) | BIT(1)));
00006a b3e2         IN   R30,0x12
00006b e5aa         LDI  R26,LOW(90)
00006c 27ea         EOR  R30,R26
00006d bbe2         OUT  0x12,R30


so even lowly CodeVision users may follow the straight-and-narrow path.

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
EW
PostPosted: Apr 15, 2004 - 04:36 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

theusch wrote:
Sorry, EW, I thought it was getbit() that was somewhat passe.


Hi, Lee. BTW, EW = Eric Weddington, who wrote the "Programming 101" post.

theusch wrote:
I can't argue over the portability issue. I suspect, though, that there WILL be differences between architectures and even AVR compilers on exactly what is a sfrb/sfrw. In thinking, all I/O instructions would need to be examined within a platform-dependent layer--even using the portable syntax, the bits to control Timer3 may be vastly different from TCCR3's definition.


You'll have to explain this one a bit more. The acronym SFRB = Special Function Register Byte (with the W = Word). What is there to argue about what it is? It's a memory-mapped register (8 or 16 bits wide).

theusch wrote:
I also find that apps up to the '4433/Mega8 size usually need to be pretty well carefully crafted to fit-in desired features, and even the modest increment of a separate layer is a luxury.


Agreed, but I thought that we're talking about preprocessor macros which don't add any extra layer of assembly.

theusch wrote:
Anyway, you can ALMOST Smile do what you posted, with one more paren.


Ah, thanks for catching that. I've edited my previous post above to show that.

theusch wrote:
so even lowly CodeVision users may follow the straight-and-narrow path.


Well that's why I mentioned that only if one is interested in compiler portability, then it's useful. If all you're ever going to use is CV, and you don't care about being able to operate on multiple, non-continguous bits, go ahead and knock yourself out. Wink
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
theusch
PostPosted: Apr 15, 2004 - 06:10 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Quote:
Hi, Lee. BTW, EW = Eric Weddington, who wrote the "Programming 101" post.


I knew that, but was too lazy to look up whether it was Eric or Erik so I copped out.

Quote:
Ah, thanks for catching that. I've edited my previous post above to show that.


Yes, the two-edged sword of editing posts--it makes my response look like an idiot. But I'm used to that. [Hmmm--I can call someone a malingering SOB, then edit it out after it's had the proper effect and claim it never happened--like subliminal advertising or many current politicians or "1984".]

Quote:
... and you don't care about being able to operate on multiple, non-continguous bits, go ahead and knock yourself out.


I posted that you could operate the same way on CV, as well as direct addressing. Actually, for I/O bits I do use one level of abstaction that helps me to cope with hardware pin assignment changes, along with active high/active low issues, as well as remembering what is assigned to what. Fragment:
Code:

#define   OUT_BACKLITE      PORTB.7
#define   OUT_COMPRESSOR      PORTB.4
#define   OUT_AUGER         PORTB.3
// Active high
#define   OUTPUT_ON         1
#define   OUTPUT_OFF         0


so that I only need to go to one spot to reconfigure.

Quote:
You'll have to explain this one a bit more.


Let's take an AVR timer as an example. To stop/disable an active timer, you write 0 to a variable number of pre-scaler selection bits in TCCRx. On an '8051 or MSP403 or Moto '08 there is probably going to be a completely different mechanism to enable/disable a timer.

So as long as I have my timer_on() and timer_off() macros or functions in one spot (like alongside the pin assignment fragment above), it doesn't matter >>what<< syntax I use within that macro--it has to be changed anyway when porting--it >>is<< platform-dependent.

Take care. Thanks for your efforts.

Lee
 
 View user's profile Send private message  
Reply with quote Back to top
EW
PostPosted: Apr 16, 2004 - 04:31 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

theusch wrote:

Yes, the two-edged sword of editing posts--it makes my response look like an idiot. But I'm used to that. [Hmmm--I can call someone a malingering SOB, then edit it out after it's had the proper effect and claim it never happened--like subliminal advertising or many current politicians or "1984".]


Laughing

theusch wrote:
I posted that you could operate the same way on CV, as well as direct addressing. Actually, for I/O bits I do use one level of abstaction that helps me to cope with hardware pin assignment changes, along with active high/active low issues, as well as remembering what is assigned to what. Fragment:
Code:

#define   OUT_BACKLITE      PORTB.7
#define   OUT_COMPRESSOR      PORTB.4
#define   OUT_AUGER         PORTB.3
// Active high
#define   OUTPUT_ON         1
#define   OUTPUT_OFF         0


so that I only need to go to one spot to reconfigure.

Quote:
You'll have to explain this one a bit more.


Let's take an AVR timer as an example. To stop/disable an active timer, you write 0 to a variable number of pre-scaler selection bits in TCCRx. On an '8051 or MSP403 or Moto '08 there is probably going to be a completely different mechanism to enable/disable a timer.

So as long as I have my timer_on() and timer_off() macros or functions in one spot (like alongside the pin assignment fragment above), it doesn't matter >>what<< syntax I use within that macro--it has to be changed anyway when porting--it >>is<< platform-dependent.

Take care. Thanks for your efforts.

Lee



Oh I totally agree. Having another layer of "abstraction" via macros definitely helps both with portability (whether target or compiler) as well as maintainability / readability.

Eric
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Bingo600
PostPosted: Sep 07, 2004 - 06:48 PM
Raving lunatic


Joined: Apr 25, 2004
Posts: 3943
Location: Denmark

Is this one "Worthy" to get into the "Bit-Macro" library Question

#define GET_BITS(num, from, to) (((num) >> (from)) & ((0x1 << ((to) - (from) + 1)) - 1))

/Bingo
 
 View user's profile Send private message  
Reply with quote Back to top
EW
PostPosted: Sep 07, 2004 - 07:34 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

Ultimately, it's totally up to you. There is no central library for these macros. Well at least not yet.

Um, it would also help if you had a description of what this is supposed to do....
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Bingo600
PostPosted: Sep 07, 2004 - 07:50 PM
Raving lunatic


Joined: Apr 25, 2004
Posts: 3943
Location: Denmark

Uhmm
Description Embarassed

It is supposed to return the bits in the range from .. to , from the parameter num.

so GETBITS(uint16_t <Parameter>,10,14) should return bit 10 to 14 of Parameter

/Bingo
 
 View user's profile Send private message  
Reply with quote Back to top
Butch
PostPosted: Sep 07, 2004 - 09:05 PM
Newbie


Joined: Sep 07, 2004
Posts: 3


I am also looking to set and clear I/O port bits
I have read the design note #008 “Efficient I/O handling with bitfields” but am unable to get it working. I am running IAR 3.10C for the Mega 64 and when I compile, with the example code, I get the error “pe029 expected an expression “ pointing at LED1 = 0; Why?
My goal is to manipulate a single bit of an I/O port with out having to read the port, mask it and rewrite the port. App note #008 would be a nice way if it works, if not, is there another way? I am not to concerned with portability as this is a one time project for a product already past mature.

Butch
 
 View user's profile Send private message  
Reply with quote Back to top
EW
PostPosted: Sep 07, 2004 - 09:10 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

Bingo600 wrote:
Uhmm
Description Embarassed

It is supposed to return the bits in the range from .. to , from the parameter num.

so GETBITS(uint16_t <Parameter>,10,14) should return bit 10 to 14 of Parameter



Ok.
Except that this macro shifts the resulting bits to the right.

Code:

#define GET_BITS(num, from, to) (((num) >> (from)) & ((0x1 << ((to) - (from) + 1)) - 1))


I would implement it as something like:
Code:

#define bits_read(v, s, f)     ((v) & ((~(0xFFFF << ((f) - (s)))) << (s)))


Hopefully I've gotten all the parentheses correct. Laughing (What is this? LISP?!) Parameters: v = variable to read, s = start bit number, f = finish bit number.

This implementation reads multiple, contiguous bits but leaves them in their original positions. Oh and it has one less operator than the other macro. Note that this is only good on 8 or 16 bit values and that the result would more than likely be an int (it's up to C's promotion rules). One would have to make a seperate 32-bit macro using 0xFFFFFFFF as the constant.

Oh, and yes, I've actually written and used something like this before. Very Happy
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
EW
PostPosted: Sep 07, 2004 - 09:11 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

Butch wrote:
I am also looking to set and clear I/O port bits
I have read the design note #008 “Efficient I/O handling with bitfields” but am unable to get it working. I am running IAR 3.10C for the Mega 64 and when I compile, with the example code, I get the error “pe029 expected an expression “ pointing at LED1 = 0; Why?
My goal is to manipulate a single bit of an I/O port with out having to read the port, mask it and rewrite the port. App note #008 would be a nice way if it works, if not, is there another way? I am not to concerned with portability as this is a one time project for a product already past mature.

Butch


I would suggest either re-reading this thread, or start a new topic.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
Bingo600
PostPosted: Sep 07, 2004 - 10:19 PM
Raving lunatic


Joined: Apr 25, 2004
Posts: 3943
Location: Denmark

He..He

Eric you are a living preprocessor Laughing Laughing

It was my intention to shift the result to the right , i was using it to get bitvalues (numbers) embedded within an Int.

/Bingo
 
 View user's profile Send private message  
Reply with quote Back to top
EW
PostPosted: Sep 07, 2004 - 10:59 PM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

Bingo600 wrote:

Eric you are a living preprocessor Laughing Laughing


Thanks, but I am by no means an expert with the preprocessor.

Bingo600 wrote:

It was my intention to shift the result to the right , i was using it to get bitvalues (numbers) embedded within an Int.


Oh, well that makes sense then.
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
tomasch
PostPosted: Dec 13, 2004 - 07:43 PM
Wannabe


Joined: Jun 23, 2003
Posts: 76


Please add Eric's excellent discription of Bit operations to the Docs and example code - or at least make it sticky to the forum - I'ts excellent and answers a million of the "How do I (Check, Set, Clear, Flip) a Bit - including my own questions - and I have been programming for 20 years!

Thanks Eric - very much

Tom
 
 View user's profile Send private message  
Reply with quote Back to top
Mazaag
PostPosted: Aug 29, 2007 - 10:21 PM
Newbie


Joined: Aug 17, 2007
Posts: 7


geneo wrote:
I use macros to simplify bit setting and I also use macros to test bits

#define BIT(x) (1 << (x))
#define SETBITS(x,y) ((x) |= (y))
#define CLEARBITS(x,y) ((x) &= (~(y)))
#define SETBIT(x,y) SETBITS((x), (BIT((y))))
#define CLEARBIT(x,y) CLEARBITS((x), (BIT((y))))
#define BITSET(x,y) ((x) & (BIT(y)))
#define BITCLEAR(x,y) !BITSET((x), (y))
#define BITSSET(x,y) (((x) & (y)) == (y))
#define BITSCLEAR(x,y) (((x) & (y)) == 0)
#define BITVAL(x,y) (((x)>>(y)) & 1)

For example, if I want to set bit 2 in portd I would simply include the followin C command:
SETBIT(PORTD,2);



Why is it that when I include these macros in a .h file , the code doesn't compile, however, if i copy it to the program itself it runs fine ?

I have a modifiedio.h file which I add stuff that I frequently use into, and I wanted to add these macros too so I could use them without having to define them all thet time...

How could I do that ?

Thanks guys
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 29, 2007 - 10:37 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 22204
Location: Lund, Sweden

Quote:

Why is it that when I include these macros in a .h file , the code doesn't compile

Why is it that you neither don't copy the actual error message(s), nor quote any "code snippets", into your post so that we get a fair chance of giving a good answer? Wink

Also, did you notice that you revived a thread that has been silent for almost three years?
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Mazaag
PostPosted: Aug 29, 2007 - 10:41 PM
Newbie


Joined: Aug 17, 2007
Posts: 7


I copy pasted the same exact lines quoted above into my modifiedio.h file...
Code:
/* Bit Operations */
#define BIT(x)          (1 << (x))
#define SETBITS(x,y)    ((x) |= (y))
#define CLEARBITS(x,y)    ((x) &= (~(y)))
#define SETBIT(x,y)    SETBITS((x), (BIT((y))))         /* EXAMPLE SETBIT(PORTB,2) sets the 2 bit of PORTB */
#define CLEARBIT(x,y)    CLEARBITS((x), (BIT((y))))
#define BITSET(x,y)    ((x) & (BIT(y)))
#define BITCLEAR(x,y)    !BITSET((x), (y))
#define BITSSET(x,y)    (((x) & (y)) == (y))
#define BITSCLEAR(x,y)    (((x) & (y)) == 0)
#define BITVAL(x,y)    (((x)>>(y)) & 1)



then..in my actual program , i include my modifiedio.h as i always do...



then when i try to use SETBIT.. I get the following error :

undefined reference to `SETBIT'
undefined reference to `SETBIT'
undefined reference to `SETBIT'
Code:
#include <avr/modifiedio.h>

int main(void)
{

   
   DDRB = 0xFF;     /* Set PORTB as Output */
   DDRD = 0 ;      /* Set PORTD as Input  */

   int READ_BIT = 0 ;   /* READ is bit 0 of Output Port */
   int WRITE_BIT = 1 ;   /* WRITE is bit 1 of Output Port */
   int INTR_BIT = 2 ;   /* INTR is bit 2 of Ouput Port */
      
   while(1)   
   {
      SETBIT(PORTB,READ_BIT) ;
      SETBIT(PORTB,WRITE_BIT) ;
      SETBIT(PORTB,INTR_BIT) ;
   
   }

}
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Aug 29, 2007 - 11:24 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 22204
Location: Lund, Sweden

OK, my bet is that you have multiple instances of modifiedio.h on your system and that you edited one but anotherone is included.

Tip:

Temporarily rename the modifiedio.h that you edited to another name. Then do a build. You should get en error message saying something to the effect that the header file could not be found. If you do not get this error message then the file you renamed is not the file that got included. Go hunt the duplicate!

Another way to detect this situation is to deliberately edit in something that will guarantee a compilation error in modifiedio.h, say a erroneous function prototype
Code:
void BadFunc(void;

Notice the missing closing parenthesis. Now if you build and do not get one or several error messages pertaining to the code above then the file you are editing is not the file that is being included. Go hunt...
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Mazaag
PostPosted: Aug 30, 2007 - 12:29 AM
Newbie


Joined: Aug 17, 2007
Posts: 7


In AVR studio, how do I set the directory where the compiler will look for the #include files ?
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Sep 04, 2007 - 10:56 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 22204
Location: Lund, Sweden

In Project menu, Configuration Options, Include Directories.

If you actually have placed your modifiedio.h in WinAVR-installation-root-dir\avr\include\avr then your include directive should work without adding any include path in Studio.

IMO, placing the file there is a bad idea though: You risk loosing the file if you reinstall or update the WinAVR installation. Generally speaking the installation trees of any toolchain should be kept clean of user-supplied files.

Better to create a directory outside of the WinAVR installation directory, place the file there and point to it by adding the path to the project settings in Studio. You'd have to add this path to every new Studio project if I understand things correctly.

Alternatively you could copy the file to the directory where the specific project has it's souce files, and do an
Code:
#include "modifiedio.h"

with "quotes" rather than <angle brackets>. This #include variant looks in the current directory before searching the "system include" directories for the header file. The drawback here is that you will end up with many copies of the file, and you'd have to update them all when you fix a bug or add/improve functionality.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
EW
PostPosted: Sep 05, 2007 - 09:31 AM
Raving lunatic


Joined: Mar 01, 2001
Posts: 5013
Location: Rocky Mountains

Please start a new thread when asking completely different questions.

Although its nice to see that the "Programming 101" thread refuses to die. Wink
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
cfavreau
PostPosted: Jan 14, 2008 - 05:55 AM
Newbie


Joined: Jan 14, 2008
Posts: 1


Originally for ATMega162 ... need to modify for other AVR's....

// Bit Field Conversion for PORT Access
typedef struct
{
unsigned bit0:1;
unsigned bit1:1;
unsigned bit2:1;
unsigned bit3:1;
unsigned bit4:1;
unsigned bit5:1;
unsigned bit6:1;
unsigned bit7:1;
} BYTE_BITFIELD;

// Data Direction
#define ddra (*((volatile BYTE_BITFIELD*)(&DDRA)))
#define ddrb (*((volatile BYTE_BITFIELD*)(&DDRB)))
#define ddrc (*((volatile BYTE_BITFIELD*)(&DDRC)))
#define ddrd (*((volatile BYTE_BITFIELD*)(&DDRD)))

// Output Port
#define porta (*((volatile BYTE_BITFIELD*)(&PORTA)))
#define portb (*((volatile BYTE_BITFIELD*)(&PORTB)))
#define portc (*((volatile BYTE_BITFIELD*)(&PORTC)))
#define portd (*((volatile BYTE_BITFIELD*)(&PORTD)))

// Input Port
#define pina (*((volatile BYTE_BITFIELD*)(&PINA)))
#define pinb (*((volatile BYTE_BITFIELD*)(&PINB)))
#define pinc (*((volatile BYTE_BITFIELD*)(&PINC)))
#define pind (*((volatile BYTE_BITFIELD*)(&PIND)))

Now you can just use:

porta.bit1 = 0

You can use them like a structure object.

Have fun.
 
 View user's profile Send private message  
Reply with quote Back to top
kmr
PostPosted: Jan 14, 2008 - 08:24 AM
Raving lunatic


Joined: Apr 01, 2004
Posts: 3812
Location: New Mexico

cfavreau: that code should compile efficiently in my previous testing on GCC and IAR. However, because of Imagecraft. When I checked last month, it's compiler did not create efficient code for bit fields like you are using. I sent an email to Imagecraft illustrating this can be an area they can work on optimizing.

_________________
Kevin Rosenberg
http://b9.com
http://kevin.hypershots.com
 
 View user's profile Send private message Send e-mail Visit poster's website 
Reply with quote Back to top
kaomoneus
PostPosted: Mar 07, 2010 - 09:04 PM
Newbie


Joined: Mar 06, 2010
Posts: 4


For IO registers with address less than 0x20 u can use this macros:
Code:
#define SBI(port, bit) \
    asm volatile("sbi [percent]0, [percent]1" \
        : \
        : "I" (_SFR_IO_ADDR(port)), "I" (bit))

#define CBI(port, bit) \
    asm volatile("cbi [percent]0, [percent]1" \
        : \
        : "I" (_SFR_IO_ADDR(port)), "I" (bit))


For all other IO registers use classic set/clear bit macros. There are a lot of them (see above). I use this ones:
Code:

#define SETBIT(reg, bit) reg |= 1 << bit
#define CLRBIT(reg, bit) reg &= ~(1 << bit)


P.S.:
[Percent] - is a '%' charater. AVRFreaks forum engine fails to process posts with [percent][digit] constructions.
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Mar 07, 2010 - 09:26 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15094
Location: Vancouver, BC

The original post was nearly 8 years ago. The previous post was over two years ago. And with avr-gcc your second set of macros are all you need, they will use SBI or CBI if they can.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
kaomoneus
PostPosted: Mar 08, 2010 - 11:33 AM
Newbie


Joined: Mar 06, 2010
Posts: 4


You right. But if I write small projects I prefer -O0. In this case SETBIT produces a lot of instructions. If -O2 is set SETBIT really produces single SBI instruction.

About old posts. I founded this thread yesterday, and I was surprised that there is nothing about SBI/CBI macros. I think, that some threads helps me and now I know about SBI and CBI, and know may be I can help another people too. After all this thoughts I registered and write my post Smile
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 08, 2010 - 11:42 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71717
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

But if I write small projects I prefer -O0.

Apart from temporary use for debugging what possible advantage can -O0 possibly have?

At other optimisation levels the compiler will recognise when SBI/CBI can be used and just make use of them automatically which is one of the many reasons to use the optimiser. You don't need to do anything "special":
Code:
PORTB |= (1<<PB6);

will simply generate:
Code:
SBI PORTB, 6

as long as PORTB lies in 0x00..0x1F range.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
kaomoneus
PostPosted: Mar 08, 2010 - 02:14 PM
Newbie


Joined: Mar 06, 2010
Posts: 4


Active delays, for example, are optimized to nothing. And sometimes, when u write asm-like code, optimization should be turned off to avoid some unwanted conversions.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 08, 2010 - 02:19 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71717
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

Active delays, for example, are optimized to nothing.

Which is why <util/delay.h> has been provided to deliberately not be discarded by the optimiser (in fact it requires the optimiser to be enabled for correct operation)
Quote:

sometimes, when u write asm-like code, optimization should be turned off to avoid some unwanted conversions.

What "unwanted conversions"? Are you talking about code sequence rearrangement when using inline Asm?

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Mar 08, 2010 - 05:26 PM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15094
Location: Vancouver, BC

Quote:
But if I write small projects I prefer -O0.

Then you are obviously unconcerned with the size of the program in that case, so why bother doing hand optimization?
Quote:
and I was surprised that there is nothing about SBI/CBI macros.

But those macros are no longer necessary and were deprecated long ago.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
kaomoneus
PostPosted: Mar 08, 2010 - 07:39 PM
Newbie


Joined: Mar 06, 2010
Posts: 4


I just can say that sometimes man thinks better than optimizer.
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: Mar 08, 2010 - 08:58 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Quote:

I just can say that sometimes man thinks better than optimizer.


I can just claim that often the optimizer "thinks" better than the average man.

But if you cripple your infinite-value compiler brand with -O0 then I can see why you feel you are the superior coder.
 
 View user's profile Send private message  
Reply with quote Back to top
Boone
PostPosted: Apr 23, 2011 - 03:41 AM
Newbie


Joined: Oct 02, 2006
Posts: 2


kaomoneus, thanks for providing your scripts. I spent the last few hours debugging some code, it turned out that because it was compiled with -O0 sbi wasn't used when I cleared an interrupt flag.

If both OCF3A and OCF3B are set in TIFR3, when you go to clear OCF3A with the code "TIFR3 |= _BV(OCF3A)" you end up also clearing the OCF3B interrupt.

Pity that different optimization levels result in code that actually functions fundamentally differently. I normally compile with -O2, but often use -O0 if I need to debug anything line-by-line.
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Apr 23, 2011 - 04:52 AM
10k+ Postman


Joined: Nov 17, 2004
Posts: 15094
Location: Vancouver, BC

You should never use "|=" with TIFR registers, always use "=". With "|=" you always run the risk of having the problem that you had. With "=" it will always clear only the flag that you want to clear.
Code:
TIFR3 = _BV(OCF3A);

Besides, sometimes the flag registers have addresses that can't use SBI.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
Boone
PostPosted: Apr 23, 2011 - 10:08 AM
Newbie


Joined: Oct 02, 2006
Posts: 2


Koshchi wrote:
You should never use "|=" with TIFR registers, always use "=". With "|=" you always run the risk of having the problem that you had. With "=" it will always clear only the flag that you want to clear.


I have to humbly admit I never clued into the fact that the TIFR registers are only made up of interrupt flags so that using = instead of |= is completely reasonable. Thanks for that!
 
 View user's profile Send private message  
Reply with quote Back to top
meysam1987
PostPosted: May 06, 2014 - 07:01 PM
Newbie


Joined: Apr 27, 2014
Posts: 3


Hi there,
I wrote code in codevision like this:
PORTC.0=PINB.7;
PORTC.1=PINB.6;
PORTC.2=PINB.5;
PORTC.3=PINB.4;
PORTC.4=PINB.3;
PORTC.5=PINB.2;
PORTC.6=PINB.1;
PORTC.7=PINB.0;

Now how can I write it in atmelstudio 6 ???? Question
it's so simple in codevision but in atmelstuio 6 ...
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 06, 2014 - 07:35 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Quote:

I wrote code in codevision like this:
PORTC.0=PINB.7;
PORTC.1=PINB.6;
PORTC.2=PINB.5;
PORTC.3=PINB.4;
PORTC.4=PINB.3;
PORTC.5=PINB.2;
PORTC.6=PINB.1;
PORTC.7=PINB.0;

Now how can I write it in atmelstudio 6 ???? Question


An interesting question, given the example. There have been prior discussions about "reversing the bits in a byte", such as perhaps in your example the wiring for an 8-bit connection ended up reversed?

Prior discussions:
http://www.avrfreaks.net/index.php?name ... +bits+byte
http://www.avrfreaks.net/index.php?name ... torder=asc
http://www.avrfreaks.net/index.php?name ... torder=asc
http://www.avrfreaks.net/index.php?name ... torder=asc

...and nearly all of the above have links to others. Note that if a whole port--8 bits--you are probably better off to read PINB; do the transformation; write PORTC.

Note that CodeVision will generate SBIC/RJMP/CBI/RJMP/SBI for each bit assignment (assuming the ports involved are within range of those instructions). That is six cycles and five words per bit, or 40 words and 48 cycles for the entire byte. Compare and contrast that with the algorithms in the links above.

The naive portable AVR C version would be (for one bit):


Code:

if (PINB & (1<<PB1))
   {
   PORTC |= (1<<PC6);
   }
else
   {
   PORTC &= ~(1<<PC6);
   }

If you haven't already, read the article in the Tutorials forum with "bit manipulation" in the title.
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: May 07, 2014 - 08:18 AM
10k+ Postman


Joined: Mar 27, 2002
Posts: 22204
Location: Lund, Sweden

Quote:

it's so simple in codevision but in atmelstuio 6

Then why not stay in CodeVision, then?

Let me guess that you need to move since you have the evaluation edition of CV, and you've "hit the limit".

Moving to AVR-GCC (as in Atmel Studio) also means you move to a very stndards-compliant C compiler. The C standard does not allow for the notation that CV uses.

It is not unlikely that you in the future will thank AVR-GCC for learning you some standard and portable C. Very Happy

_________________
"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]
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
clawson
PostPosted: May 07, 2014 - 11:46 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71717
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

Now how can I write it in atmelstudio 6 ????

The way I'd do that is:
Code:
#include "sbit.h"

...

PORT_C0=PIN_B7;
PORT_C1=PIN_B6;
PORT_C2=PIN_B5;
PORT_C3=PIN_B4;
PORT_C4=PIN_B3;
PORT_C5=PIN_B2;
PORT_C6=PIN_B1;
PORT_C7=PIN_B0;

Finding sbit.h is left as an easy exercise for the reader Wink

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 07, 2014 - 02:05 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Quote:

The way I'd do that is:
Code:
#include "sbit.h"

For curiosity, I wonder what GCC considers the best sequence...
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 07, 2014 - 02:17 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Answered my own question:
Code:

   PORT_B7=PIN_C0;
  cc:   86 b1          in   r24, 0x06   ; 6
  ce:   80 fd          sbrc   r24, 0
  d0:   2f 9a          sbi   0x05, 7   ; 5
  d2:   80 ff          sbrs   r24, 0
  d4:   2f 98          cbi   0x05, 7   ; 5


It would appear that the shortest sequence would be SBIC/SBI/SBIS/CBI . But that would include a race if the pin changes in the middle. Both the CV and GCC sequences avoid the race at the expense of a word and a cycle or two.
 
 View user's profile Send private message  
Reply with quote Back to top
meysam1987
PostPosted: May 13, 2014 - 01:18 PM
Newbie


Joined: Apr 27, 2014
Posts: 3


I couldn't find my answer in that topic , they use assembly , but I want to do it in atmel studio 6 with gcc in C code...
by the way I couldn't find "sbit.h" ?
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: May 13, 2014 - 01:28 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71717
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

by the way I couldn't find "sbit.h" ?

Exactly how hard did you try? I went to Google, typed "AVR sbit.h" into the search box and the first hit was the place where it lives:

http://www.avrfreaks.net/index.php?name ... mp;t=37871

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 13, 2014 - 01:56 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Quote:

I couldn't find my answer in that topic , they use assembly ,

??? Which topic is that, that uses assembly? After all, the thread you tacked on to is about "Set bit in C".
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: May 13, 2014 - 02:37 PM
Resident


Joined: Oct 06, 2010
Posts: 925
Location: Chicago

Just out of curiosity -- how did the original poster of this thread manage to create the thread without increasing his post count (it shows up as "0 posts").
Also, where is the mythical page 4 of this thread? If I click on the page 4 link at the bottom of the page, the server reports that the topic doesn't exist...

_________________
“Science is not consensus. Science is numbers.”
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: May 13, 2014 - 02:41 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71717
Location: (using avr-gcc in) Finchingfield, Essex, England

Just one of the joys of this forum. back in 2007 (was it?) there was a database crash and a lot of "old stuff" was lost and that included some "dead" IDs. Then there's a second effect on Freaks that the page counter can never seem to go backwards. So if 40 posts are made to a thread (I'm assuming 10 posts per page) it will spill onto "page 4". If you now delete or otherwise remove 30 of the posts you still have a 4 page thread but 3 pages are blank. Eventually this will grow onto page 4 and the "problem" will be fixed.

You can generally spot a "necromancy" thread on Freaks because in the list the original author is listed in black ink meaning the ID no longer exists.

(yeah! just got it back onto page 4)

EDIT: BTW interesting to read this entire thread - look at how many times it went dormant then some necromancer resurrected it. Must be at least 5 times! These days it's kind of been surpassed by the 101 thread in Tutorial.

_________________


Last edited by clawson on May 13, 2014 - 02:44 PM; edited 1 time in total
 
 View user's profile Send private message  
Reply with quote Back to top
theusch
PostPosted: May 13, 2014 - 02:43 PM
10k+ Postman


Joined: Feb 19, 2001
Posts: 29204
Location: Wisconsin USA

Quote:

Just out of curiosity -- how did the original poster of this thread manage to create the thread without increasing his post count (it shows up as "0 posts").
Also, where is the mythical page 4 of this thread? If I click on the page 4 link at the bottom of the page, the server reports that the topic doesn't exist...

Very old threads like this can upset the forum software. there have been several "redos" over the years. Old user information from defunct users has been lost, and perhaps sometimes a defunct user might have a post in the middle of the thread which upsets the forum software.

You managed to post. Smile Perhaps like I did--click on the thread, and then "ALL"?
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: May 13, 2014 - 02:44 PM
Resident


Joined: Oct 06, 2010
Posts: 925
Location: Chicago

Interesting regarding defunct threads.

We must have hit > 30 posts, because page 4 is now functional again...

_________________
“Science is not consensus. Science is numbers.”
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: May 13, 2014 - 02:47 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71717
Location: (using avr-gcc in) Finchingfield, Essex, England

The thread index says this topis has 70 replies (now 71 when I post this). I only count (very roughly!) 64 replies in fact so it's still FUBAR Wink

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
hobbss
PostPosted: May 13, 2014 - 02:48 PM
Resident


Joined: Oct 06, 2010
Posts: 925
Location: Chicago

Given the state of the forum software, wouldn't the appropriate acronym be SNAFU?

_________________
“Science is not consensus. Science is numbers.”
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: May 13, 2014 - 02:49 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 71717
Location: (using avr-gcc in) Finchingfield, Essex, England

Yup

(I know something you don't though Wink)

(or maybe you do if you read mysterious posts in the "Change is coming" thread).

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
meysam1987
PostPosted: May 13, 2014 - 03:56 PM
Newbie


Joined: Apr 27, 2014
Posts: 3


thanks a lot my friend,I found it Smile
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: May 13, 2014 - 04:39 PM
10k+ Postman


Joined: Mar 27, 2002
Posts: 22204
Location: Lund, Sweden

Quote:

I know something you don't though

Not only that. You see it.

It is still a question as to whether everyone will eventually see it. It's not over 'til the fat lady sings, and all that.

But after a peek I begin to believe in this former Spaghetti Monster. Wink

_________________
"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]
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits