SWITCH/CASE with Flag

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

I have a serial buffer, and one of the bytes in said buffer is used for commands.  Right now it is a simple on/off but I am using a flag to prevent the output from oscillating from logic High and logic low by setting a flag.

int main(void)
{
	avr_init();
	sei();
	uint8_t flag = FALSE;

    while(1)
    {
		if (rx_buffer_NL0 == 0x01)
		{
			   uint8_t value;	//adc reading

			  value = rx_buffer0[0];

			   SPI_MasterTransmit(value);

			   value = rx_buffer0[1];

					if((value == 0x01) & (flag == FALSE))
					{
						PORTC = PORTC ^ 0x01;	//toggle power condition
						flag = TRUE;	//set the flag so as not to keep toggling power
					}

						else if(value == 0x00)
						{
							flag = FALSE;	//clear the flag
						}

			   rx_buffer_NL0 = 0;
			   rx_counter0=0;
			   rx_wr_index0=0;

		}
    }
}

This all works fine and dandy, but I realised that I will have a few other commands, so rather than a bunch of IF...else if statements I would implement a switch/case.  But the flag I am using for the power toggle is my issue on how to implement it.

 

For example, if I was not using a flag, I could simply write this:

value = rx_buffer0[1];

    switch(value)
    case 0x00:
    {
        //do something
    }
break;

    case 0x01:
    {
        //do something
    }
break;
default:
{

}

 

 

But what do I do if I want the CASE to only occur if the FLAG is set?  My guess is to put an IF statement inside the brackets:

value = rx_buffer0[1];
uint8_t flag;

    switch(value)
    case 0x00:
    {
       flag = 0;
    }
break;

    case 0x01:
    {
        if(flag == 0)
        {
            //do something
            flag = 1;
        }
    }
break;
default:
{

}

My question is this the proper/correct way to do this, or is there a better, more suitable way to do this?

 

The FLAG is only going to occur for the power on/off toggle so it will not be implemented in any other CASE...as far as I know wink

 

Jim

 

JIm

This topic has a solution.

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

Last Edited: Thu. Mar 16, 2017 - 12:04 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My question is this the proper/correct way to do this

 

I think what you have is fine.  The cases can be arbitrary code blocks; you don't even need the outer set of braces:

 

case 0x01:
  if (flag == 0) {
     // stuff
  }
  break;

 

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

As an aside, the 'correct' way would be to use enums or #defines for the case values. Magic numbers again!

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

If "do something" consists of more than a few lines, I would prefer an "early exit":

    case 0x01:
        if (flag)
            break;
        // do something
        break;

 

Stefan Ernst

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

Kartman wrote:
As an aside, the 'correct' way would be to use enums or #defines for the case values. Magic numbers again!

If you are referring to the 0x00, and 0x01 I agree that does not make readability easy.  This was just thrown together for testing/evaluation.

 

Is this more your fancy:

#define pwr_toggle 1
#define flag_clear 0

int main(void)
{
    ....//other code 
    
    value = rx_buffer0[1];
uint8_t flag;

    switch(value)
    case flag_clear:
    {
       flag = 0;
    }
break;

    case pwr_toggle:
    {
        if(flag == 0)
        {
            //do something
            flag = 1;
        }
    }
break;
default:
{

}
}

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

jgmdesign wrote:
Is this more your fancy:
My fancy would be:

typedef enum {
    pwr_toggle = 1,
    flag_clear = 0
} cmd_type;

...

cmd_type value;

    value = (cmd_type)rx_buffer0[1];

If they were listed in the other order the =0 and =1 would not be required - but it shows how they can be used if you want to use "non sequence" values.

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

clawson wrote:
value = (cmd_type)rx_buffer0[1];

 

I don't get it Cliff Sorry.  Whats the difference between what you have and:

 

jgmdesign wrote:
value = rx_buffer0[1];

 

Value still equals what is in position 1 of the buffer.

 

All total there may be a dozen commands I would use that byte for.  Say the commands will be 0 to 11, so command '2' maybe is to be a "set", command '3' is to increment a counter.  Wouldn't I still need a SWITCH/CASE?

 

Sorry for the confusion,  I will be grabbing my K/R in the meantime.

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

jgmdesign wrote:
Whats the difference between what you have and:
Type safety. You are telling the compiler you really do mean to reinterpret the generic type of rx_buffer[] (I'm guessing it is uint8_t ?) as an enum of this newly defined type. To be honest C doesn't actually care too much about this sort of thing. If you inadvertently assign something of one type to something of another (which might involved promotion or truncation) then it lets you shoot yourself in the foot. When you get to C++ it points out these errors and will usually require you to apply a cast often because the destination is a class and it will tell you that "there is no implementation of the = operator for this that can convert A into B"

jgmdesign wrote:
Wouldn't I still need a SWITCH/CASE?

yes but you started out using 0x01's and 0x02's. Russell baulked at this saying you should give these "anonymous" values names to aid the reader of the code. The suggestion was to use either pre-pro macro #define's (as you did) or an enum (as I did). I prefer the latter as it can be "type safe".

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

clawson wrote:
or an enum (as I did). I prefer the latter as it can be "type safe".

Ok, still a little confused, "type safe"?  I am looking at a single byte and in that byte the value can be anything from 0 to 255.  I am not going that high of course, so........confused.

 

clawson wrote:
value = (cmd_type)rx_buffer0[1];

Again, I am going to have to read K/R but if you have a short form explanation as to what is going on....

 

clawson wrote:
Type safety. You are telling the compiler you really do mean to reinterpret the generic type of rx_buffer[] (I'm guessing it is uint8_t ?)

Actually no, it is type 'char', but I can easily change that to uint8_t.  It really does not matter to me.

 

Lastly:

clawson wrote:
cmd_type value;

Not sure what that is all about.

 

From what I have read here, the ENUM simply is the same thing as a list of #defines correct?  And the only reason for both the ENUM or #define is to make the code easier for someone else to understand?

 

Not being argumentative, just looking at clarity.

 

JIm

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

By using the enum, Cliff defined a type. This gives the compiler more information and therefore it can check that you did the right thing ie: you used one of the enum'd values. I get grilled at the office for using constant offsets with magic numbers, so i'm just passing on the love!

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

Kartman wrote:
By using the enum, Cliff defined a type.

Type of what?

 

Kartman wrote:
This gives the compiler more information and therefore it can check that you did the right thing ie: you used one of the enum'd values.

BUT, what if I put an ENUM value for future use, and do not use it now?  Compiler barfs?

 

Any chance you can explain what this is:

clawson wrote:
cmd_type value;

 

Kartman wrote:
I get grilled at the office for using constant offsets with magic numbers, so i'm just passing on the love!

Oh great, you get kicked around so it just seems fair to start trouble around here....wanker wink

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
typedef enum {
    pwr_toggle = 1,
    flag_clear = 0
} cmd_type;

type defines the type of  enum and the type is named cmd_type

 

If you don't use an enum - no problems the compiler she no complain.

 

since the value you want to switch on is of type char, you need to cast it to (cmd_type) to tell the compiler you want to treat it as cmd_type enum. What we've done is not only does the enum have a value, it also has a type. So power_toggle equals 1 and of type cmd_type. If you try to use power_toggle with another type, the compiler will most likely inform you of the transgression. Thus the term 'type safe' - the compiler ensures you use it correctly. What is the benefit to you? Firstly, the code is easier to comprehend, secondly you've allowed the compiler to check to see you've used it in the right context. Net result is hopefully your code is more correct - ie less defects.

 

 

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

Kartman wrote:
since the value you want to switch on is of type char, you need to cast it to (cmd_type) to tell the compiler you want to treat it as cmd_type enum. What we've done is not only does the enum have a value, it also has a type. So power_toggle equals 1 and of type cmd_type. If you try to use power_toggle with another type, the compiler will most likely inform you of the transgression.

 

My Cranial Rectitus Syndrome is really doing a number on me today. I am reading the K/R book, and it make some sense, but yours and Cliff's explanation is leaving me puzzled.  Are you saying that by doing it this way should I brain fart and somewhere define POWER_TOGGLE as 0x05 for example, the compiler will complain?

 

I still do not understand:

cmd_type value;

 

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

We've defined a new type -cmd_type. This can be used like the other types char,int, long etc. The magic thing about cmd_type is that it technically can only have the values that we defined in the enum.
Eg:
cmd_type val; // defines a variable of type cmd_type
val=1; // bao bao! Not kosher
val= power_toggle; // correct

Actually the C compiler might only warn you, C++ is a lot more stringent.

Remember, #define only does a simple text substitution.

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

Sorry but I hate to see a enum that count down! (not an error but perhaps I'm old I still hate if(0==counter) aswell ).

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

Another (potential) advantage of enum is that the debugger can display the enum names - instead of just magic numbers,

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

I dare say that Atmel Studio might have the feature of the editor doing online checking and highlighting the values or otherwise informing you whether it is good or bad. Since i rarely use Atmel Studio, I have little idea of the finer features it has. 

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

Not just the editor - also the debugger.

 

Eclipse also supports this.

 

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

Hmmmmm,

 

K/R does not mention about "typedef", nor does it provide any examples of what I am seeing.  Some online searches showed a few things.

 

So, based on what I have read here, and on the web:

cmd_type value;

is the same for example as maybe:

uint16_t value;

but in the case of my first example, the variable 'value' is defined by the enumeration type?

 

Then can someone explain:

 value = (cmd_type)rx_buffer0[1];

I am reading a one byte cell from the array/buffer.  What is the purpose of putting

(cmd_type)

in there?

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

If I understand it, someone might want to do a cast:

    char buffer0[8];            // Create an array of char
    int16_t  abc ;              // A variable defined as something other than char
    abc = (int16_t) buffer0[1]; // Cast the array element as the int16_t variable

where in this case:

int8_t rx_buffer[8];             // (I don't know how rx_buffer was defined or how large it is)
cmd_type value;                  // A variable defined as cmd_type (which was created by the typedef)
value = (cmd_type)rx_buffer0[1]; // Cast the array element as the cmd_type variable

 

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

http://publications.gbdirect.co....

 

jgmdesign wrote:
K/R does not mention about "typedef"

Geddaway - what version do you have?

 

Mine is the "2nd Edition, Based on Draft-Proposed ANSI C" of 1988 and it's certainly in there!

 

Pages 146, 210, & 221 - to be precise.

 

 

 

So, based on what I have read here, and on the web:

cmd_type value;

is the same for example as maybe:

uint16_t value;

but in the case of my first example, the variable 'value' is defined by the enumeration type?

correct.

 

I am reading a one byte cell from the array/buffer.  What is the purpose of putting

(cmd_type)

in there?

That is a cast - it tells the compiler to treat the value from the buffer as if it were of the specified type.

 

However, in 'C' there is really nothing special about enumeration types - the language places no restrictions on the values that can be assigned to a variable with enum type, and no restrictions on assigning or comparing the enum constants to variables not of that type.

 

So your cast above is purely for the benefit of the human reader.

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

unless you have more than 256 cases you should remember to select short enum in the compiler (sometimes it's the default sometimes it's not! if C don't know better enum often gets the type of unsigned int, but my winAVR default to short.)

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

sparrow2 wrote:
sometimes it's the default sometimes it's not!

#include <avr/io.h>

typedef enum {
        FOO,
        BAR
} etype;

int main(void)
{
        PORTB = sizeof(etype);
}

built with:

avr-gcc -mmcu=atmega16 -g -Os avr.c -o avr.elf

yields:

        PORTB = sizeof(etype);
  6c:   82 e0           ldi     r24, 0x02       ; 2
  6e:   88 bb           out     0x18, r24       ; 24

so you are right to be concerned. However I think most makefiles and AS7 use:

avr-gcc -mmcu=atmega16 -fshort-enums -g -Os avr.c -o avr.elf

and then it becomes:

        PORTB = sizeof(etype);
  6c:   81 e0           ldi     r24, 0x01       ; 1
  6e:   88 bb           out     0x18, r24       ; 24

@Jim, BTW I think forg's post #20 explain most things. After a typedef "cmd_type" just becomes another type added to the C language just as the int16_t in his first example. In fact int16_t itself is just a typedef ("signed int") too.

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

And for a practical information about enum (if no value given) it always start with a value zero and count up.

 

And if you give a value like 0x40, the next element will get the next value (0x41), and not filling up holes.

 

And if you (if no value given) have the last element (called last or something like that) can be used to check how many elements there are. (you can't take the size of a enum, only get the size of each element).

 

And (if I remember correct)  if you make a switch on a enum you can get a warning if there's not a case for all elements. 

Last Edited: Wed. Mar 15, 2017 - 12:15 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sparrow2 wrote:
(if I remember correct)  if you make a switch on a enum you can get a warning if there's not a case for all elements.

Yes, GCC can do that.

 

IIRC, you can still use default as a catch-all

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

IIRC, you can still use default as a catch-all

But that is often not what you want, in a big switch you want to know that all states are taken care of!  

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

sparrow2 wrote:
But that is often not what you want

So don't do it, then!

 

It gives you the option.

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

Huh.   Interesting question: if your input value is a terminal character (expected range 0-127) or network byte (0-255), and some SUBSET of them is commands, would you use an enum to define those commands?

enum cmd_t {
    LINE_BEGIN = 'a' & 0x1F;  // Ctrl-A
    CHAR_BACK = 'b' & 0x1F;   // Ctrl-B
    LINE_END = 'e' & 0x1F;    // Ctrl-E
    CHAR_FWD = 'f' & 0x1F;
} commands;

 

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

why ever not?

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

Then can someone explain:

 value = (cmd_type)rx_buffer0[1];

Using (cmd_type) is just explicitly forcing a cast (think conversion) to the "format" of your personal & custom defined type (cmd_type).  Because it is a custom type, it can only take on your defined enumerated values.    An integer can only take on a finite grouping of predefined values too, but we usually don't think of integers in that manner (we just say range).  It's very unlikely that your rx_buffer was designed using this cmd_type (maybe it was done using chars, ints, or  some other custom type)...so a conversion is obviously needed to join the cmd_type troops.  However, casting is not the magic cure all; not every transformation is do-able.  You can turn grapes into grape-juice & oranges into orange juice, but try that with rocks.  Sometimes a compiler is smart enough to figure out when & what to cast (based on it's own "best decision"), other times your help is necessary & appreciated.

 

By the way, instead of using a bunch of case statements, why not scan through a symbol table to decode your commands? Then, whether you have 1 command or 100, it is the exact same core code (and same length code, other than the commands themselves).

 

 

When in the dark remember-the future looks brighter than ever.

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

avrcandies wrote:
By the way, instead of using a bunch of case statements, why not scan through a symbol table to decode your commands?

 

I think I have done this before....not sure how though.   Thanks for the suggestion.

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

awneil wrote:

why ever not?

 

Well, those values were all 8 bit. What is the size of an enum? Will it shrink to 8 bits if you only use 8 bit values? Or will it be a 16 bit int?

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

avrcandies wrote:
 Because it is a custom type, it can only take on your defined enumerated values.  

No - that is not the case.

 

As I said earlier,

the language places no restrictions on the values that can be assigned to a variable with enum type, and no restrictions on assigning or comparing the enum constants to variables not of that type.

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

I think I have done this before....

 

Simply define a bank of strings, ex (a quick & dirty example that comes to mind):

 

const char CD13[] PROGMEM="LPAxx"; // SET LAMPA BRIGHTNESS 0-99

const char CD14[] PROGMEM="LPBxx"; // SET LAMPB BRIGHTNESS 0-99

const char CD15[] PROGMEM="ALLON";  //TURN ON ALL LAMPS 100% (A,B,C,D,E)

const char CD16[] PROGMEM="qPWARMxxx"; //Prewarm Lamps (MILLISECONDS)...0-999, 0= prewarm off, (a query if no x value supplied)

const char CD17[] PROGMEM="DRUMxrr.ff"/TRPMrrr; //Keep DRUM at desired RPM  (REQUIRES 2 DIGITS AHEAD OF DECIMAL AND 2 OPTION FRACTIONAL DIGITS, OR 3 REQUIRED WHOLE DIGITS for TRPM

const char CD18[] PROGMEM="SNS?e"; // Report Hall logic levels (ONLY USABLE IN eNGINEERING TEST MODE)

const char CD19[] PROGMEM="eqTRx/TRIPxx"; // TRx or TRIPx toggles driver line x  (ONLY USABLE IN eNGINEERING TEST MODE) (a query if no x value supplied)

const char CD23[] PROGMEM="FCLRmxx"; //Clear fault codes from bank xx (ONLY USABLE FROM mASTER UNIT)

 

Here x means optional digit, extras ignored or flagged as error, no value supplied takes a zero

r means required digit

f means fractional part, extra digits ignored/truncated

q means query, if no value entered, current setting value will be returned

e means accessible only in engineering mode

m means usable only by unit configured as the master unit

 

 

Of course this is just the beginning...you'll find some typical examples from the freaks, using tables of various flavors. 

When in the dark remember-the future looks brighter than ever.

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

why ever not?

It makes me uncomfortable to make a variable an enum if I KNOW it will have values other than those that are members of the enum.

I like to pretend enums behave like they do in Pascal, and any moment some code will come along and give me a runtime error if I have an "invalid value"...

 

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

As I said earlier,

the language places no restrictions on the values that can be assigned to a variable with enum type, and no restrictions on assigning or comparing the enum constants to variables not of that type

arrrg..yes you are correct, I forgot C is rather poor in that regard

 

For JAVA:

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

Because they are constants, the names of an enum type's fields are in uppercase letters.

In the Java programming language, you define an enum type by using the enum keyword. For example, you would specify a days-of-the-week enum type as:

public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}

You should use enum types any time you need to represent a fixed set of constants. That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile time—for example, the choices on a menu, command line flags, and so on.

When in the dark remember-the future looks brighter than ever.

Last Edited: Thu. Mar 16, 2017 - 01:39 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry Jim, my initial comments were to prod some investigation, but this thread grew legs and started running!

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

These kind of things are likely to drive people to assmb...sorry I mean drink. devil

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Assembler has no brains to check for correctness!
Two books are high on my list - Writing Solid Code and Code Complete from our friends at Microsoft Press. These should answer most programming style questions.

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

Kartman wrote:
Assembler has no brains to check for correctness!

And 'C' compilers have no brains to check beyond the rules (syntax & semantics) of the 'C' language.

 

So the fact that your code might compile without any compiler diagnostics does not mean that it is "correct" - that is necessary, but by no means sufficient!

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

westfw wrote:
It makes me uncomfortable to make a variable an enum if I KNOW it will have values other than those that are members of the enum.

Note that you can use enum just to create a set of named constants - it does not have to be a type, and there is no restriction to using those names only with enum-typed variables.

 

avrcandies wrote:
arrrg..yes you are correct, I forgot C is rather poor in that regard

'C' is not a strongly-typed language.

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

Kartman wrote:
Writing Solid Code and Code Complete from our friends at Microsoft Press.
+1. Great books.

 

Is it just me who always thinks it a little ironic that some of the best books about writing "bomb proof" code come from engineers on the Microsoft campus? cheeky

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

clawson wrote:
Is it just me who always thinks it a little ironic that some of the best books about writing "bomb proof" code come from engineers on the Microsoft campus?

No - it isn't!

 

cheeky

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

Cliff,

 

Nearly 4 hours ago when reading Russell's recommendation, I almost made the same observation... but thought the better of it. cheeky

Ross McKenzie ValuSoft Melbourne Australia

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

Exactly why I added the 'friends at microsoft press' at the end! Whilst it's easy to poke jibes at Microsoft, they are one of the largest software companies on earth and even they can't get it 100% right. such is the beast that is software.

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

Kartman wrote:

Sorry Jim, my initial comments were to prod some investigation, but this thread grew legs and started running!

  It wouldn't be AVRFREAKS if threads did not get pulled all over the place now would it? wink

 

Jim

If you want a career with a known path - become an undertaker. Dead people don't sue! - Kartman

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB user

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

Like the embarrassing drunk uncle....

 

Ross McKenzie ValuSoft Melbourne Australia