working static, marquee and pan

This commit is contained in:
interfisch 2021-07-03 23:11:45 +02:00
parent f7d33efd31
commit b9b9f8a5ee
1 changed files with 104 additions and 58 deletions

View File

@ -11,8 +11,8 @@ __TOPIC_SCROLL_INTERVAL__ = "scrollinterval"
__TOPIC_TEXT_STATIC__ = "textstatic" __TOPIC_TEXT_STATIC__ = "textstatic"
__TOPIC_TEXT_ONCE__ = "textonce" __TOPIC_TEXT_ONCE__ = "textonce"
__TOPIC_TEXT_SCROLL__ = "textscroll" __TOPIC_TEXT_SCROLL__ = "textscroll"
__TOPIC_TEXT_SCROLL_REPEAT__ = "textscrollrepeat" __TOPIC_TEXT_MARQUEE__ = "textmarquee"
__TOPIC_TEXT_SCROLL_LR__ = "textscrolllr" __TOPIC_TEXT_PAN__ = "textpan"
NUMDIGITS = 8 NUMDIGITS = 8
@ -20,21 +20,25 @@ class Mode(Enum):
STATIC = 1 #show text constantly. may cut digits STATIC = 1 #show text constantly. may cut digits
ONCE = 3 #show once for some time ONCE = 3 #show once for some time
SCROLL = 2 #scroll thorugh once SCROLL = 2 #scroll thorugh once
SCROLL_LR = 4 #scroll back and forth PAN = 4 #scroll back and forth
SCROLL_REPEAT = 5 MARQUEE = 5
class Controller: class Controller:
connected = False connected = False
displayL = None displayL = None
displayR = None displayR = None
last_scrollupdate = 0
mode = Mode.STATIC
def __init__(self, base_topic, mqtt_host, mqtt_port = 1883): def __init__(self, base_topic, mqtt_host, mqtt_port = 1883):
self.scroll_interval = 0.25 self.scroll_interval = 0.25
self.text = " " self.text = " "
self.text_last = ""
self.poscount = 0 self.poscount = 0
self.last_scrollupdate = 0
self.mode = Mode.STATIC
# Create the I2C interface. # Create the I2C interface.
self.i2c = busio.I2C(board.SCL, board.SDA) self.i2c = busio.I2C(board.SCL, board.SDA)
@ -90,24 +94,29 @@ class Controller:
else: else:
print("error not >0.0: ", val) print("error not >0.0: ", val)
if message.topic.endswith(__TOPIC_TEXT_STATIC__ + "/set"):
self.mode = Mode.STATIC
self.text = msg.ljust(NUMDIGITS)
print("changed text to ", self.text)
self.mqtt.publish(self.topic + "/" + __TOPIC_TEXT_STATIC__, self.text, 1 )
if message.topic.endswith(__TOPIC_TEXT_SCROLL_REPEAT__ + "/set"): if message.topic.endswith(__TOPIC_TEXT_MARQUEE__ + "/set"):
self.mode = Mode.SCROLL_REPEAT self.mode = Mode.MARQUEE
self.poscount = 0 #start at beginning of new text self.poscount = 0 #start at beginning of new text
self.text = msg self.text = msg
if len(self.text)==0: for i in range(NUMDIGITS):
self.text=" " self.text = " "+self.text+" " #add spaces left and right for marquee to enter and leave the full frame
print("changed text to ", self.text) print("changed text to ", self.text)
self.mqtt.publish(self.topic + "/" + __TOPIC_TEXT_SCROLL_REPEAT__, self.text, 1 ) self.mqtt.publish(self.topic + "/" + __TOPIC_TEXT_MARQUEE__, self.text, 1 )
if message.topic.endswith(__TOPIC_TEXT_SCROLL_LR__ + "/set"): if message.topic.endswith(__TOPIC_TEXT_PAN__ + "/set"):
self.mode = Mode.SCROLL_LR self.mode = Mode.PAN
self.poscount = 0 #start at beginning of new text self.poscount = 0 #start at beginning of new text
self.text = msg self.text = msg
if len(self.text)==0: for i in range(int(NUMDIGITS/4)):
self.text=" " self.text = " "+self.text+" " #add spaces left and right for marquee to enter and leave the full frame
print("changed text to ", self.text) print("changed text to ", self.text)
self.mqtt.publish(self.topic + "/" + __TOPIC_TEXT_SCROLL_LR__, self.text, 1 ) self.mqtt.publish(self.topic + "/" + __TOPIC_TEXT_PAN__, self.text, 1 )
def on_connect(self, client, userdata, flags, rc): def on_connect(self, client, userdata, flags, rc):
@ -115,36 +124,68 @@ class Controller:
self.mqtt.subscribe(self.topic + "/#") self.mqtt.subscribe(self.topic + "/#")
self.connected = True self.connected = True
def displayTextOffset(self, _text, _offset = 0, _wrap=True): def writeSegment(self, _digit, _char, clear=False):
while len(_text)<NUMDIGITS: if _digit>=0 and _digit<4:
_text+=" " if clear:
self.displayL[_digit]=' '
self.displayL[_digit] = _char
elif _digit<8:
if clear:
self.displayR[_digit-4]=' '
self.displayR[_digit-4] = _char
def displayTextOffset(self, _text, _offset = 0):
# This function is needed because library print functions only work for a single display module. This function handles the '.' character with its special cases.
_text+=" " #append NUMDIGITS spaces at end for when scrolling past end
_text=_text[_offset:] #move by offset
i=0 #counter for reading pos
d=0 #counter for writing segment pos
while d<NUMDIGITS and i<len(_text):
if _text[i]=='.' and _text[max(0,i-1)]=='.': #is dot and was before (or is at start)
self.writeSegment(d,_text[i],True)
d+=1
i+=1
if _wrap:
self.displayL[0] = _text[((_offset+0)%len(_text))]
self.displayL[1] = _text[((_offset+1)%len(_text))]
self.displayL[2] = _text[((_offset+2)%len(_text))]
self.displayL[3] = _text[((_offset+3)%len(_text))]
self.displayR[0] = _text[((_offset+4)%len(_text))]
self.displayR[1] = _text[((_offset+5)%len(_text))]
self.displayR[2] = _text[((_offset+6)%len(_text))]
self.displayR[3] = _text[((_offset+7)%len(_text))]
else: else:
if _offset+0>=0 and _offset+0<len(_text): if _text[i]!='.' : #normal char
self.displayL[0] = _text[((_offset+0))] self.writeSegment(d,_text[i])
if _offset+1>=0 and _offset+1<len(_text): i+=1
self.displayL[1] = _text[((_offset+1))]
if _offset+2>=0 and _offset+2<len(_text): if i<len(_text):
self.displayL[2] = _text[((_offset+2))] if _text[i]=='.': #dot, but can be appended to last char
if _offset+3>=0 and _offset+3<len(_text): self.writeSegment(d,_text[i])
self.displayL[3] = _text[((_offset+3))] i+=1
if _offset+4>=0 and _offset+4<len(_text):
self.displayR[0] = _text[((_offset+4))] d+=1
if _offset+5>=0 and _offset+5<len(_text):
self.displayR[1] = _text[((_offset+5))]
if _offset+6>=0 and _offset+6<len(_text): def seglen(self, _text): #len function but optimized for 14-segment display
self.displayR[2] = _text[((_offset+6))] i=0 #counter for reading pos
if _offset+7>=0 and _offset+7<len(_text): d=0 #counter for writing segment pos
self.displayR[3] = _text[((_offset+7))] while i<len(_text):
if _text[i]=='.' and _text[max(0,i-1)]=='.': #is dot and was before (or is at start)
d+=1
i+=1
else:
if _text[i]!='.' : #normal char
i+=1
if i<len(_text):
if _text[i]=='.': #dot, but can be appended to last char
i+=1
d+=1
return d
def loop_forever(self): def loop_forever(self):
run = True run = True
@ -153,28 +194,33 @@ class Controller:
self.mqtt.loop(0.1) #with block timeout self.mqtt.loop(0.1) #with block timeout
if self.displayL is not None and self.displayR is not None: #displays initialized if self.displayL is not None and self.displayR is not None: #displays initialized
if self.mode == Mode.SCROLL_REPEAT:
if time.time() > self.last_scrollupdate+self.scroll_interval: #time to update animation if self.mode == Mode.STATIC:
self.displayTextOffset(self.text, self.poscount, True) if self.text != self.text_last: #time to update animation
self.displayTextOffset(self.text, 0)
if self.mode == Mode.MARQUEE:
if time.time() > self.last_scrollupdate+self.scroll_interval or self.text != self.text_last: #time to update animation
self.displayTextOffset(self.text, self.poscount)
self.poscount += 1 self.poscount += 1
self.poscount %= len(self.text) self.poscount %= max(1,int(self.seglen(self.text)-NUMDIGITS+1))
self.last_scrollupdate = time.time() self.last_scrollupdate = time.time()
if self.mode == Mode.SCROLL_LR: if self.mode == Mode.PAN:
if time.time() > self.last_scrollupdate+self.scroll_interval: #time to update animation if time.time() > self.last_scrollupdate+self.scroll_interval or self.text != self.text_last: #time to update animation
print("pos=", self.poscount) print("pos=", self.poscount)
scrolloffset = self.poscount scrolloffset = self.poscount
if scrolloffset >= (len(self.text)-NUMDIGITS): if scrolloffset >= (self.seglen(self.text)-NUMDIGITS):
scrolloffset = (len(self.text)-NUMDIGITS) - (scrolloffset-(len(self.text)-NUMDIGITS)) #reverse scrolloffset = (self.seglen(self.text)-NUMDIGITS) - (scrolloffset-(self.seglen(self.text)-NUMDIGITS)) #reverse
scrolloffset = max(0,scrolloffset) #cap at zero scrolloffset = max(0,scrolloffset) #cap at zero
print("scrolloffset=", scrolloffset) print("scrolloffset=", scrolloffset)
self.displayTextOffset(self.text, scrolloffset, False) self.displayTextOffset(self.text, scrolloffset)
self.poscount += 1 self.poscount += 1
self.poscount %= (len(self.text)-NUMDIGITS)*2 #if poscount over scrollable width means scroll backwards self.poscount %= (self.seglen(self.text)-NUMDIGITS)*2 #if poscount over scrollable width means scroll backwards
self.last_scrollupdate = time.time() self.last_scrollupdate = time.time()
self.text_last = self.text