Skip to content

Commit d0bd3cc

Browse files
authored
feat(ssd1306): added 128X64 OLED (#13)
* feat(ssd1306): added 128X64 OLED * feat(ssd1306): rendering issue getting null instead of canvas * feat(ssd1306): need to fit the size again 100 x 54 isn't good * feat(ssd1306): faked size to fit proportions so the screen will be 128x64 * feat(ssd1306): font fallback and style tweaks * fix(ssd1306): added ability to update existing imageData * fix(ssd1306): added a story * feat(ssd1306): new image data * fix(ssd1306): hiding element while imageData is empty * fix(ssd1306): final tweaks
1 parent 47c8fc6 commit d0bd3cc

File tree

4 files changed

+131
-0
lines changed

4 files changed

+131
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.cache
22
.history
3+
.idea
34
node_modules
45
dist
56
build

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ export { ResistorElement } from './resistor-element';
1010
export { MembraneKeypadElement } from './membrane-keypad-element';
1111
export { PotentiometerElement } from './potentiometer-element';
1212
export { NeopixelMatrixElement } from './neopixel-matrix-element';
13+
export { Ssd1306Element } from './ssd1306-element';

src/ssd1306-element.stories.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { withKnobs, boolean } from '@storybook/addon-knobs';
2+
import { storiesOf } from '@storybook/web-components';
3+
import { html } from 'lit-html';
4+
import './ssd1306-element';
5+
6+
storiesOf('Ssd1306', module)
7+
.addParameters({ component: 'wokwi-ssd1306-element' })
8+
.addDecorator(withKnobs)
9+
.add('Default', () => html` <wokwi-ssd1306-element></wokwi-ssd1306-element> `);

src/ssd1306-element.ts

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Reference: https://cdn-learn.adafruit.com/assets/assets/000/036/494/original/lcds___displays_fabprint.png?1476374574
2+
import { customElement, html, LitElement, property, SVGTemplateResult } from 'lit-element';
3+
4+
type CanvasContext = CanvasRenderingContext2D | null | undefined;
5+
@customElement('wokwi-ssd1306-element')
6+
export class Ssd1306Element extends LitElement {
7+
/** ImageData is the underlying pixel data of an area of a <canvas> element.
8+
imageData can also be used to set a part of the canvas by using putImageData().
9+
You may use the the redraw() method for initiating an update of the imageData data
10+
which its reference wasn't changed.
11+
*/
12+
@property() imageData: ImageData;
13+
14+
readonly width = 150;
15+
readonly height = 116;
16+
private screenWidth = 128;
17+
private screenHeight = 64;
18+
private canvas: HTMLCanvasElement | null | undefined = void 0;
19+
private ctx: CanvasContext = null;
20+
21+
constructor() {
22+
super();
23+
this.imageData = new ImageData(this.screenWidth, this.screenHeight);
24+
}
25+
26+
/**
27+
* Used for initiating update of an imageData data which its reference wasn't changed
28+
*/
29+
public redraw() {
30+
this.ctx?.putImageData(this.imageData, 0, 0);
31+
}
32+
33+
private initContext() {
34+
this.canvas = this.shadowRoot?.querySelector('canvas');
35+
// No need to clear canvas rect - all images will have full opacity
36+
this.ctx = this.canvas?.getContext('2d');
37+
}
38+
39+
firstUpdated() {
40+
this.initContext();
41+
this.ctx?.putImageData(this.imageData, 0, 0);
42+
}
43+
44+
updated() {
45+
if (this.imageData) {
46+
this.redraw();
47+
}
48+
}
49+
50+
render(): SVGTemplateResult {
51+
const { width, height, screenWidth, screenHeight, imageData } = this;
52+
const visibility = imageData ? 'visible' : 'hidden';
53+
return html`<svg width="${width}" height="${height}" xmlns="http://www.w3.org/2000/svg">
54+
<g>
55+
<rect stroke="#BE9B72" fill="#025CAF" x=".5" y=".5" width="148" height="114" rx="13" />
56+
57+
<g transform="translate(6 6)" fill="#59340A" stroke="#BE9B72" stroke-width="0.6px">
58+
<circle cx="130" cy="6" r="5.5" />
59+
<circle cx="6" cy="6" r="5.5" />
60+
<circle cx="130" cy="96" r="5.5" />
61+
<circle cx="6" cy="96" r="5.5" />
62+
</g>
63+
64+
<g transform="translate(11.4 26)">
65+
<!-- 128 x 64 screen -->
66+
<rect fill="#1A1A1A" width="${screenWidth}" height="${screenHeight}" />
67+
<!-- image holder -->
68+
<foreignObject
69+
?visibility="${visibility}"
70+
width="${screenWidth}"
71+
height="${screenHeight}"
72+
>
73+
<canvas width="${screenWidth}" height="${screenHeight}"></canvas>
74+
</foreignObject>
75+
</g>
76+
77+
<!-- All texts -->
78+
<g
79+
fill="#FFF"
80+
text-anchor="middle"
81+
font-size="5"
82+
font-weight="300"
83+
font-family="MarkerFelt-Wide, Marker Felt, monospace"
84+
>
85+
<g transform="translate(37 3)">
86+
<text x="0" y="5">Data</text>
87+
<text x="19" y="5">SA0</text>
88+
<text x="41" y="5">CS</text>
89+
<text x="60" y="5">Vin</text>
90+
</g>
91+
92+
<g transform="translate(41 17)">
93+
<text x="0" y="6">C1k</text>
94+
<text x="12" y="6">DC</text>
95+
<text x="23" y="6">Rst</text>
96+
<text x="39" y="6">3v3</text>
97+
<text x="58" y="6">Gnd</text>
98+
</g>
99+
<!--Star -->
100+
<path
101+
d="M115.5 10.06l-1.59 2.974-3.453.464 2.495 2.245-.6 3.229 3.148-1.528 3.148 1.528-.6-3.23 2.495-2.244-3.453-.464-1.59-2.974z"
102+
stroke="#FFF"
103+
/>
104+
</g>
105+
106+
<!-- PINS -->
107+
<g transform="translate(33 9)" fill="#9D9D9A" stroke-width="0.4">
108+
<circle stroke="#262626" cx="70.5" cy="3.5" r="3.5" />
109+
<circle stroke="#007ADB" cx="60.5" cy="3.5" r="3.5" />
110+
<circle stroke="#9D5B96" cx="50.5" cy="3.5" r="3.5" />
111+
<circle stroke="#009E9B" cx="41.5" cy="3.5" r="3.5" />
112+
<circle stroke="#E8D977" cx="31.5" cy="3.5" r="3.5" />
113+
<circle stroke="#C08540" cx="21.5" cy="3.5" r="3.5" />
114+
<circle stroke="#B4AEAB" cx="12.5" cy="3.5" r="3.5" />
115+
<circle stroke="#E7DBDB" cx="3.5" cy="3.5" r="3.5" />
116+
</g>
117+
</g>
118+
</svg> `;
119+
}
120+
}

0 commit comments

Comments
 (0)