From a95e0305aeaffadf071e963863c102b30b76993a Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 27 Dec 2013 03:02:26 +0100 Subject: [PATCH] Some fixes to the host software geom stuff, added a small demo script --- firmware/main.c | 9 ++++----- host/matelight/config.py | 22 +++++++++++++--------- host/matelight/host.py | 21 ++++++++++++--------- host/matelight/nyancat-test.py | 29 +++++++++++++++++++++++++++++ host/nyancat.png | Bin 0 -> 483 bytes host/nyancat.xcf | Bin 0 -> 1658 bytes host/nyancat2.png | Bin 0 -> 477 bytes host/nyancat2.xcf | Bin 0 -> 1655 bytes host/scroller.png | Bin 0 -> 1557 bytes 9 files changed, 58 insertions(+), 23 deletions(-) create mode 100755 host/matelight/nyancat-test.py create mode 100644 host/nyancat.png create mode 100644 host/nyancat.xcf create mode 100644 host/nyancat2.png create mode 100644 host/nyancat2.xcf create mode 100644 host/scroller.png diff --git a/firmware/main.c b/firmware/main.c index a7a0436..93351cb 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -272,11 +272,10 @@ int main(void) { MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI2); MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI3); - /* 200kBd */ - MAP_SSIConfigSetExpClk(SSI0_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); - MAP_SSIConfigSetExpClk(SSI1_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); - MAP_SSIConfigSetExpClk(SSI2_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); - MAP_SSIConfigSetExpClk(SSI3_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 1000000, 8); + MAP_SSIConfigSetExpClk(SSI0_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 2000000, 8); + MAP_SSIConfigSetExpClk(SSI1_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 2000000, 8); + MAP_SSIConfigSetExpClk(SSI2_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 2000000, 8); + MAP_SSIConfigSetExpClk(SSI3_BASE, MAP_SysCtlClockGet(), SSI_FRF_MOTO_MODE_0, SSI_MODE_MASTER, 2000000, 8); /* Configure the µDMA controller for use by the SPI interface */ MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); diff --git a/host/matelight/config.py b/host/matelight/config.py index 2177292..2bc97c1 100644 --- a/host/matelight/config.py +++ b/host/matelight/config.py @@ -9,23 +9,27 @@ DEFAULT_SCROLL_SPEED = 4 # Pixels to leave blank between two letters LETTER_SPACING = 1 -FONT = bdflib.reader.read_bdf(open('fonts/5x8.bdf').readlines()) -FONT_WIDTH = 5 +#FONT = bdflib.reader.read_bdf(open('fonts/5x8.bdf').readlines()) +#FONT_WIDTH = 5 # Computed value -FONT_PADDED_BINARY = ('{:0'+str(FONT_WIDTH+'b}').format +#FONT_PADDED_BINARY = ('{:0'+str(FONT_WIDTH+'b}').format # Display geometry # ┌─────────┐ ┌───┬───┬ ⋯ ┬───┬───┐ -# │1 o o o 5│ │ 1 │ │ │ │16 │ +# │1 o o o 5│ │ 1 │ │ │ │ 8│ # │6 o o o o│ ├───┼───┼ ⋯ ┼───┼───┤ -# │o o o o o│ │17 │ │ │ │32 │ -# │o o o o20│ └───┴───┴ ⋯ ┴───┴───┘ -# └─────────┘ +# │o o o o o│ │ 9 │ │ │ │16 │ +# │o o o o20│ ├───┼───┼ ⋯ ┼───┼───┤ +# └─────────┘ │17 │ │ │ │24 │ +# ├───┼───┼ ⋯ ┼───┼───┤ +# │25 │ │ │ │32 │ +# └───┴───┴ ⋯ ┴───┴───┘ + CRATE_WIDTH = 5 CRATE_HEIGHT = 4 -CRATES_X = 16 -CRATES_Y = 2 +CRATES_X = 8 +CRATES_Y = 4 # Computed values DISPLAY_WIDTH = CRATES_X * CRATE_WIDTH diff --git a/host/matelight/host.py b/host/matelight/host.py index 461a4fa..394c299 100644 --- a/host/matelight/host.py +++ b/host/matelight/host.py @@ -1,16 +1,19 @@ -from pyusb import usb +import usb import colorsys import numpy as np +from config import * +import itertools dev = usb.core.find(idVendor=0x1cbe, idProduct=0x0003) def sendframe(framedata): - if not isinstance(framedata, np.array) or framedata.shape != (DISPLAY_WIDTH, DISPLAY_HEIGHT, 3) or framedata.dtype != np.int8: - raise ValueError('framedata must be a ({}, {}, 3)-numpy array of int8s'.format(DISPLAY_WIDTH, DISPLAY_HEIGHT)) + # not isinstance(framedata, np.array) or + if framedata.shape != (DISPLAY_HEIGHT, DISPLAY_WIDTH, 3) or framedata.dtype != np.uint8: + raise ValueError('framedata must be a ({}, {}, 3)-numpy array of int8s. Got a {}-numpy array of {}'.format(DISPLAY_WIDTH, DISPLAY_HEIGHT, framedata.shape, framedata.dtype)) - for cx, cy in itertools.product(range(16), range(2)): - cratedata = framedata[cx*CRATE_WIDTH:(cx+1)*CRATE_WIDTH, cy*CRATE_HEIGHT:(cy+1)*CRATE_HEIGHT] - # Send framebuffer data - dev.write(0x01, bytes([0, x, y])+bytes(list(cratedata.flatten()))) - # Send latch command - dev.write(0x01, b'\x01') + for cy, cx in itertools.product(range(CRATES_Y), range(CRATES_X)): + cratedata = framedata[cy*CRATE_HEIGHT:(cy+1)*CRATE_HEIGHT, cx*CRATE_WIDTH:(cx+1)*CRATE_WIDTH] + # Send framebuffer data + dev.write(0x01, bytes([0, cx, cy])+bytes(list(cratedata.flatten()))) + # Send latch command + dev.write(0x01, b'\x01') diff --git a/host/matelight/nyancat-test.py b/host/matelight/nyancat-test.py new file mode 100755 index 0000000..aaabe85 --- /dev/null +++ b/host/matelight/nyancat-test.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +import host +import numpy as np +from config import * +from PIL import Image, ImageSequence +import time + +img1 = Image.open(open('../nyancat.png', 'rb')) +img2 = Image.open(open('../nyancat2.png', 'rb')) +scroller = Image.open(open('../scroller.png', 'rb')) +datas = [] +for img in [img1, img2]: + im = img.convert("RGB") + im.thumbnail((DISPLAY_WIDTH, DISPLAY_HEIGHT), Image.NEAREST) + data = np.array(im.getdata(), dtype=np.uint8) + datas += [data.reshape((DISPLAY_HEIGHT, DISPLAY_WIDTH, 3))] + +im = scroller.convert("RGB") +bar = np.array(im.getdata(), dtype=np.uint8) +foo = bar.reshape((DISPLAY_HEIGHT, 300, 3)) + +while True: + for i in range(20): + for data in datas: + host.sendframe(data) + time.sleep(0.1) + for i in range(260): + host.sendframe(foo[:, i:i+40, :]) + diff --git a/host/nyancat.png b/host/nyancat.png new file mode 100644 index 0000000000000000000000000000000000000000..1e0bf80afb45c23c0fb3c1dc70489783ff19d019 GIT binary patch literal 483 zcmeAS@N?(olHy`uVBq!ia0y~yV9;P-U=ZM7Vqjo+y>-#E{`;$u=1m8ha?#o7@Is@978Nl&z)*pbjU!U^*-16CnigtNIc*~Ic+~fL8$AVRd1AHSCnX`uUuwy&QgtcJ~PApZ9nRE&X-j` zvisUC-M(j1+un7#g)Q0aJpI!4wJ+Xew=ym>Vpy?G)q7dn+ILewEc?Sc_m$PBtwI~q zS2A=x_#)t@eCE4@{Iexmek;8Va-UQutZ$j$sii#e?C+av`F;p)zBa3YE5Ux9;LADQ z{yl9{k)fehcOy44IQ()cwBgv0vNZo!dSLZpn+}at=PkuMO%@h0&y4E*e*fmeqSgGz z7+$m`zEt76F=Z)ZgTB3Pu2Natr^{D-4llJ`X?*R{&-Q)o%qOQFseig9?{Do=<32qB zr{{$Mv*)&{?)6)D_{*s?^|yVV3WsYitC9U*ZNSA4J?Dz?hlNdk40(y0%uRMBztmn- qZhUadFP&4?8WUGe>Wt_5$NXX4xg_>!1y&3U3=E#GelF{r5}E+EUebgB literal 0 HcmV?d00001 diff --git a/host/nyancat.xcf b/host/nyancat.xcf new file mode 100644 index 0000000000000000000000000000000000000000..af439e2d5765dce671ffabe60177298f9462c32d GIT binary patch literal 1658 zcmYe#%q>u;NKR8o%gjk-U|?X-U|?Vn05KRC7z7y@7#JBD7#M^Z7#KL5CNMC7FaraF z2m=EH3j+fK7Xt%>7?cfCC(6LUC<8J8WUOvxZen_>ZhBE>3dlT01_nk3jpCBZoK%J4 z{G7}bO)ibJ^yK`U{2~PnFr{0Ro|LFypl1LESQv&-DNRi-jU+5uVe$&N86d3{#RZAU znR)37hA_J{xil)V2|~qmOY<^I6f*OYGg6B+xil*B)6$AlOW+O!>Bba-h@ff(g##2b zHbWU83OUfZof4C?(~I&;^T5Hz1d?Z9U|@p=^M6oOK-r)m=Y+CB%0NL6iWU$X6g4n5 zHk2T4>i%Q+ z%kh_yf#vTn23=hS23RGuGW`AfkL}-2hUwE8{{8#Q_?MA^ar$2d-TyrQ ze>433_xB&;zh5AVVLIdVe+>T^|NZ?7VnS5>W%&D#{og-^=}gm^8JNM^*#9#zF#ZQg zF#iMV{>Lz#3oOI-{}0F#CWe0?3;!`p=b8SG;Xm7dMh2$oj10g3f|N6Z3}c-B_dmmQ z=IKBGgVg_LU}9kY&&=>=I>X<8tWfJgdVVrYX8HF zE;9q8?l+JLx?q9@nZu{c#K5G>#K5M@#K5S_#K59!&cJz!k%8ruCun87&X?ix7OJOauz_@;hU%#qGqgb3KsG=^^%o>m zIsP+&g7nl3)){}bK(e49{Q(Wq|6Ko>82+Bpn!!5bH^cOqGeO}x^Do2ySxmE-|1;0} z^Pl0=3?_(M-h<^q{se{a%$W?cxMwjkFrNB5Lu&>L$UThHL4nN3@NX6-gbQK21=}Zia)7hc4E(3pu0E1`;SOFsg%k*Ci9UTk|9gH2!49p$O48J=VrceLJ z28vctYMn40k^(vycp3go|2F}YRww+M@DJo2NLrl^V*X_SDfl-XHK{_ynE!$GfrAvJ z5abkQhJPSiz)2L878n_RPX{SONu9sJ;m89D#Oa`PIRRu9C=e0p^6&Hs|5!mO6B>ey z;DpTlpAlp}6Uaoye;DESpZh;J3;vt%4<(Uy{O9`5%)mJv95#O#Iy(My{s;S1l!2+^ p-~SG#4(9)i9pID-3MGaP7Gw@z2NMHR2NMHZ2NMHh2NMHJ2LNo@4(b2^ literal 0 HcmV?d00001 diff --git a/host/nyancat2.png b/host/nyancat2.png new file mode 100644 index 0000000000000000000000000000000000000000..7e4cbd4f08862c9544cc0008eafc4e355bf536f6 GIT binary patch literal 477 zcmeAS@N?(olHy`uVBq!ia0y~yV9;P-U=ZM7Vqjo+y>-#E{`;$k!rhE(Rl_2#u`r-#}JFtb3+ZwnhkjV8tu7$`NBfyzKd}S zgAZ_L7qz6M7J5yKYm`%FcDD3wU%;p5CXwv)SK^8OL;c#Hky9SF=&n92C>=gQ>F%kj z{WCorHeF`eGb3fW?snf>w~idxeBwp4$diXAb3Ah8QbJpejxk(_`aWHbAzajMevH$( z*$<~wr4+FiW)-i~((>NDb(@P$qgF`$%auA8o8s+cR!`W)c#q`*$L+)IYoBb`=AyFw zPFvNT7HPNUgJ+Y1_eR;iJCUo9_Q0EAeRK1%X%^4_riDrWIdLg!wY|}I-@9fXe|E-% zPAu+TG~p%N!6^)UC%M^}U2eTptN;Au>n8=J^$f{9?3Y@~HYzT@Qt_YD?5fw^a4v_t z-@VmuHmIBzT^IaJyMO+Qdr#FPm7A<9pB)SEKFfc%-PX}Y;oxbV_t*CvzsKyvuy`8F zp>^tO7T>z4Zd|urclFzQSw}_IKdxt1K3njvK%j541ZR8YCfUBAjXy;u-t#b6+vjS| j9{WV5^N2p{e###d8@L7#KWV{an^LB{Ts5%}mU4 literal 0 HcmV?d00001 diff --git a/host/nyancat2.xcf b/host/nyancat2.xcf new file mode 100644 index 0000000000000000000000000000000000000000..e340edd64dd10490e1fc5c8810d3a95ebd4b6b17 GIT binary patch literal 1655 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 ZcFWQ#Uq!{tdIkmt22WQ%mvv4FO#qj5^S}TA literal 0 HcmV?d00001