Alpha testing of new AVR calculator

Go To Last Post
74 posts / 0 new

Pages

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

microcarl wrote:
With all of the requests for code generation, it looks like I could have just forgone the PM requesting the same...
Well, I am considering code generation. But, the next step I plan after adding some more computations is to add an AVR part browser. By having a comprehensive list of parts, their modules, registers, and bitfields, that'd be a natural next step before adding code generation.

Thanks for all your suggestions and feedback thus far.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

uidzer0, thanks for your clarification.
I created a new user with admin-rights, in the same group as I am in, as user, and root is. When logged in as admin, I still don't get access to the folder /usr/local/bin. Very frustrating. Apparently, Linux i.c. Ubuntu is not meant for people like me. Too complicated. I give up. On Linux, that is.

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tessa and Tina, You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kmr wrote:
Quote:
(...)And I hate to be a nitpick, but where did the 5.5MB for a single for application come from?
The Lisp runtime libraries. Advatage: using those libraries allows the program to be compiled on Windows, Linux, and Mac. Though, I don't own the Mac compiler. (...)

You got to try TCL/Tk on your next version. On Linux, the interpreter is already installed, on Windows you can compress everything in less than 2MB, and the script code is always ready to run on both platforms (and others) :).

Embedded Dreams
One day, knowledge will replace money.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kmr wrote:
(...) But, the next step I plan after adding some more computations is to add an AVR part browser. By having a comprehensive list of parts, their modules, registers, and bitfields, that'd be a natural next step before adding code generation.

Suggestion: use the XML files from AVRStudio.

Embedded Dreams
One day, knowledge will replace money.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Plons wrote:
uidzer0, thanks for your clarification.
I created a new user with admin-rights, in the same group as I am in, as user, and root is. When logged in as admin, I still don't get access to the folder /usr/local/bin. Very frustrating. Apparently, Linux i.c. Ubuntu is not meant for people like me. Too complicated. I give up. On Linux, that is.

Nooo! Don't give up! You'll have to be a root user to copy the file there, after that you're good.

sudo -s
[enter root password]
cp ./kavrcalc /usr/local/bin
exit

If you're still stuck let me know and I'll be happy to help out.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nuno wrote:
Suggestion: use the XML files from AVRStudio.
It's a good suggestion. I already have written the XML parser and tree-walker to extract information from those files. I need to clarify with Atmel, though, what rights one has to reuse the data in those files in other applications.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nuno wrote:
You got to try TCL/Tk on your next version. On Linux, the interpreter is already installed, on Windows you can compress everything in less than 2MB, and the script code is always ready to run on both platforms (and others) :).
I'm quite familiar with TCL and Tk. You're right, they do have good cross-platform graphic tools. But, as a language, Common Lisp has much greater powers of abstraction making creation of complicated programs rather simple. Plus, it's compiled to native code rather than interpreted. For a simple calculator, Common Lisp can be considered overkill. But, I have plans for extension beyond the calculator.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kmr wrote:
(...) Plus, it's compiled to native code rather than interpreted. For a simple calculator, Common Lisp can be considered overkill. But, I have plans for extension beyond the calculator.

Todays PCs are quite fast. Even in TCL you can do amazing things... what have you in mind that you need so much computing power for :)?

Embedded Dreams
One day, knowledge will replace money.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Nuno wrote:
Todays PCs are quite fast. Even in TCL you can do amazing things... what have you in mind that you need so much computing power for :)?
I certainly agree about the speed of modern PCs. If TCL/Tk was a better language for programming, I'd use it even if it was interpreted. But, I'm choosing a much more powerful language to program in. Due to it's powerful macro capabilities and the ability to use data as compiled code, Lisp is commonly used in DSL (domain specific languages) applications -- if that gives you an idea where I'm going.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kmr wrote:
Here's a screenshot from the latest version for people deciding whether to download or not.
Kevin,

After seeing a number of appends about this tool, I decided to download it. The referenced append does not contain the link. Then I tried the link in the very first append and that failed too. Would you mind editing your posts to put in the correct link so other people don't spend time searching on how to download your tool.

I tried it and it looks good. I have some feedback to improve the user interface:

  • Separate out the clock speed into a nice box - it is kinda underwhelmed at the far far top left of the window.
  • I cannot type a desired baud rate - only choose from a supplied range which is missing the higher speeds by the way as well. I would also like to type in a UBRR value and see the baud rate.
  • The format for the values in the Clock speed drop down is inconsistent with the list of common clocks i.e. how are you going to specify 1MHz; as 1.0 or 1.0000?
  • The background color for the text is slightly different to the color for the window itself. I find this harder to read but this is a nit. The two colors are white (255, 255, 255) and "off-white" (255,251,240).
  • Rather than one very large window, I preferred the tabbed pane approach. Each distinct function is on a separate pane with of course the clock speed common to all tabs. This also allows use to add new function such as TWI SCL frequency or SPI SCK frequency.
  • Some help on how to use the various parts of the interface would be extremely helpful. Some aspects of the UI need "discovery".

--Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mikeperks wrote:
Would you mind editing your posts to put in the correct link so other people don't spend time searching on how to download your tool.
I appreciate your suggestions very much, Mike. I imagine I'll be able to incorporate most of them in my next release. An answer to one question follows:
Quote:
The format for the values in the Clock speed drop down is inconsistent with the list of common clocks i.e. how are you going to specify 1MHz; as 1.0 or 1.0000?
Well, 1 and 1.0 and 1.0000 are all the same numeric value. What's your idea? Have them all be the same number of decimal places?
Quote:
Rather than one very large window, I preferred the tabbed pane approach. Each distinct function is on a separate pane with of course the clock speed common to all tabs. This also allows use to add new function such as TWI SCL frequency or SPI SCK frequency.
That's a reasonable idea. I've been using tab panes for adding the AVR Part Explorer. I might be able to integrate its tabbed panes along with the calculator's tabbed panes.
Quote:
Some help on how to use the various parts of the interface would be extremely helpful. Some aspects of the UI need "discovery".
Quite true. My plan was to work on that after adding whatever features that will be stable after the initial feature expansion stage.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

A calculator application is nice for the design phase and play "what-if". When you get to implementation, I like to have the computer do the math for me instead of having "meanless" constants around. I wrote a small pre-processor to calculate timer constants. This means that I can use "extra functions" in my code, like:

[[t0cnt_us period_us]]  (calculate TCNT0 for 'period_us' given in us)

which allows me to do code or macros like this one:

#define timer0_SetupPeriodicHz(frequency) \
        { \
            TCCR0 = 0; \
            TCNT0 = [[t0cnt_hz frequency]]; \
            TCCR0 = (TCCR0 & 0xF8) | [[t0pre_hz frequency]]; \
            TIMSK |= _BV(TOIE0); \
        }

The code generated is "constant" so there's no run-time penalties.
My pre-processor (I call it AVR-CPP) is inserted as the 2nd compilation stage (after C preprocessing), and is perfectly integrated with the C toolchain (WinAVR) in a way that, if there's any error, the correct source code lines are always displayed.
Here's an extract example of a compilation output:

> make.exe all
avr-gcc -pipe -g -I. -O2  -Wall -mmcu=attiny26 -DF_CPU=6000000UL -Werror  -E -o stepdriver.i.tmp stepdriver.c
tclsh.exe avrcpp.tcl -mcu=attiny26 -fcpu=6000000UL  -in=stepdriver.i.tmp -out=stepdriver.i
AVR-CPP: attiny26 @ 6.0 MHz
	208 us - 1 8 64 256 1024
	FREQ Timer 0: 4800Hz, div 100
	208 us - 1 8 64 256 1024
	FREQ Timer 0: 4800Hz, pres 2 (/8)
	F = 4807 Hz
rm -f stepdriver.i.tmp
avr-gcc -pipe -g -I. -O2  -Wall -mmcu=attiny26 -DF_CPU=6000000UL -Werror  -c -o stepdriver.o stepdriver.i
(...)

The CPP picks up stepdriver.c and runs it only through the CPP outputting stepdriver.i.tmp. Then my AVR-CPP picks it and generates stepdriver.i, which is then finally handed-over to the compiler. This is all done in a makefile, of course.

I targeted AVR-CPP at my needs at the time, which were counters on tiny26 so that's what it supports. But would be nice to have it for everything on all AVR models, and even have more complex functions too, like generating pieces of code and not only constants calculation. This is a suggestion to where you could head your application next :).

Embedded Dreams
One day, knowledge will replace money.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Interesting idea about the preprocessor, Nuno. With the C preprocessor and static functions, gcc (and iar) can do a lot of the computation at compile-time. Like the setbaud.h header file floating around that automatically calculates a UBRR and displays a C #error if the error rate for the requested baud is too high. But, your C preprocessor obviously can do more than just the C preprocessor -- cool thing!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

kmr wrote:
[Well, 1 and 1.0 and 1.0000 are all the same numeric value. What's your idea? Have them all be the same number of decimal places?

Yes, use the same number of decimal places for a particular number so 1MHz is always written as 1.0 for example.

--Mike

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Okay, Mike. I changed to formatting so that clock rate is always display with the same (6) number of decimal places. That number of decimal places was to support the lowest clock speed of 0.032768 MHz

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kevin,

I get this error when I try to run under XP. Works great on another machine with Windows2000.

Quote:
This application has failed to start because the application configuration is incorrect. Reinstalling the application may fix this problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have XP (home edition? not the pro one) and not problems with the calculator.

Embedded Dreams
One day, knowledge will replace money.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Same here: WinXP-home: no problems

Nard

A GIF is worth a thousend words   They are called Rosa, Sylvia, Tessa and Tina, You can find them https://www.linuxmint.com/

Dragon broken ? http://aplomb.nl/TechStuff/Dragon/Dragon.html for how-to-fix tips

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the report, Dave. I'm finishing up a number of new features for the next release. Would you mind testing some prelease versions (and maybe a few other tests) on your XP system to assist in discovering what is causing the .exe problems on some Windows systems?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sure thing.

Dave

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, Dave. I'll send you PM when the next release is ready for initial testing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Kevin

Found the source code, whether this is any help.
http://www.home.unix-ag.org/tjabo/avr/dlg_02/src_coder.php
http://www.home.unix-ag.org/tjabo/avr/dlg_02/dlg_02.tgz

Quote:
Source of 'dlg02_coder.php'
The central code of my AVR delay loop generators.
License: GPL. Yes. Use it. :-)
Some functions are very ugly, especially burn_level_2. I think I'll reinvent that wheel...

Have phun, tk.

  // Author: Tjabo Kloppenburg (tjabo at  unix-ag.org)
  // Date: 08.Dez2002
  // Version: 0.0.1 (without level 3)

  // Disclaimer: The license of this file is the GPL, so use the
  //             code and spread it.
  // If you find bugs or have a better idea for LEVEL2, please send
  // me an email.

  // In this file you find the following core functions:
  

  // Nice output of AVR Code:
  /*
  function getNewLabel( $prefix="L" ) {
  function printCodeLine( $label="", $code="", $comment="" ) {
  function printCommentLine( $comment="" ) {
  */

  // helper functons:
  /*
  function byte2hex( $b ) {
  */

  // how many bytes does the start/end code take?
  // "burn" because of the heat generated when doing active delays...
  /*
  function num_start_code_cycles( $num ) {  // RCALL
  function burn_start_code( $num ) {
  function num_end_code_cycles( $num ) {    // RET
  function burn_end_code( $num ) {
  */


  // Level0: NOPs, Level1: 1 register, Level2: 2 rgisters:
  /*
  function burn_level_0( $num ) {

  function level_1_get_cycles( $startvalue ) {
  function burn_level_1( $num ) {

  function level_2_get_cycles( $A, $B ) {
  function burn_level_2( $num ) {
  */



  // time burn functions, generation of delay loops:

  function getNewLabel( $prefix="L" ) {
    global $LABEL_NUMBER;
    $LABEL_NUMBER += 1;
    $tmp = "" . $prefix . $LABEL_NUMBER;
    return $tmp;
  }


  function printCodeLine( $label="", $code="", $comment="" ) {
    $column1 = 10;
    $column2 = 15;

    $L1 = "";
    $L2 = "";
    $C1 = "";
    $C2 = "";

    $label = $label == "" ? " " : "$label:";

    while (strlen($label) < $column1) $label .= " ";
    while (strlen($code)  < $column2) $code  .= " ";

    $tmp  = "$L1$label$L2 $code";
    $tmp .= ($comment == "") ? "\n" : " $C1;$comment$C2\n";
    print $tmp;
  }


  function printCommentLine( $comment="" ) {
    $C1 = "";
    $C2 = "";
    $comment = $comment == "" ? "\n" : "$C1; $comment$C2\n";
    print $comment;
  }



  function num_start_code_cycles( $num ) {
    global $callmethod, $pcwidth;
    if ($callmethod == "rcall") {
      if (($pcwidth==16) && ($num >= 3))  {
        return 3;
      }
      if (($pcwidth==22) && ($num >= 4))  {
        return 4;
      }
    }
    return 0;
  }

  function burn_start_code( $num ) {
    global $callmethod, $pcwidth;
    $numcycles = num_start_code_cycles( $num );
    if ($callmethod == "rcall") {
      $n = getNewLabel();
      printCodeLine( $n, "", "RCALL $n ($numcycles cycles / $pcwidth Bit PC)" );
      return $numcycles;
    }
    return 0;
  }

  function byte2hex( $b ) {
    return sprintf("%02X", $b);
  }


  function num_end_code_cycles( $num ) {
    global $callmethod, $pcwidth;
    if ($callmethod == "rcall") {
      if ($pcwidth==16) {
        return 4;
      }
      elseif ($pcwidth==22) {
        return 5;
      }
      else {
        print "unknown pc width. in num_end_code_cycles()\n";
      }
    }
    return 0;
  }


  function burn_end_code( $num ) {
    global $callmethod, $pcwidth;

    $cycles_needed = num_end_code_cycles( $num );

    if ($cycles_need >= $num ) {
      if ($callmethod == "rcall") {
        printCodeLine( "", "ret", "return (" . $cycles_needed . " cycles, $pcwidth Bit PC)" );
        return $cycles_need;
      }
    }
    else {
      print "out of cylces, burn_end_code()\n";
      return 0;
    }
    return 0;
  }


  // -------------------------------------------------
  // -------------------------------------------------
  // Level 0 construction:
    /*
           nop  [nop...]
           ...
    */
  function burn_level_0( $num ) {
    printCodeLine( "", "", "$num NOPs:" );
    for ($i = 1; $i <= $num; $i++ ) {
      printCodeLine( "", "nop", "" );
    }
    return $num;
  }


  // -------------------------------------------------
  // -------------------------------------------------
  // Level 1 construction:
    /*
           ldi Rxx, $xx
       L0: dec Rxx
           brne L0
           ...
    */

  // -------------------------------------------------
  function level_1_get_cycles( $startvalue ) {
    if ($startvalue == 1) {
      return 3;
    }
    return ( 1 + (($startvalue - 1) * 3) + 2);
  }
  // -------------------------------------------------

  function burn_level_1( $num ) {
    global $registers;

    if (count($registers) == 0) {
      return 0;
    }

    if (($num >= 3) && ($num <= ( (254*3) + 255*2 ))) {

      // find start value for loop:
      $found = false;
      $test  = 256;
      while ((! $found ) && ($test >= 1)) {
        $can_do = level_1_get_cycles( $test );
        $found = ( $can_do <= $num );
        if (!$found) { $test -= 1; }
      }

      if ($found) {
        $val  = ($test == 256) ? 0 : $test;
        $val2 = byte2hex( $val );

        $Rxx = $registers[0];

        $n = getNewLabel();
        printCodeLine( "", "ldi $Rxx, \$$val2", " = $val (decimal)" );
        printCodeLine( $n, "dec $Rxx"         , ""                  );
        printCodeLine( "", "brne $Rxx, $n"    , "loop" );

        return round(level_1_get_cycles( $test ));
      }

    }
    return 0;
  }
  // -------------------------------------------------
  // -------------------------------------------------

  // Level 2 construction:
    /*
           ldi Rxx, $xx   1
       L0: ldi Ryy, $yy   1    ___
       L1: dec Ryy        1     |
           brne L1        2/1  _|_1 X
           dec Rxx        1
           brne L0        2/1
           ...
    */

  // -------------------------------------------------
  function level_2_get_cycles( $A, $B ) {
    // $A = $A == 0 ? 256 : $A;
    // $B = $B == 0 ? 256 : $B;

    // annahme: A  != 1 und B != 1:
    $X = (($A - 1)*(1+2)) + (1+1);
    $Y = 1 + (($B - 1)*(1+$X+1+2)) + (1+$X+1+1);

    return $Y;
  }
  // -------------------------------------------------


  function burn_level_2( $num ) {
    global $registers;

    $bestes_a = 1;
    $bestes_b = 1;
    $bestes_unter_diff = 50000;
    $found = false;

    for ($i = 1; $i <= 256; $i++) {
      $j = 1;
      $abbruchJ = false;
      while (($j <= 256) && (! $abbruchJ )) {
        $Y = level_2_get_cycles( $i, $j );
        if ($Y <= $num) {
          if (($num - $Y) < $bestes_unter_diff) {
            $bestes_a = $i;
            $bestes_b = $j;
            $bestes_unter_diff = $num - $Y;
            $found = true;
          }
        }
        else {
          $abbruchJ = true;
        }
        $j += 1;
      }
    }
    if ($found) {
      $gain = level_2_get_cycles( $bestes_a, $bestes_b );
      printCommentLine( "LEVEL 2 LOOP: gain=$gain");

      $val1  = ($bestes_a == 256) ? 0 : $bestes_a;
      $val2  = ($bestes_b == 256) ? 0 : $bestes_b;

      $val1h = byte2hex( $val1 );
      $val2h = byte2hex( $val2 );

      $Rxx = $registers[0];
      $Ryy = $registers[1];

      $n = getNewLabel();
      $m = getNewLabel();

      printCodeLine( "", "ldi $Rxx, \$$val1h", " \$$val1h = $val1 (decimal)" );
      printCodeLine( $n, "ldi $Ryy, \$$val2h", " \$$val2h = $val2 (decimal)" );
      printCodeLine( $m, "dec $Ryy", "" );
      printCodeLine( "", "brne $m" , "" );
      printCodeLine( "", "dec $Rxx", "" );
      printCodeLine( "", "brne $n" , "" );
      return $gain;
    }

    return 0;
  }

  // -------------------------------------------------
  // -------------------------------------------------

Ken

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Ken, thanks for looking for the file. I've already got a delay code generator written, but I appreciate your effort.

Pages