-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadc.lisp
More file actions
100 lines (85 loc) · 3.96 KB
/
adc.lisp
File metadata and controls
100 lines (85 loc) · 3.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
(in-package :picflow)
(defstruct analog-output-handler
"A record for an output from the ADC daemon"
(output (make-output-record) :type output-record)
(input-number 0 :type (integer 0 7)))
(defclass adc-daemon (node)
((adc-callback :initform (c-gensym "adc_callback") :reader adc-callback)
(output-handlers :initform '() :accessor output-handlers))
(:documentation "This node handles global setup and scaffolding for
analog-to-digital conversion. It is not used directly, but instead
supports other nodes."))
(defmethod interrupt-vector-code-emit ((node adc-daemon))
(emit "if (PIR1bits.ADIF) ~A();" (adc-callback node)))
(defmethod prototype-code-emit ((node adc-daemon))
(emit "#include \"picflow_adc.h\"")
(emit "void ~A(void);" (adc-callback node)))
(defmethod init-code-emit ((node adc-daemon))
(emit "setADC~D();" (analog-output-handler-input-number (car (output-handlers node))))
(emit-file "include/adc_init.inc"))
(defmethod extra-code-emit ((node adc-daemon))
(emit "// Callback activated by ADC completion")
(emit "void ~A(void) {" (adc-callback node))
(with-indent ()
(emit-file "include/adc_callback_top.inc")
(loop for remaining-handlers on (output-handlers node)
for index from 0
for handler = (car remaining-handlers)
for at-end-p = (null (cdr remaining-handlers))
do (progn
(emit "case ~D: // AN~D" index (analog-output-handler-input-number handler))
(with-indent ()
(emit (call-output (analog-output-handler-output handler) "adres_tenbits"))
(if at-end-p
(emit "adc_output_state = 0;")
(emit "adc_output_state++;"))
(let ((next-input-number (analog-output-handler-input-number
(if at-end-p
(car (output-handlers node))
(cadr remaining-handlers)))))
(emit "setADC~D();" next-input-number))
(emit "break;"))))
(emit "} // end of switch-case block")
(emit-file "include/adc_callback_boilerplate.inc"))
(emit "}"))
(defparameter *adc-daemon* (make-instance 'adc-daemon)
"Global ADC daemon. There can be only one.")
(defun cleanup-adc-daemon ()
"Reset the ADC daemon"
(setf *adc-daemon* (make-instance 'adc-daemon)))
(eval-when (:load-toplevel :compile-toplevel :execute)
(pushnew 'cleanup-adc-daemon *cleanup-functions*))
;; Actual user-usable code for analog pins
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defclass analog-pin (node)
((input-number :initarg :input-number :reader analog-pin-input-number :initform 0
:documentation "The number of the analog input pin. 3
for AN3, 6 for AN6, and so on."))
(:documentation "An analog input pin. Outputs 10-bit analog values repeatedly."))
(defmethod method-> :before ((node analog-pin) a-in a-out a-form (b node) b-in b-out b-form)
(declare (ignore a-in a-out b-in b-out))
;; Analog pins need the ADC daemon to support them
(use-node *adc-daemon*)
;; Add the default (and hopefully only) output linkage to the list of
;; output handlers for the ADC daemon.
(pushnew (make-analog-output-handler :input-number (analog-pin-input-number node)
:output (gethash :default (outputs node)))
(output-handlers *adc-daemon*)
:key #'analog-output-handler-input-number))
(defun new-analog-pin (input-number)
"Return a new analog pin associated with input number INPUT-NUMBER"
(make-instance 'analog-pin
:output-names '(:default)
:input-names '(:default)
:input-number input-number))
;; These are the analog ports that are accessible at the moment. They
;; were chosen because they manage to avoid stepping on the toes of
;; other important bits of the PIC, like PORTB.
(defparameter *an0* (new-analog-pin 0))
(defparameter *an1* (new-analog-pin 1))
(defparameter *an2* (new-analog-pin 2))
(defparameter *an3* (new-analog-pin 3))
(defparameter *an4* (new-analog-pin 4))
(defparameter *an5* (new-analog-pin 5))
(defparameter *an6* (new-analog-pin 6))
(defparameter *an7* (new-analog-pin 7))