####
# Test script for functional testing
# DHBW Security Testing Micropython Hardware
#
# just execute non-persisten on ESP32 target
# e.g. ampy -p /dev/ttyUSB0 run dhbw_esp32_function_test.py
#
# A vfat formated sd-card must be present!
#
# Following python code must be persisten on target,
# to run this test script
# * bmp180.py
# * sdcard.py
#
# Copyright 2020 by Christopher Scheuring <chris@aucmail.de>
# License: GPLv3 (https://www.gnu.org/licenses/gpl-3.0.de.html)
#
####

import machine, time, gc, sdcard, os, esp32
from machine import Pin, ADC, I2C, SPI
from bmp180 import BMP180


####
# Simple Button and LED test
# yellow led will blink
# red + green will be off button is pressed
# runs 10 time and waits for next test

print("Run Button and LED Test (5 times):")

gc.collect() # make some room

## define led pins
led_gr_p = 21
led_re_p = 22
led_ye_p = 17

## define switch pins
sw1_p = 32
sw2_p = 33


## init leds
led_gr = Pin(led_gr_p, Pin.OUT)
led_gr.off() # switch on led - inverted logic!

led_re = Pin(led_re_p, Pin.OUT)
led_re.off() # switch on led - inverted logic!

led_ye = Pin(led_ye_p, Pin.OUT)
led_ye.off() # switch on led - inverted logic!


## int buttons (pull-up)
sw1 = Pin(sw1_p, Pin.IN)
sw2 = Pin(sw2_p, Pin.IN)

cnt = 0
while cnt < 5:
	if sw1.value():
		print("  SW1 true")
		led_re.on()
	else:
		print("  SW1 false")
		led_re.off()
	if sw2.value():
		print("  SW2 true")
		led_gr.on()
	else:
		print("  SW2 false")
		led_gr.off()
	
	# toggle led
	if led_ye.value():
		led_ye.off();
	else:
		led_ye.on();

	cnt = cnt + 1
	time.sleep(0.5)

print("Finished Button and LED Test")
time.sleep(1)


####
# Simple Fotoresistor Test
# Just displays the changed values for 10 times testing

print("Run Fotoresistor Test (10 times):")

gc.collect() # make some room

adc = ADC(Pin(34)) # create an ADC object acting on a pin
adc.atten(ADC.ATTN_11DB) # 3.3V max

cnt = 0
while cnt < 10:
     print("  Analog Value: " , adc.read())
     cnt = cnt + 1
     time.sleep(0.5)

print("Finished Fotoresistor Test.")
time.sleep(1)

####
# Simple BMP180 Test
# Just displays the read values 5 times testing

print("Run BMP180 Test (5 times):")

gc.collect() # make some room

try:
	i2c = I2C(1, scl=Pin(25), sda=Pin(26), freq=100000)

	bmp180 = BMP180(i2c)
	#bmp180.oversample_sett = 2
	#bmp180.baseline = 101325

	cnt = 0
	while cnt < 5:
	    print(" temperature: ", bmp180.temperature, " air pressure: ", bmp180.pressure, " altitude: ", bmp180.altitude)
	    cnt = cnt + 1
	    time.sleep(0.5)

	print("Finished BMP180 Test.")
	time.sleep(1)

except:
	print("*** ERROR BMP180 Test - I2C not working ***")


####
# Simple SD-Card Test
# Just opens the SD-Card, adds a file and prints the dir listing

print("Run SD-Card Test:")

gc.collect() # make some room

try:
	spi = SPI(2, baudrate=10000000, polarity=0, phase=0, sck=machine.Pin(18), mosi=machine.Pin(23), miso=machine.Pin(19))
	sd = sdcard.SDCard(spi, machine.Pin(5))

	os.mount(sd, '/sd')

	def print_directory(path, tabs = 0):
	    for file in os.listdir(path):
	        stats = os.stat(path+"/"+file)
	        filesize = stats[6]
	        isdir = stats[0] & 0x4000
	    
	        if filesize < 1000:
	            sizestr = str(filesize) + " by"
	        elif filesize < 1000000:
	            sizestr = "%0.1f KB" % (filesize/1000)
	        else:
	            sizestr = "%0.1f MB" % (filesize/1000000)
	    
	        prettyprintname = ""
	        for i in range(tabs):
	            prettyprintname += "   "
	        prettyprintname += file
	        if isdir:
	            prettyprintname += "/"
	        print('{0:<40} Size: {1:>10}'.format(prettyprintname, sizestr))
	        
	        # recursively print directory contents
	        if isdir:
	            print_directory(path+"/"+file, tabs+1)

	with open("/sd/hello.txt", "w") as f:
	    f.write("Hello world!\r\n")

	print("Files on filesystem:")
	print("====================")
	print_directory("/sd")
	print("")

	print("Finished SD-Card Test.")
except:
	print("*** ERROR SD-Card Test - Missing SD-Card or write fail ***")

time.sleep(1)


####
# Simple KeyPad Test
# Checks the pressed buttons

print("Run KeyPad Test - finish by pressing \"#\":")

gc.collect() # make some room

# Set up LED on pin 17
led_pin = 17

led = Pin(led_pin, Pin.OUT)
led.on() # switch off led - inverted logic!

# Set up Rows
rows = []
for p in [13, 12, 14, 27]:
    row = Pin(p, Pin.OUT)
    rows.append(row)
# anodes OFF
for i in range(4):
    rows[i].off()

# Set up columns
cols = []
for p in [15, 02, 04, 16]:
    col = Pin(p, Pin.IN, Pin.PULL_DOWN)
    cols.append(col)

def getkey():  # Returns -999 or key value
    values = [1,2,3,10, 4,5,6,11, 7,8,9,12, 14,0,15,13]
    val = -999 # Error value for no key press
    for count in range(10): # Try to get key press 10 times
        for r in range(4):  # Rows, one at a time
            rows[r].on() # row HIGH
            for c in range(4): # Test columns, one at a time
                if cols[c].value() == 1: # Is column HIGH?
                    p = r * 4 + c      # Pointer to values list
                    val = values[p]
                    count = 11 # This stops looping
                    led.off() # Flash LED ON if key pressed
            rows[r].off() # row LOW
    time.sleep(0.2) # Debounce
    led.on() # LED OFF
    return val

def getvalue(digits): # Number of digits
    result = 0
    count = 0
    while True:
        x = getkey()
        if x != -999 and x < 10: # Check if numeric key pressed
            result = result * 10 + x
            print(result)
            count = count + 1
        if count == digits:
            return result

# +++++ Main +++++
print("Press 4 numeric (BLUE) keys")
y = getvalue(4)
print('\n',y)

print("\nPress any of the keys\n # halts the program")

characters =["1","2","3","4","5","6","7","8","9","A","B","C","D","*","#","0"]
running = True
while running:
    x = getkey()
    if x != -999: # A key has been pressed!
        print(characters[x-1])
        if x == 15:
            running = False
            
led.on()

print("Finished KeyPad Test - noting to do anymore.")