ugly color :-)
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 = "<font color='FF0000'>";
$L2 = "</font>";
$C1 = "<font color='009900'>";
$C2 = "</font>";
$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 = "<font color='009900'>";
$C2 = "</font>";
$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;
}
// -------------------------------------------------
// -------------------------------------------------
?>