|
| 1 | +import network |
| 2 | +import ujson |
| 3 | +import machine |
| 4 | +import os |
| 5 | +import ure |
| 6 | +import gc |
| 7 | +try: |
| 8 | + import usocket as socket |
| 9 | +except: |
| 10 | + import socket |
| 11 | +from utime import ticks_ms |
| 12 | +from utime import sleep |
| 13 | + |
| 14 | +from nxp_periph import PCA9956B, PCA9955B, PCA9632, PCA9957, LED |
| 15 | +from nxp_periph import PCT2075, LM75B, P3T1755, P3T1085 |
| 16 | +from nxp_periph import PCF2131, PCF85063 |
| 17 | +from nxp_periph import PCAL6408, PCAL6416, PCAL6524, PCAL6534 |
| 18 | +from nxp_periph import FXOS8700, FXLS8974 |
| 19 | +from nxp_periph import NAFE13388 |
| 20 | +from nxp_periph import i2c_fullscan |
| 21 | + |
| 22 | +from demo_lib import DUT_LEDC, DUT_TEMP, DUT_RTC, DUT_GPIO, DUT_ACC, DUT_AFE |
| 23 | +from demo_lib import DUT_GENERALCALL, General_call |
| 24 | +from demo_lib import DUT_base |
| 25 | + |
| 26 | +from demo_lib.I2C_Character_LCD import AE_AQM0802 |
| 27 | + |
| 28 | +NETWORK_TIMEOUT = False |
| 29 | +MEM_MONITORING = False |
| 30 | +# MEM_MONITORING = True ### |
| 31 | + |
| 32 | +def demo( ip = "dhcp" ): |
| 33 | + print( "remote device demo" ) |
| 34 | + print( " http server is started working on " + os.uname().machine ) |
| 35 | + print( "" ) |
| 36 | + |
| 37 | + src_dir = "demo_lib/" |
| 38 | + regex_file = ure.compile( r"GET /(\S+)\sHTTP" ) |
| 39 | + regex_suffix = ure.compile( r".*\.(.*)" ) |
| 40 | + |
| 41 | + |
| 42 | + if "i.MX RT1170 EVK" in os.uname().machine: |
| 43 | + i2c = machine.I2C( 2, freq = (400_000) ) |
| 44 | + spi = machine.SPI( 0, 1000_000, cs = 0 ) |
| 45 | + si2c = machine.I2C( 0, freq = (400_000) ) |
| 46 | + ep_num = 1 # Ethernet port selection. 1 for 1G port, 0 for 100M port |
| 47 | + else: |
| 48 | + i2c = machine.I2C( 0, freq = (400_000) ) |
| 49 | + #spi = machine.SPI( 0, 1000_000, cs = 0 ) |
| 50 | + |
| 51 | + # for NAFE13388 |
| 52 | + spi = machine.SPI( 0, 1000_000, cs = 0, phase = 1 ) |
| 53 | + |
| 54 | + si2c = machine.SoftI2C( sda = "D14", scl = "D15", freq = (400_000) ) |
| 55 | + ep_num = 0 |
| 56 | + |
| 57 | + devices = [ |
| 58 | +# PCA9956B( i2c, 0x02 >>1 ), |
| 59 | +# PCA9956B( i2c, 0x04 >>1 ), |
| 60 | +# PCA9955B( i2c, 0x06 >>1 ), |
| 61 | +# PCA9955B( i2c, 0x08 >>1 ), |
| 62 | +# PCA9955B( i2c, 0xBC >>1 ), |
| 63 | +# PCA9632( i2c ), |
| 64 | +# PCA9957( spi, setup_EVB = True ), |
| 65 | +# PCT2075( i2c, setup_EVB = True ), |
| 66 | +# PCF2131( i2c ), |
| 67 | +# PCAL6408( i2c, 0x21, setup_EVB = True ), |
| 68 | +# PCAL6416( i2c, 0x20, setup_EVB = True ), |
| 69 | +# PCAL6524( i2c, 0x22, setup_EVB = True ), |
| 70 | +# PCAL6534( i2c, 0x22, setup_EVB = True ), |
| 71 | +# PCF2131( spi ), |
| 72 | +# PCF85063( i2c ), |
| 73 | +# P3T1085( si2c ), |
| 74 | +# FXLS8974( i2c, address = 0x18 ), |
| 75 | + NAFE13388( spi ), |
| 76 | +# FXLS8974( i2c, address = 0x18 ), |
| 77 | + FXOS8700( i2c ), |
| 78 | + P3T1755( i2c ), |
| 79 | + General_call( i2c ), |
| 80 | + ] |
| 81 | + |
| 82 | + demo_harnesses = [ DUT_LEDC, |
| 83 | + DUT_TEMP, |
| 84 | + DUT_RTC, |
| 85 | + DUT_GPIO, |
| 86 | + DUT_ACC, |
| 87 | + DUT_AFE, |
| 88 | + DUT_GENERALCALL, |
| 89 | + ] |
| 90 | + |
| 91 | + lcd_panel = AE_AQM0802( si2c ) |
| 92 | + lcd_panel.print( [ "Hello", "mikan" ] ) |
| 93 | + |
| 94 | + dut_list = get_dut_list( devices, demo_harnesses ) |
| 95 | + |
| 96 | +# for d in dut_list: |
| 97 | +# print( d.info ) |
| 98 | + |
| 99 | +# for i in i2c_fullscan( i2c ): |
| 100 | +# print( "0x%02X (0x%02X)" % ( i, i << 1 ) ) |
| 101 | + |
| 102 | + ip_info = start_network( port = ep_num, ifcnfg_param = ip, lcd = lcd_panel ) |
| 103 | +# print( ip_info ) |
| 104 | + |
| 105 | + s = socket.socket() |
| 106 | + |
| 107 | + if NETWORK_TIMEOUT: |
| 108 | + s.settimeout( 1000 ) |
| 109 | + |
| 110 | + ai = socket.getaddrinfo( "0.0.0.0", 80 ) |
| 111 | + addr = ai[0][-1] |
| 112 | + |
| 113 | + s.setsockopt( socket.SOL_SOCKET, socket.SO_REUSEADDR, 1 ) |
| 114 | + s.bind( addr ) |
| 115 | + s.listen( 10 ) |
| 116 | + print("Listening, connect your browser to http://{}/".format( ip_info[0] )) |
| 117 | + |
| 118 | + lcd_panel.print( f"{ip_info[0]}" ) |
| 119 | + |
| 120 | + count = 0 |
| 121 | + |
| 122 | + while True: |
| 123 | + if NETWORK_TIMEOUT: |
| 124 | + try: |
| 125 | + client_stream, client_addr = s.accept() |
| 126 | + except: |
| 127 | + # print( "*", end = "" ) |
| 128 | + continue |
| 129 | + else: |
| 130 | + client_stream, client_addr = s.accept() |
| 131 | + |
| 132 | + e_time = elapsed_time( ticks_ms() ) ### |
| 133 | + # e_time.enable = True |
| 134 | + |
| 135 | + lcd_panel.backlight( False ) |
| 136 | + |
| 137 | + print( f"[{count}] : client address: {client_addr} / socket: {client_stream}" ) |
| 138 | + count += 1 |
| 139 | + |
| 140 | + try: |
| 141 | + req = client_stream.readline() |
| 142 | + except: |
| 143 | + print( "ECONNABORTED" ) |
| 144 | + client_stream.close() |
| 145 | + continue |
| 146 | + |
| 147 | + e_time.show( "readline done" ) ### |
| 148 | + print( "Request: \"{}\"".format( req.decode()[:-2] ) ) |
| 149 | + |
| 150 | + server = "mikan" |
| 151 | + content_type = "text/html" |
| 152 | + |
| 153 | + for dut in dut_list: |
| 154 | + html = dut.parse( req ) |
| 155 | + if html: |
| 156 | + break |
| 157 | + |
| 158 | + if not html: |
| 159 | + m = regex_file.match( req ) |
| 160 | + if m and (fn := m.group( 1 ).decode()): |
| 161 | + try: |
| 162 | + ext = regex_suffix.match( fn ).group( 1 ) |
| 163 | + content_type = ext_content[ ext ] |
| 164 | + except: |
| 165 | + pass |
| 166 | + |
| 167 | + try: |
| 168 | + with open( src_dir + fn, "rb" ) as f: |
| 169 | + html = f.read() |
| 170 | + except OSError as e: |
| 171 | + html = None |
| 172 | + |
| 173 | + elif "GET / " in req: |
| 174 | + html = page_setup( dut_list, i2c, live_only = True if "?live_only=True" in req else False ) |
| 175 | + else: |
| 176 | + html = "" |
| 177 | + |
| 178 | + while True: |
| 179 | + h = client_stream.readline() |
| 180 | + if h == b"" or h == b"\r\n": |
| 181 | + break |
| 182 | + |
| 183 | + send_response( client_stream, html, content_type ) |
| 184 | + client_stream.close() |
| 185 | + |
| 186 | + e_time.show( "before gc" ) ### |
| 187 | + |
| 188 | + if MEM_MONITORING: |
| 189 | + gc.collect() |
| 190 | + print( "heap used {}".format( gc.mem_alloc() / 1024 ) ) |
| 191 | + print( "heap free {}".format( gc.mem_free() / 1024 ) ) |
| 192 | + else: |
| 193 | + pass |
| 194 | + #print( "heap used {}".format( gc.mem_alloc() / 1024 ) ) |
| 195 | + #print( "heap free {}".format( gc.mem_free() / 1024 ) ) |
| 196 | + |
| 197 | + e_time.show( "end" ) ### |
| 198 | + print() |
| 199 | + |
| 200 | +def send_response( stream, content, content_type ): |
| 201 | + try: |
| 202 | + if None == content: |
| 203 | + stream.write( "HTTP/1.0 404 NOT FOUND\n\nFile Not Found" ) |
| 204 | + else: |
| 205 | + stream.write( "HTTP/1.0 200 OK\nServer:mikan\nContent-Type: {}\n\n".format( content_type ) ) |
| 206 | + stream.write( content ) |
| 207 | + except OSError as e: |
| 208 | + print( "!!! OSError:", e.args ) |
| 209 | + |
| 210 | +def get_dut_list( devices, demo_harnesses ): |
| 211 | + list = [] |
| 212 | + |
| 213 | + for dev in devices: |
| 214 | + if dev.__class__ == General_call: |
| 215 | + last_dut = DUT_GENERALCALL( dev ) |
| 216 | + continue |
| 217 | + |
| 218 | + for dh in demo_harnesses: |
| 219 | + if issubclass( dev.__class__, dh.APPLIED_TO ): |
| 220 | + list += [ dh( dev ) ] |
| 221 | + |
| 222 | + return list + [ last_dut ] |
| 223 | + |
| 224 | +def start_network( *, port = 0, ifcnfg_param = "dhcp", lcd = None ): |
| 225 | + print( "starting network" ) |
| 226 | + |
| 227 | + try: |
| 228 | + lan = network.LAN( port ) |
| 229 | + except OSError as e: |
| 230 | + if lcd is not None: |
| 231 | + lcd.print( [ "No LAN", " cable?" ] ) |
| 232 | + error_loop( 2, "Check LAN cable connection. OSError:{}".format( e.args ) ) # infinite loop inside of this finction |
| 233 | + |
| 234 | + lan.active( True ) |
| 235 | + print( "ethernet port %d is activated" % port ) |
| 236 | + |
| 237 | + try: |
| 238 | + lan.ifconfig( ifcnfg_param ) |
| 239 | + except OSError as e: |
| 240 | + if lcd is not None: |
| 241 | + lcd.print( [ "DHCP", " fail :(" ] ) |
| 242 | + error_loop( 3, "Can't get/set IP address. Tried to set {}. OSError:{}".format( ifcnfg_param, e.args ) ) # infinite loop inside of this finction |
| 243 | + |
| 244 | + return lan.ifconfig() |
| 245 | + |
| 246 | +class DEMO( DUT_base ): |
| 247 | + def __init__( self ): |
| 248 | + super().__init__( None ) |
| 249 | + |
| 250 | +def page_setup( dut_list, i2c, live_only = False ): |
| 251 | + db = DEMO() |
| 252 | + |
| 253 | + db.page_data[ "dev_name" ] = "GENERAL" |
| 254 | + |
| 255 | + table, links = page_table( dut_list, live_only = live_only ) |
| 256 | + |
| 257 | + db.page_data[ "all_links" ] = links |
| 258 | + db.page_data[ "front_page_table" ] = table |
| 259 | + db.page_data[ "filtering_list" ] = filter_setting( live_only ) |
| 260 | + db.page_data[ "i2c_scan" ] = i2c_scan_table( i2c ) |
| 261 | + |
| 262 | + return db.load_html() |
| 263 | + |
| 264 | +def filter_setting( filtering ): |
| 265 | + if filtering: |
| 266 | + return '<a href="/">show all device(s)</a>' |
| 267 | + else: |
| 268 | + return '<a href="/?live_only=True">live device(s) only</a>' |
| 269 | + |
| 270 | + |
| 271 | +def page_table( dut_list, live_only = False ): |
| 272 | + s = [ '<table>' ] |
| 273 | + l = [] |
| 274 | + |
| 275 | + s += [ '<tr>' ] |
| 276 | + s += [ '<td class="table_header"></td>' ] |
| 277 | + s += [ '<td class="table_header">device type</td>' ] |
| 278 | + s += [ '<td class="table_header">address</td>' ] |
| 279 | + s += [ '<td class="table_header">live?</td>' ] |
| 280 | + s += [ '<td class="table_header">family</td>' ] |
| 281 | + s += [ '<td class="table_header">info</td>' ] |
| 282 | + s += [ '<td class="table_header">interface</td>' ] |
| 283 | + s += [ '</tr>' ] |
| 284 | + |
| 285 | + |
| 286 | + for dut in dut_list[ :-1 ]: # ignore last DUT. It's a general call (virtual) device |
| 287 | + if "I2C" in str( dut.interface ): |
| 288 | + live = dut.dev.ping() |
| 289 | + else: |
| 290 | + live = None |
| 291 | + |
| 292 | + if live_only and (live is False): |
| 293 | + continue |
| 294 | + |
| 295 | + s += [ '<tr><td class="reg_table_name">{}</td>'.format( dut.symbol ) ] |
| 296 | + |
| 297 | + if live is not False: |
| 298 | + s += [ '<td class="reg_table_name"><a href="/{}" target="{}">{}</a></td>'.format( dut.dev_name, dut.dev_name, dut.type ) ] |
| 299 | + l += [ "'" + dut.dev_name + "'" ] |
| 300 | + else: |
| 301 | + s += [ '<td class="reg_table_name"><font color="#C0C0C0">{}</font></td>'.format( dut.type ) ] |
| 302 | + |
| 303 | + if dut.address: |
| 304 | + s += [ '<td class="reg_table_name">0x%02X (0x%02X)</td>' % ( dut.address, dut.address << 1 ) ] |
| 305 | + else: |
| 306 | + s += [ '<td class="reg_table_name">n/a</td>' ] |
| 307 | + |
| 308 | + s += [ '<td class="reg_table_name {}">{}</td>'.format( "Red_cell" if live is False else "Green_cell", live ) ] |
| 309 | + s += [ '<td class="reg_table_name">{}</td>'.format( dut.info[ 0 ] ) ] |
| 310 | + s += [ '<td class="reg_table_name">{}</td>'.format( dut.info[ 1 ] ) ] |
| 311 | + s += [ '<td class="reg_table_name">{}</td>'.format( dut.interface ) ] |
| 312 | + s += [ '</tr>' ] |
| 313 | + |
| 314 | + s += [ '</table>' ] |
| 315 | + |
| 316 | + return "\n".join( s ), ", ".join( l ) |
| 317 | + |
| 318 | +def i2c_scan_table( i2c ): |
| 319 | + scan_result = i2c_fullscan( i2c ) |
| 320 | + s = [ '<table>' ] |
| 321 | + s += [ '<tr>' ] |
| 322 | + s += [ '<td class="table_header">0x</td>' ] |
| 323 | + for x in range( 16 ): |
| 324 | + s += [ '<td class="table_header">x{:01X}</td>'.format( x ) ] |
| 325 | + s += [ '</tr>' ] |
| 326 | + |
| 327 | + for y in range( 0, 128, 16 ): |
| 328 | + s += [ '<tr>' ] |
| 329 | + s += [ '<td class="table_header">{:01X}x</td>'.format( y >> 4 ) ] |
| 330 | + |
| 331 | + for x in range( 16 ): |
| 332 | + adr = y + x |
| 333 | + s += [ '<td class="table_i2c_val"><font color="{}">{:02X}({:02X})</font></td>'.format( '#000000' if adr in scan_result else '#EEEEEE', adr, adr << 1 ) ] |
| 334 | + s += [ '</tr>' ] |
| 335 | + |
| 336 | + s += [ '</table>' ] |
| 337 | + |
| 338 | + return "\n".join( s ) |
| 339 | + |
| 340 | +from utime import sleep |
| 341 | + |
| 342 | +def error_loop( n, message ): |
| 343 | + led = machine.Pin( "D4", machine.Pin.OUT ) |
| 344 | + pattern = [ 0, 1 ] * n + [ 1 ] * 4 |
| 345 | + |
| 346 | + for i in range( 3 ): |
| 347 | + print( "**** ERROR ****" ) |
| 348 | + |
| 349 | + print( message ) |
| 350 | + |
| 351 | + while True: |
| 352 | + for p in pattern: |
| 353 | + led.value( p ) |
| 354 | + sleep( 0.1 ) |
| 355 | + |
| 356 | +class elapsed_time: |
| 357 | + def __init__( self, start ): |
| 358 | + self.start = start |
| 359 | + self.enable = False |
| 360 | + def show( self, m ): |
| 361 | + if self.enable: |
| 362 | + print( m, end = ": " ) |
| 363 | + print( ticks_ms() - self.start ) |
| 364 | + else: |
| 365 | + pass |
| 366 | + |
| 367 | +ext_content = { "css" : "text/css", |
| 368 | + "html": "text/html", |
| 369 | + "js" : "text/javascript", |
| 370 | + "png" : "image/png", |
| 371 | + "jpg" : "image/jpg", |
| 372 | + "ico" : "image/ico", |
| 373 | + } |
| 374 | + |
| 375 | +def main(): |
| 376 | + demo( ip = "dhcp" ) |
| 377 | +# demo( ip = ( "10.0.0.99", "255.255.255.0", "10.0.0.1", "8.8.8.8" ) ) |
| 378 | + |
| 379 | +if __name__ == "__main__": |
| 380 | + main() |
0 commit comments