|
|
@ -0,0 +1,332 @@ |
|
|
|
(set-cakelisp-option cakelisp-src-dir "Dependencies/cakelisp/src") |
|
|
|
(add-cakelisp-search-directory "Dependencies/cakelisp/runtime") |
|
|
|
(add-cakelisp-search-directory "src") |
|
|
|
|
|
|
|
(import |
|
|
|
;; Cakelisp |
|
|
|
"CHelpers.cake") |
|
|
|
|
|
|
|
(c-preprocessor-define-constant NULL 0) |
|
|
|
|
|
|
|
(defgenerator var-aligned (name symbol |
|
|
|
module-type-index (index any) |
|
|
|
alignment-index (index symbol) |
|
|
|
value-index (index array)) |
|
|
|
(var module-type-output (template (in std vector) StringOutput)) |
|
|
|
(var module-type-output-after-name (template (in std vector) StringOutput)) |
|
|
|
(unless (tokenizedCTypeToString_Recursive |
|
|
|
environment context tokens module-type-index |
|
|
|
true module-type-output module-type-output-after-name |
|
|
|
RequiredFeatureExposure_ModuleLocal) |
|
|
|
(return false)) |
|
|
|
(addModifierToStringOutput (call-on back module-type-output) StringOutMod_SpaceAfter) |
|
|
|
(PushBackAll (field output source) module-type-output) |
|
|
|
(var alignment-directive (array 128 char) (array 0)) |
|
|
|
(SafeSnprintf alignment-directive (sizeof alignment-directive) "__attribute__((aligned(%s)))" |
|
|
|
(call-on c_str (field (at alignment-index tokens) contents))) |
|
|
|
(addStringOutput (field output source) alignment-directive StringOutMod_SpaceAfter |
|
|
|
(addr (at alignment-index tokens))) |
|
|
|
(addStringOutput (field output source) (path name > contents) |
|
|
|
StringOutMod_ConvertVariableName name) |
|
|
|
(PushBackAll (field output source) module-type-output-after-name) |
|
|
|
|
|
|
|
;; Value |
|
|
|
(addLangTokenOutput (field output source) StringOutMod_SpaceAfter (addr (at value-index tokens))) |
|
|
|
(addStringOutput (field output source) "=" StringOutMod_SpaceAfter (addr (at value-index tokens))) |
|
|
|
(var expression-context EvaluatorContext context) |
|
|
|
(set (field expression-context scope) EvaluatorScope_ExpressionsOnly) |
|
|
|
(unless (= 0 (EvaluateGenerate_Recursive |
|
|
|
environment expression-context tokens value-index |
|
|
|
output)) |
|
|
|
(return false)) |
|
|
|
(addLangTokenOutput (field output source) StringOutMod_EndStatement name) |
|
|
|
(return true)) |
|
|
|
|
|
|
|
;; Helpers |
|
|
|
|
|
|
|
(defun write-absolute-addr |
|
|
|
(address (long long) |
|
|
|
value (unsigned int)) |
|
|
|
(set (deref (type-cast address (addr (volatile (unsigned int))))) |
|
|
|
value)) |
|
|
|
|
|
|
|
(defun read-absolute-addr |
|
|
|
(address (long long) |
|
|
|
&return (unsigned int)) |
|
|
|
(return (deref (type-cast address (addr (volatile (unsigned int))))))) |
|
|
|
|
|
|
|
;; |
|
|
|
;; VideoCore/GPU |
|
|
|
;; |
|
|
|
|
|
|
|
;; Note: must be 16-byte aligned! |
|
|
|
(def-type-alias mailbox-buffer (array 36 (volatile (unsigned int)))) |
|
|
|
(def-type-alias mailbox-addr (addr (volatile (unsigned int)))) |
|
|
|
|
|
|
|
(c-preprocessor-define-constant c-rpi-peripheral-base 0xfe000000UL) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-start-addr |
|
|
|
(+ c-rpi-peripheral-base 0x0000b880UL)) |
|
|
|
;; (todo clarity) This could be more easily read as a struct |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-read |
|
|
|
(+ c-videocore-mailbox-start-addr 0x0UL)) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-poll |
|
|
|
(+ c-videocore-mailbox-start-addr 0x10UL)) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-sender |
|
|
|
(+ c-videocore-mailbox-start-addr 0x14UL)) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-status |
|
|
|
(+ c-videocore-mailbox-start-addr 0x18UL)) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-config |
|
|
|
(+ c-videocore-mailbox-start-addr 0x1cUL)) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-write |
|
|
|
(+ c-videocore-mailbox-start-addr 0x20UL)) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-request |
|
|
|
0x0) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-response |
|
|
|
0x80000000) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-full |
|
|
|
0x80000000) |
|
|
|
(c-preprocessor-define-constant c-videocore-mailbox-empty |
|
|
|
0x40000000) |
|
|
|
|
|
|
|
(defenum mailbox-channel |
|
|
|
mailbox-channel-power ;; 0 |
|
|
|
mailbox-channel-fb ;; 1 |
|
|
|
mailbox-channel-vuart ;; 2 |
|
|
|
mailbox-channel-vchiq ;; 3 |
|
|
|
mailbox-channel-leds ;; 4 |
|
|
|
mailbox-channel-btns ;; 5 |
|
|
|
mailbox-channel-touch ;; 6 |
|
|
|
mailbox-channel-count ;; 7 |
|
|
|
mailbox-channel-properties) ;; 8 |
|
|
|
|
|
|
|
;; (var c-mailbox-tag-set-power (const (unsigned int)) 0x28001) |
|
|
|
;; (var c-mailbox-tag-set-clock-rate (const (unsigned int)) 0x38002) |
|
|
|
(var c-mailbox-tag-set-physical-width-height (const (unsigned int)) 0x48003) |
|
|
|
(var c-mailbox-tag-set-virtual-width-height (const (unsigned int)) 0x48004) |
|
|
|
(var c-mailbox-tag-set-virtual-offset (const (unsigned int)) 0x48009) |
|
|
|
(var c-mailbox-tag-set-pixel-depth (const (unsigned int)) 0x48005) |
|
|
|
(var c-mailbox-tag-set-pixel-order (const (unsigned int)) 0x48006) |
|
|
|
(var c-mailbox-tag-allocate-frame-buffer (const (unsigned int)) 0x40001) |
|
|
|
(var c-mailbox-tag-get-pixel-pitch (const (unsigned int)) 0x40008) |
|
|
|
(var c-mailbox-tag-end-sentinel (const (unsigned int)) 0) |
|
|
|
|
|
|
|
(defun-local mailbox-blocking-call |
|
|
|
(in-out-box-16byte-aligned mailbox-addr |
|
|
|
channel (unsigned char) |
|
|
|
&return int) |
|
|
|
;; (todo clarity) This could more easily be written as a bit-packed struct |
|
|
|
(var-cast-to packed-mailbox-and-channel (unsigned int) |
|
|
|
(bit-or (bit-and (type-cast in-out-box-16byte-aligned (long long)) 0xfffffff0) |
|
|
|
(bit-and channel 0xf))) |
|
|
|
;; Wait until we can write |
|
|
|
(while (bit-and (read-absolute-addr c-videocore-mailbox-status) c-videocore-mailbox-full) |
|
|
|
(ignore)) |
|
|
|
(write-absolute-addr c-videocore-mailbox-write packed-mailbox-and-channel) |
|
|
|
;; (todo performance) It is supposed to be possible to send multiple commands without blocking |
|
|
|
;; (todo robustness) This could get stuck forever |
|
|
|
(while 1 |
|
|
|
(while (bit-and (read-absolute-addr c-videocore-mailbox-status) c-videocore-mailbox-empty) |
|
|
|
(ignore)) |
|
|
|
(when (= packed-mailbox-and-channel (read-absolute-addr c-videocore-mailbox-read)) |
|
|
|
(return (= (at 1 in-out-box-16byte-aligned) c-videocore-mailbox-response)))) |
|
|
|
(return 0)) |
|
|
|
|
|
|
|
(defstruct-local pixel-framebuffer |
|
|
|
width int |
|
|
|
height int |
|
|
|
pitch int |
|
|
|
pixel-order int |
|
|
|
data (addr (unsigned char))) |
|
|
|
|
|
|
|
;; Note that you can't really have more than one I presume |
|
|
|
(defun-local initialize-framebuffer |
|
|
|
(framebuffer (addr pixel-framebuffer)) |
|
|
|
(var-aligned mail mailbox-buffer 16 (array 0)) |
|
|
|
(set (at 0 mail) (* 35 4)) ;; Length of message (bytes) |
|
|
|
(set (at 1 mail) c-videocore-mailbox-request) |
|
|
|
|
|
|
|
;; (todo clarity) This is begging to be made into a cleaner interface. Could define structs for |
|
|
|
;; all tags, then a push tag function? |
|
|
|
;; See https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface |
|
|
|
;; Note that these are already padded correctly because they only need to be aligned to 1 byte |
|
|
|
(set (at 2 mail) c-mailbox-tag-set-physical-width-height) |
|
|
|
(set (at 3 mail) 8) ;; Value size in bytes |
|
|
|
(set (at 4 mail) 0) ;; Response space |
|
|
|
(set (at 5 mail) 1920) ;; Value width |
|
|
|
(set (at 6 mail) 1080) ;; Value height |
|
|
|
|
|
|
|
(set (at 7 mail) c-mailbox-tag-set-virtual-width-height) |
|
|
|
(set (at 8 mail) 8) ;; Value size in bytes |
|
|
|
(set (at 9 mail) 8) ;; Response space |
|
|
|
(set (at 10 mail) 1920) ;; Value width |
|
|
|
(var virtual-width-index int 10) |
|
|
|
(set (at 11 mail) 1080) ;; Value height |
|
|
|
(var virtual-height-index int 11) |
|
|
|
|
|
|
|
(set (at 12 mail) c-mailbox-tag-set-virtual-offset) |
|
|
|
(set (at 13 mail) 8) ;; Value size in bytes |
|
|
|
(set (at 14 mail) 8) ;; Response space |
|
|
|
(set (at 15 mail) 0) ;; Value x |
|
|
|
(set (at 16 mail) 0) ;; Value y |
|
|
|
|
|
|
|
(var desired-pixel-depth int 32) |
|
|
|
(set (at 17 mail) c-mailbox-tag-set-pixel-depth) |
|
|
|
(set (at 18 mail) 4) ;; Value size in bytes |
|
|
|
(set (at 19 mail) 4) ;; Response space |
|
|
|
(set (at 20 mail) desired-pixel-depth) ;; Value depth |
|
|
|
(var pixel-depth-index int 20) |
|
|
|
|
|
|
|
(set (at 21 mail) c-mailbox-tag-set-pixel-order) |
|
|
|
(set (at 22 mail) 4) ;; Value size in bytes |
|
|
|
(set (at 23 mail) 4) ;; Response space |
|
|
|
(set (at 24 mail) 1) ;; Value pixel order |
|
|
|
(var pixel-order-index int 24) |
|
|
|
|
|
|
|
(set (at 25 mail) c-mailbox-tag-allocate-frame-buffer) |
|
|
|
(set (at 26 mail) 8) ;; Value size in bytes |
|
|
|
(set (at 27 mail) 8) ;; Response space |
|
|
|
(set (at 28 mail) 4096) ;; Requested buffer alignment in bytes; response becomes the base address |
|
|
|
(var frame-buffer-address-index int 28) |
|
|
|
(set (at 29 mail) 0) ;; Empty space for the frame buffer size in bytes |
|
|
|
|
|
|
|
(set (at 30 mail) c-mailbox-tag-get-pixel-pitch) |
|
|
|
(set (at 31 mail) 4) ;; Value size in bytes |
|
|
|
(set (at 32 mail) 4) ;; Response space |
|
|
|
(set (at 33 mail) 0) ;; Pitch added bytes per line |
|
|
|
(var pitch-index int 33) |
|
|
|
|
|
|
|
(set (at 34 mail) c-mailbox-tag-end-sentinel) |
|
|
|
(when |
|
|
|
(and (mailbox-blocking-call mail mailbox-channel-properties) |
|
|
|
(= (at pixel-depth-index mail) desired-pixel-depth) |
|
|
|
(at frame-buffer-address-index mail)) |
|
|
|
(set (at frame-buffer-address-index mail) |
|
|
|
(bit-and (at frame-buffer-address-index mail) |
|
|
|
0x3fffffff)) ;; Convert GPU address to arm address |
|
|
|
(set-fields (deref framebuffer) |
|
|
|
width (at virtual-width-index mail) |
|
|
|
height (at virtual-height-index mail) |
|
|
|
pitch (at pitch-index mail) |
|
|
|
pixel-order (at pixel-order-index mail) |
|
|
|
data (type-cast (type-cast (at frame-buffer-address-index mail) (long long)) |
|
|
|
(addr (unsigned char)))))) |
|
|
|
|
|
|
|
(var g-framebuffer (addr pixel-framebuffer) null) |
|
|
|
|
|
|
|
(def-type-alias argb-color int) |
|
|
|
|
|
|
|
(defun-local set-pixel |
|
|
|
(x int y int |
|
|
|
color argb-color) |
|
|
|
(unless g-framebuffer |
|
|
|
(return)) |
|
|
|
(var c-pixel-bytes int 4) |
|
|
|
(var offset int (+ (* y (path g-framebuffer > pitch)) (* x c-pixel-bytes))) |
|
|
|
(set (at offset (type-cast (path g-framebuffer > data) (addr (unsigned int)))) |
|
|
|
color)) |
|
|
|
|
|
|
|
;; |
|
|
|
;; GPIO |
|
|
|
;; |
|
|
|
|
|
|
|
(c-preprocessor-define-constant c-gpio-gp-function-select-0 0) |
|
|
|
(c-preprocessor-define-constant c-gpio-gp-function-select-1 1) |
|
|
|
(c-preprocessor-define-constant c-gpio-gp-function-select-2 2) |
|
|
|
(c-preprocessor-define-constant c-gpio-gp-function-select-3 3) |
|
|
|
(c-preprocessor-define-constant c-gpio-gp-function-select-4 4) |
|
|
|
(c-preprocessor-define-constant c-gpio-gp-function-select-5 5) |
|
|
|
|
|
|
|
(c-preprocessor-define-constant c-gpio-gpset0 7) |
|
|
|
(c-preprocessor-define-constant c-gpio-gpset1 8) |
|
|
|
|
|
|
|
(c-preprocessor-define-constant c-gpio-gp-clear0 10) |
|
|
|
(c-preprocessor-define-constant c-gpio-gp-clear1 11) |
|
|
|
|
|
|
|
|
|
|
|
(c-preprocessor-define-constant c-gpio-base-offset 0xfe200000ULL) |
|
|
|
(c-preprocessor-define-constant c-gpio-led-gp-function-select c-gpio-gp-function-select-4) |
|
|
|
(c-preprocessor-define-constant c-gpio-led-gp-function-bit 6) |
|
|
|
(c-preprocessor-define-constant c-gpio-led-gpset c-gpio-gpset1) |
|
|
|
(c-preprocessor-define-constant c-gpio-led-gp-clear c-gpio-gp-clear1) |
|
|
|
(c-preprocessor-define-constant c-gpio-led-bit 10) |
|
|
|
|
|
|
|
|
|
|
|
;; |
|
|
|
;; Main |
|
|
|
;; |
|
|
|
|
|
|
|
(defun fail-loop () |
|
|
|
(while 1 |
|
|
|
(ignore))) |
|
|
|
|
|
|
|
(var g-gpio (addr (volatile (unsigned int)))) |
|
|
|
(var wait-counter (volatile (unsigned int)) 0) |
|
|
|
(var num-blinks (volatile (unsigned int)) 0) |
|
|
|
|
|
|
|
(defun blink-led (requested-num-blinks int) |
|
|
|
(set g-gpio (type-cast c-gpio-base-offset (addr (unsigned int)))) |
|
|
|
;; Enable the led as an output |
|
|
|
(set (at c-gpio-led-gp-function-select g-gpio) |
|
|
|
(bit-or (at c-gpio-led-gp-function-select g-gpio) (bit-shift-<< 1 c-gpio-led-gp-function-bit))) |
|
|
|
(set num-blinks 0) |
|
|
|
(while (< num-blinks requested-num-blinks) |
|
|
|
(incr num-blinks) |
|
|
|
(while (< wait-counter 500000) |
|
|
|
(incr wait-counter)) |
|
|
|
(set (at c-gpio-led-gp-clear g-gpio) (bit-shift-<< 1 c-gpio-led-bit)) |
|
|
|
(set wait-counter 0) |
|
|
|
(while (< wait-counter 500000) |
|
|
|
(incr wait-counter)) |
|
|
|
(set (at c-gpio-led-gpset g-gpio) (bit-shift-<< 1 c-gpio-led-bit)) |
|
|
|
(set wait-counter 0))) |
|
|
|
|
|
|
|
(defun set-led-fail () |
|
|
|
(set g-gpio (type-cast c-gpio-base-offset (addr (unsigned int)))) |
|
|
|
;; Enable the led as an output |
|
|
|
(set (at c-gpio-led-gp-function-select g-gpio) |
|
|
|
(bit-or (at c-gpio-led-gp-function-select g-gpio) (bit-shift-<< 1 c-gpio-led-gp-function-bit))) |
|
|
|
(while 1 |
|
|
|
(while (< wait-counter 100000) |
|
|
|
(incr wait-counter)) |
|
|
|
(set (at c-gpio-led-gp-clear g-gpio) (bit-shift-<< 1 c-gpio-led-bit)) |
|
|
|
(set wait-counter 0) |
|
|
|
(while (< wait-counter 500000) |
|
|
|
(incr wait-counter)) |
|
|
|
(set (at c-gpio-led-gpset g-gpio) (bit-shift-<< 1 c-gpio-led-bit)) |
|
|
|
(set wait-counter 0))) |
|
|
|
|
|
|
|
(c-preprocessor-define-constant c-color-test 0xffdd55ee) |
|
|
|
|
|
|
|
(defun main () |
|
|
|
(blink-led 5) |
|
|
|
(var framebuffer pixel-framebuffer (array 0)) |
|
|
|
(initialize-framebuffer (addr framebuffer)) |
|
|
|
(unless (field framebuffer data) |
|
|
|
(set-led-fail)) |
|
|
|
(set g-framebuffer (addr framebuffer)) |
|
|
|
(blink-led 3) |
|
|
|
|
|
|
|
(each-in-range (path g-framebuffer > height) y |
|
|
|
(each-in-range (path g-framebuffer > width) x |
|
|
|
(var offset int (+ (* y (/ (path g-framebuffer > pitch) 4)) x)) |
|
|
|
(set (at offset (type-cast (path g-framebuffer > data) (addr (unsigned int)))) |
|
|
|
(? (or (mod y 100) |
|
|
|
(mod x 100)) |
|
|
|
0xff555555 0xffee2222)))) |
|
|
|
|
|
|
|
(set wait-counter 0) |
|
|
|
(set (at c-gpio-led-gp-function-select g-gpio) |
|
|
|
(bit-or (at c-gpio-led-gp-function-select g-gpio) (bit-shift-<< 1 c-gpio-led-gp-function-bit))) |
|
|
|
;; (var pixel-index int 0) |
|
|
|
(var led-on int 0) |
|
|
|
(while 1 |
|
|
|
(incr wait-counter) |
|
|
|
(when (> wait-counter 100000) |
|
|
|
(set led-on (not led-on)) |
|
|
|
(if led-on |
|
|
|
(set (at c-gpio-led-gpset g-gpio) (bit-shift-<< 1 c-gpio-led-bit)) |
|
|
|
(set (at c-gpio-led-gp-clear g-gpio) (bit-shift-<< 1 c-gpio-led-bit))) |
|
|
|
(set wait-counter 0))) |
|
|
|
|
|
|
|
;; Never return |
|
|
|
(fail-loop)) |