diff --git a/misc/gpu/gpu_binary.py b/misc/gpu/gpu_binary.py index 27e865e9..12d65c6c 100644 --- a/misc/gpu/gpu_binary.py +++ b/misc/gpu/gpu_binary.py @@ -4,115 +4,115 @@ # # see misc/gpu for source # -VERSION = '1.3.1' +VERSION = '1.3.2' LENGTH = const(3524) # bytes (after decompression) -# len(BINARY) = 2603 -BINARY = (b'x\x9c\x8dWkp\x1b\xd5\x15>wweK\xb2\x13\xcb\x91c\xfc\xf6J\xd7\x0e&\xb2c\xc9' - b'\x1bC\x1e\xa4Y\xb4\xa9bk\x1d\x13\x12\xc2$Vh\xd7\x0f\xc8*\x86\xb2\xc54' - b'\xa3)?\xaa&CK\xd36@\x04yH\t\x98\x98GR\xda\xc1\xf5\x8c\xfa\xa0\xf1\x90\xc20' - b'L\xa1\x806&m\x1ag\x8a!tT\x86\xa1(L\x8b\x94\x04{{Vq\x18{&\xd3\xa9\x1b\xae\xf4;R\x1f\x86' - b'\x8b\xa4\xa8\xebB\xefH\xb8\x93)\x12+\xa1\xa3\xee\x87\xb7\x95j\xe0' - b'\xa1\xfa\xf6\xce"\xcd$g\xe4\xd90\x89m\x93\xeb#\xdb\xe4\xda\x08O+\xfdm' - b'\xa9\x8f\xc2N\xe9B/I\x80\xa7Y\xbf\xb3[\xd0\xfa[\xb7\xa5J\xce\xf6\xb6\xde' - b'\x93\xeak\x95Sw\xb5\x96\xa56\xca\x1b\x83U\x8a\x95\xfa\xa7\xa8z{g\x11b' - b'>\x97~\xa8\xf5[\xa9\xa0\xbc\xabUHi\xad\xff\xd2\x83\xc1v\r=\xa6\xa0%' - b'\xa4wt\xac\x93+\x14\xc8\xd8\xa6\x89\xd7\xab\x11z\x0c\xe3\x8f\xf4\x82' - b'\x9b\xa3\xa5p$@\xf8{\x03#a\xc1\xdf\xa5\xc3M$u\xb3\\\xaf\xc1R\x92j\x97k5' - b'\xe3Fhd\x96\x9c\x0c\x08\x1d\xcb;\xd9\x88]%\xcf@\xab\xacC\x0bI\xb1\x9a' - b']\xc9\x8eCK\x8b\xde\x868\n\xa8\xa0M\xa4\xa1e\x89nd\xbfg\xb4\xcaM' - b'A\xa7\xc2\xd2\x7f\xa7\xd9\x96Z\xbd)\xd8,\x97F\x0ekwD\xfe\xa6Y\\\xfb#=ZU' - b'd\xafT\xa5\xfd\x01\xfd\x17\xea\xc4\xdd WF\xee\xd6\xec\xa8\x19C\x8dEg(' - b'\x1f,\x8d`E\xb5_\xa4\xcb\xe5:\x8cn\xa3\xef\xa5\xfbwN\x8eAka\xaa' - b'\xb0\xe5\xf8\xd9\xb2\xee\x9d5C[\xce\x8c1p,]\x0f\x04\x9eI\xef\x08\xbc\xd8' - b'7\x9a~1|\x8b\x7f4\x05\x9eljq\x84\xac~\xbe\x8f\xb4\x91\xa3\x93c\xcf\xa5q]p' - b'\xed\x96a\xcf\xb6 5 -G\xf2"m\xc0=a\x183F#\xf2\x8f"\xbf\x0e)\x88t+\xcaw\xe1' - b'\x18uW\xc9\x8b,q%\xea\xae\x947A\xa5\x8a(\x91?\x8d\\\xa9\xff\xabT\x8fZ\xd6Y' - b'*\xa2L\xecR\x8fR\xa5.\xcaK\x9b\x88\xe9\x15WK:\xedb\xa1+\x8e\xdc^)\xae\xac' - b'p\x1fV\xad\xe0\x10K\xfd\x97\xf5\xb8jC[\\\xb1\xc9\xb6`\x8fbq\x1fR' - b'\xaa\xb0{\xe03\xdc\xb1f\xcfE\xb1\xb5\xdeD\xca =f\x18\x8e)\x98\xfa\x00' - b'\xc1W\xc8C\xc9\xca\xfb*:\x86\x1b\x88T9\xf0C\x17YRu_\xa7\x85\x11\xc9~\x12?' - b'\x87{\xcd.\x9d\xeb\x9f\x1c,\xc2\x1d\x02\t#\xdb6\x03\x99\x939#\xbbu\xa6' - b'8\xb8\xa0\xd3\xa9\x16\x89N\xc5\xc8\xfez\x86\xe2:_\xd6\xf9F\x1a\xf6\xf8\xbfL' - b'A\xe6\xe9K&w1edGf.\xa5\xcd\xfc\xc4a\xeet\xc4\x81u\x19\xa6\x0e\xb7\xd55' - b'iq$\xe3\xbd\x87\xfb\xe2}\xa7h\x88\xd4`\x89\x9eP+\xc5g\xfdWR\x8e!\xe4\xfc_' - b'\xe9\xa6\xdf\xa4%\xdek]\x15\xef\xcd\x9f9^"\x0eSo\x12g7\x98\xfa#\xbd8\xd7\r' - b'\xd4\xd6\xb5\x89\x1c\xf2\x17\x9e\x1fQ\x9dsfy\xc7\x9fW\x17\x8bOa\xbcw\xb6' - b'\x13\xa1q\xe8\xb3\xb49\x7f(\xb9\x10j\x81\xac\xda3\x16\xaf \xbf\xdc?Vm' - b'\xa7\x9a\xa29\xedK\xf9\x11\xed#\r\x7f\x8b\xe1\x02\x8e7\xb2o\x1bd\xcd\xd8\xd8' - b'\x96\xca_\x8d-\xb2\xbb5\x0f\xbf\xd4~L\xbbW\xfb\x07z\x0c\xcfz\xbcb4\xe3\xf7ac' - b'h|\x98j\xf31\xd1w\xc7>\x14\xa1\xa1(\x18"\xc3\x88k\xfe\xaf\xd1\xc6\x9f' - b'Rk\xc5\xa3\x88\xab|\xe8\x1aW:D\x96\x7f\x92\xc7\xa7%k\x80{\xa9\xeeQ' - b'\n\x8b\xc1\xc8\x1e7x\xf0\x81*\x19\xd9w\x0cm\xdc\x91\xdc;Z3{*\xae\xbfr\x8aV' - b'3\x10\xdbMC@bSt\x12\x98X\x14+\x11\x0e$\xf0P5O\xa6\xe1\xcb"u\xabN\x89*\x84r' - b'\xb3\xbdo\x1f\xbdVG\xb3\x173\xc9GF\xcb\x81\x8d\xb9\x9a\xda\xcf\xdbn\x12\xce' - b'\xdb\x1a\x14\xe9\xb9\xc0\x82\xe5]R\tu\xc1\xa2\x1b\x9d\xe2\x1b\xb5%' - b'\xbe/\n\xe0\xfd\x1d\x01\xf6\xe9\x07\xeb\x0e\xdcV\x17\xdc\xe5/\x17\x19' - b'O\xbd\xbe\n\x9a\x80\xac\x86\x03F\xf6\x05\xac\x07\xa1\xa6\xdc\xe0s,75G\x8d' - b'2J\xdc.\xd4\x98\xd2\x81Y\xe9\x9f\x95d\x85)\xef3,x&\x13\x8f%\xc5z.\xe9\xe5' - b'\x94s\xc3\x01\xcb\x14\x8b\xa7\x12\xa7\xc3\xfe\xf2|\xa4O\xd3\x80\x08 ' - b"\xf6J\x9d\xc3g\xf5\x96\t\x17\xd2\xd3\n@6Y+or\xc1\xcbG\xd7}'\x00\xee\x82\x86" - b'\xaa\x0e\xc3\xe7\x04*\xde\xed\x1f\xbc\xadbC\xc8\xcf\x8a\xa1\xca-@' - b'\xda\x866\xef\xf5\x7f\xa1[\xe8\xb0\xfbS\x17\xf0!\xff&\xac$kX\x1a\x1c\x1b' - b'\x86y\x8f\x1a\x85\x87\x95\x12\xfa}\x95\xdcz\xb8\xaa\x13\xbe[ad\xcf\xcc@s' - b'F\x7fX\xb5\x05\x89\xe0\x14\xb93\x0e7Y\xbd\xc9\xef\x94\x880\x1e\xf0\xe0y\xb4' - b'u\xda0\xd8g\xf0dF\x0c"\xd6\xad\x04 \x9aK\x96\xc9&\x92\xfb\x02Q\xde' - b'\r\xe0*\x80R9\xb4\x9d\x15ka\x10\xd1\x84\xfc\xce\xa8h-\xd3\x89\xaf\xe9&' - b'\x87>\xec\x8e\xd0\xe1%&\x8aS3\x91\xc6\xdf\x80\x0b\xbc@\xd6`\xef\xcc@K' - b'N\x1f\x0f\xe4\xc6\xbd\xc0\xb4\xfd=\x1d\xc5<\n\x9e\x0fZ2J\x87\x1b\x7f4\xfa' - b'\x99e\x92\x14\xe3z\xbf\xd4k\xaex\xf7evI\x01e\x1a\xc2\x01\xack\x8c9@\xf0f\n' - b'\xe5*(\xc4nXMb@M=s\x80\x8b\xb11s\xf5\xbbs\xaen!B\xfd\x1c\xee\xc1' - b'\x13\x86\x10\x19\x91\x04M\x88L\x16\x923F6d<\x18\x81\xa5u\xa9\xca\r\xcd*4;t' - b'!r1\x12*\x9c,\x19\x8d\x18\xd9\xff\xcc\x10\xb7\x10\xd9V\xf8\xa7' - b'\x92\xbd\x12\xe7\xda\x0f?\x95\x9c8\xd3\x11\xec\xaf1+\xc3\x7f]\x19\x8f2\xdcP' - b'6{+\x92\xcbu\xf4cK8\x80\x979f.\xcdE\xe9$\x19\xe9+\x18\xd5\xb0\xd7\xcc>' - b'[\x81T\x8f5\x9bI\xcf\xa4\xb5\xf5\xe6_&\xf9\xe3\xd1"\x95y\xa2\xdeM\\$f\x01r' - b'(d\x05O\x9d\xfe\xb8\xc8\x0b\xd0\xc4\xe0\t\xf2\xfbK\xaf\x8f\xb11&\xc1\xc6C' - b'*\xde\xc6\x89\t\xb1\\\xe7\x12d5\xf1X\xcf\x0e\xaa$N\x0e\xc7$&~Z\r"\xbeA' - b'\x05\xf8B\xec\xa9\x1a\\\x9db\x91\x97\xc8\xaa\x90\xf5\xafiB\xd989\x12\x13I' - b'\xbcF\xac\xf2\x83>1u\xaf\x95\x07\x01\xea\xdd\xad*x\xb49\xb9\xf6\x98\xb9\xdc' - b'!\x88\x8b<\x1c\x94L\x0f\xf0\xec\x98c\x1fB;\x177\xed\\\xe2\x06\x89\xacn' - b'U\x88\xa7\xe1,\x93\xe0!\xa1\xd6\xbb-1\x01^\xc6\x88[\xe6\xcc\xe8\xb9N\xc4' - b'\xae9\xf6 \xda-\xf9\x887H/+f\xa4\xea\xf0\xd5H\x9fc\xa4o\xcc\xf1l\xbfN\xa4' - b'\xf69\xf6\xc6\xaf#\x99\xd8>W\x18\xcf\xb7\xf5\xd9_9E\\"T\x8a\xd6|=\x1eI\xcf' - b"\x95\xf6\xcd\x93\x86\xe7I'\xe6I\xbf\x9d'\x9d\x9a'\xe1\x9d\xa83\x89\xc7\xc5P" - b'\x98\x8b\xb5#\x96\x0fr\x85M\xbe\xf3\xb3\xd9w\x82\xa7v\x0eN=\xf7\xfaX\x89' - b';\x818\xeb\xe9A\t\x96\x95#\xcaC"O\xafZ_\xcb\x99\x15N\xe4\xeb\xd1' - b'\xda\xc7&\x88\x00\xf32\x9dM\x13~\x00\xbc"\x87\xd5\xdfe\xfd \xbd\xc4>`' - b"\xf7\x02\xc5<\x0f`\x9e\xea9y\x8e\xce\xcf\xd3\\\xa6{\xe7\xe4\xd97'\xcf\x03" - b'}o\xcd\xcbq\x0es\xec\x02^,\xc0\x1c\x03\xd6\x0f\xf1\x1d\xca\xaa\x0chI\xc2' - b'\x87\n\x9a\xdf\xefV\x8b\xd4\x8e\xb0 \xbd\xab.V\x05ia\xb8x\xa7 \xed\x0b' - b'\xb3\x12j\xc2P,H\x8en*\xb5\x8b\x1e|\xb1mV\x7f\xae.\xecn\x92\x04\xb1B\x8a\xd2' - b"\x8dJ59\xea\xe7NG\xf9\xcd\xaaHXi\xb3\x12\xa5\xc0'\xc8\x11?\xa3\xcb;\x13c\xce" - b'\xde\x890\x8b/\xad\t\xbc\x17D0\x8c+\x99\xab\xcf@\xe2fUo2&\xb1' - b'\xca\xdb\x18\xaf\x9a\xe1T\x8fT\xb6\xa1Y\xa4\xa8\x91Ug\x17\xdb\xcb' - b'\xaa\x0b\xc2U\x12\xa3\xecQ\xf7\x86\xa9\xb8\x07\xc7\xa5\xd2\xa4}\x92\xa9' - b'\x92v+\xd0\xc2\xa5\xa2t7\xcesJ{\x14F\xb5\xcaUb\x91jzKj\x10\xbd\x9d\x92' - b'\x84{\xc6\x8b\xfb\xd3\x98\xba\xf6\xf6|\xcf\xa8q\x11Z\xcd\x1d\xf2\x93\t(v\xac' - b'\xac\xb6\xe79\xbbue\xb5-\xcf\xd9\xb8\x95\xcc1\xc7v\xb1\xc2|\x93r,\xc3' - b'\x10\xfc\\\xfb_\x82\x85\xdd\x151\xdce\xda\xfaJ\x8d\x08x\xe7\xd3' - b'\xd7\xf0\xd6\x85\xa5W\xf4\xadu\xf8\n\x81\\\xf2T w\xd2z\xf2\xe9\x80\xb6~' - b'.\xef[&,\xf3\xc1\xed2\xf8{\x07\xf8\xfe\xfb\x07\xd6\xe6\x99\xde\x07w\x0c\xad' - b'\xbd\x16zm\xcdB\xa8\xdf\x07S%9\xe3\xb17/\xcc\xac\xbdp1g\\\xcc\xb13+\xbe' - b'\x9au\xc8\xc7\xe0\x1f\n\xdf\x7f\xcf\x9a6o\x9b\xe0k\xf3\xf9\x96\xf9' - b'\x84\xf6\x15\xde\x15\xfc\x8e\xf0Ck\xee\x10\xfbV\xfa|\xed7\x0f\xf0' - b'\xeb\xbey\xd7\x1a\xdf\xd59\x9f\x00X\xff\x88\xf4_\xdc\x9cbu') +# len(BINARY) = 2607 +BINARY = (b'x\x9c\x8dWkp\x1b\xd5\x15>wweK\xb2\x13\xcb\x91c\xfc\xf6J\xd7NLd\xc7\xb2' + b'7.y\x90f\xd1\xa6\x8a\xaduLH\x08\x93X\xa1]\xdby\xacb([L3\x9a\xf2\xa3' + b'\x82\x0c-M\xdb\x00\x11\xe4!%\xc1\xc1\xe5\x91\xa1\x9d\xb8\x9eQ\x1f4\x1eR\x18' + b'\x86)\x14\xd0\xc6\xa4M\xe3L1\x84\x8e\xca0\x14\x85i\x91\x92`o\xcf*\x0e#\xcfd:' + b'\x95\xe7\xe8\x9e\xd7=\xe7\xd3\xb9\xf7\x9e{\r\x15\xc0\xdb\x08X\xdbl' + b'`\x15\x90\xe0\x7f|:\xf2\xec\xb7!\xbf\x02i3\xb9\xae3\xc7\x9b\xd1\xffc\xbb' + b'\x11\xf3f\xfe7\xd3\xe7cr$\n\xbai\x18<\x85\xbaE\x06\x0f\x93\xe4:a\n^%\x94' + b"j\x8eqt\xe4M\x9f\xdf\xcd\x03+';\x12\xe0a\x93l\xd7u\x0f\xc7\xf8\x19\xbfi+F" + b'\x1f\xd3^\xdc\xf9\x98\x1f\xd2O_\x01\x17;e\x97\x83[\xa4\r\\\x9b\xad\xd3.' + b"\xfb*b\xbe/'l\x01f\n\xa8S\xe1\xda\x0b\xe5\x98\xef\xca\x04\xa4\xdf\xb82" + b'\x93\x82\x8a\\\xfc\x1cYgi-\x12Z \x9d \x8d?\x19-sc\xbc\x97 }v\xbaD' + b'\x1en\xe8\x1dd\x16/\x91z\x07\x82\x83\x1f[<"\x89\x92\xf8\x1a\xca\x9c\xe4!' + b"\xb2\x88\x89r\x87 \xfd\x97k@\xbf$<0'\x99\x83\xec3\xdc\xa1\x82(\xa4" + b'\xff|\xed\x85~\xdbhz\x1c\x1c\x8c\xe8H0\r\xbc\xec\xea\xea\xbd\xff\xf1Q\xbb' + b'\xd8\xbb\xa3w\x10\\\xee\\\xbcb7\x15!\x8a\x99\xe2\x90>:}\x86\x92\xe8\xab' + b'\xab\xb8(9i\x11\xca;\x0b\xa2\xcc\xd3\x90~\xe9Z\rb!\x88\xe5g\xd3\x0bdg7\x13' + b'}\x8b\xf2\x80\x1e\x98\xc33\x1d\xa1\xfdj\x9csJ\x03\xca%u^\xc0)^\xc2\xb187R' + b'\xb5\x08G\x8a\xa3=7ZG\x1d9,\xc6{\x86\x01\x1clpr\x0e\x80\xbbA$Y\xc30~\x88dd' + b'\x90\xa6\x8d\x08e\x03A\xa6T-\x92\x9c\x8a\xb6\x0ek\xcd3\xa2\x95f\x12\x03\xdd' + b"\xdb\x03'B\x95>G\xf2\xc3P\x91\x14q]\xea\x1b\tu1Eb%t\xd6=rG\xa9\x06\x1e\xaao" + b'\xeb*\xd2Lr\x86O\x84Ht\xab\\\x1f\xde*\xd7\x86yZ\xe9kO~\x14rJ\x97\xfa' + b'H\x1c<\xcd\xfa\xdd=\x826\xd0\xba5Yr\xbe\xafuG\xb2\xbfUN\xde\xd3Z\x96\xdc ' + b"o\x08T)V\xea\x9b\xa2\xea\x9d]E\x88\xf9B\xea\xa1\xd6o'\x03\xf2\x9eV" + b'!\xa9\xb5\xfeK\x0f\x04:4\xf4\x98\x82\x96mzg\xe7Z\xb9B\x81\xb4m\x9a' + b'x\xbd\x1a\xa1\xcfa\xfc\x91>ps\xb4\x14\x8e\xfa\t\xbf\xd3?\x12\x12|\xebu' + b'\xb8\x95$\xbf!\xd7k\xb0\x84$;\xe4Z\xcdX\x0c\x8d\xcc\xa2\xd3~\xa1sY' + b'\x17\x1b\xb6\xab\xe4Yh\xed\xd6\xa1\x85$Y\xcd\xaed\xc6\xa1e\xa9\xde\x8e8\n' + b'\xa8\xa0M\xa4\xa0e\xb1nd\xbeo\xb4\xcaM\x01\xa7\xc2\xd2\x7f\xa7\xd8\x96:\xbd' + b')\xd0,\x97\x86\x8fhw\x85\xff\xa6Y\\\x07\xc2\xbdZUx\x9fT\xa5\xfd\x01' + b'\xfdKt\xe2n\x90+\xc3v\x94\xef\xd5\xc6PS\xa0\xb3.^6=J\x81q\x7f\x91*\x97' + b'k1\xbe\x8d\xbe\x9b\x1a\xd8=9\x06\xad\x85\xc9\xc2\x96\x17\xcf;{v\xd7\x0cm' + b'>7\xc6\xc0\x89T=\x108\x9e\xda\xe5\x7f\xb1\xffT\xea\xc5\xd0m\xbeSI\xf0' + b'd\x92\x0b\xc3d\xd5\xf3\xfd\xa4\x9d\x1c\x9b\x1c\x1bI\x99k\xb7\x14\xf7' + b'l\x0bR\x03\xd22$/\xd2z<\x13\x861c4"\xff8\xf2k\x91\x02H\xb7\xa3|\x0f' + b'\x8e\x11w\x95\xbc\xc0\x12S"\xeeJy#T\xaa\x88\x13\xf9\xb3\xc8\x95\xfa\xbeJ' + b'\xf6\xaae]\xa5"\xca\xc4.\xf5*U\xea\x82\x9c\xb4\x91\x98^1\xb5\xa4\xcb.' + b'\x16\xbab\xc8\xed\x93b\xcar\xf7\x11\xd5\n\x0e\xb1\xd4wU\x8f\xa96\xb4\xc5\x14' + b'\x9bl\x0b\xf4*\x16\xf7a\xa5\nw\x0f|\x86\'\xd6\xdcs\x11\xdcZo"\xa5' + b'\x91\x9e0\x0c\xc7\x14L}\x80\xe0+\xe4\xa1D\xe5}\x15\x9d\xc3\rD\xaa\xdc\xfe' + b'\x88\x8b,\xaa\xba\xaf\xcb\xc2\x88\xe4\x00\x89]\xc0\xb3f\x97.\x0cL' + b'\x0e\x16\xe1\t\x81\xb8\x91i\x9f\x81\xf4\xe9\xac\x91\xd92S\x1c\x98\xd7' + b'\xe5T\x8bD\xa7bd~=Cq\x9d\xaf\xea|#\ry|_&!}\xfc\x8a\xc9]N\x1a\x99\x91\x99+)3?' + b"q\x98'\x1dq`]\x86\xa9\xc3muMZ\x1c\x89X\xdf\x91\xfeX\xff\x19\x1a$5X\xa2" + b'\xa7\xd4J\xf1\x84\xefZ\xd21\x84\x9c\xef+\xdd\xf4\x9b\xb4\xc4\xfa\xac+c}\xb9' + b'\x9e\xe3%\xe20\xf5&pv\x83\xa9?\xda\x87s\xdd@m\xdd\x1b\xc9a_\xe1' + b'\xc5\x11\xd5\x997\xcb;\xfe\xbc\xbaP|\x06\xe3\xbd\xb3\x8d\x08\x8dC' + b'\x9f\xa5\xcc\xf9C\x89\xf9P\x0bd\xe5\xde\xb1X\x05\xf9\xe5\x81\xb1j' + b';\xd5\x14\xcdi_\xc2\x8fh\x1fi\xf8[\x0c\x17p\xbc\x91y\xdb \xab\xc7\xc66W\xfej' + b'l\x81\xdd\xady\xf8%\xf6\xe7\xb4\x9d\xda?\xd0cx\xd6\xe3\x15\xa3' + b'\x19\xbf\x8f\x18C\xe3\xc3T\x9b\x8b\x89\xbe;\xf6\xa1\x08\rE\x81 \x19F\\s' + b'\x7f\x8d6\xfe\x8cZ+\x1eC\\\xe5C7\xb8\xd2!\xb2\xec\x93\x1c>-Q\x03' + b'\xdc\xcbu\x8fSX\x08F\xe6%\x83\x876P%#\xf3\x8e\xa1\x8d;\x12\xfbFkf\xbb\xe2' + b'\xbakgh5\x03\xd1Gi\x10Ht\x8aN\x02\x13\x8d`%B\xfe86U\xb33\r_\x15\xa9[uJT!\x94' + b'\x0b\x94\x86\xb1\x9bh\xf6\xd1\x1bu4\xf7b:\xf1\xd8h9\xb0QWS\xc7E\xdb\xad\xc2E' + b'[\x83"\xfd\xc2?oY\xb7TB]\xb0`\xb1S|\xa3\xb6\xa4\xed\x8b\x02x\x7f\x97\x9f=' + b'\xfe`\xdd\xc1;\xea\x02{|\xe5"\xe3\xa9\xd7WB\x13\x90Up\xd0\xc8\xbc\x80' + b'\xf5 \xd4\x94\x1b\xda\x1c\xcbL\xcd1\xa3\x8c\x12\xb7\x0b5\xa6tpV\xfag%' + b'Yn\xca\xfb\r\x0b\xf6d\xe2\xb1$Y\xcf\x15\xbd\x9crn8h\x99b\xb1+q:\x1c(' + b'\xcfE\xfa4\x05\x88\x00\xa2\xaf\xd49\xda\xac\xde2\xe1RjZ\x01\xc8$j\xe5\x8d.8u' + b'l\xedw\xfd\xe0.h\xa8\xea4\xda\x9c@\xc5{}\x83wT\xac\x0f\xfaX1X\xb9\x19H' + b'\xfb\xd0\xa6}\xbe/t\x0b\x1dv\x7f\xea\x02>\xe8\xdb\x88\x95d\rK\x83c\xfd' + b'0\xefQ#\xf0\xb0RB\x7f\xa0\x92\xdb\x8fTu\xc1\xf7*\x8c\xcc\xb9\x19hN' + b'\xeb\x0f\xab\xb6\x00\x11\x9c"w\xce\xe1&\xab6\xfa\x9c\x12\x11\xc6\xfd' + b'\x1e\xecG[\xa6\r\x83}\x16;3b\x10\xb1n%\x00\x91l\xa2L6\x91\xdc\xe7\x8f\xf0n' + b'\x00W\x01\x94\xca\xc1m\xacX\x0b\x83\x88&\xe8sFDk\x99N\xda\x9anu\xe8\xc3\xee0' + b'\x1d^d\xa283\x13n\xfc\r\xb8\xc0\x0bd5\xee\x9d\x19h\xc9\xea\xe3\xfe\xec' + b'\xb8\x17\x98\xf6\xbf\xa7"\x98G\xc1\xfe\xa0%"t\xb8\xf1G\xa3\x9fY&I1' + b'\xae\xf7\xcb}\xe6\x8a\xf7\\e\x17\x15P\xa6!\xe4\xc7\xbaF\x99\x83\x04o\xa6`' + b"\xb6\x82B\xf4\x96U$\n\xd4\xd43\x07\xb9(\x1b5W\xbf'\xeb\xea\x11\xc2\xd4" + b'\xc7\xe1\x19!\x96\xeb\\\x9c\xac"\x1e' + b'\xeb\xf9A\x95\xc4\xc8\x91\xa8\xc4\xc4\xce\xaa\x01\xc47\xa8\x00_\x88{' + b'\xaa\x06W\xa7X\xe4%\xb22h\xfdk\x8aP6F\x8eFE\x12\xab\x11\xab|\xa0OL\xed' + b'\xb4\xf2 @\xbd\xbbU\x05\x8f\x96\x97k\xaf\x99\xcb\x1d\x84\x98\xc8\xc3' + b'!\xc9\xf4\x00\xcf\xae<\xfb\x10\xda\xb9\x98i\xe7\xe2\xb7HdU\xabB<\r\xe7' + b'\x998\x0fq\xb5\xdem\x89\np\n#n\xce\x9b\xd1{\x93\x88\xddy\xf6\x00\xda' + b'-\xb9\x88\xb7H\xa7\x143Ru\xe8z\xa4\xcf1\xd27\xf3<;n\x12\xa9#\xcf\xde\xf8u' + b'$\x13\xdb\xe7\n\xe3\xf9\x8e>\xfb+\xa7\x88K\x84J\xd1\x9a\xab\xc7c\xa9|i' + b'\xff\x1cix\x8etr\x8e\xf4\xdb9\xd2\x999\x12\xde\x88:\x13\x7fR\x0c\x86\xb8' + b'h\x07b\xf9 [\xd8\xd4vq6\xfbn\xf0\xd4\xe6\xe1\xd4\xb3\xaf\x8f\x95\xb8\xe3' + b'\x88\xb3\x9e\x1e\x92`i9\xa2<,\xf2\xf4\xba\xf5\xb5\xacY\xe1x\xae\x1e\xad\xfd' + b"l\x9c\x080'\xd3\xf9\x14\xe1\xb7\x83W\xe4\xb0\xfa{\xac\x1f\xa4\x16" + b'\xd9\xb7\xdb\xbd@1\xcf\x03\x98\xa7:/\xcf\xb1\xb9y\x9a\xcbto^\x9e\xfdy' + b'y\x1e\xe8\x7fkN\x8e\x0b\x98c\x0f\xf0b\x01\xe6\xd8n\xfd\x10\xdf' + b'\xa1\xac\xca\x80\x96 |\xb0\xa0\xf9\xfd\x1e\xb5H\xed\x0c\t\xd2\xbb\xea' + b'BU\x90\xe6\x87\x8aw\x0b\xd2\xfe\x10+\xa1&\x04\xc5\x82\xe4\xe8\xa1' + b'R\x87\xe8\xc1\x17\xdb&\xf5\xe7\xea\xfc\x9e&I\x10+\xa4\x08\xdd\xa0T\x93c>' + b'\xeel\x84\xdf\xa4\x8a\x84\x956)\x11\n|\x9c\x1c\xf51\xba\xbc;>\xe6\xec\x9b' + b'\x08\xb1\xf8\xd2\x9a\xc0{A\x04\xc3\xb8\x96\xbe\xfe\x0c$nV\xf5&' + b'\xa2\x12\xab\xbc\x8d\xf1\xaa\x19N\xf5He\xeb\x9bE\x8a\x1aYuv\xb3}\xac:/T%1' + b'\xca^u_\x88\x8a{q\\"M\xda\'\x99*\xe9Q\x05Z\xb8d\x84>\x8a\xf3\x9c\xd2^' + b'\x85Q\xadr\x95X\xa4\x9a\xde\x92\x1a@o\xa7$\xe1\x99\xf1\xe2\xf94\xa6n\xbc' + b'=\xdf3j\\\x84Vs\x87}d\x02\x8a\x1d+\xaa\xed9\xcen]Qm\xcbq6n\x05\xf3\x9cc\x9b' + b'Xa\xbeI9\x96a\x08~n\xfc/\xc1\xc2\xa3\x15Q // Public version number for humans. Lots more version data added by Makefile. -#define RELEASE_VERSION "1.3.1" +#define RELEASE_VERSION "1.3.2" extern const char version_string[]; diff --git a/shared/actions.py b/shared/actions.py index 8c16b588..29fb84c3 100644 --- a/shared/actions.py +++ b/shared/actions.py @@ -27,18 +27,10 @@ from charcodes import KEY_NFC, KEY_QR, KEY_CANCEL CLEAR_PIN = '999999-999999' async def start_selftest(*args): - - if len(args) and not version.is_factory_mode: - # called from inside menu, not directly - # - mk4 doesn't damage settings, only earlier marks - if not await ux_confirm('''Selftest may destroy settings on other profiles (not seeds). Requires MicroSD card and might have other consequences. Recommended only for factory.'''): - return await ux_aborted() - + # selftest is harmless, no need to warn anymore with imported('selftest') as st: await st.start_selftest() - settings.save() - async def needs_primary(): # Standard msg shown if action can't be done w/o main PIN diff --git a/shared/selftest.py b/shared/selftest.py index 2a53cc51..272cc377 100644 --- a/shared/selftest.py +++ b/shared/selftest.py @@ -50,13 +50,23 @@ async def test_numpad(): assert k == ch async def test_gpu(): - dis.gpu.take_spi() - dis.clear() - dis.text(0,-1, "GPU Test okay?") - dis.show() - dis.gpu.show_test_pattern() + import gpu_binary - await wait_ok() + try: + dis.gpu.take_spi() + dis.clear() + dis.text(0,-1, "GPU Test okay?") + dis.show() + + dis.bootrom_takeover() + assert dis.gpu.get_version() == gpu_binary.VERSION + dis.gpu.show_test_pattern() + + await wait_ok() + finally: + dis.real_clear() + dis.draw_status(full=1) + dis.clear() async def test_keyboard(): # for Q1 @@ -143,19 +153,18 @@ async def test_sd_active(): gg = not ph led.value(gg) + dis.clear() if version.has_qwerty: - dis.clear() if num == 0: dis.text(0, 2, "<-- SD A is %s? " % ('ON' if gg else 'off')) else: dis.text(0, 7, "<-- SD B is %s? " % ('ON' if gg else 'off')) else: - dis.clear() if gg: dis.text(0,16, "<-- Green ON?") else: dis.text(0,16, "<-- Green off?") - dis.show() + dis.show() await wait_ok() @@ -204,7 +213,7 @@ async def test_psram(): test_len = PSRAM.length * 2 chk = bytearray(32) - spots = set() + spots = [] for pos in range(0, PSRAM.length, 800 * 17): if pos >= PSRAM.length: break rnd = ngu.hash.sha256s(pack('I', pos)) @@ -213,7 +222,7 @@ async def test_psram(): PSRAM.read(pos, chk) assert chk == rnd, "bad @ 0x%x" % pos dis.progress_bar_show(pos / test_len) - spots.add(pos) + spots.append(pos) for pos in spots: rnd = ngu.hash.sha256s(pack('I', pos)) @@ -221,7 +230,6 @@ async def test_psram(): assert chk == rnd, "RB bad @ 0x%x" % pos dis.progress_bar_show((PSRAM.length + pos) / test_len) - async def test_oled(): # all on/off tests for ph in (1, 0): diff --git a/stm32/mk4-bootloader/main.c b/stm32/mk4-bootloader/main.c index 7e48029a..09987dc0 100644 --- a/stm32/mk4-bootloader/main.c +++ b/stm32/mk4-bootloader/main.c @@ -98,13 +98,22 @@ system_startup(void) rng_delay(); #endif +#ifdef FOR_Q1_ONLY + extern void lcd_full_setup(void); + + // clear and setup LCD display - includes long config process + lcd_full_setup(); +#else + // clear and OLED display + oled_setup(); +#endif + // Workaround to get into DFU from micropython // LATER: none of this is useful with RDP=2, but okay in the office/factory if(memcmp(dfu_flag->magic, REBOOT_TO_DFU, sizeof(dfu_flag->magic)) == 0) { dfu_flag->magic[0] = 0; // still see a flash here, but that's proof it works. - oled_setup(); oled_show(dfu_flag->screen); enter_dfu(); @@ -112,8 +121,7 @@ system_startup(void) } rng_delay(); - // clear and setup OLED display - oled_setup(); + // Show main boot-up screen oled_show_progress(screen_verify, 0); // wipe all of SRAM (except our own memory, which was already wiped) diff --git a/stm32/mk4-bootloader/storage.c b/stm32/mk4-bootloader/storage.c index edf2de2b..863b90d8 100644 --- a/stm32/mk4-bootloader/storage.c +++ b/stm32/mk4-bootloader/storage.c @@ -264,6 +264,10 @@ pick_pairing_secret(void) // important the RNG works here. ok to call setup multiple times. rng_setup(); +#ifdef FOR_Q1_ONLY + // nicer, simpler screen for Q + oled_show(screen_se_setup); +#else // Demo to anyone watching that the RNG is working, but likely only // to be seen by production team during initial powerup. uint8_t tmp[1024]; @@ -274,6 +278,7 @@ pick_pairing_secret(void) } oled_factory_busy(); +#endif // .. but don't use those numbers, because those are semi-public now. uint32_t secret[8]; @@ -499,10 +504,16 @@ flash_setup(void) } // real power cycle required now. +#ifdef FOR_Q1_ONLY + // Q: just do it (we warned them) + extern void turn_power_off(void); + turn_power_off(); +#else + // Mk: operator must do it oled_show(screen_replug); puts("replug required"); - LOCKUP_FOREVER(); +#endif } rng_delay(); diff --git a/stm32/q1-bootloader/gpio.c b/stm32/q1-bootloader/gpio.c index ed5d18a3..c0078bb9 100644 --- a/stm32/q1-bootloader/gpio.c +++ b/stm32/q1-bootloader/gpio.c @@ -154,7 +154,7 @@ gpio_setup(void) // - and PE2 needs to be pull-down input, because active high signal and // GPU may not be running yet { GPIO_InitTypeDef setup = { - .Pin = GPIO_PIN_5 | GPIO_PIN_6, + .Pin = PIN_G_CTRL | PIN_G_RESET, .Mode = GPIO_MODE_OUTPUT_OD, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_LOW, @@ -163,13 +163,13 @@ gpio_setup(void) HAL_GPIO_Init(GPIOE, &setup); // G_BUSY: input, pull down - setup.Pin = GPIO_PIN_2; + setup.Pin = PIN_G_BUSY; setup.Pull = GPIO_PULLDOWN; HAL_GPIO_Init(GPIOE, &setup); // assert reset, leave others high - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, 1); - HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, 0); + HAL_GPIO_WritePin(GPIOE, PIN_G_CTRL, 1); + HAL_GPIO_WritePin(GPIOE, PIN_G_RESET, 0); } diff --git a/stm32/q1-bootloader/gpio.h b/stm32/q1-bootloader/gpio.h index 745d8d31..60a84d27 100644 --- a/stm32/q1-bootloader/gpio.h +++ b/stm32/q1-bootloader/gpio.h @@ -9,4 +9,11 @@ void gpio_setup(void); // sample the DFU button inline bool dfu_button_pressed(void) { return false; } +// Pin Names (incomplete) + +// Port E - GPU stuff mostly +#define PIN_G_BUSY GPIO_PIN_2 +#define PIN_G_CTRL GPIO_PIN_5 +#define PIN_G_RESET GPIO_PIN_6 + diff --git a/stm32/q1-bootloader/lcd.c b/stm32/q1-bootloader/lcd.c index 621ba1bb..150a9d7e 100644 --- a/stm32/q1-bootloader/lcd.c +++ b/stm32/q1-bootloader/lcd.c @@ -11,6 +11,7 @@ #include "stm32l4xx_hal.h" #include #include "misc.h" +#include "gpio.h" #include "assets/q1_screens.h" // OLED pins block use of MCO for testing @@ -31,10 +32,6 @@ // port B #define TEAR_PIN GPIO_PIN_11 -// port E - GPU connections -#define G_BUSY GPIO_PIN_2 -#define G_CTRL GPIO_PIN_6 - const int LCD_WIDTH = 320; const int LCD_HEIGHT = 240; const int NUM_PIXELS = (LCD_WIDTH*LCD_HEIGHT); @@ -181,8 +178,11 @@ lcd_full_setup(void) // configure SPI port and associated pins oled_setup(); - // => attempt to avoid flash of garbage at boot/powerup + // Attempt to avoid flash of garbage at boot/powerup + // - just enough to clear screen based on default power-up config of LCD lcd_write_cmd(0x28); // DISPOFF + lcd_write_cmd(0x36); // MADCTL: memory addr ctrl, page 215 + lcd_write_data1(0x60); // MV=1 => horz mode, first byte=top-left corner, RGB order lcd_fill_solid(COL_BLACK); // Need 10us+ low-going pulse on reset pin; do 1ms. @@ -305,16 +305,17 @@ oled_setup(void) inited = 0x238a572F; // enable some internal clocks - __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_SPI1_CLK_ENABLE(); // take over from GPU // - can be issue when coming in via callgate from mpy which might have been showing menu - HAL_GPIO_WritePin(GPIOE, G_CTRL, 1); // set G_CTRL pin -- we have control + HAL_GPIO_WritePin(GPIOE, PIN_G_CTRL, 1); // set G_CTRL pin -- we have control // .. wait for GPU to finish it's work - for(int i=0; i<100000; i++) { - if(HAL_GPIO_ReadPin(GPIOE, G_BUSY) == 0) break; + // - might take 16+ms because waiting for next vsync, etc + for(int i=0; i<100; i++) { + if(HAL_GPIO_ReadPin(GPIOE, PIN_G_BUSY) == 0) break; + delay_ms(1); } // Simple pins @@ -331,7 +332,6 @@ oled_setup(void) // starting values HAL_GPIO_WritePin(GPIOA, RESET_PIN | CS_PIN | DC_PIN, 1); - // SPI pins (same but with AF) setup.Pin = SPI_SCK | SPI_MOSI; setup.Alternate = GPIO_AF5_SPI1;