You are on page 1of 121

LỜI MỞ ĐẦU

Với sự phát triển không ngừng của khoa học công nghệ, cuộc sống con
người ngày càng trở nên tiện nghi và hiện đại hơn. Điều đó đem lại cho chúng ta
nhiều giải pháp tốt hơn, đa dạng hơn trong việc xử lý những vấn đề tưởng chừng
như rất phức tạp gặp phải trong cuộc sống. Việc ứng dụng các thành tựu khoa
học kỹ thuật hiện đại trong tất cả các lĩnh vực đã và đang rất phổ biến trên toàn
thế giới, thay thế dần những phương thức thủ công , lạc hậu và ngày càng được
cải tiến hiện đại hơn ,hoàn mỹ hơn.

Cùng với sự phát triển chung đó, nước ta cũng đang mạnh mẽ tiến hành
công cuộc công nghiệp hóa và hiện đại hóa đất nước để theo kịp sự phát triển
của các nước trong khu vực và trên thế giới. Trong đó lĩnh vực điện tử đang
ngày càng đóng vai trò quan trọng trong việc phát triển kinh tế và đời sống con
người. Sự phổ biến của nó đóng góp không nhỏ tới sự phát triển của tất cả các
ngành sản xuất, giải trí, ...trong những năm gần đây đặc biệt trong lĩnh vực giải
trí, quảng cáo đã có sự phát triển mạnh mẽ với nhiều hình thức, phương pháp
tiếp cận, quảng bá và chia sẻ thông tin hiện đại và toàn diện hơn.

Với lòng đam mê, yêu thích của mình trong lĩnh vực này, nhóm đã quyết
định chọn đề tài “Quang Báo Hiển Thị Bằng Led Ma Trận” làm đề tài tốt
nghiệp.

Trong thời gian ngắn thực hiện đề tài cộng với kiến thức còn nhiều hạn
chế, nên trong tập đồ án này không tránh khỏi thiếu sót, nhóm thực hiện rất
mong được sự đóng góp ý kiến của thầy cô và các bạn sinh viên.

1
LỜI CẢM ƠN
Em xin chân thành cám ơn thầy …………………………………….đã tận
tình hướng dẫn và tạo điều kiện thuận lợi cho em có thể hoàn thành tốt đề tài
này.

Em xin chân thành cám ơn các thầy trong khoa điện tử cùng các bạn sinh
viên trong lớp đã đóng góp ý kiến và kinh nghiệm trong quá trình thực hiện đề
tài này.

Sinh viên thực hiện

aaaaaaaaaaa

2
Chương 1

1.1: Đặt vấn đề…………………………………………………..……...5


1.2: Nội dung đề tài………………..…………………………………...5
1.3: Mục đích đề tài………………..……….…………………..……… 6
1.4: Đối tượng nghiên cứu……………...……………………………….6
1.5: Lập kế hoạch nghiên cứu…………….………………………..…...6
Chương 2: Giới thiệu về bảng led matrix……………………..………….7
2.1: Một số bảng led matrix thông dụng ………………………...……7
2.2: Giới thiệu về bảng led matrix P10 trong đồ án …………...… 8
Chương 3: Khảo sát linh kiện
3.1: Arduino UNO R3 …………… ………..……………...………...9
3.2: Linh kiện khác trong bảng led matrix………………...…………32
Chương 4: Sơ đồ khối và chức năng từng khối………..………………..44
4.1: Sơ đồ khối hệ thống ……………..…………………………..….…44
4.2: Ý nghĩa từng khối………………………………………………......44

Chương 5:Sơ đồ mạch và nguyên lý hoạt động………….……..……. 52


5.1: Sơ đồ nguyên lý mạch……………..………………………….. …52
Chương6: Lưu đồ giải thuật và chương trình hoạt động ……………….…54
6.1: Lưu đồ giải thuật………………. …………………………………..54
6.2: Chương trình hoạt động…………….…………………………….57

3
CHƯƠNG 1

1.1 ĐẶT VẤN ĐỀ:


Thông tin liên lạc là vấn đề được quan tâm trong xã hội. Ngay từ ngày xưa, con
người đã biết vận dụng những gì đã có sẵn để truyền tin như lửa, âm thanh, các dấu
hiệu…
Ngày nay, với sự phát triển của xã hội thì ngày càng có nhiều cách tiếp cận với
những thông tin mới. Ta có thể biết được thông tin qua báo chí, truyền hình, mạng
internet, qua các pano, áp phích… Thông tin cần phải được truyền đi nhanh chóng, kịp
thời và phổ biến rộng rãi trong toàn xã hội. Và việc thu thập thông tin kịp thời, chính
xác là yếu tố hết sức quan trọng trong sự thành công của mọi lĩnh vực. Các thiết bị tự
động được điều khiển từ xa qua một thiết bị chủ hoặc được điều khiển trực tiếp qua hệ
thống máy tính.
Việc sử dụng vi điều khiển để điều khiển hiển thị có rất nhiều ưu điểm mà các
phương pháp truyền thống như panô, áp phích không có được như việc điều chỉnh
thông tin một cách nhanh chóng bằng cách thay đổi phần mềm. Với những lý do trên,
nhóm thực hiện đề tài đưa ra một cách thức nữa phục vụ thông tin là dùng led matrix.
Nội dung nghiên cứu của đề tài chính là tạo ra một bảng led matrix ứng dụng trong
việc hiển thị truyền thông ở các nơi công cộng như công ty, nhà xưởng, các ngã tư báo
hiệu…
Thế giới ngày càng phát triển thì lĩnh vực điều khiển cần phải được mở rộng
hơn. Việc ứng dụng mạng truyền thông công nghiệp vào sản xuất mang lại nhiều thuận
lợi cho xã hội loài người, thông tin được cập nhật nhanh chóng và được điều khiển
một cách chính xác .

1.2 NỘI DUNG ĐỀ TÀI:


- Nghiên cứu và tìm phương án điều khiển và xử lý dữ liệu cho bảng led matrix

4
hiển thị.
- Thi công bảng led matrix hiển thị kích thước 16x32 điểm ảnh.
- Viết chương trình tạo hiệu ứng và xử lý dữ liệu.

1.3 MỤC ĐÍCH ĐỂ TÀI:

- Tăng khả năng tự nghiên cứu cũng như tự học.


- Bước đầu tiếp xúc với thực tế .
- Vận dụng những kiến thức đã có đồng thời tìm tòi những kiến thức mới để
hiểu sâu sắc hơn trong lĩnh vực này.
Để thiết kế được một hệ thống như đã nêu ở trên thì người nghiên cứu phải
nắm vững kiến thức chuyên ngành điện tử, tìm hiểu, nghiên cứu qua sách vở, tài liệu
nước ngoài và dạng mạch thực tế để thi công phần cứng.
1.4 ĐỐI TƯỢNG NGHIÊN CỨU:
- Các phương án điều khiển và xử lý dữ liệu cho bảng led ma trận.
- Tìm hiểu về arduino.
- Tìm hiểu phương pháp lập trình C.
- Bảng led ma trận kích thước 16×32điểm ảnh.
1.5 LẬP KẾ HOẠCH NGHIÊN CỨU:
Để thực hiện đề tài này em đã kết hợp sử dụng nhiều phương pháp và phương tiện
hỗ trợ gồm có:
 Tham khảo tài liệu: kỹ thuật xung số, điện tử căn bản, vi điều khiển….
 Quan sát.
 Thực nghiệm.
 Tổng kết kinh nghiệm.
 Phương tiện: máy vi tính, Internet, thư viện…..

5
CHƯƠNG 2
GIỚI THIỆU VỀ BẢNG LED MATRIX
Ngày nay, các bảng led matrix ngày càng trở nên phổ biến và rất đa dạng về chủng loại
và công nghệ thay thế dần cho các hình thức truyền thống như pano, áp phích,….bởi
những tiện lợi và linh hoạt mà nó đem lại. Dưới đây, nhóm xin giới thiệu
một số kiểu bảng led matrix thường được sử dụng:

3.1 MỘT SỐ BẢNG LED MATRIX THÔNG DỤNG:

Led matrix 8x8

- Kích thước :31 mm x 31 mm x 12 mm


- Điện áp hoạt động: 5v

- Mầu sắc : đỏ,vàng ,xanh

6
Led P10

Kích thước : 16x32x18mm

Mật độ điểm ảnh : 16x32pixel

Điện áp hoạt động : 5v

Màu sắc : đỏ,xanh,RGB

2.2. GIỚI THIỆU VỀ BẢNG LED MATRIX P10 TRONG ĐỒ


ÁN:
2.2.1. Phần cứng:
- Kích thước hiển thị: chiều cao 16cm,chiều dài 96cm
- Độ phân giải (số điểm ảnh):16x96.
- Hiển thị:
o Một màu.
o Nội dung hiển thị được cho chạy theo nhiều hướng khác nhau như :cuốn từ
dưới lên, cuốn từ trên xuống, sang trái, sang phải.
2.2.2. Phần mềm:
- Dùng ngôn ngữ C lập trình cho arduino
- Phần mềm để viết chương trình IDE arduino

7
CHƯƠNG 3
KHẢO SÁT LINH KIỆN

3.1. Arduino UNO R3:


Arduino hiện nay đã được biết đến một cách rộng rãi tại Việt Nam, và trên
thế giới thì nó đã quá phổ biến! Sức mạnh của chúng ngày càng được chứng tỏ
theo thời gian với vô vàn các ứng dụng mở (open source) độc đáo được chia sẻ
rộng rãi. Nhắc tới dòng mạch Arduino dùng để lập trình, cái đầu tiên mà người
ta thường nói tới chính là dòng Arduino UNO. Hiện dòng mạch này đã phát
triển tới thế hệ thứ 3 (R3).

 Một vài thông số của Arduino UNO R3:

Vi điều khiển ATmega328 họ 8bit

Điện áp hoạt động 5V DC (chỉ được cấp qua cổng USB)

Tần số hoạt động 16 MHz

8
Dòng tiêu thụ khoảng 30mA

Điện áp vào khuyên dùng 7-12V DC

Điện áp vào giới hạn 6-20V DC

Số chân Digital I/O 14 (6 chân hardware PWM)

Số chân Analog 6 (độ phân giải 10bit)

Dòng tối đa trên mỗi chân


30 mA
I/O

Dòng ra tối đa (5V) 500 mA

Dòng ra tối đa (3.3V) 50 mA

32 KB (ATmega328) với 0.5KB dùng bởi


Bộ nhớ flash
bootloader

SRAM 2 KB (ATmega328)

EEPROM 1 KB (ATmega328)

Arduino UNO có thể sử dụng 3 vi điều khiển họ 8bit AVR là ATmega8,


ATmega168, ATmega328. Bộ não này có thể xử lí những tác vụ đơn giản như
điều khiển đèn LED nhấp nháy, xử lí tín hiệu cho xe điều khiển từ xa, làm một
trạm đo nhiệt độ - độ ẩm và hiển thị lên màn hình LCD,… hay những ứng dụng
khác.

 Năng lượng

Arduino UNO có thể được cấp nguồn 5V thông qua cổng USB hoặc cấp
nguồn ngoài với điện áp khuyên dùng là 7-12V DC và giới hạn là 6-20V.
Thường thì cấp nguồn bằng pin vuông 9V là hợp lí nhất nếu bạn không có sẵn
nguồn từ cổng USB. Nếu cấp nguồn vượt quá ngưỡng giới hạn trên, bạn sẽ làm
hỏng Arduino UNO.

 Các chân năng lượng

9
+ GND (Ground): cực âm của nguồn điện cấp cho Arduino UNO. Khi
bạn dùng các thiết bị sử dụng những nguồn điện riêng biệt thì những chân
này phải được nối với nhau.

5V: cấp điện áp 5V đầu ra. Dòng tối đa cho phép ở chân này là 500mA.

3.3V: cấp điện áp 3.3V đầu ra. Dòng tối đa cho phép ở chân này là 50mA.

+ Vin (Voltage Input): để cấp nguồn ngoài cho Arduino UNO, bạn nối cực
dương của nguồn với chân này và cực âm của nguồn với chân GND.

+ IOREF: điện áp hoạt động của vi điều khiển trên Arduino UNO có thể
được đo ở chân này. Và dĩ nhiên nó luôn là 5V. Mặc dù vậy bạn không được lấy
nguồn 5V từ chân này để sử dụng bởi chức năng của nó không phải là cấp
nguồn.

+ RESET: việc nhấn nút Reset trên board để reset vi điều khiển tương
đương với việc chân RESET được nối với GND qua 1 điện trở 10KΩ.

 Lưu ý:

Arduino UNO không có bảo vệ cắm ngược nguồn vào. Do đó bạn phải hết
sức cẩn thận, kiểm tra các cực âm – dương của nguồn trước khi cấp cho
Arduino UNO. Việc làm chập mạch nguồn vào của Arduino UNO sẽ biến nó
thành một miếng nhựa chặn giấy. mình khuyên bạn nên dùng nguồn từ cổng
USB nếu có thể.

Các chân 3.3V và 5V trên Arduino là các chân dùng để cấp nguồn ra cho
các thiết bị khác, không phải là các chân cấp nguồn vào. Việc cấp nguồn sai vị
trí có thể làm hỏng board. Điều này không được nhà sản xuất khuyến khích.

Cấp nguồn ngoài không qua cổng USB cho Arduino UNO với điện áp dưới
6V có thể làm hỏng board.

Cấp điện áp trên 13V vào chân RESET trên board có thể làm hỏng vi điều
khiển ATmega328.

Cường độ dòng điện vào/ra ở tất cả các chân Digital và Analog của
Arduino UNO nếu vượt quá 200mA sẽ làm hỏng vi điều khiển.

Cấp điệp áp trên 5.5V vào các chân Digital hoặc Analog của Arduino UNO
sẽ làm hỏng vi điều khiển.

10
Cường độ dòng điện qua một chân Digital hoặc Analog bất kì của Arduino
UNO vượt quá 40mA sẽ làm hỏng vi điều khiển. Do đó nếu không dùng để
truyền nhận dữ liệu, bạn phải mắc một điện trở hạn dòng.

 Bộ nhớ

Vi điều khiển Atmega328 tiêu chuẩn cung cấp cho người dùng:

32KB bộ nhớ Flash: những đoạn lệnh bạn lập trình sẽ được lưu trữ trong bộ
nhớ Flash của vi điều khiển. Thường thì sẽ có khoảng vài KB trong số này sẽ
được dùng cho bootloader nhưng đừng lo, bạn hiếm khi nào cần quá 20KB bộ
nhớ này đâu.

2KB cho SRAM (Static Random Access Memory): giá trị các biến bạn khai báo
khi lập trình sẽ lưu ở đây. Bạn khai báo càng nhiều biến thì càng cần nhiều bộ
nhớ RAM. Tuy vậy, thực sự thì cũng hiếm khi nào bộ nhớ RAM lại trở thành
thứ mà bạn phải bận tâm. Khi mất điện, dữ liệu trên SRAM sẽ bị mất.

1KB cho EEPROM (Electrically Eraseble Programmable Read Only Memory):


đây giống như một chiếc ổ cứng mini – nơi bạn có thể đọc và ghi dữ liệu của
mình vào đây mà không phải lo bị mất khi cúp điện giống như dữ liệu trên
SRAM.

 Các cổng ra vào:

ARDUINO có 14 chân digital dùng để đọc hoặc xuất tín hiệu. Chúng chỉ có
2 mức điện áp là 0V và 5V với dòng vào/ra tối đa trên mỗi chân là 40mA. Ở
mỗi chân đều có các điện trở pull-up từ được cài đặt ngay trong vi điều khiển
ATmega328 (mặc định thì các điện trở này không được kết nối).

Một số chân digital có các chức năng đặc biệt như sau:

2 chân Serial: 0 (RX) và 1 (TX): dùng để gửi (transmit – TX) và nhận


(receive – RX) dữ liệu TTL Serial. Arduino Uno có thể giao tiếp với thiết bị khác
thông qua 2 chân này. Kết nối bluetooth thường thấy nói nôm na chính là kết nối
Serial không dây. Nếu không cần giao tiếp Serial, bạn không nên sử dụng 2 chân
này nếu không cần thiết

Chân PWM (~): 3, 5, 6, 9, 10, và 11: cho phép bạn xuất ra xung PWM với độ
phân giải 8bit (giá trị từ 0 → 28-1 tương ứng với 0V → 5V) bằng hàm

11
analogWrite(). Nói một cách đơn giản, bạn có thể điều chỉnh được điện áp ra ở
chân này từ mức 0V đến 5V thay vì chỉ cố định ở mức 0V và 5V như những chân
khác.

Chân giao tiếp SPI: 10 (SS), 11 (MOSI), 12 (MISO), 13 (SCK). Ngoài các chức
năng thông thường, 4 chân này còn dùng để truyền phát dữ liệu bằng giao thức
SPI với các thiết bị khác.

LED 13: trên Arduino UNO có 1 đèn led màu cam (kí hiệu chữ L). Khi bấm
nút Reset, bạn sẽ thấy đèn này nhấp nháy để báo hiệu. Nó được nối với chân số
13. Khi chân này được người dùng sử dụng, LED sẽ sáng.

Arduino UNO có 6 chân analog (A0 → A5) cung cấp độ phân giải tín hiệu
10bit (0 → 210-1) để đọc giá trị điện áp trong khoảng 0V → 5V. Với
chân AREF trên board, bạn có thể để đưa vào điện áp tham chiếu khi sử dụng
các chân analog. Tức là nếu bạn cấp điện áp 2.5V vào chân này thì bạn có thể
dùng các chân analog để đo điện áp trong khoảng từ 0V → 2.5V với độ phân
giải vẫn là 10bit.

Đặc biệt, Arduino UNO có 2 chân A4 (SDA) và A5 (SCL) hỗ trợ giao tiếp
I2C/TWI với các thiết bị khác

 Lập trình cho Arduino

Để lập trình cũng như gửi lệnh và nhận tín hiệu từ mạch Arduino, nhóm
phát triển dự án này đã cũng cấp đến cho người dùng một môi trường lập
trình Arduino được gọi là Arduino IDE
(Intergrated Development Environment)

3.2 LEDMATRIX
3.2.1 Hình dạng và cấu tạo của LEDMATRIX

12
Ma trận led bao gồm nhiều led đơn bố trí thành hàng và cột trong một
vỏ. Các tín hiệu điều khiển cột đƣợc nối với Anode của tất cả các led trên
cùng một cột. Các tín hiệu điều khiển hàng cũng được nối với Cathode của tất
cả các led trên cùng một hàng như hình vẽ:

13
3.2.2 NGUYÊN LÝ HOẠT ĐỘNG
Khi có một tín hiệu điều khiển ở cột và hàng, các chân Anode của các
led trên cột tương ứng đƣợc cấp điện áp cao, đồng thời các chân Cathode của
các led trên hàng tương ứng được cấp điện áp thấp. Tuy nhiên lúc đó chỉ có
một led sáng, vì nó có đồng thời điện thế cao trên Anode và điện thế thấp trên
Cathode. Như vậy khi có một tín hiệu điều khiển hàng và cột, thi tại một thời
điểm chỉ có duy nhất một led tại chỗ gặp nhau của một hàng và cột là sáng.
Các bảng quang báo với số lượng led lớn hơn cũng được kết nối theo câu trúc
như vậy
14
Trong trường hợp ta muốn cho sáng đồng thời một số led rời rạc trên
ma trận, để hiển thị một ký tự nào đó, nếu trong hiển thị tĩnh ta phải cấp áp
cao cho Anode và áp thấp cho Cathode, cho các led tƣơng ứng mà ta muốn
sáng. Nhưng khi đó một số led ta không muốn cũng sẽ sáng, miễn là nó nằm
tại vị trí gặp nhau của các cột và hàng mà ta cấp nguồn. Vì vậy trong điều
khiển led ma trận ta không thể sử dụng phương pháp hiện thị tĩnh mà phải sử
dụng phương pháp quét ( hiển thị động ), có nghĩa là ta phải tiến hành cấp tín
hiệu điều khiển theo dạng xung quét trên các hàng và cột có led cần hiển thị.
Để đảm bảo cho mắt nhìn thấy các led không bị nháy, thì tần số quét nhỏ nhất
cho mỗi chu kỳ là khoảng 20hz(50ms). Trong lập trình điều khiển led ma trận
bằng vi xử lý ta cũng phải sử dụng phương pháp quét như vậy.
Ma trận led có thể là loại chỉ hiển thi được một màu hoặc hiển thị đƣợc
2 mày trên một điểm, khi đó led có số chân ra tƣơng ứng: đối với ma trận led
8x8 hiển thị một màu, thi số chân ra là 16, trong đó 8 chân dùng để điều khiển
hàng và 8 chân còn lại dùng để điểu khiển cột. Đối với loại 8x8 có 2 màu thi
số chân ra của led là 24 chân, trong đó 8 chân dùng để điều khiển hàng ( hoặc
cột ) chung cho cả hai màu, 16 chân còn lại thi 8 chân dùng để điểu khiển
hàng ( hoặc cột) màu thứ nhất, 8 chân còn lại dùng để điều khiển màu thứ 2.

3.2.3 LED Matrix – Module P10

Dựa trên nguyên tắc như quét màn hình tivi, máy tính, ta có thể thực
hiện việc hiển thị ma trận đèn bằng cách quét theo hàng và quét theo cột. Mỗi
Led trên ma trận Led có thể coi nhƣ một điểm ảnh. Địa chỉ của mỗi điểm ảnh
này được xác định đồng thời bởi mạch giải mã hàng và giải mã cột, điểm ảnh
này sẽ được xác định nhờ dữ liệu đƣa ra từ mạch điều khiển. Như vậy tại mỗi
thời điểm chỉ có trạng thái của một điểm ảnh xác định. Tuy nhiên khi xác định
địa chỉ và trạng thái của điểm ảnh tiếp theo thì các điểm ảnh còn lại sẽ chuyển

15
về trạng thái tắt.Vì thế để hiển thị được toàn bộ hình ảnh mà ta muốn thì ta
phải quét ma trận nhiều lần với tốc độ quét rất lớn, lớn hơn nhiều lần thời gian
kịp tắt của đèn. Mắt ngƣời chỉ nhận biết được tối đa 24 hình/s do đó nếu tốc
độ quét lớn mắt người sẽ không nhận biết được sự gián đoạn hay là nhấp nháy
của đèn Led(đánh lừa cảm giác mắt). Ứng dụng trong hiển thị Led matrix để
đảm bảo phù hợp các thông số về điện của từng Led đơn người ta không điều
khiển theo chu trình như màn hình tivi (CRT) bởi như vậy để đảm bảo độ
sáng của toàn bộ bảng led thì dòng tức thời qua từng led là vô cùng lớn do đó
có thể đánh thủng lớp tiếp giáp của led .Trên thực tế ngƣời ta có thể ghép
chung anot hoặc catot của 1 hàng hoặc 1 cột . Khi đó công việc điều khiển sẽ
là chuyển dữ liệu ra các cột và cấp điện cho hàng .Nhƣ vậy tài 1 thời điểm sẽ
có 1 hàng được điều khiển sáng theo dữ liệu đƣa ra. Ngoài ra để đảm bảo độ
sáng của bảng thông tin là tốt nhất, đặc biệt với những bảng cỡ lớn theo chiều
dọc ( có nhiều hàng), thời gian sáng của 1 hàng lúc này sẽ bị giảm đi rất nhiều
nếu dữ nguyên kiểu quét 1 hàng .Để khác phục điều này ngƣời ta sử dụng
phƣơng pháp điều khiển cho 2 hoặc 4 hàng cùng sáng, từ đó giúp giảm dòng
tức thời qua từng led mà vẫn đảm bảo độ sáng tối ƣu .Và trong đồ án này
module P10 đuợc sử dụng hoạt động trên phƣơng pháp điều khiển cùng lúc 4
hàng cùng sáng tại 1 thời điểm, sau 4 lần quét ta sẽ có 1 khung hình hoàn
thiện. 2. Module P10 a.

Thông số Module LED 16x32

Cách sử dụng Bảng ngoài trời Độ phân giải (mm) 10mm Module dày
30,5mm Kích thƣớc (mm) 320 * 160 Pixel Density (pexel / m) 10.000 Hiển
thị một màu Màu đỏ Độ phân giải (pixel) 32 * 16 Trọng lƣợng (G) 425
Khoảng cách (m) ≥ 12,5 Góc nhìn (°) lựa chọn Nghiêng 110 ± 5 độ, thẳng 60
độ. Nhiệt độ hoạt động (° C) Làm việc Nhiệt độ: -20 °C ~ 50°C Nhiệt độ lưu
trữ: -40°C ~ 85 ° C Độ ẩm hoạt động 10 ~ 95% Công suất Trung bình (W /

16
m²) 100 ~ 300 Công suất tiêu thụ tối đa (W / m²) ≤ 500 Chế độ kiểm soát
Không đồng bộ Chế độ quét 1/4 quét bởi áp Constant Cân bằng trắng Độ sáng

(cd / m²) ≥ 2000 Lớp chống thấm nước IP51 MTTF ≥ 10.000 Tuổi thọ (giờ) ≥
100,000 Nguồn điện sử dụng 5V/20A chuyên dụng.

Nguyên lý hoạt động:


Giản đồ xung điều khiển mudue : Các đường điều khiển gồm : - Tín
hiệu OE : tích cực mức logic cao (5V) cho phép chốt hàng ( hàng tƣơng ứng
với 2 tín hiệu A,B được nối đất ) - Tín hiệu chọn hàng : A,B là 2 đường tín
hiệu cho phép chọn hàng hiển thị

- Tín hiệu CLK : Tín hiệu cho phép chốt dữ liệu ra cột . - Tín hiệu SCK
: xung đưa dữ liệu ra IC ghi dịch . - Tín hiệu DATA: đưa dữ liệu cần hiển thị
ra bảng led. - Sơ đồ quét của mudule : + Quét theo tỉ lệ ¼ + Tất cả module có
16 dòng,32 cột .Tại 1 thời điểm nhất định sẽ có 4 dòng đồng thời được nối với
nguồn Vcc (được cho phép sáng )

17
Lý do chọn loại modul này:
P10 – 1R là loại module LED rất phổ biến trên thị trƣờng và đang đƣợc sử

18
dụng rộng rãi tại Việt Nam. +Cách điều khiển đơn giản. +Phù hợp với các bảng
thông tin điện tử cỡ vừa và nhỏ. + Cấu tạo đơn giản, rễ dàng lắp đặt , sửa chữa .
+ Mở rộng kích thước bảng đơn giản, không cần thay đổi phần cứng . + Độ
sáng phù hợp với các bảng thông tin ngoài trời . +Sử dụng, lắp đặt đơn giản.
+Giá thành không quá đắt (200.000VND / 1module - giá bán lẻ )

3.3 IC 74HC595

3.3.1 Chức năng:

Là một IC ghi dịch 8 bit kết hợp chốt dữ liệu, đầu vào nối tiếp đầu ra
song song. Chức năng thƣờng đƣợc dung trong các mạch quét led 7 thanh, led
matrix… để tiết kiệm số chân VDK tối đa ( 3 chân ). Có thể mở rộng số chân
vi điều khiển bao nhiêu tùy thích mà không IC nào có thể làm đƣợc bằng cách
nối tiếp đầu vào dữ liệu các ic với nhau.

3.3.2 Sơ đồ chân:

19
Hình 2.7: Sơ đồ chân 74HC595

Giải thích ý nghĩa hoạt động của một số chân quan trọng:
(input)
Chân 14 : đầu vào dữ liệu nối tiếp . Tại 1 thời điểm xung clock chỉ đưa
vào được 1 bit

(output)
QA=>QH : trên các chân (15,1,2,3,4,5,6,7)
Xuất dữ liệu khi chân chân 13 tích cực ở mức thấp và có một xung tích
cực ở sườn âm tại chân chốt 12
(output-enable)
Chân 13 : Chân cho phép tích cực ở mức thấp (0) .Khi ở mức cao, tất
cả các đầu ra của 74595 trở về trạng thái cao trở, không có đầu ra nào được
cho phép.
(SQH)
Chân 9: Chân dữ liệu nối tiếp . Nếu dùng nhiều 74595 mắc nối tiếp
nhau thì chân này đƣa vào đầu vào của con tiếp theo khi đã dịch đủ 8bit.
(Shift clock)

20
Chân 11: Chân vào xung clock . Khi có 1 xung clock tích cực ở sƣờn
dƣơng(từ 0 lên 1) thì 1bit đƣợc dịch vào ic.
(Latch clock)
Chân 12 : xung clock chốt dữ liệu . Khi có 1 xung clock tích cực ở
sƣờn dƣơng thì cho phép xuất dữ liệu trên các chân output . lƣu ý có thể xuất
dữ liệu bất kỳ lúc nào bạn muốn ,ví dụ đầu vào chân 14 dc 2 bit khi có xung
clock ở chân 12 thì dữ liệu sẽ ra ở chân Qa và Qb (chú ý chiều dịch dữ liệu từ
Qa=>Qh)
(Reset)
Chân 10: khi chân này ở mức thấp(mức 0) thì dữ liệu sẽ bị xóa trên chip)
Sơ đồ hoạt động của chip:

3.3.3 Bảng thông số chip:

Đây là ic đầu ra hoạt động ở 2 mức 0 &1 dòng ra tầm 35mA . điện áp
hoạt động <=7V . Công suất trung bình 500mW.
3.3.4 Tần số đáp ứng:

21
3.4 Bluetooth HC06
Với thiết kế nhỏ gọn, tiện lợi, giao tiếp với vi điều khiển chỉ bằng 2 chân (Tx và
Rx), module bluetooth HC06 sẽ giúp bạn thực hiện các dự án truyền dẫn và điều
khiển từ xa một cách dễ dàng.
Điểm khác biệt so với HC05 đó là HC06 chỉ có thể chạy được 1 chế độ Slave
(khác với HC05 có thể hoạt động với chế độ Mater hoặc Slave). Điều này có
nghĩa là bạn không thể chủ động kết nối từ vi điều khiển đến các thiết bị ngoại
vi. Mà cách kết nối là: bạn phải sử dụng thiết bị ngoại vi (điện thoại thông minh,
máy tính laptop) để dò tín hiệu kêt nối Buletooth mà HC06 phát ra. Sau khi pair
thành công bạn có thể gửi tín hiệu từ vi điều khiển đến các thiết bị ngoại vi này,
và ngược lại.
Thông số kĩ thuật
 Điện áp hoạt động: 3V3-5V DC
 Dòng điện tiêu thụ: 20-30mA
 Nhiệt độ hoạt động: -20~75°C
 Sử dụng chip: CSR Bluetooth V2.0
 Cấu hình Slave mặc định, không thay đổi được.
 Hỗ trợ tốc độ baud: 200,2400,4800,9600, 19200,38400,57600,
115200
 Kích thước: 28x15x2,35mm
 Giao tiếp: UART (TX,RX)
 Tốc độ:

22
 Bất đồng bộ: 2.1Mbps(Max)/160kbps
 Đồng bộ: 1Mbps/1Mbps
 Bảo mật: mã hóa và chứng thực
 Cấu hình mặc định:
 Tốc độ baud 9600, N, 8, 1
 Mật khẩu: 1234

23
24
CHƯƠNG 4
SƠ ĐỒ KHỐI VÀ CHỨC NĂNG
TỪNG KHỐI
5.1 SƠ ĐỒ KHỐI HỆ THỐNG:

4.2 Ý NGHĨA TỪNG KHỐI:

25
4.2.1 Khối điều khiển:

Khối điều khiển: Được thiết kế bởi Arduino UNO R3 có nhiệm vụ xử lý tất cả các
dữ liệu của chương trình. Điều khiển dữ liệu hiển thị. Điều khiển xuất nhập dữ liệu.
Điều khiển truy xuất dữ liệu và xử lý sau đó truyền đến các khối: công suất, chốt và
đệm để hiển thị trên Led ma trận.

4.2.2 Khối công suất:


Nâng công suất đủ lớn để cung cấp cho khối hiển thị.
Nếu ta dùng các IC để thúc công suất thì ta sẽ có dòng ngõ ra cố định, khi muốn
dùng tải công suất lớn hơn thì ta khó có thể sửa đổi lại mạch công suất được. Và một
điều nữa là theo tính toán, dòng điện ở mỗi hàng có thể lên tới vài trăm mA , giá trị
này cao hơn nhiều so với dòng ngõ cực đại của IC .Do đó cần phải thiết kế mạch để
thúc công suất cho tải.

4.2.3 Khối hiển thị:

Có nhiệm vụ dịch chuyển dữ liệu ra các cột, đệm tăng dòng đủ lớn để điều
khiển hiển thị các yêu cầu của người sử dụng.
Khối hiển thị làm nhiệm vụ dịch dữ liệu từ vi điều khiển, chốt dữ liệu, đệm dữ
liệu đủ dòng và hiển thị trên Led ma trận .

4.2.4 Khối nguồn:

Trong một mạch điện tử thì bộ nguồn có vai trò rất quan trọng, nó quyết định
sự hoạt động hay ngưng hoạt động của mạch. Một bộ nguồn không tốt sẽ làm cho
mạch hoạt động kém ổn định và dể làm hỏng linh kiện. Vì vậy bộ nguồn ổn áp tốt sẽ
rất cần thiết cho các mạch điện tử ( mạch dùng các IC số).

Chức năng của mọi ổn áp DC là biến đổi điện áp vào DC chưa ổn định thành
điện áp ra DC ổn định và giá trị điện áp này phải đúng với giá trị khi tính toán lý
thuyết. Điện áp này phải được duy trì liên tục và không thay đổi khi điện áp ngõ vào

26
hoặc dòng tải thay đổi (ở một giới hạn cho phép của mạch). Để thực hiện điều này thì
một nguồn ổn áp thường gồm các phần sau:

Hình 5.6: Sơ đồ khối của khối nguồn.

* Khối chỉnh lưu và lọc: có nhiệm vụ đổi điện áp xoay chiều thành điện áp một chiều
và lọc.
* Khối công suất: cung cấp dòng chính cho tải.
* Khối lấy mẫu: lấy một điện áp từ ngõ ra đưa về so sánh với Vref để điều khiển ổn
định điện áp.

27
CHƯƠNG 5
SƠ ĐÔ NGUYÊN LÍ

28
29
CHƯƠNG 6
LƯU ĐỒ GIẢI THUẬT VÀ CHƯƠNG TRÌNH
HOẠT ĐỘNG
Ý TƯỞNG THIẾT KẾ PHẦN MỀM:
Bảng quang báo chạy text với font t tiếng Anh, chạy từ trái sang phải, từ phải sang
trái, chạy từ trên xuống dưới, từ dưới lên trên.
- Tạo font chữ và giải mã.
- Vi điều khiển lưu vào vùng nhớ trong ROM sau đó vi điều khiển lấy dữ liệu
điều khiển hiển thị ra màn hình led ma trận thông qua mạch công suất và mạch hiển
thị.

6.1. LƯU DỒ THUẬT TOÁN

30
31
6.2 CHƯƠNG TRÌ NH

6.2.1: Các thư viêṇ

a. Arial14.h

#include <inttypes.h>

32
#include <avr/pgmspace.h>

#ifndef ARIAL_14_H

#define ARIAL_14_H

#define ARIAL_14_WIDTH 10

#define ARIAL_14_HEIGHT 14

const static uint8_t Arial_14[] PROGMEM = {

0x1E, 0x6C, // size

0x0A, // width

0x0E, // height

0x20, // first char

0x60, // char count

// char widths

0x00, 0x01, 0x03, 0x08, 0x07, 0x0A, 0x08, 0x01, 0x03, 0x03,

0x05, 0x07, 0x01, 0x04, 0x01, 0x04, 0x06, 0x03, 0x06, 0x06,

0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01, 0x06, 0x06,

0x06, 0x06, 0x0D, 0x09, 0x07, 0x08, 0x08, 0x07, 0x07, 0x09,

0x07, 0x01, 0x05, 0x08, 0x07, 0x09, 0x07, 0x09, 0x07, 0x09,

0x08, 0x07, 0x07, 0x07, 0x09, 0x0D, 0x08, 0x09, 0x08, 0x02,
33
0x04, 0x02, 0x05, 0x08, 0x02, 0x06, 0x06, 0x05, 0x06, 0x06,

0x04, 0x06, 0x06, 0x01, 0x02, 0x06, 0x01, 0x09, 0x06, 0x06,

0x06, 0x06, 0x04, 0x05, 0x04, 0x06, 0x07, 0x09, 0x06, 0x07,

0x06, 0x03, 0x01, 0x03, 0x07, 0x07,

// font data

0xFE, 0x14, // 33

0x1E, 0x00, 0x1E, 0x00, 0x00, 0x00, // 34

0x90, 0x90, 0xF8, 0x96, 0x90, 0xF8, 0x96, 0x90, 0x00, 0x1C, 0x00, 0x00, 0x1C,
0x00, 0x00, 0x00, // 35

0x18, 0x24, 0x22, 0xFF, 0x42, 0x42, 0x84, 0x08, 0x10, 0x10, 0x3C, 0x10, 0x08,
0x04, // 36

0x1C, 0x22, 0x22, 0x1C, 0xC0, 0x30, 0x8C, 0x42, 0x40, 0x80, 0x00, 0x00, 0x10,
0x0C, 0x00, 0x00, 0x0C, 0x10, 0x10, 0x0C, // 37

0x80, 0x5C, 0x22, 0x62, 0x92, 0x0C, 0x80, 0x00, 0x0C, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x08, 0x10, // 38

0x1E, 0x00, // 39

0xF0, 0x0C, 0x02, 0x1C, 0x60, 0x80, // 40

0x02, 0x0C, 0xF0, 0x80, 0x60, 0x1C, // 41

0x04, 0x14, 0x0E, 0x14, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, // 42

0x40, 0x40, 0x40, 0xF8, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00,
0x00, // 43

0x00, 0x70, // 44

34
0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, // 45

0x00, 0x10, // 46

0x00, 0xC0, 0x38, 0x06, 0x18, 0x04, 0x00, 0x00, // 47

0xFC, 0x02, 0x02, 0x02, 0x02, 0xFC, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x0C, // 48

0x08, 0x04, 0xFE, 0x00, 0x00, 0x1C, // 49

0x0C, 0x02, 0x02, 0x82, 0x42, 0x3C, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, // 50

0x0C, 0x02, 0x22, 0x22, 0x22, 0xDC, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x0C, // 51

0x80, 0x40, 0x30, 0x08, 0x04, 0xFE, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1C,
0x04, // 52

0x38, 0x16, 0x12, 0x12, 0x12, 0xE2, 0x0C, 0x10, 0x10, 0x10, 0x18, 0x04, // 53

0xF8, 0x44, 0x22, 0x22, 0x22, 0xC4, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x0C, // 54

0x02, 0x02, 0x02, 0xE2, 0x1A, 0x06, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, // 55

0xDC, 0x22, 0x22, 0x22, 0x22, 0xDC, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x0C, // 56

0x3C, 0x42, 0x42, 0x42, 0x22, 0xFC, 0x08, 0x10, 0x10, 0x10, 0x08, 0x04, // 57

0x08, 0x10, // 58

0x08, 0x70, // 59

0x40, 0xA0, 0xA0, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00, 0x04, 0x04, 0x08, // 60

0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 61

0x08, 0x10, 0x10, 0xA0, 0xA0, 0x40, 0x08, 0x04, 0x04, 0x00, 0x00, 0x00, // 62

0x0C, 0x02, 0x82, 0x42, 0x22, 0x1C, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, // 63

0xE0, 0x18, 0x04, 0xC4, 0x22, 0x12, 0x12, 0x12, 0xA2, 0x72, 0x04, 0x08, 0xF0,
0x0C, 0x30, 0x40, 0x4C, 0x90, 0x90, 0x90, 0x88, 0x9C, 0x90, 0x50, 0x4C, 0x20, //
64
35
0x00, 0x80, 0xE0, 0x9C, 0x82, 0x9C, 0xE0, 0x80, 0x00, 0x18, 0x04, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04, 0x18, // 65

0xFE, 0x22, 0x22, 0x22, 0x22, 0x22, 0xDC, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10,
0x0C, // 66

0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x04, 0x08, 0x04, 0x08, 0x10, 0x10, 0x10,
0x10, 0x08, 0x04, // 67

0xFE, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x1C, 0x10, 0x10, 0x10, 0x10,
0x10, 0x08, 0x04, // 68

0xFE, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, // 69

0xFE, 0x22, 0x22, 0x22, 0x22, 0x22, 0x02, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // 70

0xF8, 0x04, 0x02, 0x02, 0x02, 0x42, 0x42, 0x44, 0xC8, 0x04, 0x08, 0x10, 0x10,
0x10, 0x10, 0x10, 0x08, 0x04, // 71

0xFE, 0x20, 0x20, 0x20, 0x20, 0x20, 0xFE, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1C, // 72

0xFE, 0x1C, // 73

0x00, 0x00, 0x00, 0x00, 0xFE, 0x0C, 0x10, 0x10, 0x10, 0x0C, // 74

0xFE, 0x80, 0x40, 0x20, 0x50, 0x88, 0x04, 0x02, 0x1C, 0x00, 0x00, 0x00, 0x00,
0x04, 0x08, 0x10, // 75

0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, // 76

0xFE, 0x0C, 0x30, 0xC0, 0x00, 0xC0, 0x30, 0x0C, 0xFE, 0x1C, 0x00, 0x00,
0x04, 0x18, 0x04, 0x00, 0x00, 0x1C, // 77

36
0xFE, 0x04, 0x18, 0x60, 0x80, 0x00, 0xFE, 0x1C, 0x00, 0x00, 0x00, 0x04, 0x08,
0x1C, // 78

0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x04, 0x08, 0x10, 0x10,
0x10, 0x10, 0x10, 0x08, 0x04, // 79

0xFE, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // 80

0xF8, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0xF8, 0x04, 0x08, 0x10, 0x10,
0x10, 0x14, 0x08, 0x1C, 0x10, // 81

0xFE, 0x42, 0x42, 0x42, 0xC2, 0x42, 0x42, 0x3C, 0x1C, 0x00, 0x00, 0x00, 0x00,
0x04, 0x08, 0x10, // 82

0x1C, 0x22, 0x22, 0x22, 0x42, 0x42, 0x8C, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x10,
0x0C, // 83

0x02, 0x02, 0x02, 0xFE, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00,
0x00, // 84

0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x04, 0x08, 0x10, 0x10, 0x10, 0x08,
0x04, // 85

0x06, 0x18, 0x60, 0x80, 0x00, 0x80, 0x60, 0x18, 0x06, 0x00, 0x00, 0x00, 0x04,
0x18, 0x04, 0x00, 0x00, 0x00, // 86

0x06, 0x38, 0xC0, 0x00, 0xC0, 0x3C, 0x02, 0x3C, 0xC0, 0x00, 0xC0, 0x38, 0x06,
0x00, 0x00, 0x04, 0x18, 0x04, 0x00, 0x00, 0x00, 0x04, 0x18, 0x04, 0x00, 0x00, // 87

0x02, 0x0C, 0x90, 0x60, 0x60, 0x90, 0x0C, 0x02, 0x10, 0x0C, 0x00, 0x00, 0x00,
0x04, 0x0C, 0x10, // 88

0x02, 0x04, 0x18, 0x20, 0xC0, 0x20, 0x18, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00,
0x1C, 0x00, 0x00, 0x00, 0x00, // 89

0x00, 0x02, 0x82, 0x42, 0x22, 0x1A, 0x06, 0x02, 0x10, 0x18, 0x14, 0x10, 0x10,
0x10, 0x10, 0x10, // 90
37
0xFE, 0x02, 0xFC, 0x80, // 91

0x06, 0x38, 0xC0, 0x00, 0x00, 0x00, 0x04, 0x18, // 92

0x02, 0xFE, 0x80, 0xFC, // 93

0x20, 0x1C, 0x02, 0x1C, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, // 94

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, // 95

0x02, 0x04, 0x00, 0x00, // 96

0x10, 0x88, 0x48, 0x48, 0x48, 0xF0, 0x0C, 0x10, 0x10, 0x10, 0x08, 0x1C, // 97

0xFE, 0x10, 0x08, 0x08, 0x08, 0xF0, 0x1C, 0x08, 0x10, 0x10, 0x10, 0x0C, // 98

0xF0, 0x08, 0x08, 0x08, 0x10, 0x0C, 0x10, 0x10, 0x10, 0x08, // 99

0xF0, 0x08, 0x08, 0x08, 0x10, 0xFE, 0x0C, 0x10, 0x10, 0x10, 0x08, 0x1C, // 100

0xF0, 0x48, 0x48, 0x48, 0x48, 0x70, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x08, // 101

0x08, 0xFC, 0x0A, 0x0A, 0x00, 0x1C, 0x00, 0x00, // 102

0xF0, 0x08, 0x08, 0x08, 0x10, 0xF8, 0x4C, 0x90, 0x90, 0x90, 0x88, 0x7C, // 103

0xFE, 0x10, 0x08, 0x08, 0x08, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x1C, // 104

0xFA, 0x1C, // 105

0x00, 0xFA, 0x80, 0x7C, // 106

0xFE, 0x80, 0x40, 0xA0, 0x10, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x0C, 0x10, // 107

0xFE, 0x1C, // 108

0xF8, 0x10, 0x08, 0x08, 0xF0, 0x10, 0x08, 0x08, 0xF0, 0x1C, 0x00, 0x00, 0x00,
0x1C, 0x00, 0x00, 0x00, 0x1C, // 109

0xF8, 0x10, 0x08, 0x08, 0x08, 0xF0, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x1C, // 110

38
0xF0, 0x08, 0x08, 0x08, 0x08, 0xF0, 0x0C, 0x10, 0x10, 0x10, 0x10, 0x0C, // 111

0xF8, 0x10, 0x08, 0x08, 0x08, 0xF0, 0xFC, 0x08, 0x10, 0x10, 0x10, 0x0C, // 112

0xF0, 0x08, 0x08, 0x08, 0x10, 0xF8, 0x0C, 0x10, 0x10, 0x10, 0x08, 0xFC, // 113

0xF8, 0x10, 0x08, 0x08, 0x1C, 0x00, 0x00, 0x00, // 114

0x30, 0x48, 0x48, 0x48, 0x90, 0x08, 0x10, 0x10, 0x10, 0x0C, // 115

0x08, 0xFE, 0x08, 0x08, 0x00, 0x1C, 0x10, 0x10, // 116

0xF8, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0C, 0x10, 0x10, 0x10, 0x08, 0x1C, // 117

0x18, 0x60, 0x80, 0x00, 0x80, 0x60, 0x18, 0x00, 0x00, 0x04, 0x18, 0x04, 0x00,
0x00, // 118

0x18, 0xE0, 0x00, 0xE0, 0x18, 0xE0, 0x00, 0xE0, 0x18, 0x00, 0x04, 0x18, 0x04,
0x00, 0x04, 0x18, 0x04, 0x00, // 119

0x08, 0x30, 0xC0, 0xC0, 0x30, 0x08, 0x10, 0x0C, 0x00, 0x00, 0x0C, 0x10, // 120

0x18, 0x60, 0x80, 0x00, 0x80, 0x60, 0x18, 0x00, 0x80, 0x8C, 0x70, 0x0C, 0x00,
0x00, // 121

0x08, 0x08, 0x88, 0x68, 0x18, 0x08, 0x10, 0x18, 0x14, 0x10, 0x10, 0x10, // 122

0x80, 0x7C, 0x02, 0x00, 0x7C, 0x80, // 123

0xFE, 0xFC, // 124

0x02, 0x7C, 0x80, 0x80, 0x7C, 0x00, // 125

0x40, 0x20, 0x20, 0x60, 0x40, 0x40, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // 126

0xFC, 0x04, 0x04, 0x04, 0x04, 0x04, 0xFC, 0x1C, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1C // 127

39
};

#endif

B. Arial_Black_16_ISO_8859_1.h

#include <inttypes.h>

#include <avr/pgmspace.h>

#ifndef ARIAL_BLACK_16_ISO_8859_1_H

#define ARIAL_BLACK_16_ISO_8859_1_H

#define ARIAL_BLACK_16_ISO_8859_1_WIDTH 10

#define ARIAL_BLACK_16_ISO_8859_1_HEIGHT 16

const static uint8_t Arial_Black_16_ISO_8859_1[] PROGMEM =

0x64, 0x36,

0x0A,

0x10,

0x20,

0xE0,
40
0x00, 0x03, 0x07, 0x08, 0x07, 0x0B, 0x0A, 0x03, 0x04, 0x04,

0x05, 0x06, 0x03, 0x04, 0x03, 0x04, 0x07, 0x06, 0x07, 0x07,

0x09, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x07, 0x07,

0x07, 0x07, 0x0A, 0x09, 0x08, 0x08, 0x08, 0x07, 0x07, 0x09,

0x09, 0x03, 0x08, 0x0A, 0x07, 0x0A, 0x09, 0x09, 0x07, 0x09,

0x09, 0x07, 0x09, 0x09, 0x09, 0x0D, 0x09, 0x0A, 0x07, 0x05,

0x04, 0x05, 0x06, 0x07, 0x03, 0x08, 0x08, 0x08, 0x08, 0x08,

0x05, 0x08, 0x08, 0x03, 0x03, 0x09, 0x03, 0x0B, 0x08, 0x08,

0x08, 0x08, 0x06, 0x07, 0x06, 0x08, 0x08, 0x0C, 0x09, 0x08,

0x06, 0x04, 0x02, 0x04, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,

0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,

0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,

0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x03,

0x08, 0x07, 0x08, 0x09, 0x02, 0x08, 0x04, 0x0A, 0x05, 0x07,

0x07, 0x04, 0x0A, 0x07, 0x03, 0x06, 0x05, 0x05, 0x03, 0x08,

0x09, 0x00, 0x04, 0x03, 0x05, 0x07, 0x0C, 0x0C, 0x0D, 0x07,

0x09, 0x09, 0x09, 0x09, 0x09, 0x0A, 0x0C, 0x08, 0x07, 0x07,

0x07, 0x07, 0x03, 0x04, 0x05, 0x05, 0x09, 0x09, 0x09, 0x09,

0x09, 0x09, 0x09, 0x07, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0A,

0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0C, 0x08,

0x08, 0x08, 0x08, 0x08, 0x03, 0x04, 0x04, 0x04, 0x08, 0x08,

0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x08, 0x08, 0x08, 0x08,
41
0x08, 0x08, 0x08, 0x08,

// font data

0xF8, 0xF8, 0xF8, 0x1D, 0x1D, 0x1D, // 33

0x38, 0x38, 0x38, 0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // 34

0x60, 0x60, 0xE0, 0xF8, 0x78, 0xE0, 0xF8, 0x78, 0x06, 0x1E, 0x1F, 0x07, 0x1E,
0x1F, 0x07, 0x06, // 35

0x70, 0xF8, 0x98, 0xFC, 0x98, 0xB8, 0x30, 0x0C, 0x1C, 0x19, 0x3F, 0x19, 0x1F,
0x0F, // 36

0x70, 0xF8, 0x88, 0xF8, 0x70, 0x80, 0x60, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00,
0x10, 0x0C, 0x02, 0x01, 0x0E, 0x1F, 0x11, 0x1F, 0x0E, // 37

0x00, 0x70, 0xF8, 0xD8, 0xD8, 0x78, 0x30, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0x1F,
0x19, 0x1B, 0x1F, 0x1F, 0x0E, 0x0F, 0x1F, // 38

0x38, 0x38, 0x38, 0x00, 0x00, 0x00, // 39

0x80, 0xE0, 0x70, 0x10, 0x1F, 0x7F, 0xE0, 0x80, // 40

0x10, 0x70, 0xE0, 0x80, 0x80, 0xE0, 0x7F, 0x1F, // 41

0x10, 0x50, 0x38, 0x50, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, // 42

0x80, 0x80, 0xE0, 0xE0, 0x80, 0x80, 0x01, 0x01, 0x07, 0x07, 0x01, 0x01, // 43

0x00, 0x00, 0x00, 0xDC, 0x7C, 0x3C, // 44

0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, // 45

0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, // 46

0x00, 0x00, 0xE0, 0x18, 0x18, 0x07, 0x00, 0x00, // 47

42
0xE0, 0xF0, 0xF8, 0x18, 0xF8, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x18, 0x1F, 0x0F,
0x07, // 48

0xC0, 0xC0, 0x60, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, // 49

0x30, 0x38, 0x38, 0x18, 0xF8, 0xF0, 0xE0, 0x18, 0x1C, 0x1E, 0x1F, 0x1B, 0x19,
0x18, // 50

0x30, 0x38, 0x38, 0x98, 0xF8, 0xF0, 0x60, 0x0C, 0x1C, 0x1C, 0x19, 0x1F, 0x0F,
0x06, // 51

0x00, 0x80, 0xC0, 0x60, 0x30, 0xF8, 0xF8, 0xF8, 0x00, 0x07, 0x07, 0x07, 0x06,
0x06, 0x1F, 0x1F, 0x1F, 0x06, // 52

0xC0, 0xF8, 0xF8, 0xD8, 0xD8, 0xD8, 0x98, 0x0C, 0x1D, 0x1C, 0x18, 0x1F, 0x0F,
0x07, // 53

0xE0, 0xF0, 0xF8, 0x18, 0xB8, 0xB8, 0x30, 0x07, 0x0F, 0x1F, 0x19, 0x1F, 0x1F,
0x0F, // 54

0x18, 0x18, 0x18, 0xD8, 0xF8, 0x78, 0x18, 0x00, 0x1C, 0x1F, 0x1F, 0x03, 0x00,
0x00, // 55

0x70, 0xF8, 0xF8, 0x98, 0xF8, 0xF8, 0x70, 0x0E, 0x1F, 0x1F, 0x19, 0x1F, 0x1F,
0x0E, // 56

0xF0, 0xF8, 0xF8, 0x98, 0xF8, 0xF0, 0xE0, 0x0C, 0x1D, 0x1D, 0x18, 0x1F, 0x0F,
0x07, // 57

0xC0, 0xC0, 0xC0, 0x1D, 0x1D, 0x1D, // 58

0xC0, 0xC0, 0xC0, 0xDD, 0x7D, 0x3D, // 59

0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0x60, 0x03, 0x03, 0x03, 0x06, 0x06, 0x06,
0x0C, // 60

0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, // 61

43
0x60, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x0C, 0x06, 0x06, 0x06, 0x03, 0x03,
0x03, // 62

0x30, 0x38, 0x18, 0x98, 0xF8, 0xF8, 0x70, 0x00, 0x00, 0x1B, 0x1B, 0x1B, 0x00,
0x00, // 63

0xC0, 0x20, 0x90, 0xC8, 0x28, 0xC8, 0xE8, 0xE8, 0x10, 0xE0, 0x07, 0x08, 0x17,
0x2F, 0x28, 0x2F, 0x2F, 0x28, 0x14, 0x13, // 64

0x00, 0xE0, 0xF8, 0xF8, 0x38, 0xF8, 0xF8, 0xE0, 0x00, 0x1C, 0x1F, 0x1F, 0x07,
0x06, 0x07, 0x1F, 0x1F, 0x1C, // 65

0xF8, 0xF8, 0xF8, 0x98, 0x98, 0xF8, 0xF8, 0x70, 0x1F, 0x1F, 0x1F, 0x19, 0x19,
0x1F, 0x1F, 0x0E, // 66

0xE0, 0xF0, 0xF8, 0x18, 0x18, 0x38, 0x30, 0x20, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1E, 0x0E, 0x04, // 67

0xF8, 0xF8, 0xF8, 0x18, 0x18, 0xF8, 0xF0, 0xE0, 0x1F, 0x1F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 68

0xF8, 0xF8, 0xF8, 0x98, 0x98, 0x98, 0x98, 0x1F, 0x1F, 0x1F, 0x19, 0x19, 0x19,
0x19, // 69

0xF8, 0xF8, 0xF8, 0x98, 0x98, 0x98, 0x18, 0x1F, 0x1F, 0x1F, 0x01, 0x01, 0x01,
0x00, // 70

0xC0, 0xF0, 0xF8, 0x38, 0x18, 0x98, 0xB8, 0xB8, 0xB0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x19, 0x1F, 0x0F, 0x0F, // 71

0xF8, 0xF8, 0xF8, 0x80, 0x80, 0x80, 0xF8, 0xF8, 0xF8, 0x1F, 0x1F, 0x1F, 0x01,
0x01, 0x01, 0x1F, 0x1F, 0x1F, // 72

0xF8, 0xF8, 0xF8, 0x1F, 0x1F, 0x1F, // 73

0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x06, 0x0E, 0x1E, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 74

44
0xF8, 0xF8, 0xF8, 0xC0, 0xE0, 0xF0, 0xB8, 0x18, 0x08, 0x00, 0x1F, 0x1F, 0x1F,
0x01, 0x00, 0x03, 0x0F, 0x1F, 0x1C, 0x10, // 75

0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x18, 0x18, 0x18,
0x18, // 76

0xF8, 0xF8, 0x78, 0xE0, 0x00, 0x00, 0xE0, 0x78, 0xF8, 0xF8, 0x1F, 0x1F, 0x00,
0x03, 0x1F, 0x1F, 0x03, 0x00, 0x1F, 0x1F, // 77

0xF8, 0xF8, 0x70, 0xE0, 0xC0, 0x80, 0x00, 0xF8, 0xF8, 0x1F, 0x1F, 0x00, 0x01,
0x03, 0x07, 0x0E, 0x1F, 0x1F, // 78

0xE0, 0xF0, 0xF8, 0x38, 0x18, 0x38, 0xF8, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0F, 0x07, // 79

0xF8, 0xF8, 0xF8, 0x98, 0xF8, 0xF8, 0xF0, 0x1F, 0x1F, 0x1F, 0x01, 0x01, 0x01,
0x00, // 80

0xE0, 0xF0, 0xF8, 0x18, 0x18, 0x38, 0xF8, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x18,
0x1E, 0x1C, 0x1F, 0x1F, 0x37, // 81

0xF8, 0xF8, 0xF8, 0x98, 0x98, 0xF8, 0xF8, 0xF0, 0x00, 0x1F, 0x1F, 0x1F, 0x01,
0x03, 0x0F, 0x1E, 0x1C, 0x10, // 82

0x70, 0xF8, 0xF8, 0x98, 0x98, 0xB8, 0x30, 0x0C, 0x1C, 0x19, 0x19, 0x1F, 0x1F,
0x0F, // 83

0x18, 0x18, 0x18, 0xF8, 0xF8, 0xF8, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x1F,
0x1F, 0x1F, 0x00, 0x00, 0x00, // 84

0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0x07, 0x0F, 0x1F, 0x18,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 85

0x18, 0xF8, 0xF8, 0xE0, 0x00, 0xE0, 0xF8, 0xF8, 0x18, 0x00, 0x00, 0x07, 0x1F,
0x1C, 0x1F, 0x07, 0x00, 0x00, // 86

0x18, 0xF8, 0xF8, 0x00, 0xC0, 0xF8, 0x78, 0xF8, 0xC0, 0x00, 0xF8, 0xF8, 0x18,
0x00, 0x03, 0x1F, 0x1F, 0x1F, 0x07, 0x00, 0x07, 0x1F, 0x1F, 0x1F, 0x03, 0x00, // 87

45
0x08, 0x38, 0x78, 0xF0, 0xC0, 0xF0, 0x78, 0x38, 0x08, 0x10, 0x1C, 0x1F, 0x0F,
0x03, 0x0F, 0x1F, 0x1C, 0x10, // 88

0x08, 0x18, 0x78, 0xF0, 0xE0, 0x80, 0xE0, 0xF0, 0x78, 0x18, 0x00, 0x00, 0x00,
0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, // 89

0x18, 0x18, 0x18, 0x98, 0xF8, 0x78, 0x38, 0x1C, 0x1E, 0x1F, 0x19, 0x18, 0x18,
0x18, // 90

0xF0, 0xF0, 0xF0, 0x30, 0x30, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, // 91

0x18, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x07, 0x18, // 92

0x30, 0x30, 0xF0, 0xF0, 0xF0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, // 93

0x80, 0xE0, 0x38, 0x38, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 94

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, // 95

0x08, 0x18, 0x10, 0x00, 0x00, 0x00, // 96

0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x0D, 0x1D, 0x1D, 0x1A,
0x0A, 0x1F, 0x1F, 0x1F, // 97

0xF8, 0xF8, 0xF8, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x1F, 0x1F, 0x1F, 0x08, 0x18,
0x1F, 0x1F, 0x0F, // 98

0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1D, 0x0D, 0x05, // 99

0x80, 0xC0, 0xC0, 0xC0, 0x80, 0xF8, 0xF8, 0xF8, 0x0F, 0x1F, 0x1F, 0x18, 0x08,
0x1F, 0x1F, 0x1F, // 100

0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x1A, 0x1A,
0x1B, 0x1B, 0x0B, // 101

0xF0, 0xF8, 0xF8, 0xC8, 0x08, 0x1F, 0x1F, 0x1F, 0x00, 0x00, // 102

46
0x80, 0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0xC0, 0x4F, 0xDF, 0xDF, 0xD8,
0xC8, 0xFF, 0xFF, 0x7F, // 103

0xF8, 0xF8, 0xF8, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x1F, 0x1F, 0x1F, 0x00, 0x00,
0x1F, 0x1F, 0x1F, // 104

0xD8, 0xD8, 0xD8, 0x1F, 0x1F, 0x1F, // 105

0xD8, 0xD8, 0xD8, 0xFF, 0xFF, 0x7F, // 106

0xF8, 0xF8, 0xF8, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x00, 0x1F, 0x1F, 0x1F, 0x07,
0x07, 0x0F, 0x1E, 0x18, 0x10, // 107

0xF8, 0xF8, 0xF8, 0x1F, 0x1F, 0x1F, // 108

0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x1F, 0x1F,
0x1F, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x1F, 0x1F, 0x1F, // 109

0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x1F, 0x1F, 0x1F, 0x00, 0x00,
0x1F, 0x1F, 0x1F, // 110

0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 111

0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0xFF, 0xFF, 0xFF, 0x08, 0x18,
0x1F, 0x1F, 0x0F, // 112

0x80, 0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0xC0, 0x0F, 0x1F, 0x1F, 0x18, 0x08,
0xFF, 0xFF, 0xFF, // 113

0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0x40, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, // 114

0x80, 0xC0, 0xC0, 0x40, 0x40, 0xC0, 0x80, 0x09, 0x1B, 0x13, 0x17, 0x1E, 0x1E,
0x0C, // 115

0xC0, 0xF0, 0xF0, 0xF8, 0xC0, 0x00, 0x00, 0x0F, 0x1F, 0x1F, 0x18, 0x18, // 116

0xC0, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0x0F, 0x1F, 0x1F, 0x18, 0x08,
0x1F, 0x1F, 0x1F, // 117

47
0xC0, 0xC0, 0x80, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x01, 0x07, 0x1F, 0x1C, 0x1F,
0x07, 0x01, 0x00, // 118

0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x40, 0x03,
0x1F, 0x1F, 0x1C, 0x07, 0x01, 0x07, 0x1C, 0x1F, 0x1F, 0x03, 0x00, // 119

0x40, 0xC0, 0xC0, 0x80, 0x00, 0x80, 0xC0, 0xC0, 0x40, 0x10, 0x18, 0x1F, 0x0F,
0x07, 0x0F, 0x1F, 0x18, 0x10, // 120

0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0x40, 0xC3, 0xCF, 0xFF, 0xF8, 0x7F,
0x0F, 0x03, 0x00, // 121

0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x18, 0x1C, 0x1E, 0x1B, 0x19, 0x18, // 122

0x00, 0xE0, 0xF0, 0x30, 0x06, 0x7F, 0xF9, 0xC0, // 123

0xF8, 0xF8, 0xFF, 0xFF, // 124

0x30, 0xF0, 0xE0, 0x00, 0xC0, 0xF9, 0x7F, 0x06, // 125

0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, 0x03, 0x01, 0x01, 0x03, 0x03, 0x03,
0x01, // 126

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 127

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 128

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 129

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 130

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 131

48
0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 132

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 133

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 134

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 135

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 136

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 137

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 138

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 139

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 140

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 141

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 142

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 143

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 144

49
0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 145

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 146

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 147

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 148

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 149

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 150

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 151

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 152

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 153

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 154

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 155

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 156

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 157

50
0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 158

0xE0, 0x20, 0x20, 0x20, 0x20, 0x20, 0xE0, 0x1F, 0x10, 0x10, 0x10, 0x10, 0x10,
0x1F, // 159

0xC0, 0xC0, 0xC0, 0xFD, 0xFD, 0xFD, // 161

0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xF0, 0x80, 0x00, 0x07, 0x0F, 0x7F, 0x1E, 0x19,
0x1D, 0x0D, 0x05, // 162

0xF0, 0xF8, 0xD8, 0xD8, 0xD8, 0x18, 0x10, 0x1C, 0x0F, 0x0F, 0x0C, 0x18, 0x18,
0x08, // 163

0x40, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0x40, 0x08, 0x1F, 0x0F, 0x0C, 0x0C,
0x0F, 0x1F, 0x08, // 164

0x88, 0xB8, 0xF8, 0xF0, 0xC0, 0xF0, 0xF8, 0xB8, 0x88, 0x0D, 0x0D, 0x0D, 0x1F,
0x1F, 0x1F, 0x0D, 0x0D, 0x0D, // 165

0xF8, 0xF8, 0xF9, 0xF9, // 166

0x00, 0xF0, 0xF8, 0xF8, 0xD8, 0x98, 0xB8, 0x30, 0x63, 0x67, 0xCF, 0xCE, 0xDD,
0xFF, 0xFF, 0x77, // 167

0x18, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, // 168

0xC0, 0x30, 0xD0, 0xE8, 0x28, 0x28, 0x68, 0x50, 0x30, 0xC0, 0x03, 0x0C, 0x0B,
0x17, 0x14, 0x14, 0x16, 0x0A, 0x0C, 0x03, // 169

0xC8, 0xE8, 0xA8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, // 170

0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x02, 0x0F, 0x1D, 0x13, 0x0F, 0x1D,
0x10, // 171

0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
0x07, // 172

0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x06, 0x06, // 173

51
0xC0, 0x30, 0x10, 0xE8, 0xE8, 0x28, 0xE8, 0xD0, 0x30, 0xC0, 0x03, 0x0C, 0x08,
0x17, 0x17, 0x11, 0x17, 0x0C, 0x0C, 0x03, // 174

0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // 175

0x38, 0x28, 0x38, 0x00, 0x00, 0x00, // 176

0xC0, 0xC0, 0xF0, 0xF0, 0xC0, 0xC0, 0x18, 0x18, 0x1B, 0x1B, 0x18, 0x18, // 177

0x90, 0xD8, 0xE8, 0xB8, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x00, // 178

0x90, 0x98, 0xA8, 0xF8, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, // 179

0x10, 0x18, 0x08, 0x00, 0x00, 0x00, // 180

0xC0, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0x18, 0x18,
0x1F, 0x1F, 0x1F, // 181

0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0x18, 0xF8, 0xF8, 0x18, 0x00, 0x01, 0x01, 0xFF,
0xFF, 0x00, 0xFF, 0xFF, 0x00, // 182

0x00, 0x00, 0x00, 0x00, 0xA0, 0xA0, 0xE0, 0xE0, // 184

0x10, 0xF8, 0xF8, 0x00, 0x00, 0x00, // 185

0x70, 0xF8, 0x88, 0xF8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, // 186

0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x1D, 0x0F, 0x12, 0x1C, 0x0F,
0x02, // 187

0x10, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x80, 0x60, 0x10, 0x08, 0x00, 0x00, 0x00,
0x00, 0x10, 0x08, 0x06, 0x01, 0x00, 0x0C, 0x0E, 0x0A, 0x1F, 0x1F, // 188

0x10, 0xF8, 0xF8, 0x00, 0x00, 0x80, 0x60, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00,
0x10, 0x08, 0x06, 0x01, 0x00, 0x00, 0x12, 0x1B, 0x1D, 0x17, 0x16, // 189

52
0x90, 0x98, 0xA8, 0xF8, 0x50, 0x00, 0x00, 0x80, 0x60, 0x10, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x08, 0x06, 0x01, 0x00, 0x0C, 0x0E, 0x0A, 0x1F, 0x1F, //
190

0x00, 0x00, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x70, 0xF8, 0xFE, 0xCE, 0xC6, 0xE0,
0x60, // 191

0x00, 0xE0, 0xF8, 0xF9, 0x3B, 0xFA, 0xF8, 0xE0, 0x00, 0x1C, 0x1F, 0x1F, 0x07,
0x06, 0x07, 0x1F, 0x1F, 0x1C, // 192

0x00, 0xE0, 0xF8, 0xF8, 0x3A, 0xFB, 0xF9, 0xE0, 0x00, 0x1C, 0x1F, 0x1F, 0x07,
0x06, 0x07, 0x1F, 0x1F, 0x1C, // 193

0x00, 0xE0, 0xFA, 0xFB, 0x39, 0xFB, 0xFA, 0xE0, 0x00, 0x1C, 0x1F, 0x1F, 0x07,
0x06, 0x07, 0x1F, 0x1F, 0x1C, // 194

0x00, 0xE0, 0xF8, 0xFB, 0x39, 0xFA, 0xFB, 0xE0, 0x00, 0x1C, 0x1F, 0x1F, 0x07,
0x06, 0x07, 0x1F, 0x1F, 0x1C, // 195

0x00, 0xE0, 0xFB, 0xFB, 0x38, 0xFB, 0xFB, 0xE0, 0x00, 0x1C, 0x1F, 0x1F, 0x07,
0x06, 0x07, 0x1F, 0x1F, 0x1C, // 196

0x00, 0x00, 0xC0, 0xF8, 0xFC, 0x3A, 0xFC, 0xF8, 0xC0, 0x00, 0x10, 0x1E, 0x1F,
0x0F, 0x07, 0x06, 0x06, 0x07, 0x1F, 0x1E, // 197

0x00, 0x00, 0xC0, 0xF0, 0xF8, 0x18, 0xF8, 0xF8, 0xF8, 0x98, 0x98, 0x98, 0x10,
0x1E, 0x1F, 0x07, 0x06, 0x06, 0x1F, 0x1F, 0x1F, 0x19, 0x19, 0x19, // 198

0xE0, 0xF0, 0xF8, 0x18, 0x18, 0x38, 0x30, 0x20, 0x07, 0x0F, 0xBF, 0xB8, 0xF8,
0xFE, 0x0E, 0x04, // 199

0xF8, 0xF8, 0xF9, 0x9B, 0x9A, 0x98, 0x98, 0x1F, 0x1F, 0x1F, 0x19, 0x19, 0x19,
0x19, // 200

0xF8, 0xF8, 0xF8, 0x9A, 0x9B, 0x99, 0x98, 0x1F, 0x1F, 0x1F, 0x19, 0x19, 0x19,
0x19, // 201

53
0xF8, 0xFA, 0xFB, 0x99, 0x9B, 0x9A, 0x98, 0x1F, 0x1F, 0x1F, 0x19, 0x19, 0x19,
0x19, // 202

0xF8, 0xFB, 0xFB, 0x98, 0x9B, 0x9B, 0x98, 0x1F, 0x1F, 0x1F, 0x19, 0x19, 0x19,
0x19, // 203

0xF9, 0xFB, 0xFA, 0x1F, 0x1F, 0x1F, // 204

0xF8, 0xFA, 0xFB, 0x01, 0x1F, 0x1F, 0x1F, 0x00, // 205

0x02, 0xFB, 0xF9, 0xFB, 0x02, 0x00, 0x1F, 0x1F, 0x1F, 0x00, // 206

0x03, 0xFB, 0xF8, 0xFB, 0x03, 0x00, 0x1F, 0x1F, 0x1F, 0x00, // 207

0x80, 0xF8, 0xF8, 0xF8, 0x98, 0x18, 0xF8, 0xF0, 0xE0, 0x00, 0x1F, 0x1F, 0x1F,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 208

0xF8, 0xF8, 0x70, 0xE3, 0xC1, 0x82, 0x03, 0xF8, 0xF8, 0x1F, 0x1F, 0x00, 0x01,
0x03, 0x07, 0x0E, 0x1F, 0x1F, // 209

0xE0, 0xF0, 0xF8, 0x39, 0x1B, 0x3A, 0xF8, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0F, 0x07, // 210

0xE0, 0xF0, 0xF8, 0x38, 0x1A, 0x3B, 0xF9, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0F, 0x07, // 211

0xE0, 0xF0, 0xFA, 0x3B, 0x19, 0x3B, 0xFA, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0F, 0x07, // 212

0xE0, 0xF0, 0xF8, 0x3B, 0x19, 0x3A, 0xFB, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0F, 0x07, // 213

0xE0, 0xF0, 0xFB, 0x3B, 0x18, 0x3B, 0xFB, 0xF0, 0xE0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0F, 0x07, // 214

0x40, 0xE0, 0xC0, 0x80, 0xC0, 0xE0, 0x40, 0x04, 0x0E, 0x07, 0x03, 0x07, 0x0E,
0x04, // 215

54
0xE0, 0xF0, 0xF8, 0x38, 0x98, 0xD8, 0xF8, 0xF0, 0xF8, 0x1F, 0x0F, 0x1F, 0x1B,
0x19, 0x1C, 0x1F, 0x0F, 0x07, // 216

0xF8, 0xF8, 0xF8, 0x01, 0x03, 0x02, 0xF8, 0xF8, 0xF8, 0x07, 0x0F, 0x1F, 0x18,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 217

0xF8, 0xF8, 0xF8, 0x00, 0x02, 0x03, 0xF9, 0xF8, 0xF8, 0x07, 0x0F, 0x1F, 0x18,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 218

0xF8, 0xF8, 0xFA, 0x03, 0x01, 0x03, 0xFA, 0xF8, 0xF8, 0x07, 0x0F, 0x1F, 0x18,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 219

0xF8, 0xF8, 0xFB, 0x03, 0x00, 0x03, 0xFB, 0xF8, 0xF8, 0x07, 0x0F, 0x1F, 0x18,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 220

0x08, 0x18, 0x78, 0xF0, 0xE0, 0x82, 0xE3, 0xF1, 0x78, 0x18, 0x00, 0x00, 0x00,
0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, // 221

0xF8, 0xF8, 0xF8, 0x60, 0xE0, 0xE0, 0xC0, 0x1F, 0x1F, 0x1F, 0x06, 0x07, 0x07,
0x03, // 222

0xE0, 0xF0, 0xF8, 0x18, 0x98, 0xF8, 0xF8, 0x30, 0x1F, 0x1F, 0x1F, 0x00, 0x19,
0x1B, 0x1F, 0x0E, // 223

0x80, 0xC0, 0xC8, 0xD8, 0xD0, 0xC0, 0xC0, 0x80, 0x0D, 0x1D, 0x1D, 0x1A,
0x0A, 0x1F, 0x1F, 0x1F, // 224

0x80, 0xC0, 0xC0, 0xD0, 0xD8, 0xC8, 0xC0, 0x80, 0x0D, 0x1D, 0x1D, 0x1A,
0x0A, 0x1F, 0x1F, 0x1F, // 225

0x80, 0xC0, 0xD0, 0xD8, 0xC8, 0xD8, 0xD0, 0x80, 0x0D, 0x1D, 0x1D, 0x1A,
0x0A, 0x1F, 0x1F, 0x1F, // 226

0x80, 0xC0, 0xD8, 0xC8, 0xD0, 0xD8, 0xC0, 0x80, 0x0D, 0x1D, 0x1D, 0x1A,
0x0A, 0x1F, 0x1F, 0x1F, // 227

0x80, 0xC0, 0xD8, 0xD8, 0xC0, 0xD8, 0xD8, 0x80, 0x0D, 0x1D, 0x1D, 0x1A,
0x0A, 0x1F, 0x1F, 0x1F, // 228

55
0x80, 0xC0, 0xC0, 0xDC, 0xD4, 0xDC, 0xC0, 0x80, 0x0D, 0x1D, 0x1D, 0x1A,
0x0A, 0x1F, 0x1F, 0x1F, // 229

0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80,
0x0D, 0x1D, 0x1D, 0x1A, 0x1A, 0x0F, 0x0F, 0x1F, 0x1A, 0x1B, 0x1B, 0x0B, // 230

0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x07, 0x0F, 0xBF, 0xB8, 0xF8,
0xFD, 0x0D, 0x05, // 231

0x00, 0x80, 0xC8, 0xD8, 0xD0, 0xC0, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x1A, 0x1A,
0x1B, 0x1B, 0x0B, // 232

0x00, 0x80, 0xC0, 0xD0, 0xD8, 0xC8, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x1A, 0x1A,
0x1B, 0x1B, 0x0B, // 233

0x00, 0x80, 0xD0, 0xD8, 0xC8, 0xD8, 0x90, 0x00, 0x07, 0x0F, 0x1F, 0x1A, 0x1A,
0x1B, 0x1B, 0x0B, // 234

0x00, 0x80, 0xD8, 0xD8, 0xC0, 0xD8, 0x98, 0x00, 0x07, 0x0F, 0x1F, 0x1A, 0x1A,
0x1B, 0x1B, 0x0B, // 235

0xC8, 0xD8, 0xD0, 0x1F, 0x1F, 0x1F, // 236

0xC0, 0xD0, 0xD8, 0x08, 0x1F, 0x1F, 0x1F, 0x00, // 237

0xD8, 0xC8, 0xD8, 0x10, 0x1F, 0x1F, 0x1F, 0x00, // 238

0xD8, 0xC0, 0xD8, 0x18, 0x1F, 0x1F, 0x1F, 0x00, // 239

0x00, 0x80, 0xE0, 0xD8, 0xF8, 0xF8, 0xE8, 0x80, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 240

0xC0, 0xC0, 0xD8, 0x88, 0xD0, 0xD8, 0xC0, 0x80, 0x1F, 0x1F, 0x1F, 0x00, 0x00,
0x1F, 0x1F, 0x1F, // 241

0x00, 0x80, 0xC8, 0xD8, 0xD0, 0xC0, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 242

56
0x00, 0x80, 0xC0, 0xD0, 0xD8, 0xC8, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 243

0x00, 0x80, 0xD0, 0xD8, 0xC8, 0xD8, 0x90, 0x00, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 244

0x00, 0x80, 0xD8, 0xC8, 0xD0, 0xD8, 0x80, 0x00, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 245

0x00, 0x80, 0xD8, 0xD8, 0xC0, 0xD8, 0x98, 0x00, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 246

0x80, 0x80, 0xB8, 0xB8, 0xB8, 0x80, 0x80, 0x01, 0x01, 0x1D, 0x1D, 0x1D, 0x01,
0x01, // 247

0x00, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x20, 0x27, 0x1F, 0x1F, 0x1E, 0x19,
0x1F, 0x0F, 0x07, // 248

0xC0, 0xC0, 0xC8, 0x18, 0x10, 0xC0, 0xC0, 0xC0, 0x0F, 0x1F, 0x1F, 0x18, 0x08,
0x1F, 0x1F, 0x1F, // 249

0xC0, 0xC0, 0xC0, 0x10, 0x18, 0xC8, 0xC0, 0xC0, 0x0F, 0x1F, 0x1F, 0x18, 0x08,
0x1F, 0x1F, 0x1F, // 250

0xC0, 0xC0, 0xD0, 0x18, 0x08, 0xD8, 0xD0, 0xC0, 0x0F, 0x1F, 0x1F, 0x18, 0x08,
0x1F, 0x1F, 0x1F, // 251

0xC0, 0xC0, 0xD8, 0x18, 0x00, 0xD8, 0xD8, 0xC0, 0x0F, 0x1F, 0x1F, 0x18, 0x08,
0x1F, 0x1F, 0x1F, // 252

0xC0, 0xC0, 0x00, 0x10, 0x18, 0xC8, 0xC0, 0x40, 0xC3, 0xCF, 0xFF, 0xF8, 0x7F,
0x0F, 0x03, 0x00, // 253

0xF8, 0xF8, 0xF8, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0xFF, 0xFF, 0xFF, 0x08, 0x18,
0x1F, 0x1F, 0x0F, // 254

0xC0, 0xD8, 0x18, 0x00, 0x18, 0xD8, 0xC0, 0x40, 0xC3, 0xCF, 0xFF, 0xF8, 0x7F,
0x0F, 0x03, 0x00 // 255

57
};

#endif

C. Arial_black_16.h

#include <inttypes.h>

#include <avr/pgmspace.h>

#ifndef ARIAL_BLACK_16_H

#define ARIAL_BLACK_16_H

#define ARIAL_BLACK_16_WIDTH 10

#define ARIAL_BLACK_16_HEIGHT 16

const static uint8_t Arial_Black_16[] PROGMEM = {

0x30, 0x86, // size

0x0A, // width

0x10, // height

0x20, // first char

0x60, // char count

// char widths
58
0x00, 0x03, 0x07, 0x0B, 0x09, 0x0E, 0x0B, 0x03, 0x05, 0x05,

0x06, 0x09, 0x03, 0x05, 0x03, 0x04, 0x08, 0x06, 0x08, 0x08,

0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x03, 0x03, 0x09, 0x08,

0x09, 0x08, 0x0C, 0x0C, 0x09, 0x09, 0x09, 0x09, 0x08, 0x0A,

0x0A, 0x03, 0x09, 0x0C, 0x08, 0x0C, 0x0A, 0x0A, 0x09, 0x0A,

0x0A, 0x09, 0x0B, 0x0A, 0x0C, 0x10, 0x0C, 0x0B, 0x09, 0x05,

0x04, 0x05, 0x08, 0x08, 0x03, 0x09, 0x09, 0x09, 0x09, 0x09,

0x06, 0x09, 0x09, 0x03, 0x04, 0x0A, 0x03, 0x0D, 0x09, 0x09,

0x09, 0x09, 0x06, 0x08, 0x06, 0x09, 0x09, 0x0F, 0x0B, 0x09,

0x07, 0x06, 0x02, 0x06, 0x09, 0x08,

// font data

0xFE, 0xFE, 0xFE, 0x1D, 0x1D, 0x1D, // 33

0x1E, 0x1E, 0x1E, 0x00, 0x1E, 0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, // 34

0x30, 0x30, 0xF0, 0xFE, 0x3E, 0x30, 0x30, 0xF0, 0xFE, 0x3E, 0x30, 0x06, 0x1E,
0x1F, 0x07, 0x06, 0x06, 0x1E, 0x1F, 0x07, 0x06, 0x06, // 35

0x38, 0x7C, 0xFE, 0xE6, 0xFF, 0xC6, 0xCE, 0x8C, 0x0C, 0x04, 0x0C, 0x1C,
0x18, 0x3F, 0x19, 0x1F, 0x0F, 0x07, // 36

0x3C, 0x7E, 0x42, 0x42, 0x7E, 0x3C, 0x80, 0x60, 0x10, 0x8C, 0x82, 0x80, 0x80,
0x00, 0x00, 0x00, 0x00, 0x10, 0x0C, 0x02, 0x01, 0x00, 0x0F, 0x1F, 0x10, 0x10,
0x1F, 0x0F, // 37

59
0x00, 0x80, 0x9C, 0xFE, 0xFE, 0xE6, 0xBE, 0x3E, 0x9C, 0x80, 0x80, 0x07, 0x0F,
0x1F, 0x19, 0x18, 0x19, 0x1F, 0x0F, 0x0F, 0x1F, 0x1D, // 38

0x1E, 0x1E, 0x1E, 0x00, 0x00, 0x00, // 39

0xE0, 0xF8, 0xFC, 0x1E, 0x02, 0x0F, 0x3F, 0x7F, 0xF0, 0x80, // 40

0x02, 0x1E, 0xFC, 0xF8, 0xE0, 0x80, 0xF0, 0x7F, 0x3F, 0x0F, // 41

0x08, 0x68, 0x3E, 0x3E, 0x68, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 42

0xC0, 0xC0, 0xC0, 0xF8, 0xF8, 0xF8, 0xC0, 0xC0, 0xC0, 0x01, 0x01, 0x01, 0x0F,
0x0F, 0x0F, 0x01, 0x01, 0x01, // 43

0x00, 0x00, 0x00, 0xDC, 0x7C, 0x3C, // 44

0x80, 0x80, 0x80, 0x80, 0x80, 0x03, 0x03, 0x03, 0x03, 0x03, // 45

0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, // 46

0x00, 0x80, 0x78, 0x06, 0x18, 0x07, 0x00, 0x00, // 47

0xF8, 0xFC, 0xFE, 0x06, 0x06, 0xFE, 0xFC, 0xF8, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 48

0x60, 0x70, 0x38, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, // 49

0x18, 0x1C, 0x1E, 0x06, 0x86, 0xFE, 0xFC, 0x78, 0x18, 0x1C, 0x1E, 0x1F, 0x1B,
0x19, 0x18, 0x18, // 50

0x08, 0x1C, 0x1E, 0xC6, 0xC6, 0xFE, 0xFC, 0x38, 0x06, 0x0E, 0x1E, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 51

0x80, 0xC0, 0xF0, 0x38, 0x1C, 0xFE, 0xFE, 0xFE, 0x00, 0x03, 0x03, 0x03, 0x03,
0x03, 0x1F, 0x1F, 0x1F, 0x03, // 52

0xF0, 0xFE, 0xFE, 0x66, 0x66, 0xE6, 0xC6, 0x86, 0x06, 0x0E, 0x1E, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 53

60
0xF0, 0xFC, 0xFE, 0x46, 0x66, 0xEE, 0xCE, 0x8C, 0x03, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 54

0x06, 0x06, 0x06, 0x86, 0xE6, 0xF6, 0x1E, 0x06, 0x00, 0x00, 0x1C, 0x1F, 0x1F,
0x01, 0x00, 0x00, // 55

0x38, 0xFC, 0xFE, 0xC6, 0xC6, 0xFE, 0xFC, 0x38, 0x07, 0x0F, 0x1F, 0x18, 0x18,
0x1F, 0x0F, 0x07, // 56

0x78, 0xFC, 0xFE, 0x86, 0x86, 0xFE, 0xFC, 0xF0, 0x04, 0x0C, 0x1D, 0x19, 0x18,
0x1F, 0x0F, 0x03, // 57

0x70, 0x70, 0x70, 0x1C, 0x1C, 0x1C, // 58

0x70, 0x70, 0x70, 0xDC, 0x7C, 0x3C, // 59

0xE0, 0xE0, 0xE0, 0xF0, 0x70, 0x70, 0x70, 0x38, 0x38, 0x03, 0x03, 0x03, 0x07,
0x07, 0x07, 0x07, 0x0E, 0x0E, // 60

0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, // 61

0x38, 0x38, 0x70, 0x70, 0x70, 0xF0, 0xE0, 0xE0, 0xE0, 0x0E, 0x0E, 0x07, 0x07,
0x07, 0x07, 0x03, 0x03, 0x03, // 62

0x18, 0x1C, 0x9E, 0xC6, 0xE6, 0xFE, 0x7C, 0x38, 0x00, 0x00, 0x1D, 0x1D, 0x1D,
0x00, 0x00, 0x00, // 63

0xE0, 0x18, 0xC4, 0xF4, 0x3A, 0x0A, 0x0A, 0xF2, 0xFA, 0x7C, 0x08, 0xF0, 0x07,
0x18, 0x27, 0x2F, 0x48, 0x48, 0x4C, 0x4F, 0x4F, 0x28, 0x36, 0x11, // 64

0x00, 0x80, 0xE0, 0xF8, 0xFE, 0x1E, 0xFE, 0xF8, 0xE0, 0x80, 0x00, 0x00, 0x1C,
0x1F, 0x0F, 0x07, 0x06, 0x06, 0x06, 0x07, 0x0F, 0x1F, 0x1C, 0x10, // 65

0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xFE, 0xBC, 0x98, 0x00, 0x1F, 0x1F, 0x1F, 0x18,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 66

61
0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0x0E, 0x1E, 0x1C, 0x08, 0x03, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0E, 0x06, // 67

0xFE, 0xFE, 0xFE, 0x06, 0x06, 0x0E, 0xFE, 0xFC, 0xF0, 0x1F, 0x1F, 0x1F, 0x18,
0x18, 0x1C, 0x1F, 0x0F, 0x03, // 68

0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x06, 0x1F, 0x1F, 0x1F, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, // 69

0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6, 0x06, 0x1F, 0x1F, 0x1F, 0x00, 0x00,
0x00, 0x00, 0x00, // 70

0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0xC6, 0xCE, 0xDE, 0xDC, 0xC8, 0x03, 0x0F,
0x0F, 0x1C, 0x18, 0x18, 0x1C, 0x1F, 0x0F, 0x0F, // 71

0xFE, 0xFE, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xFE, 0xFE, 0x1F, 0x1F,
0x1F, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, // 72

0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F, // 73

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x06, 0x0F, 0x1F, 0x1C,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 74

0xFE, 0xFE, 0xFE, 0xC0, 0xE0, 0xF0, 0xF8, 0xDC, 0x0E, 0x06, 0x02, 0x00, 0x1F,
0x1F, 0x1F, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1F, 0x1E, 0x18, 0x10, // 75

0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x18, 0x18,
0x18, 0x18, 0x18, // 76

0xFE, 0xFE, 0xFE, 0x3E, 0xF8, 0x80, 0x80, 0xF8, 0x3E, 0xFE, 0xFE, 0xFE, 0x1F,
0x1F, 0x1F, 0x00, 0x03, 0x1F, 0x1F, 0x03, 0x00, 0x1F, 0x1F, 0x1F, // 77

0xFE, 0xFE, 0xFE, 0x7C, 0xF0, 0xE0, 0x80, 0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F,
0x00, 0x01, 0x03, 0x0F, 0x1F, 0x1F, 0x1F, // 78

0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0x06, 0x0E, 0xFC, 0xFC, 0xF0, 0x03, 0x0F, 0x0F,
0x1C, 0x18, 0x18, 0x1C, 0x0F, 0x0F, 0x03, // 79

62
0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x3C, 0x1F, 0x1F, 0x1F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, // 80

0xF0, 0xFC, 0xFC, 0x0E, 0x06, 0x06, 0x0E, 0xFC, 0xFC, 0xF0, 0x03, 0x0F, 0x0F,
0x1C, 0x18, 0x1E, 0x1C, 0x1F, 0x1F, 0x33, // 81

0xFE, 0xFE, 0xFE, 0xC6, 0xC6, 0xC6, 0xFE, 0x7E, 0x3C, 0x00, 0x1F, 0x1F, 0x1F,
0x00, 0x00, 0x03, 0x0F, 0x1F, 0x1C, 0x10, // 82

0x38, 0x7C, 0xFE, 0xE6, 0xE6, 0xEE, 0xDE, 0xDC, 0x98, 0x06, 0x0E, 0x1E,
0x1C, 0x18, 0x19, 0x1F, 0x0F, 0x07, // 83

0x06, 0x06, 0x06, 0x06, 0xFE, 0xFE, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, // 84

0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFE, 0xFE, 0x07, 0x0F, 0x1F,
0x1C, 0x18, 0x18, 0x1C, 0x1F, 0x0F, 0x07, // 85

0x1E, 0xFE, 0xFC, 0xF0, 0x80, 0x00, 0x80, 0xF0, 0xFC, 0xFE, 0x1E, 0x02, 0x00,
0x00, 0x03, 0x1F, 0x1F, 0x1C, 0x1F, 0x1F, 0x03, 0x00, 0x00, 0x00, // 86

0xFE, 0xFE, 0xF8, 0x00, 0x80, 0xF8, 0xFE, 0x3E, 0xFE, 0xF8, 0x80, 0x00, 0xF8,
0xFE, 0xFE, 0x06, 0x00, 0x0F, 0x1F, 0x1F, 0x1F, 0x07, 0x01, 0x00, 0x01, 0x07,
0x1F, 0x1F, 0x1F, 0x0F, 0x00, 0x00, // 87

0x06, 0x1E, 0x3C, 0xF8, 0xF0, 0xE0, 0xF0, 0xF8, 0x3C, 0x1E, 0x06, 0x02, 0x18,
0x1E, 0x0F, 0x07, 0x03, 0x01, 0x03, 0x07, 0x0F, 0x1E, 0x18, 0x10, // 88

0x02, 0x0E, 0x1E, 0x7E, 0xF8, 0xE0, 0xF8, 0x7E, 0x1E, 0x0E, 0x02, 0x00, 0x00,
0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, 0x00, // 89

0x00, 0x06, 0x06, 0xC6, 0xE6, 0xF6, 0x3E, 0x1E, 0x0E, 0x1C, 0x1E, 0x1F, 0x1B,
0x19, 0x18, 0x18, 0x18, 0x18, // 90

0xFE, 0xFE, 0xFE, 0x06, 0x06, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, // 91

0x06, 0x78, 0x80, 0x00, 0x00, 0x00, 0x07, 0x18, // 92

63
0x06, 0x06, 0xFE, 0xFE, 0xFE, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, // 93

0x40, 0x70, 0x7C, 0x1E, 0x1E, 0x7C, 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, // 94

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, // 95

0x02, 0x06, 0x04, 0x00, 0x00, 0x00, // 96

0x40, 0x60, 0x70, 0x30, 0xB0, 0xB0, 0xF0, 0xF0, 0xE0, 0x0E, 0x1F, 0x1F, 0x1B,
0x19, 0x09, 0x1F, 0x1F, 0x1F, // 97

0xFE, 0xFE, 0xFE, 0x60, 0x30, 0x30, 0xF0, 0xE0, 0xC0, 0x1F, 0x1F, 0x1F, 0x0C,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 98

0xC0, 0xE0, 0xF0, 0x70, 0x30, 0x30, 0x70, 0x60, 0x40, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x18, 0x1C, 0x0C, 0x04, // 99

0xC0, 0xE0, 0xF0, 0x30, 0x30, 0x60, 0xFE, 0xFE, 0xFE, 0x07, 0x0F, 0x1F, 0x18,
0x18, 0x0C, 0x1F, 0x1F, 0x1F, // 100

0xC0, 0xE0, 0xF0, 0xB0, 0xB0, 0xB0, 0xF0, 0xE0, 0xC0, 0x07, 0x0F, 0x1F, 0x1D,
0x19, 0x19, 0x1D, 0x0D, 0x05, // 101

0x30, 0xFC, 0xFE, 0xFE, 0x36, 0x36, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, // 102

0xC0, 0xE0, 0xF0, 0x30, 0x30, 0x60, 0xF0, 0xF0, 0xF0, 0x47, 0xCF, 0xDF, 0xD8,
0xD8, 0xCC, 0xFF, 0x7F, 0x3F, // 103

0xFE, 0xFE, 0xFE, 0x20, 0x30, 0x30, 0xF0, 0xF0, 0xE0, 0x1F, 0x1F, 0x1F, 0x00,
0x00, 0x00, 0x1F, 0x1F, 0x1F, // 104

0xF6, 0xF6, 0xF6, 0x1F, 0x1F, 0x1F, // 105

0x00, 0xF6, 0xF6, 0xF6, 0xC0, 0xFF, 0xFF, 0x7F, // 106

0xFE, 0xFE, 0xFE, 0xC0, 0xE0, 0xF0, 0xF0, 0x30, 0x10, 0x00, 0x1F, 0x1F, 0x1F,
0x03, 0x01, 0x07, 0x1F, 0x1E, 0x1C, 0x10, // 107

64
0xFE, 0xFE, 0xFE, 0x1F, 0x1F, 0x1F, // 108

0xF0, 0xF0, 0xF0, 0x20, 0x30, 0xF0, 0xF0, 0xE0, 0x20, 0x30, 0xF0, 0xF0, 0xE0,
0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x1F, 0x1F, 0x1F, //
109

0xF0, 0xF0, 0xF0, 0x20, 0x30, 0x30, 0xF0, 0xF0, 0xE0, 0x1F, 0x1F, 0x1F, 0x00,
0x00, 0x00, 0x1F, 0x1F, 0x1F, // 110

0xC0, 0xE0, 0xF0, 0x70, 0x30, 0x70, 0xF0, 0xE0, 0xC0, 0x07, 0x0F, 0x1F, 0x1C,
0x18, 0x1C, 0x1F, 0x0F, 0x07, // 111

0xF0, 0xF0, 0xF0, 0x60, 0x30, 0x70, 0xF0, 0xE0, 0xC0, 0xFF, 0xFF, 0xFF, 0x0C,
0x18, 0x18, 0x1F, 0x0F, 0x07, // 112

0xC0, 0xE0, 0xF0, 0x30, 0x30, 0x60, 0xF0, 0xF0, 0xF0, 0x07, 0x0F, 0x1F, 0x18,
0x18, 0x0C, 0xFF, 0xFF, 0xFF, // 113

0xF0, 0xF0, 0xF0, 0x20, 0x30, 0x10, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00, // 114

0xE0, 0xF0, 0xF0, 0x90, 0x90, 0xB0, 0x30, 0x20, 0x08, 0x19, 0x1B, 0x13, 0x13,
0x1F, 0x1F, 0x0E, // 115

0x30, 0xFC, 0xFC, 0xFE, 0x30, 0x30, 0x00, 0x0F, 0x1F, 0x1F, 0x18, 0x18, // 116

0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0x0F, 0x1F, 0x1F, 0x18,
0x18, 0x08, 0x1F, 0x1F, 0x1F, // 117

0x10, 0xF0, 0xF0, 0xC0, 0x00, 0xE0, 0xF0, 0xF0, 0x10, 0x00, 0x00, 0x07, 0x1F,
0x1C, 0x1F, 0x07, 0x00, 0x00, // 118

0x10, 0xF0, 0xF0, 0xE0, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0xE0, 0xF0,
0xF0, 0x10, 0x00, 0x00, 0x07, 0x1F, 0x1E, 0x0F, 0x03, 0x00, 0x03, 0x0F, 0x1E,
0x1F, 0x07, 0x00, 0x00, // 119

0x10, 0x30, 0x70, 0xE0, 0xC0, 0x80, 0xC0, 0xE0, 0x70, 0x30, 0x10, 0x10, 0x18,
0x1E, 0x0F, 0x07, 0x03, 0x07, 0x0F, 0x1E, 0x18, 0x10, // 120

65
0x10, 0xF0, 0xF0, 0xC0, 0x00, 0xC0, 0xF0, 0xF0, 0x30, 0xC0, 0xC0, 0xC7, 0xFF,
0xFC, 0x3F, 0x0F, 0x01, 0x00, // 121

0x30, 0x30, 0x30, 0xF0, 0xF0, 0xF0, 0x30, 0x1C, 0x1E, 0x1F, 0x1B, 0x19, 0x18,
0x18, // 122

0x00, 0x00, 0xFC, 0xFE, 0xFE, 0x06, 0x03, 0x03, 0x7F, 0xFF, 0xFC, 0xC0, // 123

0xFE, 0xFE, 0xFF, 0xFF, // 124

0x06, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0xC0, 0xFC, 0xFF, 0x7F, 0x03, 0x03, // 125

0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xE0, 0x01, 0x00, 0x00, 0x00,
0x01, 0x01, 0x01, 0x01, 0x00, // 126

0xF8, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xF8, 0x1F, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x1F // 127

};

#endif

D. DMD.cpp

/*--------------------------------------------------------------------------------------

DMD.cpp - Function and support library for the Freetronics DMD, a 512 LED matrix
display

panel arranged in a 32 x 16 layout.

Copyright (C) 2011 Marc Alexander (info <at> freetronics <dot> com)

66
Note that the DMD library uses the SPI port for the fastest, low overhead writing to
the

display. Keep an eye on conflicts if there are any other devices running from the same

SPI port, and that the chip select on those devices is correctly set to be inactive

when the DMD is being written to.

---

This program is free software: you can redistribute it and/or modify it under the terms

of the version 3 GNU General Public License as published by the Free Software
Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY;

without even the implied warranty of MERCHANTABILITY or FITNESS FOR A


PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this
program.

If not, see <http://www.gnu.org/licenses/>.

67
--------------------------------------------------------------------------------------*/

#include "DMD.h"

/*--------------------------------------------------------------------------------------

Setup and instantiation of DMD library

Note this currently uses the SPI port for the fastest performance to the DMD, be

careful of possible conflicts with other SPI port devices

--------------------------------------------------------------------------------------*/

DMD::DMD(byte panelsWide, byte panelsHigh)

uint16_t ui;

DisplaysWide=panelsWide;

DisplaysHigh=panelsHigh;

DisplaysTotal=DisplaysWide*DisplaysHigh;

row1 = DisplaysTotal<<4;

row2 = DisplaysTotal<<5;

row3 = ((DisplaysTotal<<2)*3)<<2;

bDMDScreenRAM = (byte *) malloc(DisplaysTotal*DMD_RAM_SIZE_BYTES);

// initialize the SPI port

SPI.begin(); // probably don't need this since it inits the port pins only,
which we do just below with the appropriate DMD interface setup

68
SPI.setBitOrder(MSBFIRST); //

SPI.setDataMode(SPI_MODE0); // CPOL=0, CPHA=0

SPI.setClockDivider(SPI_CLOCK_DIV4); // system clock / 4 = 4MHz SPI CLK


to shift registers. If using a short cable, can put SPI_CLOCK_DIV2 here for 2x faster
updates

digitalWrite(PIN_DMD_A, LOW); //

digitalWrite(PIN_DMD_B, LOW); //

digitalWrite(PIN_DMD_CLK, LOW); //

digitalWrite(PIN_DMD_SCLK, LOW); //

digitalWrite(PIN_DMD_R_DATA, HIGH); //

digitalWrite(PIN_DMD_nOE, LOW); //

pinMode(PIN_DMD_A, OUTPUT); //

pinMode(PIN_DMD_B, OUTPUT); //

pinMode(PIN_DMD_CLK, OUTPUT); //

pinMode(PIN_DMD_SCLK, OUTPUT); //

pinMode(PIN_DMD_R_DATA, OUTPUT); //

pinMode(PIN_DMD_nOE, OUTPUT); //

clearScreen(true);

69
// init the scan line/ram pointer to the required start point

bDMDByte = 0;

//DMD::~DMD()

//{

// // nothing needed here

//}

/*--------------------------------------------------------------------------------------

Set or clear a pixel at the x and y location (0,0 is the top left corner)

--------------------------------------------------------------------------------------*/

void

DMD::writePixel(unsigned int bX, unsigned int bY, byte bGraphicsMode, byte


bPixel)

unsigned int uiDMDRAMPointer;

if (bX >= (DMD_PIXELS_ACROSS*DisplaysWide) || bY >=


(DMD_PIXELS_DOWN * DisplaysHigh)) {

return;

70
byte panel=(bX/DMD_PIXELS_ACROSS) +
(DisplaysWide*(bY/DMD_PIXELS_DOWN));

bX=(bX % DMD_PIXELS_ACROSS) + (panel<<5);

bY=bY % DMD_PIXELS_DOWN;

//set pointer to DMD RAM byte to be modified

uiDMDRAMPointer = bX/8 + bY*(DisplaysTotal<<2);

byte lookup = bPixelLookupTable[bX & 0x07];

switch (bGraphicsMode) {

case GRAPHICS_NORMAL:

if (bPixel == true)

bDMDScreenRAM[uiDMDRAMPointer] &= ~lookup; // zero bit


is pixel on

else

bDMDScreenRAM[uiDMDRAMPointer] |= lookup; // one bit is pixel


off

break;

case GRAPHICS_INVERSE:

if (bPixel == false)

bDMDScreenRAM[uiDMDRAMPointer] &= ~lookup; // zero bit


is pixel on

else

71
bDMDScreenRAM[uiDMDRAMPointer] |= lookup; // one bit is pixel
off

break;

case GRAPHICS_TOGGLE:

if (bPixel == true) {

if ((bDMDScreenRAM[uiDMDRAMPointer] & lookup) == 0)

bDMDScreenRAM[uiDMDRAMPointer] |= lookup; // one bit is pixel


off

else

bDMDScreenRAM[uiDMDRAMPointer] &= ~lookup; // one bit


is pixel off

break;

case GRAPHICS_OR:

//only set pixels on

if (bPixel == true)

bDMDScreenRAM[uiDMDRAMPointer] &= ~lookup; // zero bit


is pixel on

break;

case GRAPHICS_NOR:

//only clear on pixels

if ((bPixel == true) &&

((bDMDScreenRAM[uiDMDRAMPointer] & lookup) == 0))

72
bDMDScreenRAM[uiDMDRAMPointer] |= lookup; // one bit is pixel
off

break;

void DMD::drawString(int bX, int bY, const char *bChars, byte length,

byte bGraphicsMode)

if (bX >= (DMD_PIXELS_ACROSS*DisplaysWide) || bY >=


DMD_PIXELS_DOWN * DisplaysHigh)

return;

uint8_t height = pgm_read_byte(this->Font + FONT_HEIGHT);

if (bY+height<0) return;

int strWidth = 0;

this->drawLine(bX -1 , bY, bX -1 , bY + height, GRAPHICS_INVERSE);

for (int i = 0; i < length; i++) {

int charWide = this->drawChar(bX+strWidth, bY, bChars[i], bGraphicsMode);

if (charWide > 0) {

73
strWidth += charWide ;

this->drawLine(bX + strWidth , bY, bX + strWidth , bY + height,


GRAPHICS_INVERSE);

strWidth++;

} else if (charWide < 0) {

return;

if ((bX + strWidth) >= DMD_PIXELS_ACROSS * DisplaysWide || bY >=


DMD_PIXELS_DOWN * DisplaysHigh) return;

void DMD::drawMarquee(const char *bChars, byte length, int left, int top)

marqueeWidth = 0;

for (int i = 0; i < length; i++) {

marqueeText[i] = bChars[i];

marqueeWidth += charWidth(bChars[i]) + 1;

marqueeHeight=pgm_read_byte(this->Font + FONT_HEIGHT);

marqueeText[length] = '\0';

marqueeOffsetY = top;

74
marqueeOffsetX = left;

marqueeLength = length;

drawString(marqueeOffsetX, marqueeOffsetY, marqueeText, marqueeLength,

GRAPHICS_NORMAL);

boolean DMD::stepMarquee(int amountX, int amountY)

boolean ret=false;

marqueeOffsetX += amountX;

marqueeOffsetY += amountY;

if (marqueeOffsetX < -marqueeWidth) {

marqueeOffsetX = DMD_PIXELS_ACROSS * DisplaysWide;

clearScreen(true);

ret=true;

} else if (marqueeOffsetX > DMD_PIXELS_ACROSS * DisplaysWide) {

marqueeOffsetX = -marqueeWidth;

clearScreen(true);

ret=true;

75
if (marqueeOffsetY < -marqueeHeight) {

marqueeOffsetY = DMD_PIXELS_DOWN * DisplaysHigh;

clearScreen(true);

ret=true;

} else if (marqueeOffsetY > DMD_PIXELS_DOWN * DisplaysHigh) {

marqueeOffsetY = -marqueeHeight;

clearScreen(true);

ret=true;

// Special case horizontal scrolling to improve speed

if (amountY==0 && amountX==-1) {

// Shift entire screen one bit

for (int i=0; i<DMD_RAM_SIZE_BYTES*DisplaysTotal;i++) {

if ((i%(DisplaysWide*4)) == (DisplaysWide*4) -1) {

bDMDScreenRAM[i]=(bDMDScreenRAM[i]<<1)+1;

} else {

bDMDScreenRAM[i]=(bDMDScreenRAM[i]<<1) +
((bDMDScreenRAM[i+1] & 0x80) >>7);

76
// Redraw last char on screen

int strWidth=marqueeOffsetX;

for (byte i=0; i < marqueeLength; i++) {

int wide = charWidth(marqueeText[i]);

if (strWidth+wide >= DisplaysWide*DMD_PIXELS_ACROSS) {

drawChar(strWidth,
marqueeOffsetY,marqueeText[i],GRAPHICS_NORMAL);

return ret;

strWidth += wide+1;

} else if (amountY==0 && amountX==1) {

// Shift entire screen one bit

for (int i=(DMD_RAM_SIZE_BYTES*DisplaysTotal)-1; i>=0;i--) {

if ((i%(DisplaysWide*4)) == 0) {

bDMDScreenRAM[i]=(bDMDScreenRAM[i]>>1)+128;

} else {

bDMDScreenRAM[i]=(bDMDScreenRAM[i]>>1) +
((bDMDScreenRAM[i-1] & 1) <<7);

77
// Redraw last char on screen

int strWidth=marqueeOffsetX;

for (byte i=0; i < marqueeLength; i++) {

int wide = charWidth(marqueeText[i]);

if (strWidth+wide >= 0) {

drawChar(strWidth,
marqueeOffsetY,marqueeText[i],GRAPHICS_NORMAL);

return ret;

strWidth += wide+1;

} else {

drawString(marqueeOffsetX, marqueeOffsetY, marqueeText, marqueeLength,

GRAPHICS_NORMAL);

return ret;

/*--------------------------------------------------------------------------------------

Clear the screen in DMD RAM

78
--------------------------------------------------------------------------------------*/

void DMD::clearScreen(byte bNormal)

if (bNormal) // clear all pixels

memset(bDMDScreenRAM,0xFF,DMD_RAM_SIZE_BYTES*DisplaysTotal);

else // set all pixels

memset(bDMDScreenRAM,0x00,DMD_RAM_SIZE_BYTES*DisplaysTotal);

/*--------------------------------------------------------------------------------------

Draw or clear a line from x1,y1 to x2,y2

--------------------------------------------------------------------------------------*/

void DMD::drawLine(int x1, int y1, int x2, int y2, byte bGraphicsMode)

int dy = y2 - y1;

int dx = x2 - x1;

int stepx, stepy;

if (dy < 0) {

dy = -dy;

stepy = -1;

} else {
79
stepy = 1;

if (dx < 0) {

dx = -dx;

stepx = -1;

} else {

stepx = 1;

dy <<= 1; // dy is now 2*dy

dx <<= 1; // dx is now 2*dx

writePixel(x1, y1, bGraphicsMode, true);

if (dx > dy) {

int fraction = dy - (dx >> 1); // same as 2*dy - dx

while (x1 != x2) {

if (fraction >= 0) {

y1 += stepy;

fraction -= dx; // same as fraction -= 2*dx

x1 += stepx;

fraction += dy; // same as fraction -= 2*dy

writePixel(x1, y1, bGraphicsMode, true);


80
}

} else {

int fraction = dx - (dy >> 1);

while (y1 != y2) {

if (fraction >= 0) {

x1 += stepx;

fraction -= dy;

y1 += stepy;

fraction += dx;

writePixel(x1, y1, bGraphicsMode, true);

/*--------------------------------------------------------------------------------------

Draw or clear a circle of radius r at x,y centre

--------------------------------------------------------------------------------------*/

void DMD::drawCircle(int xCenter, int yCenter, int radius,

byte bGraphicsMode)

int x = 0;
81
int y = radius;

int p = (5 - radius * 4) / 4;

drawCircleSub(xCenter, yCenter, x, y, bGraphicsMode);

while (x < y) {

x++;

if (p < 0) {

p += 2 * x + 1;

} else {

y--;

p += 2 * (x - y) + 1;

drawCircleSub(xCenter, yCenter, x, y, bGraphicsMode);

void DMD::drawCircleSub(int cx, int cy, int x, int y, byte bGraphicsMode)

if (x == 0) {

writePixel(cx, cy + y, bGraphicsMode, true);

writePixel(cx, cy - y, bGraphicsMode, true);


82
writePixel(cx + y, cy, bGraphicsMode, true);

writePixel(cx - y, cy, bGraphicsMode, true);

} else if (x == y) {

writePixel(cx + x, cy + y, bGraphicsMode, true);

writePixel(cx - x, cy + y, bGraphicsMode, true);

writePixel(cx + x, cy - y, bGraphicsMode, true);

writePixel(cx - x, cy - y, bGraphicsMode, true);

} else if (x < y) {

writePixel(cx + x, cy + y, bGraphicsMode, true);

writePixel(cx - x, cy + y, bGraphicsMode, true);

writePixel(cx + x, cy - y, bGraphicsMode, true);

writePixel(cx - x, cy - y, bGraphicsMode, true);

writePixel(cx + y, cy + x, bGraphicsMode, true);

writePixel(cx - y, cy + x, bGraphicsMode, true);

writePixel(cx + y, cy - x, bGraphicsMode, true);

writePixel(cx - y, cy - x, bGraphicsMode, true);

/*--------------------------------------------------------------------------------------

Draw or clear a box(rectangle) with a single pixel border

--------------------------------------------------------------------------------------*/
83
void DMD::drawBox(int x1, int y1, int x2, int y2, byte bGraphicsMode)

drawLine(x1, y1, x2, y1, bGraphicsMode);

drawLine(x2, y1, x2, y2, bGraphicsMode);

drawLine(x2, y2, x1, y2, bGraphicsMode);

drawLine(x1, y2, x1, y1, bGraphicsMode);

/*--------------------------------------------------------------------------------------

Draw or clear a filled box(rectangle) with a single pixel border

--------------------------------------------------------------------------------------*/

void DMD::drawFilledBox(int x1, int y1, int x2, int y2,

byte bGraphicsMode)

for (int b = x1; b <= x2; b++) {

drawLine(b, y1, b, y2, bGraphicsMode);

/*--------------------------------------------------------------------------------------

Draw the selected test pattern

--------------------------------------------------------------------------------------*/
84
void DMD::drawTestPattern(byte bPattern)

unsigned int ui;

int numPixels=DisplaysTotal * DMD_PIXELS_ACROSS *


DMD_PIXELS_DOWN;

int pixelsWide=DMD_PIXELS_ACROSS*DisplaysWide;

for (ui = 0; ui < numPixels; ui++) {

switch (bPattern) {

case PATTERN_ALT_0: // every alternate pixel, first pixel on

if ((ui & pixelsWide) == 0)

//even row

writePixel((ui & (pixelsWide-1)), ((ui & ~(pixelsWide-1)) /


pixelsWide), GRAPHICS_NORMAL, ui & 1);

else

//odd row

writePixel((ui & (pixelsWide-1)), ((ui & ~(pixelsWide-1)) /


pixelsWide), GRAPHICS_NORMAL, !(ui & 1));

break;

case PATTERN_ALT_1: // every alternate pixel, first pixel off

if ((ui & pixelsWide) == 0)

//even row

85
writePixel((ui & (pixelsWide-1)), ((ui & ~(pixelsWide-1)) /
pixelsWide), GRAPHICS_NORMAL, !(ui & 1));

else

//odd row

writePixel((ui & (pixelsWide-1)), ((ui & ~(pixelsWide-1)) /


pixelsWide), GRAPHICS_NORMAL, ui & 1);

break;

case PATTERN_STRIPE_0: // vertical stripes, first stripe on

writePixel((ui & (pixelsWide-1)), ((ui & ~(pixelsWide-1)) /


pixelsWide), GRAPHICS_NORMAL, ui & 1);

break;

case PATTERN_STRIPE_1: // vertical stripes, first stripe off

writePixel((ui & (pixelsWide-1)), ((ui & ~(pixelsWide-1)) /


pixelsWide), GRAPHICS_NORMAL, !(ui & 1));

break;

/*--------------------------------------------------------------------------------------

Scan the dot matrix LED panel display, from the RAM mirror out to the display
hardware.

86
Call 4 times to scan the whole display which is made up of 4 interleaved rows within
the 16 total rows.

Insert the calls to this function into the main loop for the highest call rate, or from a
timer interrupt

--------------------------------------------------------------------------------------*/

void DMD::scanDisplayBySPI()

//if PIN_OTHER_SPI_nCS is in use during a DMD scan request then


scanDisplayBySPI() will exit without conflict! (and skip that scan)

if( digitalRead( PIN_OTHER_SPI_nCS ) == HIGH )

//SPI transfer pixels to the display hardware shift registers

int rowsize=DisplaysTotal<<2;

int offset=rowsize * bDMDByte;

for (int i=0;i<rowsize;i++) {

SPI.transfer(bDMDScreenRAM[offset+i+row3]);

SPI.transfer(bDMDScreenRAM[offset+i+row2]);

SPI.transfer(bDMDScreenRAM[offset+i+row1]);

SPI.transfer(bDMDScreenRAM[offset+i]);

OE_DMD_ROWS_OFF();

LATCH_DMD_SHIFT_REG_TO_OUTPUT();
87
switch (bDMDByte) {

case 0: // row 1, 5, 9, 13 were clocked out

LIGHT_DMD_ROW_01_05_09_13();

bDMDByte=1;

break;

case 1: // row 2, 6, 10, 14 were clocked out

LIGHT_DMD_ROW_02_06_10_14();

bDMDByte=2;

break;

case 2: // row 3, 7, 11, 15 were clocked out

LIGHT_DMD_ROW_03_07_11_15();

bDMDByte=3;

break;

case 3: // row 4, 8, 12, 16 were clocked out

LIGHT_DMD_ROW_04_08_12_16();

bDMDByte=0;

break;

OE_DMD_ROWS_ON();

88
void DMD::selectFont(const uint8_t * font)

this->Font = font;

int DMD::drawChar(const int bX, const int bY, const unsigned char letter, byte
bGraphicsMode)

if (bX > (DMD_PIXELS_ACROSS*DisplaysWide) || bY >


(DMD_PIXELS_DOWN*DisplaysHigh) ) return -1;

unsigned char c = letter;

uint8_t height = pgm_read_byte(this->Font + FONT_HEIGHT);

if (c == ' ') {

int charWide = charWidth(' ');

this->drawFilledBox(bX, bY, bX + charWide, bY + height,


GRAPHICS_INVERSE);

return charWide;

uint8_t width = 0;

uint8_t bytes = (height + 7) / 8;

uint8_t firstChar = pgm_read_byte(this->Font + FONT_FIRST_CHAR);


89
uint8_t charCount = pgm_read_byte(this->Font + FONT_CHAR_COUNT);

uint16_t index = 0;

if (c < firstChar || c >= (firstChar + charCount)) return 0;

c -= firstChar;

if (pgm_read_byte(this->Font + FONT_LENGTH) == 0

&& pgm_read_byte(this->Font + FONT_LENGTH + 1) == 0) {

// zero length is flag indicating fixed width font (array does not contain width
data entries)

width = pgm_read_byte(this->Font + FONT_FIXED_WIDTH);

index = c * bytes * width + FONT_WIDTH_TABLE;

} else {

// variable width font, read width data, to get the index

for (uint8_t i = 0; i < c; i++) {

index += pgm_read_byte(this->Font + FONT_WIDTH_TABLE + i);

index = index * bytes + charCount + FONT_WIDTH_TABLE;

width = pgm_read_byte(this->Font + FONT_WIDTH_TABLE + c);

if (bX < -width || bY < -height) return width;

90
// last but not least, draw the character

for (uint8_t j = 0; j < width; j++) { // Width

for (uint8_t i = bytes - 1; i < 254; i--) { // Vertical Bytes

uint8_t data = pgm_read_byte(this->Font + index + j + (i * width));

int offset = (i * 8);

if ((i == bytes - 1) && bytes > 1) {

offset = height - 8;

for (uint8_t k = 0; k < 8; k++) { // Vertical bits

if ((offset+k >= i*8) && (offset+k <= height)) {

if (data & (1 << k)) {

writePixel(bX + j, bY + offset + k, bGraphicsMode, true);

} else {

writePixel(bX + j, bY + offset + k, bGraphicsMode, false);

return width;

}
91
int DMD::charWidth(const unsigned char letter)

unsigned char c = letter;

// Space is often not included in font so use width of 'n'

if (c == ' ') c = 'n';

uint8_t width = 0;

uint8_t firstChar = pgm_read_byte(this->Font + FONT_FIRST_CHAR);

uint8_t charCount = pgm_read_byte(this->Font + FONT_CHAR_COUNT);

uint16_t index = 0;

if (c < firstChar || c >= (firstChar + charCount)) {

return 0;

c -= firstChar;

if (pgm_read_byte(this->Font + FONT_LENGTH) == 0

&& pgm_read_byte(this->Font + FONT_LENGTH + 1) == 0) {

// zero length is flag indicating fixed width font (array does not contain width
data entries)

92
width = pgm_read_byte(this->Font + FONT_FIXED_WIDTH);

} else {

// variable width font, read width data

width = pgm_read_byte(this->Font + FONT_WIDTH_TABLE + c);

return width;

E.DMD.h

#ifndef DMD_H_

#define DMD_H_

//Arduino toolchain header, version dependent

#if defined(ARDUINO) && ARDUINO >= 100

#include "Arduino.h"

#else

#include "WProgram.h"

#endif

//SPI library must be included for the SPI scanning/connection method to the DMD

#include "pins_arduino.h"

#include <avr/pgmspace.h>
93
#include <SPI.h>

//
#####################################################################
#################################################

//
#####################################################################
#################################################

#warning CHANGE THESE TO SEMI-ADJUSTABLE PIN DEFS!

//Arduino pins used for the display connection

#define PIN_DMD_nOE 9 // D9 active low Output Enable, setting this low lights
all the LEDs in the selected rows. Can pwm it at very high frequency for brightness
control.

#define PIN_DMD_A 6 // D6

#define PIN_DMD_B 7 // D7

#define PIN_DMD_CLK 13 // D13_SCK is SPI Clock if SPI is used

#define PIN_DMD_SCLK 8 // D8

#define PIN_DMD_R_DATA 11 // D11_MOSI is SPI Master Out if SPI is used

//Define this chip select pin that the Ethernet W5100 IC or other SPI device uses

//if it is in use during a DMD scan request then scanDisplayBySPI() will exit without
conflict! (and skip that scan)

#define PIN_OTHER_SPI_nCS 10

94
//
#####################################################################
#################################################

//
#####################################################################
#################################################

//DMD I/O pin macros

#define LIGHT_DMD_ROW_01_05_09_13() { digitalWrite( PIN_DMD_B,


LOW ); digitalWrite( PIN_DMD_A, LOW ); }

#define LIGHT_DMD_ROW_02_06_10_14() { digitalWrite( PIN_DMD_B,


LOW ); digitalWrite( PIN_DMD_A, HIGH ); }

#define LIGHT_DMD_ROW_03_07_11_15() { digitalWrite( PIN_DMD_B,


HIGH ); digitalWrite( PIN_DMD_A, LOW ); }

#define LIGHT_DMD_ROW_04_08_12_16() { digitalWrite( PIN_DMD_B,


HIGH ); digitalWrite( PIN_DMD_A, HIGH ); }

#define LATCH_DMD_SHIFT_REG_TO_OUTPUT() { digitalWrite(


PIN_DMD_SCLK, HIGH ); digitalWrite( PIN_DMD_SCLK, LOW ); }

#define OE_DMD_ROWS_OFF() { digitalWrite( PIN_DMD_nOE, LOW );


}

#define OE_DMD_ROWS_ON() { digitalWrite( PIN_DMD_nOE, HIGH );


}

//Pixel/graphics writing modes (bGraphicsMode)

#define GRAPHICS_NORMAL 0

95
#define GRAPHICS_INVERSE 1

#define GRAPHICS_TOGGLE 2

#define GRAPHICS_OR 3

#define GRAPHICS_NOR 4

//drawTestPattern Patterns

#define PATTERN_ALT_0 0

#define PATTERN_ALT_1 1

#define PATTERN_STRIPE_0 2

#define PATTERN_STRIPE_1 3

//display screen (and subscreen) sizing

#define DMD_PIXELS_ACROSS 32 //pixels across x axis (base 2 size


expected)

#define DMD_PIXELS_DOWN 16 //pixels down y axis

#define DMD_BITSPERPIXEL 1 //1 bit per pixel, use more bits to allow for
pwm screen brightness control

#define DMD_RAM_SIZE_BYTES
((DMD_PIXELS_ACROSS*DMD_BITSPERPIXEL/8)*DMD_PIXELS_DOWN)

// (32x * 1 / 8) = 4 bytes, * 16y = 64 bytes per screen here.

//lookup table for DMD::writePixel to make the pixel indexing routine faster

static byte bPixelLookupTable[8] =

{
96
0x80, //0, bit 7

0x40, //1, bit 6

0x20, //2. bit 5

0x10, //3, bit 4

0x08, //4, bit 3

0x04, //5, bit 2

0x02, //6, bit 1

0x01 //7, bit 0

};

// Font Indices

#define FONT_LENGTH 0

#define FONT_FIXED_WIDTH 2

#define FONT_HEIGHT 3

#define FONT_FIRST_CHAR 4

#define FONT_CHAR_COUNT 5

#define FONT_WIDTH_TABLE 6

typedef uint8_t (*FontCallback)(const uint8_t*);

//The main class of DMD library functions


97
class DMD

public:

//Instantiate the DMD

DMD(byte panelsWide, byte panelsHigh);

//virtual ~DMD();

//Set or clear a pixel at the x and y location (0,0 is the top left corner)

void writePixel( unsigned int bX, unsigned int bY, byte bGraphicsMode, byte bPixel
);

//Draw a string

void drawString( int bX, int bY, const char* bChars, byte length, byte
bGraphicsMode);

//Select a text font

void selectFont(const uint8_t* font);

//Draw a single character

int drawChar(const int bX, const int bY, const unsigned char letter, byte
bGraphicsMode);

//Find the width of a character


98
int charWidth(const unsigned char letter);

//Draw a scrolling string

void drawMarquee( const char* bChars, byte length, int left, int top);

//Move the maquee accross by amount

boolean stepMarquee( int amountX, int amountY);

//Clear the screen in DMD RAM

void clearScreen( byte bNormal );

//Draw or clear a line from x1,y1 to x2,y2

void drawLine( int x1, int y1, int x2, int y2, byte bGraphicsMode );

//Draw or clear a circle of radius r at x,y centre

void drawCircle( int xCenter, int yCenter, int radius, byte bGraphicsMode );

//Draw or clear a box(rectangle) with a single pixel border

void drawBox( int x1, int y1, int x2, int y2, byte bGraphicsMode );

//Draw or clear a filled box(rectangle) with a single pixel border

void drawFilledBox( int x1, int y1, int x2, int y2, byte bGraphicsMode );
99
//Draw the selected test pattern

void drawTestPattern( byte bPattern );

//Scan the dot matrix LED panel display, from the RAM mirror out to the display
hardware.

//Call 4 times to scan the whole display which is made up of 4 interleaved rows
within the 16 total rows.

//Insert the calls to this function into the main loop for the highest call rate, or from a
timer interrupt

void scanDisplayBySPI();

private:

void drawCircleSub( int cx, int cy, int x, int y, byte bGraphicsMode );

//Mirror of DMD pixels in RAM, ready to be clocked out by the main loop or high
speed timer calls

byte *bDMDScreenRAM;

//Marquee values

char marqueeText[256];

byte marqueeLength;

100
int marqueeWidth;

int marqueeHeight;

int marqueeOffsetX;

int marqueeOffsetY;

//Pointer to current font

const uint8_t* Font;

//Display information

byte DisplaysWide;

byte DisplaysHigh;

byte DisplaysTotal;

int row1, row2, row3;

//scanning pointer into bDMDScreenRAM, setup init @ 48 for the first valid scan

volatile byte bDMDByte;

};

#endif /* DMD_H_ */

f. SystemFont5x7.h

101
*/

#include <inttypes.h>

#include <avr/pgmspace.h>

#ifndef SYSTEM5x7_H

#define SYSTEM5x7_H

#define SYSTEM5x7_WIDTH 5

#define SYSTEM5x7_HEIGHT 7

#define SystemFont5x7 System5x7

const static uint8_t System5x7[] PROGMEM = {

0x0, 0x0, // size of zero indicates fixed width font, actual length is width * height

0x05, // width

0x07, // height

0x20, // first char

0x60, // char count

102
0x00, 0x00, 0x00, 0x00, 0x00,// (space)

0x00, 0x00, 0x5F, 0x00, 0x00,// !

0x00, 0x07, 0x00, 0x07, 0x00,// "

0x14, 0x7F, 0x14, 0x7F, 0x14,// #

0x24, 0x2A, 0x7F, 0x2A, 0x12,// $

0x23, 0x13, 0x08, 0x64, 0x62,// %

0x36, 0x49, 0x55, 0x22, 0x50,// &

0x00, 0x05, 0x03, 0x00, 0x00,// '

0x00, 0x1C, 0x22, 0x41, 0x00,// (

0x00, 0x41, 0x22, 0x1C, 0x00,// )

0x08, 0x2A, 0x1C, 0x2A, 0x08,// *

0x08, 0x08, 0x3E, 0x08, 0x08,// +

0x00, 0x50, 0x30, 0x00, 0x00,// ,

0x08, 0x08, 0x08, 0x08, 0x08,// -

0x00, 0x60, 0x60, 0x00, 0x00,// .

0x20, 0x10, 0x08, 0x04, 0x02,// /

0x3E, 0x51, 0x49, 0x45, 0x3E,// 0

0x00, 0x42, 0x7F, 0x40, 0x00,// 1

0x42, 0x61, 0x51, 0x49, 0x46,// 2

0x21, 0x41, 0x45, 0x4B, 0x31,// 3

0x18, 0x14, 0x12, 0x7F, 0x10,// 4

0x27, 0x45, 0x45, 0x45, 0x39,// 5


103
0x3C, 0x4A, 0x49, 0x49, 0x30,// 6

0x01, 0x71, 0x09, 0x05, 0x03,// 7

0x36, 0x49, 0x49, 0x49, 0x36,// 8

0x06, 0x49, 0x49, 0x29, 0x1E,// 9

0x00, 0x36, 0x36, 0x00, 0x00,// :

0x00, 0x56, 0x36, 0x00, 0x00,// ;

0x00, 0x08, 0x14, 0x22, 0x41,// <

0x14, 0x14, 0x14, 0x14, 0x14,// =

0x41, 0x22, 0x14, 0x08, 0x00,// >

0x02, 0x01, 0x51, 0x09, 0x06,// ?

0x32, 0x49, 0x79, 0x41, 0x3E,// @

0x7E, 0x11, 0x11, 0x11, 0x7E,// A

0x7F, 0x49, 0x49, 0x49, 0x36,// B

0x3E, 0x41, 0x41, 0x41, 0x22,// C

0x7F, 0x41, 0x41, 0x22, 0x1C,// D

0x7F, 0x49, 0x49, 0x49, 0x41,// E

0x7F, 0x09, 0x09, 0x01, 0x01,// F

0x3E, 0x41, 0x41, 0x51, 0x32,// G

0x7F, 0x08, 0x08, 0x08, 0x7F,// H

0x00, 0x41, 0x7F, 0x41, 0x00,// I

0x20, 0x40, 0x41, 0x3F, 0x01,// J

0x7F, 0x08, 0x14, 0x22, 0x41,// K


104
0x7F, 0x40, 0x40, 0x40, 0x40,// L

0x7F, 0x02, 0x04, 0x02, 0x7F,// M

0x7F, 0x04, 0x08, 0x10, 0x7F,// N

0x3E, 0x41, 0x41, 0x41, 0x3E,// O

0x7F, 0x09, 0x09, 0x09, 0x06,// P

0x3E, 0x41, 0x51, 0x21, 0x5E,// Q

0x7F, 0x09, 0x19, 0x29, 0x46,// R

0x46, 0x49, 0x49, 0x49, 0x31,// S

0x01, 0x01, 0x7F, 0x01, 0x01,// T

0x3F, 0x40, 0x40, 0x40, 0x3F,// U

0x1F, 0x20, 0x40, 0x20, 0x1F,// V

0x7F, 0x20, 0x18, 0x20, 0x7F,// W

0x63, 0x14, 0x08, 0x14, 0x63,// X

0x03, 0x04, 0x78, 0x04, 0x03,// Y

0x61, 0x51, 0x49, 0x45, 0x43,// Z

0x00, 0x00, 0x7F, 0x41, 0x41,// [

0x02, 0x04, 0x08, 0x10, 0x20,// "\"

0x41, 0x41, 0x7F, 0x00, 0x00,// ]

0x04, 0x02, 0x01, 0x02, 0x04,// ^

0x40, 0x40, 0x40, 0x40, 0x40,// _

0x00, 0x01, 0x02, 0x04, 0x00,// `

0x20, 0x54, 0x54, 0x54, 0x78,// a


105
0x7F, 0x48, 0x44, 0x44, 0x38,// b

0x38, 0x44, 0x44, 0x44, 0x20,// c

0x38, 0x44, 0x44, 0x48, 0x7F,// d

0x38, 0x54, 0x54, 0x54, 0x18,// e

0x08, 0x7E, 0x09, 0x01, 0x02,// f

0x08, 0x14, 0x54, 0x54, 0x3C,// g

0x7F, 0x08, 0x04, 0x04, 0x78,// h

0x00, 0x44, 0x7D, 0x40, 0x00,// i

0x20, 0x40, 0x44, 0x3D, 0x00,// j

0x00, 0x7F, 0x10, 0x28, 0x44,// k

0x00, 0x41, 0x7F, 0x40, 0x00,// l

0x7C, 0x04, 0x18, 0x04, 0x78,// m

0x7C, 0x08, 0x04, 0x04, 0x78,// n

0x38, 0x44, 0x44, 0x44, 0x38,// o

0x7C, 0x14, 0x14, 0x14, 0x08,// p

0x08, 0x14, 0x14, 0x18, 0x7C,// q

0x7C, 0x08, 0x04, 0x04, 0x08,// r

0x48, 0x54, 0x54, 0x54, 0x20,// s

0x04, 0x3F, 0x44, 0x40, 0x20,// t

0x3C, 0x40, 0x40, 0x20, 0x7C,// u

0x1C, 0x20, 0x40, 0x20, 0x1C,// v

0x3C, 0x40, 0x30, 0x40, 0x3C,// w


106
0x44, 0x28, 0x10, 0x28, 0x44,// x

0x0C, 0x50, 0x50, 0x50, 0x3C,// y

0x44, 0x64, 0x54, 0x4C, 0x44,// z

0x00, 0x08, 0x36, 0x41, 0x00,// {

0x00, 0x00, 0x7F, 0x00, 0x00,// |

0x00, 0x41, 0x36, 0x08, 0x00,// }

0x08, 0x08, 0x2A, 0x1C, 0x08,// ->

0x08, 0x1C, 0x2A, 0x08, 0x08 // <-

};

#endif

g. TimerOne.cpp

*/

#ifndef TIMERONE_cpp

#define TIMERONE_cpp

#include "TimerOne.h"

TimerOne Timer1; // preinstatiate

107
ISR(TIMER1_OVF_vect) // interrupt service routine that wraps a user defined
function supplied by attachInterrupt

Timer1.isrCallback();

void TimerOne::initialize(long microseconds)

TCCR1A = 0; // clear control register A

TCCR1B = _BV(WGM13); // set mode 8: phase and frequency correct pwm,


stop the timer

setPeriod(microseconds);

void TimerOne::setPeriod(long microseconds) // AR modified for atomic


access

long cycles = (F_CPU / 2000000) * microseconds; // the counter


runs backwards after TOP, interrupt is at BOTTOM so divide microseconds by 2

108
if(cycles < RESOLUTION) clockSelectBits = _BV(CS10); // no
prescale, full xtal

else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11); //


prescale by /8

else if((cycles >>= 3) < RESOLUTION) clockSelectBits = _BV(CS11) | _BV(CS10);


// prescale by /64

else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12); //


prescale by /256

else if((cycles >>= 2) < RESOLUTION) clockSelectBits = _BV(CS12) | _BV(CS10);


// prescale by /1024

else cycles = RESOLUTION - 1, clockSelectBits = _BV(CS12) | _BV(CS10); //


request was out of bounds, set as maximum

oldSREG = SREG;

cli(); // Disable interrupts for 16 bit register


access

ICR1 = pwmPeriod = cycles; // ICR1 is TOP in p & f


correct pwm mode

SREG = oldSREG;

TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12));

TCCR1B |= clockSelectBits; // reset clock select register,


and starts the clock

109
void TimerOne::setPwmDuty(char pin, int duty)

unsigned long dutyCycle = pwmPeriod;

dutyCycle *= duty;

dutyCycle >>= 10;

oldSREG = SREG;

cli();

if(pin == 1 || pin == 9) OCR1A = dutyCycle;

else if(pin == 2 || pin == 10) OCR1B = dutyCycle;

SREG = oldSREG;

void TimerOne::pwm(char pin, int duty, long microseconds) // expects duty cycle to
be 10 bit (1024)

if(microseconds > 0) setPeriod(microseconds);

if(pin == 1 || pin == 9) {

DDRB |= _BV(PORTB1); // sets data direction register for


pwm output pin

110
TCCR1A |= _BV(COM1A1); // activates the output pin

else if(pin == 2 || pin == 10) {

DDRB |= _BV(PORTB2);

TCCR1A |= _BV(COM1B1);

setPwmDuty(pin, duty);

resume(); // Lex - make sure the clock is running. We don't want to


restart the count, in case we are starting the second WGM

// and the first one is in the middle of a cycle

void TimerOne::disablePwm(char pin)

if(pin == 1 || pin == 9) TCCR1A &= ~_BV(COM1A1); // clear the bit that


enables pwm on PB1

else if(pin == 2 || pin == 10) TCCR1A &= ~_BV(COM1B1); // clear the bit that
enables pwm on PB2

void TimerOne::attachInterrupt(void (*isr)(), long microseconds)

if(microseconds > 0) setPeriod(microseconds);


111
isrCallback = isr; // register the user's callback with the real
ISR

TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt


enable bit

// might be running with interrupts disabled (eg inside an ISR), so don't touch
the global state

// sei();

resume();

void TimerOne::detachInterrupt()

TIMSK1 &= ~_BV(TOIE1); // clears the timer overflow


interrupt enable bit

// timer continues to count without calling the isr

void TimerOne::resume() // AR suggested

TCCR1B |= clockSelectBits;

112
void TimerOne::restart() // Depricated - Public interface to start at zero - Lex
10/9/2011

start();

void TimerOne::start() // AR addition, renamed by Lex to reflect it's actual role

unsigned int tcnt1;

TIMSK1 &= ~_BV(TOIE1); // AR added

GTCCR |= _BV(PSRSYNC); // AR added - reset prescaler (NB: shared


with all 16 bit timers);

oldSREG = SREG; // AR - save status register

cli(); // AR - Disable interrupts

TCNT1 = 0;

SREG = oldSREG; // AR - Restore status register

resume();

do { // Nothing -- wait until timer moved on from zero - otherwise get a phantom
interrupt

oldSREG = SREG;
113
cli();

tcnt1 = TCNT1;

SREG = oldSREG;

} while (tcnt1==0);

// TIFR1 = 0xff; // AR - Clear interrupt flags

// TIMSK1 = _BV(TOIE1); // sets the timer overflow interrupt enable bit

void TimerOne::stop()

TCCR1B &= ~(_BV(CS10) | _BV(CS11) | _BV(CS12)); // clears all clock


selects bits

unsigned long TimerOne::read() //returns the value of the timer in


microseconds

{ //rember! phase and freq


correct mode counts up to then down again

unsigned long tmp; // AR amended to hold more than


65536 (could be nearly double this)

unsigned int tcnt1; // AR added

114
oldSREG= SREG;

cli();

tmp=TCNT1;

SREG = oldSREG;

char scale=0;

switch (clockSelectBits)

case 1:// no prescalse

scale=0;

break;

case 2:// x8 prescale

scale=3;

break;

case 3:// x64

scale=6;

break;

case 4:// x256

scale=8;

break;

case 5:// x1024

scale=10;
115
break;

do { // Nothing -- max delay here is ~1023 cycles. AR modified

oldSREG = SREG;

cli();

tcnt1 = TCNT1;

SREG = oldSREG;

} while (tcnt1==tmp); //if the timer has not ticked yet

//if we are counting down add the top value to how far we have counted down

tmp = ( (tcnt1>tmp) ? (tmp) : (long)(ICR1-tcnt1)+(long)ICR1 ); //


AR amended to add casts and reuse previous TCNT1

return ((tmp*1000L)/(F_CPU /1000L))<<scale;

#endif

h. TimerOne.h

#ifndef TIMERONE_h

#define TIMERONE_h

116
#include <avr/io.h>

#include <avr/interrupt.h>

#define RESOLUTION 65536 // Timer1 is 16 bit

class TimerOne

public:

// properties

unsigned int pwmPeriod;

unsigned char clockSelectBits;

char oldSREG; // To hold Status Register while


ints disabled

// methods

void initialize(long microseconds=1000000);

void start();

void stop();

void restart();

void resume();

unsigned long read();

117
void pwm(char pin, int duty, long microseconds=-1);

void disablePwm(char pin);

void attachInterrupt(void (*isr)(), long microseconds=-1);

void detachInterrupt();

void setPeriod(long microseconds);

void setPwmDuty(char pin, int duty);

void (*isrCallback)();

};

extern TimerOne Timer1;

#endif

6.2.2: Chương trin


̀ h chính.

#include <SPI.h>

#include <DMD.h>

#include <TimerOne.h>

#include "SystemFont5x7.h"

#include "Arial_black_16.h"

#define DISPLAYS_ACROSS 2

#define DISPLAYS_DOWN 1

DMD dmd(DISPLAYS_ACROSS, DISPLAYS_DOWN);

#define max_char 100

118
char message[max_char];

char r_char;

byte index = 0;

int i;

char greeting[] ="TRUONG DAI HOC CONG NGHE DONG A NGANH


DIEU KHIEN TU DONG HOA" ;

void ScanDMD()

dmd.scanDisplayBySPI();

void setup(void)

Timer1.initialize( 5000);

Timer1.attachInterrupt( ScanDMD );

dmd.clearScreen( true );

Serial.begin(9600);

strcpy(message,greeting);

119
void loop(void)

if(Serial.available())

for(i=0; i<99; i++){

message[i] = '\0';

//resests the index

index=0;

while(Serial.available() > 0)

dmd.clearScreen( true );

if(index < (max_char-1))

r_char = Serial.read();

message[index] = r_char;

index++;

120
}

dmd.selectFont(Arial_Black_16);

dmd.drawMarquee(message ,max_char,(32*DISPLAYS_ACROSS)-1 ,0);

long start=millis();

long timer=start;

boolean ret=false;

while(!ret)

if ((timer+30) < millis()) {

ret=dmd.stepMarquee(-1,0);

timer=millis();

121

You might also like