Go Down

Topic: Can not properly set pin13 to low (Read 824 times) previous topic - next topic

Udo Klein

I did the following:

Code: [Select]

#include <WProgram.h>
#include <string.h>
#include <pins_arduino.h>

// will initialize output pin with 1, then measure time for  input pin go to high


typedef int32_t micros_type;

// output pin
const uint8_t c_output_pin = 13; // internal LED is connected to digital pin 13
const uint8_t c_output_pin__bit  = 5;                                    // lookup in pins_arduino.c

// attention: input pin and break pin must use the same port !!!
const uint8_t c_input_pin  = 19;  // used as primary trigger pin
const uint8_t c_input_pin__bit  = 5;


int32_t measure_lag_micros;

int32_t measure_lag() {
       
    pinMode(c_input_pin, INPUT);  
      digitalWrite(c_input_pin, HIGH);


     // output to low because we want to trigger with high
     // because the opto coupler will turn this to low again
     pinMode(c_output_pin, OUTPUT);  
       digitalWrite(c_output_pin, HIGH);

     // compute pin ports and bit masks in advance
       volatile uint8_t* in_port   = portInputRegister(digitalPinToPort(c_input_pin));
       volatile uint8_t* out_port  = portInputRegister(digitalPinToPort(c_output_pin));
       //volatile uint8_t* break_port = portInputRegister(digitalPinToPort(c_break_pin));
           uint8_t in_bit     = 1 << c_input_pin__bit;              
           uint8_t out_bit    = 1 << c_output_pin__bit;       

       // ensure that we will never see 0 microseconds in the assembler part
       // this is because it would wrap around and give way to long delays
       // impact is that latency will never be below 1 microsecodns
       const micros_type timeout = 99999999;
       measure_lag_micros = timeout;

   uint8_t tmp = 0;

     cli();    
       // the inline assembler loop will burn 16 cycles or 1 microsecond at 16 MHz
     // for details:
     //            http://www.rn-wissen.de/index.php/Inline-Assembler_in_avr-gcc
     //            http://www.avr-asm-tutorial.net/avr_de/beginner/register.html
     //            http://www.avr-asm-tutorial.net/avr_en/beginner/PDETAIL.html#IOPORTS
       
     __asm__ __volatile__ (            
                             
           //       activate output
           "   eor  %[tmp], %[tmp]"   "\n\t"  // set output to low
           "   st  %a[out_port], %[tmp]" "\n\t"   // now
       
       // the loop below will take exactly 16 cycles per pass = 1us at 16 MHz
           "1: nop"                       "\n\t"
           "   nop"                      "\n\t"
           "   nop"                      "\n\t"
           "   nop"                      "\n\t"
           "   nop"                      "\n\t"
           "   ld  %[tmp], %a[in_port]"  "\n\t" // 2 cycles
           "   and %[tmp], %[in_bit]"    "\n\t" // 1 cycle
           "   cp  %[tmp], %[in_bit]"    "\n\t" // 1 cycle
           "   breq 2f"                       "\n\t" // 1 cycle    // stop timing once we see a high
           "   subi %A[micros],1"             "\n\t" // subtract immediate,  1 cycle
           "   sbci %B[micros],0"             "\n\t" // subtract with carry, 1 cycle
           "   sbci %C[micros],0"             "\n\t" // subtract with carry, 1 cycle
           "   sbci %D[micros],0"             "\n\t" // subtract with carry, 1 cycle
           "   brne 1b"                       "\n\t" //                      2 cycles (1 in the last pass)            
                   
           "2: nop"  "\n\t"
           
           : [micros]     "+a" (measure_lag_micros)   // constraint: simple upper register            
           :              "0"  (measure_lag_micros),  // constraint: use same register as [micros]          
             [in_port]    "e" (in_port),              // constraint: pointer register
             [in_bit]     "a" (in_bit),               // constraint: simple upper register            
             [out_port]   "e" (out_port),             // constraint: pointer register      
             [out_bit]    "a" (out_bit),              // constraint: simple upper register        
             [tmp]        "a" (tmp)                     // constraint: simple upper register      
           :                      
     );

       digitalWrite(c_output_pin, HIGH);      

       measure_lag_micros = timeout - measure_lag_micros;
       
       sei();
       return measure_lag_micros;
}


int main(){

     Serial.begin(115200);  
     Serial.println("ready");

     for (;;) {
           micros_type rv;
           rv = measure_lag();
           if (rv>0) {      
           Serial.println(rv ,DEC); }
     }
}



(Sorry for the messed up tabs).

The issue is: if I code a digitalWrite(13,LOW) it will set pin 13 to low. But if I do not it will not.

However I would expect that

Code: [Select]

           "   eor  %[tmp], %[tmp]"   "\n\t"  // set output to low
           "   st  %a[out_port], %[tmp]" "\n\t"   // now


would set pin 13 to low. But it fails to do so. Can anyone hit me with a cluebat?

Cheers, Udo
Check out my experiments http://blog.blinkenlight.net

retrolefty

#1
Sep 06, 2009, 09:24 pm Last Edit: Sep 07, 2009, 02:05 am by retrolefty Reason: 1
Why are you not using the standard Arduino setup() and loop() functions rather then using a main() function?

Lefty


Udo Klein

This code is part of a bigger project. I extracted it. The reason why I do not use the IDE is because I do not like it. It always gives me some kind of trouble. For example I can not define prototypes, compiler errors do not refer to proper line numbers and more. The libraries and the bootloader are a big help, but the IDE not really.

But this is definitely not the issue here. If I move this into a "normal" sketch the issue persists.
Check out my experiments http://blog.blinkenlight.net

Udo Klein

Aargh!

I thought the bug is in the assembly code, but

Code: [Select]
 volatile uint8_t* out_port  = portInputRegister(digitalPinToPort(c_output_pin));


should have been

Code: [Select]
 volatile uint8_t* out_port  = portOutputRegister(digitalPinToPort(c_output_pin));


Sorry for the stupid question.

Cheers, Udo
Check out my experiments http://blog.blinkenlight.net


Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy