diff --git a/README.md b/README.md index e4d0e4b..2885e77 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,50 @@ -# PixelTime + +
+
+
+
+
+ + +
+ + +# [PixelTime](https://oshwhub.com/kakaka/PixelTime) a low power led watch based on ESP32 C3 + +![5](documents/images/5.png) + +![7](documents/images/7.jpg) + +![4](documents/images/4.jpg) + +![2](documents/images/2.jpg) + +![3](documents/images/3.jpg) + +![6](documents/images/6.jpg) + +![1](documents/images/1.png) + +## Software + +based on MicroPython + + + + + +## Mechanical + + + +## License + +(hardware/mechanical)[Creative Commons — Attribution-NonCommercial-ShareAlike 4.0 International — CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/) + + + +## Extra + + diff --git a/documents/images/1.png b/documents/images/1.png new file mode 100644 index 0000000..3b32da8 Binary files /dev/null and b/documents/images/1.png differ diff --git a/documents/images/2.jpg b/documents/images/2.jpg new file mode 100644 index 0000000..f6e654d Binary files /dev/null and b/documents/images/2.jpg differ diff --git a/documents/images/3.jpg b/documents/images/3.jpg new file mode 100644 index 0000000..819d19d Binary files /dev/null and b/documents/images/3.jpg differ diff --git a/documents/images/4.jpg b/documents/images/4.jpg new file mode 100644 index 0000000..2877f4e Binary files /dev/null and b/documents/images/4.jpg differ diff --git a/documents/images/5.png b/documents/images/5.png new file mode 100644 index 0000000..d0757d4 Binary files /dev/null and b/documents/images/5.png differ diff --git a/documents/images/6.jpg b/documents/images/6.jpg new file mode 100644 index 0000000..5623585 Binary files /dev/null and b/documents/images/6.jpg differ diff --git a/documents/images/7.jpg b/documents/images/7.jpg new file mode 100644 index 0000000..29b9e58 Binary files /dev/null and b/documents/images/7.jpg differ diff --git a/hardware/SCH_1.3a.pdf b/hardware/SCH_1.3a.pdf new file mode 100644 index 0000000..de6b3bf Binary files /dev/null and b/hardware/SCH_1.3a.pdf differ diff --git a/hardware/gerber_bom_pick/BOM_1.3a_PCB1_2_2023-08-18.xlsx b/hardware/gerber_bom_pick/BOM_1.3a_PCB1_2_2023-08-18.xlsx new file mode 100644 index 0000000..0415794 Binary files /dev/null and b/hardware/gerber_bom_pick/BOM_1.3a_PCB1_2_2023-08-18.xlsx differ diff --git a/hardware/gerber_bom_pick/Gerber_PCB1_2_2023-08-18.zip b/hardware/gerber_bom_pick/Gerber_PCB1_2_2023-08-18.zip new file mode 100644 index 0000000..c8ff834 Binary files /dev/null and b/hardware/gerber_bom_pick/Gerber_PCB1_2_2023-08-18.zip differ diff --git a/mechanical/Panel/Panel_2023-08-08.epanm b/mechanical/Panel/Panel_2023-08-08.epanm new file mode 100644 index 0000000..d69d112 Binary files /dev/null and b/mechanical/Panel/Panel_2023-08-08.epanm differ diff --git "a/mechanical/stl/\345\216\213\346\235\277.stl" "b/mechanical/stl/\345\216\213\346\235\277.stl" new file mode 100644 index 0000000..b5e9117 Binary files /dev/null and "b/mechanical/stl/\345\216\213\346\235\277.stl" differ diff --git "a/mechanical/stl/\345\244\226\345\243\263.stl" "b/mechanical/stl/\345\244\226\345\243\263.stl" new file mode 100644 index 0000000..6b4070f Binary files /dev/null and "b/mechanical/stl/\345\244\226\345\243\263.stl" differ diff --git "a/mechanical/stl/\346\214\211\351\224\256.stl" "b/mechanical/stl/\346\214\211\351\224\256.stl" new file mode 100644 index 0000000..5d26bbf Binary files /dev/null and "b/mechanical/stl/\346\214\211\351\224\256.stl" differ diff --git a/software/bitmapfont.py b/software/bitmapfont.py new file mode 100644 index 0000000..a09141d --- /dev/null +++ b/software/bitmapfont.py @@ -0,0 +1,69 @@ +# MicroPython basic bitmap font renderer. +# Author: Tony DiCola +# License: MIT License (https://opensource.org/licenses/MIT) +try: + import ustruct +except ImportError: + import struct as ustruct + + +class BitmapFont: + + def __init__(self, width, height, pixel, font_name='font5x8.bin'): + # Specify the drawing area width and height, and the pixel function to + # call when drawing pixels (should take an x and y param at least). + # Optionally specify font_name to override the font file to use (default + # is font5x8.bin). The font format is a binary file with the following + # format: + # - 1 unsigned byte: font character width in pixels + # - 1 unsigned byte: font character height in pixels + # - x bytes: font data, in ASCII order covering all 255 characters. + # Each character should have a byte for each pixel column of + # data (i.e. a 5x8 font has 5 bytes per character). + self._width = width + self._height = height + self._pixel = pixel + self._font_name = font_name + + def init(self): + # Open the font file and grab the character width and height values. + # Note that only fonts up to 8 pixels tall are currently supported. + self._font = open(self._font_name, 'rb') + self._font_width, self._font_height = ustruct.unpack('BB', self._font.read(2)) + + def deinit(self): + # Close the font file as cleanup. + self._font.close() + + def __enter__(self): + self.init() + return self + + def __exit__(self, exception_type, exception_value, traceback): + self.deinit() + + def draw_char(self, ch, x, y, *args, **kwargs): + # Don't draw the character if it will be clipped off the visible area. + if x < -self._font_width or x >= self._width or \ + y < -self._font_height or y >= self._height: + return + # Go through each column of the character. + for char_x in range(self._font_width): + # Grab the byte for the current column of font data. + self._font.seek(2 + (ord(ch) * self._font_width) + char_x) + line = ustruct.unpack('B', self._font.read(1))[0] + # Go through each row in the column byte. + for char_y in range(self._font_height): + # Draw a pixel for each bit that's flipped on. + if (line >> char_y) & 0x1: + self._pixel(x + char_x, y + char_y, *args, **kwargs) + + def text(self, text, x, y, *args, **kwargs): + # Draw the specified text at the specified location. + for i in range(len(text)): + self.draw_char(text[i], x + (i * (self._font_width + 1)), y, + *args, **kwargs) + + def width(self, text): + # Return the pixel width of the specified text message. + return len(text) * (self._font_width + 1) diff --git a/software/boot.py b/software/boot.py new file mode 100644 index 0000000..f50ed9b --- /dev/null +++ b/software/boot.py @@ -0,0 +1,5 @@ +# This file is executed on every boot (including wake-boot from deepsleep) +#import esp +#esp.osdebug(None) +#import webrepl +#webrepl.start() diff --git a/software/config.py b/software/config.py new file mode 100644 index 0000000..6a4baec --- /dev/null +++ b/software/config.py @@ -0,0 +1,6 @@ + + + +#wifi +ssid = " " +password = " " diff --git a/software/font3x8.py b/software/font3x8.py new file mode 100644 index 0000000..a70f7a1 --- /dev/null +++ b/software/font3x8.py @@ -0,0 +1,122 @@ +FONT3X8 = ( +# +# NUM0 = +( + 1, 1, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 1, 1, +), +# +# NUM1 = + ( + 0, 1, 0, + 1, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 0, 1, 0, + 1, 1, 1, +), +# +# NUM2 = + ( + 1, 1, 1, + 0, 0, 1, + 0, 0, 1, + 1, 1, 1, + 1, 0, 0, + 1, 0, 0, + 1, 0, 0, + 1, 1, 1, +), +# +# NUM3 = +( + 1, 1, 1, + 0, 0, 1, + 0, 0, 1, + 1, 1, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 1, 1, 1, +), +# +# NUM4 = +( + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 1, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, +), +# +# NUM5 = +( + 1, 1, 1, + 1, 0, 0, + 1, 0, 0, + 1, 1, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 1, 1, 1, +), +# +# NUM6 = + ( + 1, 1, 1, + 1, 0, 0, + 1, 0, 0, + 1, 1, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 1, 1, +), +# +# NUM7 = + ( + 1, 1, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, +), +# +# NUM8 = + ( + 1, 1, 1, + 1, 0, 1, + 1, 0, 1, + 1, 1, 1, + 1, 0, 1, + 1, 0, 1, + 1, 0, 1, + 1, 1, 1, +), +# +# NUM9 = + ( + 1, 1, 1, + 1, 0, 1, + 1, 0, 1, + 1, 1, 1, + 0, 0, 1, + 0, 0, 1, + 0, 0, 1, + 1, 1, 1, +) +) \ No newline at end of file diff --git a/software/font5x8.bin b/software/font5x8.bin new file mode 100644 index 0000000..9a0563b Binary files /dev/null and b/software/font5x8.bin differ diff --git a/software/main.py b/software/main.py new file mode 100644 index 0000000..56515a6 --- /dev/null +++ b/software/main.py @@ -0,0 +1,444 @@ + +from machine import I2C, Pin +import time +import network +import neopixel +import gc +import bitmapfont +from font3x8 import * +from week7x7 import * +import rx8111 + +import config + +ssid = config.ssid +password =config.password + +zonetime = 8*3600 + +NEOPIXEL_PIN = 5 +ROWS = 8 +COLS = 15 +NUMBER_PIXELS = ROWS * COLS + +C_BLACK=(0,0,0) +C_GREEN=(0,35,0) +C_BLUE=(0,0,35) +C_RED=(35,0,0) +C_YELLOW=(35,35,0) +C_MONTH=(31,5,12) +C_DAY=(35,31,31) + +np = neopixel.NeoPixel(Pin(NEOPIXEL_PIN), NUMBER_PIXELS) + + + + +#15x8 +ICON_WIFI=( + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,0,1,0,0,1,0,0,1,1,1,0,0,1,0, + 1,0,1,0,0,0,0,0,1,0,0,0,0,0,0, + 1,0,1,0,0,1,0,0,1,1,0,0,0,1,0, + 1,0,1,0,0,1,0,0,1,0,0,0,0,1,0, + 1,1,1,0,0,1,0,0,1,0,0,0,0,1,0, + 1,1,1,0,0,1,0,0,1,0,0,0,0,1,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + +) + +class Display(object): + def __init__(self,np): + self.np=np + + + def write_pixel(self,x,y,value): + if y >= 0 and y < ROWS and x >=0 and x < COLS: + self.np[x*ROWS + y] = value + + def drawPixel(self,x,y,value): + self.write_pixel(x,y,value) + + + + def clear(self): + for i in range(NUMBER_PIXELS): + np[i]=(0,0,0) + self.np.write() + + def show(self): + self.np.write() + + def draw1Num(self,x,y,num,color,bg=None): + num=num%10 + for j in range(8): + for i in range(3): + if FONT3X8[num][i+j*3]==1: + self.write_pixel(x+i,y+j,color) + else : + if bg != None: + self.write_pixel(x+i,y+j,bg) + + def drawNum(self,x,y,num,color,bg=None) : + self.draw1Num(x,y,num//1000%10,color,bg) + self.draw1Num(x+4,y,num%1000//100,color,bg) + self.draw1Num(x+4*2,y,num%100//10,color,bg) + self.draw1Num(x+4*3,y,num%10,color,bg) + + def change1Num(self,x,y,num_src,num_dest,color,bg=None): + num_src=num_src%10 + num_dest=num_dest%10 + + for i in range(1,9): + self.draw1Num(x,y-i,num_src,color,bg) + self.draw1Num(x,y+8-i,num_dest,color,bg) + time.sleep(0.01) + self.show() + + def draw1Week(self,x,y,num,color,bg=None): + for j in range(8): + for i in range(7): + if WEEK7X8[num][i+j*7]==1: + self.write_pixel(x+i,y+j,color) + else : + if bg != None: + self.write_pixel(x+i,y+j,bg) + + def drawWeek(self,x,y,watch,color,bg=None) : + # num=num%7 + # print(num) + self.draw1Week(x,y,7,color,bg) + self.draw1Week(x+8,y,watch.time_now[6],color,bg) + + def drawTime(self,x,y,watch,color1,color2,bg=None): + self.draw1Num(x+0,y,watch.time_now[3]//10,color1,bg) + self.draw1Num(x+4,y,watch.time_now[3]%10,color1,bg) + self.draw1Num(x+8,y,watch.time_now[4]//10,color2,bg) + self.draw1Num(x+12,y,watch.time_now[4]%10,color2,bg) + self.show() + + def drawDate(self,x,y,watch,color1,color2,bg=None): + if watch.time_now[1]//10: + self.draw1Num(x+0,y,watch.time_now[1]//10,color1,bg) + else: + self.draw1Num(x+0,y,watch.time_now[1]//10,bg,bg) + + self.draw1Num(x+4,y,watch.time_now[1]%10,color1,bg) + if watch.time_now[2]//10: + self.draw1Num(x+8,y,watch.time_now[2]//10,color2,bg) + else: + self.draw1Num(x+8,y,watch.time_now[2]//10,bg,bg) + self.draw1Num(x+12,y,watch.time_now[2]%10,color2,bg) + self.show() + + def drawIcon(self,x,y,width,height,icon,color,bg=None): + for j in range(height): + for i in range(width): + if icon[i+j*width]==1: + self.write_pixel(x+i,y+j,color) + else : + if bg != None: + self.write_pixel(x+i,y+j,bg) + + + + +disp = Display(np) + +import machine +class Watch(object): + def __init__(self,time_now): + self.time_now=time_now + self.time_old=time_now + self.timeout=0 #关机超时时间,ms单位 + self.timeout_stamp=time.ticks_ms() + + + def resetTimeout(self,timeout=5000): + self.timeout= timeout + self.timeout_stamp=time.ticks_ms() + + def checkTimeout(self): + deadline = time.ticks_add(self.timeout_stamp, self.timeout) + if time.ticks_diff(deadline, time.ticks_ms()) > 0: + return False + else: + return True + + + + + + + def poweroff(self): + machine.deepsleep() + + + + + +INDEX_HOUR = 3 +INDEX_MINUTE = 4 +INDEX_SECOND = 5 + + + +def updateTime(watch): + watch.time_now = rtc.datetime() + if watch.time_now != watch.time_old: + if watch.time_now[INDEX_MINUTE]%10 != watch.time_old[INDEX_MINUTE]%10: + disp.change1Num(12,0,watch.time_old[INDEX_MINUTE]%10,watch.time_now[INDEX_MINUTE]%10,C_YELLOW,C_BLACK) + + if watch.time_now[INDEX_MINUTE]//10 != watch.time_old[INDEX_MINUTE]//10: + disp.change1Num(8,0,watch.time_old[INDEX_MINUTE]//10,watch.time_now[INDEX_MINUTE]//10,C_YELLOW,C_BLACK) + + if watch.time_now[INDEX_HOUR]%10 != watch.time_old[INDEX_HOUR]%10: + disp.change1Num(4,0,watch.time_old[INDEX_HOUR]%10,watch.time_now[INDEX_HOUR]%10,C_GREEN,C_BLACK) + + if watch.time_now[INDEX_HOUR]//10 != watch.time_old[INDEX_HOUR]//10: + disp.change1Num(0,0,watch.time_old[INDEX_HOUR]//10,watch.time_now[INDEX_HOUR]//10,C_GREEN,C_BLACK) + + watch.time_old = watch.time_now + + +print('rx8111 test') +i2c = I2C(0, scl=Pin(7), sda=Pin(8), freq=400000) +rtc = rx8111.RX8111(i2c) + +week=('SUN','MON','TUE','WED','THU','FRI','SAT') + + + +def syncTimeByWifi(ssid,password,trycnt=10): + if ssid == None : + return + import ntptime + wlan = network.WLAN(network.STA_IF) + wlan.active(True) + wlan.connect(ssid,password) + + while not wlan.isconnected() and wlan.status()>=0 and trycnt>=0: + print("Waiting to connect:") + time.sleep(1.0) + trycnt-=1 + if trycnt%2 : + disp.drawPixel(5,1,C_GREEN) + else: + disp.drawPixel(5,1,C_RED) + + disp.show() + + + if trycnt<0: + wlan.disconnect() + wlan.active(False) + watch.resetTimeout() + + print(wlan.ifconfig()) + + while True: + try: + print('获取时间中') + ntptime.host = 'ntp1.aliyun.com' + ntptime.settime() + print('成功获取') + break + except: + print('获取失败') + time.sleep(1) + wlan.disconnect() + wlan.active(False) + watch.resetTimeout() + + + +charge = Pin(20, Pin.IN, Pin.PULL_UP) + +k1 = Pin(4, Pin.IN) +k2 = Pin(0, Pin.IN) +k3 = Pin(9, Pin.IN) + + +class Event(): + K1_PRESSED=1 + K1_RELEASED=2 + K2_PRESSED=3 + K2_RELEASED=4 + K3_PRESSED=5 + K3_RELEASED=6 + def __init__(self): + self.event=[] + + def addEvent(self,evt): + self.event.append(evt) + + def getEvent(self): + if len(self.event)==0: + return -1 + return self.event.pop(0) + + + +def fun(key): + watch.resetTimeout() + if key==k1: + if key.value() == 0: + # print('k1 pressed') + evt.addEvent(Event.K1_PRESSED) + else: + # print('k1 released') + evt.addEvent(Event.K1_RELEASED) + if key==k2: + if key.value() == 1: + # print('k2 pressed') + evt.addEvent(Event.K2_PRESSED) + else: + # print('k2 released') + evt.addEvent(Event.K2_RELEASED) + if key==k3: + if key.value() == 0: + # print('k3 pressed') + evt.addEvent(Event.K3_PRESSED) + else: + # print('k3 released') + evt.addEvent(Event.K3_RELEASED) + + + + + +k1.irq(fun,Pin.IRQ_FALLING | Pin.IRQ_RISING) +k2.irq(fun,Pin.IRQ_FALLING | Pin.IRQ_RISING) +k3.irq(fun,Pin.IRQ_FALLING | Pin.IRQ_RISING) + +currentPage=0 + + + + +# syncTimeByWifi(ssid,password) +# sec=time.mktime(time.localtime())#获取时间戳 +# now = time.localtime(sec+zonetime)#获取新时区的时间 + +# rtc.datetime(now) + +evt = Event() +disp.clear() + +watch = Watch(rtc.datetime()) + +disp.drawTime( 0,0,watch,C_GREEN,C_YELLOW,C_BLACK) + +watch.resetTimeout() + +def switchPage(): + global currentPage + if currentPage==0: + + for j in range(8): + disp.drawTime(0,-1-j,watch,C_GREEN,C_YELLOW,C_BLACK) + disp.drawWeek(0,7-j,watch,C_GREEN,C_BLACK) + disp.show() + time.sleep(0.01) + currentPage=1 + print(currentPage) + return + + if currentPage==1: + for j in range(8): + disp.drawWeek(0,-1-j,watch,C_GREEN,C_BLACK) + disp.drawDate(0,7-j,watch,C_MONTH,C_DAY,C_BLACK) + disp.show() + time.sleep(0.01) + currentPage=2 + print(currentPage) + return + + if currentPage==2: + for j in range(8): + disp.drawDate(0,-1-j,watch,C_MONTH,C_DAY,C_BLACK) + disp.drawTime(0,7-j,watch,C_GREEN,C_YELLOW,C_BLACK) + disp.show() + time.sleep(0.01) + currentPage=0 + print(currentPage) + return + +def handleEvent(evt): + global currentPage + if evt<=0: + return + + if evt==Event.K2_PRESSED: + switchPage() + pass + if evt==Event.K3_PRESSED: + watch.poweroff() + + if evt==Event.K1_PRESSED: + print('syncTimeByWifi') + + disp.drawIcon(0,0,15,8,ICON_WIFI,C_BLUE,C_BLACK) + disp.show() + syncTimeByWifi(ssid,password) + sec=time.mktime(time.localtime())#获取时间戳 + now = time.localtime(sec+zonetime)#获取新时区的时间 + + rtc.datetime(now) + if currentPage ==0: + disp.drawTime(0,0,watch,C_GREEN,C_YELLOW,C_BLACK) + updateTime(watch) + elif currentPage ==1: + disp.drawWeek(0,0,watch,C_GREEN,C_BLACK) + elif currentPage ==2: + disp.drawDate(0,0,watch,C_MONTH,C_DAY,C_BLACK) + + disp.show() + + print(now) + pass + + + +timeout_en = False + +if charge.value()==0 : + timeout_en = False + +else: + timeout_en = True + + +print(timeout_en) + + + + +while True: + if charge.value()==0 : + time.sleep(1.0) + disp.clear() +# timeout_en = True + + + if watch.checkTimeout() and timeout_en: + print("timeout") + watch.poweroff() + watch.resetTimeout() + + + handleEvent(evt.getEvent()) + # Calculate deadline for operation and test for it + deadline = time.ticks_add(time.ticks_ms(), 5000) + if time.ticks_diff(deadline, time.ticks_ms()) > 0: + deadline = time.ticks_add(time.ticks_ms(), 5000) + if currentPage ==0: + updateTime(watch) + + + + # print(watch.time_now) + time.sleep(0.2) + gc.collect() + # print(f'mem: {gc.mem_free()}') + diff --git a/software/rx8111.py b/software/rx8111.py new file mode 100644 index 0000000..de2b077 --- /dev/null +++ b/software/rx8111.py @@ -0,0 +1,243 @@ +''' + RX8111 RTC drive + + Author: M0dular + Date: 2023-8-5 + Ver: 0.1.0 + + https://oshwhub.com/kakaka +''' + + + +from micropython import const +from math import log2 +from gc import collect +# bus address +RX8111_ADDR = const(0x32) + +# Basic time and calendar register +RX8111_SEC = const(0x10) +RX8111_MIN = const(0x11) +RX8111_HOUR = const(0x12) +RX8111_WEEK = const(0x13) +RX8111_DAY = const(0x14) +RX8111_MONTH = const(0x15) +RX8111_YEAR = const(0x16) +RX8111_MIN_ALARM = const(0x17) +RX8111_HOUR_ALARM = const(0x18) +RX8111_WEEK_DAY_ALARM = const(0x19) +RX8111_TIMER_COUNTER0 = const(0x1A) +RX8111_TIMER_COUNTER1 = const(0x1B) +RX8111_TIMER_COUNTER2 = const(0x1C) +RX8111_EXTENREG = const(0x1D) +RX8111_FLAGREG = const(0x1E) +RX8111_CTRLREG = const(0x1F) + +RX8111_TIMESTAMP_1_1000S = const(0x20) +RX8111_TIMESTAMP_1_100S = const(0x21) +RX8111_TIMESTAMP_SEC = const(0x22) +RX8111_TIMESTAMP_MIN = const(0x23) +RX8111_TIMESTAMP_HOUR = const(0x24) +RX8111_TIMESTAMP_WEEK = const(0x25) +RX8111_TIMESTAMP_DAY = const(0x26) +RX8111_TIMESTAMP_MONTHS = const(0x27) +RX8111_TIMESTAMP_YEAR = const(0x28) +RX8111_STATUS_STAMP = const(0x29) + +RX8111_EVIN_SETTING = const(0x2B) +RX8111_SEC_ALARM = const(0x2C) +RX8111_TIMER_CONTROL = const(0x2D) +RX8111_CMD_TRIG_CTRL = const(0x2E) +RX8111_COMMAND_TRIGGER = const(0x2F) + +RX8111_PWR_SWITCH_CTRL = const(0x32) +RX8111_STATUS_MONITOR = const(0x33) +RX8111_TIME_STAMP_BUF_CTRL = const(0x34) +RX8111_TIME_STAMP_TRIG_CTRL = const(0x35) +RX8111_TIME_STAMP_DATA_STATUS = const(0x36) + +''' +RX8111_EXT_TSEL0 BIT(0) +RX8111_EXT_TSEL1 BIT(1) +RX8111_EXT_ECP BIT(2) +RX8111_EXT_WADA BIT(3) +RX8111_EXT_TE BIT(4) +RX8111_EXT_USEL BIT(5) +RX8111_EXT_FSEL0 BIT(6) +RX8111_EXT_FSEL1 BIT(7) + +RX8111_FLAG_FSTOPF BIT(0) +RX8111_FLAG_VLF BIT(1) +RX8111_FLAG_EVF BIT(2) +RX8111_FLAG_AF BIT(3) +RX8111_FLAG_TF BIT(4) +RX8111_FLAG_UF BIT(5) +RX8111_FLAG_PORF BIT(7) +''' +RX8111_CTRL_STOP =const(0) +''' +RX8111_CTRL_EIE BIT(2) +RX8111_CTRL_AIE BIT(3) +RX8111_CTRL_TIE BIT(4) +RX8111_CTRL_UIE BIT(5) + +RX8111_EVIN_EOVEN BIT(1) +RX8111_EVIN_EPRUP_SEL0 BIT(2) +RX8111_EVIN_EPRUP_SEL1 BIT(3) +RX8111_EVIN_EPRDW_SEL BIT(4) +RX8111_EVIN_ET0 BIT(5) +RX8111_EVIN_ET1 BIT(6) +RX8111_EVIN_EHL BIT(7) + +RX8111_TIMER_CTRL_TSTP BIT(0) +RX8111_TIMER_CTRL_TMPIN BIT(1) +RX8111_TIMER_CTRL_TBKE BIT(2) +RX8111_TIMER_CTRL_TBKON BIT(3) + +RX8111_CMD_TRIG_DUMMY0 BIT(0) +RX8111_CMD_TRIG_DUMMY1 BIT(1) +RX8111_CMD_TRIG_DUMMY2 BIT(2) +RX8111_CMD_TRIG_DUMMY3 BIT(3) +RX8111_CMD_TRIG_DUMMY4 BIT(4) +RX8111_CMD_TRIG_DUMMY5 BIT(5) +RX8111_CMD_TRIG_DUMMY6 BIT(6) +RX8111_CMD_TRIG_DUMMY7 BIT(7) + +RX8111_PSC_SMP_TSEL0 BIT(0) +RX8111_PSC_SMP_TSEL1 BIT(1) +RX8111_PSC_SMP_SWSEL0 BIT(2) +RX8111_PSC_SMP_SWSEL1 BIT(3) +RX8111_PSC_SMP_INIEN BIT(6) +RX8111_PSC_SMP_CHGEN BIT(7) + +RX8111_PSC_SMP_CHGEN BIT(7) + +RX8111_STAT_M_FVLOW BIT(1) +RX8111_STAT_M_FVCMP BIT(3) +RX8111_STAT_M_EVINMON BIT(6) +# Insert and Defined ALARM_AE +RX8111_ALARM_AE BIT(7) + +''' + +class RX8111(object): + def __init__(self,i2c): + self.i2c = i2c + self.tb = bytearray(1) + self.rb = bytearray(1) + self.buf = bytearray(7) + self.DT = [0] * 7 + # if RX8111_ADDR in self.i2c.scan(): + # print('RTC: rx8111 find at address: 0x%x ' %(RX8111_ADDR)) + # else: + # print('RTC: rx8111 not found at address: 0x%x ' %(RX8111_ADDR)) + # collect() # + + # set reg + def setReg(self, reg, dat): + self.tb[0] = dat + self.i2c.writeto_mem(RX8111_ADDR, reg, self.tb) + + # get reg + def getReg(self, reg): + self.i2c.readfrom_mem_into(RX8111_ADDR, reg, self.rb) + return self.rb[0] + + + # 将二进制编码的十进制数转换为普通十进制数 + def _bcd2dec(self, bcd) : + """Convert binary coded decimal (BCD) format to decimal""" + return (((bcd & 0xf0) >> 4) * 10 + (bcd & 0x0f)) + + # 将十进制编码的二进制数转换为普通十进制数 + def _dec2bcd(self, dec): + """Convert decimal to binary coded decimal (BCD) format""" + tens, units = divmod(dec, 10) + return (tens << 4) + units + + def WeekToBdc(self, val) : + return 0x01 << val + + + def WeekToNum(self, val) : + return int(log2(val)) + + + + def setBit(self, reg, bit_addr): + + data = self.getReg(reg) + data |= (0x01 << bit_addr) + + self.setReg(reg, data) + + + def clearBit(self, reg, bit_addr): + + data = self.getReg(reg) + data &= ~(0x01 << bit_addr) + + self.setReg(reg, data) + + def datetime(self,DT=None): + ''' + DT: year,month,day,hour,minute,second,weekday + 在Python的time.localtime()函数中,stars from Monday (0) and ends on Sunday (6)。所以星期从0开始计数,0代表星期一。 + 而rx8111是从星期日开始计数,0代表星期日 + Sunday 0 0 0 0 0 0 0 1 01 h + Monday 0 0 0 0 0 0 1 0 02 h + Tuesday 0 0 0 0 0 1 0 0 04 h + Wednesday 0 0 0 0 1 0 0 0 08 h + Thursday 0 0 0 1 0 0 0 0 10 h + Friday 0 0 1 0 0 0 0 0 20 h + Saturday 0 1 0 0 0 0 0 0 40 h + ''' + if DT==None: + self.i2c.readfrom_mem_into(RX8111_ADDR, RX8111_SEC, self.buf) + + self.DT[0] = self._bcd2dec(self.buf[6]) + 2000 # year + self.DT[1] = self._bcd2dec(self.buf[5]& 0x1F)# month + self.DT[2] = self._bcd2dec(self.buf[4] & 0x3F)# day + + self.DT[3] = self._bcd2dec(self.buf[2] & 0x3F)# hour + self.DT[4] = self._bcd2dec(self.buf[1]& 0x7F)# minute + self.DT[5] = self._bcd2dec(self.buf[0]& 0x7F)# second + + self.DT[6] = self.WeekToNum(self.buf[3]) # week day + + return tuple(self.DT) + else: + self.setBit(RX8111_CTRLREG, RX8111_CTRL_STOP) + self.setReg(RX8111_FLAGREG, 0x00) + + self.buf[6] = self._dec2bcd(DT[0]%100) # year + self.buf[5] = self._dec2bcd(DT[1]%13) # month + self.buf[4] = self._dec2bcd(DT[2]%32) # day + + self.buf[2] = self._dec2bcd(DT[3]%24) # hour + self.buf[1] = self._dec2bcd(DT[4]%60) # minute + self.buf[0] = self._dec2bcd(DT[5]%60) # second + + self.buf[3] = self.WeekToBdc((DT[6]+1)%7) # week day + + self.i2c.writeto_mem(RX8111_ADDR, RX8111_SEC, self.buf) + + self.clearBit(RX8111_CTRLREG, RX8111_CTRL_STOP) + + + + + +if __name__ == "__main__": + from machine import I2C, Pin + import time + print('rx8111 test') + i2c = I2C(0, scl=Pin(7), sda=Pin(8), freq=400000) + rtc = RX8111(i2c) + rtc.datetime((2023,8,5,16,25,59,6)) + while True: + print(rtc.datetime()) + time.sleep(1.0) + + diff --git a/software/week7x7.py b/software/week7x7.py new file mode 100644 index 0000000..2505a0c --- /dev/null +++ b/software/week7x7.py @@ -0,0 +1,86 @@ +WEEK7X8=( + (0,1,1,1,1,1,0, + 0,1,0,0,0,1,0, + 0,1,0,0,0,1,0, + 0,1,1,1,1,1,0, + 0,1,0,0,0,1,0, + 0,1,0,0,0,1,0, + 0,1,1,1,1,1,0, + 0,0,0,0,0,0,0, + + ),#日 + (0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,1,0, + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + + ),#一 + ( + 0,0,0,0,0,0,0, + 0,1,1,1,1,1,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,1,0, + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + + ),#二 + (0,0,0,0,0,0,0, + 0,1,1,1,1,1,0, + 0,0,0,0,0,0,0, + 0,0,1,1,1,0,0, + 0,0,0,0,0,0,0, + 0,0,0,0,0,0,0, + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + + ),#三 + ( + 1,1,1,1,1,1,1, + 1,0,1,0,1,0,1, + 1,0,1,0,1,0,1, + 1,0,1,0,1,1,1, + 1,1,0,0,0,0,1, + 1,0,0,0,0,0,1, + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + ),#四 + ( + 0,1,1,1,1,1,0, + 0,0,0,1,0,0,0, + 0,0,0,1,0,0,0, + 0,1,1,1,1,1,0, + 0,0,1,0,0,1,0, + 0,0,1,0,0,1,0, + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + + ),#五 + ( + 0,0,0,1,0,0,0, + 1,1,1,1,1,1,1, + 0,0,0,0,0,0,0, + 0,0,1,0,1,0,0, + 0,0,1,0,1,0,0, + 0,1,0,0,0,1,0, + 1,0,0,0,0,0,1, + 0,0,0,0,0,0,0, + ),#六 + ( + 0,1,1,1,1,1,1, + 0,1,0,1,0,0,1, + 0,1,1,1,1,0,1, + 0,1,0,1,0,0,1, + 0,1,1,1,1,1,1, + 0,1,1,0,1,0,1, + 1,0,1,1,1,0,1, + 0,0,0,0,0,0,0, + ),#周 + + + ) \ No newline at end of file