Skip to content

Commit f88e4db

Browse files
committed
initial commit
0 parents  commit f88e4db

File tree

11 files changed

+762
-0
lines changed

11 files changed

+762
-0
lines changed

.github/workflows/build.yml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: build
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
env:
8+
CARGO_TERM_COLOR: always
9+
10+
jobs:
11+
rust:
12+
runs-on: ${{ matrix.os }}
13+
strategy:
14+
matrix:
15+
os: [macos-latest, ubuntu-latest, windows-latest]
16+
steps:
17+
- uses: actions/checkout@v2
18+
- uses: dorny/paths-filter@v2
19+
id: changes
20+
with:
21+
filters: |
22+
rust:
23+
- '**.rs'
24+
- 'Cargo.lock'
25+
- '.github/workflows/**'
26+
- if: steps.changes.outputs.rust == 'true'
27+
run: cargo build
28+
rustdoc:
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v2
32+
- uses: dorny/paths-filter@v2
33+
id: changes
34+
with:
35+
filters: |
36+
rust:
37+
- '**.rs'
38+
- 'Cargo.lock'
39+
- '.github/workflows/**'
40+
- if: steps.changes.outputs.rust == 'true'
41+
run: cargo doc

.github/workflows/lint.yml

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: lint
2+
3+
on:
4+
- push
5+
- pull_request
6+
7+
env:
8+
CARGO_TERM_COLOR: always
9+
10+
jobs:
11+
rustfmt:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
- uses: dorny/paths-filter@v2
16+
id: changes
17+
with:
18+
filters: |
19+
rust:
20+
- '**.rs'
21+
- 'rustfmt.toml'
22+
- '.github/workflows/**'
23+
- if: steps.changes.outputs.rust == 'true'
24+
uses: actions-rs/toolchain@v1
25+
with:
26+
toolchain: nightly
27+
components: rustfmt
28+
override: true
29+
- if: steps.changes.outputs.rust == 'true'
30+
run: cargo fmt --check
31+

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Cargo.lock
2+
/target/
3+
**/*.rs.bk

Cargo.toml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
name = "hcms-29xx"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors = ["nonik0"]
6+
categories = ["embedded", "no-std"]
7+
description = "Driver for HCMS-29XX and HCMS-39XX display ICs"
8+
license = "MIT"
9+
repository = "https://github.com/nonik0/hcms-29xx"
10+
readme = "README.md"
11+
12+
[dependencies]
13+
embedded-hal = "1.0.0"
14+
avr-progmem = "0.4.0" # TODO: use as feature
15+
16+
# The latest releases of `proc-macro2` do not support the rust toolchain that
17+
# we use. Thus, we must fix this dependency to an older version where our
18+
# toolchain is still supported. See https://github.com/Rahix/avr-hal/issues/537
19+
[build-dependencies.proc-macro2]
20+
version = "=1.0.79"
21+
22+
#[[example]]
23+
#name = "arduino-uno"
24+
25+
#[dependencies.arduino-hal]
26+
#path = "../../arduino-hal/"
27+
#features = ["arduino-uno"]

README.md

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# HCMS-29xx Driver
2+
3+
[![Crates.io](https://img.shields.io/crates/v/hcms-29xx)](https://crates.io/crates/hcms-29xx)
4+
[![Crates.io](https://img.shields.io/crates/d/hcms-29xx)](https://crates.io/crates/hcms-29xx)
5+
[![docs.rs](https://img.shields.io/docsrs/hcms-29xx)](https://docs.rs/hcms-29xx/latest/hcms-29xx/)
6+
7+
[![lint](https://github.com/gleich/hcms-29xx/actions/workflows/lint.yml/badge.svg)](https://github.com/gleich/hcms-29xx/actions/workflows/lint.yml)
8+
[![build](https://github.com/gleich/hcms-29xx/actions/workflows/build.yml/badge.svg)](https://github.com/gleich/hcms-29xx/actions/workflows/build.yml)
9+
10+
Driver for [HCMS-29XX](https://docs.broadcom.com/doc/HCMS-29xx-Series-High-Performance-CMOS-5-x-7-Alphanumeric-Displays) and [HCMS-39XX](https://docs.broadcom.com/doc/AV02-0868EN) display ICs. Many thanks for @Andy4495's existing [HCMS39XX](https://github.com/Andy4495/HCMS39xx) Arduino/C++ library, which I used for a reference implementation.
11+
12+
## Features:
13+
* Single dependency on embedded-hal v1.0
14+
* Examples for Arduino Uno using avr-hal
15+
* TBD
16+
17+
## Install
18+
19+
To install this driver in your project add the following line to your `Cargo.toml`'s `dependencies` table:
20+
21+
```toml
22+
hcms-29xx = "0.1.0"
23+
```
24+
25+
## TODO
26+
- [ ] Arduino Uno sample
27+
- [ ] Test on other hardware, add feature flags if needed for specific functionality (e.g. progmem for AVR)
28+
- [ ] Katakana font

examples/arduino-uno.rs

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use panic_halt as _;
5+
6+
const NUM_CHARS: usize = 8;
7+
const MESSAGE: &[u8] = b"Hello from Rust on Arduino!";
8+
9+
#[arduino_hal::entry]
10+
fn main() -> ! {
11+
let dp = arduino_hal::Peripherals::take().unwrap();
12+
let pins = arduino_hal::pins!(dp);
13+
14+
// modify pin assignments to match wiring, if optional pins are not specified the logic
15+
// level must set as appropriate externally with pull-up/down resistors or other means
16+
let mut display = hcms29xx::Hcms29xx::new(
17+
NUM_CHARS, // Number of characters in the display
18+
pins.d0.into_output().downgrade(), // Data pin
19+
pins.d1.into_output().downgrade(), // Clock pin
20+
pins.d2.into_output().downgrade(), // Chip select pin
21+
pins.d3.into_output().downgrade(), // Reset pin
22+
Some(pins.d4.into_output().downgrade()), // Optional: Enable pin
23+
Some(pins.d5.into_output().downgrade()), // Optional: Write pin
24+
Some(pins.d6.into_output().downgrade()), // Optional: Read pin
25+
)
26+
.unwrap();
27+
28+
display.begin().unwrap();
29+
display.display_unblank().unwrap();
30+
31+
display.set_current(1).unwrap(); // set current (0-3) to 1
32+
//display.set_brightness(15).unwrap(); // set brightness (0-15) to max
33+
//display.set_int_osc().unwrap(); // set internal oscillator (default internal)
34+
35+
// show a scrolling message, wrapping around at the end
36+
let mut cursor: usize = 0;
37+
loop {
38+
let mut buf = [0; NUM_CHARS];
39+
40+
for i in 0..NUM_CHARS {
41+
let index = (cursor + i as usize) % MESSAGE.len();
42+
buf[i as usize] = MESSAGE[index];
43+
}
44+
45+
display.print_c_string(&buf).unwrap();
46+
cursor = (cursor + 1) % MESSAGE.len();
47+
arduino_hal::delay_ms(30);
48+
}
49+
}

rust-toolchain.toml

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[toolchain]
2+
channel = "nightly-2024-03-22"
3+
components = ["rust-src"]
4+
profile = "minimal"

src copy/main.rs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#![no_std]
2+
#![no_main]
3+
4+
use panic_halt as _;
5+
6+
const NUM_CHARS: usize = 8;
7+
const MESSAGE: &[u8] = b"Stella and Beau and Stevie and Louie and ";
8+
9+
#[arduino_hal::entry]
10+
fn main() -> ! {
11+
let dp = arduino_hal::Peripherals::take().unwrap();
12+
let pins = arduino_hal::pins!(dp);
13+
14+
let mut led_pin = pins.d13.into_output();
15+
16+
// high impedance pins
17+
pins.sck.into_floating_input();
18+
pins.mosi.into_floating_input();
19+
pins.d9.into_floating_input();
20+
pins.d5.into_floating_input();
21+
22+
let mut display = hcms29xx::Hcms29xx::new(
23+
NUM_CHARS, // Number of characters in the display
24+
pins.d0.into_output().downgrade(), // Data pin
25+
pins.d1.into_output().downgrade(), // Clock pin
26+
pins.d11.into_output().downgrade(), // Chip select pin
27+
pins.d2.into_output().downgrade(), // Reset pin
28+
Some(pins.d3.into_output().downgrade()), // Optional: Enable pin
29+
Some(pins.d6.into_output().downgrade()), // Optional: Write pin
30+
Some(pins.d10.into_output().downgrade()), // Optional: Read pin
31+
)
32+
.unwrap();
33+
display.begin().unwrap();
34+
display.display_unblank().unwrap();
35+
display.set_current(1).unwrap();
36+
//display.set_int_osc().unwrap(); now default
37+
38+
// test max current/power draw
39+
// display.set_current(crate::hcms29xx::constants::control_word_0::current::MAX_12_8MA).unwrap();
40+
// display.set_brightness(crate::hcms29xx::constants::control_word_0::MAX_BRIGHTNESS).unwrap();
41+
42+
let mut cursor: usize = 0;
43+
let mut count: u16 = 0;
44+
let mut buf: [u8; NUM_CHARS] = [0; NUM_CHARS];
45+
loop {
46+
count = (count + 1) % 10000;
47+
if (count % 30) == 0 {
48+
cursor = (cursor + 1) % MESSAGE.len();
49+
}
50+
if (count % 500) == 0 {
51+
led_pin.toggle();
52+
}
53+
54+
for i in 0..4 {
55+
let index = (cursor + i as usize) % MESSAGE.len();
56+
buf[i as usize] = MESSAGE[index];
57+
}
58+
59+
let mut count_dec = count;
60+
for i in (0..4).rev() {
61+
buf[i as usize + 4] = if count_dec > 0 {
62+
(count_dec % 10) as u8 + b'0'
63+
} else {
64+
b' '
65+
};
66+
count_dec /= 10;
67+
}
68+
69+
display.print_c_string(&buf).unwrap();
70+
arduino_hal::delay_ms(1);
71+
}
72+
}

src/constants.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
pub const CHAR_WIDTH: usize = 5;
2+
pub const CHAR_HEIGHT: usize = 7;
3+
pub const DEVICE_CHARS: usize = 4;
4+
5+
pub const CONTROL_WORD_SELECT_BIT: u8 = 0b1000_0000; // low: control word 0, high: control word 1
6+
7+
pub mod control_word_0 {
8+
pub const BRIGHTNESS_MASK: u8 = 0b0000_1111;
9+
pub const CURRENT_MASK: u8 = 0b0011_0000;
10+
pub const WAKE_BIT: u8 = 0b0100_0000;
11+
12+
pub const MAX_BRIGHTNESS: u8 = 15;
13+
pub const DEFAULT_BRIGHTNESS: u8 = 12;
14+
pub const DEFAULT_CURRENT: u8 = current::MAX_4_0MA;
15+
16+
pub mod current {
17+
pub const MAX_4_0MA: u8 = 0b0010_0000;
18+
pub const MAX_6_4MA: u8 = 0b0001_0000;
19+
pub const MAX_9_3MA: u8 = 0b0000_0000;
20+
pub const MAX_12_8MA: u8 = 0b0011_0000;
21+
}
22+
}
23+
24+
pub mod control_word_1 {
25+
pub const DATA_OUT_BIT: u8 = 0b0000_0001; // low: serial, high: simultaneous
26+
pub const EXT_OSC_PRESCALER_BIT: u8 = 0b0000_0010; // low: clock/1, clock/8
27+
28+
pub const DEFAULT_DATA_OUT_MODE: u8 = DATA_OUT_BIT;
29+
}

0 commit comments

Comments
 (0)