Skip to content

Commit 1058399

Browse files
authored
Merge pull request #1 from adafruit/main
Correct CircuitPython IR ?learning guides to match irremote library example
2 parents 465fe5a + 6c93e10 commit 1058399

File tree

23 files changed

+819
-2
lines changed

23 files changed

+819
-2
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// SPDX-FileCopyrightText: 2024 ladyada for Adafruit Industries
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#include "SdFat.h"
6+
#include "Adafruit_TestBed.h"
7+
#include "Adafruit_TinyUSB.h"
8+
9+
// HID report descriptor using TinyUSB's template
10+
// Single Report (no ID) descriptor
11+
uint8_t const desc_hid_report[] = {
12+
TUD_HID_REPORT_DESC_KEYBOARD()
13+
};
14+
15+
Adafruit_USBD_HID usb_hid;
16+
17+
#define TIP_KEYCODE HID_KEY_SPACE
18+
#define RING_KEYCODE HID_KEY_ENTER
19+
20+
21+
extern Adafruit_TestBed TB;
22+
uint8_t allpins[] = {PIN_TIP, PIN_RING1, PIN_RING2, PIN_SLEEVE};
23+
24+
bool cableinserted = false;
25+
bool last_cablestate = false;
26+
uint32_t last_i2cscan = 0;
27+
28+
void setup() {
29+
Serial.begin(115200);
30+
//while (!Serial) { yield(); delay(10); } // wait till serial port is opened
31+
32+
usb_hid.setBootProtocol(HID_ITF_PROTOCOL_KEYBOARD);
33+
usb_hid.setPollInterval(2);
34+
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
35+
usb_hid.setStringDescriptor("TinyUSB Keyboard");
36+
usb_hid.begin();
37+
38+
39+
TB.neopixelPin = PIN_NEOPIXEL;
40+
TB.neopixelNum = NUM_NEOPIXEL;
41+
TB.begin();
42+
}
43+
44+
void loop() {
45+
delay(10); // sample every 10 ms
46+
47+
uint8_t keycode[6] = { 0 };
48+
uint8_t count = 0;
49+
// used to avoid send multiple consecutive zero report for keyboard
50+
static bool keyPressedPreviously = false;
51+
52+
pinMode(PIN_TIP, OUTPUT);
53+
digitalWrite(PIN_TIP, LOW);
54+
pinMode(PIN_TIP_SWITCH, INPUT_PULLUP);
55+
cableinserted = digitalRead(PIN_TIP_SWITCH);
56+
57+
if (!cableinserted) {
58+
TB.setColor(RED);
59+
}
60+
61+
if (cableinserted && !last_cablestate) {
62+
TB.setColor(GREEN);
63+
delay(250); // give em a quarter second to plug completely
64+
}
65+
66+
last_cablestate = cableinserted;
67+
68+
// Wake up host if we are in suspend mode
69+
if ( TinyUSBDevice.suspended() && count ) {
70+
TinyUSBDevice.remoteWakeup();
71+
}
72+
// skip if hid is not ready e.g still transferring previous report
73+
if ( !usb_hid.ready() ) return;
74+
75+
if (!cableinserted) {
76+
keyPressedPreviously = false;
77+
usb_hid.keyboardRelease(0);
78+
79+
// do an I2C scan while we're here, if we have pullups on SDA/SCL
80+
if ((millis() - last_i2cscan) > 1000) {
81+
TB.disableI2C();
82+
if (TB.testPullup(SDA) && TB.testPullup(SCL)) {
83+
Wire.begin();
84+
TB.printI2CBusScan();
85+
} else {
86+
Serial.println("No pullups on SDA/SCL");
87+
}
88+
last_i2cscan = millis();
89+
}
90+
return;
91+
}
92+
// make two inputs
93+
pinMode(PIN_TIP, INPUT_PULLUP);
94+
pinMode(PIN_RING1, INPUT_PULLUP);
95+
96+
// make two 'ground' pins
97+
pinMode(PIN_SLEEVE, OUTPUT);
98+
digitalWrite(PIN_SLEEVE, LOW);
99+
pinMode(PIN_RING2, OUTPUT);
100+
digitalWrite(PIN_RING2, LOW);
101+
102+
delay(1);
103+
104+
if (!digitalRead(PIN_TIP)) {
105+
keycode[0] = TIP_KEYCODE;
106+
count++;
107+
}
108+
if (!digitalRead(PIN_RING1)) {
109+
keycode[1] = RING_KEYCODE;
110+
count++;
111+
}
112+
113+
if (count) { // Send report if there is key pressed
114+
uint8_t const report_id = 0;
115+
uint8_t const modifier = 0;
116+
117+
keyPressedPreviously = true;
118+
usb_hid.keyboardReport(report_id, modifier, keycode);
119+
}
120+
else
121+
{
122+
// Send All-zero report to indicate there is no keys pressed
123+
// Most of the time, it is, though we don't need to send zero report
124+
// every loop(), only a key is pressed in previous loop()
125+
if ( keyPressedPreviously )
126+
{
127+
keyPressedPreviously = false;
128+
usb_hid.keyboardRelease(0);
129+
}
130+
}
131+
}

Halo_Energy_Sword/code.py

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
# SPDX-FileCopyrightText: 2019 Kattni Rembor for Adafruit Industries
2+
# SPDX-FileCopyrightText: 2019 Limor Fried for Adafruit Industries
3+
#
4+
# SPDX-License-Identifier: MIT
5+
6+
"""
7+
RP2040 Prop-Maker Feather Energy Sword
8+
Adafruit invests time and resources providing this open source code.
9+
Please support Adafruit and open source hardware by purchasing
10+
products from Adafruit!
11+
Written by Kattni Rembor & Limor Fried for Adafruit Industries
12+
Copyright (c) 2019-2020 Adafruit Industries
13+
Licensed under the MIT license.
14+
All text above must be included in any redistribution.
15+
"""
16+
17+
import time
18+
import random
19+
import digitalio
20+
import audiocore
21+
import audiobusio
22+
import board
23+
import neopixel
24+
import adafruit_lis3dh
25+
26+
# CUSTOMISE COLORS HERE:
27+
COLOR = (0, 120, 120) # Default idle is light blue
28+
ALT_COLOR = (255, 0, 250) # hit color is purple
29+
30+
# CUSTOMISE IDLE PULSE SPEED HERE: 0 is fast, above 0 slows down
31+
IDLE_PULSE_SPEED = 0 # Default is 0 seconds
32+
SWING_BLAST_SPEED = 0.0007
33+
34+
# CUSTOMISE BRIGHTNESS HERE: must be a number between 0 and 1
35+
IDLE_PULSE_BRIGHTNESS_MIN = 0.2 # Default minimum idle pulse brightness
36+
IDLE_PULSE_BRIGHTNESS_MAX = 1 # Default maximum idle pulse brightness
37+
38+
# CUSTOMISE SENSITIVITY HERE: smaller numbers = more sensitive to motion
39+
HIT_THRESHOLD = 250
40+
SWING_THRESHOLD = 150
41+
42+
# Set to the length in seconds of the "on.wav" file
43+
POWER_ON_SOUND_DURATION = 1.7
44+
45+
NUM_PIXELS = 73 # Number of pixels used in project
46+
NEOPIXEL_PIN = board.EXTERNAL_NEOPIXELS
47+
48+
enable = digitalio.DigitalInOut(board.EXTERNAL_POWER)
49+
enable.direction = digitalio.Direction.OUTPUT
50+
enable.value = True
51+
52+
strip = neopixel.NeoPixel(NEOPIXEL_PIN, NUM_PIXELS, brightness=1, auto_write=False)
53+
strip.fill(0) # NeoPixels off ASAP on startup
54+
strip.show()
55+
56+
# i2s audio
57+
audio = audiobusio.I2SOut(board.I2S_BIT_CLOCK, board.I2S_WORD_SELECT, board.I2S_DATA)
58+
wave_file = None
59+
60+
# Set up accelerometer on I2C bus, 4G range:
61+
i2c = board.I2C() # uses board.SCL and board.SDA
62+
# i2c = board.STEMMA_I2C() # For using the built-in STEMMA QT connector on a microcontroller
63+
accel = adafruit_lis3dh.LIS3DH_I2C(i2c)
64+
accel.range = adafruit_lis3dh.RANGE_4_G
65+
66+
COLOR_IDLE = COLOR # 'idle' color is the default
67+
COLOR_HIT = ALT_COLOR # "hit" color is ALT_COLOR set above
68+
COLOR_SWING = (255, 255, 255) # "swing" color white
69+
70+
71+
def play_wav(name, loop=False):
72+
"""
73+
Play a WAV file in the 'sounds' directory.
74+
:param name: partial file name string, complete name will be built around
75+
this, e.g. passing 'foo' will play file 'sounds/foo.wav'.
76+
:param loop: if True, sound will repeat indefinitely (until interrupted
77+
by another sound).
78+
"""
79+
global wave_file # pylint: disable=global-statement
80+
print("playing", name)
81+
if wave_file:
82+
wave_file.close()
83+
try:
84+
wave_file = open('sounds/' + name + '.wav', 'rb')
85+
wave = audiocore.WaveFile(wave_file)
86+
audio.play(wave, loop=loop)
87+
except OSError:
88+
pass # we'll just skip playing then
89+
90+
91+
def power_on(sound, duration):
92+
"""
93+
Animate NeoPixels with accompanying sound effect for power on.
94+
:param sound: sound name (similar format to play_wav() above)
95+
:param duration: estimated duration of sound, in seconds (>0.0)
96+
"""
97+
prev = 0
98+
start_time = time.monotonic() # Save audio start time
99+
play_wav(sound)
100+
while True:
101+
elapsed = time.monotonic() - start_time # Time spent playing sound
102+
if elapsed > duration: # Past sound duration?
103+
break # Stop animating
104+
animation_time = elapsed / duration # Animation time, 0.0 to 1.0
105+
threshold = int(NUM_PIXELS * animation_time + 0.5)
106+
num = threshold - prev # Number of pixels to light on this pass
107+
if num != 0:
108+
strip[prev:threshold] = [ALT_COLOR] * num
109+
strip.show()
110+
prev = threshold
111+
112+
113+
def mix(color_1, color_2, weight_2):
114+
"""
115+
Blend between two colors with a given ratio.
116+
:param color_1: first color, as an (r,g,b) tuple
117+
:param color_2: second color, as an (r,g,b) tuple
118+
:param weight_2: Blend weight (ratio) of second color, 0.0 to 1.0
119+
:return (r,g,b) tuple, blended color
120+
"""
121+
if weight_2 < 0.0:
122+
weight_2 = 0.0
123+
elif weight_2 > 1.0:
124+
weight_2 = 1.0
125+
weight_1 = 1.0 - weight_2
126+
return (int(color_1[0] * weight_1 + color_2[0] * weight_2),
127+
int(color_1[1] * weight_1 + color_2[1] * weight_2),
128+
int(color_1[2] * weight_1 + color_2[2] * weight_2))
129+
130+
# List of swing wav files without the .wav in the name for use with play_wav()
131+
swing_sounds = [
132+
'swing1',
133+
'swing2',
134+
'swing3',
135+
'swing4',
136+
]
137+
138+
# List of hit wav files without the .wav in the name for use with play_wav()
139+
hit_sounds = [
140+
'hit1',
141+
'hit2',
142+
'hit3',
143+
'hit4',
144+
]
145+
146+
147+
mode = 0 # Initial mode = OFF
148+
149+
# Setup idle pulse
150+
idle_brightness = IDLE_PULSE_BRIGHTNESS_MIN # current brightness of idle pulse
151+
idle_increment = 0.01 # Initial idle pulse direction
152+
153+
# Main loop
154+
while True:
155+
156+
if mode == 0: # If currently off...
157+
enable.value = True
158+
power_on('on', POWER_ON_SOUND_DURATION) # Power up!
159+
play_wav('idle', loop=True) # Play idle sound now
160+
mode = 1 # Idle mode
161+
162+
# Setup for idle pulse
163+
idle_brightness = IDLE_PULSE_BRIGHTNESS_MIN
164+
idle_increment = 0.01
165+
strip.fill([int(c*idle_brightness) for c in COLOR])
166+
strip.show()
167+
168+
elif mode >= 1: # If not OFF mode...
169+
x, y, z = accel.acceleration # Read accelerometer
170+
accel_total = x * x + z * z
171+
# (Y axis isn't needed, due to the orientation that the Prop-Maker
172+
# Wing is mounted. Also, square root isn't needed, since we're
173+
# comparing thresholds...use squared values instead.)
174+
if accel_total > HIT_THRESHOLD: # Large acceleration = HIT
175+
TRIGGER_TIME = time.monotonic() # Save initial time of hit
176+
play_wav(random.choice(hit_sounds)) # Start playing 'hit' sound
177+
COLOR_ACTIVE = COLOR_HIT # Set color to fade from
178+
mode = 3 # HIT mode
179+
elif mode == 1 and accel_total > SWING_THRESHOLD: # Mild = SWING
180+
TRIGGER_TIME = time.monotonic() # Save initial time of swing
181+
play_wav(random.choice(swing_sounds)) # Randomly choose from available swing sounds
182+
# make a larson scanner animation_time
183+
strip_backup = strip[0:-1]
184+
for p in range(-1, len(strip)):
185+
for i in range (p-1, p+2): # shoot a 'ray' of 3 pixels
186+
if 0 <= i < len(strip):
187+
strip[i] = COLOR_SWING
188+
strip.show()
189+
time.sleep(SWING_BLAST_SPEED)
190+
if 0 <= (p-1) < len(strip):
191+
strip[p-1] = strip_backup[p-1] # restore previous color at the tail
192+
strip.show()
193+
while audio.playing:
194+
pass # wait till we're done
195+
mode = 2 # we'll go back to idle mode
196+
197+
elif mode == 1:
198+
# Idle pulse
199+
idle_brightness += idle_increment # Pulse up
200+
if idle_brightness > IDLE_PULSE_BRIGHTNESS_MAX or \
201+
idle_brightness < IDLE_PULSE_BRIGHTNESS_MIN: # Then...
202+
idle_increment *= -1 # Pulse direction flip
203+
strip.fill([int(c*idle_brightness) for c in COLOR_IDLE])
204+
strip.show()
205+
time.sleep(IDLE_PULSE_SPEED) # Idle pulse speed set above
206+
elif mode > 1: # If in SWING or HIT mode...
207+
if audio.playing: # And sound currently playing...
208+
blend = time.monotonic() - TRIGGER_TIME # Time since triggered
209+
if mode == 2: # If SWING,
210+
blend = abs(0.5 - blend) * 2.0 # ramp up, down
211+
strip.fill(mix(COLOR_ACTIVE, COLOR, blend)) # Fade from hit/swing to base color
212+
strip.show()
213+
else: # No sound now, but still SWING or HIT modes
214+
play_wav('idle', loop=True) # Resume idle sound
215+
mode = 1 # Return to idle mode

Halo_Energy_Sword/sounds/hit1.wav

57.5 KB
Binary file not shown.

Halo_Energy_Sword/sounds/hit2.wav

63.2 KB
Binary file not shown.

Halo_Energy_Sword/sounds/hit3.wav

34.5 KB
Binary file not shown.

Halo_Energy_Sword/sounds/hit4.wav

43.1 KB
Binary file not shown.

Halo_Energy_Sword/sounds/idle.wav

190 KB
Binary file not shown.

Halo_Energy_Sword/sounds/on.wav

84.7 KB
Binary file not shown.

Halo_Energy_Sword/sounds/swing1.wav

24.4 KB
Binary file not shown.

Halo_Energy_Sword/sounds/swing2.wav

20.1 KB
Binary file not shown.

Halo_Energy_Sword/sounds/swing3.wav

20.1 KB
Binary file not shown.

Halo_Energy_Sword/sounds/swing4.wav

17.3 KB
Binary file not shown.

PiCowbell_Camera_Demos/TFT_Viewer/code.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,12 @@
5858
height = display.height
5959

6060
#cam.test_pattern = OV7670_TEST_PATTERN_COLOR_BAR_FADE
61-
bitmap = displayio.Bitmap(cam.width, cam.height, 65535)
61+
try:
62+
bitmap = displayio.Bitmap(cam.width, cam.height, 65535)
63+
except MemoryError:
64+
print("Oops, 240x240 is a little too big, trying 240x176..")
65+
cam.size = adafruit_ov5640.OV5640_SIZE_QCIF
66+
bitmap = displayio.Bitmap(cam.width, cam.height, 65535)
6267
print(width, height, cam.width, cam.height)
6368
if bitmap is None:
6469
raise SystemExit("Could not allocate a bitmap")
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// SPDX-FileCopyrightText: 2024 ladyada for Adafruit Industries
2+
//
3+
// SPDX-License-Identifier: MIT
4+
5+
#define NEOPIXEL_PIN 10
6+
#define A0 11
7+
#define A1 14
8+
#define A2 15
9+
#define MOSI A2
10+
#define MISO 16
11+
#define SCK 17
12+
#define RX 30
13+
#define TX 31
14+
#define A3 32
15+
#define SCL 33
16+
#define SDA 34
17+
18+
int led = MISO;
19+
20+
void setup() {
21+
pinMode(led, OUTPUT);
22+
}
23+
24+
void loop() {
25+
digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
26+
delay(1000); // wait for a second
27+
digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
28+
delay(1000); // wait for a second
29+
}

0 commit comments

Comments
 (0)