84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
"""
|
|
Circuitpython MY9221 LED driver
|
|
|
|
MIT License
|
|
Copyright (c) 2018 Mike Causer
|
|
Copyright (c) 2025 P.M. Kuipers
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
of this software and associated documentation files (the "Software"), to deal
|
|
in the Software without restriction, including without limitation the rights
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
furnished to do so, subject to the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
SOFTWARE.
|
|
"""
|
|
|
|
from digitalio import DigitalInOut, Direction
|
|
from microcontroller import delay_us
|
|
|
|
class MY9221:
|
|
def __init__(self, di, dcki, reverse=False):
|
|
self._d = DigitalInOut(di)
|
|
self._c = DigitalInOut(dcki)
|
|
self._r = reverse
|
|
self._d.direction = Direction.OUTPUT
|
|
self._d.value = 0
|
|
self._c.direction = Direction.OUTPUT
|
|
self._c.value = 0
|
|
|
|
def _latch(self):
|
|
self._d.value = 0
|
|
delay_us(10000)
|
|
for i in range(4):
|
|
self._d.value = 1
|
|
self._d.value = 0
|
|
delay_us(10000)
|
|
|
|
def _write16(self, data):
|
|
for i in range(15,-1,-1):
|
|
self._d.value = ((data >> i) & 1) # shift next bit
|
|
self._c.value = not self._c.value # trigger clock (triggers on both rising and falling edges)
|
|
|
|
def _begin(self):
|
|
self._write16(0x0000) # command: 8bit mode
|
|
|
|
def _end(self):
|
|
# unused last 2 channels are required to fill the 208 bit shift register
|
|
self._write16(0)
|
|
self._write16(0)
|
|
self._latch()
|
|
|
|
def reverse(self, val=None):
|
|
if val is None:
|
|
return self._r
|
|
self._r = val
|
|
|
|
def level(self, val, brightness=255):
|
|
self._begin()
|
|
for i in range(9,-1,-1) if self._r else range(10):
|
|
self._write16(brightness if val > i else 0)
|
|
self._end()
|
|
|
|
def bits(self, val, brightness=255):
|
|
val &= 0x3FF
|
|
self._begin()
|
|
for i in range(9,-1,-1) if self._r else range(10):
|
|
self._write16(brightness if (val >> i) & 1 else 0)
|
|
self._end()
|
|
|
|
def bytes(self, buf):
|
|
self._begin()
|
|
for i in range(9,-1,-1) if self._r else range(10):
|
|
self._write16(buf[i])
|
|
self._end()
|