Shop OBEX P1 Docs P2 Docs Learn Events
Duplicating A 16-bit Timer At 16MHz - Page 2 — Parallax Forums

Duplicating A 16-bit Timer At 16MHz

2»

Comments

  • idbruceidbruce Posts: 6,197
    edited 2015-03-13 16:06
    I am beginning to think that I am over thinking this.....

    F_CPU equals the clock frequency going into the formulas and algorithms. So let's say that F_CPU equals 80MHz instead 16MHz, by the time it comes out of all the calculations, the only thing that I really need to worry about is buffer overrun. Providing that does not happen, the input intended for a 16 bit !6MHz timer, should already be set for an 80Mhz timer. Could it be so? Hmmmmm......

    On the other hand, worse case scenario, I could just swap out my crystal, and with the correct PLL, I could obtain 16MHz.
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-03-13 17:55
    Bruce,

    If solving puzzles is your thing, keep doing what you're dong. There are lots to solve.

    However, if making teacup run on the propeller is your thing, take a step back. If I give you bricks and tell you to build a house of wood, you don't grind the bricks into soil, plant trees and build a house 300 years later... you go buy some wood! Accept that some parts of Teacup just aren't going to be usable and need to be re-written from the ground up for your brand new architecture. This timer thing... take Heater's advice. Figure out where it's being used (the steppers I guess) and re-write that code such that it works correctly on the Propeller.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-13 20:54
    David

    You make it sound so simple!
  • DavidZemonDavidZemon Posts: 2,973
    edited 2015-03-13 21:20
    idbruce wrote: »
    David

    You make it sound so simple!

    I don't mean it to. I only meant to imply that your current path is very complicated, and taking a step back might show that a different path is the lesser of two evils.
  • kwinnkwinn Posts: 8,697
    edited 2015-03-14 05:35
    David has a good point. Anything you can do with a 16 bit timer at 16MHz should be doable with a 32 bit timer at 80MHz. The key is to understand exactly what the code does. It's tempting to try and make use of the code "as is" with minimal changes, but not always practical. Perhaps it's time to figure out what the code does and modify it to work with what you have.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-14 06:34
    kwinn

    As it turns out, it may be much easier than I was making it out to be. I was so busy looking at the garbage code, that I did not see a 32 bit value staring at me. I am thinking that I may be able compute my values for a 80MHz uC, and the value that is passed to the 16-bit timer, well I may be able to just simply add the to CNT, as Jon suggested with
    sync := cnt
      repeat
        waitcnt(sync += looptix)
        ' loop code.
    

    or something along those lines.
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-14 07:30
    Bruce, in simulator/timer_ext.c there is a routine called sim_tick_counter, which looks like this:
    uint16_t sim_tick_counter(void) {
      if (time_scale) {
        // microseconds to 16-bit clock ticks
        return (now_us() / time_scale) US;
      }
      return (uint16_t)(ticks % 0xFFFF);
    }
    
    "US" is defined as "#define US * (F_CPU/1000000)". For real-time operation, time_scale has a value of 1. So the routine simplifies to:
    uint16_t sim_tick_counter(void) {
        // microseconds to 16-bit clock ticks
        return now_us() *  (F_CPU/1000000);
    }
    
    The routine now_us() gives the current time in micro-seconds based on the C time functions. now_us() returns a 64-bit value. Things can simplify even more if you use a value of F_CPU that is either 1/4th or 1/8th the Prop's clock rate. Then you don't have to use the actual time, but can just use CNT. So if F_CPU were 20MHz sim_tick_counter reduces to.
    uint16_t sim_tick_counter(void) {
      return (CNT >> 2);
    }
    
    Or you could even define it as a macro as "#define sim_tick_counter ((CNT >> 2) & 0xffff).
    If you think 20MHz is too high for F_CPU then use 10MHz, and use ((CNT >> 3) & 0xffff) instead.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-14 07:59
    Dave

    I will keep all that in mind, or at least I will remember your post here :)
    Then you don't have to use the actual time, but can just use CNT.

    If you remember, it took me a while to finally figure out where the Propeller port of Teacup actually needed to begin. My course of action was only determined by thorough examination of the code. Well the same holds true in this instance. Upon further study of the source code, I now believe that I can just use CNT. I believe it was there all the time and I just failed to realize it.

    Although I may not need this information, and I have asked this before (can't find the link), but what is the maximum value of CNT? Is it 4,294,967,295?
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-14 08:34
    Bruce, if I get some time today I'll try to port Teacup to the Prop using the method I suggested. Maybe then you'll understand what I'm suggesting. You can't just use CNT because all of the Teacup code assumes a 16-bit counter. If you set F_CPU to 80MHz you won't have enough range in the 16-bit variables to prevent overflows. I think you can get by with F_CPU set to 20MHz, but to be safe 10MHz would be better. Then you just use ((CNT >> 3) & 0xffff) for the system counter.

    You could use F_CPU set to 16MHz, but then the math becomes more complicated. Your system counter then becomes ((CNT/5) & 0xffff). However, the problem with CNT/5 is that it glitches when the counter wraps. To prevent the glitches you would have to include a counter that counts every time the counter wraps, and uses the wrap count as the upper 32 bits of a 64-bit counter. So if you did that you could use F_CPU set to 16MHz, and your 16-bit system counter then becomes ((cnt64/5) & 0xffff). However, I don't think that's worth the trouble, and it would be better to use 20 or 10 MHz.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-14 09:09
    Dave
    If you set F_CPU to 80MHz you won't have enough range in the 16-bit variables to prevent overflows.

    :)

    I suppose what I should tell you is this......

    Tracing the variables all the way back from setTimer ---> calculations performed by formulas and algorithms ----> DDA structure

    They are all 32 bit

    EDIT: However, I may have a problem with LOOKAHEAD, but this is only limiting the feedrate of endpoint.F, which is actually 32 bit also.
    		// Lookahead can deal with 16 bits (= 1092 mm/s), only.
    		if(dda->endpoint.F > 65535)
    		{
    			dda->endpoint.F = 65535;
    		}
    
  • Dave HeinDave Hein Posts: 6,347
    edited 2015-03-14 10:33
    Yes, I realize you can rip out all the AVR code and avoid the 16-bit problem. But then you have to change a lot of code. Retaining the 16-bit AVR code minimizes the amount of changes that you have to make.
  • idbruceidbruce Posts: 6,197
    edited 2015-03-14 10:45
    Dave
    Yes, I realize you can rip out all the AVR code and avoid the 16-bit problem. But then you have to change a lot of code. Retaining the 16-bit AVR code minimizes the amount of changes that you have to make.

    Although not finished completely, the ADS1015 code ripped out most of the AVR source already and the last remaining significant portion of AVR code is the step timer. From there it is just little bits and pieces. Most of the code should be pretty close to being finished, with the exception of that timer, and finishing up the ADS1015 code.

    Besides those two items, the rest could probably be finished in an afternoon.
Sign In or Register to comment.