chiark / gitweb /
new make-clocks program and some initial work for it
authorian <ian>
Mon, 19 Dec 2005 02:46:57 +0000 (02:46 +0000)
committerian <ian>
Mon, 19 Dec 2005 02:46:57 +0000 (02:46 +0000)
detpic/.cvsignore
detpic/make-clocks [new file with mode: 0755]
detpic/program.clocks [new file with mode: 0644]

index fa24f632f4721c996c0ef8ba96494907175d0961..f9c4ae6f11e8bbf4a66b2588ee037b8e0584ae2e 100644 (file)
@@ -1,4 +1,5 @@
 *+morse.asm
+*+clocks.inc
 *.cod
 *.hex
 *.lst
diff --git a/detpic/make-clocks b/detpic/make-clocks
new file mode 100755 (executable)
index 0000000..a121e62
--- /dev/null
@@ -0,0 +1,109 @@
+#!/usr/bin/perl -w
+
+use strict qw(vars);
+use POSIX;
+
+our ($name,$ms,$interval,$msclock);
+# $interval is in seconds
+# mclock or sclock is in kHz
+# ourtimerclock is mclock or sclock * 250 (for Fosc/4)
+# call 250 foscscale
+# basically interval = cycles / clock
+# adjusted for units  interval = cycles * prescale / (foscscale * msclock)
+#                 ie  cycles = interval * foscscale * msclock / prescale
+#                 or  msclock = cycles * prescale / (foscscale * interval)
+
+sub p ($) { print $_[0] or die $!; }
+
+sub scaleable ($$$$$) {
+    my ($width, $foscscale, $scalebitnums, $scales, $deadcycles) = @_;
+    my ($maxcycles, $scalespec, $scalebits, $maxmsclock);
+    my ($lastmaxmsclock, $cycles_per_msclock, $cyclesexpr, @scalebits);
+    my ($prescale, $shift);
+    $maxcycles = (1 << $width) - $deadcycles;
+    foreach $scalespec (@$scales) {
+       $scalespec =~ m/^(\d+)\:([01]+)$/;
+       ($prescale,$scalebits) = ($1,$2);
+       length($scalebits) == @$scalebitnums
+           or die "$scalespec @$scalebitnums";
+       $maxmsclock= floor($maxcycles * $prescale / ($foscscale * $interval));
+       p(" if");
+       p(" $msclock > $lastmaxmsclock &&") if defined $lastmaxmsclock;
+       p(" $msclock <= $maxmsclock\n");
+       if (length($scalebits)) {
+           p("${name}scale equ ");
+           @scalebits = (map { "(1<<$_)" }
+                         grep { $scalebits =~ s/^.// or die; $&; }
+                         @$scalebitnums);
+           push @scalebits, '0' unless @scalebits;
+           p(join '|', @scalebits);
+           p("; $prescale:1\n");
+       }
+       $cycles_per_msclock = $interval * $foscscale / $prescale;
+       $shift = 31 - ceil(log($maxmsclock * $cycles_per_msclock) / log(2.0));
+       p(sprintf "%scycles equ (%s * %d) >> %d\n",
+         $name, $msclock, $cycles_per_msclock * (1<<$shift), $shift);
+       $cyclesexpr= sprintf("(%d - %scycles)",
+                            (1<<$width) - $deadcycles, $name);
+       if ($width == 16) {
+           p("${name}inith equ $cyclesexpr / 256\n");
+           p("${name}initl equ $cyclesexpr & 255\n");
+       } elsif ($width == 8) {
+           p("${name}init equ $cyclesexpr\n");
+       } else {
+           die "$width";
+       }
+       p(" endif\n");
+       $lastmaxmsclock= $maxmsclock;
+    }
+    p(" if $msclock > $lastmaxmsclock\n");
+    p("  error \"clock speed too high for $name\"\n");
+    p(" endif\n");
+}
+
+sub do_T13ov ($) {
+    my ($n) = @_;
+    local ($name) = "${name}_t${n}";
+    scaleable(16, 250.0, ["T${n}CKPS1","T${n}CKPS0"],
+             [qw(1:00 2:01 4:10 8:11)], 1);
+}
+
+sub do_T0ov ($) {
+    my ($w) = @_;
+    local ($name) = "${name}_t0";
+    scaleable($w, 250.0, ["PSA","T0PS2","T0PS1","T0PS0"],
+             [qw(1:1000 2:0000 4:0001 8:0010 16:0011
+               32:0100 64:0101 128:0110 256:0111)], 1);
+}
+
+sub do_T0ov8 { do_T0ov(8); }
+sub do_T0ov16 { do_T0ov(16); }
+sub do_T1ov { do_T13ov(1); }
+sub do_T3ov { do_T13ov(3); }
+
+sub doline () {
+    my ($orgname,$mswant,$unit,$how);
+    chomp;
+    s/[;\#].*//;
+    return unless m/^\S/;
+    die "$_ ?" unless
+       m/^(\w+)\s+(M|S|MS)\s+(\w+)\s+([0-9.]+)(s|ms|us|ns|Hz|kHz|MHz)$/;
+    ($orgname,$mswant,$how,$interval,$unit) = ($1,$2,$3,$4,$5);
+    if ($unit =~ m/M/) { $interval *= 1.e6; }
+    if ($unit =~ m/k/) { $interval *= 1.e3; }
+    if ($unit =~ m/m/) { $interval *= 1.e-3; }
+    if ($unit =~ m/u/) { $interval *= 1.e-6; }
+    if ($unit =~ m/n/) { $interval *= 1.e-9; }
+    if ($unit =~ s/Hz//) { $interval = 1.0 / $interval; }
+    foreach $ms (qw(m s)) {
+       next unless $mswant =~ m/$ms/i;
+       $msclock= "${ms}clock";
+       $name = $orgname.'_'.($ms eq 'm' ? 'master' : 'slave');
+       p(";---------- $name ----------\n");
+       &{ "do_$how" };
+    }
+}
+
+while (<>) {
+    doline();
+}
diff --git a/detpic/program.clocks b/detpic/program.clocks
new file mode 100644 (file)
index 0000000..073a9f3
--- /dev/null
@@ -0,0 +1,12 @@
+# Each line is:
+#  <name>      M|S|MS          how     interval
+# where how is one of
+#  T1ov T3ov
+#      set  T[13]CON to  <stuff> | <name>_{master,slave}_t[13]scale
+#      load TMR[13][HL] with  <name>_{master,slave}_t[13]init[hl]
+#       or to put it another way, TMR[13] with
+#              65535 - <name>_{master,slave}_t[13]cycles
+#      then time to overflow will be specified time
+
+#morse         MS      T0ov16          66ms
+points         MS      T3ov            20ms