├── .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 | --------------------------------------------------------------------------------