|
|
------------------------------------------------------------------------------
|
|
|
-- --
|
|
|
-- Copyright (C) 2019-2020, AdaCore --
|
|
|
-- --
|
|
|
-- Redistribution and use in source and binary forms, with or without --
|
|
|
-- modification, are permitted provided that the following conditions are --
|
|
|
-- met: --
|
|
|
-- 1. Redistributions of source code must retain the above copyright --
|
|
|
-- notice, this list of conditions and the following disclaimer. --
|
|
|
-- 2. Redistributions in binary form must reproduce the above copyright --
|
|
|
-- notice, this list of conditions and the following disclaimer in --
|
|
|
-- the documentation and/or other materials provided with the --
|
|
|
-- distribution. --
|
|
|
-- 3. Neither the name of the copyright holder nor the names of its --
|
|
|
-- contributors may be used to endorse or promote products derived --
|
|
|
-- from this software without specific prior written permission. --
|
|
|
-- --
|
|
|
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS --
|
|
|
-- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT --
|
|
|
-- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR --
|
|
|
-- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT --
|
|
|
-- HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, --
|
|
|
-- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT --
|
|
|
-- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, --
|
|
|
-- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY --
|
|
|
-- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT --
|
|
|
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE --
|
|
|
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --
|
|
|
-- --
|
|
|
------------------------------------------------------------------------------
|
|
|
|
|
|
-- Bit-bang a sequence of color LED values to a one-pin LED strip (WS2812B
|
|
|
-- or similar).
|
|
|
|
|
|
with System.Machine_Code; use System, System.Machine_Code;
|
|
|
|
|
|
with NRF_SVD.GPIO; use NRF_SVD.GPIO;
|
|
|
with MicroBit.Time;
|
|
|
|
|
|
package body MicroBit.IOs.NeoPixel is
|
|
|
|
|
|
-----------
|
|
|
-- Write --
|
|
|
-----------
|
|
|
|
|
|
procedure Write (Pin : Pin_Id; Values : UInt8_Array) is
|
|
|
Point : constant GPIO_Point := Points (Pin);
|
|
|
Mask : constant UInt32 := 2 ** Point.Pin;
|
|
|
EOL : constant String := ASCII.LF & ASCII.HT;
|
|
|
begin
|
|
|
-- Set pin to digital out mode and reset strip
|
|
|
|
|
|
Set (Pin, False);
|
|
|
MicroBit.Time.Delay_Ms (1);
|
|
|
|
|
|
-- The following loop is very time-sensitive. The bit frame is 1.25 <EFBFBD>s,
|
|
|
-- i.e. 20 cycles of the 16 MHz clock. So, we run it with IRQs disabled,
|
|
|
-- and carefully account for every cycle.
|
|
|
-- Code taken from:
|
|
|
-- https://github.com/Microsoft/pxt-ws2812b/blob/master/sendBuffer.asm
|
|
|
|
|
|
Asm (" cpsid i @ disable irq" & EOL &
|
|
|
" b .start" & EOL &
|
|
|
|
|
|
".nextbit: @ c0" & EOL &
|
|
|
" str %2, [%1, #0] @ pin := hi c2" & EOL &
|
|
|
" tst r6, r0 @ c3" & EOL &
|
|
|
" bne .islate @ c4" & EOL &
|
|
|
" str %2, [%0, #0] @ pin := lo c6" & EOL &
|
|
|
|
|
|
".islate:" & EOL &
|
|
|
" lsr r6, r6, #1 @ r6 >>= 1 c7" & EOL &
|
|
|
" bne .justbit @ c8" & EOL &
|
|
|
|
|
|
"@ not just a bit - need new byte" & EOL &
|
|
|
|
|
|
" add %3, #1 @ buf++ c9" & EOL &
|
|
|
" sub %4, #1 @ len-- c10" & EOL &
|
|
|
" bcc .stop @ if (len<0) goto .stop c11" & EOL &
|
|
|
|
|
|
".start:" & EOL &
|
|
|
" movs r6, #0x80 @ reset mask c12" & EOL &
|
|
|
" nop @ c13" & EOL &
|
|
|
|
|
|
".common: @ c13" & EOL &
|
|
|
" str %2, [%0, #0] @ pin := lo c15" & EOL &
|
|
|
|
|
|
" @ always re-load byte - it just fits with the" & EOL &
|
|
|
" @ cycles better this way." & EOL &
|
|
|
|
|
|
" ldrb r0, [%3, #0] @ r0 := *buf c17" & EOL &
|
|
|
" b .nextbit @ c20" & EOL &
|
|
|
|
|
|
".justbit: @ c10" & EOL &
|
|
|
|
|
|
" @ no nops, branch taken is already 3 cycles" & EOL &
|
|
|
" b .common @ c13" & EOL &
|
|
|
|
|
|
".stop:" & EOL &
|
|
|
" str %2, [%0, #0] @ pin := lo" & EOL &
|
|
|
" cpsie i @ enable irq",
|
|
|
|
|
|
Inputs => (Address'Asm_Input ("l", GPIO_Periph_0.OUTCLR'Address), -- %0
|
|
|
Address'Asm_Input ("l", GPIO_Periph_0.OUTSET'Address), -- %1
|
|
|
UInt32'Asm_Input ("l", Mask), -- %2
|
|
|
Address'Asm_Input ("l", Values'Address), -- %3
|
|
|
Natural'Asm_Input ("l", Values'Length)), -- %4
|
|
|
Volatile => True,
|
|
|
Clobber => "r0,r6");
|
|
|
end Write;
|
|
|
|
|
|
end MicroBit.IOs.NeoPixel;
|
|
|
|