## Half carry flag

14 posts / 0 new
Author
Message

Hi guys

I have a small question. What is a half carry flag. I understand all the other flags in the sreg. But half carry, I see that some asm commands change this H flag but do not understan why or what this flag is.
Can some one help me.

Thanks

Pinkpanter

Its a relict from older days, where some peripherals used the packed bcd format (two decimal digits packed into one byte).

Then the half carry signals an overflow from one digit to the next inside a byte.

Peter

two nibbles = one byte (2 * 4bit), but bcd is not a nibble ?

thanks

4 bits can represent 0-15 but in BCD on 0-9 were valid. When a sum was 10-15 then an adjustment had to be made. 10 had to be subtracted from this character and 1 added to the next higher one. When the adjustment was to the low order character, the half carry reflected this.

As pointed out, the half carry is a legacy function, but it is still quite useful.

We normally think of a byte as representing numbers from 0x00 to 0xff or decimal 0 to 255.

But, thats not the only way numbers can be represented in 8 bits. Another representation is called "binary coded decimal" or BCD. In this representation, the high 4 bits represent one decimal digit and the low 4 bits represent the next most significant decimal digit. These four-bit chuncks are called nibbles (small byte). The values 0xb through 0xf for each nibble are never used.

As an example, the decimal number 39 is represented by 0x3a.

The half-carry comes into play when you add two bcd values. Sometimes, you need to know when a decimal carry happens from the addition of the two low nibbles that would not result in a carry under binary rules. Here is an example:

Suppose that you have the two bytes 0x37 and 0x44 representing the obvious decimal numbers 37 and 44. When you add these under binary rules, you get 0x7b. But, this is not a valid hexidecimal number, because there SHOULD have been a carry from the low nibble, resulting in decimal 81. In this case, the halfcarry is set by the ALU. This can be tested, and if its set, then you subtract decimal 10 (0xa) from the low nibble and add 1 to the high nibble.

Using this method, addition and subdtraction of decimal values can be fairly easy to an arbitrary number of digits.

Jim Wagner

The half carry flag is a hex carry on the lower nibble and not a decimal carry, so adding 0x37 and 0x44 will not produce a half carry flag.
39 in decimal is represented as 0x39 in bcd.
There are no decimal instructions in AVR (such as the old dadj of Z80 and others) so bcd arithmetic requires a fair amount of processing.
Please correct me if I am wrong.
Dave Raymond

The AVR instruction set manual says for ADD:

h: Rd3&Rr3 | Rr3&!R3 | !R3&Rd3

where R is the result after the operation and Rd and Rr
are the register values before the operation. I read this
as saying it is a binary carry if the low 4 bits overflow on
set or else one of the registers before the Add had bit 3
set but the result did not have bit 3 set.

I was wrong! Still thinking about another processor from an earlier existance.

Sorry -

Jim

thanks guys for the info will make my own designnote with this info.
thanks again

Even if the half-carry flag was a decimal flag (marking overflow when eg. 0x09 + 0x01 was performed) it would only solve half of the BCD-carry problem. We would still lack a flag signalling overflow when 0x90 + 0x10 was performed (which should carry over to a BCD-digit in another byte). Right?

As has been stated the half-carry flag marks an overflow into the high nibble when eg. 0x0F + 0x01 is performed. So the "what" in PinkPanters original post is dealt with but the "why" is still open. Apart from the now obvious answer "to perform arithmetics on 4-bit binary integers" does anyone have a more specific example of its use?

Hi!

Well, this seems to be logical...half carry on half a byte....interesting...you can always learn something new from the great forum..

Björn

Maybe it will be interesting:

How a CPU Adds Decimal Numbers
Calculations in assembler language

Szymon

Atmel has a design note:
http://www.atmel.com/dyn/resourc...
which uses the long version of bcd_add that Szymon pointed to in his second link. The short version in that link is very much more compact. Here is a short version of subtract where it is desired to subtract bcd value r3 from bcd value in r2, result in r2, borrow from r1:

clr r16
sub r2, r3
brcc NoCy
dec r1
ori r16, 0x60
NoCy:
brhc NoHc
ori r16, 0x06
NoHc:
sub r2, r16

The borrow here (and the carry in the bcd_add) need to be tailored to the application.
Dave Raymond