Current section
4 Versions
Jump to
Current section
4 Versions
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…