#      ----------------------------------------------------------------------------
#      "THE TSCHUNK-WARE LICENSE" (Revision 23):
#      Niklas Roy wrote this file. As long as you retain this notice you
#      can do whatever you want with this stuff. If we meet some day, and you think
#      this stuff is worth it, you can buy me a tschunk in return
#      ----------------------------------------------------------------------------

import buttons
import display
import os
import utime
import bhi160
import bme680
import math
import power
import vibra
import leds
import light_sensor
import sys

sys.path.append("/apps/control_center/")
import fonts

WIDTH  = 160
HEIGHT = 80

GESTURE_THRESHOLD = 30
SLEEP_TIMEOUT     = 20

LAUNCHER     = 0
WATCH        = 1
DATE         = 2
BATTERY      = 3
WEATHER      = 4
IMU          = 5
MAIN         = 6
TRANSITION   = 7
VOID         = 8
ALARM_SCREEN = 9

screen       = TRANSITION
p_screen     = VOID
highlighted  = VOID
selected     = VOID

display_brightness = 30
target_brightness  = 30


#-------------------------------------------------------------- mini text
def mini_text(text,x_text,y_text,text_col, fast_update = False):

    for i in range(len(text)):
        c = ord(text[i])
        if c>96 and c<123: # a->A ... z->Z
            c-=32
        c-=32
        if c<0 or c>58:
            c=0
        if x_text < WIDTH:
            if c==0:
                x_text += 5 # increment start position of next character
            else:    
                for x in range(7): # show character
                    for y in range(7):
                        if (fonts.mini_alphabet[c][y][x]==1):
                            x_px =  x  + x_text 
                            y_px =  y  + y_text
                            if x_px>=0 and x_px<WIDTH and y_px>=0 and y_px<HEIGHT:
                                disp.pixel(x_px, y_px,col=text_col)

                if c==14:
                    x_text += 4 # increment start position of next character after '.' 
                else:
                    x_text += 10 # increment start position of next character

            
            if i%4 == 0 and i>0 and fast_update == True:
                disp.update()
        

#-------------------------------------------------------------- micro text
def micro_text(text,x_text,y_text,text_col):
    
    for i in range(len(text)):

        c = ord(text[i])
        if c>96 and c<123: # a->A ... z->Z
            c-=32
        c-=32
        if c<0 or c>58:
            c=0
               
        for x in range(5): # show character
            for y in range(5):
                if (fonts.micro_alphabet[c][y][x]==1):
                    x_px =  x  + x_text 
                    y_px =  y  + y_text
                    
                    if x_px >=0 and x_px <WIDTH and y_px>=0 and y_px<=HEIGHT:
                        disp.pixel(x_px, y_px, col=text_col)
        if c==14:
            x_text += 3 # increment start position of next character after '.' 
        else:
            x_text += 7 # increment start position of next character  
    return



#-------------------------------------------------------------- robust line (coordinates can be floats and outside screen - line will still be displayed)
def r_line(x1,y1,x2,y2,color=(255,255,255)):

    if x1>=0 and x1<= WIDTH and  x2>=0 and x2<= WIDTH and y1>=0 and y1<= HEIGHT and y2>=0 and y2<= HEIGHT: # line is on screen
        disp.line(int(x1),int(y1),int(x2),int(y2),col=color)
    else:
        
        if x1>WIDTH:
            dxa = x1  - x2     # x-distance
            dxb = WIDTH - x2

            r=1
            if dxa>0:
                r   = dxb / dxa
            
            dy  = y1 - y2      # y-distance
            dy  = dy * r
            y1  = y2 + dy
            x1  = WIDTH

        elif x1<0:
            dxa = x2  - x1     # x-distance
            dxb = 0 - x2
            r=1
            if dxa>0:
                r   = dxb / dxa
            dy  = y2 - y1      # y-distance
            dy  = dy * r
            y1  = y2 + dy
            x1  = 0

        if x2>WIDTH:
            dxa = x2  - x1    # x-distance
            dxb = WIDTH - x1
            r=1
            if dxa>0:
                r   = dxb / dxa
            dy  = y2 - y1      # y-distance
            dy  = dy * r
            y2  = y1 + dy
            x2  = WIDTH

        elif x2<0:
            dxa = x1  - x2     # x-distance
            dxb = 0 - x1
            r=1
            if dxa>0:
                r   = dxb / dxa
            dy  = y1 - y2      # y-distance
            dy  = dy * r
            y2  = y1 + dy
            x2  = 0
            
        if y1>HEIGHT:
            dya = y1  - y2     # y-distance
            dyb = HEIGHT - y2
            r=1
            if dya>0:
                r   = dyb / dya
            dx  = x1 - x2      # x-distance
            dx  = dx * r
            x1  = x2 + dx
            y1  = HEIGHT

        elif y1<0:
            dya = y2  - y1     # y-distance 
            dyb = 0 - y2
            r=1
            if dya>0:
                r   = dyb / dya
            dx  = x2 - x1      # x-distance 
            dx  = dx * r
            x1  = x2 + dx
            y1  = 0

        if y2>HEIGHT:
            dya = y2  - y1    # y-distance
            dyb = HEIGHT - y1
            r=1
            if dya>0:
                r   = dyb / dya
            dx  = x2 - x1      # x-distance
            dx  = dx * r
            x2  = x1 + dx
            y2  = HEIGHT

        elif y2<0:
            dya = y1  - y2     # y-distance
            dyb = 0 - y1
            r=1
            if dya>0:
                r   = dyb / dya
            dx  = x1 - x2      # x-distance
            dx  = dx * r
            x2  = x1 + dx
            y2  = 0
        
        disp.line(constrain(int(x1),0,WIDTH),constrain(int(y1),0,HEIGHT),constrain(int(x2),0,WIDTH),constrain(int(y2),0,HEIGHT),col=color)

    return
#-------------------------------------------------------------- rotation matrices

pi = 3.14159265359

def rot_x(p=(1,1,1),a=0):
    x =  math.cos(a) * p[0] + math.sin(a) * p[2]
    y =  p[1]
    z = -math.sin(a) * p[0] + math.cos(a) * p[2]
    return (x,y,z)

def rot_y(p=(1,1,1),a=0):
    x =  p[0]
    y =  math.cos(a) * p[1] + math.sin(a) * p[2]
    z = -math.sin(a) * p[1] + math.cos(a) * p[2]
    return (x,y,z)

def rot_z(p=(1,1,1),a=0):
    x =  math.cos(a) * p[0] + math.sin(a) * p[1]
    y = -math.sin(a) * p[0] + math.cos(a) * p[1]
    z =  p[2]
    return (x,y,z)
#-------------------------------------------------------------- draw one 3d line, rotated in x,y,z 
def draw_3d_line(l_start,l_end,l_color=(255,255,255),rx = 0,ry = 0,rz = 0,persp = 8, zoom=3, x_shift=0 ):
 
    l_start = rot_z(l_start, rz)
    l_end   = rot_z(l_end  , rz)
    
    l_start = rot_x( l_start , rx)
    l_end   = rot_x( l_end   , rx)

    l_start = rot_y(l_start, ry)
    l_end   = rot_y(l_end  , ry)


    screen_s_x = int( ( l_start[0] * zoom * ( l_start[2] + persp ) ) + 80 + x_shift)
    screen_s_y = int( ( l_start[1] * zoom * ( l_start[2] + persp ) ) + 40)
    screen_e_x = int( ( l_end[0]   * zoom * ( l_end[2]   + persp ) ) + 80 + x_shift)
    screen_e_y = int( ( l_end[1]   * zoom * ( l_end[2]   + persp ) ) + 40)

    r_line( screen_s_x, screen_s_y, screen_e_x, screen_e_y, color=l_color)
        
    return
#-------------------------------------------------------------- constrain
def constrain(value, minimum, maximum):
    if value<minimum:
        value=minimum
    if value>maximum:
        value=maximum
    return value


#-------------------------------------------------------------- read bhi / orientation / imu
gyro            = bhi160.BHI160Orientation(sample_rate=20)
gx              = 0.0 # gyro values
gy              = 0.0
gz              = 0.0
gs              = 0
accelerometer   = bhi160.BHI160Accelerometer(sample_rate=20)
ax              = 0.0 # accelerometer values
ay              = 0.0
az              = 0.0

def read_bhi():
    global gx
    global gy
    global gz
    global gs
    global ax
    global ay
    global az  
    #.......................................................... read virtual gyro

    samples = gyro.read()
    
    if len(samples) > 0:                     
        sample = samples[len(samples)-1]
          
        gx =   sample.x 
        gy =   sample.y 
        gz =   sample.z
        gs =   sample.status
        
        #.......................................................... read accelerometer

    samples = accelerometer.read()
    
    if len(samples) > 0:                     
        sample = samples[len(samples)-1]

            
        ax =   sample.x 
        ay =   sample.y 
        az =   sample.z
        
    return 




############################################################### controlcenter specific functions


#============================================================== show time
show_time_update = False
time_color = (0,0,0)
p_time_color = (0,0,0)

def show_time(x_pos,y_pos,color, wireframe = False , forced_update = False):
    
    global show_time_update
    global time_color
    global p_time_color

    p_time_color = time_color
    time_color = color

    if forced_update == True:
        show_time_update = True

    if p_screen != screen:
        show_time_update = True
        
    if p_time_color != time_color:
        show_time_update = True
        
    if new_minute == True or wireframe == True:# update only if there's a new minute or if wireframe has been shown before
        show_time_update = True

    if show_time_update == True:
        if wireframe == False:
            show_time_update = False
        
        if wireframe == False:
            disp.rect(x_pos,y_pos,122+x_pos,29+y_pos,col=(0,0,0))    
        
        time = '%02d%02d' % (hour,minute)
        for i in range(4):
            c = ord(time[i])-48
            for x in range(5): # show character
                for y in range(7):
                    if (fonts.big_number[c][y][x]==1):
                        x_start =  x*4  + x_pos 
                        y_start =  y*4  + y_pos
                        
                        if wireframe == True:
                            r_line(   x_start, y_start, x_start+4,y_start+4,color=color)
                        else:
                            disp.rect(x_start, y_start, x_start+4,y_start+4,col=color)
            x_pos += 28 # increment start position of next character
            if i==1:
                if wireframe == True:
                    r_line(   x_pos+3,y_pos+6, x_pos+7,y_pos+10,color=color)
                    r_line(   x_pos+3,y_pos+18,x_pos+7,y_pos+22,color=color)
                else:
                    disp.rect(x_pos+3,y_pos+6, x_pos+7,y_pos+10,col=color)
                    disp.rect(x_pos+3,y_pos+18,x_pos+7,y_pos+22,col=color)
                x_pos+=17
    return
#============================================================== show date
p_date_color = (0,0,0)
p_day = 0
days   = ('MON','TUE','WED','THU','FRI','SAT','SUN')
months = ('JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC')
    
def show_date(x_pos,y_pos,color):
    global p_date_color
    global p_day

    date_update = False

    if p_screen != screen:
        date_update = True
        
    if p_day != time_all[2]:
        date_update = True
    p_day = time_all[2]
    
    if p_date_color != color:
        date_update = True
    p_date_color = color
    

    if date_update == True:
        disp.rect(130 + x_pos,0,156,28,col=(0,0,0))
        mini_text(   days[  time_all[6]]   , 130 + x_pos,  0 + y_pos, color )
        mini_text( months[  time_all[1]-1] , 130 + x_pos, 10 + y_pos, color )
        mini_text( '%02d'% time_all[2]     , 130 + x_pos, 20 + y_pos, color )
    
    return

#============================================================== volt to percent - looks up charge from voltage
battery_curve       = (407, 406, 404, 402, 402, 401, 400, 399, 398, 398, 398, 397, 396, 395, 395, 395, 395, 395, 393, 393, 393,
                       393, 392, 392, 392, 392, 391, 391, 391, 391, 390, 388, 388, 388, 388, 388, 387, 387, 387, 387, 387, 386,
                       386, 386, 386, 385, 385, 385, 385, 383, 383, 383, 383, 383, 383, 383, 382, 381, 381, 381, 381, 380, 380,
                       380, 380, 379, 379, 379, 379, 379, 379, 379, 379, 377, 377, 377, 377, 377, 377, 376, 376, 376, 376, 376,
                       375, 375, 375, 375, 374, 374, 374, 374, 374, 373, 373, 373, 373, 373, 372, 372, 372, 372, 372, 371, 371,
                       371, 371, 371, 370, 370, 370, 370, 370, 370, 369, 369, 369, 369, 369, 368, 368, 368, 368, 368, 368, 368,
                       368, 368, 368, 367, 367, 367, 367, 367, 366, 365, 365, 365, 365, 365, 363, 363, 363, 363, 362, 362, 362,
                       362, 360, 360, 360, 359, 357, 357, 356, 355, 354, 351, 351)

def volt_to_percent(voltage):
    voltage = voltage * 100
    curve_position = 0
    for i in range(len(battery_curve)):
        if battery_curve[i] > voltage:
            curve_position = i
        
    return 100-constrain(curve_position/len(battery_curve)*100,0,100)

#============================================================== draw battery flash
def draw_flash(x_pos,y_pos,color=(255,255,255)):
    x_pos+=4
    for i in range(5):#draw flash
        disp.line(x_pos,y_pos,x_pos-i,y_pos+10,col=color)
        disp.line(x_pos,y_pos+19,x_pos+i,y_pos+9,col=color)
    
    return
#============================================================== show battery

charge_line         = 0
charging            = False
p_charge_line       = 0
p_charging          = False
battery_updated     = False
show_battery_update = False
p_bat_color         = (0,0,0)


def show_battery(x_pos,y_pos,color, wireframe = False):
 
    global charge_line
    global charging
    global p_charge_line
    global p_charging
    global battery_updated
    global show_battery_update
    global last_interaction_ms 
    global p_bat_color

    if charging != p_charging:
        last_interaction_ms = millis

    p_charge_line = charge_line
    p_charging    = charging
        
    charging = False
    dash_distance = 3
    
    #.......................................................... update?
    if p_bat_color != color:
        show_battery_update = True
        
    p_bat_color = color
    
    if p_screen != screen:
        show_battery_update = True


    #.......................................................... draw battery infill   
    if wireframe == False:
        charge = volt_to_percent(smooth_voltage)
        charge_line   = 33+int((100-charge)/100*27)
        charge_color  = color
        
        if(power.read_chargein_voltage()>4): # check if charging
            charge   = 100
            charging = True
            dash_distance = 1

        if charging != p_charging:
            last_interaction_ms = millis
            
        if charge_line != p_charge_line or charging != p_charging:  #update battery content if charge / charging has changed
            show_battery_update = True

        if show_battery_update == True:
            
            
            disp.rect(0,32,12,61,col=(0,0,0))       # clear battery background

            j = 0
            for i in range(0,42,dash_distance):

                x_begin = i-32
                y_begin = 32
                x_end   = i-4
                y_end   = 60
                
                if x_end > 12:
                    y_end = y_end - (x_end - 12)
                    x_end = 12
                
                if x_end > 0:
                    r_line( x_begin,y_begin,x_end,y_end,  charge_color)   # draw full charge as diagonal lines
            if charging == False:
                disp.rect(0,33 ,12, charge_line,col=(0,0,0),filled=True)  # black fill mask to cover non-charged bat w/ blk
                disp.line(0,charge_line,12,charge_line,col=charge_color)  # top line of charge bar
            
            disp.rect( 0,  32, 3,      34, col = (0,0,0) , filled=True)   # black battery shoulder masks
            disp.rect( 9,  32, 12,     34, col = (0,0,0) , filled=True)

            if charging:
                draw_flash(2,38,(0,0,0))

                    
    #.......................................................... draw battery outlines 
    if wireframe == True or show_battery_update == True: #update outline if battery content has been drawn or if wireframe has to be drawn
        
        r_line( 0  + x_pos,  35 + y_pos, 4  + x_pos,  35 + y_pos, color = color) #- outline, starting from top left shoulder of battery, drawing clockwise
        r_line( 4  + x_pos,  35 + y_pos, 4  + x_pos,  32 + y_pos, color = color) #|
        r_line( 4  + x_pos,  32 + y_pos, 8  + x_pos,  32 + y_pos, color = color) #-
        r_line( 8  + x_pos,  32 + y_pos, 8  + x_pos,  35 + y_pos, color = color) # |
        r_line( 8  + x_pos,  35 + y_pos, 12 + x_pos,  35 + y_pos, color = color) # -
        r_line( 12 + x_pos,  35 + y_pos, 12 + x_pos,  61 + y_pos, color = color) #|
        r_line( 12 + x_pos,  61 + y_pos, 0  + x_pos,  61 + y_pos, color = color) #-
        r_line( 0  + x_pos,  61 + y_pos, 0  + x_pos,  35 + y_pos, color = color) #|
        
    return

#============================================================== show weather screen

LOG                   = 0
REALTIME              = 1
weather_screen        = LOG
p_weather_screen      = LOG
max_pressure_realtime = 0.0
min_pressure_realtime = 0.0
max_humidity_realtime = 0.0
min_humidity_realtime = 0.0

def show_weather():
    
    global max_pressure_realtime
    global min_pressure_realtime
    global max_humidity_realtime
    global min_humidity_realtime
    global weather_screen
    global p_weather_screen

        #...................................................... init
    if p_screen!= WEATHER:
        weather_screen = LOG
        #...................................................... show realtime screen
    if weather_screen == REALTIME:
        disp.clear()
        with bme680.Bme680() as environment:
            e=environment.get_data()
             
            if p_weather_screen == weather_screen: #update min and max values
                if max_pressure_realtime  <= e.pressure:
                    max_pressure_realtime = int(e.pressure+1)
                if min_pressure_realtime  >= e.pressure:
                    min_pressure_realtime = int(e.pressure)
                if max_humidity_realtime  <= e.humidity:
                    max_humidity_realtime = int(e.humidity+1)
                if min_humidity_realtime  >= e.humidity:
                    min_humidity_realtime = int(e.humidity)
            else:
                max_pressure_realtime = int(e.pressure+.5)
                min_pressure_realtime = int(e.pressure-.5)
                max_humidity_realtime = int(e.humidity+.5)
                min_humidity_realtime = int(e.humidity-.5)

            mini_text('REAL-TIME DATA',12,0,(255,255,255))
            
            #disp.rect(0,12,159,79,col=(255,255,255),filled=False)  # big frame
            #disp.line(0,45,159,45,col=(255,255,255))  # big frame
            
            mini_text('AIR PRESSURE',22,15,(255,255,255))

            y_pos = 25
            value = constrain(int((e.pressure-min_pressure_realtime) / (max_pressure_realtime - min_pressure_realtime) * 155)+2,2,157)
            disp.rect(0,y_pos,159,y_pos+6,col=(255,255,255),filled=False)  # frame
            disp.rect(2,y_pos+2,value,y_pos+4,col=(255,255,255),filled=True)# bar
            for i in range(min_pressure_realtime+1,max_pressure_realtime,1):
                x_mark = int((i-min_pressure_realtime)/(max_pressure_realtime - min_pressure_realtime)*159)
                c_mark = (255,255,255)
                if x_mark<value:
                    c_mark=(0,0,0)
                if i%10==0:
                    disp.line(x_mark,y_pos+2,x_mark,y_pos+4,col=c_mark)
                else:
                    disp.pixel(x_mark,y_pos+3,col=c_mark)

            micro_text('%i'%min_pressure_realtime,1,y_pos+10,(255,255,255))
            if max_pressure_realtime<1000:
                micro_text('%i'%max_pressure_realtime,140,y_pos+10,(255,255,255))
            else:
                micro_text('%i'%max_pressure_realtime,133,y_pos+10,(255,255,255))
            mini_text('%.1f HPA'%e.pressure,36,y_pos+10,(255,255,255))
            
            mini_text('HUMIDITY',42,49,(255,255,255))
            
            y_pos = 59    
            value = constrain(int((e.humidity-min_humidity_realtime) / (max_humidity_realtime - min_humidity_realtime) * 157)+2,2,157)
            disp.rect(0,y_pos,159,y_pos+6,col=(255,255,255),filled=False)  # frame
            disp.rect(2,y_pos+2,value,y_pos+4,col=(255,255,255),filled=True)# bar   
            for i in range(min_humidity_realtime+1,max_humidity_realtime,1):
                x_mark = int((i-min_humidity_realtime)/(max_humidity_realtime - min_humidity_realtime)*159)
                c_mark = (255,255,255)
                if x_mark<value:
                    c_mark=(0,0,0)
                if i%10==0:
                    disp.line(x_mark,y_pos+2,x_mark,y_pos+4,col=c_mark)
                else:
                    disp.pixel(x_mark,y_pos+3,col=c_mark)
                
            micro_text('%i'%min_humidity_realtime,1,y_pos+10,(255,255,255))
            micro_text('%i'%max_humidity_realtime,147,y_pos+10,(255,255,255))
            mini_text('%.1f'%e.humidity+' %RH',47,y_pos+10,(255,255,255))

        #...................................................... show log screen
    if weather_screen == LOG:
        disp.clear((0,0,0))
        
        mini_text('SENSOR LOGS',12,0,(255,255,255))
        
        color=(255,255,255)
        
        #...................................................... find min and max in barometer log
        
        min_pressure = 10000
        max_pressure = 0
        
        for log_data in barometer_log:
            if log_data > max_pressure:
                max_pressure = log_data
            if log_data < min_pressure and log_data!=0:
                min_pressure = log_data

        delta_pressure = max_pressure - min_pressure
        if delta_pressure==0:
            delta_pressure=.01
            
        #...................................................... draw baro log graph stretched to fit window
        log_x = 7
        log_y = 11
        log_w = 111
        log_h = 28
        
        disp.rect(log_x, log_y, log_x + log_w, log_y + log_h, col=(0,0,0))     # clear log window        
        disp.rect(log_x, log_y, log_x + log_w, log_y + log_h, col=color, filled = False)     #  log window frame
        
        for i in range(log_y,log_y+log_h,4):               # draw hour marks as dashed lines
            disp.pixel(log_w//3+log_x,i,col=color)
            disp.pixel(log_w*2//3+log_x,i,col=color)
            
        
        micro_text('%.1f'%max_pressure,log_x+log_w+6,log_y+3,(255,255,255))
        micro_text('%.1f'%min_pressure,log_x+log_w+6,log_y+log_h-7,(255,255,255))
        micro_text('HPA' ,log_x+log_w+13,log_y+log_h//2-2,(255,255,255))
            
        y_data   = -1
        p_y_data = -1

        up_down = 0
        
        for i in range(log_w):
            p_y_data = y_data
            x_data = (log_w-i)+log_x # r -> l

                
            index = int(weather_log_index-(i/(log_w-1))*179) # new -> old
            if barometer_log[(index-1)%180]!=0 and barometer_log[(index-2)%180]!=0:
                y_data = int((1-(((barometer_log[(index-1)%180]+barometer_log[(index-2)%180])/2 - min_pressure) / delta_pressure)) * (log_h-3) + log_y +2)
            else:
                y_data = -1
            if y_data>-1 and p_y_data>-1:
                if i==0:
                    p_y_data=y_data
                if i==log_w-1:
                    y_data=p_y_data
                r_line(x_data,p_y_data,x_data-1,y_data,color = color) # draw graph

            if i>(log_w*2//3):
                if y_data<(log_y+log_h/2):
                    up_down += 1
                else:
                    up_down -=1
        y_text = log_y+2
        if up_down>0:
            y_text = log_y+log_h-6
        disp.rect(log_x+2,y_text-1,log_x+29,y_text+5,col=(0,0,0),filled=True)
        micro_text('BARO',log_x+3,y_text,(255,255,255))
            

        
        #...................................................... find min and max in hygrometer log
        
        min_humidity = 10000
        max_humidity = 0
        
        for log_data in hygrometer_log:
            if log_data > max_humidity:
                max_humidity = log_data
            if log_data < min_humidity and log_data!=0:
                min_humidity = log_data

        delta_humidity = max_humidity - min_humidity
        if delta_humidity==0:
            delta_humidity=.01
            
        #...................................................... draw hygro log graph stretched to fit window
        log_x = 7
        log_y = 42
        log_w = 111
        log_h = 28
        
        disp.rect(log_x, log_y, log_x + log_w, log_y + log_h, col=(0,0,0))     # clear log window        
        disp.rect(log_x, log_y, log_x + log_w, log_y + log_h, col=color, filled = False)     #  log window frame
        
        for i in range(log_y,log_y+log_h,4):               # draw hour marks as dashed lines
            disp.pixel(log_w//3+log_x,i,col=color)
            disp.pixel(log_w*2//3+log_x,i,col=color)
            
        micro_text('-3H',log_x-7,log_y+log_h+5,(255,255,255))
        micro_text('-2H',log_w//3+log_x-7,log_y+log_h+5,(255,255,255))
        micro_text('-1H',log_w*2//3+log_x-7,log_y+log_h+5,(255,255,255))
        micro_text('NOW',log_x+log_w-9,log_y+log_h+5,(255,255,255))

        
        micro_text('%.1f'%max_humidity,log_x+log_w+6,log_y+3,(255,255,255))
        micro_text('%.1f'%min_humidity,log_x+log_w+6,log_y+log_h-7,(255,255,255))
        micro_text('%RH' ,log_x+log_w+13,log_y+log_h//2-2,(255,255,255))
            
        y_data   = -1
        p_y_data = -1
        
        up_down = 0
        for i in range(log_w):
            p_y_data = y_data
            x_data = (log_w-i)+log_x # r -> l
            index = int(weather_log_index-(i/(log_w-1))*179) # new -> old
            if hygrometer_log[(index-1)%180]!=0 and hygrometer_log[(index-2)%180]!=0:
                y_data = int((1-(((hygrometer_log[(index-1)%180]+hygrometer_log[(index-2)%180])/2 - min_humidity) / delta_humidity)) * (log_h-3) + log_y+2)
            else:
                y_data = -1
            if y_data>-1 and p_y_data>-1:
                if i==0:
                    p_y_data=y_data
                if i==log_w-1:
                    y_data=p_y_data
                r_line(x_data,p_y_data,x_data-1,y_data,color = color) # draw graph
            if i>(log_w*2//3):
                if y_data<(log_y+log_h/2):
                    up_down += 1
                else:
                    up_down -=1
        y_text = log_y+2
        if up_down>0:
            y_text = log_y+log_h-6
        disp.rect(log_x+2,y_text-1,log_x+36,y_text+5,col=(0,0,0),filled=True)
        micro_text('HYGRO',log_x+3,y_text,(255,255,255))
        

    p_weather_screen = weather_screen            
    return
#============================================================== show weather log

    
barometer_log           = [0.0]*180   #                            air pressure for the last 180 minutes
hygrometer_log          = [0.0]*180   #                            air pressure for the last 180 minutes 
weather_log_index       = 0           #                            position in logging buffer 0...179
p_rel_humidity          = 0
rel_humidity            = 0
show_weather_log_update = False
p_log_color             = (0,0,0)

def show_weather_log(x_pos,y_pos,color, wireframe = False):

    global show_weather_log_update
    global p_rel_humidity
    global rel_humidity
    global p_log_color

    if p_log_color != color:
        show_weather_log_update = True
        
    p_log_color = color

    
    if p_screen != screen:
        show_weather_log_update = True
        
    if new_minute == True:                        # update log every new minute or when battery state has changed
        show_weather_log_update = True

    #.......................................................... draw outlines of weather window
    if wireframe == True or show_weather_log_update == True:
        
        
        r_line( 17  + x_pos,  33 + y_pos, 121 + x_pos, 33 + y_pos, color = color)#-  
        r_line( 121 + x_pos,  33 + y_pos, 121 + x_pos, 53 + y_pos, color = color)#|
        r_line( 121 + x_pos,  53 + y_pos,  79 + x_pos, 53 + y_pos, color = color)#-
        r_line( 79  + x_pos,  61 + y_pos,  17 + x_pos, 61 + y_pos, color = color)#-
        r_line( 17  + x_pos,  61 + y_pos,  17 + x_pos, 33 + y_pos, color = color)#|
        r_line( 79  + x_pos,  33 + y_pos,  79 + x_pos, 61 + y_pos, color = color)#| vertical separator 

    #.......................................................... draw content of weather window
    if wireframe == False and show_weather_log_update == True:
        #...................................................... find min and max in log
        
        min_pressure = 10000
        max_pressure = 0
        
        for log_data in barometer_log:
            if log_data > max_pressure:
                max_pressure = log_data
            if log_data < min_pressure and log_data!=0:
                min_pressure = log_data

        delta_pressure = max_pressure - min_pressure
        if delta_pressure==0:
            delta_pressure=.01
            
        #...................................................... draw log graph stretched to fit window

        disp.rect(18,34,78,60,col=(0,0,0))     # clear log window
        
        for i in range(37,60,4):               # draw hour marks as dashed lines
            disp.pixel(37,i,col=color)
            disp.pixel(58,i,col=color)
            
        y_data   = -1
        p_y_data = -1
        
        for i in range(60):
            p_y_data = y_data
            x_data = i+19
            index = (i*3+weather_log_index)
            if barometer_log[index%180]!=0 and barometer_log[(index+1)%180]!=0 and barometer_log[(index+2)%180]!=0:
                y_data = int((1-((barometer_log[index%180]+barometer_log[(index+1)%180]+barometer_log[(index+2)%180])/3 - min_pressure) / delta_pressure) * 26 + 35)
            else:
                y_data = -1
            if y_data>-1 and p_y_data>-1:
                disp.line(x_data-1,p_y_data,x_data,y_data,col = color)
            
        #...................................................... write pressure legend
        disp.rect(80,34,120,52,col=(0,0,0))  # clear text window
        
        hpa_string = '%i'%(int(delta_pressure))
        if delta_pressure<1:
            hpa_string = '.%01d'%(int(delta_pressure*10))
        if delta_pressure>99 or len(hpa_string)>2:
            hpa_string = 'XX'
                
        micro_text(hpa_string,84,37,color)
        micro_text('HPA',99,37,color)

        min_barometric_height = 288.15/0.0065*(1-(max_pressure/1013.25)**(1/5.255)) # formula taken from 'barometric altimeter' by Nubesik
        max_barometric_height = 288.15/0.0065*(1-(min_pressure/1013.25)**(1/5.255))
        delta_height = max_barometric_height - min_barometric_height
        height_string= '%i'%(int(delta_height))
        if len(height_string)>4:
            height_string = 'XX'
        micro_text(height_string,84,45,color)
        micro_text('M',113,45,color)
    
    #...................................................... write humidity
    if wireframe == False and ((p_second!=second and second%3 == 0) or show_weather_log_update == True):
        
        with bme680.Bme680() as environment:

            if show_weather_log_update == True: # legend
                disp.rect(100,57,121,61,col=(0,0,0))
                micro_text('%' ,100,57,color)
                micro_text('RH',110,57,color)
                
            p_rel_humidity      = rel_humidity
            rel_humidity        = int(environment.get_data().humidity+.5)
            
            if p_rel_humidity != rel_humidity or show_weather_log_update == True: # only update if necessary
                rel_humidity_string ='%02d'%(rel_humidity)
                if rel_humidity > 99:
                    rel_humidity_string = 'XX'
                    
                disp.rect(84,57,95,61,col=(0,0,0))
                micro_text(rel_humidity_string,84,57,color)
        
        environment.close()

    #.......................................................... save info for dynamic updating in next cycle
    if show_weather_log_update == True:
        show_weather_log_update = False
    if wireframe == True:
        show_weather_log_update = True
        
    return
#============================================================== save barometer log
def save_weather_log():

    global barometer_log
    global hygrometer_log
    global weather_log_index
    print ('saving weather log')
    
    with bme680.Bme680() as environment:
        e=environment.get_data()
        barometer_log[weather_log_index]  = e.pressure
        hygrometer_log[weather_log_index] = e.humidity
        weather_log_index += 1
        weather_log_index  = weather_log_index % 180

        with open('/apps/control_center/cc_weather.log','w+') as b_log:
            b_log.write('time:\r\n%02d%02d\r\n'%(hour,minute)) 
            b_log.write('index:\r\n%03d\r\n'%(weather_log_index))
            b_log.write('barometer, hygrometer:\r\n')
            for i in range(180):
                b_log.write('%06d,%05d\r\n'%(int(barometer_log[i]*100),int(hygrometer_log[i]*100)))
                
    environment.close()
    return

#============================================================== load weather log
def load_weather_log():

    global barometer_log
    global hygrometer_log
    global weather_log_index
    print ('loading weather log')
    
    try: # check if there's a log file
        with open('/apps/control_center/cc_weather.log','r') as b_log:
            
            for line, data in enumerate(b_log):
                if line==3:
                    weather_log_index = int(data.strip('\r\n'))
                elif line>=5:        
                    barometer_log[line-5]  = int(data[:6])/100
                    hygrometer_log[line-5] = int(data[7:-2])/100
       
    except:
        save_weather_log()
        
    return

#============================================================== show compass

def show_compass(x_pos,y_pos,color, wireframe = False):

    
    xc = 144 + x_pos
    yc = 47 + y_pos
            
    

    steps = 4
    if wireframe == False:
        disp.rect(xc-15,yc-15,xc+15,yc+15,col=(0,0,0))  # clear area
        steps = 2
        if gs==3:                                       # indicate full trust in compass by drawing circle undashed
            steps=1

    north = (gx+450)/180*pi           
    for i in range(0,24,steps):                         # dashed circle segments
        ri = pi/12*i
        
        if steps>1:
            ri += north 
        ric1=rot_z((14.5, 0 ,0), ri - pi /24)
        ric2=rot_z((14.5, 0 ,0), ri + pi /24)
        r_line(xc + ric1[0], yc + ric1[1], xc + ric2[0], yc + ric2[1],color)
        
    
    if wireframe == False:
        
        angle = north                         # draw north pointing needle 
                
        line_begin = rot_z (( 11,  0 ,0 ) , angle)
        line_end   = rot_z (( -9,  4 ,0 ) , angle)
                
        r_line(xc + line_begin[0], yc + line_begin[1], xc + line_end[0], yc + line_end[1],color)

        line_begin = rot_z (( 11,  0 ,0 ) , angle)
        line_end   = rot_z (( -9, -4 ,0 ) , angle)
                
        r_line(xc + line_begin[0], yc + line_begin[1], xc + line_end[0], yc + line_end[1],color)

        line_begin = rot_z (( -9, -4 ,0 ) , angle)
        line_end   = rot_z (( -9,  4 ,0 ) , angle)
                
        r_line(xc + line_begin[0], yc + line_begin[1], xc + line_end[0], yc + line_end[1],color)
    return
#============================================================== show imu

# n
n = [[-1, 1, 0],[-1,-1, 0],[ 1, 1, 0],[ 1,-1, 0]]
for i in range(4):
    n[i][0]=n[i][0]/8
    n[i][1]=n[i][1]/8-1
    
#s
s = [[-1, 1, 0],[ 1, 1, 0],[ 1, 0, 0],[-1, 0, 0],[-1,-1, 0],[ 1,-1, 0]]
for i in range(6):
    s[i][0]=s[i][0]/8
    s[i][1]=s[i][1]/8+1  

#w
w = [[-1,-1, 0],[-1, 1, 0],[ 0, 0, 0],[ 1, 1, 0],[ 1,-1, 0]]
for i in range(5):
    w[i][0]=w[i][0]/8-.9
    w[i][1]=w[i][1]/8

#e
e = [[ 1, 1, 0],[-1, 1, 0],[-1, 0, 0],[.5, 0, 0],[-1, 0, 0],[-1,-1, 0],[ 1,-1, 0]]
for i in range(7):
    e[i][0]=e[i][0]/8+.9
    e[i][1]=e[i][1]/8  

def show_imu():
    
    global north_south
    global east_west
    global up_down
    
    z_mag = 3.7 + constrain(abs(gy)-10,0,80)/80 * .75

    if p_screen!=IMU:
        disp.clear()
        disp.rect(0,0,159,79,col=(255,255,255),filled=False) # frame left side
        disp.line(0,28,76,28,col=(255,255,255))
        disp.line(76,0,76,79,col=(255,255,255))
        disp.rect(7,44,69     ,  49,col=(255,255,255),filled=False) # trust bar frame
        
        mini_text ('VIRTUAL' , 5,  5, (255,255,255))
        mini_text ('GYRO'    ,20, 16, (255,255,255))
        micro_text('TRUST:'  , 7, 34, (255,255,255))
        micro_text('ELEV:'   , 7, 58, (255,255,255))
        micro_text('ROLL:'   , 7, 68, (255,255,255))
        
    gxp = (gx)/180*pi
    gyp = (gy)/180*pi
    gzp = (gz)/180*pi

    # compass bgnd
    disp.rect(77,1,158,78,col=(0,0,0),filled=True)

    # ring
    ring_size = .5
    step = 40
    if gs == 3:
        step = 20
    for i in range(30,320,step):
        if i!=170:
            start = (math.sin(i/180*pi)*ring_size,math.cos(i/180*pi)*ring_size,0)
            end   = (math.sin((i+20)/180*pi)*ring_size,math.cos((i+20)/180*pi)*ring_size,0)
            draw_3d_line( start,end, l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )
        
    # needle
    draw_3d_line((  0 , -.7  ,0),( .25, .65 ,0), l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )
    draw_3d_line(( .25,  .65 ,0),(-.25,  .65,0), l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )
    draw_3d_line((-.25,  .65 ,0),(  0 ,-.7  ,0), l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )
 
    for i in range(3):
        draw_3d_line(n[i],n[i+1],l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )

    for i in range(5):
        draw_3d_line(s[i],s[i+1],l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )
        
    for i in range(4):
        draw_3d_line(w[i],w[i+1],l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )

    for i in range(6):
        draw_3d_line(e[i],e[i+1],l_color=(255,255,255), rx = gzp, ry = gyp, rz = gxp, persp = 8, zoom=z_mag, x_shift=38 )

    disp.rect(9,46,68, 47,col=(0,0,0),filled=True ) # trust bar bgnd
    disp.rect(9,46,9+int(gs*19.3), 47,col=(255,255,255),filled=True ) # trust bar
    disp.rect(41,58,75,78,col=(0,0,0),filled=True) # numbers bgnd
    
    elev='%.1f°'%(-gy)
    if gy>99:
        elev='%i°'%(-gy)
        micro_text(elev, 41,                58, (255,255,255))
    else:
        micro_text(elev, 41+(7-len(elev))*7,58, (255,255,255))
    roll='%.1f°'%(-gz)
    micro_text    (roll, 41+(7-len(roll))*7,68, (255,255,255))
    return

#============================================================== microlauncher
show_microlauncher_update   = False
launch_line                 = ''
p_launch_line               = ''
launch_selection            = 0
all_apps                    = os.listdir("/apps")
max_apps                    = len(all_apps)
p_launch_color              = (0,0,0)

def show_launcher(x_pos,y_pos,color, wireframe = False):
    global launch_line
    global p_launch_line
    global show_microlauncher_update
    global launch_selection
    global p_launch_color

    fast_update = False
    
    if p_launch_color != color:
        show_microlauncher_update = True
    p_launch_color = color

    if p_screen != screen:
        show_microlauncher_update = True
    
    if wireframe ==True:
        show_microlauncher_update = True

    if wireframe == False:
        p_launch_line = launch_line
        
        if selected == LAUNCHER:
            
            launch_line  = all_apps[launch_selection%max_apps]
            
        else:
            launch_line   = '../MICROLAUNCHER'

        if p_launch_line != launch_line:
            show_microlauncher_update = True
            fast_update = True
       

    r_line (0 + x_pos,    66 + y_pos, 159 + x_pos, 66 + y_pos, color = (0,0,0)) # clear scrollbar
    r_line (0 + x_pos,    67 + y_pos, 159 + x_pos, 67 + y_pos, color = (0,0,0))        
    r_line ( 0 + x_pos,   79 + y_pos,   0 + x_pos, 65 + y_pos, color = color )  # | l
    r_line ( 159 + x_pos, 65 + y_pos, 159 + x_pos, 79 + y_pos, color = color )  # | r
    r_line ( 159 + x_pos, 79 + y_pos,   0 + x_pos, 79 + y_pos, color = color )  # - b
    r_line ( 0 + x_pos,   65 + y_pos, 159 + x_pos, 65 + y_pos, color = color )  # - t
        
    if selected == LAUNCHER:
        
        if max_apps>0: # draw scrollbar
            for i in range(1,max_apps,1):                              
                div_x = (159/max_apps)*i
                disp.line(int(div_x),66,int(div_x),67,col=(255,255,255))
            disp.rect(constrain(int((159/max_apps)*(launch_selection%max_apps)),1,158),65,constrain(int((159/max_apps)*((launch_selection%max_apps)+1)),1,158),67,col=(255,255,255))
                
    if wireframe == False and show_microlauncher_update == True:    
        #...................................................... window content
        disp.rect(1,70,WIDTH-2,HEIGHT-2,col=(0,0,0))
        mini_text(launch_line, 5,70, color, fast_update)
        show_microlauncher_update = False
    
    return

#============================================================== check gesture
lopass_gy1 = 0 # used for rotation detection
lopass_gy2 = 100

def check_gesture():

    global lopass_gy1
    global lopass_gy2
    
    lopass_gy1 =  (gy)
    lopass_gy2 =  (lopass_gy2 * 9 + gy) / 10
    if lopass_gy2 < lopass_gy1:
        lopass_gy2 = lopass_gy1
    rotation_y = lopass_gy2 - lopass_gy1
    trigger = False
    if (rotation_y > GESTURE_THRESHOLD) and (abs(gz)<45):
        trigger=True
        
    return trigger

#============================================================== highlighted colors
def color_select(compare_selection):
    
    color_selection     = (255,255,255)
    if compare_selection == highlighted:
        color_selection = (255,64,64)

    return color_selection

#============================================================== load settings
def load_settings ():
    global launch_selection
    global alarm_on
    global alarm_hour
    global alarm_minute
    
    try: # check if there's a settings file
        with open('/apps/control_center/cc_settings.txt') as settings:
            launch_selection = int(settings.read(4))
            alarm_on_int     = int(settings.read(1))
            if alarm_on_int == 0:
                alarm_on = False
            else:
                alarm_on = True
            alarm_hour     = int(settings.read(2))
            alarm_minute   = int(settings.read(2))
    except:
        save_settings()
    return

#============================================================== save settings
def save_settings ():

    with open('/apps/control_center/cc_settings.txt','w+') as settings:
        settings.write('%04d'%launch_selection)
        alarm_on_int     = 0
        if alarm_on:
            alarm_on_int = 1
        settings.write('%01d'%alarm_on_int)
        settings.write('%02d'%alarm_hour)
        settings.write('%02d'%alarm_minute)
            

    return
#============================================================== show set time

def show_set_time(time,highlighted_digit = 0):
    
    disp.rect(0,0,122,29,col=(0,0,0))    
    x_pos = 0
    
    for i in range(4):
        c = ord(time[i])-48
        for x in range(5): # show character
            for y in range(7):
                if (fonts.big_number[c][y][x]==1):
                    x_start =  x*4 + x_pos 
                    y_start =  y*4  
                    digit_color = (255,255,255)
                    if highlighted_digit == (i + 1):
                        digit_color= (255,64,64)
                    disp.rect(x_start, y_start, x_start+4,y_start+4,col=digit_color)
                    
        x_pos += 28 # increment start position of next character
        if i==1:

            disp.rect(x_pos+3,6, x_pos+7,10,col=(255,255,255))
            disp.rect(x_pos+3,18,x_pos+7,22,col=(255,255,255))

            x_pos+=17
    return
#============================================================== highlighting
def highlight_c(a,b):
    return_color = (255,255,255)
    if a==b:
        return_color = (255,64,64)
    return return_color

#============================================================== alarm screen

alarm_count=0

def show_alarm_screen():
    global alarm_count
    alarm_count+=1
    if p_screen!=ALARM_SCREEN:
        disp.clear().backlight(display_brightness)
    p_white=False
    white = False
    for i in range(239):
        p_white = white
        white = False
        if ((i-alarm_count)//10)%2==0:
            white = True
        if white!= p_white:
            
            color = (0,0,0)
            if white:
                color = (255,255,255)

            x_begin = constrain(i,0,159)
            y_begin = constrain(i-159,0,79)
            x_end   = constrain(i-79,0,159)
            y_end   = constrain(i,0,79)
            
            r_line(x_begin,y_begin,x_end,y_end,color=color)

    disp.rect(10,10,149,69,col=(0,0,0),filled=True)
    if(alarm_count//10)%4>0 or alarm_count%2==1:
        show_time(19,26,color=(255,255,255),forced_update=True)
    else:
        vibra.vibrate(alarm_count%40*5+60)
    return
#============================================================== day of week algorithm from https://www.hackerearth.com/blog/developers/how-to-find-the-day-of-a-week/
def day_of_week(year, month, day):
    t = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4]
    year -= month < 3
    return (year + int(year/4) - int(year/100) + int(year/400) + t[month-1] + day) % 7

#============================================================== show calendar

calendar_day     = 0
calendar_month   = 0
calendar_year    = 0
p_calendar_month = 0

def show_calendar():
    global calendar_day
    global calendar_month
    global calendar_year
    global p_calendar_month

    refresh_calendar = False
    
    if p_screen != DATE:
        calendar_day   = time_all[2]
        calendar_month = time_all[1]
        calendar_year  = time_all[0]
        refresh_calendar = True

    if p_calendar_month != calendar_month:
        refresh_calendar = True
        
    if refresh_calendar:
        disp.clear()
        headline = months[calendar_month-1]+' %04d'%(calendar_year)
        mini_text(headline,44,0,(255,255,255)) # headline month, year
            
            
            
        for i in range(7):
            weekday = days[i]
            micro_text(weekday[:2],i*22+7,75,(255,255,255)) # write weekdays

            for w in range(6):                              # draw boxes for four weeks
                disp.rect(i*22+2,11+w*10,(i+1)*22+2,21+w*10,col=(255,255,255), filled = False)

        for i in range(113,156,2):                          # dashed lines for weekend boxes
            disp.line(i,11,i,71,col=(0,0,0))
        for i in range(12,71,2):
            disp.line(113,i,156,i,col=(0,0,0))
                

        max_feb = 28
        if calendar_year %4 == 0:
            max_feb = 29
        max_day = (31,max_feb,31,30,31,30,31,31,30,31,30,31)

        day = 1
        row = 0
        col = (day_of_week(calendar_year, calendar_month, day)-1)%7
            
        for i in range(max_day[calendar_month-1]):

            day_string = str(day)
            if day<10:
                day_string = ' '+day_string

            if (day == calendar_day and
                calendar_month == time_all[1] and
                calendar_year  == time_all[0]
                ): # highlight current day
                disp.rect(col*22+1,10+row*10,(col+1)*22+3,22+row*10,col=(0,0,0), filled = True)
                disp.rect(col*22+2,11+row*10,(col+1)*22+2,21+row*10,col=(255,64,64), filled = False)
                micro_text(day_string,col*22+7,row*10+14,(255,64,64)) # write each day in box
            else:
                micro_text(day_string,col*22+7,row*10+14,(255,255,255)) # write each day in box

            day +=1
            col += 1
            if col == 7:
                col=0
                row +=1
    
    p_calendar_month = calendar_month
    return

#============================================================== show power manager
CHARGE_CURVE   = 0
CHARGE_DETAILS = 1

power_manager_screen = CHARGE_CURVE

def show_power_manager():
    
    disp.clear()
    voltage = smooth_voltage 
    
    if power_manager_screen == CHARGE_DETAILS:
        
        battery_voltage = power.read_battery_voltage() #battery voltage in V
        battery_current = power.read_battery_current() #battery-side current flow in A
        battery_power   = battery_voltage * battery_current
        
        charge_voltage  = power.read_chargein_voltage()#charge voltage in V
        charge_current  = power.read_chargein_current()#charge current in A
        charge_power    = charge_voltage * charge_current

        if charge_voltage <1:
            charge_voltage = 0
            charge_current = 0
            charge_power   = 0

        x_txt_l = 11
        x_txt_r = 101
        x_txt_u = 145
        y_txt = 6
        line_height = 11
        

        mini_text('BATTERY:',x_txt_l,y_txt,(255,255,255))
        mini_text('%.2f'%battery_voltage,x_txt_r,y_txt,(255,255,255))
        mini_text('V',x_txt_u,y_txt,(255,255,255))
        y_txt+=line_height
        mini_text('%.2f'%battery_current,x_txt_r,y_txt,(255,255,255))
        mini_text('A',x_txt_u,y_txt,(255,255,255))
        y_txt+=line_height
        mini_text('%.2f'%battery_power,x_txt_r,y_txt,(255,255,255))
        mini_text('W',x_txt_u,y_txt,(255,255,255))
        y_txt+=line_height+5

        mini_text('USB:',x_txt_l,y_txt,(255,255,255))
        if charge_voltage > 0:
            mini_text('%.2f'%charge_voltage,x_txt_r,y_txt,(255,255,255))
        else:
            mini_text('-.--',x_txt_r,y_txt,(255,255,255))
        mini_text('V',x_txt_u,y_txt,(255,255,255))
        y_txt+=line_height
        
        if charge_voltage > 0:
            mini_text('%.2f'%charge_current,x_txt_r,y_txt,(255,255,255))
        else:
            mini_text('-.--',x_txt_r,y_txt,(255,255,255))
        mini_text('A',x_txt_u,y_txt,(255,255,255))
        y_txt+=line_height

        if charge_voltage > 0:
            mini_text('%.2f'%charge_power,x_txt_r,y_txt,(255,255,255))
        else:
            mini_text('-.--',x_txt_r,y_txt,(255,255,255))
        mini_text('W',x_txt_u,y_txt,(255,255,255))

        disp.rect(5,1, 159,77,col=(255,255,255),filled=False)
        disp.line(5,39,159,39,col=(255,255,255))
        
        if charge_voltage > 0:
            draw_flash(69,48,(255,255,255))  

            
    if power_manager_screen == CHARGE_CURVE:

        x_graph = 20
        y_graph = 14
        graph_w = 100
        graph_h = 50

        mini_text('BATTERY:%.2fV'%voltage,x_graph-6,0,(255,255,255))             # headline
        disp.rect(x_graph,y_graph,graph_w+x_graph,graph_h+y_graph,col=(255,255,255),filled = False) # draw graph frame

        for x in range(graph_w):
            if x%(graph_w//6)==0:
                for y_dots in range(y_graph,y_graph+graph_h,3):                # draw vertical dotted lines each 20%
                    disp.pixel(x + x_graph ,y_dots ,col=(255,255,255))

        for v in range(35,41,1):                                               # draw horizontal dotted lines each .1V
            y_dots = volt_to_y(v/10,graph_h,y_graph)
            for x in range(x_graph , graph_w + x_graph , 3):
                disp.pixel(x,y_dots,col=(255,255,255))
            micro_text('%.1f'%(v/10),x_graph + graph_w+7,y_dots-4,(255,255,255)) # write voltages next to lines
                
        micro_text('V',x_graph + graph_w+26,graph_h+y_graph-4,(255,255,255))     # label y with 'V'
        
        for x in range(graph_w):

            index = (graph_w-1)-x
            index = constrain(int(index / (graph_w-1) * len(battery_curve)),0,len(battery_curve)-1)
                                                                               # index goes from end to beginning of discharge curve
            y_dot = volt_to_y(battery_curve[index]/100,graph_h,y_graph)        # volt_to_y(voltage,window_height,window_y)
            disp.pixel(x + x_graph ,y_dot ,col=(255,255,255))                    # draw battery discharge graph


        v_percent = int(volt_to_percent(voltage))
        x_line = int(v_percent/100*graph_w)+x_graph
        y_line = volt_to_y(smooth_voltage,graph_h,y_graph)
            
        disp.line(x_line,y_graph-3,x_line,y_graph+graph_h+3,col=(255,255,255))     # charge line vertical %
        disp.line(x_graph-3,y_line,x_graph+graph_w+3,y_line,col=(255,255,255))     # charge line horizontal V

        for i in range (4):
            disp.line(x_graph-i-3,y_line-i,x_graph-i-3,y_line+i,col=(255,255,255)) # arrow left: V
            disp.line(x_line-i,y_graph+i+graph_h+2,x_line+i,y_graph+i+graph_h+2,col=(255,255,255))#arrow bottom: %
            
        disp.rect(x_line-1, y_line-1, x_line+1, y_line+1, col=(255,255,255))

        mini_text('CHARGE:'+str(v_percent)+'%',x_graph,y_graph+graph_h+8,(255,255,255))
            
        if(power.read_chargein_voltage()>4):                                   # check if charging
            draw_flash(3,28,(255,255,255))  
    return
#============================================================== show set watch screen

alarm_hour      = 0
alarm_minute    = 0
alarm_on        = False
set_minute      = 0
set_hour        = 0
set_year        = 0
set_month       = 0
set_day         = 0
EXIT            = 0
SET_TIME        = 1
SET_DATE        = 2
SET_ALARM       = 3
SET_TIME_1      = 4
SET_TIME_2      = 5
SET_TIME_3      = 6
SET_TIME_4      = 7
SET_DATE_1      = 8
SET_DATE_2      = 9
SET_DATE_3      = 10
SET_ALARM_1     = 11
SET_ALARM_2     = 12
SET_ALARM_3     = 13

watch_state     = EXIT
watch_highlight = EXIT


def show_set_watch_screen():

    global watch_highlight
    global watch_state
    global alarm_hour       
    global alarm_minute     
    global alarm_on         
    global set_minute       
    global set_hour         
    global set_year         
    global set_month       
    global set_day          
    # . . . . . . . . . . . . . . . init    
    if p_screen!= WATCH: 
        watch_highlight = EXIT
        watch_state     = EXIT
    # . . . . . . . . . . . . . . . draw watch menu
            
    mini_text("SET TIME",  3,55, highlight_c(watch_highlight,SET_TIME))
    mini_text("SET DATE", 83,55, highlight_c(watch_highlight,SET_DATE))
    mini_text("SET ALARM" ,3,69, highlight_c(watch_highlight,SET_ALARM))
    mini_text("RETURN"   ,97,69, highlight_c(watch_highlight,EXIT))
    disp.rect(0,51,159,79,col=(255,255,255),filled=False)
    disp.line(0,65,159,65,col=(255,255,255))#-
    disp.line(79,51,79,65,col=(255,255,255))#|top
    disp.line(90,79,90,65,col=(255,255,255))#|bottom


    if watch_highlight == SET_TIME:
        disp.rect(80,66,0,51,  col=(0,0,0),filled=False) # set time frame
        disp.rect(79,65,0,51,  col=(255,64,64),filled=False) # 
    if watch_highlight == SET_DATE:
        disp.rect(78,51,159,66,col=(0,0,0),filled=False) # set date frame
        disp.rect(79,51,159,65,col=(255,64,64),filled=False) # 
    if watch_highlight == SET_ALARM:
        disp.rect(0,64,91,79,  col=(0,0,0),filled=False) # set alarm frame
        disp.rect(0,65,90,79,  col=(255,64,64),filled=False) # 
    if watch_highlight == EXIT:
        disp.rect(89,64,159,79,col=(0,0,0),filled=False) # return frame
        disp.rect(90,65,159,79,col=(255,64,64),filled=False) # 

            
    if watch_state == EXIT:
                
        set_minute      = minute
        set_hour        = hour
        set_year        = time_all[0]
        set_month       = time_all[1]
        set_day         = time_all[2]
 

    if watch_state >= SET_TIME_1 and watch_state <= SET_TIME_4:
        show_set_time('%02d%02d'%(set_hour,set_minute),watch_state - SET_TIME_1 + 1)
    else:
        show_set_time('%02d%02d'%(hour,minute),0)
                
                
    if watch_state == SET_DATE_1:
        mini_text("SET YEAR:", 1,36, (255,255,255))
        mini_text("%04d"%(set_year), 93,36, (255,64,64))

    if watch_state == SET_DATE_2:
        mini_text("SET MONTH: ", 1,36, (255,255,255))
        mini_text(months[set_month-1], 103,36, (255,64,64))

    if watch_state == SET_DATE_3:
        mini_text("SET DAY:", 1,36, (255,255,255))
        mini_text("%02d"%(set_day), 83,36, (255,64,64))
            

    if watch_state == SET_ALARM_1:
        if alarm_on:
            mini_text("ALARM IS", 1,36, (255,255,255))
            mini_text("ON!", 81,36, (255,64,64))
        else:
            mini_text("ALARM IS", 1,36, (255,255,255))
            mini_text("OFF!", 81,36, (255,64,64))
                    
    if watch_state == SET_ALARM_2:
        mini_text("ALARM HOUR:", 1,36, (255,255,255))
        mini_text("%02d"%alarm_hour, 111,36, (255,64,64))

    if watch_state == SET_ALARM_3:
        mini_text("ALARM MINUTE:", 1,36, (255,255,255))
        mini_text("%02d"%alarm_minute, 131,36, (255,64,64))

    if watch_state < SET_DATE_1 or watch_state > SET_DATE_3:
        mini_text(   days[  time_all[6]]   , 130,  0, (255,255,255) )
        mini_text( months[  time_all[1]-1] , 130, 10, (255,255,255) )
        mini_text( '%02d'% time_all[2]     , 130, 20, (255,255,255) )

    if watch_state == EXIT or (watch_state>=SET_TIME_1 and watch_state<=SET_TIME_4):
        if alarm_on:
            mini_text("ALARM TIME: %02d:%02d"%(alarm_hour,alarm_minute), 1,36, (255,255,255))
        else:
            mini_text("ALARM IS OFF", 1,36, (255,255,255))

    return
#============================================================== volt to y: calculates y-position for voltage in battery graph
def volt_to_y(voltage,window_height,window_y):

    y_return = (voltage - 3.51)/.56 # 3.51 ... 4.07 -> 0 ... 1
    y_return = 1 - y_return
    y_return = int((y_return * window_height) + window_y)
    y_return = constrain(y_return,window_y,window_y+window_height)
    
    return y_return



############################################################### main



smooth_voltage  = 3.6
hour            = 0
minute          = 0
second          = 0
p_minute        = 0
p_second        = 0
new_minute      = False
time_all        = utime.localtime()

animation           = 0 # fade-in animation goes from 0...20
last_interaction_ms = 0 # time in millis when last interaction happened


p_button_state = 0
button_state = 0


button_left_pressed   = False
button_right_pressed  = False
button_select_pressed = False
repeat_millis = 1000000000

with display.open() as disp:

    #.............. load stuff
        
    load_settings()
    load_weather_log()
        
    #.............. default variable values
    
    minute        = utime.localtime()[4]
        
    while True:

        vibra_tock = 0
        
        #...................................................... timing
        p_second    = second
        p_minute    = minute
        time_all    = utime.localtime()
        second      = time_all[5]
        minute      = time_all[4]
        hour        = time_all[3]
        new_minute  = p_minute != minute
        millis      = utime.monotonic_ms()
        
        #...................................................... gyro
        read_bhi() # updates gyro: gx, gy, gz, gs
        gesture_trigger = check_gesture()
        
        #...................................................... data logging
        if new_minute == True:
            save_weather_log()
            
        #...................................................... voltage
        smooth_voltage = (power.read_battery_voltage() + smooth_voltage*5)/6
        
        #...................................................... adjust display brightness to environment

        target_brightness =(target_brightness *50 + (light_sensor.read()*17 - 180))/51

        if target_brightness < display_brightness-2:
            display_brightness -= 1
        if target_brightness > display_brightness+2:
            display_brightness = int(target_brightness+1)
        display_brightness = constrain(display_brightness,5,100)
        if screen == VOID:
            display_brightness = 0
            target_brightness  = 0

        #...................................................... buttons
        p_button_state = button_state
        button_state = buttons.read(0xFF)

        
        
        button_left_pressed   = (button_state & buttons.BOTTOM_LEFT != 0  and p_button_state == 0)
        button_right_pressed  = (button_state & buttons.BOTTOM_RIGHT != 0 and p_button_state == 0)
        button_select_pressed = (button_state & buttons.TOP_RIGHT != 0    and p_button_state == 0)
        
        if p_button_state != button_state:
            last_interaction_ms = millis
            if button_state !=0:
                repeat_millis = millis + 1200
                vibra.vibrate(8)
                vibra_tock = 10
            else:
                repeat_millis = millis + 10000000
                
        if millis>repeat_millis and button_state != 0: # long button push -> repeated triggers
            last_interaction_ms = millis
            repeat_millis = millis + 250
            vibra_tock = 7
            button_left_pressed   = (button_state & buttons.BOTTOM_LEFT  != 0)
            button_right_pressed  = (button_state & buttons.BOTTOM_RIGHT != 0)
            button_select_pressed = (button_state & buttons.TOP_RIGHT    != 0)

        
        #...................................................... state machine
        if screen != p_screen:
            last_interaction_ms = millis
            
        p_screen = screen

        if (alarm_on == True and
            hour == alarm_hour and
            minute == alarm_minute and
            (watch_state == 0 or (watch_state >=8 and watch_state <=10))):
            screen = ALARM_SCREEN

        if screen == ALARM_SCREEN and (hour != alarm_hour or minute != alarm_minute):
            screen = VOID
     
        if (screen == VOID and ((gesture_trigger               == True) or # wake up: gesture trigger, button press or charging!
                                 (power.read_chargein_voltage() >  4   ) or
                                 (p_button_state != button_state and  button_state!=0))
             ):
            
            screen = TRANSITION
            disp.backlight(display_brightness).update() # backlight on
            last_interaction_ms = millis

        if screen == TRANSITION and animation <  5:
            animation += 1

        if screen == TRANSITION and animation == 5:
            screen = MAIN
            animation  = 0
            last_interaction_ms = millis

        if charging == False and screen!=ALARM_SCREEN: # fall asleep: timeout from main screen if device is not charging
            if millis > (last_interaction_ms + (SLEEP_TIMEOUT *1000)) and screen!=VOID: 
                screen = VOID
                for i in range(display_brightness,0,-1): # backlight fade out
                    disp.backlight(i).update()
                disp.clear().backlight(0).update()

        if screen == VOID:
            highlighted = VOID

        if screen != MAIN:
            p_day  = 0    # sets previous day in month to zero -> will force the date to be shown on main screen after wake up transition
            selected = VOID
            highlighted = VOID

        #...................................................... button actions imu screen

        if screen == IMU:
            if button_select_pressed or button_right_pressed == True or button_left_pressed == True:
                screen = TRANSITION
                animation =0


        #...................................................... button actions weather screen

        if screen == WEATHER:
            if button_right_pressed == True:
                weather_screen += 1
                
            if button_left_pressed == True:
                weather_screen -= 1
                
            weather_screen = weather_screen % 2
            
            if button_select_pressed:
                screen = TRANSITION
                animation =0
                
        #...................................................... button actions power manager

        if screen == BATTERY:
            if button_right_pressed == True:
                power_manager_screen += 1
                        

            if button_left_pressed == True:
                power_manager_screen -= 1

            power_manager_screen = power_manager_screen%2
                    
            if button_select_pressed == True:
                screen = TRANSITION
                animation =0
                
        #...................................................... button actions date / calendar screen

        if screen == DATE:
            if button_right_pressed == True:
                calendar_month += 1
                if calendar_month>12:
                    calendar_month = 1
                    calendar_year += 1
                        

            if button_left_pressed == True:
                calendar_month -= 1
                if calendar_month<1:
                    calendar_month = 12
                    calendar_year -= 1
                    

            if button_select_pressed == True:
                screen = TRANSITION
                animation =0

                    
        #...................................................... button actions alarm screen

        if screen == ALARM_SCREEN:
            if button_right_pressed or button_left_pressed or button_select_pressed:
                screen = TRANSITION
                animation =0
                alarm_on = False
                save_settings()
                
        #...................................................... button actions main screen

        if screen == MAIN:

            if selected == LAUNCHER:
                
                if button_right_pressed == True:
                    launch_selection += 1
                if button_left_pressed == True:
                    launch_selection -= 1
                if button_select_pressed == True:

                    # try loading app
                    load_app = all_apps[ launch_selection % max_apps ]
                    if load_app[-4:] == '.elf':
                        load_app = '/apps/'+load_app
                        print("NOT loading " + load_app)
                        #disp.clear().update()
                        #os.exec(load_app)
                        vibra.vibrate(20)                   # my current card10 doesn't support .elf
                    else:
                        load_app = '/apps/'+load_app+"/__init__.py"
                        print("loading " + load_app)
                        for i in range(display_brightness,0,-1): # backlight fade out
                            disp.backlight(i).update()
                        disp.clear().update()
                        utime.sleep_ms(20)
                        save_settings()
                        disp.backlight(display_brightness).update()
                        os.exec(load_app)
                        
            if selected != LAUNCHER:
                if button_right_pressed == True: # right button: move clockwise through items
                    
                    if highlighted == VOID:
                        highlighted   = LAUNCHER
                    else:
                        highlighted = (highlighted + 1)%6

                if  button_left_pressed == True: # left button: move counter-clockwise through items
                    if highlighted  == VOID:
                        highlighted   = LAUNCHER
                    else:
                        highlighted = (highlighted - 1)%6
                

                if button_select_pressed == True: # select - top right:
                    selected = highlighted
                    
                    if highlighted == WATCH: 
                        screen = WATCH
                        selected = VOID
                        highlighted = VOID

                    if highlighted == DATE: 
                        screen = DATE
                        selected = VOID
                        highlighted = VOID

                    if highlighted == BATTERY: 
                        screen = BATTERY
                        selected = VOID
                        highlighted = VOID
                        power_manager_screen = CHARGE_CURVE

                    if highlighted == WEATHER: 
                        screen = WEATHER
                        selected = VOID
                        highlighted = VOID

                    if highlighted == IMU: 
                        screen = IMU
                        selected = VOID
                        highlighted = VOID
                        
                    if highlighted == VOID: # quick access to launcher from void
                        selected  = LAUNCHER
                        highlighted = LAUNCHER
                
            if millis > last_interaction_ms + 5000 and highlighted != VOID: # timeout from selection
                highlighted = VOID
                selected  = VOID
                vibra_tock = 6
                save_settings()
            
        #...................................................... button actions watch screen

        elif screen == WATCH and p_screen==WATCH:
            
            if watch_state == EXIT: # exit -> return to main
                if button_left_pressed:
                    watch_highlight = (watch_highlight-1)%4
                if button_right_pressed:
                    watch_highlight = (watch_highlight+1)%4
                    
                if button_select_pressed:
                    if watch_highlight == EXIT:
                        disp.clear()
                        screen = MAIN
                        
                    if watch_highlight == SET_TIME:
                        watch_state = SET_TIME_1
                        button_select_pressed = False
                        
                    if watch_highlight == SET_DATE:
                        watch_state = SET_DATE_1
                        button_select_pressed = False
                        
                    if watch_highlight == SET_ALARM:
                        watch_state = SET_ALARM_1
                        button_select_pressed = False
                        
                        
            if watch_state == SET_TIME_1: # set 1st digit of hour
                if button_left_pressed:
                    h1 = set_hour//10
                    h2 = set_hour%10
                    h1 = (h1 - 1)%2
                    set_hour = h1*10+h2
                    
                if button_right_pressed:
                    h1 = set_hour//10
                    h2 = set_hour%10
                    h1 = (h1 + 1)%2
                    set_hour = h1*10+h2
                    
                if button_select_pressed:
                    watch_state = SET_TIME_2
                    button_select_pressed = False
            
            if watch_state == SET_TIME_2: # set 2nd digit of hour
                if button_left_pressed:
                    h1 = set_hour//10
                    h2 = set_hour%10
                    h2 = (h2 - 1)%10
                    set_hour = h1*10+h2
                    
                if button_right_pressed:
                    h1 = set_hour//10
                    h2 = set_hour%10
                    h2 = (h2 + 1)%10
                    set_hour = h1*10+h2
                    
                if button_select_pressed:
                    watch_state = SET_TIME_3
                    button_select_pressed = False
                    
            if watch_state == SET_TIME_3: # set 3rd digit of hour
                if button_left_pressed:
                    m1 = set_minute//10
                    m2 = set_minute%10
                    m1 = (m1 - 1)%6
                    set_minute = m1*10+m2
                    
                if button_right_pressed:
                    m1 = set_minute//10
                    m2 = set_minute%10
                    m1 = (m1 + 1)%6
                    set_minute = m1*10+m2
                    
                if button_select_pressed:
                    watch_state = SET_TIME_4
                    button_select_pressed = False
                    
            if watch_state == SET_TIME_4: # set 4th digit of hour
                if button_left_pressed:
                    m1 = set_minute//10
                    m2 = set_minute%10
                    m2 = (m2 - 1)%10
                    set_minute = m1*10+m2
                    
                if button_right_pressed:
                    m1 = set_minute//10
                    m2 = set_minute%10
                    m2 = (m2 + 1)%10
                    set_minute = m1*10+m2
                    
                if button_select_pressed: # save new time, return to exit
                    minute = set_minute
                    hour   = set_hour                    
                    utime.set_time(utime.mktime((time_all[0],time_all[1],time_all[2],set_hour,set_minute,0,time_all[6],time_all[7])))

                    watch_highlight = SET_DATE
                    watch_state     = EXIT
                    button_select_pressed = False
                    
            if watch_state == SET_DATE_1: # set year
                if button_left_pressed:
                    set_year -= 1
                    
                if button_right_pressed:
                    set_year += 1
                set_year = constrain(set_year,2019,3000)
                    
                if button_select_pressed:
                    watch_state = SET_DATE_2
                    button_select_pressed = False

                    
            if watch_state == SET_DATE_2: # set month
                if button_left_pressed:
                    set_month -= 1
                    
                if button_right_pressed:
                    set_month += 1
                    
                set_month = ((set_month-1) % 12)+1
                    
                if button_select_pressed:
                    watch_state = SET_DATE_3
                    button_select_pressed = False
                    
                    
            if watch_state == SET_DATE_3: # set day
                
                max_feb = 28
                if set_year %4 == 0:
                    max_feb = 29
                max_day = (31,max_feb,31,30,31,30,31,31,30,31,30,31)
                
                if button_left_pressed:
                    set_day -= 1
                    
                if button_right_pressed:
                    set_day += 1

                set_day = ((set_day-1) % max_day[set_month-1]) +1
                    
                if button_select_pressed:# save new date, return to exit
                   
                    utime.set_time(utime.mktime((set_year,set_month,set_day,time_all[3],time_all[4],time_all[5],time_all[6],time_all[7])))

                    watch_highlight = EXIT
                    watch_state     = EXIT
                    button_select_pressed = False


            if watch_state == SET_ALARM_1: # alarm on / off
                    
                if button_left_pressed or button_right_pressed:
                    alarm_on = (alarm_on==False)
                    
                if button_select_pressed:
                    if alarm_on == False:
                        watch_state = EXIT
                        watch_highlight = EXIT
                        save_settings()
                        button_select_pressed = False
                    else:
                        watch_state = SET_ALARM_2
                        button_select_pressed = False
                            
            if watch_state == SET_ALARM_2: # alarm hours
                    
                if button_left_pressed:
                    alarm_hour -=1
                if button_right_pressed:
                    alarm_hour +=1
                alarm_hour = alarm_hour % 24
                
                if button_select_pressed:
                    watch_state = SET_ALARM_3
                    button_select_pressed = False

            if watch_state == SET_ALARM_3: # alarm minutes
                    
                if button_left_pressed:
                    alarm_minute -=1
                if button_right_pressed:
                    alarm_minute +=1
                alarm_minute = alarm_minute % 60
                
                if button_select_pressed:
                    watch_state     = EXIT
                    watch_highlight = EXIT
                    save_settings()
                    button_select_pressed = False
                        
        #...................................................... draw stuff on screen
        if screen == TRANSITION:
            disp.clear()
            b = animation * 63
            show_time(        0,                        animation*animation*2-32,   (b,b,b), wireframe = True) #............. time 
            show_battery(     0,                        16-animation*animation,     (b,b,b), wireframe = True) #............. battery (has to be drawn before air pressure log & microlauncher!)
            show_weather_log( 0,                        animation*animation-16,     (b,b,b), wireframe = True) #............. barometer log + humidity
            show_compass(     16-animation*animation,   0,                          (b,b,b), wireframe = True) #............. compass
            show_launcher(    0,                        32-animation*animation*2,   (b,b,b), wireframe = True) #............. microlauncher

        #`````````````````````````````````````````````````````` draw main screen    
        if screen == MAIN:
            if selected!=LAUNCHER:
                show_time       ( 0,0,color = color_select(WATCH)   ) #............. time
                show_date       ( 0,0,color = color_select(DATE))     #............. date                 show_battery    ( 0,0,color = color_select(BATTERY))  #............. battery (has to be drawn before air pressure log & microlauncher!)
                show_battery    ( 0,0,color = color_select(BATTERY))  #............. battery (has to be drawn before air pressure log & microlauncher!)
                show_weather_log( 0,0,color = color_select(WEATHER))  #............. barometer log + humidity
                show_compass    ( 0,0,color = color_select(IMU)     ) #............. compass 
                show_launcher   ( 0,0,color = color_select(LAUNCHER)) #............. microlauncher
            else:
                show_time       ( 0,0,color = (255,64,64))            #............. time
                show_date       ( 0,0,color = (255,64,64))            #............. date 
                show_battery    ( 0,0,color = (255,64,64))            #............. battery (has to be drawn before air pressure log & microlauncher!)
                show_weather_log( 0,0,color = (255,64,64))            #............. barometer log + humidity
                show_compass    ( 0,0,color = (255,64,64))            #............. compass 
                show_launcher   ( 0,0,color = (255,255,255))          #............. microlauncher

        #`````````````````````````````````````````````````````` draw void screen
        if screen == VOID:
            display_brightness = 0
            disp.backlight(0).clear()

        
        #`````````````````````````````````````````````````````` draw watch / set time, date screen             
        if screen == WATCH: 
            
            disp.clear()
            show_set_watch_screen()
                    
        #`````````````````````````````````````````````````````` draw alarm screen
        if screen == ALARM_SCREEN:
            show_alarm_screen()
            
        #`````````````````````````````````````````````````````` draw date / calendar screen
        if screen == DATE:
            show_calendar()
            
        #`````````````````````````````````````````````````````` draw battery screen
        if screen == BATTERY:
            show_power_manager()

        #`````````````````````````````````````````````````````` draw weather screen
        if screen == WEATHER:
            show_weather()
            
        #`````````````````````````````````````````````````````` draw inertial measurement unit screen
        if screen == IMU:
            show_imu()
        #...................................................... leds
        if alarm_on == True:
            b=170-abs(((millis//5)%1000)-500)//3
            leds.prep(0, (b,int(b*.9),b))
        else:
            leds.prep(0, (0,0,0))


        leds.update()
                
        #...................................................... vibra tocks        
        if vibra_tock >0:
            vibra.vibrate(vibra_tock)

        #disp.print('t: %i b: %i    '%(target_brightness,display_brightness),fg=(255,255,255),bg=(0,0,0))
            
        #...................................................... update screen            
        disp.backlight(display_brightness).update()
        

        

	
