r11572: new deb pkg
[cluck.git] / cluck.lisp
1 ;;;; -*- Mode: LISP; Syntax: ANSI-Common-Lisp; Base: 10 -*-
2 ;;;; *************************************************************************
3 ;;;; FILE IDENTIFICATION
4 ;;;;
5 ;;;; Name:          cluck.asd
6 ;;;; Purpose:       Common Lisp uControler Clock Calculator
7 ;;;; Programmer:    Kevin M. Rosenberg
8 ;;;; Date Started:  March 2007
9 ;;;;
10 ;;;; $Id$
11 ;;;;
12 ;;;; Copyright (c) 2007 Kevin M. Rosenberg
13 ;;;;
14 ;;;; Redistribution and use in source and binary forms, with or without
15 ;;;; modification, are permitted provided that the following conditions
16 ;;;; are met:
17 ;;;; 1. Redistributions of source code must retain the above copyright
18 ;;;;    notice, this list of conditions and the following disclaimer.
19 ;;;; 2. Redistributions in binary form must reproduce the above copyright
20 ;;;;    notice, this list of conditions and the following disclaimer in the
21 ;;;;    documentation and/or other materials provided with the distribution.
22 ;;;; 3. Neither the name of the author nor the names of the contributors
23 ;;;;    may be used to endorse or promote products derived from this software
24 ;;;;    without specific prior written permission.
25 ;;;;
26 ;;;; THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
27 ;;;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 ;;;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 ;;;; ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
30 ;;;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 ;;;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 ;;;; OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 ;;;; HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 ;;;; LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 ;;;; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 ;;;; SUCH DAMAGE.
37 ;;;; *************************************************************************
38
39 (defpackage #:cluck
40   (:use #:cl)
41   (:export
42    #:show-timers
43    #:show-8-bit-timers
44    #:show-16-bit-timers
45    #:show-32-bit-timers
46    #:ms-clocks
47    #:avr-uart-divisors
48    #:pic-uart-divisors
49    #:zero-error-uart-clocks))
50
51 (in-package #:cluck)
52
53 (defvar *f-cpu* 16000000)
54
55 (defvar *8-bit-prescalars* '(1 8 64 256))
56 (defvar *10-bit-prescalars* '(1 8 64 256 1024))
57
58 (defvar *base-error-zero-baud-clk* (* 9 25 8192)
59 "Base multiple for multi-megahertz clock frequencies to have
60 0% error at common UART baud rates. Value of this base is 1.8432 million.
61 Common multiples of this are 2 (3.6864Mhz), 4 (7.3728Mhz), 8 (14745600),
62 and 10 (18.432MHz)")
63
64 (defun show-timers (f-cpu prescalers width)
65   (let ((max-count (expt 2 width)))
66     (format t "~&Prescalar MaxRate     MinUS     MinRate        MaxMS~%")
67     (dolist (prescale prescalers)
68       (let ((base (/ f-cpu prescale)))
69         (format t "~4D ~12,1F ~9,3F ~10,4F ~13,3F~%"
70                 prescale
71                 (coerce base 'float)
72                 (coerce (/ 1000000 base) 'float)
73                 (coerce (/ base max-count) 'float)
74                 (coerce (/ 1000 (/ base max-count)) 'float))))))
75
76 (defun show-8-bit-timers (&optional (f-cpu *f-cpu*))
77   (show-timers f-cpu *10-bit-prescalars* 8))
78
79 (defun show-16-bit-timers (&optional (f-cpu *f-cpu*))
80   (show-timers f-cpu *10-bit-prescalars* 16))
81
82 (defun show-32-bit-timers (&optional (f-cpu *f-cpu*))
83   "Show max/min periods for 32-bit timers. For 16-bit PIC
84 controllers, 32-bit timers use 8-bit prescalers"
85   (show-timers f-cpu *8-bit-prescalars* 32))
86
87 (defun ms-timer-width (ms f-cpu prescalars width)
88   "Returns the prescalar and compare count for both 8 and 16 bit timers."
89   (labels ((nearest-count (prescale)
90              (let ((count (round (* ms (/ f-cpu 1000 prescale))))
91                    (max-count (expt 2 width)))
92                (cond
93                  ((< count 1)
94                    1)
95                  ((<= count max-count)
96                    count)
97                  ((> max-count)
98                    max-count))))
99            (clk-ms (prescale count)
100              (unless (zerop count)
101                (/ count (/ f-cpu 1000 prescale))))
102            (percent-error (actual desired)
103              (* 100 (- (/ actual desired) 1))))
104
105     (dolist (prescale prescalars)
106       (let* ((count (nearest-count prescale))
107              (clk-ms (clk-ms prescale count))
108              (err (percent-error clk-ms ms))
109              (fmt-err (if (> err 1000)
110                         "   >1000%"
111                         (format nil "~8,3F%" err))))
112         (format t "~2D  ~4D  ~5D ~10,4F ~A~%"
113                 width prescale count clk-ms fmt-err)))))
114
115 (defun ms-timer (ms &optional (f-cpu *f-cpu*))
116   "Returns the prescalar and compare count for both 8 and 16 bit timers."
117   (dolist (width '(8 16))
118     (ms-timer-width ms f-cpu *10-bit-prescalars* width)))
119
120 (defparameter *baud-rates* '(300 600 1200 2400 4800 9600 14400 19200 28800
121                              38400 56000 57600 76800 115200 128000 250000
122                              256000 500000))
123
124 (defun avr-uart-divisors (&optional (f-cpu *f-cpu*) (view-below-percent nil))
125   "Displays the divisor UBRR and error percent for various baud
126 rates for F_CPU. UBBR is limited to 12 bits."
127   (dolist (baud *baud-rates*)
128     (let* ((ubrr (min 4096
129                       (max 0 (round (- (/ f-cpu 16 baud) 1)))))
130            (ubrr2 (min 4096
131                        (max 0 (round (- (/ f-cpu 8 baud) 1)))))
132            (actual-baud (/ f-cpu 16 (1+ ubrr)))
133            (actual-baud2 (/ f-cpu 8 (1+ ubrr2)))
134            (err (* 100 (- (/ actual-baud baud) 1)))
135            (err2 (* 100 (- (/ actual-baud2 baud) 1))))
136       (when (or (not view-below-percent)
137                 (or (< (abs err) view-below-percent)
138                     (< (abs err2) view-below-percent)))
139         (format t "~6D ~4D ~5,1F% ~4D ~5,1F%~%"
140                 baud ubrr err ubrr2 err2)))))
141
142 (defun pic-uart-divisors (&optional (fcy *f-cpu*) (view-below-percent nil))
143   "Displays the divisor BRG and error percent for various baud
144 rates for Fcy. BRG is limited to 16 bits."
145   (dolist (baud *baud-rates*)
146     (let* ((brg (min 65536
147                      (max 0 (round (- (/ fcy 16 baud) 1)))))
148            (actual-baud (/ fcy 16 (1+ brg)))
149            (err (* 100 (- (/ actual-baud baud) 1))))
150       (when (or (not view-below-percent)
151                 (< (abs err) view-below-percent))
152         (format t "~6D ~4D ~5,1F%~%" baud brg err)))))
153
154 (defun zero-error-uart-clocks ()
155   (dolist (mult '(1 2 4 6 8 10 12))
156     (format t "~&~8,4F MHz~%" (* mult  *base-error-zero-baud-clk* 1e-6))))
157