├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── custom.md
│ └── feature_request.md
└── workflows
│ ├── stale.yml
│ └── sync_issues.yml
├── .travis.yml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── examples
├── NullFunctional
│ └── NullFunctional.ino
└── USBDisplayAndMouseControl
│ ├── USBDisplayAndMouseControl.ino
│ └── USBDisplayAndMouseControl.jpg
├── keywords.txt
├── library.properties
└── src
├── USBDISP.cpp
├── USBDISP.h
└── rpusbdisp_protocol.h
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/custom.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Custom issue template
3 | about: Describe this issue template's purpose here.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | name: 'Close stale issues and PRs'
2 |
3 | on:
4 | workflow_dispatch:
5 | schedule:
6 | - cron: '0 4 * * *'
7 |
8 | jobs:
9 | stale:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | - name: Checkout repository
14 | uses: actions/checkout@v4
15 |
16 | - name: Checkout script repository
17 | uses: actions/checkout@v4
18 | with:
19 | repository: Seeed-Studio/sync-github-all-issues
20 | path: ci
21 |
22 | - name: Run script
23 | run: ./ci/tools/stale.sh
24 | env:
25 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26 |
--------------------------------------------------------------------------------
/.github/workflows/sync_issues.yml:
--------------------------------------------------------------------------------
1 | name: Automate Issue Management
2 |
3 | on:
4 | issues:
5 | types:
6 | - opened
7 | - edited
8 | - assigned
9 | - unassigned
10 | - labeled
11 | - unlabeled
12 | - reopened
13 |
14 | jobs:
15 | add_issue_to_project:
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Add issue to GitHub Project
19 | uses: actions/add-to-project@v1.0.2
20 | with:
21 | project-url: https://github.com/orgs/Seeed-Studio/projects/17
22 | github-token: ${{ secrets.ISSUE_ASSEMBLE }}
23 | labeled: bug
24 | label-operator: NOT
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: generic
2 | dist: bionic
3 | sudo: false
4 | cache:
5 | directories:
6 | - ~/Arduino
7 | - ~/.arduino15/packages/
8 |
9 | # default phases
10 | before_install:
11 | - mkdir -p "$HOME/bin"
12 | - curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR="$HOME/bin" sh
13 | - export PATH="$PATH:$HOME/bin"
14 | - arduino-cli core update-index --additional-urls https://downloads.arduino.cc/packages/package_index.json
15 | - arduino-cli core update-index --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
16 | - arduino-cli core install arduino:avr --additional-urls https://downloads.arduino.cc/packages/package_index.json
17 | - arduino-cli core install Seeeduino:samd --additional-urls https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json
18 | - |
19 | installLibrary() {
20 | local -r repositoryFullName="$1"
21 | local -r repositoryName="${repositoryFullName##*/}"
22 | # clone repository to the libraries folder of the Seeed_Arduino_USBDISP
23 | git clone https://github.com/${repositoryFullName} "${HOME}/Arduino/libraries/${repositoryName}"
24 | cd "${HOME}/Arduino/libraries/${repositoryName}"
25 | cd "${TRAVIS_BUILD_DIR}"
26 | }
27 | - buildExampleSketch() { arduino-cli compile --warnings all --fqbn $BOARD $PWD/examples/$1 --verbose; }
28 | - buildExampleUtilitySketch() { arduino-cli compile --warnings all --fqbn $BOARD $PWD/examples/utility/$1 --verbose; }
29 |
30 | install:
31 | - mkdir -p $HOME/Arduino/libraries
32 |
33 | script:
34 | - echo "*************************************NullFunctional*********************************************"
35 | - rm -rf $HOME/Arduino/libraries/*
36 | - installLibrary Seeed-Studio/Seeed_Arduino_USBDISP
37 | - export BOARD=Seeeduino:samd:seeed_wio_terminal
38 | - buildExampleSketch NullFunctional;
39 |
40 | - echo "*************************************USBDisplayAndMouseControl*********************************************"
41 | - rm -rf $HOME/Arduino/libraries/*
42 | - installLibrary Seeed-Studio/Seeed_Arduino_USBDISP
43 | - installLibrary arduino-libraries/Mouse
44 | - export BOARD=Seeeduino:samd:seeed_wio_terminal
45 | - buildExampleSketch USBDisplayAndMouseControl;
46 |
47 | notifications:
48 | webhooks:
49 | urls:
50 | - https://www.travisbuddy.com/
51 | on_success: never
52 | on_failure: always
53 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | In the interest of fostering an open and welcoming environment, we as
6 | contributors and maintainers pledge to making participation in our project and
7 | our community a harassment-free experience for everyone, regardless of age, body
8 | size, disability, ethnicity, sex characteristics, gender identity and expression,
9 | level of experience, education, socio-economic status, nationality, personal
10 | appearance, race, religion, or sexual identity and orientation.
11 |
12 | ## Our Standards
13 |
14 | Examples of behavior that contributes to creating a positive environment
15 | include:
16 |
17 | * Using welcoming and inclusive language
18 | * Being respectful of differing viewpoints and experiences
19 | * Gracefully accepting constructive criticism
20 | * Focusing on what is best for the community
21 | * Showing empathy towards other community members
22 |
23 | Examples of unacceptable behavior by participants include:
24 |
25 | * The use of sexualized language or imagery and unwelcome sexual attention or
26 | advances
27 | * Trolling, insulting/derogatory comments, and personal or political attacks
28 | * Public or private harassment
29 | * Publishing others' private information, such as a physical or electronic
30 | address, without explicit permission
31 | * Other conduct which could reasonably be considered inappropriate in a
32 | professional setting
33 |
34 | ## Our Responsibilities
35 |
36 | Project maintainers are responsible for clarifying the standards of acceptable
37 | behavior and are expected to take appropriate and fair corrective action in
38 | response to any instances of unacceptable behavior.
39 |
40 | Project maintainers have the right and responsibility to remove, edit, or
41 | reject comments, commits, code, wiki edits, issues, and other contributions
42 | that are not aligned to this Code of Conduct, or to ban temporarily or
43 | permanently any contributor for other behaviors that they deem inappropriate,
44 | threatening, offensive, or harmful.
45 |
46 | ## Scope
47 |
48 | This Code of Conduct applies both within project spaces and in public spaces
49 | when an individual is representing the project or its community. Examples of
50 | representing a project or community include using an official project e-mail
51 | address, posting via an official social media account, or acting as an appointed
52 | representative at an online or offline event. Representation of a project may be
53 | further defined and clarified by project maintainers.
54 |
55 | ## Enforcement
56 |
57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
58 | reported by contacting the project team at zuobaozhu@gmail.com. All
59 | complaints will be reviewed and investigated and will result in a response that
60 | is deemed necessary and appropriate to the circumstances. The project team is
61 | obligated to maintain confidentiality with regard to the reporter of an incident.
62 | Further details of specific enforcement policies may be posted separately.
63 |
64 | Project maintainers who do not follow or enforce the Code of Conduct in good
65 | faith may face temporary or permanent repercussions as determined by other
66 | members of the project's leadership.
67 |
68 | ## Attribution
69 |
70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
72 |
73 | [homepage]: https://www.contributor-covenant.org
74 |
75 | For answers to common questions about this code of conduct, see
76 | https://www.contributor-covenant.org/faq
77 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Contributing guidelines
2 |
3 | All guidelines for contributing to the Seeed_Arduino_USBDISP repository can be found at [`How to contribute guideline`](https://github.com/Seeed-Studio/Seeed_Arduino_USBDISP/wiki/How_to_contribute).
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Seeed Studio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Seeed Arduino USB Display
2 |
3 | USB Display firmware for Wio Terminal
4 |
5 |
6 | ## WIKI
7 | Get more detail about Wio Terminal as USB Display from:
8 | [WIKI](https://wiki.seeedstudio.com/Wio-Terminal-HMI)
9 |
10 |
11 | ## Get Started
12 | Download the Seeed_Arduino_USBDISP library to your local.
13 | There are two examples, NullFunctional and USBDisplayAndMouseControl:
14 |
15 | 1. If you want higher screen refresh rate on Wio Terminal, upload NullFunctional to Wio Terminal.
16 |
17 | 2. If you want Wio Terminal to also act as a USB Mouse, upload USBDisplayAndMouseControl to Wio Terminal.
18 |
19 |
20 | ## Note
21 | The USBDISP().begin(bool reverse, bool usermode) function has two parameters.
22 | In our examples, the default setting is USBDISP().begin(true)
23 | If you want to parse drawing function in usermode-sdk or python-demo(seeed-linux-usbdisp),
24 | you need to set it as USBDISP().begin(true, true)
25 |
26 |
27 | ## Contributing
28 | Contributing to this software is warmly welcomed. You can do this basically by
29 | [forking](https://help.github.com/articles/fork-a-repo), committing modifications and then [pulling requests](https://help.github.com/articles/using-pull-requests) (follow the links above
30 | for operating guide). Adding change log and your contact into file header is encouraged.
31 | Thanks for your contribution.
32 |
33 | Seeed Studio is an open hardware facilitation company based in Shenzhen, China.
34 | Benefiting from local manufacture power and convenient global logistic system,
35 | we integrate resources to serve new era of innovation. Seeed also works with
36 | global distributors and partners to push open hardware movement.
37 |
--------------------------------------------------------------------------------
/examples/NullFunctional/NullFunctional.ino:
--------------------------------------------------------------------------------
1 | /*
2 | NullFunctional.ino
3 |
4 | This code is a null functional example,
5 | will only enumerate a USB Display Device.
6 |
7 | Note:
8 | The USBDISP().begin(bool reverse, bool usermode) function has two parameters.
9 | In our demo, the default setting is USBDISP().begin(true)
10 | If you want to parse drawing function in usermode-sdk or python-demo(seeed-linux-usbdisp),
11 | you need to set it as USBDISP().begin(true, true)
12 | */
13 |
14 | #define SERHD SERIAL_PORT_HARDWARE
15 | #include "USBDISP.h"
16 |
17 | void setup() {
18 | // Construct the singleton object
19 | (void)USBDISP();
20 |
21 | // open the serial port
22 | SERHD.begin(115200);
23 | SERHD.println("WIO Termianl USB Display");
24 |
25 | SerialUSB.begin(115200);
26 | /*
27 | while (!SerialUSB) {
28 | delay(1);
29 | }
30 | SerialUSB.println("WIO Termianl USB Display");
31 | */
32 |
33 | // Should after SerialUSB ready.
34 | // Please see the note above.
35 | USBDISP().begin(true);
36 | }
37 |
38 | void loop() {
39 | // SERHD.print(".");
40 | // SerialUSB.print(".");
41 | USBDISP().eventRun();
42 | }
43 |
--------------------------------------------------------------------------------
/examples/USBDisplayAndMouseControl/USBDisplayAndMouseControl.ino:
--------------------------------------------------------------------------------
1 | /*
2 | * USBDisplayAndMouseControl.ino
3 | *
4 | * A demo for Wio Terminal to enumerate a USB Display Device and simulate mouse by buttons.
5 | * It is used as a raspberry PI monitor to display the desktop and mouse control.
6 | * Such as Mouse Up, Mouse Down, Mouse Left, Mouse Right,
7 | * Click the left mouse button, Click the right mouse button,
8 | * Up roll, Down roll and etc.
9 | *
10 | * Copyright (c) 2020 seeed technology co., ltd.
11 | * Author : weihong.cai (weihong.cai@seeed.cc)
12 | * Create Time : July 2020
13 | * Change Log :
14 | *
15 | * The MIT License (MIT)
16 | *
17 | * Permission is hereby granted, free of charge, to any person obtaining a copy
18 | * of this software and associated documentation files (the "Software"), to deal
19 | * in the Software without restriction, including without limitation the rights
20 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 | * copies of the Software, and to permit persons to whom the Software istm
22 | * furnished to do so, subject to the following conditions:
23 | *
24 | * The above copyright notice and this permission notice shall be included in
25 | * all copies or substantial portions of the Software.
26 | *
27 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS INcommInterface
33 | * THE SOFTWARE.
34 | *
35 | * Mouse Usage(in Wio Terminal):
36 | * Press the WIO_5S_UP -----------------------> Mouse Up
37 | * Press the WIO_5S_DOWN ---------------------> Mouse Down
38 | * Press the WIO_5S_LEFT ---------------------> Mouse Left
39 | * Press the WIO_5S_RIGHT --------------------> Mouse Right
40 | * Press the WIO_5S_PRESS --------------------> Click the left mouse button
41 | * Press the BUTTON_3 ------------------------> Click the right mouse button
42 | * Press the BUTTON_2 ------------------------> Switch the speed of mouse moving
43 | * Press the BUTTON_1 and WIO_5S_UP ----------> Up roll
44 | * Press the BUTTON_1 and WIO_5S_DOWN --------> Down roll
45 | *
46 | * Some tips:
47 | * 1. If your PC unables to recognize USB device leading the Wio Terminal can’t work.
48 | * You can solve this problem through updating your ArduinoCore.
49 | * Please follow this: https://forum.seeedstudio.com/t/seeeduino-xiao-cant-simulate-keys-pressed/252819/6?u=weihong.cai
50 | *
51 | * You can know more about the Wio Terminal from: https://wiki.seeedstudio.com/Wio-Terminal-Getting-Started/
52 | * If you have any questions, you can leave a message on the forum: https://forum.seeedstudio.com
53 | *
54 | * Note:
55 | * The USBDISP().begin(bool reverse, bool usermode) function has two parameters.
56 | * In our demo, the default setting is USBDISP().begin(true)
57 | * If you want to parse drawing function in usermode-sdk or python-demo(seeed-linux-usbdisp),
58 | * you need to set it as USBDISP().begin(true, true)
59 | */
60 |
61 | #define SERHD SERIAL_PORT_HARDWARE
62 | #include "USBDISP.h"
63 | #include "Mouse.h"
64 |
65 | /*----------------Define the button pins---------------------------*/
66 | const int upButton = WIO_5S_UP;
67 | const int downButton = WIO_5S_DOWN;
68 | const int leftButton = WIO_5S_LEFT;
69 | const int rightButton = WIO_5S_RIGHT;
70 | const int mouseBttonLeft = WIO_5S_PRESS;
71 | const int mouseBttonRight = BUTTON_3;
72 | const int switchRangeButton = BUTTON_2;
73 | const int mouseWheel = BUTTON_1;
74 |
75 | // Output range of X or Y movement; affects movement speed
76 | int range = 6;
77 |
78 | // The time record paramas
79 | unsigned long _currentMillis;
80 | unsigned long _previousMillis;
81 | unsigned long timeDifference;
82 | char flag;
83 |
84 | #define TIME_100_Ms 100
85 | #define TIME_500_Ms 500
86 |
87 | void setup() {
88 | // Initialize the buttons' inputs:
89 | pinMode(upButton, INPUT);
90 | pinMode(downButton, INPUT);
91 | pinMode(leftButton, INPUT);
92 | pinMode(rightButton, INPUT);
93 | pinMode(mouseWheel, INPUT);
94 | pinMode(mouseBttonLeft, INPUT);
95 | pinMode(mouseBttonRight, INPUT);
96 | pinMode(switchRangeButton, INPUT);
97 |
98 | // Initialize mouse control:
99 | Mouse.begin();
100 |
101 | // Construct the singleton object
102 | (void)USBDISP();
103 |
104 | // Open the serial port
105 | SERHD.begin(115200);
106 | SERHD.println("WIO Termianl USB Display");
107 |
108 | SerialUSB.begin(115200);
109 | /*
110 | while (!SerialUSB) {
111 | delay(1);
112 | }
113 | SerialUSB.println("WIO Termianl USB Display");
114 | */
115 |
116 | // Should after SerialUSB ready.
117 | // Please see the note above.
118 | USBDISP().begin(true);
119 | }
120 |
121 | void loop() {
122 | // Read the button state:
123 | int upState = digitalRead(upButton);
124 | int downState = digitalRead(downButton);
125 | int rightState = digitalRead(rightButton);
126 | int leftState = digitalRead(leftButton);
127 | int clickState_mouseWheel = digitalRead(mouseWheel);
128 | int clickState_mouseButtonLeft = digitalRead(mouseBttonLeft);
129 | int clickState_mouseButtonRight = digitalRead(mouseBttonRight);
130 | int switchRangeButtonState = digitalRead(switchRangeButton);
131 |
132 | // Calculate the movement distance based on the button states:
133 | int xDistance = leftState - rightState;
134 | int yDistance = upState - downState;
135 |
136 | /*------------------Mouse Move-------------------------------------*/
137 | // if X or Y is non-zero, move:
138 | if ((xDistance != 0) || (yDistance != 0)) {
139 | // use millis() to record current time(ms)
140 | _currentMillis = millis();
141 | timeDifference = _currentMillis - _previousMillis;
142 | if (timeDifference >= TIME_500_Ms) {
143 | flag = 2;
144 | }
145 | else if (timeDifference >= TIME_100_Ms) {
146 | flag = 1;
147 | }
148 | else {
149 | flag = 0;
150 | }
151 |
152 | switch (flag) {
153 | case 0: Mouse.move(xDistance, yDistance, 0); break; // low speed
154 | case 1: Mouse.move(0, 0, 0); break; // stop
155 | case 2: Mouse.move(xDistance*range, yDistance*range, 0); break; // high speed
156 | default: Mouse.move(0, 0, 0); break; // stop
157 | }
158 | }
159 | else {
160 | _previousMillis = millis();
161 | flag = 0;
162 | }
163 |
164 | /*-------------Mouse Button Left Click-----------------------------*/
165 | // if the mouse button left is pressed:
166 | if (clickState_mouseButtonLeft == LOW) {
167 | // if the mouse is not pressed, press it:
168 | if (!Mouse.isPressed(MOUSE_LEFT)) {
169 | Mouse.press(MOUSE_LEFT);
170 | }
171 | }
172 | // else the mouse button left is not pressed:
173 | else {
174 | // if the mouse is pressed, release it:
175 | if (Mouse.isPressed(MOUSE_LEFT)) {
176 | Mouse.release(MOUSE_LEFT);
177 | }
178 | }
179 |
180 | /*-------------Mouse Button Right Click----------------------------*/
181 | // if the mouse button right is pressed:
182 | if (clickState_mouseButtonRight == LOW) {
183 | // if the mouse is not pressed, press it:
184 | if (!Mouse.isPressed(MOUSE_RIGHT)) {
185 | Mouse.press(MOUSE_RIGHT);
186 | }
187 | }
188 | // else the mouse button right is not pressed:
189 | else {
190 | // if the mouse is pressed, release it:
191 | if (Mouse.isPressed(MOUSE_RIGHT)) {
192 | Mouse.release(MOUSE_RIGHT);
193 | }
194 | }
195 |
196 | /*------------------Up roll----------------------------------------*/
197 | if ((upState == LOW) && (clickState_mouseWheel == LOW)) {
198 | Mouse.move(0, 0, 1);
199 | }
200 |
201 | /*------------------Down roll--------------------------------------*/
202 | if ((downState == LOW) && (clickState_mouseWheel == LOW)) {
203 | Mouse.move(0, 0, -1);
204 | }
205 |
206 | /*------------------Switch Range-----------------------------------*/
207 | if (switchRangeButtonState == LOW) {
208 | range += 2;
209 | if(range > 10){
210 | range = 2;
211 | }
212 | }
213 |
214 | /*--------------------Run USB Diaplay------------------------------*/
215 | // SERHD.print(".");
216 | // SerialUSB.print(".");
217 | USBDISP().eventRun();
218 | }
--------------------------------------------------------------------------------
/examples/USBDisplayAndMouseControl/USBDisplayAndMouseControl.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Seeed-Studio/Seeed_Arduino_USBDISP/f13ab007afb3d0a9872d2fddb8be6eab6f427825/examples/USBDisplayAndMouseControl/USBDisplayAndMouseControl.jpg
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map HID
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | HID KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 | begin KEYWORD2
15 | SendReport KEYWORD2
16 | AppendDescriptor KEYWORD2
17 |
18 | #######################################
19 | # Constants (LITERAL1)
20 | #######################################
21 | HID_TX LITERAL1
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=Seeed_Arduino_USBDISP
2 | version=1.0.0
3 | author=Seeed Studio
4 | maintainer=Seeed Studio
5 | sentence=Support USB Display Device.
6 | paragraph=An Arduino library for Seeed Arduino USBDISP
7 | category=Display
8 | url=https://github.com/Seeed-Studio/Seeed_Arduino_USBDISP
9 | architectures=*
10 |
--------------------------------------------------------------------------------
/src/USBDISP.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2020, Seeed Studio. All right reserved.
3 |
4 | Arduino Setting:
5 | CPU Speed: 200 MHz
6 | Optimize : Small (-Os)
7 | USB Stack: Arduino
8 | Debug : On // printf message will output to RPI compatible UART
9 |
10 | Permission to use, copy, modify, and/or distribute this software for
11 | any purpose with or without fee is hereby granted, provided that the
12 | above copyright notice and this permission notice appear in all copies.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
15 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
16 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
17 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
18 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 | SOFTWARE.
22 | */
23 |
24 | #include "USBDISP.h"
25 | #include "SPI.h"
26 |
27 | // Use hardware SPI
28 | TFT_eSPI tft = TFT_eSPI();
29 |
30 | bool USBDISP_::parseDrawFunction;
31 |
32 | #if defined(USBCON)
33 |
34 | static rpusbdisp_status_normal_packet_t usbdisp_status[1] = {
35 | 0x00, // Packet Type
36 | RPUSBDISP_DISPLAY_STATUS_DIRTY_FLAG,
37 | RPUSBDISP_TOUCH_STATUS_NO_TOUCH,
38 | 0x0U,
39 | 0x0U,
40 | };
41 |
42 | USBDISP_& USBDISP()
43 | {
44 | static USBDISP_ obj;
45 | return obj;
46 | }
47 |
48 | int USBDISP_::getInterface(uint8_t* interfaceCount)
49 | {
50 | *interfaceCount += 1; // uses 1
51 | USBDISPDescriptor dispInterface = {
52 | D_INTERFACE(pluggedInterface, 2, USB_INTERFACE_DISP_CLASS, USB_INTERFACE_DISP_SUBCLASS, USB_INTERFACE_PROTOCOL_NONE),
53 | D_ENDPOINT(USB_ENDPOINT_OUT(pluggedEndpoint), USB_ENDPOINT_TYPE_BULK, EPX_SIZE, 0x01),
54 | D_ENDPOINT(USB_ENDPOINT_IN(pluggedEndpoint + 1), USB_ENDPOINT_TYPE_INTERRUPT, 32, 0x05),
55 | };
56 | return USBDevice.sendControl(&dispInterface, sizeof(dispInterface));
57 | }
58 |
59 | int USBDISP_::getDescriptor(USBSetup& setup)
60 | {
61 | // Check if this is a USBDISP Class Descriptor request
62 | if (setup.bmRequestType != REQUEST_DEVICETOHOST_STANDARD_INTERFACE) { return 0; }
63 |
64 | // In a USBDISP Class Descriptor wIndex cointains the interface number
65 | if (setup.wIndex != pluggedInterface) { return 0; }
66 |
67 | int total = 0;
68 | /*
69 | USBDevice.packMessages(true);
70 | int res = USBDevice.sendControl(thisDesc, thisDescLength);
71 | if (res == -1)
72 | return -1;
73 | total += res;
74 | USBDevice.packMessages(false);
75 | */
76 | return total;
77 | }
78 |
79 | uint32_t USBDISP_::usbBackRead(void *data, uint32_t len) {
80 | uint8_t& ep = pluggedEndpoint;
81 | uint8_t* dptr = (uint8_t*)data;
82 | unsigned sz;
83 | int i = 0;
84 |
85 | if ((sz = backbuf.available())) {
86 | for (; i < len && i < sz; i++) {
87 | dptr[i] = backbuf.read_char();
88 | }
89 | }
90 |
91 | /*
92 | sz = USBDevice.available(ep);
93 | if (sz > len - i)
94 | sz = len - i;
95 | */
96 | sz = USBDevice.recv(ep, &dptr[i], len - i);
97 | return sz + i;
98 | }
99 |
100 | uint32_t USBDISP_::usbBackPeek(void) {
101 | uint8_t& ep = pluggedEndpoint;
102 | // #.2 Receive USB DATA when screen drawing,
103 | // or else will missing USB DATA.
104 | uint32_t av = USBDevice.available(ep);
105 | for (int i = 0; i < av; i++) {
106 | uint8_t c = USBDevice.recv(ep);
107 | backbuf.store_char(c);
108 | }
109 | return av;
110 | }
111 |
112 | unsigned USBDISP_::usbBackAvail(void) {
113 | uint8_t& ep = pluggedEndpoint;
114 | return backbuf.available() + USBDevice.available(ep);
115 | }
116 |
117 | // return pixel data bytes processed,
118 | // unprocessed/next-action data will save into backbuf.
119 | int USBDISP_::bitbltAppendData(int rle, uint8_t* dptr, int sz) {
120 | static int rle_comn = 0;
121 | static uint16_t the_pixel;
122 | int i, rsz; /* required size */
123 |
124 | if (!rle) {
125 | rsz = (frame_pos + sz > frame_sz)? frame_sz - frame_pos: sz;
126 |
127 | #if USE_FRAME_BUFF
128 | memcpy(&frame_buff[frame_pos], dptr, rsz);
129 | frame_pos += rsz;
130 | i = rsz;
131 | #else
132 |
133 | for (i = 0; i < rsz; i++) {
134 | if (++frame_pos & 0x1U) {
135 | the_pixel = dptr[i] << 0;
136 | } else {
137 | the_pixel |= dptr[i] << 8;
138 | tft.pushColor(the_pixel);
139 | }
140 | }
141 | #endif
142 | goto _remain;
143 | }
144 |
145 | rsz = 0;
146 | // decompress RLE DATA
147 | for (i = 0; i < sz; i++) {
148 | if (frame_pos >= frame_sz) {
149 | break;
150 | }
151 |
152 | if (rle_pos >= rle_len) {
153 | // rle header char
154 | rle_len = ((dptr[i] & RPUSBDISP_RLE_BLOCKFLAG_SIZE_BIT) + 1) << 1;
155 | rle_comn = !!(dptr[i] & RPUSBDISP_RLE_BLOCKFLAG_COMMON_BIT);
156 |
157 | rle_pos = 0;
158 | if (rle_comn) {
159 | // common section only have a single color
160 | // 2 Bytes (BGR565)
161 | rle_pos = rle_len - 2;
162 | }
163 | continue;
164 | }
165 |
166 | // rle content char
167 | ++rle_pos;
168 |
169 | if (rle_comn) {
170 | if (rle_pos >= rle_len) {
171 | // compressed upper part color
172 | the_pixel |= dptr[i] << 8;
173 |
174 | #if USE_FRAME_BUFF
175 | for (int k = 0; k < rle_len >> 1; k++) {
176 | *(uint16_t*)&frame_buff[frame_pos] = the_pixel;
177 | frame_pos += 2;
178 | }
179 | #else
180 | tft.pushColor(the_pixel, rle_len >> 1);
181 | frame_pos += rle_len;
182 | #endif
183 | rsz += rle_len;
184 | } else {
185 | // compressed lower part color
186 | the_pixel = dptr[i] << 0;
187 | }
188 | continue;
189 | }
190 |
191 | // normal color part
192 | #if USE_FRAME_BUFF
193 | frame_buff[frame_pos++] = dptr[i];
194 | #else
195 | if (++frame_pos & 0x1U) {
196 | the_pixel = dptr[i] << 0;
197 | } else {
198 | the_pixel |= dptr[i] << 8;
199 | tft.pushColor(the_pixel);
200 | }
201 | #endif
202 | rsz++;
203 | }
204 |
205 | _remain:
206 | /* remain chars unprocessed */
207 | if (i < sz) {
208 | printf("M%d\r\n", sz - i);
209 |
210 | for (; i < sz; i++) {
211 | backbuf.store_char(dptr[i]);
212 | }
213 | }
214 | return rsz;
215 | }
216 |
217 | int USBDISP_::parseBitblt(int rle) {
218 | static rpusbdisp_disp_bitblt_packet_t bb[1];
219 | unsigned load;
220 | uint8_t& ep = pluggedEndpoint;
221 | /*
222 | #define TIMEOUT_MAX 10000000
223 | volatile unsigned timeout = TIMEOUT_MAX;
224 | */
225 | int sz;
226 |
227 | *bb = ucmd->bblt;
228 |
229 | load = bb->width * bb->height * 2/*RGB565*/;
230 | frame_sz = load;
231 | frame_pos = 0;
232 |
233 | rle_len = rle_pos = 0;
234 |
235 | tft.setAddrWindow(bb->x, bb->y, bb->width, bb->height);
236 | tft.startWrite();
237 |
238 | if (bulkpos > sizeof ucmd->bblt) {
239 | sz = bulkpos - sizeof ucmd->bblt;
240 | sz = bitbltAppendData(rle, &bulkbuf[sizeof ucmd->bblt], sz);
241 | load -= sz;
242 | }
243 |
244 | for (bulkpos = 0; load;) {
245 | if ((sz = usbBackAvail()) == 0) {
246 | continue;
247 | }
248 |
249 | sz = min(sz, EPX_SIZE - bulkpos);
250 | bulkpos += usbBackRead(bulkbuf + bulkpos, sz);
251 | /*
252 | // Bug, will block the USB receiving
253 | if (--timeout != 0 && bulkpos < EPX_SIZE) {
254 | continue;
255 | }
256 | timeout = TIMEOUT_MAX;
257 | */
258 | bulkpos = 0;
259 |
260 | if (!rle && *bulkbuf != RPUSBDISP_DISPCMD_BITBLT
261 | || rle && *bulkbuf != RPUSBDISP_DISPCMD_BITBLT_RLE
262 | ) {
263 | printf("BBE#0\r\n");
264 | break;
265 | }
266 |
267 | // skip header
268 | --sz;
269 | sz = bitbltAppendData(rle, &bulkbuf[1], sz);
270 |
271 | load -= sz;
272 | }
273 |
274 | #if USE_FRAME_BUFF
275 | for (sz = 0; sz < frame_pos; sz += bb->width << 1) {
276 | int i;
277 | /*
278 | * pushColors 16 bit pixel MSB first,
279 | * and argument swap = true is ineffective.
280 | */
281 | for (i = 0; i < (bb->width << 1); i += 2) {
282 | uint8_t* ptr = &frame_buff[sz + i];
283 | uint8_t pix = *ptr;
284 | *ptr = ptr[1];
285 | ptr[1] = pix;
286 | }
287 |
288 | tft.pushColors((uint16_t*)&frame_buff[sz], bb->width, false);
289 | usbBackPeek();
290 | }
291 | #endif
292 | tft.endWrite();
293 |
294 | if (bb->header.cmd_flag & RPUSBDISP_CMD_FLAG_CLEARDITY) {
295 | usbdisp_status->display_status &= ~RPUSBDISP_DISPLAY_STATUS_DIRTY_FLAG;
296 | }
297 |
298 | // report display status
299 | USBDevice.send(ep + 1, usbdisp_status, sizeof usbdisp_status);
300 | return 0;
301 | }
302 |
303 | int USBDISP_::parseFill(void) {
304 | static rpusbdisp_disp_fill_packet_t Fill[1];
305 | uint8_t& ep = pluggedEndpoint;
306 |
307 | *Fill = ucmd->fill;
308 |
309 | tft.startWrite();
310 | tft.fillScreen(Fill->color_565);
311 | tft.endWrite();
312 |
313 | if (Fill->header.cmd_flag & RPUSBDISP_CMD_FLAG_CLEARDITY) {
314 | usbdisp_status->display_status &= ~RPUSBDISP_DISPLAY_STATUS_DIRTY_FLAG;
315 | }
316 |
317 | // report display status
318 | USBDevice.send(ep + 1, usbdisp_status, sizeof usbdisp_status);
319 | return 0;
320 | }
321 |
322 | int USBDISP_::parseFillRect(void) {
323 | static rpusbdisp_disp_fillrect_packet_t Rect[1];
324 | uint8_t& ep = pluggedEndpoint;
325 |
326 | *Rect = ucmd->rect;
327 |
328 | tft.startWrite();
329 | tft.fillRect(Rect->left, Rect->top, Rect->right - Rect->left, Rect->bottom - Rect->top, Rect->color_565);
330 | tft.endWrite();
331 |
332 | if (Rect->header.cmd_flag & RPUSBDISP_CMD_FLAG_CLEARDITY) {
333 | usbdisp_status->display_status &= ~RPUSBDISP_DISPLAY_STATUS_DIRTY_FLAG;
334 | }
335 |
336 | // report display status
337 | USBDevice.send(ep + 1, usbdisp_status, sizeof usbdisp_status);
338 | return 0;
339 | }
340 |
341 | int USBDISP_::parseCopyArea(void) {
342 | static rpusbdisp_disp_copyarea_packet_t CopyArea[1];
343 | uint8_t& ep = pluggedEndpoint;
344 |
345 | uint16_t *data;
346 |
347 | *CopyArea = ucmd->copy;
348 |
349 | data = (uint16_t *) malloc(CopyArea->width * CopyArea->height * sizeof(uint16_t));
350 |
351 | // Read a block of pixels to a data buffer, buffer is 16 bit and the array size must be at least w * h
352 | tft.readRect(CopyArea->sx, CopyArea->sy, CopyArea->width, CopyArea->height, (uint16_t *)data);
353 |
354 | tft.startWrite();
355 | // Write a block of pixels to the screen
356 | tft.pushRect(CopyArea->dx, CopyArea->dy, CopyArea->width, CopyArea->height, (uint16_t *)data);
357 | tft.endWrite();
358 |
359 | if (CopyArea->header.cmd_flag & RPUSBDISP_CMD_FLAG_CLEARDITY) {
360 | usbdisp_status->display_status &= ~RPUSBDISP_DISPLAY_STATUS_DIRTY_FLAG;
361 | }
362 |
363 | // report display status
364 | USBDevice.send(ep + 1, usbdisp_status, sizeof usbdisp_status);
365 |
366 | free(data);
367 |
368 | return 0;
369 | }
370 |
371 | int USBDISP_::eventRun(void) {
372 | uint32_t av;
373 | int mode_rle;
374 |
375 | /*
376 | * #.3 cooperate with #.4, drop packet only has a broken header.
377 | */
378 | /*
379 | if (bulkpos != 0)
380 | printf("bulkpos = %d\r\n", bulkpos);
381 | */
382 | bulkpos = 0;
383 | _repeat:
384 | if /*while*/ ((av = usbBackAvail())) {
385 | av = min(av, EPX_SIZE - bulkpos);
386 | av = usbBackRead(bulkbuf + bulkpos, av);
387 | bulkpos += av;
388 | __DMB();
389 |
390 | if (!(*bulkbuf & RPUSBDISP_CMD_FLAG_START)) {
391 | printf("PE#1:%d\r\n", bulkpos);
392 | bulkpos = 0;
393 | goto _repeat;
394 | }
395 | mode_rle = 0;
396 | switch (*bulkbuf & RPUSBDISP_CMD_MASK) {
397 | case RPUSBDISP_DISPCMD_NOPE:
398 | break;
399 | case RPUSBDISP_DISPCMD_BITBLT_RLE:
400 | mode_rle = 1;
401 | /* intentional fall-through */
402 | case RPUSBDISP_DISPCMD_BITBLT:
403 | /* #.4 */
404 | if (bulkpos < sizeof ucmd->bblt) {
405 | printf("<%d\r\n", bulkpos);
406 | goto _repeat;
407 | }
408 | parseBitblt(mode_rle);
409 | break;
410 | case RPUSBDISP_DISPCMD_FILL:
411 | if(USBDISP_::parseDrawFunction)
412 | parseFill();
413 | break;
414 | case RPUSBDISP_DISPCMD_RECT:
415 | if(USBDISP_::parseDrawFunction)
416 | parseFillRect();
417 | break;
418 | case RPUSBDISP_DISPCMD_COPY_AREA:
419 | if(USBDISP_::parseDrawFunction)
420 | parseCopyArea();
421 | break;
422 | default:
423 | printf("PE#2:%d\r\n", *bulkbuf);
424 | break;
425 | }
426 | bulkpos = 0;
427 | }
428 |
429 | // Prevent missing USB DATA in the process
430 | // for other things doing.
431 | usbBackPeek();
432 | return 0;
433 | }
434 |
435 | bool USBDISP_::setup(USBSetup& setup)
436 | {
437 | if (pluggedInterface != setup.wIndex) {
438 | return false;
439 | }
440 | return false;
441 | }
442 |
443 | USBDISP_::USBDISP_(void) : PluggableUSBModule(2, 1, epType),
444 | bulkbuf(&ucmd->epbuf[0]), bulkpos(0)
445 | {
446 | epType[0] = USB_ENDPOINT_TYPE_BULK | USB_ENDPOINT_OUT(0);
447 | epType[1] = USB_ENDPOINT_TYPE_INTERRUPT | USB_ENDPOINT_IN(0);
448 | PluggableUSB().plug(this);
449 | }
450 |
451 | int USBDISP_::begin(bool reverse, bool usermode)
452 | {
453 | // on/off the UserMode drawing function.
454 | if(usermode)
455 | USBDISP_::parseDrawFunction = true;
456 | else
457 | USBDISP_::parseDrawFunction = false;
458 |
459 | // Initial notify, not works yet
460 | // Screen image are out of sync from power up
461 | USBDevice.send(pluggedEndpoint + 1, usbdisp_status, sizeof usbdisp_status);
462 |
463 | tft.init();
464 | // Plot with 90 deg. clockwise rotation
465 | // Required a 320x240 screen, not a 240x320.
466 | tft.setRotation(reverse? 3: 1);
467 | return 0;
468 | }
469 |
470 | #endif /* if defined(USBCON) */
471 |
--------------------------------------------------------------------------------
/src/USBDISP.h:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright (c) 2015, Arduino LLC
3 | Original code (pre-library): Copyright (c) 2011, Peter Barrett
4 |
5 | Permission to use, copy, modify, and/or distribute this software for
6 | any purpose with or without fee is hereby granted, provided that the
7 | above copyright notice and this permission notice appear in all copies.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 | WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 | WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
12 | BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
13 | OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
14 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
15 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
16 | SOFTWARE.
17 | */
18 |
19 | #ifndef __USBDISP_H__
20 | #define __USBDISP_H__
21 |
22 | #include
23 | #include
24 | #include "USB/PluggableUSB.h"
25 | #include "rpusbdisp_protocol.h"
26 | #include "TFT_eSPI.h"
27 |
28 | #if defined(USBCON)
29 |
30 | // DISP 'Driver'
31 | #define USB_INTERFACE_DISP_CLASS 0xFF /* Vendor Specific */
32 | #define USB_INTERFACE_DISP_SUBCLASS 0xFF /* Vendor Specific */
33 | #define USB_INTERFACE_PROTOCOL_NONE 0
34 |
35 | typedef struct
36 | {
37 | InterfaceDescriptor if_desc;
38 | EndpointDescriptor ep_dp; /* Display Endpoint */
39 | EndpointDescriptor ep_st; /* Status Endpoint */
40 | } USBDISPDescriptor;
41 |
42 | class USBDISP_ : public PluggableUSBModule
43 | {
44 | public:
45 | static bool parseDrawFunction;
46 |
47 | USBDISP_(void);
48 | int begin(bool reverse = false, bool usermode = false);
49 | int eventRun(void);
50 | protected:
51 | // Implementation of the PluggableUSBModule
52 | int getInterface(uint8_t* interfaceCount);
53 | int getDescriptor(USBSetup& setup);
54 | bool setup(USBSetup& setup);
55 |
56 | // Save remain unprocessed data.
57 | unsigned usbBackAvail(void);
58 | uint32_t usbBackPeek(void);
59 | uint32_t usbBackRead(void *data, uint32_t len);
60 |
61 | int parseBitblt(int rle);
62 | int bitbltAppendData(int rle, uint8_t* dptr, int sz);
63 |
64 | int parseFill(void);
65 | int parseFillRect(void);
66 | int parseCopyArea(void);
67 | private:
68 | uint32_t epType[2];
69 |
70 | /*
71 | * #.1 USE_FRAME_BUFF=1 not stable.
72 | * RAM left for backbuf are too small.
73 | */
74 | #define USE_FRAME_BUFF 0
75 | #if USE_FRAME_BUFF
76 | __attribute__((__aligned__(4))) uint8_t frame_buff[ TFT_WIDTH * TFT_HEIGHT * 2 ];
77 | #endif
78 | volatile int frame_pos; // in bytes
79 | int frame_sz; // in bytes
80 |
81 | union {
82 | #define LINEBUF_SZ (TFT_HEIGHT << 1)
83 | uint8_t epbuf[LINEBUF_SZ];
84 | rpusbdisp_disp_packet_header_t hdr;
85 | rpusbdisp_disp_fill_packet_t fill;
86 | rpusbdisp_disp_bitblt_packet_t bblt;
87 | rpusbdisp_disp_fillrect_packet_t rect;
88 | rpusbdisp_disp_copyarea_packet_t copy;
89 | } ucmd[1];
90 | uint8_t* const bulkbuf;
91 | volatile int bulkpos;
92 |
93 | RingBufferN<32768> backbuf;
94 |
95 | volatile int rle_len, rle_pos;
96 | };
97 |
98 | // Replacement for global singleton.
99 | // This function prevents static-initialization-order-fiasco
100 | // https://isocpp.org/wiki/faq/ctors#static-init-order-on-first-use
101 | USBDISP_& USBDISP();
102 |
103 | #endif // USBCON
104 |
105 | #endif // __USBDISP_H__
106 |
--------------------------------------------------------------------------------
/src/rpusbdisp_protocol.h:
--------------------------------------------------------------------------------
1 | /*
2 | * RoboPeak Project
3 | * Copyright 2009 - 2013
4 | *
5 | * RP USB Display
6 | * Protocol Def
7 | *
8 | * Initial Version by Shikai Chen
9 | */
10 |
11 | #pragma once
12 |
13 |
14 | #define RPUSBDISP_DISP_CHANNEL_MAX_SIZE 64 //64bytes
15 | #define RPUSBDISP_STATUS_CHANNEL_MAX_SIZE 32 //32bytes
16 |
17 |
18 | // -- Display Packets
19 | #define RPUSBDISP_DISPCMD_NOPE 0
20 | #define RPUSBDISP_DISPCMD_FILL 1
21 | #define RPUSBDISP_DISPCMD_BITBLT 2
22 | #define RPUSBDISP_DISPCMD_RECT 3
23 | #define RPUSBDISP_DISPCMD_COPY_AREA 4
24 | #define RPUSBDISP_DISPCMD_BITBLT_RLE 5
25 |
26 |
27 | #define RPUSBDISP_OPERATION_COPY 0
28 | #define RPUSBDISP_OPERATION_XOR 1
29 | #define RPUSBDISP_OPERATION_OR 2
30 | #define RPUSBDISP_OPERATION_AND 3
31 |
32 | #if defined(_WIN32) || defined(__ICCARM__)
33 | #pragma pack(1)
34 | #endif
35 |
36 |
37 | #define RPUSBDISP_CMD_MASK (0x3F)
38 | #define RPUSBDISP_CMD_FLAG_CLEARDITY (0x1<<6)
39 | #define RPUSBDISP_CMD_FLAG_START (0x1<<7)
40 | typedef struct _rpusbdisp_disp_packet_header_t {
41 | #if 0
42 | uint8_t cmd:6;
43 | uint8_t cleardirty:1;
44 | uint8_t start:1;
45 | #else
46 | uint8_t cmd_flag;
47 | #endif
48 | } __attribute__((packed)) rpusbdisp_disp_packet_header_t;
49 |
50 |
51 | typedef struct _rpusbdisp_disp_fill_packet_t {
52 | rpusbdisp_disp_packet_header_t header;
53 | uint16_t color_565;
54 | } __attribute__((packed)) rpusbdisp_disp_fill_packet_t;
55 |
56 |
57 | typedef struct _rpusbdisp_disp_bitblt_packet_t {
58 | rpusbdisp_disp_packet_header_t header;
59 | uint16_t x;
60 | uint16_t y;
61 | uint16_t width;
62 | uint16_t height;
63 | uint8_t operation;
64 | } __attribute__((packed)) rpusbdisp_disp_bitblt_packet_t;
65 |
66 |
67 | typedef struct _rpusbdisp_disp_fillrect_packet_t {
68 | rpusbdisp_disp_packet_header_t header;
69 | uint16_t left;
70 | uint16_t top;
71 | uint16_t right;
72 | uint16_t bottom;
73 | uint16_t color_565;
74 | uint8_t operation;
75 | } __attribute__((packed)) rpusbdisp_disp_fillrect_packet_t;
76 |
77 |
78 | typedef struct _rpusbdisp_disp_copyarea_packet_t {
79 | rpusbdisp_disp_packet_header_t header;
80 | uint16_t sx;
81 | uint16_t sy;
82 | uint16_t dx;
83 | uint16_t dy;
84 | uint16_t width;
85 | uint16_t height;
86 | } __attribute__((packed)) rpusbdisp_disp_copyarea_packet_t;
87 |
88 | #if defined(_WIN32) || defined(__ICCARM__)
89 | #pragma pack()
90 | #endif
91 |
92 |
93 | // RLE Packet Define
94 | #define RPUSBDISP_RLE_BLOCKFLAG_COMMON_BIT 0x80
95 | #define RPUSBDISP_RLE_BLOCKFLAG_SIZE_BIT 0x7f
96 |
97 | // -- Status Packets
98 |
99 | #define RPUSBDISP_STATUS_TYPE_NORMAL 0
100 |
101 |
102 | #define RPUSBDISP_DISPLAY_STATUS_DIRTY_FLAG 0x80 //a full screen transfer is required
103 |
104 |
105 | #define RPUSBDISP_TOUCH_STATUS_NO_TOUCH 0
106 | #define RPUSBDISP_TOUCH_STATUS_PRESSED 1
107 |
108 | #if defined(_WIN32) || defined(__ICCARM__)
109 | #pragma pack(1)
110 | #endif
111 |
112 |
113 | typedef struct _rpusbdisp_status_packet_header_t {
114 | uint8_t packet_type;
115 | } __attribute__((packed)) rpusbdisp_status_packet_header_t;
116 |
117 |
118 | typedef struct _rpusbdisp_status_normal_packet_t {
119 | rpusbdisp_status_packet_header_t header;
120 | uint8_t display_status;
121 | uint8_t touch_status;
122 | uint32_t touch_x;
123 | uint32_t touch_y;
124 | } __attribute__((packed)) rpusbdisp_status_normal_packet_t;
125 |
126 | #if defined(_WIN32) || defined(__ICCARM__)
127 | #pragma pack()
128 | #endif
129 |
--------------------------------------------------------------------------------