From: rearman Date: Sat, 7 Jan 2023 19:51:51 +0000 (-0500) Subject: Go to split config, add qmk functions X-Git-Url: https://git.earman.xyz/?a=commitdiff_plain;h=8972d7a09f74ef50af3fb0600ce217456101718e;p=emacsinit.git Go to split config, add qmk functions Splitting init.el into multiple *.el files in .emacs.d. Adding defuns and eshell alias for some qmk-related tasks - editing keymaps, and calling qmk msys. --- diff --git a/.gitignore b/.gitignore index dc85ccf..09386f9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ * !/eshell/alias -!/config -!early-init.el -!init.el +!/*.el diff --git a/bindings.el b/bindings.el new file mode 100644 index 0000000..5b8b11c --- /dev/null +++ b/bindings.el @@ -0,0 +1,43 @@ +;; -*- lexical-binding: t; -*- +;; BINDINGS +;; USER SPACE +(global-set-key (kbd "C-c a") 'org-agenda) +(global-set-key (kbd "C-c b") 'buffer-menu-other-window) +(global-set-key (kbd "C-c c") 'org-capture) +(global-set-key (kbd "C-c ei") 'edit-init) +(global-set-key (kbd "C-c r") 'rotate-windows) +(global-set-key (kbd "C-c s") 'eshell) +(global-set-key (kbd "C-c t") 'toggle-window-split) +(global-set-key (kbd "C-c w") 'edit-work-eqs) +(global-set-key (kbd "") 'recentf-open-files) +;; OVERRIDES +(global-set-key [remap move-beginning-of-line] 'smart-beginning-of-line) +(global-set-key (kbd "M-j") 'backward-join-line) +(global-set-key (kbd "M-S-j") 'join-line) +(global-set-key (kbd "C-S-k") 'kill-whole-line) +(global-set-key (kbd "C-o") 'open-line-below) +(global-set-key (kbd "M-o") 'open-line-above) +(global-set-key (kbd "M-s .") 'isearch-forward-thing-at-point) +(global-set-key (kbd "M-s M-.") 'isearch-forward-symbol-at-point) +(global-set-key (kbd "C-u") 'backward-kill-line) +(global-set-key (kbd "C-w") 'kill-bword-or-region) +(global-set-key (kbd "C-z") 'zap-up-to-char) +(global-set-key (kbd "C-M-z") 'eval-region) +(global-set-key (kbd "C-'") 'universal-argument) +(global-set-key (kbd "C-.") 'next-window-any-frame) +(global-set-key (kbd "C-,") 'previous-window-any-frame) +(global-set-key (kbd "C-x C-b") 'buffer-menu) +(global-set-key (kbd "C-x .") 'next-buffer) +(global-set-key (kbd "C-x ,") 'previous-buffer) +(global-set-key (kbd "C-%") 'replace-regexp) +(global-set-key (kbd "M-%") 'slot/replace-string-many) +(global-set-key (kbd "C-M-%") 'slot/query-replace-many) +;; MODE-SPECIFIC +(add-hook 'eshell-mode-hook (lambda () + (define-key eshell-mode-map (kbd ")") 'eshell-send-on-close-paren))) +(add-hook 'org-mode-hook (lambda () + (define-key org-mode-map (kbd "C-'") nil) + (define-key org-mode-map (kbd "C-,") nil))) +(add-hook 'org-agenda-mode-hook (lambda () + (define-key org-agenda-mode-map (kbd "C-'") nil) + (define-key org-agenda-mode-map (kbd "C-,") nil))) diff --git a/defuns.el b/defuns.el new file mode 100644 index 0000000..32647b7 --- /dev/null +++ b/defuns.el @@ -0,0 +1,216 @@ +;; -*- lexical-binding: t; -*- +;; DEFUNS +(defun open-line-below () + "Creates a new empty line below the current line." + (interactive) + (end-of-line) + (newline) + (indent-for-tab-command)) + +(defun open-line-above () + "Creates a new empty line above the current line. +Can't go prev line first, edge case of beginning of buffer." + (interactive) + (beginning-of-line) + (newline) + (previous-line) + (indent-for-tab-command)) + +(defun kill-bword-or-region () + "Kill region if active, otherwise kill back one word." + (interactive) + (if (region-active-p) + (call-interactively 'kill-region) + (call-interactively 'backward-kill-word))) + +(defun backward-kill-line () + "Kill back to beginning of line from point." + (interactive) + (kill-line 0)) + +(defun backward-join-line () + "A wrapper for join-line to make it go in the right direction." + (interactive) + (join-line 0)) + +(defun edit-init () + "Bring up init.el for editing." + (interactive) + (find-file user-init-file)) + +(defun edit-work-eqs () + "Bring up work-eqs.el for editing." + (interactive) + (find-file work-eqns)) + +(defun toggle-window-split () + "If two windows are open, toggle their split layout between vert. and horiz. +Stolen from http://whattheemacsd.com" + (interactive) + (if (= (count-windows) 2) + (let* ((this-win-buffer (window-buffer)) + (next-win-buffer (window-buffer (next-window))) + (this-win-edges (window-edges (selected-window))) + (next-win-edges (window-edges (next-window))) + (this-win-2nd (not (and (<= (car this-win-edges) + (car next-win-edges)) + (<= (cadr this-win-edges) + (cadr next-win-edges))))) + (splitter + (if (= (car this-win-edges) + (car (window-edges (next-window)))) + 'split-window-horizontally + 'split-window-vertically))) + (delete-other-windows) + (let ((first-win (selected-window))) + (funcall splitter) + (if this-win-2nd (other-window 1)) + (set-window-buffer (selected-window) this-win-buffer) + (set-window-buffer (next-window) next-win-buffer) + (select-window first-win) + (if this-win-2nd (other-window 1)))))) + +(defun rotate-windows () + "Rotate your windows. +Stolen from http://whattheemacsd.com" + (interactive) + (cond ((not (> (count-windows)1)) + (message "You can't rotate a single window!")) + (t + (setq i 1) + (setq numWindows (count-windows)) + (while (< i numWindows) + (let* ( + (w1 (elt (window-list) i)) + (w2 (elt (window-list) (+ (% i numWindows) 1))) + + (b1 (window-buffer w1)) + (b2 (window-buffer w2)) + + (s1 (window-start w1)) + (s2 (window-start w2)) + ) + (set-window-buffer w1 b2) + (set-window-buffer w2 b1) + (set-window-start w1 s2) + (set-window-start w2 s1) + (setq i (1+ i))))))) + +(defun smart-beginning-of-line () + "Move point to first non-whitespace character or beginning-of-line. +If point was already at that position, move point to beginning of line. +Stolen from BrettWitty's dotemacs github repo." + (interactive "^") + (let ((oldpos (point))) + (back-to-indentation) + (and (= oldpos (point)) + (beginning-of-line)))) + +(defun unfuck-aveva-license () + "Remove the offending xml files when aveva can't find the license." + (interactive) + (let ((xml1 "c:/ProgramData/AVEVA/Licensing/License API2/Data/LocalAcquireInfo.xml") + (xml2 "c:/ProgramData/AVEVA/Licensing/License API2/Data/LocalBackEndAcquireInfo.xml")) + (when (file-exists-p xml1) (delete-file xml1)) + (when (file-exists-p xml2) (delete-file xml2)))) + +(defun eshell-send-on-close-paren () + "Makes eshell act somewhat like genera. +Makes a closing paren execute the sexp. Currently in test, look out for errors." + (interactive) + (insert-char ?\)) + (let ((p (point))) + ;;(eshell-bol) + ;;(syntax-ppss-flush-cache (point)) + ;;(goto-char p) + (cond ((= 0 (car (syntax-ppss))) + (eshell-send-input)) + ((< (car (syntax-ppss)) 0) + (message "Check flush-cache")) + ((t nil))))) + +(defun slot/get-queries (title &optional pairs) + "Get multiple `query-replace' pairs from the user. +PAIRS is a list of replacement pairs of the form (FROM . TO). +Stolen from https://tony-zorman.com/posts/query-replace/2022-08-06-query-replace-many.html" + (-let* (((from to delim arg) + (query-replace-read-args + (s-join " " + (-non-nil + (list title + (cond ((eq current-prefix-arg '-) "backward") + (current-prefix-arg "word")) + (when (use-region-p) "in region")))) + nil)) ; no regexp-flag + (from-to (cons (regexp-quote from) + (s-replace "\\" "\\\\" to)))) + ;; HACK: Since the default suggestion of replace.el will be + ;; the last one we've entered, an empty string will give us + ;; exactly that. Instead of trying to fight against this, + ;; use it in order to signal an exit. + (if (-contains? pairs from-to) + (list pairs delim arg) + (slot/get-queries (push from-to pairs))))) + +(defun slot/replace-string-many + (pairs &optional delimited start end backward region-noncontiguous-p) + "Like `replace-string', but query for several replacements. +Query for replacement pairs until the users enters an empty +string (but see `slot/get-queries'). + +Refer to `query-replace' and `perform-replace' for what the other +arguments actually mean. +Stolen from https://tony-zorman.com/posts/query-replace/2022-08-06-query-replace-many.html +Edited and renamed to remove the Query." + (interactive + (let ((common (slot/get-queries "Replace strings"))) + (list (nth 0 common) (nth 1 common) + (if (use-region-p) (region-beginning)) + (if (use-region-p) (region-end)) + (nth 2 common) + (if (use-region-p) (region-noncontiguous-p))))) + (perform-replace + (concat "\\(?:" (mapconcat #'car pairs "\\|") "\\)") ; build query + (cons (lambda (pairs _count) + (cl-loop for (from . to) in pairs + when (string-match from (match-string 0)) + return to)) + pairs) + nil :regexp + delimited nil nil start end backward region-noncontiguous-p)) + +(defun slot/query-replace-many + (pairs &optional delimited start end backward region-noncontiguous-p) + "Like `query-replace', but query for several replacements. +Query for replacement pairs until the users enters an empty +string (but see `slot/get-queries'). + +Refer to `query-replace' and `perform-replace' for what the other +arguments actually mean. +Stolen from https://tony-zorman.com/posts/query-replace/2022-08-06-query-replace-many.html" + (interactive + (let ((common (slot/get-queries "Query Replace Strings"))) + (list (nth 0 common) (nth 1 common) + (if (use-region-p) (region-beginning)) + (if (use-region-p) (region-end)) + (nth 2 common) + (if (use-region-p) (region-noncontiguous-p))))) + (perform-replace + (concat "\\(?:" (mapconcat #'car pairs "\\|") "\\)") ; build query + (cons (lambda (pairs _count) + (cl-loop for (from . to) in pairs + when (string-match from (match-string 0)) + return to)) + pairs) + :query :regexp + delimited nil nil start end backward region-noncontiguous-p)) + +(defun edit-keymap-planck () + "Bring up planck keymap for editing." + (interactive) + (find-file "~/qmk_firmware/keyboards/planck/keymaps/ehrman/keymap.c")) + +(defun edit-keymap-tokyo60 () + "Bring up tokyo60 keymap for editing." + (interactive) + (find-file "~/qmk_firmware/keyboards/tokyokeyboard/tokyo60/keymaps/ehrman/keymap.c")) diff --git a/eshell/alias b/eshell/alias index 78ab70e..2910772 100644 --- a/eshell/alias +++ b/eshell/alias @@ -1 +1,2 @@ alias weather clear -l && curl https://wttr.in +alias qmk c:/QMK_MSYS/conemu/ConEmu64.exe diff --git a/hooks-puts.el b/hooks-puts.el new file mode 100644 index 0000000..2a57b02 --- /dev/null +++ b/hooks-puts.el @@ -0,0 +1,10 @@ +;; -*- lexical-binding: t; -*- +;; HOOKS +(add-hook 'before-save-hook 'whitespace-cleanup) +(add-hook 'dired-mode-hook 'dired-hide-details-mode t) + +;; PUTS AND PUSHES +(put 'upcase-region 'disabled nil) +(put 'downcase-region 'disabled nil) +(put 'narrow-to-region 'disabled nil) +(put 'dired-find-alternate-file 'disabled nil) diff --git a/init.el b/init.el index 980f8eb..b051f2a 100644 --- a/init.el +++ b/init.el @@ -4,13 +4,13 @@ (progn (setq delete-by-moving-to-trash t)) nil) -(load (expand-file-name "config/work-eqs.el" user-emacs-directory)) -(load (expand-file-name "config/package-config.el" user-emacs-directory)) -(load (expand-file-name "config/setq-defaults.el" user-emacs-directory)) -(load (expand-file-name "config/defuns.el" user-emacs-directory)) -(load (expand-file-name "config/org-setup.el" user-emacs-directory)) -(load (expand-file-name "config/hooks-puts.el" user-emacs-directory)) -(load (expand-file-name "config/bindings.el" user-emacs-directory)) +(load (expand-file-name "work-eqs.el" user-emacs-directory)) +(load (expand-file-name "package-config.el" user-emacs-directory)) +(load (expand-file-name "setq-defaults.el" user-emacs-directory)) +(load (expand-file-name "defuns.el" user-emacs-directory)) +(load (expand-file-name "org-setup.el" user-emacs-directory)) +(load (expand-file-name "hooks-puts.el" user-emacs-directory)) +(load (expand-file-name "bindings.el" user-emacs-directory)) (custom-set-variables ;; custom-set-variables was added by Custom. diff --git a/org-setup.el b/org-setup.el new file mode 100644 index 0000000..d40d529 --- /dev/null +++ b/org-setup.el @@ -0,0 +1,54 @@ +;; -*- lexical-binding: t; -*- +;; ORG SETTINGS AND DEFUNS +(defun erfassen-zettel () + "Add a new zettel to the kasten. +Creates a new file -name.org in ~/org/kasten." + (interactive) + (let ((name (read-string "Zettel-Name: "))) + (expand-file-name (format "%s-%s.org" (format-time-string "%Y-%m-%d-%H%M") name) "~/org/kasten/"))) + +(defun org-auto-archive () + "Automatically archive completed tasks in an org file. +Intended for use as an after-save-hook." + (interactive) + (org-map-entries + (lambda () + (org-archive-subtree) + (setq org-map-continue-from (org-element-property :begin (org-element-at-point)))) + "TODO=\"DONE\"|TODO=\"CANCELLED\"" + 'file) + (save-buffer)) + +(setq org-M-RET-may-split-line nil + org-startup-folded t + org-reverse-note-order t + org-use-fast-todo-selection 'expert + org-agenda-start-on-weekday nil + org-catch-invisible-edits 'show + org-directory "~/org" + org-agenda-files '("~/org/" + "~/org/kasten/") + org-refile-targets '((nil :maxlevel . 9) + (org-agenda-files :maxlevel . 9)) + org-default-notes-file (concat org-directory "/notes.org") + safe-local-variable-values '((after-save-hook org-auto-archive)) + org-todo-keywords '((sequence "TODO(t@)" + "WAITING(w@)" + "IN-PROGRESS(i@)" + "DELEGATED(l@)" + "APPT(a@)" "|" + "DONE(d@)" + "CANCELLED(c@)")) + org-capture-templates '(("n" "Note" entry (file+olp org-default-notes-file "Notes") "* %u %?") + ("t" "TODO" entry (file+olp org-default-notes-file "Tasks") "* TODO %? \n %u") + ("s" "Service" entry (file+olp org-default-notes-file "Service") "* TODO %? \n %u") + ("z" "Zettel" entry (file erfassen-zettel) "* %? ::")) + org-agenda-custom-commands '(("n" "Agenda and all TODOs" + ((agenda "") (alltodo ""))) + ("u" "Unscheduled TODOs" + alltodo "" ((org-agenda-skip-function + (lambda nil + (org-agenda-skip-entry-if 'scheduled + 'deadline + 'regexp "\n]+>"))) + (org-agenda-overriding-header "Unscheduled TODO entries: "))))) diff --git a/package-config.el b/package-config.el new file mode 100644 index 0000000..4beb122 --- /dev/null +++ b/package-config.el @@ -0,0 +1,58 @@ +;; -*- lexical-binding: t; -*- + +;; PACKAGES +;; NEW STRAIGHT.EL CONFIG +(defvar bootstrap-version) +(let ((bootstrap-file + (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) + (bootstrap-version 6)) + (unless (file-exists-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously + "https://raw.githubusercontent.com/radian-software/straight.el/develop/install.el" + 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp))) + (load bootstrap-file nil 'nomessage)) + +(straight-use-package 'use-package) + +(use-package straight + :custom (straight-use-package-by-default t)) + +(use-package company + :custom + (company-idle-delay 0) + (company-minimum-prefix-length 3) + (company-selection-wrap-around t) + (company-dabbrev-other-buffers t) + (company-dabbrev-code-other-buffers t) + (company-dabbrev-downcase nil) + (company-dabbrev-ignore-case t) + :config + (global-company-mode t)) + +(use-package expand-region + :bind (("C-=" . er/expand-region))) + +(use-package magit + :init + (message "Loading Magit...") + :config + (message "Loaded Magit!") + :bind (("C-x g" . magit-status))) + +(use-package gnuplot-mode) + +(use-package openwith + :config + (openwith-mode t) + (setq openwith-associations '(("\\.pdf\\'" "sumatrapdf" (file)) + ("\\.xls\\'" "excel" (file)) + ("\\.xlsx\\'" "excel" (file)) + ("\\.doc\\'" "word" (file)) + ("\\.docx\\'" "word" (file)) + ("\\.adpro\\'" "PoductivitySuite" (file))))) +(use-package s) + +(use-package dash) diff --git a/setq-defaults.el b/setq-defaults.el new file mode 100644 index 0000000..0395b9c --- /dev/null +++ b/setq-defaults.el @@ -0,0 +1,47 @@ +;; -*- lexical-binding: t; -*- +;; SETQ AND DEFAULTS +(setq-default indicate-empty-lines t + fill-column 80 + read-file-name-completion-ignore-case t + read-buffer-completion-ignore-case t + cursor-type 'bar + cursor-in-non-selected-windows nil) + +(setq default-directory "~/" + inhibit-startup-message t + initial-scratch-message nil + server-client-instructions nil + require-final-newline t + use-short-answers t + mode-line-compact t + make-backup-files nil + auto-save-default nil + confirm-nonexistent-file-or-buffer nil + show-paren-delay 0 + show-paren-style 'expression + blink-matching-paren 'jump + global-hl-line-sticky-flag t + echo-keystrokes 0.01 + save-interprogram-paste-before-kill t) + +;; OPTIONS +(recentf-mode t) +(fringe-mode 1) +(menu-bar-mode -1) +(tool-bar-mode -1) +(scroll-bar-mode -1) +(show-paren-mode t) +(auto-fill-mode t) +(midnight-mode t) +(mouse-avoidance-mode 'animate) +(column-number-mode t) +(delete-selection-mode t) +(global-hl-line-mode t) +(global-prettify-symbols-mode t) +(global-display-line-numbers-mode t) +(set-face-background 'show-paren-match nil) +(set-face-underline 'show-paren-match t) +(add-to-list 'default-frame-alist '(background-color . "#cae0a6")) + +(unless (display-graphic-p) + (xterm-mouse-mode 1)) diff --git a/work-eqs.el b/work-eqs.el new file mode 100644 index 0000000..d217c77 --- /dev/null +++ b/work-eqs.el @@ -0,0 +1,145 @@ +;; WORK (NON-EDITING) RELATED DEFUNS +(defun square (x) + "Calculate the square of a value." + (expt x 2)) + +(defun cube (x) + "Calculate the cube of a value." + (expt x 3)) + +(defun inv (x) + "Calculate the inverse of a value." + (/ 1 x)) + +(defun scaleval (pmax pmin emax emin &optional ai) + "Calculate the slope and offset given PLC Max/Min and Eng. Max/Min. +With optional argument 'ai', also calculate a final scaled value from an input." + (let ((div (/ (- pmax pmin) (- (float emax) (float emin))))) + (let ((ofst (- emin (/ pmin div)))) + (if (eq nil ai) + (list div ofst) + (let ((final (+ ofst (/ ai div)))) + (list div ofst final)))))) + +(defun cfm-circ (fpm radius) + "Calculate the CFM of a circular duct given fpm and radius (in)." + (list (* pi fpm (square (/ radius 12))))) + +(defun cfm-rect (fpm width height) + "Calculate the CFM of a rectangular duct given fpm, width (in) and height (in)." + (list (* fpm (/ width 12) (/ height 12)))) + +(defun pid-tune (Ku Tu &optional p-type) + "Use the Ziegler-Nichols method to tune a P, PI or PID loop. +Takes Ku, Tu and optional p-type (P, PI, or PID [default]) as arguments, + and returns appropriate kp, ki, and kd." + (cond ((or (equal 'p p-type) + (equal 'P p-type)) + (list (* 0.5 Ku))) + ((or (equal 'pi p-type) + (equal 'PI p-type)) + (list (* 0.45 Ku) (/ (* 0.54 Ku) Tu))) + (t (list (* 0.6 Ku) (/ (* 1.2 Ku) Tu) (/ (* 3.0 Ku Tu) 40))))) + +(defun gn-water-per-lb (temp humidity) + "Calculate the grains of water per lb of air, given temperature (F) and humidity (%). +Returns a list of Sat. Water Press., Hum. Ratio, and Gns water/lb air." + (let ((sat-water-press (+ .0182795 + (* temp .001029904) + (* (square temp) 0.00002579408) + (* (cube temp) (* 2.400493 (expt 10 -7))) + (* (expt temp 4) (* 8.100939 (expt 10 -10))) + (* (expt temp 5) (* 3.256805 (expt 10 -11))) + (* (expt temp 6) (* -1.001922 (expt 10 -13))) + (* (expt temp 7) (* 2.44161 (expt 10 -16)))))) + (let ((hum-press (* (/ humidity 100.0) sat-water-press))) + (let ((hum-ratio (/ (* hum-press 0.62198) (- 14.7 hum-press)))) + (let ((gns-water-lb-air (* hum-ratio 7000))) + (list sat-water-press hum-ratio gns-water-lb-air)))))) + +(defun mm-to-in (mm) + "Convert milimeters to inches." + (/ mm 25.4)) + +(defun in-to-mm (in) + "Convert milimeters to inches." + (* in 25.4)) + +(defun k-to-c (tempk) + "Convert degrees Kelvin to degrees Celsius." + (- tempk 273.15)) + +(defun c-to-k (tempc) + "Convert degrees Celsius to degrees Kelvin." + (+ tempc 273.15)) + +(defun c-to-f (tempc) + "Convert degrees Celsius to degrees Fahrenheit." + (+ (* tempc 1.8) 32.0)) + +(defun f-to-c (tempf) + "Convert degrees Fahrenheit to degrees Celsius." + (/ (- tempf 32.0) 1.8)) + +(defun k-to-f (tempk) + "Convert degrees Kelvin to degrees Fahrenheit. +Applies `c-to-f' to `k-to-c'." + (c-to-f (k-to-c tempk))) + +(defun f-to-k (tempf) + "Convert degrees Fahrenheit to degrees Kelvin. +Applies `c-to-k' to `f-to-c'." + (c-to-k (f-to-c tempf))) + +(defun max-counts (resolution) + "Calculate the max count for a PLC analog, given card's bit-resolution. +Formula is 1 - 2^(resolution)" + (- (expt 2 resolution) 1)) + +(defun volts-to-counts (vin vmax resolution) + "Convert a voltage signal to a PLC count. +Calculates a ratio of vin/vmax, then scales by `max-counts'." + (* (/ (float vin) (float vmax)) (float (max-counts resolution)))) + +(defun counts-to-volts (cin vmax resolution) + "Convert a PLC count to a voltage. +Calculates a ratio of cin/`max-counts', then multiplies by vmax." + (* (/ cin (float (max-counts resolution))) vmax)) + +(defun eff-imp (r1 &optional r2) + "Calculate the effective input impedance, given two resistances. +For use in `amps-to-volts' and related. The handling of only one resistance +given is done here, instead of doing it in every function that uses this." + (if (eq nil r2) + r1 + (inv (+ (inv (float r1)) (inv (float r2)))))) + +(defun amps-to-volts (amps r1 &optional r2) + "Calculate the voltage, given amperage and impedance. +Multiplies the amperage by the effective impedance calculated with `eff-imp'." + (* amps (eff-imp r1 r2))) + +(defun volts-to-amps (volts r1 &optional r2) + "Calculate the amperage, given voltage and impedance. +Divides the voltage by the effective impedance calculated with `eff-imp'." + (/ volts (eff-imp r1 r2))) + +(defun amps-to-counts (amps vmax resolution r1 &optional r2) + "Convert an amp signal to PLC Counts. +Converts the amperage to a voltage using `amps-to-volts' (with r1 and optional r2), +then applies `volts-to-counts' to the resulting voltage, vmax, and resolution." + (volts-to-counts (amps-to-volts amps r1 r2) vmax resolution)) + +(defun count-range (type upper lower vmax resolution &optional r1 r2) + "Given an upper and lower signal, return the list of upper and lower PLC counts. +Type takes either a v or an i, corresponding to a voltage or current signal. +With a current signal, use r1 and maybe r2 to calculate `amps-to-counts'. +Otherwise ignore r1/r2 and calculate `volts-to-counts'." + (cond ((or (equal 'v type) + (equal 'V type)) + (list (volts-to-counts upper vmax resolution) + (volts-to-counts lower vmax resolution))) + ((or (equal 'i type) + (equal 'I type)) + (list (amps-to-counts upper vmax resolution r1 r2) + (amps-to-counts lower vmax resolution r1 r2)))))