Skip to content

Commit 1a2b141

Browse files
authored
Merge pull request #23 from adafruit/develop
resolve #21 added webusb RGB example
2 parents 01897a8 + 4bbc865 commit 1a2b141

File tree

8 files changed

+357
-10
lines changed

8 files changed

+357
-10
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ before_install:
3535
- git clone --quiet https://github.com/adafruit/ArduinoCore-samd.git $BSP_PATH/samd/$BSP_VERSION
3636

3737
install:
38-
- arduino --install-library "Adafruit SPIFlash","MIDI Library","Adafruit seesaw Library"
38+
- arduino --install-library "Adafruit SPIFlash","MIDI Library","Adafruit seesaw Library","Adafruit NeoPixel"
3939
- git clone --quiet https://github.com/adafruit/SdFat.git $HOME/Arduino/libraries/SdFat
4040
- pip3 install --user adafruit-nrfutil
4141

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
.main-content {
2+
width: 1440px;
3+
margin: auto;
4+
font-size: 14px;
5+
}
6+
7+
.connect-container {
8+
margin: 20px 0;
9+
}
10+
11+
.button::before {
12+
-webkit-border-radius: 3px;
13+
-moz-border-radius: 3px;
14+
-webkit-box-shadow: #959595 0 2px 5px;
15+
-moz-box-shadow: #959595 0 2px 5px;
16+
border-radius: 3px;
17+
box-shadow: #959595 0 2px 5px;
18+
content: "";
19+
display: block;
20+
left: 0;
21+
padding: 2px 0 0;
22+
position: absolute;
23+
top: 0;
24+
}
25+
26+
.button:active::before { padding: 1px 0 0; }
27+
28+
.button.black {
29+
background: #656565;
30+
background: -webkit-gradient(linear, 0 0, 0 bottom, from(#656565), to(#444));
31+
background: -moz-linear-gradient(#656565, #444);
32+
background: linear-gradient(#656565, #444);
33+
border: solid 1px #535353;
34+
border-bottom: solid 3px #414141;
35+
box-shadow: inset 0 0 0 1px #939393;
36+
color: #fff;
37+
text-shadow: 0 1px 0 #2f2f2f;
38+
padding: 8px 16px;
39+
outline: none;
40+
}
41+
42+
.button.black:hover {
43+
background: #4c4c4c;
44+
background: -webkit-gradient(linear, 0 0, 0 bottom, from(#4c4c4c), to(#565656));
45+
background: -moz-linear-gradient(#4c4c4c, #565656);
46+
background: linear-gradient(#4c4c4c, #565656);
47+
border: solid 1px #464646;
48+
border-bottom: solid 3px #414141;
49+
box-shadow: inset 0 0 0 1px #818181;
50+
}
51+
52+
.button.black:active {
53+
background: #474747;
54+
background: -webkit-gradient(linear, 0 0, 0 bottom, from(#474747), to(#444));
55+
background: -moz-linear-gradient(#474747, #444);
56+
background: linear-gradient(#474747, #444);
57+
border: solid 1px #2f2f2f;
58+
box-shadow: inset 0 10px 15px 0 #3e3e3e;
59+
}
60+
61+
.color-picker-container {
62+
width: 100px;
63+
height: 100px;
64+
border-radius: 50px;
65+
overflow: hidden;
66+
}
67+
68+
.color-picker {
69+
padding: 0;
70+
border: none;
71+
width: 200px;
72+
height: 200px;
73+
outline: none;
74+
transform: translate(-25%, -25%)
75+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
(function() {
2+
'use strict';
3+
4+
document.addEventListener('DOMContentLoaded', event => {
5+
let connectButton = document.querySelector("#connect");
6+
let statusDisplay = document.querySelector('#status');
7+
let port;
8+
9+
function connect() {
10+
port.connect().then(() => {
11+
statusDisplay.textContent = '';
12+
connectButton.textContent = 'Disconnect';
13+
14+
port.onReceiveError = error => {
15+
console.error(error);
16+
};
17+
}, error => {
18+
statusDisplay.textContent = error;
19+
});
20+
}
21+
22+
connectButton.addEventListener('click', function() {
23+
if (port) {
24+
port.disconnect();
25+
connectButton.textContent = 'Connect';
26+
statusDisplay.textContent = '';
27+
port = null;
28+
} else {
29+
serial.requestPort().then(selectedPort => {
30+
port = selectedPort;
31+
connect();
32+
}).catch(error => {
33+
statusDisplay.textContent = error;
34+
});
35+
}
36+
});
37+
38+
serial.getPorts().then(ports => {
39+
if (ports.length === 0) {
40+
statusDisplay.textContent = 'No device found.';
41+
} else {
42+
statusDisplay.textContent = 'Connecting...';
43+
port = ports[0];
44+
connect();
45+
}
46+
});
47+
48+
let colorPicker = document.getElementById("color_picker");
49+
50+
colorPicker.addEventListener("change", function(event) {
51+
port.send(new TextEncoder("utf-8").encode(colorPicker.value));
52+
});
53+
});
54+
})();

docs/examples/webusb-rgb/index.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>TinyUSB</title>
5+
<script src="serial.js"></script>
6+
<script src="application.js"></script>
7+
<link rel="stylesheet" href="application.css">
8+
</head>
9+
<body>
10+
<div class="main-content">
11+
<h1>TinyUSB - WebUSB RGB Example</h1>
12+
<div class="connect-container">
13+
<button id="connect" class="button black">Connect</button>
14+
<span id="status"></span>
15+
</div>
16+
<div class="color-picker-container">
17+
<input type="color" id="color_picker" value="#00ff00" class="color-picker">
18+
</div>
19+
</div>
20+
</body>
21+
</html>

docs/examples/webusb-rgb/serial.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
var serial = {};
2+
3+
(function() {
4+
'use strict';
5+
6+
serial.getPorts = function() {
7+
return navigator.usb.getDevices().then(devices => {
8+
return devices.map(device => new serial.Port(device));
9+
});
10+
};
11+
12+
serial.requestPort = function() {
13+
const filters = [
14+
{ 'vendorId': 0x239A }, // Adafruit boards
15+
{ 'vendorId': 0xcafe }, // TinyUSB example
16+
];
17+
return navigator.usb.requestDevice({ 'filters': filters }).then(
18+
device => new serial.Port(device)
19+
);
20+
}
21+
22+
serial.Port = function(device) {
23+
this.device_ = device;
24+
this.interfaceNumber = 0;
25+
this.endpointIn = 0;
26+
this.endpointOut = 0;
27+
};
28+
29+
serial.Port.prototype.connect = function() {
30+
let readLoop = () => {
31+
this.device_.transferIn(this.endpointIn, 64).then(result => {
32+
this.onReceive(result.data);
33+
readLoop();
34+
}, error => {
35+
this.onReceiveError(error);
36+
});
37+
};
38+
39+
return this.device_.open()
40+
.then(() => {
41+
if (this.device_.configuration === null) {
42+
return this.device_.selectConfiguration(1);
43+
}
44+
})
45+
.then(() => {
46+
var interfaces = this.device_.configuration.interfaces;
47+
interfaces.forEach(element => {
48+
element.alternates.forEach(elementalt => {
49+
if (elementalt.interfaceClass==0xFF) {
50+
this.interfaceNumber = element.interfaceNumber;
51+
elementalt.endpoints.forEach(elementendpoint => {
52+
if (elementendpoint.direction == "out") {
53+
this.endpointOut = elementendpoint.endpointNumber;
54+
}
55+
if (elementendpoint.direction=="in") {
56+
this.endpointIn =elementendpoint.endpointNumber;
57+
}
58+
})
59+
}
60+
})
61+
})
62+
})
63+
.then(() => this.device_.claimInterface(this.interfaceNumber))
64+
.then(() => this.device_.selectAlternateInterface(this.interfaceNumber, 0))
65+
.then(() => this.device_.controlTransferOut({
66+
'requestType': 'class',
67+
'recipient': 'interface',
68+
'request': 0x22,
69+
'value': 0x01,
70+
'index': this.interfaceNumber}))
71+
.then(() => {
72+
readLoop();
73+
});
74+
};
75+
76+
serial.Port.prototype.disconnect = function() {
77+
return this.device_.controlTransferOut({
78+
'requestType': 'class',
79+
'recipient': 'interface',
80+
'request': 0x22,
81+
'value': 0x00,
82+
'index': this.interfaceNumber})
83+
.then(() => this.device_.close());
84+
};
85+
86+
serial.Port.prototype.send = function(data) {
87+
return this.device_.transferOut(this.endpointOut, data);
88+
};
89+
})();

docs/examples/webusb-serial/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
</head>
99
<body>
1010
<div class="main-content">
11-
<h1>TinyUSB's WebUSB Demo</h1>
11+
<h1>TinyUSB - WebUSB Serial Example</h1>
1212
<div class="connect-container">
1313
<button id="connect" class="button black">Connect</button>
1414
<span id="status"></span>
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*********************************************************************
2+
Adafruit invests time and resources providing this open source code,
3+
please support Adafruit and open-source hardware by purchasing
4+
products from Adafruit!
5+
6+
MIT license, check LICENSE for more information
7+
Copyright (c) 2019 Ha Thach for Adafruit Industries
8+
All text above, and the splash screen below must be included in
9+
any redistribution
10+
*********************************************************************/
11+
12+
/* This sketch demonstrates WebUSB as web serial with browser with WebUSB support (e.g Chrome).
13+
* After enumerated successfully, Browser will pop-up notification
14+
* with URL to landing page, click on it to test
15+
* - Click "Connect" and select device, When connected the neopixel LED will change color to Green.
16+
* - When received color from browser in format '#RRGGBB', device will change the color of neopixel accordingly
17+
*
18+
* Note:
19+
* - The WebUSB landing page notification is currently disabled in Chrome
20+
* on Windows due to Chromium issue 656702 (https://crbug.com/656702). You have to
21+
* go to landing page (below) to test
22+
*
23+
* - On Windows 7 and prior: You need to use Zadig tool to manually bind the
24+
* WebUSB interface with the WinUSB driver for Chrome to access. From windows 8 and 10, this
25+
* is done automatically by firmware.
26+
*/
27+
28+
#include "Adafruit_TinyUSB.h"
29+
#include <Adafruit_NeoPixel.h>
30+
31+
// Which pin on the Arduino is connected to the NeoPixels?
32+
// On a Trinket or Gemma we suggest changing this to 1
33+
// use on-board neopixel PIN_NEOPIXEL if existed
34+
#ifdef PIN_NEOPIXEL
35+
#define PIN PIN_NEOPIXEL
36+
#else
37+
#define PIN 8
38+
#endif
39+
40+
// How many NeoPixels are attached to the Arduino?
41+
#define NUMPIXELS 1
42+
43+
// When we setup the NeoPixel library, we tell it how many pixels, and which pin to use to send signals.
44+
// Note that for older NeoPixel strips you might need to change the third parameter--see the strandtest
45+
// example for more information on possible values.
46+
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
47+
48+
// USB WebUSB object
49+
Adafruit_USBD_WebUSB usb_web;
50+
51+
// Landing Page: scheme (0: http, 1: https), url
52+
WEBUSB_URL_DEF(landingPage, 1 /*https*/, "adafruit.github.io/Adafruit_TinyUSB_Arduino/examples/webusb-rgb");
53+
54+
// the setup function runs once when you press reset or power the board
55+
void setup()
56+
{
57+
usb_web.begin();
58+
usb_web.setLandingPage(&landingPage);
59+
usb_web.setLineStateCallback(line_state_callback);
60+
61+
Serial.begin(115200);
62+
63+
// This initializes the NeoPixel with RED
64+
pixels.begin();
65+
pixels.setBrightness(50);
66+
pixels.setPixelColor(0, 0xff0000);
67+
pixels.show();
68+
69+
// wait until device mounted
70+
while( !USBDevice.mounted() ) delay(1);
71+
72+
Serial.println("TinyUSB WebUSB RGB example");
73+
}
74+
75+
// convert a hex character to number
76+
uint8_t char2num(char c)
77+
{
78+
if (c >= 'a') return c - 'a' + 10;
79+
if (c >= 'A') return c - 'A' + 10;
80+
return c - '0';
81+
}
82+
83+
void loop()
84+
{
85+
// Landing Page 7 characters as hex color '#RRGGBB'
86+
if (usb_web.available() < 7) return;
87+
88+
uint8_t input[7];
89+
usb_web.readBytes(input, 7);
90+
91+
// Print to serial for debugging
92+
Serial.write(input, 7);
93+
Serial.println();
94+
95+
uint8_t red = 16*char2num(input[1]) + char2num(input[2]);
96+
uint8_t green = 16*char2num(input[3]) + char2num(input[4]);
97+
uint8_t blue = 16*char2num(input[5]) + char2num(input[6]);
98+
99+
pixels.setPixelColor(0, red, green, blue);
100+
pixels.show();
101+
}
102+
103+
void line_state_callback(bool connected)
104+
{
105+
// connected = green, disconnected = red
106+
pixels.setPixelColor(0, connected ? 0x00ff00 : 0xff0000);
107+
pixels.show();
108+
}

0 commit comments

Comments
 (0)