]> vault307.fbx.one Git - PicoTamachibi.git/commitdiff
initial commit
authorAus000Alex <143391931+Aus000Alex@users.noreply.github.com>
Wed, 14 Feb 2024 09:14:48 +0000 (10:14 +0100)
committerGitHub <noreply@github.com>
Wed, 14 Feb 2024 09:14:48 +0000 (10:14 +0100)
Added files form localy working version

81 files changed:
baby.pbm [new file with mode: 0644]
baby_bounce01.pbm [new file with mode: 0644]
baby_bounce02.pbm [new file with mode: 0644]
baby_bounce03.pbm [new file with mode: 0644]
baby_bounce04.pbm [new file with mode: 0644]
baby_zzz01.pbm [new file with mode: 0644]
baby_zzz02.pbm [new file with mode: 0644]
baby_zzz03.pbm [new file with mode: 0644]
baby_zzz04.pbm [new file with mode: 0644]
book.pbm [new file with mode: 0644]
bubble.pbm [new file with mode: 0644]
bubble.xcf [new file with mode: 0644]
button_test.py [new file with mode: 0644]
call.pbm [new file with mode: 0644]
call_animate01.pbm [new file with mode: 0644]
call_animate03.pbm [new file with mode: 0644]
disc.pbm [new file with mode: 0644]
display.py [new file with mode: 0644]
eat01.pbm [new file with mode: 0644]
eat02.pbm [new file with mode: 0644]
eat03.pbm [new file with mode: 0644]
eat04.pbm [new file with mode: 0644]
eat05.pbm [new file with mode: 0644]
eat06.pbm [new file with mode: 0644]
eat07.pbm [new file with mode: 0644]
eat08.pbm [new file with mode: 0644]
firstaid.pbm [new file with mode: 0644]
food.pbm [new file with mode: 0644]
game.pbm [new file with mode: 0644]
heart.pbm [new file with mode: 0644]
heart_plus.pbm [new file with mode: 0644]
icon.py [new file with mode: 0644]
lib/sdcard.py [new file with mode: 0644]
lightbulb.pbm [new file with mode: 0644]
main.py [new file with mode: 0644]
poop01.pbm [new file with mode: 0644]
poop02.pbm [new file with mode: 0644]
poop03.pbm [new file with mode: 0644]
poop04.pbm [new file with mode: 0644]
potty01.pbm [new file with mode: 0644]
potty02.pbm [new file with mode: 0644]
potty03.pbm [new file with mode: 0644]
potty04.pbm [new file with mode: 0644]
potty05.pbm [new file with mode: 0644]
potty06.pbm [new file with mode: 0644]
potty07.pbm [new file with mode: 0644]
potty08.pbm [new file with mode: 0644]
potty09.pbm [new file with mode: 0644]
potty10.pbm [new file with mode: 0644]
potty11.pbm [new file with mode: 0644]
potty12.pbm [new file with mode: 0644]
potty13.pbm [new file with mode: 0644]
potty14.pbm [new file with mode: 0644]
raw_assets/baby_zzz01.xcf [new file with mode: 0644]
raw_assets/baby_zzz02.xcf [new file with mode: 0644]
raw_assets/baby_zzz03.xcf [new file with mode: 0644]
raw_assets/baby_zzz04.xcf [new file with mode: 0644]
raw_assets/baby_zzz05.xcf [new file with mode: 0644]
raw_assets/bubble.xcf [new file with mode: 0644]
raw_assets/call_animate01.xcf [new file with mode: 0644]
raw_assets/call_animate02.xcf [new file with mode: 0644]
raw_assets/call_animate03.xcf [new file with mode: 0644]
raw_assets/potty01.xcf [new file with mode: 0644]
raw_assets/potty02.xcf [new file with mode: 0644]
raw_assets/potty03.xcf [new file with mode: 0644]
raw_assets/potty04.xcf [new file with mode: 0644]
raw_assets/potty05.xcf [new file with mode: 0644]
raw_assets/potty06.xcf [new file with mode: 0644]
raw_assets/potty07.xcf [new file with mode: 0644]
raw_assets/potty08.xcf [new file with mode: 0644]
raw_assets/potty09.xcf [new file with mode: 0644]
raw_assets/potty10.xcf [new file with mode: 0644]
raw_assets/potty11.xcf [new file with mode: 0644]
raw_assets/potty12.xcf [new file with mode: 0644]
raw_assets/skull01.xcf [new file with mode: 0644]
raw_assets/skull02.xcf [new file with mode: 0644]
sdcardtest.py [new file with mode: 0644]
skull01.pbm [new file with mode: 0644]
skull02.pbm [new file with mode: 0644]
ssd1306.py [new file with mode: 0644]
toilet.pbm [new file with mode: 0644]

diff --git a/baby.pbm b/baby.pbm
new file mode 100644 (file)
index 0000000..6f5c079
Binary files /dev/null and b/baby.pbm differ
diff --git a/baby_bounce01.pbm b/baby_bounce01.pbm
new file mode 100644 (file)
index 0000000..1cbc4fc
Binary files /dev/null and b/baby_bounce01.pbm differ
diff --git a/baby_bounce02.pbm b/baby_bounce02.pbm
new file mode 100644 (file)
index 0000000..b089a60
Binary files /dev/null and b/baby_bounce02.pbm differ
diff --git a/baby_bounce03.pbm b/baby_bounce03.pbm
new file mode 100644 (file)
index 0000000..7ceda96
Binary files /dev/null and b/baby_bounce03.pbm differ
diff --git a/baby_bounce04.pbm b/baby_bounce04.pbm
new file mode 100644 (file)
index 0000000..bae5c77
Binary files /dev/null and b/baby_bounce04.pbm differ
diff --git a/baby_zzz01.pbm b/baby_zzz01.pbm
new file mode 100644 (file)
index 0000000..17ec879
Binary files /dev/null and b/baby_zzz01.pbm differ
diff --git a/baby_zzz02.pbm b/baby_zzz02.pbm
new file mode 100644 (file)
index 0000000..d4bf401
Binary files /dev/null and b/baby_zzz02.pbm differ
diff --git a/baby_zzz03.pbm b/baby_zzz03.pbm
new file mode 100644 (file)
index 0000000..9da9e1d
Binary files /dev/null and b/baby_zzz03.pbm differ
diff --git a/baby_zzz04.pbm b/baby_zzz04.pbm
new file mode 100644 (file)
index 0000000..25c8908
Binary files /dev/null and b/baby_zzz04.pbm differ
diff --git a/book.pbm b/book.pbm
new file mode 100644 (file)
index 0000000..566955d
Binary files /dev/null and b/book.pbm differ
diff --git a/bubble.pbm b/bubble.pbm
new file mode 100644 (file)
index 0000000..88f1dba
Binary files /dev/null and b/bubble.pbm differ
diff --git a/bubble.xcf b/bubble.xcf
new file mode 100644 (file)
index 0000000..13fa5e9
Binary files /dev/null and b/bubble.xcf differ
diff --git a/button_test.py b/button_test.py
new file mode 100644 (file)
index 0000000..fbf15c5
--- /dev/null
@@ -0,0 +1,10 @@
+from machine import Pin
+
+button = Pin(15, Pin.IN, Pin.PULL_DOWN)
+
+while True:
+    print(button.value())
+    if button.value() == 0:
+        print("0")
+    if button.value() == 1:
+        print("1")
\ No newline at end of file
diff --git a/call.pbm b/call.pbm
new file mode 100644 (file)
index 0000000..2ef732d
Binary files /dev/null and b/call.pbm differ
diff --git a/call_animate01.pbm b/call_animate01.pbm
new file mode 100644 (file)
index 0000000..1a0303e
Binary files /dev/null and b/call_animate01.pbm differ
diff --git a/call_animate03.pbm b/call_animate03.pbm
new file mode 100644 (file)
index 0000000..deae954
Binary files /dev/null and b/call_animate03.pbm differ
diff --git a/disc.pbm b/disc.pbm
new file mode 100644 (file)
index 0000000..d9400ff
Binary files /dev/null and b/disc.pbm differ
diff --git a/display.py b/display.py
new file mode 100644 (file)
index 0000000..872ef96
--- /dev/null
@@ -0,0 +1,39 @@
+from machine import I2C, Pin
+from ssd1306 import SSD1306_I2C
+import framebuf
+from time import sleep
+
+sda = Pin(0)
+scl = Pin(1)
+id = 0
+
+i2c = I2C(id=id, sda=sda, scl=scl)
+
+oled = SSD1306_I2C(width=128, height=64, i2c=i2c)
+oled.init_display()
+oled.text("test", 1, 1)
+oled.show()
+sleep(1)
+
+images = []
+for n in range (1,5):
+    with open('frame0%s.pbm' % n, 'rb') as f:
+        f.readline() # magic number
+        f.readline() # creator comment
+        f.readline() # dimensions
+        data = bytearray(f.read())
+    fbuf = framebuf.FrameBuffer(data, 128,64, framebuf.MONO_HLSB)
+    images.append(fbuf)
+
+while True:
+    for i in images:
+        oled.invert(1)
+        oled.blit(i,0,0)
+        oled.show()
+        sleep(0.1)
+    sleep(0.4)
+    for i in reversed(images):
+        oled.invert(1)
+        oled.blit(i,0,0)
+        oled.show()
+        sleep(0.1)
diff --git a/eat01.pbm b/eat01.pbm
new file mode 100644 (file)
index 0000000..c8dea3d
Binary files /dev/null and b/eat01.pbm differ
diff --git a/eat02.pbm b/eat02.pbm
new file mode 100644 (file)
index 0000000..425f990
Binary files /dev/null and b/eat02.pbm differ
diff --git a/eat03.pbm b/eat03.pbm
new file mode 100644 (file)
index 0000000..7e28ec3
Binary files /dev/null and b/eat03.pbm differ
diff --git a/eat04.pbm b/eat04.pbm
new file mode 100644 (file)
index 0000000..ae04fa3
Binary files /dev/null and b/eat04.pbm differ
diff --git a/eat05.pbm b/eat05.pbm
new file mode 100644 (file)
index 0000000..6a82821
Binary files /dev/null and b/eat05.pbm differ
diff --git a/eat06.pbm b/eat06.pbm
new file mode 100644 (file)
index 0000000..a24c0a8
Binary files /dev/null and b/eat06.pbm differ
diff --git a/eat07.pbm b/eat07.pbm
new file mode 100644 (file)
index 0000000..87278ba
Binary files /dev/null and b/eat07.pbm differ
diff --git a/eat08.pbm b/eat08.pbm
new file mode 100644 (file)
index 0000000..9b0db4c
Binary files /dev/null and b/eat08.pbm differ
diff --git a/firstaid.pbm b/firstaid.pbm
new file mode 100644 (file)
index 0000000..424b902
Binary files /dev/null and b/firstaid.pbm differ
diff --git a/food.pbm b/food.pbm
new file mode 100644 (file)
index 0000000..cdd1e06
Binary files /dev/null and b/food.pbm differ
diff --git a/game.pbm b/game.pbm
new file mode 100644 (file)
index 0000000..9c7b680
Binary files /dev/null and b/game.pbm differ
diff --git a/heart.pbm b/heart.pbm
new file mode 100644 (file)
index 0000000..2f32140
Binary files /dev/null and b/heart.pbm differ
diff --git a/heart_plus.pbm b/heart_plus.pbm
new file mode 100644 (file)
index 0000000..76ddad1
Binary files /dev/null and b/heart_plus.pbm differ
diff --git a/icon.py b/icon.py
new file mode 100644 (file)
index 0000000..564bd2f
--- /dev/null
+++ b/icon.py
@@ -0,0 +1,665 @@
+import framebuf
+from machine import Pin
+from time import sleep
+from os import listdir
+import gc
+
+class Icon():
+    """ Models an icon and all the properties it requires """
+    __image = None
+    __x = 0
+    __y = 0
+    __invert = False
+    __width = 16
+    __height = 16
+    __name = "Empty"
+
+
+    def __init__(self, filename:None, width=None, height=None, x=None, y=None, name=None):
+        """ Sets up the default values """
+        if width:
+            self.__width = width
+        if height:
+            self.__height = height
+        if name:
+            self.__name = name
+        if x:
+            self.__x = x
+        if y:
+            self.__y = y
+        if filename is not None:
+            self.__image = self.loadicons(filename)
+
+    @property
+    def image(self):
+        """ gets the icon image """
+
+        return self.__image
+
+    @image.setter
+    def image(self, buf):
+        """ Sets the icon image """
+
+        self.__image = buf
+    
+    @property
+    def x(self)->int:
+        """ Gets the X value """
+
+        return self.__x
+
+
+    @x.setter
+    def x(self, value):
+        """ Sets the X value """
+
+        self.__x = value
+
+
+    @property
+    def width(self)->int:
+        """ Get the width"""
+
+        return self.__width
+
+
+    @width.setter
+    def width(self, value):
+        """ Sets the icon width """
+
+        self.__width = value
+
+
+    @property
+    def height(self):
+        """ Returns height """
+        return self.__height
+
+
+    @height.setter
+    def height(self, value):
+        """ Gets the height """
+
+        self.__height = value
+
+
+    @property
+    def name(self):
+        """ Gets the name """
+
+        return self.__name
+
+
+    @name.setter
+    def name(self, value):
+        """ Sets the icon name """
+
+        self.__name = value
+
+
+    @property
+    def y(self)->int:
+        """ Gets the y value """
+
+        return self.__y
+
+
+    @y.setter
+    def y(self, value):
+        """ Sets the Y value """
+
+        self.__y = value
+
+
+    @property
+    def invert(self)->bool:
+        """ Flips the bits in the image so white become black etc and returns the image """
+        print("Invert is", self.__invert)
+        return self.__invert
+
+    @invert.setter
+    def invert(self, value:bool):
+        """ Inverts the icon colour """
+        
+        image = self.__image
+        for x in range(0,self.width):
+            for y in range(0, self.height):
+                pxl = image.pixel(x,y)
+                if pxl == 0:
+                    image.pixel(x,y,1)
+                else:
+                    image.pixel(x,y,0)
+                
+        self.__image = image
+        self.__invert = value
+        # print("Invert is", self.__invert)
+
+    def loadicons(self, file):
+        # print(file)
+        with open(file, 'rb') as f:
+            f.readline() # magic number
+            f.readline() # creator comment
+            f.readline() # dimensions
+            data = bytearray(f.read())
+        fbuf = framebuf.FrameBuffer(data, self.__width,self.__height, framebuf.MONO_HLSB)
+        # print(self.__name, self.__width, self.__height)
+        return fbuf
+
+class Toolbar():
+    """ Models the toolbar """
+    __icon_array = []
+    __framebuf = framebuf.FrameBuffer(bytearray(160*64*1), 160, 16, framebuf.MONO_HLSB)
+    __spacer = 1
+    __selected_item = None
+    __selected_index = -1 # -1 means no item selected
+  
+    def __init__(self):
+        # print("building toolbar")
+        self.__framebuf = framebuf.FrameBuffer(bytearray(160*64*8), 160, 16, framebuf.MONO_HLSB)
+
+    def additem(self, icon):
+        self.__icon_array.append(icon)
+        print("mehr icons...")
+
+
+    def remove(self, icon):
+        self.__icon_array.remove(icon)
+
+    def getlength(self):
+        return len(self.__icon_array)
+    
+    """
+    @property
+    def data(self):
+        
+        x = 0
+        count = 0
+        for icon in self.__icon_array:
+            # print("x:",x)
+            count += 1
+            if type(icon) == Icon:
+                self.__framebuf.blit(icon.image, x, 0)
+            if type(icon) == Animate:
+                self.__framebuf.blit(icon.__frames[icon.__current_frame].image, x, 0)
+            fb = self.__framebuf
+            x += icon.width + self.spacer
+        return fb
+    """
+    
+    @property
+    def spacer(self):
+        """ returns the spacer value"""
+        return self.__spacer
+
+    @spacer.setter
+    def spacer(self, value):
+        """ Sets the spacer value"""
+        self.__spacer = value
+
+    def show(self, oled):
+        oled.blit(self.__framebuf, 0,0)
+        # oled.show()
+    
+    def select(self, index, oled):
+        """ Set the item in the index to inverted """
+        # for item in self.__icon_array:
+        #     item.invert = False 
+        self.__icon_array[index].invert = True
+        self.__selected_index = index
+        offsetvalue = 3
+        x=0
+        for loopcount in range(len(self.__icon_array)):
+            offset = loopcount - offsetvalue
+            zeiger = (index + offset) % len(self.__icon_array)
+            # print("x:",x)
+            if type(self.__icon_array[zeiger]) == Icon:
+                self.__framebuf.blit(self.__icon_array[zeiger].image, x, 0) 
+            if type(self.__icon_array[zeiger]) == Animate:
+                self.__framebuf.blit(self.__icon_array[zeiger].__frames[self.__icon_array[zeiger].__current_frame].image, x, 0)
+            fb = self.__framebuf
+            x += self.__icon_array[zeiger].width + self.spacer
+        return fb
+
+    def unselect(self, index, oled):
+        self.__icon_array[index].invert = False
+        self.__selected_index = -1
+        self.show(oled)
+
+    @property
+    def selected_item(self):
+        """ Returns the name of the currently selected icon """
+        self.__selected_item = self.__icon_array[self.__selected_index].name
+        return self.__selected_item
+
+class Animate():
+    __frames = []
+    __current_frame = 0
+    __speed = "normal" # Other speeds are 'fast' and 'slow' - it just adds frames or skips frames
+    __speed_value = 0
+    __done = False # Has the animation completed
+    __loop_count = 0
+    __bouncing = False
+    __animation_type = "default"
+    __pause = 0
+    __set = False
+    __x = 0
+    __y = 0
+    __width = 16
+    __height = 16
+    __cached = False
+    __filename = None
+    """ other animations types: 
+        - loop
+        - bounce
+        - reverse
+    """
+    @property
+    def set(self)->bool:
+        return self.__set
+
+    @set.setter
+    def set(self, value:bool):
+        self.__set = value
+        if value == True:
+            self.load()
+        else:
+            self.unload()
+            
+
+    @property
+    def speed(self):
+        """ Returns the current speed """
+        return self.__speed
+
+    @speed.setter
+    def speed(self, value:str):
+        if value in ['very slow','slow','normal','fast']:
+            self.__speed = value
+            if value == 'very slow':
+                self.__pause = 10
+                self.__speed_value = 10
+            if value == 'slow':
+                self.__pause = 1
+                self.__speed_value = 1
+            if value == "normal":
+                self.__pause = 0
+                self.__speed_value = 0
+        else:
+            print(value, "is not a valid value, try 'fast','normal' or 'slow'")
+
+    @property
+    def animation_type(self):
+        return self.__animation_type
+
+    @animation_type.setter
+    def animation_type(self, value):
+        if value in ['default','loop','bounce','reverse']:
+            self.__animation_type = value
+        else:
+            print(value," is not a valid Animation type - it should be 'loop','bounce','reverse' or 'default'")
+
+    def __init__(self, frames=None, animation_type:str=None,x:int=None,y:int=None, width:int=None, height:int=None, filename=None):
+       """ setup the animation """ 
+
+       if x:
+           self.__x = x
+       if y:
+           self.__y = y
+       if width:
+           self.__width = width
+       if height:
+           self.__height = height  
+       self.__current_frame = 0
+       if frames is not None:
+        self.__frames = frames
+       self.__done = False
+       self.__loop_count = 1
+       if animation_type is not None:
+            self.animation_type = animation_type
+       if filename:
+           self.__filename = filename 
+
+    @property
+    def filename(self):
+        """ Returns the current filename"""
+        return self.__filename
+
+    @filename.setter
+    def filename(self, value):
+        """ Sets the filename """
+        self.__filename = value
+
+    def forward(self):
+        """ progress the current frame """
+        if self.__speed == 'normal':
+            self.__current_frame +=1
+
+        if self.__speed in ['very slow','slow']:
+            if self.__pause > 0:
+                self.__pause -= 1
+            else:
+                self.__current_frame +=1
+                self.__pause = self.__speed_value
+
+        if self.__speed == 'fast':
+            if self.__current_frame < self.frame_count +2:
+                self.__current_frame +=2
+            else:
+                self.__current_frame +=1
+
+    def reverse(self):
+        if self.__speed == 'normal':
+            self.__current_frame -=1
+
+        if self.__speed in ['very slow','slow']:
+            if self.__pause > 0:
+                self.__pause -= 1
+            else:
+                self.__current_frame -=1                
+                self.__pause = self.__speed_value
+
+        if self.__speed == 'fast':
+            if self.__current_frame < self.frame_count +2:
+                self.__current_frame -=2
+            else:
+                self.__current_frame -=1
+    
+    def load(self):
+        """ load the animation files """
+
+        # load the files from disk
+        if not self.__cached:
+            files = listdir()
+            array = []
+            for file in files:
+                if (file.startswith(self.__filename)) and (file.endswith('.pbm')):
+                    array.append(Icon(filename=file, width=self.__width, height=self.__height, x=self.__x, y=self.__y, name=file))
+            self.__frames = array
+            self.__cached = True
+
+    def unload(self):
+        """ free up memory """
+
+        self.__frames = None
+        self.__cached = False
+        gc.collect()
+
+    def animate(self, oled):
+        """ Animates the frames based on the animation type and for the number of times specified """
+
+        cf = self.__current_frame # Current Frame number - used to index the frames array
+        frame = self.__frames[cf]        
+        oled.blit(frame.image, frame.x, frame.y)
+       
+        if self.__animation_type == "loop":
+            # Loop from the first frame to the last, for the number of cycles specificed, and then set done to True
+            self.forward()
+           
+            if self.__current_frame > self.frame_count:
+                self.__current_frame = 0
+                self.__loop_count -=1
+                if self.__loop_count == 0:
+                    self.__done = True
+            
+        if self.__animation_type == "bouncing":
+           
+            # Loop from the first frame to the last, and then back to the first again, then set done to True
+            if self.__bouncing:
+               
+                if self.__current_frame == 0:
+                    if self.__loop_count == 0:
+                        self.__done == True
+                    else:
+                        if self.__loop_count >0:
+                            self.__loop_count -=1
+                            self.forward()
+                            self.__bouncing = False
+                    if self.__loop_count == -1:
+                        # bounce infinately
+                        self.forward()
+                        self.__bouncing = False
+                if (self.__current_frame < self.frame_count) and (self.__current_frame>0):
+                    self.reverse()
+            else:
+                if self.__current_frame == 0:
+                    if self.__loop_count == 0:
+                        self.__done == True
+                    elif self.__loop_count == -1:
+                        # bounce infinatey
+                        self.forward()
+                    else:
+                        self.forward()
+                        self.__loop_count -= 1
+                elif self.__current_frame == self.frame_count:
+                    self.reverse()
+                    self.__bouncing = True
+                else:
+                    self.forward()
+            
+        if self.__animation_type == "default":
+            # loop through from first frame to last, then set done to True
+            
+            if self.__current_frame == self.frame_count:
+                self.__current_frame = 0
+                self.__done = True
+            else:
+                self.forward()
+   
+    @property
+    def frame_count(self):
+        """ Returns the total number of frames in the animation """
+        return len(self.__frames)-1
+    
+    @property
+    def done(self):
+        """ Has the animation completed """
+        if self.__done:
+            self.__done = False
+            return True
+        else:
+            return False
+
+    def loop(self, no:int=None):
+        """ Loops the animation
+        if no is None or -1 the animation will continue looping until animate.stop() is called """
+
+        if no is not None:
+            self.__loop_count = no
+        else:
+            self.__loop_count = -1
+        self.__animation_type = "loop"
+
+    def stop(self):
+        self.__loop_count = 0
+        self.__bouncing = False
+        self.__done = True
+
+    def bounce(self, no:int=None):
+        """ Loops the animation forwared, then backward, the number of time specified in no,
+         if there is no number provided it will animate infinately """
+
+        self.__animation_type = "bouncing"
+        if no is not None:
+            self.__loop_count = no
+        else:
+            self.__loop_count = -1
+
+    @property
+    def width(self):
+        """ Gets the icon width """
+        return self.__width
+    
+    @width.setter
+    def width(self, value):
+        """ Sets the icon width """
+        self.__width = value
+    
+    @property
+    def height(self):
+        """ Gets the icon height """
+        return self.__width
+    
+    @height.setter
+    def height(self, value):
+        """ Sets the icon height """
+        self.__height = value
+
+
+class Button():
+    """ Models a button, check the status with is_pressed """
+
+    # The private variables
+    __pressed = False
+    __pin = 0
+    __button_down = False
+
+    def __init__(self, pin:int):
+        """ Sets up the button """
+
+        self.__pin = Pin(pin, Pin.IN, Pin.PULL_DOWN)
+        self.__pressed = False
+
+    @property
+    def is_pressed(self)->bool:
+        """ Returns the current state of the button """
+
+        if self.__pin.value() == 0:
+            self.__button_down = False
+            return False
+        if self.__pin.value() == 1:
+            if not self.__button_down:
+                # print("button pressed")
+                self.__button_down = True
+                return True
+            else:
+                return False
+
+class Event():
+    """ Models events that can happen, with timers and pop up messages """
+    __name = ""
+    __value = 0
+    __sprite = None
+    __timer = -1 # -1 means no timer set
+    __timer_ms = 0
+    __callback = None
+    __message = ""
+
+    def __init__(self, name=None, sprite=None, value=None, callback=None):
+        """ Create a new event """
+
+        if name:
+            self.__name = name
+        if sprite:
+            self.__sprite = sprite
+        if value:
+            self.__value = value
+        if callback is not None:
+            self.__callback = callback
+    
+
+    @property
+    def name(self):
+        """ Return the name of the event"""
+
+        return self.__name
+
+
+    @name.setter
+    def name(self, value):
+        """ Set the name of the Event"""
+
+        self.__name = value
+
+
+    @property
+    def value(self):
+        """ Gets the current value """
+        return self.__value
+
+
+    @value.setter
+    def value(self, value):
+        """ Sets the current value """
+        self.__value = value
+
+
+    @property
+    def sprite(self):
+        """ Gets the image sprite """
+
+        return self.__sprite
+
+
+    @sprite.setter
+    def sprite(self, value):
+        """ Sets the image sprite """
+
+        self.__value = value
+
+
+    @property
+    def message(self):
+        """ Return the message """
+
+        return self.__message
+    
+
+    @message.setter
+    def message(self, value):
+        """ Set the message """
+        self.__message = value
+
+    def popup(self, oled):
+        # display popup window
+        # show sprite
+        # show message
+
+        fbuf = framebuf.FrameBuffer(bytearray(128 * 48 * 1), 128, 48, framebuf.MONO_HLSB)
+        fbuf.rect(0,0,128,48, 1)
+        fbuf.blit(self.sprite.image, 5, 10)
+        fbuf.text(self.message, 32, 18)
+        oled.blit(fbuf, 0, 16)
+        oled.show()
+        sleep(2)
+    
+    @property
+    def timer(self):
+        """ Gets the current timer value """
+
+        return self.__timer
+
+
+    @timer.setter
+    def timer(self, value):
+        """ Sets the current timer value """
+
+        self.__timer = value
+
+
+    @property
+    def timer_ms(self):
+        """ Get the timer in MS """
+
+        return self.__timer_ms
+
+
+    @timer_ms.setter
+    def timer_ms(self, value):
+        """ Set the timer in MS """
+        self.__timer_ms = value
+
+
+    def tick(self):
+        """ Progresses the animation on frame """
+
+        self.__timer_ms += 1
+        if self.__timer_ms >= self.__timer:
+            if self.__callback is not None:
+                print("poop check callback")
+                self.__callback
+                self.__timer = -1
+                self.__timer_ms = 0
+            else:
+                # print("Timer Alert!")
+                pass
+
diff --git a/lib/sdcard.py b/lib/sdcard.py
new file mode 100644 (file)
index 0000000..cea5845
--- /dev/null
@@ -0,0 +1,309 @@
+"""
+MicroPython driver for SD cards using SPI bus.
+
+Requires an SPI bus and a CS pin.  Provides readblocks and writeblocks
+methods so the device can be mounted as a filesystem.
+
+Example usage on pyboard:
+
+    import pyb, sdcard, os
+    sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
+    pyb.mount(sd, '/sd2')
+    os.listdir('/')
+
+Example usage on ESP8266:
+
+    import machine, sdcard, os
+    sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15))
+    os.mount(sd, '/sd')
+    os.listdir('/')
+
+"""
+
+from micropython import const
+import time
+
+
+_CMD_TIMEOUT = const(100)
+
+_R1_IDLE_STATE = const(1 << 0)
+# R1_ERASE_RESET = const(1 << 1)
+_R1_ILLEGAL_COMMAND = const(1 << 2)
+# R1_COM_CRC_ERROR = const(1 << 3)
+# R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
+# R1_ADDRESS_ERROR = const(1 << 5)
+# R1_PARAMETER_ERROR = const(1 << 6)
+_TOKEN_CMD25 = const(0xFC)
+_TOKEN_STOP_TRAN = const(0xFD)
+_TOKEN_DATA = const(0xFE)
+
+
+class SDCard:
+    def __init__(self, spi, cs, baudrate=1320000):
+        self.spi = spi
+        self.cs = cs
+
+        self.cmdbuf = bytearray(6)
+        self.dummybuf = bytearray(512)
+        self.tokenbuf = bytearray(1)
+        for i in range(512):
+            self.dummybuf[i] = 0xFF
+        self.dummybuf_memoryview = memoryview(self.dummybuf)
+
+        # initialise the card
+        self.init_card(baudrate)
+
+    def init_spi(self, baudrate):
+        try:
+            master = self.spi.MASTER
+        except AttributeError:
+            # on ESP8266
+            self.spi.init(baudrate=baudrate, phase=0, polarity=0)
+        else:
+            # on pyboard
+            self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
+
+    def init_card(self, baudrate):
+        # init CS pin
+        self.cs.init(self.cs.OUT, value=1)
+
+        # init SPI bus; use low data rate for initialisation
+        self.init_spi(100000)
+
+        # clock card at least 100 cycles with cs high
+        for i in range(16):
+            self.spi.write(b"\xff")
+
+        # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
+        for _ in range(5):
+            if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
+                break
+        else:
+            raise OSError("no SD card")
+
+        # CMD8: determine card version
+        r = self.cmd(8, 0x01AA, 0x87, 4)
+        if r == _R1_IDLE_STATE:
+            self.init_card_v2()
+        elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
+            self.init_card_v1()
+        else:
+            raise OSError("couldn't determine SD card version")
+
+        # get the number of sectors
+        # CMD9: response R2 (R1 byte + 16-byte block read)
+        if self.cmd(9, 0, 0, 0, False) != 0:
+            raise OSError("no response from SD card")
+        csd = bytearray(16)
+        self.readinto(csd)
+        if csd[0] & 0xC0 == 0x40:  # CSD version 2.0
+            self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
+        elif csd[0] & 0xC0 == 0x00:  # CSD version 1.0 (old, <=2GB)
+            c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6
+            c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
+            read_bl_len = csd[5] & 0b1111
+            capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
+            self.sectors = capacity // 512
+        else:
+            raise OSError("SD card CSD format not supported")
+        # print('sectors', self.sectors)
+
+        # CMD16: set block length to 512 bytes
+        if self.cmd(16, 512, 0) != 0:
+            raise OSError("can't set 512 block size")
+
+        # set to high data rate now that it's initialised
+        self.init_spi(baudrate)
+
+    def init_card_v1(self):
+        for i in range(_CMD_TIMEOUT):
+            time.sleep_ms(50)
+            self.cmd(55, 0, 0)
+            if self.cmd(41, 0, 0) == 0:
+                # SDSC card, uses byte addressing in read/write/erase commands
+                self.cdv = 512
+                # print("[SDCard] v1 card")
+                return
+        raise OSError("timeout waiting for v1 card")
+
+    def init_card_v2(self):
+        for i in range(_CMD_TIMEOUT):
+            time.sleep_ms(50)
+            self.cmd(58, 0, 0, 4)
+            self.cmd(55, 0, 0)
+            if self.cmd(41, 0x40000000, 0) == 0:
+                self.cmd(58, 0, 0, -4)  # 4-byte response, negative means keep the first byte
+                ocr = self.tokenbuf[0]  # get first byte of response, which is OCR
+                if not ocr & 0x40:
+                    # SDSC card, uses byte addressing in read/write/erase commands
+                    self.cdv = 512
+                else:
+                    # SDHC/SDXC card, uses block addressing in read/write/erase commands
+                    self.cdv = 1
+                # print("[SDCard] v2 card")
+                return
+        raise OSError("timeout waiting for v2 card")
+
+    def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
+        self.cs(0)
+
+        # create and send the command
+        buf = self.cmdbuf
+        buf[0] = 0x40 | cmd
+        buf[1] = arg >> 24
+        buf[2] = arg >> 16
+        buf[3] = arg >> 8
+        buf[4] = arg
+        buf[5] = crc
+        self.spi.write(buf)
+
+        if skip1:
+            self.spi.readinto(self.tokenbuf, 0xFF)
+
+        # wait for the response (response[7] == 0)
+        for i in range(_CMD_TIMEOUT):
+            self.spi.readinto(self.tokenbuf, 0xFF)
+            response = self.tokenbuf[0]
+            if not (response & 0x80):
+                # this could be a big-endian integer that we are getting here
+                # if final<0 then store the first byte to tokenbuf and discard the rest
+                if final < 0:
+                    self.spi.readinto(self.tokenbuf, 0xFF)
+                    final = -1 - final
+                for j in range(final):
+                    self.spi.write(b"\xff")
+                if release:
+                    self.cs(1)
+                    self.spi.write(b"\xff")
+                return response
+
+        # timeout
+        self.cs(1)
+        self.spi.write(b"\xff")
+        return -1
+
+    def readinto(self, buf):
+        self.cs(0)
+
+        # read until start byte (0xff)
+        for i in range(_CMD_TIMEOUT):
+            self.spi.readinto(self.tokenbuf, 0xFF)
+            if self.tokenbuf[0] == _TOKEN_DATA:
+                break
+            time.sleep_ms(1)
+        else:
+            self.cs(1)
+            raise OSError("timeout waiting for response")
+
+        # read data
+        mv = self.dummybuf_memoryview
+        if len(buf) != len(mv):
+            mv = mv[: len(buf)]
+        self.spi.write_readinto(mv, buf)
+
+        # read checksum
+        self.spi.write(b"\xff")
+        self.spi.write(b"\xff")
+
+        self.cs(1)
+        self.spi.write(b"\xff")
+
+    def write(self, token, buf):
+        self.cs(0)
+
+        # send: start of block, data, checksum
+        self.spi.read(1, token)
+        self.spi.write(buf)
+        self.spi.write(b"\xff")
+        self.spi.write(b"\xff")
+
+        # check the response
+        if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
+            self.cs(1)
+            self.spi.write(b"\xff")
+            return
+
+        # wait for write to finish
+        while self.spi.read(1, 0xFF)[0] == 0:
+            pass
+
+        self.cs(1)
+        self.spi.write(b"\xff")
+
+    def write_token(self, token):
+        self.cs(0)
+        self.spi.read(1, token)
+        self.spi.write(b"\xff")
+        # wait for write to finish
+        while self.spi.read(1, 0xFF)[0] == 0x00:
+            pass
+
+        self.cs(1)
+        self.spi.write(b"\xff")
+
+    def readblocks(self, block_num, buf):
+        # workaround for shared bus, required for (at least) some Kingston
+        # devices, ensure MOSI is high before starting transaction
+        self.spi.write(b"\xff")
+
+        nblocks = len(buf) // 512
+        assert nblocks and not len(buf) % 512, "Buffer length is invalid"
+        if nblocks == 1:
+            # CMD17: set read address for single block
+            if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
+                # release the card
+                self.cs(1)
+                raise OSError(5)  # EIO
+            # receive the data and release card
+            self.readinto(buf)
+        else:
+            # CMD18: set read address for multiple blocks
+            if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
+                # release the card
+                self.cs(1)
+                raise OSError(5)  # EIO
+            offset = 0
+            mv = memoryview(buf)
+            while nblocks:
+                # receive the data and release card
+                self.readinto(mv[offset : offset + 512])
+                offset += 512
+                nblocks -= 1
+            if self.cmd(12, 0, 0xFF, skip1=True):
+                raise OSError(5)  # EIO
+
+    def writeblocks(self, block_num, buf):
+        # workaround for shared bus, required for (at least) some Kingston
+        # devices, ensure MOSI is high before starting transaction
+        self.spi.write(b"\xff")
+
+        nblocks, err = divmod(len(buf), 512)
+        assert nblocks and not err, "Buffer length is invalid"
+        if nblocks == 1:
+            # CMD24: set write address for single block
+            if self.cmd(24, block_num * self.cdv, 0) != 0:
+                raise OSError(5)  # EIO
+
+            # send the data
+            self.write(_TOKEN_DATA, buf)
+        else:
+            # CMD25: set write address for first block
+            if self.cmd(25, block_num * self.cdv, 0) != 0:
+                raise OSError(5)  # EIO
+            # send the data
+            offset = 0
+            mv = memoryview(buf)
+            while nblocks:
+                self.write(_TOKEN_CMD25, mv[offset : offset + 512])
+                offset += 512
+                nblocks -= 1
+            self.write_token(_TOKEN_STOP_TRAN)
+
+    def ioctl(self, op, arg):
+        if op == 4:  # get number of blocks
+            return self.sectors
+        if op == 5:  # get block size in bytes
+            return 512
+
+
+__version__ = '0.1.0'
diff --git a/lightbulb.pbm b/lightbulb.pbm
new file mode 100644 (file)
index 0000000..91cdea7
Binary files /dev/null and b/lightbulb.pbm differ
diff --git a/main.py b/main.py
new file mode 100644 (file)
index 0000000..98d469b
--- /dev/null
+++ b/main.py
@@ -0,0 +1,270 @@
+# from icons import food_icon
+from machine import I2C, Pin
+from ssd1306 import SSD1306_I2C
+from icon import Animate, Icon, Toolbar, Button, Event
+from time import sleep
+from sys import exit
+import framebuf
+import gc
+
+sda = Pin(0)
+scl = Pin(1)
+id = 0
+
+i2c = I2C(id=id, sda=sda, scl=scl)
+
+oled = SSD1306_I2C(width=128, height=64, i2c=i2c)
+oled.init_display()
+
+health = 2
+happiness = 1
+energy = 1
+
+# load icons
+food = Icon('food.pbm', width=16, height=16, name="food")
+lightbulb = Icon('lightbulb.pbm', width=16, height=16, name="lightbulb")
+game = Icon('game.pbm', width=16, height=16, name="game")
+firstaid = Icon('firstaid.pbm', width=16, height=16, name="firstaid")
+toilet = Icon('toilet.pbm', width=16, height=16, name="toilet")
+heart = Icon('heart.pbm', width=16, height=16, name="heart")
+call = Icon('call.pbm', width=16, height=16, name="call")
+save = Icon('disc.pbm', width=16, height=16, name="toilet")
+
+def clear():
+    """ Clear the screen """
+    oled.fill_rect(0,0,128,64,0)
+
+# def animate(frames, timer):
+#     for frame in frames:
+#         oled.blit(frame.image, frame.x, frame.y)
+#         oled.show()
+#         sleep(0.1)
+
+def build_toolbar():
+    toolbar = Toolbar()
+    toolbar.spacer = 2
+    toolbar.additem(food)    
+    toolbar.additem(lightbulb)
+    toolbar.additem(game)
+    toolbar.additem(firstaid)
+    toolbar.additem(toilet)
+    toolbar.additem(heart)
+    toolbar.additem(call)
+    toolbar.additem(save)
+    return toolbar
+
+tb = build_toolbar()
+poopy = Animate(x=96,y=48, width=16, height=16, filename='poop')
+baby = Animate(x=48,y=16, width=48, height=48, filename='baby_bounce', animation_type='bounce')
+eat = Animate(x=48,y=16, width=48, height=48, filename='eab: 20t')
+babyzzz = Animate(animation_type="loop", x=48,y=16, width=48, height=48, filename='baby_zzz')
+death = Animate(animation_type='bounce', x=40,y=16, width=16, height=16, filename="skull")
+go_potty = Animate(filename="potty", animation_type='bounce',x=64,y=16, width=48, height=48)
+call_animate = Animate(filename='call_animate', width=16, height=16, x=108, y=0)
+call_animate.speed = 'very slow'
+
+#button_jleft = Button(20)
+#button_jright = Button(19)
+#button_jup = Button(22)
+#button_jdown = Button(21)
+#button_jmid = Button(18)
+#button_jset = Button(17)
+#button_jrst = Button(16)
+
+class ButtonConfig:
+    Configurations = {
+                            "default":{
+                                        "left":20,
+                                        "right":19,
+                                        "action":18,
+                                        "cancel":16
+                                        },
+                            "set1":{
+                                        "left":20,
+                                        "right":19,
+                                        "action":18
+                                    }
+    }
+    __ActiveConfig={}
+    
+    def __init__(self, set="default"):
+        self.__ActiveConfig=self.Configurations[set]
+    
+    @property
+    def ActiveConfig(self):
+        return self.__ActiveConfig
+        
+
+class controller:
+    PinObjects={}
+    
+    def __init__(self,config):
+        for button in config.ActiveConfig:
+            self.PinObjects[button]=Pin(config.ActiveConfig[button])
+            
+ButtonSetup=ButtonConfig()           
+InputDevice=controller(ButtonSetup)
+
+index = 3
+tb.select(index, oled)
+cancel = False
+feeding_time = False
+sleeping = False
+death.set = True
+
+# Set up Events
+energy_increase = Event(name="Increase Energy", sprite=heart, value=1)
+firstaid = Event(name="First Aid", sprite=firstaid, value=0)
+toilet = Event(name="Toilet", sprite=toilet, value=0)
+greatgame = Event(name="Gaming", sprite=game, value=0)
+# poop_event = Event(name="poop time", sprite=poop_sprite, callback=poop_check())
+sleep_time = Event(name="sleep time", sprite=lightbulb, value=1)
+heart_status = Event(name="Status", sprite=heart)
+# poop_event.timer = 3
+# poop_event.timer_ms = 1
+
+baby.bounce()
+poopy.bounce()
+death.loop(no=-1)
+death.speed='slow'
+babyzzz.speed = 'very slow'
+go_potty.loop(no=1)
+go_potty.set = True
+poopy.set = False
+go_potty.load()
+
+while True:
+    if not cancel:
+        tb.unselect(index, oled)
+    if InputDevice.PinObjects["left"].value():
+        index -= 1
+        if index < 0:
+            index = tb.getlength()-1
+        cancel = False
+    if InputDevice.PinObjects["right"].value():
+        index += 1
+        if index == tb.getlength():
+            index = 0
+        cancel = False
+    if InputDevice.PinObjects["cancel"].value():
+        cancel = True
+        index = -1
+
+    if not cancel:
+        tb.select(index, oled)
+
+    if InputDevice.PinObjects["action"].value():
+        if tb.selected_item == "food":
+            feeding_time = True
+            sleeping = False
+            baby.unload()
+            
+        if tb.selected_item == "game":
+            greatgame.message = "Gaming!!!"
+            greatgame.popup(oled=oled)
+            happiness += 1
+            energy -= 1
+            greatgame.message = "happy = " + str(happiness)
+            greatgame.popup(oled)
+            greatgame.message = "energy = " + str(energy)
+            greatgame.popup(oled)
+            clear()
+            print("game:\n energy = " + str(energy)+"\n happy = " + str(happiness))
+        if tb.selected_item == "toilet":
+            toilet.message = "Cleaning..."
+            toilet.popup(oled=oled)
+            poopy.set = False
+            baby.set = True
+            happiness += 1
+            clear()
+            poopy.unload()
+        if tb.selected_item == "lightbulb":
+            if not sleeping:
+                sleeping = True
+                babyzzz.load()
+                sleep_time.message = "Night Night"
+                sleep_time.popup(oled)
+                clear()
+                # need to add an event that increases energy level after sleeping for 1 minute
+            else:
+                sleeping = False
+                babyzzz.unload()
+            print("lightbulb")
+        if tb.selected_item == "firstaid":
+            firstaid.message = "Vitamins"
+            firstaid.popup(oled=oled)
+            health += 1
+
+            clear()
+        if tb.selected_item == "heart":
+            heart_status.message = "health = " + str(health)
+            heart_status.popup(oled)
+            heart_status.message = "happy = " + str(happiness)
+            heart_status.popup(oled)
+            heart_status.message = "energy = " + str(energy)
+            heart_status.popup(oled)
+            clear()
+        if tb.selected_item == "call":
+        #    call_animate.animate(oled)
+        #    call_animate.set = False
+            print("call")
+
+    # Time for Poop?
+    # poop_check()
+    # poop_event.tick()
+
+    if feeding_time:
+        eat.load()
+        if not eat.done:
+            eat.animate(oled)
+        if feeding_time and eat.done:
+            feeding_time = False
+            energy_increase.message = "ENERGY + 1"
+            energy_increase.popup(oled=oled)
+            energy += 1
+            
+            clear()
+            eat.unload()
+            baby.load()
+    else:
+        if sleeping:
+            babyzzz.animate(oled)
+        else:
+            if baby.set:
+                baby.load()
+                baby.animate(oled)
+            if go_potty.set:
+                go_potty.animate(oled)
+            if go_potty.done:
+                print("potty done")
+                go_potty.set = False
+                poopy.set = True
+                baby.load()
+                baby.bounce(no=-1)
+                baby.set = True
+    if (energy <= 1) and (happiness <= 1) and (health <=1):
+        death.set = True
+    else:
+        death.set = False
+
+    #if (energy <= 1) or (happiness <= 1) or (health <= 1):
+        # set the toolbar call icon to flash
+    #    call_animate.set = True
+    #else:
+    #    call_animate.set = False
+
+    if poopy.set:
+        poopy.load()
+        poopy.animate(oled)
+    if death.set:
+        death.animate(oled)
+    tb.show(oled)  
+    if index == 6:
+        tb.select(index, oled)
+    #else:
+    #   if call_animate.set:
+    #      call_animate.animate(oled)        
+         
+    oled.show()
+    sleep(0.05)
+    
\ No newline at end of file
diff --git a/poop01.pbm b/poop01.pbm
new file mode 100644 (file)
index 0000000..a97abc9
Binary files /dev/null and b/poop01.pbm differ
diff --git a/poop02.pbm b/poop02.pbm
new file mode 100644 (file)
index 0000000..884be48
Binary files /dev/null and b/poop02.pbm differ
diff --git a/poop03.pbm b/poop03.pbm
new file mode 100644 (file)
index 0000000..a9b9b83
Binary files /dev/null and b/poop03.pbm differ
diff --git a/poop04.pbm b/poop04.pbm
new file mode 100644 (file)
index 0000000..532164d
Binary files /dev/null and b/poop04.pbm differ
diff --git a/potty01.pbm b/potty01.pbm
new file mode 100644 (file)
index 0000000..0b78bcb
Binary files /dev/null and b/potty01.pbm differ
diff --git a/potty02.pbm b/potty02.pbm
new file mode 100644 (file)
index 0000000..29e3843
Binary files /dev/null and b/potty02.pbm differ
diff --git a/potty03.pbm b/potty03.pbm
new file mode 100644 (file)
index 0000000..fd50091
Binary files /dev/null and b/potty03.pbm differ
diff --git a/potty04.pbm b/potty04.pbm
new file mode 100644 (file)
index 0000000..22df073
Binary files /dev/null and b/potty04.pbm differ
diff --git a/potty05.pbm b/potty05.pbm
new file mode 100644 (file)
index 0000000..0c7ea60
Binary files /dev/null and b/potty05.pbm differ
diff --git a/potty06.pbm b/potty06.pbm
new file mode 100644 (file)
index 0000000..a0401d4
Binary files /dev/null and b/potty06.pbm differ
diff --git a/potty07.pbm b/potty07.pbm
new file mode 100644 (file)
index 0000000..ef073fb
Binary files /dev/null and b/potty07.pbm differ
diff --git a/potty08.pbm b/potty08.pbm
new file mode 100644 (file)
index 0000000..17b090d
Binary files /dev/null and b/potty08.pbm differ
diff --git a/potty09.pbm b/potty09.pbm
new file mode 100644 (file)
index 0000000..c1e47f4
Binary files /dev/null and b/potty09.pbm differ
diff --git a/potty10.pbm b/potty10.pbm
new file mode 100644 (file)
index 0000000..d3e706c
Binary files /dev/null and b/potty10.pbm differ
diff --git a/potty11.pbm b/potty11.pbm
new file mode 100644 (file)
index 0000000..499d2ce
Binary files /dev/null and b/potty11.pbm differ
diff --git a/potty12.pbm b/potty12.pbm
new file mode 100644 (file)
index 0000000..02f5af3
Binary files /dev/null and b/potty12.pbm differ
diff --git a/potty13.pbm b/potty13.pbm
new file mode 100644 (file)
index 0000000..2f9da33
Binary files /dev/null and b/potty13.pbm differ
diff --git a/potty14.pbm b/potty14.pbm
new file mode 100644 (file)
index 0000000..ccb7c91
Binary files /dev/null and b/potty14.pbm differ
diff --git a/raw_assets/baby_zzz01.xcf b/raw_assets/baby_zzz01.xcf
new file mode 100644 (file)
index 0000000..f5106d2
Binary files /dev/null and b/raw_assets/baby_zzz01.xcf differ
diff --git a/raw_assets/baby_zzz02.xcf b/raw_assets/baby_zzz02.xcf
new file mode 100644 (file)
index 0000000..a8904a6
Binary files /dev/null and b/raw_assets/baby_zzz02.xcf differ
diff --git a/raw_assets/baby_zzz03.xcf b/raw_assets/baby_zzz03.xcf
new file mode 100644 (file)
index 0000000..d68080e
Binary files /dev/null and b/raw_assets/baby_zzz03.xcf differ
diff --git a/raw_assets/baby_zzz04.xcf b/raw_assets/baby_zzz04.xcf
new file mode 100644 (file)
index 0000000..cc44139
Binary files /dev/null and b/raw_assets/baby_zzz04.xcf differ
diff --git a/raw_assets/baby_zzz05.xcf b/raw_assets/baby_zzz05.xcf
new file mode 100644 (file)
index 0000000..154b80d
Binary files /dev/null and b/raw_assets/baby_zzz05.xcf differ
diff --git a/raw_assets/bubble.xcf b/raw_assets/bubble.xcf
new file mode 100644 (file)
index 0000000..13fa5e9
Binary files /dev/null and b/raw_assets/bubble.xcf differ
diff --git a/raw_assets/call_animate01.xcf b/raw_assets/call_animate01.xcf
new file mode 100644 (file)
index 0000000..13dec51
Binary files /dev/null and b/raw_assets/call_animate01.xcf differ
diff --git a/raw_assets/call_animate02.xcf b/raw_assets/call_animate02.xcf
new file mode 100644 (file)
index 0000000..8e93c11
Binary files /dev/null and b/raw_assets/call_animate02.xcf differ
diff --git a/raw_assets/call_animate03.xcf b/raw_assets/call_animate03.xcf
new file mode 100644 (file)
index 0000000..4aa82e1
Binary files /dev/null and b/raw_assets/call_animate03.xcf differ
diff --git a/raw_assets/potty01.xcf b/raw_assets/potty01.xcf
new file mode 100644 (file)
index 0000000..60c4227
Binary files /dev/null and b/raw_assets/potty01.xcf differ
diff --git a/raw_assets/potty02.xcf b/raw_assets/potty02.xcf
new file mode 100644 (file)
index 0000000..e22286f
Binary files /dev/null and b/raw_assets/potty02.xcf differ
diff --git a/raw_assets/potty03.xcf b/raw_assets/potty03.xcf
new file mode 100644 (file)
index 0000000..804bbeb
Binary files /dev/null and b/raw_assets/potty03.xcf differ
diff --git a/raw_assets/potty04.xcf b/raw_assets/potty04.xcf
new file mode 100644 (file)
index 0000000..ddebf73
Binary files /dev/null and b/raw_assets/potty04.xcf differ
diff --git a/raw_assets/potty05.xcf b/raw_assets/potty05.xcf
new file mode 100644 (file)
index 0000000..f1ac2ba
Binary files /dev/null and b/raw_assets/potty05.xcf differ
diff --git a/raw_assets/potty06.xcf b/raw_assets/potty06.xcf
new file mode 100644 (file)
index 0000000..b904a0c
Binary files /dev/null and b/raw_assets/potty06.xcf differ
diff --git a/raw_assets/potty07.xcf b/raw_assets/potty07.xcf
new file mode 100644 (file)
index 0000000..eacb424
Binary files /dev/null and b/raw_assets/potty07.xcf differ
diff --git a/raw_assets/potty08.xcf b/raw_assets/potty08.xcf
new file mode 100644 (file)
index 0000000..5f7ffff
Binary files /dev/null and b/raw_assets/potty08.xcf differ
diff --git a/raw_assets/potty09.xcf b/raw_assets/potty09.xcf
new file mode 100644 (file)
index 0000000..6317d4e
Binary files /dev/null and b/raw_assets/potty09.xcf differ
diff --git a/raw_assets/potty10.xcf b/raw_assets/potty10.xcf
new file mode 100644 (file)
index 0000000..b0cabf5
Binary files /dev/null and b/raw_assets/potty10.xcf differ
diff --git a/raw_assets/potty11.xcf b/raw_assets/potty11.xcf
new file mode 100644 (file)
index 0000000..56cc6ed
Binary files /dev/null and b/raw_assets/potty11.xcf differ
diff --git a/raw_assets/potty12.xcf b/raw_assets/potty12.xcf
new file mode 100644 (file)
index 0000000..671a59b
Binary files /dev/null and b/raw_assets/potty12.xcf differ
diff --git a/raw_assets/skull01.xcf b/raw_assets/skull01.xcf
new file mode 100644 (file)
index 0000000..a9595cc
Binary files /dev/null and b/raw_assets/skull01.xcf differ
diff --git a/raw_assets/skull02.xcf b/raw_assets/skull02.xcf
new file mode 100644 (file)
index 0000000..9e3a7c2
Binary files /dev/null and b/raw_assets/skull02.xcf differ
diff --git a/sdcardtest.py b/sdcardtest.py
new file mode 100644 (file)
index 0000000..6729547
--- /dev/null
@@ -0,0 +1,104 @@
+import machine\r
+import sdcard\r
+import uos\r
+import json\r
+\r
+mytestdata = {\r
+                "health":11,\r
+                "happiness":1,\r
+                "energy":1\r
+            }\r
+\r
+# Create a file and write something to it\r
+#with open("/sd/test01.txt", "w") as file:\r
+#    file.write(json.dumps(mytestdata))\r
+\r
+# Open the file we just created and read from it\r
+#with open("/sd/test01.txt", "r") as file:\r
+#    data = file.read()\r
+#    print(data)\r
+#    varx =json.loads(data)\r
+#    print(varx["health"])\r
+    \r
+class SaveGameManager:\r
+    __SaveGameData = {}\r
+    __FileSocket = None\r
+    __cs = None\r
+    __spi = None\r
+    __sd = None\r
+    \r
+    def __init__(self, savename="01"):\r
+        print("initializing")\r
+        try:\r
+            # Assign chip select (CS) pin (and start it high)\r
+            self.__cs = machine.Pin(9, machine.Pin.OUT)\r
+\r
+            # Intialize SPI peripheral (start with 1 MHz)\r
+            self.__spi = machine.SPI(1,\r
+                              baudrate=1000000,\r
+                              polarity=0,\r
+                              phase=0,\r
+                              bits=8,\r
+                              firstbit=machine.SPI.MSB,\r
+                              sck=machine.Pin(10),\r
+                              mosi=machine.Pin(11),\r
+                              miso=machine.Pin(8))\r
+\r
+            # Initialize SD card\r
+            self.__sd = sdcard.SDCard(self.__spi, self.__cs)\r
+\r
+            # Mount filesystem\r
+            self.__FileSocket = uos.VfsFat(self.__sd)\r
+            uos.mount(self.__FileSocket, "/sd")\r
+            \r
+            #load values from FS\r
+            self.LoadSaveData()\r
+        except:\r
+            pass\r
+\r
+        \r
+            \r
+    @property\r
+    def CheckFilesystemReady(self):\r
+        if self.__FileSocket is None:\r
+            print("No FileSocket")\r
+            return False\r
+        return True    \r
+\r
+    def LoadSaveData(self):\r
+        print("loading")\r
+        # Open the file we just created and read from it\r
+        if not self.CheckFilesystemReady:\r
+            return # If we have no filesystem we cannot write or read anyways...\r
+        \r
+        with open("/sd/test00.txt", "rb") as file:\r
+            file.read(1)       #ignore first byte, it containes the version number as binary... later :)\r
+            data = file.read()\r
+            self.__SaveGameData = json.loads(data)\r
+        \r
+    def WriteSaveData(self):\r
+        if not self.CheckFilesystemReady:\r
+            pass # If we have no filesystem we cannot write or read anyways...\r
+        # Create a file and write something to it\r
+        with open("/sd/test01.txt", "wb") as file:\r
+            file.write("0")\r
+            file.write(json.dumps(self.__SaveGameData))\r
+            \r
+    def UpdateData(self, key, value):\r
+        print("updating internal data")\r
+        self.__SaveGameData[key]=value\r
+        \r
+    def GetData(self, key, defaultvalue=""):\r
+        print("getting internaldata")\r
+        if key in self.__SaveGameData:\r
+            return self.__SaveGameData \r
+        return defaultvalue\r
+    \r
+    \r
+mysavegame = SaveGameManager()\r
+mysavegame.UpdateData("bla","blub")\r
+mysavegame.WriteSaveData()\r
+mysavegame.LoadSaveData()\r
+print(mysavegame.GetData("bla"))\r
+print("x:"+mysavegame.GetData("something"))\r
+print("x:"+mysavegame.GetData("something","defaultthing"))
\ No newline at end of file
diff --git a/skull01.pbm b/skull01.pbm
new file mode 100644 (file)
index 0000000..b860ad3
--- /dev/null
@@ -0,0 +1,4 @@
+P4
+# Created by GIMP version 2.10.22 PNM plug-in
+16 16
+\ fð?ü\7fþÿÿÿÿÿÿá\87Á\83ÃÃÿÿþ\7fþ\7f\7fþ?ü\r°\r°
\ No newline at end of file
diff --git a/skull02.pbm b/skull02.pbm
new file mode 100644 (file)
index 0000000..219ddb7
--- /dev/null
@@ -0,0 +1,4 @@
+P4
+# Created by GIMP version 2.10.22 PNM plug-in
+16 16
+\ fð?ü\7fþÿÿÿÿÿÿÿÿÿÿÿÿÿÿþ\7fþ\7f\7fþ?ü\r°\r°
\ No newline at end of file
diff --git a/ssd1306.py b/ssd1306.py
new file mode 100644 (file)
index 0000000..1bb6679
--- /dev/null
@@ -0,0 +1,155 @@
+# MicroPython SSD1306 OLED driver, I2C and SPI interfaces\r
+\r
+from micropython import const\r
+import framebuf\r
+\r
+\r
+# register definitions\r
+SET_CONTRAST = const(0x81)\r
+SET_ENTIRE_ON = const(0xA4)\r
+SET_NORM_INV = const(0xA6)\r
+SET_DISP = const(0xAE)\r
+SET_MEM_ADDR = const(0x20)\r
+SET_COL_ADDR = const(0x21)\r
+SET_PAGE_ADDR = const(0x22)\r
+SET_DISP_START_LINE = const(0x40)\r
+SET_SEG_REMAP = const(0xA0)\r
+SET_MUX_RATIO = const(0xA8)\r
+SET_COM_OUT_DIR = const(0xC0)\r
+SET_DISP_OFFSET = const(0xD3)\r
+SET_COM_PIN_CFG = const(0xDA)\r
+SET_DISP_CLK_DIV = const(0xD5)\r
+SET_PRECHARGE = const(0xD9)\r
+SET_VCOM_DESEL = const(0xDB)\r
+SET_CHARGE_PUMP = const(0x8D)\r
+\r
+# Subclassing FrameBuffer provides support for graphics primitives\r
+# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html\r
+class SSD1306(framebuf.FrameBuffer):\r
+    def __init__(self, width, height, external_vcc):\r
+        self.width = width\r
+        self.height = height\r
+        self.external_vcc = external_vcc\r
+        self.pages = self.height // 8\r
+        self.buffer = bytearray(self.pages * self.width)\r
+        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)\r
+        self.init_display()\r
+\r
+    def init_display(self):\r
+        for cmd in (\r
+            SET_DISP | 0x00,  # off\r
+            # address setting\r
+            SET_MEM_ADDR,\r
+            0x00,  # horizontal\r
+            # resolution and layout\r
+            SET_DISP_START_LINE | 0x00,\r
+            SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0\r
+            SET_MUX_RATIO,\r
+            self.height - 1,\r
+            SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0\r
+            SET_DISP_OFFSET,\r
+            0x00,\r
+            SET_COM_PIN_CFG,\r
+            0x02 if self.width > 2 * self.height else 0x12,\r
+            # timing and driving scheme\r
+            SET_DISP_CLK_DIV,\r
+            0x80,\r
+            SET_PRECHARGE,\r
+            0x22 if self.external_vcc else 0xF1,\r
+            SET_VCOM_DESEL,\r
+            0x30,  # 0.83*Vcc\r
+            # display\r
+            SET_CONTRAST,\r
+            0xFF,  # maximum\r
+            SET_ENTIRE_ON,  # output follows RAM contents\r
+            SET_NORM_INV,  # not inverted\r
+            # charge pump\r
+            SET_CHARGE_PUMP,\r
+            0x10 if self.external_vcc else 0x14,\r
+            SET_DISP | 0x01,\r
+        ):  # on\r
+            self.write_cmd(cmd)\r
+        self.fill(0)\r
+        self.show()\r
+\r
+    def poweroff(self):\r
+        self.write_cmd(SET_DISP | 0x00)\r
+\r
+    def poweron(self):\r
+        self.write_cmd(SET_DISP | 0x01)\r
+\r
+    def contrast(self, contrast):\r
+        self.write_cmd(SET_CONTRAST)\r
+        self.write_cmd(contrast)\r
+\r
+    def invert(self, invert):\r
+        self.write_cmd(SET_NORM_INV | (invert & 1))\r
+\r
+    def show(self):\r
+        x0 = 0\r
+        x1 = self.width - 1\r
+        if self.width == 64:\r
+            # displays with width of 64 pixels are shifted by 32\r
+            x0 += 32\r
+            x1 += 32\r
+        self.write_cmd(SET_COL_ADDR)\r
+        self.write_cmd(x0)\r
+        self.write_cmd(x1)\r
+        self.write_cmd(SET_PAGE_ADDR)\r
+        self.write_cmd(0)\r
+        self.write_cmd(self.pages - 1)\r
+        self.write_data(self.buffer)\r
+\r
+\r
+class SSD1306_I2C(SSD1306):\r
+    def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):\r
+        self.i2c = i2c\r
+        self.addr = addr\r
+        self.temp = bytearray(2)\r
+        self.write_list = [b"\x40", None]  # Co=0, D/C#=1\r
+        super().__init__(width, height, external_vcc)\r
+\r
+    def write_cmd(self, cmd):\r
+        self.temp[0] = 0x80  # Co=1, D/C#=0\r
+        self.temp[1] = cmd\r
+        self.i2c.writeto(self.addr, self.temp)\r
+\r
+    def write_data(self, buf):\r
+        self.write_list[1] = buf\r
+        self.i2c.writevto(self.addr, self.write_list)\r
+\r
+\r
+class SSD1306_SPI(SSD1306):\r
+    def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):\r
+        self.rate = 10 * 1024 * 1024\r
+        dc.init(dc.OUT, value=0)\r
+        res.init(res.OUT, value=0)\r
+        cs.init(cs.OUT, value=1)\r
+        self.spi = spi\r
+        self.dc = dc\r
+        self.res = res\r
+        self.cs = cs\r
+        import time\r
+\r
+        self.res(1)\r
+        time.sleep_ms(1)\r
+        self.res(0)\r
+        time.sleep_ms(10)\r
+        self.res(1)\r
+        super().__init__(width, height, external_vcc)\r
+\r
+    def write_cmd(self, cmd):\r
+        self.spi.init(baudrate=self.rate, polarity=0, phase=0)\r
+        self.cs(1)\r
+        self.dc(0)\r
+        self.cs(0)\r
+        self.spi.write(bytearray([cmd]))\r
+        self.cs(1)\r
+\r
+    def write_data(self, buf):\r
+        self.spi.init(baudrate=self.rate, polarity=0, phase=0)\r
+        self.cs(1)\r
+        self.dc(1)\r
+        self.cs(0)\r
+        self.spi.write(buf)\r
+        self.cs(1)
\ No newline at end of file
diff --git a/toilet.pbm b/toilet.pbm
new file mode 100644 (file)
index 0000000..07efcb3
Binary files /dev/null and b/toilet.pbm differ