Set an output pin but never get a signal out

10 Jul 2011

I am trying to intercept a signal to drive a scanbar. The old bar has a clock in of 4MHz and requires a one clock pulse start trigger. We are testing another bar that needs a four clock pulse instead. (Scanbar runs on 3.3V logic)

So I grabbed the mbed and built a routine that looks for the start pulse as an interrupt in and then puts a 960ns pulse on a digital out pin.

I know that the signal in is seen as I have a message that goes out to the LCD. But the oscope never sees a pulse on the digital out pin.

Maybe I missed something in setting things up?

Here is the code: <<code>>

  1. include "mbed.h"
  2. include "TextLCD_20X4.h"

TextLCD_20X4 lcd(p5, p6, p7, p8, p9, p10); rs, e, d4, d5, d6, d7

DigitalOut myled(LED1); DigitalOut test_pin(p21); InterruptIn Start_pulse_In(p30); DigitalOut Start_pulse_Out(p27);

int spacer = 16;

void scan () { Start_pulse_Out = 1; wait_us(0.1); while (spacer > 0) { spacer; } spacer = 16; Start_pulse_Out = 0; lcd.locate(0,1); lcd.printf("Start Pulse!"); }

int main() {

lcd.locate(6,0); lcd.printf("Mad_Lab");

lcd.locate(0,2); lcd.printf("SystemCoreClock = %d Hz\n", SystemCoreClock);

Start_pulse_Out = 0;

Start_pulse_In.rise(&scan);

test_pin = 0; while(1) { myled = 1; test_pin = 1; wait(0.2); myled = 0; test_pin = 0; wait(0.2); } } <<code>>

Probably something basic wrong, been a while since I was really digging into code.

10 Jul 2011

Reformatted for legibility:

#include "mbed.h"
#include "TextLCD_20X4.h"
TextLCD_20X4 lcd(p5, p6, p7, p8, p9, p10); // rs, e, d4, d5, d6, d7

DigitalOut myled(LED1);
DigitalOut test_pin(p21);

InterruptIn Start_pulse_In(p30);
DigitalOut Start_pulse_Out(p27);

int spacer = 16;

void scan () {
    Start_pulse_Out = 1;
    wait_us(0.1);
    while (spacer > 0) {
        spacer--;
    }
    spacer = 16;
    Start_pulse_Out = 0;
    lcd.locate(0,1);
    lcd.printf("Start Pulse!");
}

int main() {

    lcd.locate(6,0);
    lcd.printf("Mad_Lab");

    lcd.locate(0,2);
    lcd.printf("SystemCoreClock = %d Hz\n", SystemCoreClock);

    Start_pulse_Out = 0;

    Start_pulse_In.rise(&scan);

    test_pin = 0;
    while (1) {
        myled = 1;
        test_pin = 1;
        wait(0.2);
        myled = 0;
        test_pin = 0;
        wait(0.2);
    }
}

Hi Michael,

The wait_us function only takes whole numbers, so wait_us(0.1) is reduced to wait_us(0) and your pulse will be nothing more than a glitch. The spacer loop is executed so fast (or maybe even optimized out) that it will not have a great effect. Also remember to set the scope to trigger on the rising edge since the default is low. Is it a storage scope?

Quote:

wait_us

void wait_us( int us ) Waits a number of microseconds.

Variables us the whole number of microseconds to wait

You said you need a pulse of 960 ns which is quite close to 1 usec so try wait_us(1) instead:

void scan () {
    Start_pulse_Out = 1;
    wait_us(1);
    Start_pulse_Out = 0;
    lcd.locate(0,1);
    lcd.printf("Start Pulse!");
}

Gert

10 Jul 2011

Thanks, I'll try that when I get in tomorrow morning. We have a fairly nice storage scope and I'm certain that I had the wait loop timed to the exact need. Problem is that I did this several months ago and then got caught up in other issues.

I'll post some waveform pics tomorrow. Have the feeling that maybe I need to declare either pullup or pulldown on the output pin.

When I was trying to use p28, the pin stayed high no matter what I did and using p27 is the same thing except it is always low.

(btw, what did you do to get the formatting on the code to play nice?)

10 Jul 2011

The <<code>> <</code>> tags must begin at the start of the line otherwise placing it elsewhere just results in it being displayed inline.

10 Jul 2011

if you create a timing loop like this:

for (t=0; t<100; t++){
  __nop();
  __nop();
}

You will get a delay loop which will not be optimized out but it will be inconsistent because of possible timer interrupts. So if you need exactly 960ns you must switch off interrupts or use an external monoflop for example.

Gert

P.S. if you set a pin with DigitalOut it will sink and source by default (AFAIK), so no need for pullups.

10 Jul 2011

Hmm, my inputs are a 4Mhz clock pulse and the start pulse. I think I might try using the clock pulse to enable a counter on the clock pulses. On the next rising edge clock set the output pin high and then count four pulses and drop it low. I can slip a clock pulse for the trigger, or even two if I want. The main thing is that I get a clean four clock pulse width start fed to the scan bar.

11 Jul 2011

I have managed to get different port pins transitions about 40 nsecs each transition , which is not perhaps the best I can get from a 96 Mhz Arm .. 40 nsec equals to only about 24 Mhz .... , Is there a better code for achieving faster transitions ? this is the "not so fast code ".... http://mbed.org/users/bitman/programs/howfast

#include "mbed.h"

DigitalOut red(p5);
DigitalOut green(p6);
DigitalOut blue(p7);
DigitalOut flag(p8);
int main() {
    while (1) {
        flag = !flag;  // toggle pin 8 so we have a period indication....
        // check period
        red=1;//  these transitions take about 40 nsec ,ie  red>1 to blue>1 almost 40nsecs
        blue=1;
        green=1;
        blue=0;  // 
        green=0;//
        red=0; //
        red=1;    // this transition 0->1 is possibly too short for my  analyser 
                  //(24Msamples/sec= 40 nsec resolution ) and is not captured ! 
        red=0;     // ??

        wait(0.001);
    }
}

11 Jul 2011

You might try Ivo van Poortens fastlib library http://mbed.org/users/Ivop/, I used it for my QVGA project and also tried his direct VGA output for the mbed. It works by direct accessing the set/reset registers of an output port, it also means you have to preshift your data and set appropriate masks to not disturb other pins/functions.

Although I think 40 nsec is not bad for a compiled routine, also consider the interrupt response time is somewhere in the order of at least 120 nsec.

11 Jul 2011

Thanks . They seem very nice projects ! both yours and Ivo's

BTW , I dont know if I was exact , 40 nsec is the time from "red" pin to "blue" pin transition , etc , I edited again the code comments for clarity.

However , I dont know if it is a problem with the logic analyser I used ( 24Msamples/sec max ) or the mbed compiler produced faster transition code but the logic analyser did not capture the last transient , "red" pin change state 0>1>0 !!!

I have to borrow an even faster logic analyser to capture port out improvements with fastlib !!!

this image shows shows the above mentioned transitions , but with a different red 1>0> 1 final transition that is not captured with my analyser as well ! . first line is red pin , then green , then blue , then flag .

/media/uploads/bitman/howfast.jpg

12 Jul 2011

on what signal is the analyzer triggered ?

13 Jul 2011

Michael (X M?),

At 28 Mega-samples per second, the logic analyser has a sample period of 42 ns, so it cannot see anything faster. In addition, the mbed outputs have rise and fall times around 15 ns. The best bet for seeing signals in the time frame you are discussing would be an oscilloscope with at least 150 MHz bandwidth.

As previously noted, the interrupt response delay of 120+ns might be a problem for your intended purpose. If the mbed has nothing else to do, you might connect both the input 4 MHz clock and the input Start signal to mbed digital inputs. Then run something like the following (psuedo-code) in main() -

while (1) { // do forever
  while (Start_pulse_In == 0) ; // wait for input start pulse
  while (Clock_In == 1) SET_START_OUT; // copy start pulse (Macro TBD)
  while (Clock_In == 0) ; // finish first clock
  while (Clock_In == 1) ; // begin second clock
  while (Clock_In == 0) ; // finish second clock
  while (Clock_In == 1) ; // begin third clock
  while (Clock_In == 0) ; // finish third clock
  while (Clock_In == 1) ; // begin fourth clock
  while (Clock_In == 0) ; // finish fourth clock
  CLEAR_START_OUT; // finish extended Output pulse (Macro TBD)
}

Adapt the above scheme as needed to match actual start pulse polarity, clock phase, etc.

P.S. If your goal is to learn about the mbed, then fine. But your stated goal may be better accomplished with a few low-voltage TTL flip-flop and gate chips (less parts, less cost, less board space, less signal jitter, etc.).

13 Jul 2011

@Fred . Name is Christos ( χρηστος in greek ) but I have put the initials for possible unicode errors .... I understand I am pushing this logic analyser to the limits .... it is a 24Msps usbee model connected to my laptop through usb , with about 40 nsec resolution . the problem is 100% the logic analyser , but my question was why did it capture the transients between different pins , red to blue , ( as seen in my previous picture )etc and not the red>red>red one which is marked with hand in the end ?

Perhaps same pin transient is a little bit faster than different pin changes , perhaps 30 something nsecs , and so the logic analyser missed it ! This test had nothing to do with interrupts , just pushing mbed and compiler to check its speed !!!

@Gert . the analyser stores 1 sec data to my laptop , so I suppose it is not trigger issue... the above picture is zoomed 160 nsec between lines x1 and x2 of the 1 sec captured buffer .

13 Jul 2011

Christos,

I would guess that the digital-out method uses the port hardware mask to limit which bits of the output port are written. When different bits are written the code sequence produced by the compiler would be 'mask-port-mask-port...'. When you write a series of values to the same bit the sequence would be 'mask-port-port-port...'. Thus your last pulse durations are probably only 10 or 21 ns, too short for the logic analyser and/or too attenuated by the mbed's 15 ns rise and fall times. Again, a fast oscilloscope is what is needed to see the 'runt' pulses. The 1768 documents say (for example) that the clock-out pin will not work for clocks faster than 48 MHz. This is probably another example of the rise/fall time limit.

Try adding no-ops on both sides of the final 'red = 1;', and check more than one episode in your one second of captured data to see if the runt pulses occasioanlly line up with the LA's sample timing. You might see a 'beat pattern' in the caught and missed (21 ns) pulses that prove it is due to a sampeling artifact.

13 Jul 2011

With this I ran to the limits of my display but maybe even the mbed too:

    // direct access pointer to port0
    volatile uint32_t *myport0= (volatile uint32_t *) 0x2009c000;

    // shift a line of the framebuffer out
    for (t=120; t>0; t--) {            // 120 bytes to go (counting down is faster)
        *(myport0+7)=0x00000FF0;       // clear all 8 data bits of port0
        *(myport0+6)=1|(*pointer++)<<4; // set the 1 bits of a framebuffer byte on port0 and CL2
        __nop();                       // slow down
        __nop();                       // and stretch CL2
        *(myport0+7)=1;                // now reset CL2 to 0;
    }

CL2 (port0.0) is the data clock for the display, with no nops the display did not respond at all, with a single nop the display began to respond but with errors and with 2 nops it was perfect. I did not check with a scope or analyzer though.