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
Sith
PostPosted: Nov 05, 2011 - 12:55 PM
Rookie


Joined: Sep 17, 2006
Posts: 37
Location: Czech Republic

Hi all : )

I'm looking how to read CARRY flag from SREG after certain operation - LEFT SHIFT.

Sample code is following:
Code:
char carry;
char data;

data = data<<1;
// There I need to read bit that was shifted out into carry


It is clear to me this is job for inline ASM, but I never work with ASM in C.

Can you give me some advice?

David
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 05, 2011 - 01:16 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 19386
Location: Wormshill, England

Do not even dream of accessing the Carry flag in C. It is not guaranteed to be valid in C.

If you want to know whether a carry is shifted out, you simply:
Code:

char data;
// just check bit 7 before the shift.
char carry = (data & 0x80) != 0;
data = data<<1;


David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
wek
PostPosted: Nov 05, 2011 - 01:40 PM
Raving lunatic


Joined: Dec 16, 2005
Posts: 3197
Location: Bratislava, Slovakia

David's reply covers the vast majority of possible uses, but if you believe you need better and you tell us why do you think you need the carry bit, we might come up with alternative solutions.

Jan
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Sith
PostPosted: Nov 05, 2011 - 02:05 PM
Rookie


Joined: Sep 17, 2006
Posts: 37
Location: Czech Republic

Generally, I'm trying to write MFM coder as simple as it is possible. Input is byte array, output is MFM-coded stream.

If it helps you, there is whole procedure - I'm not saying that is the best solution, but until now i haven't wrote better solution.

Base idea, if I understood it OK, is that data bits (x,y,z,...) are coded to (x,x NOR y, y NOR z, z, z NOR .......)

So I came with this solution. David, your code will work of course, but I think variant with use of CARRY flag will save some instructions.

Code:
void FDDIO_encodeMfm() {
    char carry = 0;
    char prvek = FDD_sector[0];
    prvek = (prvek << 1);
    //!!! carry = ?; !!!
    // Data x
    FDD_sectorMfm[0] |= carry;
   
    for(int i = 0; i < 658;i++) {
        prvek = FDD_sector[i];
        for(c = 0; c < 9; c++) {
            // CLOCK  x NOR y
            FDD_sectorMfm[i] = (short) (FDD_sectorMfm[i] << 1);
            FDD_sectorMfm[i] |= carry;
                if(c==8 && i!= (658-1)) prvek = FDD_sector[i+1];
            prvek = (prvek<<1);
            //!!! carry = ?; !!!
            FDD_sectorMfm[i] |= carry;
            FDD_sectorMfm[i] ^= (1<<0);
           
            // DATA y
            if(c < 8) {
                FDD_sectorMfm[i] = (FDD_sectorMfm[i] << 1);
                FDD_sectorMfm[i] |= carry;   // bit 14 16bit slova, 15. je pro ulozeni clocku ktery uz souvisi s dalsim prvkem
            }
        }
    }
}
 
 View user's profile Send private message  
Reply with quote Back to top
Sith
PostPosted: Nov 05, 2011 - 02:07 PM
Rookie


Joined: Sep 17, 2006
Posts: 37
Location: Czech Republic

Forgotten global defs:
short FDD_sectorMfm[658];
char FDD_sector[512];

.. I have tested almost the same code on PC (java) and it works OK..

_________________
David Sedláček
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 05, 2011 - 02:21 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 19386
Location: Wormshill, England

You never assign carry apart from initialising to zero.

I should just write the algorithm to be accurate. Do not worry about the efficiency.

Once you are working, by all means optimise it.

I notice that you have multiple array references. Some compilers may spot this. OTOH, you might just as well introduce a temporary variable.

Note that you can equally well use a 16-bit int. Then the 'carry' is in bit 8.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
Koshchi
PostPosted: Nov 05, 2011 - 04:26 PM
10k+ Postman


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

Code:
            prvek = (prvek<<1);
            carry = SREG & (1<<7) != 0;
This could give you the current state of the carry bit, but you must realize what "current" means. It is certainly not the state of the carry bit immediately after the shift since, at the very least, the asignment to prvek has happened since then. There could also be several opcodes run in preparation of reading SREG that might have changed its value. And worst case, an interrupt might have occurred in between which means hundreds or even thousands of opcodes could have been run.

Davids solution of using a 16 bit int sounds easiest to me (however, you need to change the declaration of prvek to unsigned char, which is probably advisable anyways):
Code:
unsigned int temp = prvek << 1;;
prvek = temp;
carry = temp >> 8;

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
sternst
PostPosted: Nov 05, 2011 - 04:49 PM
Raving lunatic


Joined: Jul 23, 2001
Posts: 2728
Location: Osnabrueck, Germany

Quote:
And worst case, an interrupt might have occurred in between which means hundreds or even thousands of opcodes could have been run.
If you use a compiler that does not preserve SREG in interrupts, then you should consider to use a different one. Wink

(of course the central point "reading Carry from SREG in C is pointless" is true nevertheless)

_________________
Stefan Ernst
 
 View user's profile Send private message  
Reply with quote Back to top
Brutte
PostPosted: Nov 06, 2011 - 09:21 AM
Raving lunatic


Joined: Oct 05, 2006
Posts: 3042
Location: Poland

Well, you can read SREG as any other IO register, but this will not bring you any closer with your
Quote:
I'm trying to write MFM coder as simple as it is possible (..)with GCC

idea because GCC does not understand SREG flags and their brbx functionality.

_________________
No RSTDISBL, no fun!
 
 View user's profile Send private message  
Reply with quote Back to top
Sith
PostPosted: Nov 06, 2011 - 05:15 PM
Rookie


Joined: Sep 17, 2006
Posts: 37
Location: Czech Republic

Hey guys I dont want to work with 16bit integer unless it is not efficient. There must be way to do it in inline ASM this is what I'm asking for : ).
I'm not saying it must be only SREG bit saving line, but what if whole left shift and then SREG bit save section, or more, will be in inline ASM?

Koshchi it is as you wrote - there is some operation(s) after LSHIFT and it is not guaranteed that in CARRY will be correct val.

Again, see this in pseudocode and compare efficiency:
Code:
prvek <<= 1;
prvekMfm |= (SREG&1);


... which I need to convert into inline ASM or generic way:
Code:

carry = (prvek >>7);
prvek <<= 1;
prvekMfm |= carry;



Question Cool
 
 View user's profile Send private message  
Reply with quote Back to top
JohanEkdahl
PostPosted: Nov 06, 2011 - 05:19 PM
10k+ Postman


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

Have you actually looked at what code the compiler generates for an implementation in C? Do that, and then tell what needs further optimization.
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
sternst
PostPosted: Nov 06, 2011 - 05:25 PM
Raving lunatic


Joined: Jul 23, 2001
Posts: 2728
Location: Osnabrueck, Germany

Quote:
which I need to convert into inline ASM
Why you "need to"? What is wrong with a C solution? With all the other stuff in that function do you really think a few cycles matter?

_________________
Stefan Ernst
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 06, 2011 - 07:16 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 19386
Location: Wormshill, England

You do not need to do all calculations in 16-bit. Simply do a cast whenever you want to 'find' the carry.

Forget about efficiency. Get your algorithm working correctly.

Quite honestly, the C compiler will translate straightforward code very well. Only if it needs extra performance do you ever look at the ASM.

A human can often spot the odd peephole optimisation that will make a significant improvement. But believe me, the Compiler has done most of them already.

The main advantage of the 'tweak generated code' approach is that you have already got a working algorithm. So your testing regime only has to compare against the original.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
Sith
PostPosted: Nov 06, 2011 - 07:36 PM
Rookie


Joined: Sep 17, 2006
Posts: 37
Location: Czech Republic

I need this it running as fast as it is possible. There is working AVR 8bit algorithm.

Code:
void FDDIO_encodeMfm() {
   
    unsigned int prvekMfm = FDD_sectorMfm[0];
    unsigned char prvek = FDD_sector[0];
    unsigned char carry = 0;
    prvek <<= 1;
    carry = ((prvek&128)>>7);
    // Data x
    prvekMfm |= carry;
   
    for(int i = 0; i < 524;i++) {
        prvek = FDD_sector[i];
        prvekMfm = FDD_sectorMfm[i];
        for(c = 0; c < 9; c++) {
            // CLOCK  x NOR y
            prvekMfm <<= 1;
            prvekMfm |= (uint8_t) carry;
            if((c==8) && (i < (524-1))) {
                prvek = FDD_sector[i+1];
            }
            carry = ((prvek&128)>>7);
            prvek <<= 1;
            prvekMfm |= carry;
            prvekMfm ^= (1<<0);
           
            // DATA y
            if(c < 8) {
                prvekMfm <<= 1;
                prvekMfm |= carry;   // bit 14 16bit slova, 15. je pro ulozeni clocku ktery uz souvisi s dalsim prvkem
            }
        }
        FDD_sectorMfm[i] = prvekMfm;
    }
}


It counts about 24ops to code 1 data bit with -O3... Data bits are streamed from FDD_sector[] to FDD_sectorMfm[]. I believe there is faster way.
 
 View user's profile Send private message  
Reply with quote Back to top
Koshchi
PostPosted: Nov 06, 2011 - 08:47 PM
10k+ Postman


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

Code:
   unsigned int prvekMfm = FDD_sectorMfm[0];
    unsigned char prvek = FDD_sector[0];
Exactly how do you think you are going to use arrays that have no elements?
Code:
 carry = ((prvek&128)>>7);
You say that you want to be as fast as possible, then you choose the most inefficient method suggested in this thread. Besides that, you get the bit after that bit has already been lost.

_________________
Regards,
Steve A.

The Board helps those that help themselves.
 
 View user's profile Send private message  
Reply with quote Back to top
sternst
PostPosted: Nov 06, 2011 - 08:50 PM
Raving lunatic


Joined: Jul 23, 2001
Posts: 2728
Location: Osnabrueck, Germany

Koshchi wrote:
Code:
   unsigned int prvekMfm = FDD_sectorMfm[0];
    unsigned char prvek = FDD_sector[0];
Exactly how do you think you are going to use arrays that have no elements?
Steve, you should rethink that. Wink

_________________
Stefan Ernst
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Nov 06, 2011 - 08:51 PM
10k+ Postman


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

Quote:

Exactly how do you think you are going to use arrays that have no elements?

Steve? he's just assigning element 0 from those two global arrays to each of prvekMfm and prvek surely?

BTW:
Code:
 carry = ((prvek&128)>>7);

Haven't checked but what does:
Code:
 carry = !!(prvek&128);

yield?

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
sternst
PostPosted: Nov 06, 2011 - 08:59 PM
Raving lunatic


Joined: Jul 23, 2001
Posts: 2728
Location: Osnabrueck, Germany

clawson wrote:
Code:
 carry = ((prvek&128)>>7);
Haven't checked but what does:
Code:
 carry = !!(prvek&128);
yield?
gcc supports C99, so also worth a check is:
Code:
 carry = (_Bool)(prvek&128);

_________________
Stefan Ernst
 
 View user's profile Send private message  
Reply with quote Back to top
david.prentice
PostPosted: Nov 06, 2011 - 09:01 PM
10k+ Postman


Joined: Feb 12, 2005
Posts: 19386
Location: Wormshill, England

I know nothing about MFM. But I am sure there will be algorithms in the public domain.

I would also guess that the whole operation can be done with one or two XORs.

You just need to ask Uncle Google.

I have not looked at the generated ASM. But most compilers will do this in about three instructions.
Code:

    if (val & 128) carry = 1;
    else carry = 0;


Personally, I think you have written your algorithm fairly clearly (for the compiler). I have made no attempt to understand it myself (human). I just guess that there are better algorithms.

David.
 
 View user's profile Send private message Send e-mail  
Reply with quote Back to top
Sith
PostPosted: Nov 06, 2011 - 09:30 PM
Rookie


Joined: Sep 17, 2006
Posts: 37
Location: Czech Republic

I have tried all variants mentioned there but
carry = ((prvek&128)>>7); is really the fastest.

Code:
    47:     carry = ((prvek&128)>>7);
MOV R26,R18      Copy register
LSL R26      Logical Shift Left
MOV R19,R26      Copy register
ROL R19      Rotate Left Through Carry
CLR R19      Clear Register
ROL R19      Rotate Left Through Carry


In short it seems in 6 ops R19 contains CARRY, which will be ORed with desired var later (7ops). What I want is to OR this var straight with CARRY (1op)
>>> the same as "ROL" op works.

I believe this is temporary solution until I find how to save CARRY straight to register with desired var. In better some GCC/ASM geek there will tell me how to do it : )

Unfortunatelly MFM coding is very obsolete and was realized very often only by hardware controllers, so there are not any codes nor avr sample codes. Anyway it is really old thing and is described in datasheets from ~70's....
 
 View user's profile Send private message  
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