Packages

A library for interfacing with SSD1322 based OLED displays

Current section

4 Versions

Jump to

Compare versions

6 files changed
+38 additions
-19 deletions
  @@ -1,6 +1,6 @@
1 1 MIT License
2 2
3 - Copyright (c) 2018 Mat Trudel on behalf of FunnelCloud Inc.
3 + Copyright (c) 2018 Mat Trudel
4 4
5 5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 6 of this software and associated documentation files (the "Software"), to deal
  @@ -37,17 +37,17 @@ Common usage looks like so:
37 37 SSD1322.draw(pid, data)
38 38
39 39 # You can also turn the display on and off
40 - display_on(pid)
41 - display_off(pid)
40 + SSD1322.display_on(pid)
41 + SSD1322.display_off(pid)
42 42
43 43 # Set the contrast to a value between 0 and 255
44 - contrast(pid, contrast)
44 + SSD1322.contrast(pid, contrast)
45 45
46 46 # Clear the display to a given grey (black by default)
47 - clear(pid, grey \\ 0x00)
47 + SSD1322.clear(pid, grey \\ 0x00)
48 48
49 49 # Or reset the connection if something goes wrong
50 - reset(pid)
50 + SSD1322.reset(pid)
51 51 ```
52 52
53 53 Note that although this library serializes access for callers sharing a single connection instance,
  @@ -21,4 +21,4 @@
21 21 {<<"optional">>,false},
22 22 {<<"repository">>,<<"hexpm">>},
23 23 {<<"requirement">>,<<"~> 0.1">>}]]}.
24 - {<<"version">>,<<"0.2.0">>}.
24 + {<<"version">>,<<"0.3.0">>}.
  @@ -34,6 +34,10 @@ defmodule SSD1322 do
34 34 GenServer.call(pid, {:draw, bitmap})
35 35 end
36 36
37 + def draw(pid, bitmap, {x, y}, {w, h}) do
38 + GenServer.call(pid, {:draw, bitmap, {x, y}, {w, h}})
39 + end
40 +
37 41 def init(args) do
38 42 {:ok, SSD1322.Device.init(args)}
39 43 end
  @@ -58,7 +62,11 @@ defmodule SSD1322 do
58 62 {:reply, SSD1322.Device.clear(device, grey), device}
59 63 end
60 64
61 - def handle_call({:draw, bitmap}, _from, device) do
62 - {:reply, SSD1322.Device.draw(device, bitmap), device}
65 + def handle_call({:draw, bitmap}, from, device) do
66 + handle_call({:draw, bitmap, {0, 0}, {device.width, device.height}}, from, device)
67 + end
68 +
69 + def handle_call({:draw, bitmap, {x, y}, {width, height}}, _from, device) do
70 + {:reply, SSD1322.Device.draw(device, bitmap, {x, y}, {width, height}), device}
63 71 end
64 72 end
  @@ -11,7 +11,7 @@ defmodule SSD1322.Device do
11 11
12 12 defstruct conn: nil, width: 0, height: 0
13 13
14 - @gdram_row_width 120
14 + @gdram_row_width 480
15 15
16 16 alias SSD1322.SPIConnection
17 17
  @@ -66,17 +66,28 @@ defmodule SSD1322.Device do
66 66 end
67 67
68 68 def clear(%__MODULE__{width: width, height: height} = device, grey \\ 0) do
69 - draw(device, :binary.copy(<<grey::4, grey::4>>, div(width * height, 2)))
69 + draw(device, :binary.copy(<<grey::4, grey::4>>, div(width * height, 2)), {0, 0}, {width, height})
70 70 end
71 71
72 - def draw(%__MODULE__{conn: conn, width: width, height: height}, binary) do
73 - # GDRAM writes word-wise (16 bits at a time), and each pixel is 4 bits, so the width in RAM is width/4.
74 - # We write our pixels inthe the middle of each GDRAM row
75 - width_to_write = div(width, 4)
76 - offset = div(@gdram_row_width - width_to_write, 2)
72 + # This function does not perform any clipping or validation on the given binary other than to other than to
73 + # validate that its x offset and width are both multiples of 4
74 + def draw(%__MODULE__{conn: conn, width: display_width}, binary, {x, y}, {width, height}) do
75 + if rem(x, 4) != 0, do: raise("Cannot draw when x is not divisible by 4 (x=#{x})")
76 + if rem(width, 4) != 0, do: raise("Cannot draw when width is not divisible by 4 (width=#{width})")
77 77
78 - SPIConnection.command(conn, <<0x15>>, <<offset, offset + width_to_write - 1>>)
79 - SPIConnection.command(conn, <<0x75>>, <<0, height - 1>>)
78 + # Memory row widths don't know anything about the actual number of pixels on the device. The SSD1322 chip
79 + # supports displays up to 480 pixels wide, and if a display is narrower than that its pixels are centered in the
80 + # memory row. As a consequence, pixel column 0 on the display is actually (480 - display_width) / 2 bytes into the
81 + # row.
82 + display_zero = div(@gdram_row_width - display_width, 2)
83 + offset = display_zero + x
84 +
85 + # GDRAM addresses 16 bit words, and each pixel is 4 bits, so offsets / widths need to divide by 4
86 + offset_to_write = div(offset, 4)
87 + width_to_write = div(width, 4)
88 +
89 + SPIConnection.command(conn, <<0x15>>, <<offset_to_write, offset_to_write + width_to_write - 1>>)
90 + SPIConnection.command(conn, <<0x75>>, <<y, y + height - 1>>)
80 91 SPIConnection.command(conn, <<0x5C>>, binary)
81 92 end
82 93 end
Loading more files…