# mPy - print / plot normalised LDR light intensity.
# copyright by Anthony Vogelaar, Perth Scotland
# rev 0.10  2025-04-30  initial release

# https://docs.micropython.org/en/latest/esp32/quickref.html

import	time
import	json
from	machine		import	Pin, ADC

PLOTTER = False

# ==================== hardware =========================

ldr    = ADC(35, atten=ADC.ATTN_11DB)		# 0.15 .. 2.45V
btn000 = Pin(14, Pin.IN, Pin.PULL_UP)		# red    button calibrate   0%
btn100 = Pin(27, Pin.IN, Pin.PULL_UP)		# yellow button calibrate 100%

# ====================== Button =========================

# debounce button class
class Button:
    
    def __init__(self, btn):				# btn is instance of Pin
        self.btn   = btn
        self.count = 0						# debounce counter
        
        
    # call repeatedly ex @ 50 mSec
    def exe(self):
        if self.btn():						# if not pressed
            self.count = 0					
        elif self.count < 3:				# else pressed
            self.count += 1
            if self.count == 3: return True	# three consecutive samples low
                                            # else return None
# ====================== Main ===========================

# print / plot normalised light intensisy
class Main:
    
    def __init__(self):
        self.btn_000   = Button(btn000)				# Button Red      0%
        self.btn_100   = Button(btn100)				# Button Yellow 100%
#       self.level_000 = 0							# default parameters
#       self.level_100 = 4095
        self.loadPars()								# load default parameters
        print('level_000:', self.level_000)			# debug info
        print('level_100:', self.level_100, '\n')
        while True:
            self.exe50()
            time.sleep_ms(50)


    # load default parameters from file 'pars.json'
    def loadPars(self):
        try:
            with open('pars.json', 'r') as f:
                pars = json.load(f)
            lo = pars['low']
            assert isinstance(lo, int) and 0 <= lo <= 4095
            hi = pars['high']
            assert isinstance(hi, int) and 0 <= hi <= 4095
            assert lo != hi
            self.level_000 = lo						# default parameters
            self.level_100 = hi
        except:
            print('Data error in pars.json')
            self.level_000 = 0						# default values
            self.level_100 = 4095
        

    # save default parametrs in file 'pars.json'
    def savePars(self):
        d = dict(low=self.level_000, high=self.level_100)
        with open('pars.json', 'w') as f:
            json.dump(d, f)


    # called @ 20 Hz / 50 mSec. Reading buttons and print / plot light intensity
    def exe50(self):
        y1 = ldr.read()								# light intensity 0..4095
        y2 = int(100 * (y1 - self.level_000) / (self.level_100 - self.level_000))	# normalised 0..100
        if self.btn_000.exe():						# calibrate   0% at button red    press
            self.level_000 = y1
            self.savePars()
        if self.btn_100.exe():						# calibrate 100% at button yellow press
            self.level_100 = y1
            self.savePars()
        print(y2) if PLOTTER else print(f'{y2:4}', end='')
                    
                    
try:
    Main()
except KeyboardInterrupt:
    print('\nTerminated')

# ======================= end ===========================
