forked from MichaelKirsch/KintaroSnes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pcb.py
executable file
·194 lines (163 loc) · 7.83 KB
/
pcb.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#!/usr/bin/python3
#Copyright 2017 Michael Kirsch
#Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
#to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
# and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
#The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
import configparser
import time
import os
import ASUS.GPIO as GPIO
import subprocess
from configparser import SafeConfigParser
from enum import Enum
class SNES:
def __init__(self):
#GPIOs
self.led_pin=7
self.fan_pin=8
self.reset_pin=3
self.power_pin=5
self.check_pin=10
#vars
self.fan_hysteresis = 5
self.fan_starttemp = 60
self.fan_hysteresis_pwm = 20
self.fan_starttemp_pwm = 60
self.reset_hold_short = 100
self.reset_hold_long = 500
self.debounce_time = 0.1
self.counter_time = 0.01
self.delay_until_reset = 2
self.is_pwm = False
#path
self.kintaro_folder = "/opt/KintaroSnes/"
self.start_folder = "start/"
self.intro_video = self.kintaro_folder + self.start_folder + "intro.mp4"
self.config_file = self.kintaro_folder + self.start_folder + "kintaro.config"
# self.temp_command = 'vcgencmd measure_temp'
#Set the GPIOs
GPIO.setmode(GPIO.BOARD) # Use the same layout as the pins
GPIO.setwarnings(False)
GPIO.setup(self.led_pin, GPIO.OUT) # LED Output
GPIO.setup(self.fan_pin, GPIO.OUT) # Fan normal Output
GPIO.setup(self.power_pin, GPIO.IN) # set pin as input
GPIO.setup(self.reset_pin, GPIO.IN,
pull_up_down=GPIO.PUD_UP) # set pin as input and switch on internal pull up resistor
GPIO.setup(self.check_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
if self.return_config_bool("PWM_FAN"):
self.is_pwm = True
self.pwm=GPIO.PWM(self.fan_pin,50)
self.pwm.start(0)
def power_interrupt(self, channel):
time.sleep(self.debounce_time) # debounce
if GPIO.input(self.power_pin) == GPIO.HIGH and GPIO.input(
self.check_pin) == GPIO.LOW: # shutdown function if the powerswitch is toggled
self.led(0) # led and fan off
os.system("killall emulationstation") #end emulationstation
self.blink(20, 0.1) #wait for the metadata to be safed
self.fan(0)
os.system("sudo shutdown -h now")
def reset_interrupt(self, channel):
if GPIO.input(self.reset_pin) == GPIO.LOW: # reset function
reset_counter = 0 # counter for the time funktion
time.sleep(self.debounce_time) # debounce time
while GPIO.input(self.reset_pin) == GPIO.LOW: # while the button is hold the counter counts up
reset_counter = reset_counter + 1
time.sleep(self.counter_time)
if reset_counter > self.reset_hold_short: # check if its hold more that one second
if reset_counter <= self.reset_hold_long: # if you hold it less than 5 sec it will toggle the fan
self.change_config_value("fan")
self.blink(3, 0.5)
self.led(1)
if reset_counter > self.reset_hold_long: # if you hold it more than 5 seconds if will toggle the bootupvideo
self.change_config_value("video")
self.blink(10, 0.5)
self.led(1)
else:
os.system("killall emulationstation")
self.blink(15, 0.1)
os.system("sudo reboot")
def pcb_interrupt(self, channel):
GPIO.cleanup() # when the pcb is pulled clean all the used GPIO pins
def temp(self): # read tinkerboard temperature
# there are 2 thermal zones (0 and 1) but they are usually the same
with open('/sys/class/thermal/thermal_zone0/temp', 'r') as myfile:
temp = float(myfile.read().replace('\n','')) / 1000
print('polling temp:{}C'.format(temp))
return temp
def led(self,status): #toggle the led on of off
if status == 0: #the led is inverted
GPIO.output(self.led_pin, GPIO.LOW)
if status == 1:
GPIO.output(self.led_pin, GPIO.HIGH)
def blink(self,amount,interval): #blink the led
for x in range(amount):
self.led(1)
time.sleep(interval)
self.led(0)
time.sleep(interval)
def return_config_bool(self,searchterm):
Config = configparser.ConfigParser()
Config.read(self.config_file) # read the configfile
return Config.getboolean("Boot", searchterm)
def fan(self,status): #switch the fan on or off
if status == 1:
GPIO.output(self.fan_pin, GPIO.HIGH)
if status == 0:
GPIO.output(self.fan_pin, GPIO.LOW)
def fancontrol_normal(self,hysteresis,starttemp): #read the temp and have a buildin hysteresis
if self.temp() > starttemp:
self.fan(1)
if self.temp() < starttemp-hysteresis:
self.fan(0)
def pwm_fancontrol(self,hysteresis, starttemp, temp):
perc = 100.0 * ((temp - (starttemp - hysteresis)) / (starttemp - (starttemp - hysteresis)))
perc=float(min(max(perc, 0.0), 100.0))
print('PWM duty cycle: {}'.format(perc))
self.pwm.ChangeDutyCycle(perc)
def change_config_value(self,toggle_this): #change one of the values in the config file
parser = configparser.ConfigParser()
parser.read(self.config_file)
if self.return_config_bool(toggle_this):
parser.set('Boot', toggle_this, "False")
self.fan(0)
else:
parser.set('Boot', toggle_this, "True")
with open(self.config_file, "w+") as configfile:
parser.write(configfile)
def check_video(self):
if self.return_config_bool("video"):
os.system("omxplayer " + self.intro_video + " &") # start the bootvideo on start
def check_fan(self):
if self.return_config_bool("fan"): # check if the fan is activated in the config
if self.is_pwm:
self.pwm_fancontrol(self.fan_hysteresis_pwm,self.fan_starttemp_pwm,self.temp())
else:
self.fancontrol_normal(self.fan_hysteresis,self.fan_starttemp) # fan starts at 60 degrees and has a 5 degree hysteresis
def attach_interrupts(self):
if self.return_config_bool("pcb") and GPIO.input(self.check_pin) == GPIO.LOW: # check if there is an pcb and if so attach the interrupts
GPIO.add_event_detect(self.check_pin, GPIO.RISING,callback=self.pcb_interrupt) # if not the interrupt gets attached
if GPIO.input(self.power_pin) == GPIO.HIGH: #when the system gets startet in the on position it gets shutdown
print('shutting down')
os.system("sudo shutdown -h now")
else:
self.led(1)
GPIO.add_event_detect(self.reset_pin, GPIO.FALLING, callback=self.reset_interrupt)
GPIO.add_event_detect(self.power_pin, GPIO.RISING, callback=self.power_interrupt)
else: #no pcb attached so lets exit
print('no PCB detected')
GPIO.cleanup()
exit()
print('starting')
snes = SNES()
snes.attach_interrupts()
snes.check_video()
print('ready')
if snes.return_config_bool("fan"):
# kickstart the fan to get it spinning and prevent burning it out
snes.pwm.ChangeDutyCycle(100)
while True:
time.sleep(5)
snes.led(1)
snes.check_fan()