Initial commit
This commit is contained in:
@@ -0,0 +1,278 @@
|
|||||||
|
# Baby Mobile Audio Board — Design Document
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Drop-in replacement board for a baby crib mobile. Plays custom audio from
|
||||||
|
SPI flash memory, drives a DC motor, handles 8 button inputs, and runs
|
||||||
|
for days on two AA batteries.
|
||||||
|
|
||||||
|
**Key design decisions for long battery life:**
|
||||||
|
- SPI flash instead of microSD (4mA vs 30–100mA read current)
|
||||||
|
- Class-D amplifier at 90% efficiency (vs ~50% for class AB)
|
||||||
|
- ATmega328P internal 8MHz oscillator (no crystal, lower BOM)
|
||||||
|
- Logic-level MOSFET motor driver (no gate driver IC needed)
|
||||||
|
- Aggressive sleep with pin-change interrupt wake
|
||||||
|
|
||||||
|
|
||||||
|
## Schematic Netlist (Logical Connections)
|
||||||
|
|
||||||
|
### Power
|
||||||
|
```
|
||||||
|
2xAA Battery → SW9(PWR) → VCC rail
|
||||||
|
VCC → C1(100µF) → GND bulk decoupling
|
||||||
|
VCC → C2(100nF) → GND MCU VCC decoupling
|
||||||
|
VCC → C3(100nF) → GND MCU AVCC decoupling
|
||||||
|
VCC → C5(100nF) → GND Flash decoupling
|
||||||
|
VCC → C8(10µF) → GND Amp supply bypass
|
||||||
|
```
|
||||||
|
|
||||||
|
### MCU: U1 — ATmega328P-AU (TQFP-32)
|
||||||
|
|
||||||
|
| MCU Pin | Port | Function | Connected To |
|
||||||
|
|---------|----------|---------------|---------------------------|
|
||||||
|
| 30 | PD0/RXD | Serial RX | J5 pin 3 (SERIAL header) |
|
||||||
|
| 31 | PD1/TXD | Serial TX | J5 pin 2 (SERIAL header) |
|
||||||
|
| 32 | PD2/INT0 | Button 3 | SW3 → GND (active LOW) |
|
||||||
|
| 1 | PD3/INT1 | Button 4 | SW4 → GND (active LOW) |
|
||||||
|
| 2 | PD4 | Button 5 | SW5 → GND (active LOW) |
|
||||||
|
| 9 | PD5/OC0B | Motor PWM | R4(100Ω) → Q1 gate |
|
||||||
|
| 10 | PD6/OC0A | Button 6 | SW6 → GND (active LOW) |
|
||||||
|
| 11 | PD7 | Button 7 | SW7 → GND (active LOW) |
|
||||||
|
| 12 | PB0 | Button 8 | SW8 → GND (active LOW) |
|
||||||
|
| 13 | PB1/OC1A | Audio PWM | R2(4.7K) → C7(10nF) → U3 |
|
||||||
|
| 14 | PB2/SS | Flash ~CS | U2 pin 1 |
|
||||||
|
| 15 | PB3/MOSI | SPI MOSI | U2 pin 5, J4 MOSI |
|
||||||
|
| 16 | PB4/MISO | SPI MISO | U2 pin 2, J4 MISO |
|
||||||
|
| 17 | PB5/SCK | SPI SCK | U2 pin 6, J4 SCK |
|
||||||
|
| 23 | PC0/ADC0 | Button 1 | SW1 → GND (active LOW) |
|
||||||
|
| 24 | PC1/ADC1 | Button 2 | SW2 → GND (active LOW) |
|
||||||
|
| 25 | PC2/ADC2 | Amp ~SD | U3 pin 1 + R3(100K)→GND |
|
||||||
|
| 26 | PC3/ADC3 | Status LED | R6(1K) → D2(LED) → GND |
|
||||||
|
| 27 | PC4/SDA | (spare/I2C) | — |
|
||||||
|
| 28 | PC5/SCL | (spare/I2C) | — |
|
||||||
|
| 29 | PC6/~RST | Reset | R1(10K)→VCC, C4(100nF)→GND|
|
||||||
|
| 4 | VCC | Power | VCC rail |
|
||||||
|
| 6 | AVCC | Analog power | VCC rail (via ferrite opt) |
|
||||||
|
| 21 | AREF | Reference | C3(100nF) → GND |
|
||||||
|
| 3, 5 | GND | Ground | GND rail |
|
||||||
|
| 7 | XTAL1 | (unused) | leave floating |
|
||||||
|
| 8 | XTAL2 | (unused) | leave floating |
|
||||||
|
|
||||||
|
|
||||||
|
### SPI Flash: U2 — W25Q128JVSIQ (SOIC-8)
|
||||||
|
|
||||||
|
| Pin | Name | Connected To |
|
||||||
|
|-----|-----------|-----------------|
|
||||||
|
| 1 | ~CS | PB2 (FLASH_CS) |
|
||||||
|
| 2 | DO (MISO) | PB4 (SPI_MISO) |
|
||||||
|
| 3 | ~WP | VCC (tie high) |
|
||||||
|
| 4 | GND | GND |
|
||||||
|
| 5 | DI (MOSI) | PB3 (SPI_MOSI) |
|
||||||
|
| 6 | CLK | PB5 (SPI_SCK) |
|
||||||
|
| 7 | ~HOLD | VCC (tie high) |
|
||||||
|
| 8 | VCC | VCC |
|
||||||
|
|
||||||
|
|
||||||
|
### Audio Amplifier: U3 — PAM8302AASCR (SOIC-8)
|
||||||
|
|
||||||
|
| Pin | Name | Connected To |
|
||||||
|
|-----|------|-------------------------------------------|
|
||||||
|
| 1 | ~SD | PC2 (AMP_SD) + R3(100K) pulldown to GND |
|
||||||
|
| 2 | VDD | VCC + C8(10µF) bypass |
|
||||||
|
| 3 | GND | GND |
|
||||||
|
| 4 | A+ | Audio signal from RC filter |
|
||||||
|
| 5 | A- | GND (single-ended input) |
|
||||||
|
| 6 | PAD | GND (thermal pad) |
|
||||||
|
| 7 | VO- | Speaker - |
|
||||||
|
| 8 | VO+ | Speaker + |
|
||||||
|
|
||||||
|
**Audio signal path:**
|
||||||
|
```
|
||||||
|
PB1 (OC1A PWM) → R2 (4.7KΩ) → node → C6 (1µF coupling) → U3 A+ (pin 4)
|
||||||
|
|
|
||||||
|
C7 (10nF) → GND
|
||||||
|
|
||||||
|
RC low-pass filter: fc = 1/(2π × 4700 × 10e-9) ≈ 3.4 kHz
|
||||||
|
This removes the PWM carrier while passing audio baseband.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Shutdown control:**
|
||||||
|
- R3 (100K) pulls ~SD LOW by default = amplifier OFF
|
||||||
|
- MCU drives PC2 HIGH to enable amplifier
|
||||||
|
- Saves ~2mA quiescent current when not playing
|
||||||
|
|
||||||
|
|
||||||
|
### Motor Driver
|
||||||
|
|
||||||
|
```
|
||||||
|
PD5 (OC0B) → R4 (100Ω gate resistor) → Q1 Gate
|
||||||
|
|
|
||||||
|
R5 (100K) → GND (pulldown, ensures OFF at boot)
|
||||||
|
|
||||||
|
Q1: AO3400A N-ch MOSFET (SOT-23)
|
||||||
|
Drain → Motor terminal 1
|
||||||
|
Source → GND
|
||||||
|
(Motor terminal 2 → VCC)
|
||||||
|
|
||||||
|
D1: SS14 Schottky flyback diode across motor (Cathode → VCC, Anode → Drain)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Motor specs:**
|
||||||
|
- PWM on Timer0 (OC0B) for variable speed
|
||||||
|
- AO3400A: Vgs(th) = 0.65V typ, fully enhanced at 1.8V → works at depleted AA voltage
|
||||||
|
- R4 limits gate ringing; R5 ensures MOSFET OFF during MCU reset/programming
|
||||||
|
|
||||||
|
|
||||||
|
### Button Matrix
|
||||||
|
|
||||||
|
All 8 buttons connect between their MCU pin and GND (active LOW).
|
||||||
|
MCU internal pull-ups enabled (~30–50KΩ). No external pull-up resistors needed.
|
||||||
|
|
||||||
|
Buttons are on PCINT-capable pins for wake-from-sleep:
|
||||||
|
- SW1 (PC0) → PCINT8
|
||||||
|
- SW2 (PC1) → PCINT9
|
||||||
|
- SW3 (PD2) → INT0 (hardware interrupt)
|
||||||
|
- SW4 (PD3) → INT1 (hardware interrupt)
|
||||||
|
- SW5 (PD4) → PCINT20
|
||||||
|
- SW6 (PD6) → PCINT22
|
||||||
|
- SW7 (PD7) → PCINT23
|
||||||
|
- SW8 (PB0) → PCINT0
|
||||||
|
|
||||||
|
|
||||||
|
### Headers
|
||||||
|
|
||||||
|
**J4 — ISP (2×3, standard Atmel AVR ISP pinout):**
|
||||||
|
```
|
||||||
|
MISO 1 ● 2 VCC
|
||||||
|
SCK 3 4 MOSI
|
||||||
|
~RST 5 6 GND
|
||||||
|
```
|
||||||
|
|
||||||
|
**J5 — Serial (1×3, for bootloader programming / debug):**
|
||||||
|
```
|
||||||
|
GND 1
|
||||||
|
TXD 2 (MCU TX out)
|
||||||
|
RXD 3 (MCU RX in)
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Bill of Materials
|
||||||
|
|
||||||
|
| Ref | Value/Part | Package | Qty | ~Cost | Notes |
|
||||||
|
|------|------------------|-------------------|-----|--------|-------------------------------|
|
||||||
|
| U1 | ATmega328P-AU | TQFP-32 | 1 | $2.50 | Pre-burn Arduino bootloader |
|
||||||
|
| U2 | W25Q128JVSIQ | SOIC-8 | 1 | $1.20 | 16MB, 33min @ 8kHz/8bit |
|
||||||
|
| U3 | PAM8302AASCR | SOIC-8 | 1 | $0.80 | 2.5W class-D, Vmin=2.0V |
|
||||||
|
| Q1 | AO3400A | SOT-23 | 1 | $0.15 | Logic-level N-ch MOSFET |
|
||||||
|
| D1 | SS14 | SMA | 1 | $0.10 | Motor flyback protection |
|
||||||
|
| D2 | LED (green) | 0805 | 1 | $0.05 | Status indicator |
|
||||||
|
| R1 | 10KΩ | 0805 | 1 | $0.01 | Reset pull-up |
|
||||||
|
| R2 | 4.7KΩ | 0805 | 1 | $0.01 | Audio LPF resistor |
|
||||||
|
| R3 | 100KΩ | 0805 | 1 | $0.01 | Amp shutdown pull-down |
|
||||||
|
| R4 | 100Ω | 0805 | 1 | $0.01 | MOSFET gate resistor |
|
||||||
|
| R5 | 100KΩ | 0805 | 1 | $0.01 | MOSFET gate pull-down |
|
||||||
|
| R6 | 1KΩ | 0805 | 1 | $0.01 | LED current limit |
|
||||||
|
| C1 | 100µF/10V | Radial 5mm | 1 | $0.15 | Bulk power decoupling |
|
||||||
|
| C2 | 100nF | 0805 | 1 | $0.01 | MCU VCC bypass |
|
||||||
|
| C3 | 100nF | 0805 | 1 | $0.01 | MCU AVCC/AREF bypass |
|
||||||
|
| C4 | 100nF | 0805 | 1 | $0.01 | Reset noise filter |
|
||||||
|
| C5 | 100nF | 0805 | 1 | $0.01 | Flash bypass |
|
||||||
|
| C6 | 1µF | 0805 | 1 | $0.02 | Audio AC coupling |
|
||||||
|
| C7 | 10nF | 0805 | 1 | $0.01 | Audio LPF capacitor |
|
||||||
|
| C8 | 10µF | 0805 | 1 | $0.05 | Amp supply bypass |
|
||||||
|
| SW1-8| Tactile switch | 6mm SMD | 8 | $0.80 | Or reuse existing buttons |
|
||||||
|
| SW9 | SPDT slide | THT | 1 | $0.20 | Power switch |
|
||||||
|
| J1 | JST-PH 2-pin | THT | 1 | $0.15 | Battery connector |
|
||||||
|
| J2 | JST-PH 2-pin | THT | 1 | $0.15 | Speaker connector |
|
||||||
|
| J3 | JST-PH 2-pin | THT | 1 | $0.15 | Motor connector |
|
||||||
|
| J4 | 2×3 pin header | 2.54mm | 1 | $0.10 | ISP programming |
|
||||||
|
| J5 | 1×3 pin header | 2.54mm | 1 | $0.05 | Serial debug |
|
||||||
|
| — | AA battery holder| 2×AA | 1 | $0.50 | Reuse existing |
|
||||||
|
| | | | | | |
|
||||||
|
| | **TOTAL** | | |**~$7** | |
|
||||||
|
|
||||||
|
|
||||||
|
## Power Analysis
|
||||||
|
|
||||||
|
### Current draw by state:
|
||||||
|
|
||||||
|
| State | MCU | Flash | Amp | Motor | Total |
|
||||||
|
|--------------------|--------|--------|--------|--------|---------|
|
||||||
|
| Playing + spinning | 4 mA | 4 mA | 3 mA | 80 mA | ~91 mA |
|
||||||
|
| Playing only | 4 mA | 4 mA | 3 mA | 0 | ~11 mA |
|
||||||
|
| Idle (awake) | 4 mA | 0.001 | 0.001 | 0 | ~4 mA |
|
||||||
|
| Deep sleep | 0.0001 | 0.001 | 0.001 | 0 | <0.01mA |
|
||||||
|
|
||||||
|
### Estimated runtime on 2× AA Alkaline (2500 mAh):
|
||||||
|
|
||||||
|
| Mode | Current | Runtime |
|
||||||
|
|--------------------|---------|-------------|
|
||||||
|
| Audio + Motor | 91 mA | ~27 hours |
|
||||||
|
| Audio only | 11 mA | ~227 hours |
|
||||||
|
| Sleep | <10 µA | ~28 years |
|
||||||
|
|
||||||
|
With typical use of 30 min/day (motor + audio), batteries last roughly **54 days**.
|
||||||
|
With 1 hour/day, roughly **27 days** — well within AA change interval for a toy.
|
||||||
|
|
||||||
|
|
||||||
|
## PCB Layout Guidelines
|
||||||
|
|
||||||
|
**Board size target:** 40mm × 30mm (fits inside most mobile housings)
|
||||||
|
|
||||||
|
**Layer stackup:** 2-layer (plenty for this design)
|
||||||
|
|
||||||
|
**Key layout rules:**
|
||||||
|
1. Place C2 and C3 as close to U1 pins 4/6 as physically possible
|
||||||
|
2. Place C5 directly adjacent to U2 pin 8
|
||||||
|
3. Keep SPI traces short and parallel-routed
|
||||||
|
4. Audio RC filter (R2, C7) close to U3 input
|
||||||
|
5. Wide traces for motor path (VCC → motor → Q1 drain): 0.5mm minimum
|
||||||
|
6. Ground pour on bottom layer
|
||||||
|
7. Thermal relief on U3 pad (pin 6) connected to ground pour
|
||||||
|
8. Keep battery/motor power traces away from audio section
|
||||||
|
|
||||||
|
**Recommended trace widths:**
|
||||||
|
- Power (VCC, GND, motor): 0.5mm+
|
||||||
|
- Signal (SPI, buttons): 0.25mm
|
||||||
|
- Audio: 0.25mm (keep short, away from digital noise)
|
||||||
|
|
||||||
|
|
||||||
|
## Programming
|
||||||
|
|
||||||
|
### Bootloader
|
||||||
|
Burn the Arduino bootloader for "ATmega328P 8MHz internal" using the ISP
|
||||||
|
header (J4) and an Arduino-as-ISP or USBasp programmer.
|
||||||
|
|
||||||
|
In Arduino IDE:
|
||||||
|
- Board: "ATmega328P"
|
||||||
|
- Clock: "Internal 8 MHz"
|
||||||
|
- BOD: "BOD 1.8V" (for low-voltage operation)
|
||||||
|
|
||||||
|
### Loading audio onto W25Q128
|
||||||
|
Use the serial header (J5) with a USB-serial adapter. The firmware
|
||||||
|
includes a serial protocol to receive audio data and write it to flash.
|
||||||
|
Alternatively, program the flash chip directly with a CH341A SPI
|
||||||
|
programmer before soldering (~$3 on Amazon).
|
||||||
|
|
||||||
|
### Audio format
|
||||||
|
Raw unsigned 8-bit PCM, 8000 Hz sample rate, mono.
|
||||||
|
Convert with ffmpeg:
|
||||||
|
```
|
||||||
|
ffmpeg -i input.mp3 -ar 8000 -ac 1 -f u8 -acodec pcm_u8 output.raw
|
||||||
|
```
|
||||||
|
|
||||||
|
At 8KB/s, the 16MB flash holds about **34 minutes** of audio.
|
||||||
|
|
||||||
|
|
||||||
|
## Possible Enhancements
|
||||||
|
|
||||||
|
- **Volume control:** Use a digital pot on amp input, or just use
|
||||||
|
the PWM duty cycle adjustment in software
|
||||||
|
- **Battery voltage monitor:** Read VCC via bandgap reference trick
|
||||||
|
on ATmega328P (no extra pin needed) — blink LED when low
|
||||||
|
- **Touch sensing:** Replace buttons with copper pads; use ADC-based
|
||||||
|
capacitive sensing on PC0/PC1 (ATmega328P supports this with
|
||||||
|
careful firmware)
|
||||||
|
- **More audio:** Swap W25Q128 (16MB) for W25Q256 (32MB) → 68 min
|
||||||
|
- **Bluetooth:** Add HC-05 module on serial pins for wireless audio
|
||||||
|
upload from phone (adds ~30mA when active)
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"meta": {
|
||||||
|
"filename": "baby-mobile.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"board": {
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"board_outline_line_width": 0.1,
|
||||||
|
"copper_line_width": 0.2,
|
||||||
|
"copper_text_size_h": 1.5,
|
||||||
|
"copper_text_size_v": 1.5,
|
||||||
|
"other_line_width": 0.15
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"min_copper_edge_clearance": 0.3,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_track_width": 0.2,
|
||||||
|
"min_via_annular_width": 0.13,
|
||||||
|
"min_via_diameter": 0.6,
|
||||||
|
"solder_mask_to_copper_clearance": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer_presets": []
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.3,
|
||||||
|
"via_diameter": 0.6,
|
||||||
|
"via_drill": 0.3,
|
||||||
|
"wire_width": 6
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": []
|
||||||
|
},
|
||||||
|
"sheets": [
|
||||||
|
[
|
||||||
|
"",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,628 @@
|
|||||||
|
(kicad_sch (version 20230121) (generator "custom_generator")
|
||||||
|
|
||||||
|
(uuid "391da8c7-7217-4ed9-a918-95efab6bbe33")
|
||||||
|
(paper "A3")
|
||||||
|
|
||||||
|
(title_block
|
||||||
|
(title "Baby Mobile Audio Board")
|
||||||
|
(date "2026-03-08")
|
||||||
|
(rev "1.0")
|
||||||
|
(comment 1 "ATmega328P + W25Q128 + PAM8302A")
|
||||||
|
(comment 2 "2xAA Battery Powered - Long Runtime Design")
|
||||||
|
(comment 3 "8-ohm 0.25W Speaker, DC Motor, 8 Buttons")
|
||||||
|
(comment 4 "Arduino Compatible (8MHz Internal Osc)")
|
||||||
|
)
|
||||||
|
|
||||||
|
(lib_symbols
|
||||||
|
|
||||||
|
(symbol "baby_mobile:ATmega328P-AU" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "U" (at 0 26 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "ATmega328P-AU" (at 0 24 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_QFP:TQFP-32_7x7mm_P0.8mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:ATmega328P-AU_0_1"
|
||||||
|
(rectangle (start -17 23) (end 17 -23) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:ATmega328P-AU_1_1"
|
||||||
|
(pin power_in line (at -7 -26 90) (length 3) (name "GND" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -5 -26 90) (length 3) (name "GND2" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -3 26 270) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -1 26 270) (length 3) (name "AVCC" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 1 26 270) (length 3) (name "AREF" (effects (font (size 1 1)))) (number "21" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 15 0) (length 3) (name "PD0/RXD" (effects (font (size 1 1)))) (number "30" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 12.5 0) (length 3) (name "PD1/TXD" (effects (font (size 1 1)))) (number "31" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 10 0) (length 3) (name "PD2/INT0" (effects (font (size 1 1)))) (number "32" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 7.5 0) (length 3) (name "PD3/INT1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 5 0) (length 3) (name "PD4" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 2.5 0) (length 3) (name "PD5/OC0B" (effects (font (size 1 1)))) (number "9" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 0 0) (length 3) (name "PD6/OC0A" (effects (font (size 1 1)))) (number "10" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 -2.5 0) (length 3) (name "PD7" (effects (font (size 1 1)))) (number "11" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 15 180) (length 3) (name "PB0" (effects (font (size 1 1)))) (number "12" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 12.5 180) (length 3) (name "PB1/OC1A" (effects (font (size 1 1)))) (number "13" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 10 180) (length 3) (name "PB2/SS" (effects (font (size 1 1)))) (number "14" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 7.5 180) (length 3) (name "PB3/MOSI" (effects (font (size 1 1)))) (number "15" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 5 180) (length 3) (name "PB4/MISO" (effects (font (size 1 1)))) (number "16" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 2.5 180) (length 3) (name "PB5/SCK" (effects (font (size 1 1)))) (number "17" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -2.5 180) (length 3) (name "PC0/ADC0" (effects (font (size 1 1)))) (number "23" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -5 180) (length 3) (name "PC1/ADC1" (effects (font (size 1 1)))) (number "24" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -7.5 180) (length 3) (name "PC2/ADC2" (effects (font (size 1 1)))) (number "25" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -10 180) (length 3) (name "PC3/ADC3" (effects (font (size 1 1)))) (number "26" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -12.5 180) (length 3) (name "PC4/SDA" (effects (font (size 1 1)))) (number "27" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -15 180) (length 3) (name "PC5/SCL" (effects (font (size 1 1)))) (number "28" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -20 -10 0) (length 3) (name "~{RESET}" (effects (font (size 1 1)))) (number "29" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -20 -15 0) (length 3) (name "XTAL1" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at -20 -17.5 0) (length 3) (name "XTAL2" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:W25Q128" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "U" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "W25Q128JVSIQ" (at 0 7 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:W25Q128_0_1"
|
||||||
|
(rectangle (start -7 6) (end 7 -6) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:W25Q128_1_1"
|
||||||
|
(pin input line (at -10 4 0) (length 3) (name "~{CS}" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at -10 1.5 0) (length 3) (name "DO/IO1" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -10 -1.5 0) (length 3) (name "~{WP}/IO2" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -10 -4 0) (length 3) (name "GND" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at 10 -4 180) (length 3) (name "DI/IO0" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at 10 -1.5 180) (length 3) (name "CLK" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at 10 1.5 180) (length 3) (name "~{HOLD}/IO3" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at 10 4 180) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:PAM8302A" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "U" (at 0 11 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "PAM8302A" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:PAM8302A_0_1"
|
||||||
|
(rectangle (start -8 8) (end 8 -8) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:PAM8302A_1_1"
|
||||||
|
(pin input line (at -11 5 0) (length 3) (name "~{SD}" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -11 2 0) (length 3) (name "VDD" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -11 -1 0) (length 3) (name "GND" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -11 -4 0) (length 3) (name "A+" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -11 -7 0) (length 3) (name "A-" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at 11 2 180) (length 3) (name "VO+" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at 11 -1 180) (length 3) (name "VO-" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at 11 -4 180) (length 3) (name "PAD" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:NMOS" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "Q" (at 3 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "AO3400A" (at 5 -2.5 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_TO_SOT_SMD:SOT-23" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:NMOS_0_1"
|
||||||
|
(polyline (pts (xy -0.5 0.5) (xy -0.5 -0.5)) (stroke (width 0.33) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -0.5 -2) (xy -0.5 2)) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy 0 -2.5) (xy 0 -1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy 0 1.5) (xy 0 2.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy 0 0) (xy -1.5 0)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:NMOS_1_1"
|
||||||
|
(pin passive line (at 0 5 270) (length 2.5) (name "D" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -4 0 0) (length 2.5) (name "G" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -5 90) (length 2.5) (name "S" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Capacitor" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "C" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "C" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Capacitor_0_1"
|
||||||
|
(polyline (pts (xy -1.5 1) (xy 1.5 1)) (stroke (width 0.4) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.4) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Capacitor_1_1"
|
||||||
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Resistor" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "R" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "R" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Resistor_0_1"
|
||||||
|
(rectangle (start -1 2.5) (end 1 -2.5) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Resistor_1_1"
|
||||||
|
(pin passive line (at 0 5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Diode_Schottky" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "D" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "SS14" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Diode_SMD:D_SMA" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Diode_Schottky_0_1"
|
||||||
|
(polyline (pts (xy -1.5 1) (xy 0 -1) (xy 1.5 1) (xy -1.5 1)) (stroke (width 0.2) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.3) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Diode_Schottky_1_1"
|
||||||
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "A" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "K" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Inductor" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "L" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "L" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Inductor_0_1"
|
||||||
|
(arc (start 0 2.5) (mid 0.75 1.875) (end 0 1.25) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(arc (start 0 1.25) (mid 0.75 0.625) (end 0 0) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(arc (start 0 0) (mid 0.75 -0.625) (end 0 -1.25) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(arc (start 0 -1.25) (mid 0.75 -1.875) (end 0 -2.5) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Inductor_1_1"
|
||||||
|
(pin passive line (at 0 5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Switch" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "SW" (at 0 3 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "SW" (at 0 -3 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Switch_0_1"
|
||||||
|
(circle (center -2 0) (radius 0.4) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(circle (center 2 0) (radius 0.4) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.6 0) (xy 1.6 1)) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Switch_1_1"
|
||||||
|
(pin passive line (at -5 0 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 5 0 180) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Conn_2Pin" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "J" (at 0 4 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "Conn_2" (at 0 -4 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Conn_2Pin_0_1"
|
||||||
|
(rectangle (start -2 3) (end 2 -3) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Conn_2Pin_1_1"
|
||||||
|
(pin passive line (at -5 1.5 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -5 -1.5 0) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Conn_3Pin" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "J" (at 0 5.5 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "Conn_3" (at 0 -5.5 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Conn_3Pin_0_1"
|
||||||
|
(rectangle (start -2 4) (end 2 -4) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Conn_3Pin_1_1"
|
||||||
|
(pin passive line (at -5 2.5 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -5 0 0) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -5 -2.5 0) (length 3) (name "3" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:Conn_6Pin" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "J" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "ISP_2x3" (at 0 -9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Conn_6Pin_0_1"
|
||||||
|
(rectangle (start -3 8) (end 3 -8) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Conn_6Pin_1_1"
|
||||||
|
(pin passive line (at -6 5 0) (length 3) (name "MISO" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 6 5 180) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -6 0 0) (length 3) (name "SCK" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 6 0 180) (length 3) (name "MOSI" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -6 -5 0) (length 3) (name "~{RST}" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 6 -5 180) (length 3) (name "GND" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:LED" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "D" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "LED" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:LED_0_1"
|
||||||
|
(polyline (pts (xy -1.5 1) (xy 0 -1) (xy 1.5 1) (xy -1.5 1)) (stroke (width 0.2) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.3) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:LED_1_1"
|
||||||
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "A" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "K" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
(symbol "baby_mobile:PWR_FLAG" (power) (in_bom no) (on_board no)
|
||||||
|
(property "Reference" "#FLG" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Value" "PWR_FLAG" (at 0 3 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:PWR_FLAG_0_1"
|
||||||
|
(polyline (pts (xy 0 0) (xy 0 1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1 1.5) (xy 0 3) (xy 1 1.5) (xy -1 1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:PWR_FLAG_1_1"
|
||||||
|
(pin power_out line (at 0 0 90) (length 0) (name "pwr" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Conn_2Pin") (at 25 35 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "507bdf9f-e516-4e7b-8916-4c751f1b84e2")
|
||||||
|
(property "Reference" "J1" (at 25 32 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BATTERY" (at 25 38 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal" (at 25 35 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 25 35 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 55 35 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "c40c113d-1405-44ce-a1f0-58bef96d538e")
|
||||||
|
(property "Reference" "C1" (at 55 32 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100uF" (at 55 38 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_THT:CP_Radial_D5.0mm_P2.00mm" (at 55 35 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 55 35 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 100 30 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "399c833b-8964-48dd-b796-3cb9e41ff4d0")
|
||||||
|
(property "Reference" "C2" (at 100 27 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100nF" (at 100 33 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric" (at 100 30 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 100 30 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 115 30 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "da1e40d4-4aae-4393-8ac3-273b705cd8d2")
|
||||||
|
(property "Reference" "C3" (at 115 27 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100nF" (at 115 33 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric" (at 115 30 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 115 30 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 40 25 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "d5f6e2c8-1f5a-4b82-abbb-cb3f97490465")
|
||||||
|
(property "Reference" "SW9" (at 40 22 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "PWR" (at 40 28 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_THT:SW_SPDT_CK-JS102011SAQN" (at 40 25 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 40 25 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:ATmega328P-AU") (at 130 90 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "45044e9c-b35e-4aac-8523-60d85a6a6df8")
|
||||||
|
(property "Reference" "U1" (at 130 87 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "ATmega328P-AU" (at 130 93 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_QFP:TQFP-32_7x7mm_P0.8mm" (at 130 90 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 130 90 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Resistor") (at 95 55 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "94af8e3c-b3da-4777-8e91-865edfc76cdf")
|
||||||
|
(property "Reference" "R1" (at 95 52 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "10K" (at 95 58 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric" (at 95 55 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 95 55 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 95 65 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "65aa9490-ed2d-43cc-bec1-e1f276413ef2")
|
||||||
|
(property "Reference" "C4" (at 95 62 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100nF" (at 95 68 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric" (at 95 65 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 95 65 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:W25Q128") (at 230 60 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "b5dc96e3-fbe8-4c5b-b1a7-82f3926f520f")
|
||||||
|
(property "Reference" "U2" (at 230 57 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "W25Q128JVSIQ" (at 230 63 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 230 60 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 230 60 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 255 50 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "63c2829e-7fd6-485b-82f8-94ec57fe959b")
|
||||||
|
(property "Reference" "C5" (at 255 47 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100nF" (at 255 53 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric" (at 255 50 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 255 50 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:PAM8302A") (at 230 140 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "dc5d606b-6f45-42d0-82bb-b0db3a981adf")
|
||||||
|
(property "Reference" "U3" (at 230 137 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "PAM8302A" (at 230 143 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 230 140 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 230 140 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 200 135 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "85967935-a5f6-4065-9ae7-b181b28d0674")
|
||||||
|
(property "Reference" "C6" (at 200 132 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "1uF" (at 200 138 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric" (at 200 135 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 200 135 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Resistor") (at 185 135 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "2d985162-8660-47cc-9982-688a70e5af66")
|
||||||
|
(property "Reference" "R2" (at 185 132 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "4.7K" (at 185 138 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric" (at 185 135 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 185 135 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 192 145 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "136fb80a-2afa-44da-887f-5760ca0c20ee")
|
||||||
|
(property "Reference" "C7" (at 192 142 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "10nF" (at 192 148 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric" (at 192 145 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 192 145 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Capacitor") (at 255 130 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "47509d19-833e-498c-8131-5ad8bc4f9b89")
|
||||||
|
(property "Reference" "C8" (at 255 127 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "10uF" (at 255 133 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Capacitor_SMD:C_0805_2012Metric" (at 255 130 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 255 130 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Conn_2Pin") (at 265 145 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "d84e0dcb-8d75-4de2-b76d-db6013404837")
|
||||||
|
(property "Reference" "J2" (at 265 142 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "SPEAKER" (at 265 148 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal" (at 265 145 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 265 145 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Resistor") (at 210 150 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "c73fafc0-ebff-46a7-b8a6-93719e4ba183")
|
||||||
|
(property "Reference" "R3" (at 210 147 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100K" (at 210 153 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric" (at 210 150 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 210 150 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:NMOS") (at 140 190 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "f44467d7-d2d3-4056-b74e-d8e247ada0c0")
|
||||||
|
(property "Reference" "Q1" (at 140 187 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "AO3400A" (at 140 193 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_TO_SOT_SMD:SOT-23" (at 140 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 140 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Resistor") (at 120 190 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "d2efdc5b-60e1-40ac-b81e-b671ae9e2524")
|
||||||
|
(property "Reference" "R4" (at 120 187 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100R" (at 120 193 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric" (at 120 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 120 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Resistor") (at 130 200 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "fa36bf14-db5f-4c2d-aa38-322990e1a079")
|
||||||
|
(property "Reference" "R5" (at 130 197 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "100K" (at 130 203 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric" (at 130 200 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 130 200 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Diode_Schottky") (at 155 180 90) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "a86dfdae-f4a0-4d77-9501-410a463b4929")
|
||||||
|
(property "Reference" "D1" (at 155 177 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "SS14" (at 155 183 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Diode_SMD:D_SMA" (at 155 180 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 155 180 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Conn_2Pin") (at 160 170 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "e215997e-3139-4cb2-903e-f84cabd0b1af")
|
||||||
|
(property "Reference" "J3" (at 160 167 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "MOTOR" (at 160 173 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal" (at 160 170 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 160 170 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 75 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "7f01bcc9-33e2-4fec-9df9-ee78a82cb270")
|
||||||
|
(property "Reference" "SW1" (at 30 72 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN1" (at 30 78 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 75 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 75 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 90 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "bfa6ab0a-df05-4515-8d1f-72749aba4a20")
|
||||||
|
(property "Reference" "SW2" (at 30 87 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN2" (at 30 93 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 90 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 90 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 105 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "1b1fc388-ea85-4a5c-bee5-7e769d4b59eb")
|
||||||
|
(property "Reference" "SW3" (at 30 102 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN3" (at 30 108 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 105 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 105 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 120 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "bc5829d7-ff9c-4c0a-834e-e85b6795fb22")
|
||||||
|
(property "Reference" "SW4" (at 30 117 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN4" (at 30 123 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 120 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 120 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 135 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "182c3254-622e-4fb9-a960-ce401433f071")
|
||||||
|
(property "Reference" "SW5" (at 30 132 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN5" (at 30 138 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 135 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 135 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 150 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "86d0f6ec-c847-470d-9bbd-f4bed67fc489")
|
||||||
|
(property "Reference" "SW6" (at 30 147 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN6" (at 30 153 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 150 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 150 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 165 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "cf404039-6a3b-4246-816c-1be4597bebb0")
|
||||||
|
(property "Reference" "SW7" (at 30 162 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN7" (at 30 168 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 165 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 165 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Switch") (at 30 180 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "80093bcc-1f31-4639-8591-9f1cfa8e1721")
|
||||||
|
(property "Reference" "SW8" (at 30 177 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "BTN8" (at 30 183 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Button_Switch_SMD:SW_SPST_TL3342" (at 30 180 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 180 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:LED") (at 85 190 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "e0fae357-d301-48e8-a964-a410bbb95bc6")
|
||||||
|
(property "Reference" "D2" (at 85 187 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "LED" (at 85 193 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "LED_SMD:LED_0805_2012Metric" (at 85 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 85 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Resistor") (at 75 190 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "898d416a-1773-4205-a6ee-11a04534c363")
|
||||||
|
(property "Reference" "R6" (at 75 187 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "1K" (at 75 193 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Resistor_SMD:R_0805_2012Metric" (at 75 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 75 190 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Conn_6Pin") (at 250 200 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "049eaee8-ace8-4be4-8664-1f02e3371a2e")
|
||||||
|
(property "Reference" "J4" (at 250 197 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "ISP" (at 250 203 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Connector_PinHeader_2.54mm:PinHeader_2x03_P2.54mm_Vertical" (at 250 200 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 250 200 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(symbol (lib_id "baby_mobile:Conn_3Pin") (at 30 210 0) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "6e205180-7724-405f-af1d-daa148abacc5")
|
||||||
|
(property "Reference" "J5" (at 30 207 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "SERIAL" (at 30 213 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical" (at 30 210 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 30 210 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)
|
||||||
|
(label "VCC" (at 55 25 0) (effects (font (size 1.27 1.27))) (uuid "38d66dc5-0dfe-483d-b51e-2d579b758f33"))
|
||||||
|
(label "VCC" (at 100 25 0) (effects (font (size 1.27 1.27))) (uuid "56a7d1c9-361a-42f8-9d77-7cc94df15408"))
|
||||||
|
(label "VCC" (at 115 25 0) (effects (font (size 1.27 1.27))) (uuid "78fe02e6-db3b-4885-8a22-d0d962a13bd1"))
|
||||||
|
(label "VCC" (at 130 50 0) (effects (font (size 1.27 1.27))) (uuid "8dcc821a-8787-4ba3-aa6e-a13c6942949f"))
|
||||||
|
(label "VCC" (at 255 45 0) (effects (font (size 1.27 1.27))) (uuid "dc2b0694-b4c5-4e2f-a970-c86f81c186ed"))
|
||||||
|
(label "VCC" (at 255 125 0) (effects (font (size 1.27 1.27))) (uuid "1e7be094-6bef-468b-b0d8-960ef3ee34da"))
|
||||||
|
(label "VCC" (at 95 50 0) (effects (font (size 1.27 1.27))) (uuid "813d1f5e-21ee-46ad-90c9-d2746d49c93a"))
|
||||||
|
(label "VCC" (at 160 165 0) (effects (font (size 1.27 1.27))) (uuid "3cc3028b-6ef6-4394-b379-d6fddafb61c7"))
|
||||||
|
(label "GND" (at 55 45 0) (effects (font (size 1.27 1.27))) (uuid "e58d5e07-b8ad-408f-a3e2-23cba82e951c"))
|
||||||
|
(label "GND" (at 100 40 0) (effects (font (size 1.27 1.27))) (uuid "427f2a2e-c2c9-4e85-8dc5-6ac456496582"))
|
||||||
|
(label "GND" (at 115 40 0) (effects (font (size 1.27 1.27))) (uuid "c40ed645-0a77-432f-98e1-3022a591a6bf"))
|
||||||
|
(label "GND" (at 130 130 0) (effects (font (size 1.27 1.27))) (uuid "13423fca-5ee9-42db-97d7-8d291085433a"))
|
||||||
|
(label "GND" (at 255 70 0) (effects (font (size 1.27 1.27))) (uuid "f1680748-3b5e-4b5c-9231-f5b123334267"))
|
||||||
|
(label "GND" (at 255 155 0) (effects (font (size 1.27 1.27))) (uuid "3f2ad3e8-cab3-4661-8c6d-27a5c37248bd"))
|
||||||
|
(label "GND" (at 95 70 0) (effects (font (size 1.27 1.27))) (uuid "fdb07bc1-2a3f-4bfa-8e0d-44095ddb4eed"))
|
||||||
|
(label "GND" (at 140 205 0) (effects (font (size 1.27 1.27))) (uuid "a2e87db6-701b-4ee4-9680-ce3e641a1ce3"))
|
||||||
|
(label "GND" (at 192 155 0) (effects (font (size 1.27 1.27))) (uuid "2f5d05c3-2b85-442d-82e1-f9b8f73b99ae"))
|
||||||
|
(label "SPI_MOSI" (at 165 85 0) (effects (font (size 1.27 1.27))) (uuid "3c4184cd-6302-4f79-ad70-499253e6926a"))
|
||||||
|
(label "SPI_MOSI" (at 215 55 0) (effects (font (size 1.27 1.27))) (uuid "f6281dca-e340-4987-a951-2f82a1714181"))
|
||||||
|
(label "SPI_MISO" (at 165 90 0) (effects (font (size 1.27 1.27))) (uuid "15344a55-c345-4d4f-bc69-d1123a2c9edf"))
|
||||||
|
(label "SPI_MISO" (at 215 60 0) (effects (font (size 1.27 1.27))) (uuid "979ceaf3-85e4-449e-957c-41ef8f11c043"))
|
||||||
|
(label "SPI_SCK" (at 165 95 0) (effects (font (size 1.27 1.27))) (uuid "4382cc5e-6bd2-4b3c-a286-89e68a9bfe44"))
|
||||||
|
(label "SPI_SCK" (at 215 65 0) (effects (font (size 1.27 1.27))) (uuid "5a6dfb3a-06a4-49ca-aad3-f7193a293ce3"))
|
||||||
|
(label "FLASH_CS" (at 165 80 0) (effects (font (size 1.27 1.27))) (uuid "c791cf26-bc22-410d-aaea-c2eda0b338cd"))
|
||||||
|
(label "FLASH_CS" (at 215 50 0) (effects (font (size 1.27 1.27))) (uuid "ef59be0a-fc41-456f-947c-1692d138b101"))
|
||||||
|
(label "AUDIO_PWM" (at 165 100 0) (effects (font (size 1.27 1.27))) (uuid "29036b7e-9203-47e8-9d64-1f906a93ef48"))
|
||||||
|
(label "AUDIO_PWM" (at 175 135 0) (effects (font (size 1.27 1.27))) (uuid "44583660-84d0-446b-a09f-9b7c62d110a6"))
|
||||||
|
(label "AMP_SD" (at 165 105 0) (effects (font (size 1.27 1.27))) (uuid "52045a7c-f447-4d0c-a9eb-850e34f11964"))
|
||||||
|
(label "AMP_SD" (at 210 145 0) (effects (font (size 1.27 1.27))) (uuid "1bcd7182-a352-4545-afe0-2f863d13594c"))
|
||||||
|
(label "MOTOR_PWM" (at 165 110 0) (effects (font (size 1.27 1.27))) (uuid "6c11ecd3-674e-4579-b26f-fa7cc592b2ef"))
|
||||||
|
(label "MOTOR_PWM" (at 110 190 0) (effects (font (size 1.27 1.27))) (uuid "18a66086-7b01-4c86-904c-f721fc2edce7"))
|
||||||
|
(label "BTN1" (at 45 75 0) (effects (font (size 1.27 1.27))) (uuid "92101bd4-f77a-410a-ab6a-0e3d3d66bc02"))
|
||||||
|
(label "BTN1" (at 95 85 0) (effects (font (size 1.27 1.27))) (uuid "28383130-7933-45e2-bfed-0dd34ff8e876"))
|
||||||
|
(label "BTN2" (at 45 90 0) (effects (font (size 1.27 1.27))) (uuid "a2f3390b-61b3-4812-ada2-1f4246e4f0cb"))
|
||||||
|
(label "BTN2" (at 95 90 0) (effects (font (size 1.27 1.27))) (uuid "42b61c7b-b336-4758-b778-9b4ea4905074"))
|
||||||
|
(label "BTN3" (at 45 105 0) (effects (font (size 1.27 1.27))) (uuid "fe284da5-c9e9-48e5-a293-7bf5f6aa33c9"))
|
||||||
|
(label "BTN3" (at 95 95 0) (effects (font (size 1.27 1.27))) (uuid "46e2de5c-c19d-4699-8367-e91303e840d5"))
|
||||||
|
(label "BTN4" (at 45 120 0) (effects (font (size 1.27 1.27))) (uuid "1d9dff94-06c9-49c6-b8e0-66657dd4245a"))
|
||||||
|
(label "BTN4" (at 95 100 0) (effects (font (size 1.27 1.27))) (uuid "e53835b8-f6b2-40f7-9245-d0d67614ec45"))
|
||||||
|
(label "BTN5" (at 45 135 0) (effects (font (size 1.27 1.27))) (uuid "4322ba20-38b0-41cf-a3c4-8bf56908ce34"))
|
||||||
|
(label "BTN5" (at 95 105 0) (effects (font (size 1.27 1.27))) (uuid "a04ee831-82c5-48b5-85c1-9d7fb0a24e33"))
|
||||||
|
(label "BTN6" (at 45 150 0) (effects (font (size 1.27 1.27))) (uuid "f64f61ae-b22d-41a4-a8ea-770610aebd0a"))
|
||||||
|
(label "BTN6" (at 95 110 0) (effects (font (size 1.27 1.27))) (uuid "53e714b1-e914-4811-8290-a921f65cac0e"))
|
||||||
|
(label "BTN7" (at 45 165 0) (effects (font (size 1.27 1.27))) (uuid "ce9834a4-38a7-4ea9-931a-2f9919142d64"))
|
||||||
|
(label "BTN7" (at 95 115 0) (effects (font (size 1.27 1.27))) (uuid "ddf7162b-f974-4375-885a-f25f1b1d9f57"))
|
||||||
|
(label "BTN8" (at 45 180 0) (effects (font (size 1.27 1.27))) (uuid "783f1d6f-fe69-492a-aab0-a98b6ec4338b"))
|
||||||
|
(label "BTN8" (at 95 120 0) (effects (font (size 1.27 1.27))) (uuid "12159112-3e7e-478d-96a5-db94ad9ab8a7"))
|
||||||
|
(label "SPI_MOSI" (at 240 195 0) (effects (font (size 1.27 1.27))) (uuid "28dda728-344b-400c-81bf-085acc569b01"))
|
||||||
|
(label "SPI_MISO" (at 240 200 0) (effects (font (size 1.27 1.27))) (uuid "3c258f39-bf6c-4f9d-977a-ca79c60e541a"))
|
||||||
|
(label "SPI_SCK" (at 240 205 0) (effects (font (size 1.27 1.27))) (uuid "a7f8b6cd-ff0a-4f2e-95e2-c09c7380629b"))
|
||||||
|
(label "RESET" (at 240 210 0) (effects (font (size 1.27 1.27))) (uuid "8ca5b857-1e0a-4810-9169-7a53d9010e7a"))
|
||||||
|
(label "RESET" (at 95 60 0) (effects (font (size 1.27 1.27))) (uuid "892fcef9-51e4-47c6-95bc-23995df359e9"))
|
||||||
|
(label "TXD" (at 40 210 0) (effects (font (size 1.27 1.27))) (uuid "b7910a83-f672-4c68-89d5-a06db98757ec"))
|
||||||
|
(label "RXD" (at 40 215 0) (effects (font (size 1.27 1.27))) (uuid "db832982-7322-4447-8344-cc95d72ebb5b"))
|
||||||
|
(label "TXD" (at 95 75 0) (effects (font (size 1.27 1.27))) (uuid "16f4752d-6c95-4710-ba23-85842ce78a5d"))
|
||||||
|
(label "RXD" (at 95 80 0) (effects (font (size 1.27 1.27))) (uuid "e269931d-0da1-4020-9952-ef4385a672f7"))
|
||||||
|
(label "LED_OUT" (at 65 190 0) (effects (font (size 1.27 1.27))) (uuid "3cf2c0dd-1277-46aa-bbfa-0319ce140d17"))
|
||||||
|
(label "LED_OUT" (at 95 125 0) (effects (font (size 1.27 1.27))) (uuid "231cf2b7-4593-4067-9607-34041c287667"))
|
||||||
|
(text "POWER: 2xAA (1.8V-3.3V) → Long runtime design" (at 15 15 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "950687a6-9e66-444c-bf5d-ac1f097f704f")
|
||||||
|
)
|
||||||
|
(text "MCU: ATmega328P-AU @ 8MHz internal osc, Arduino compatible" (at 15 18 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "f0cdcdd5-ae9a-4fac-b551-a92f7212bfdd")
|
||||||
|
)
|
||||||
|
(text "FLASH: W25Q128 16MB = ~33 min @ 8kHz 8-bit PCM" (at 200 15 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "dd881348-3856-462b-bd58-72d20fb89ca3")
|
||||||
|
)
|
||||||
|
(text "AMP: PAM8302A Class-D, 90% efficient, Vmin=2.0V" (at 200 18 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "7c7a46f6-98e4-4bf2-ae72-3ea92549e1d7")
|
||||||
|
)
|
||||||
|
(text "BUTTONS: Internal pull-ups, active LOW, PCINT wake-from-sleep" (at 15 220 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "eca71b6b-2202-4712-8241-1daf4bd4d0b3")
|
||||||
|
)
|
||||||
|
(text "MOTOR: AO3400A logic-level N-MOSFET, PWM speed control" (at 120 220 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "d36eb55c-80a1-4119-a4d5-92f77873caa6")
|
||||||
|
)
|
||||||
|
(text "ESTIMATED RUNTIME: Audio+Motor ~23h, Audio only ~200h, Sleep ~years" (at 15 225 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "79709c38-5874-4567-856d-15479cbe33cd")
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,639 @@
|
|||||||
|
/*
|
||||||
|
* Baby Mobile Audio Board — Firmware
|
||||||
|
*
|
||||||
|
* ATmega328P @ 8MHz internal oscillator
|
||||||
|
* Plays 8-bit unsigned PCM audio from W25Q128 SPI flash
|
||||||
|
* Controls DC motor via PWM
|
||||||
|
* 8 button inputs with sleep/wake support
|
||||||
|
*
|
||||||
|
* Board: ATmega328P, 8MHz internal, BOD 1.8V
|
||||||
|
*
|
||||||
|
* Pin mapping:
|
||||||
|
* PB1 (OC1A, pin 9) - Audio PWM output
|
||||||
|
* PB2 (pin 10) - Flash ~CS
|
||||||
|
* PB3 (pin 11) - SPI MOSI
|
||||||
|
* PB4 (pin 12) - SPI MISO
|
||||||
|
* PB5 (pin 13) - SPI SCK
|
||||||
|
* PD5 (OC0B, pin 5) - Motor PWM
|
||||||
|
* PC2 (A2) - Amp ~SD (HIGH=on, LOW=off)
|
||||||
|
* PC3 (A3) - Status LED
|
||||||
|
* PC0 (A0) - Button 1
|
||||||
|
* PC1 (A1) - Button 2
|
||||||
|
* PD2 (pin 2) - Button 3 (INT0)
|
||||||
|
* PD3 (pin 3) - Button 4 (INT1)
|
||||||
|
* PD4 (pin 4) - Button 5
|
||||||
|
* PD6 (pin 6) - Button 6
|
||||||
|
* PD7 (pin 7) - Button 7
|
||||||
|
* PB0 (pin 8) - Button 8
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <avr/sleep.h>
|
||||||
|
#include <avr/power.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
// ---- Pin definitions ----
|
||||||
|
#define PIN_AUDIO_PWM 9 // PB1 / OC1A
|
||||||
|
#define PIN_FLASH_CS 10 // PB2
|
||||||
|
#define PIN_MOTOR_PWM 5 // PD5 / OC0B
|
||||||
|
#define PIN_AMP_SD A2 // PC2 - amp shutdown (active HIGH = enabled)
|
||||||
|
#define PIN_LED A3 // PC3
|
||||||
|
#define PIN_BTN1 A0 // PC0
|
||||||
|
#define PIN_BTN2 A1 // PC1
|
||||||
|
#define PIN_BTN3 2 // PD2 / INT0
|
||||||
|
#define PIN_BTN4 3 // PD3 / INT1
|
||||||
|
#define PIN_BTN5 4 // PD4
|
||||||
|
#define PIN_BTN6 6 // PD6
|
||||||
|
#define PIN_BTN7 7 // PD7
|
||||||
|
#define PIN_BTN8 8 // PB0
|
||||||
|
|
||||||
|
// ---- Audio config ----
|
||||||
|
#define SAMPLE_RATE 8000 // Hz
|
||||||
|
#define FLASH_PAGE_SIZE 256
|
||||||
|
#define FLASH_SECTOR 4096
|
||||||
|
#define AUDIO_BUF_SIZE 256 // double buffer
|
||||||
|
|
||||||
|
// ---- Flash commands (W25Q128) ----
|
||||||
|
#define FLASH_CMD_READ 0x03
|
||||||
|
#define FLASH_CMD_FAST_READ 0x0B
|
||||||
|
#define FLASH_CMD_WRITE_EN 0x06
|
||||||
|
#define FLASH_CMD_PAGE_PROG 0x02
|
||||||
|
#define FLASH_CMD_SECT_ERASE 0x20
|
||||||
|
#define FLASH_CMD_CHIP_ERASE 0xC7
|
||||||
|
#define FLASH_CMD_READ_SR1 0x05
|
||||||
|
#define FLASH_CMD_JEDEC_ID 0x9F
|
||||||
|
#define FLASH_CMD_POWER_DOWN 0xB9
|
||||||
|
#define FLASH_CMD_WAKE 0xAB
|
||||||
|
|
||||||
|
// ---- Track table ----
|
||||||
|
// First 4KB (sector 0) of flash stores a track index:
|
||||||
|
// Offset 0x000: uint8_t num_tracks
|
||||||
|
// Offset 0x004: uint32_t track_start[32] (byte address in flash)
|
||||||
|
// Offset 0x084: uint32_t track_length[32] (length in bytes = samples)
|
||||||
|
// Audio data begins at sector 1 (address 0x1000).
|
||||||
|
|
||||||
|
#define TRACK_TABLE_ADDR 0x000000
|
||||||
|
#define AUDIO_START_ADDR 0x001000
|
||||||
|
#define MAX_TRACKS 32
|
||||||
|
|
||||||
|
// ---- State ----
|
||||||
|
volatile bool g_playing = false;
|
||||||
|
volatile bool g_motorOn = false;
|
||||||
|
volatile bool g_wakeFlag = false;
|
||||||
|
volatile uint8_t g_buttonPressed = 0;
|
||||||
|
|
||||||
|
uint8_t g_numTracks = 0;
|
||||||
|
uint32_t g_trackStart[MAX_TRACKS];
|
||||||
|
uint32_t g_trackLen[MAX_TRACKS];
|
||||||
|
uint8_t g_currentTrack = 0;
|
||||||
|
uint32_t g_playPos = 0; // current position in track (byte offset)
|
||||||
|
uint32_t g_playEnd = 0; // end position
|
||||||
|
uint8_t g_motorSpeed = 180; // PWM duty cycle (0-255)
|
||||||
|
|
||||||
|
// Double buffer for audio DMA-style playback
|
||||||
|
uint8_t g_audioBuf[2][AUDIO_BUF_SIZE];
|
||||||
|
volatile uint8_t g_activeBuf = 0; // buffer currently being played
|
||||||
|
volatile uint16_t g_bufPos = 0; // position in active buffer
|
||||||
|
volatile bool g_bufReady[2] = {false, false};
|
||||||
|
uint32_t g_nextReadAddr = 0;
|
||||||
|
|
||||||
|
// Auto-shutoff timer (milliseconds)
|
||||||
|
#define AUTO_OFF_MS (30UL * 60UL * 1000UL) // 30 minutes
|
||||||
|
unsigned long g_lastActivity = 0;
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// FLASH FUNCTIONS
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void flashSelect() { digitalWrite(PIN_FLASH_CS, LOW); }
|
||||||
|
void flashDeselect() { digitalWrite(PIN_FLASH_CS, HIGH); }
|
||||||
|
|
||||||
|
void flashWake() {
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_WAKE);
|
||||||
|
flashDeselect();
|
||||||
|
delayMicroseconds(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flashSleep() {
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_POWER_DOWN);
|
||||||
|
flashDeselect();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t flashReadJEDEC() {
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_JEDEC_ID);
|
||||||
|
uint32_t id = (uint32_t)SPI.transfer(0) << 16;
|
||||||
|
id |= (uint32_t)SPI.transfer(0) << 8;
|
||||||
|
id |= SPI.transfer(0);
|
||||||
|
flashDeselect();
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flashReadBytes(uint32_t addr, uint8_t *buf, uint16_t len) {
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_READ);
|
||||||
|
SPI.transfer((addr >> 16) & 0xFF);
|
||||||
|
SPI.transfer((addr >> 8) & 0xFF);
|
||||||
|
SPI.transfer(addr & 0xFF);
|
||||||
|
for (uint16_t i = 0; i < len; i++) {
|
||||||
|
buf[i] = SPI.transfer(0);
|
||||||
|
}
|
||||||
|
flashDeselect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flashWaitBusy() {
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_READ_SR1);
|
||||||
|
while (SPI.transfer(0) & 0x01) { /* spin */ }
|
||||||
|
flashDeselect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flashWriteEnable() {
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_WRITE_EN);
|
||||||
|
flashDeselect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flashEraseSector(uint32_t addr) {
|
||||||
|
flashWriteEnable();
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_SECT_ERASE);
|
||||||
|
SPI.transfer((addr >> 16) & 0xFF);
|
||||||
|
SPI.transfer((addr >> 8) & 0xFF);
|
||||||
|
SPI.transfer(addr & 0xFF);
|
||||||
|
flashDeselect();
|
||||||
|
flashWaitBusy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void flashPageProgram(uint32_t addr, const uint8_t *data, uint16_t len) {
|
||||||
|
flashWriteEnable();
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_PAGE_PROG);
|
||||||
|
SPI.transfer((addr >> 16) & 0xFF);
|
||||||
|
SPI.transfer((addr >> 8) & 0xFF);
|
||||||
|
SPI.transfer(addr & 0xFF);
|
||||||
|
for (uint16_t i = 0; i < len; i++) {
|
||||||
|
SPI.transfer(data[i]);
|
||||||
|
}
|
||||||
|
flashDeselect();
|
||||||
|
flashWaitBusy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// TRACK TABLE
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void loadTrackTable() {
|
||||||
|
uint8_t header[4];
|
||||||
|
flashReadBytes(TRACK_TABLE_ADDR, header, 4);
|
||||||
|
g_numTracks = header[0];
|
||||||
|
if (g_numTracks == 0 || g_numTracks == 0xFF || g_numTracks > MAX_TRACKS) {
|
||||||
|
g_numTracks = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read start addresses
|
||||||
|
uint8_t buf[4];
|
||||||
|
for (uint8_t i = 0; i < g_numTracks; i++) {
|
||||||
|
flashReadBytes(TRACK_TABLE_ADDR + 4 + i * 4, buf, 4);
|
||||||
|
g_trackStart[i] = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
|
||||||
|
((uint32_t)buf[2] << 8) | buf[3];
|
||||||
|
}
|
||||||
|
// Read lengths
|
||||||
|
for (uint8_t i = 0; i < g_numTracks; i++) {
|
||||||
|
flashReadBytes(TRACK_TABLE_ADDR + 4 + MAX_TRACKS * 4 + i * 4, buf, 4);
|
||||||
|
g_trackLen[i] = ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
|
||||||
|
((uint32_t)buf[2] << 8) | buf[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// AUDIO PLAYBACK (Timer1 ISR)
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void audioInit() {
|
||||||
|
// Timer1: Fast PWM, 8-bit, TOP=255
|
||||||
|
// At 8MHz clock: 8000000 / 256 = 31250 Hz PWM frequency
|
||||||
|
// Good enough — well above audible range
|
||||||
|
|
||||||
|
// We use a separate Timer1 compare match for sample rate:
|
||||||
|
// Timer1 in Fast PWM mode for output,
|
||||||
|
// Timer2 for sample rate interrupt
|
||||||
|
|
||||||
|
// Timer1: Fast PWM 8-bit on OC1A (PB1)
|
||||||
|
TCCR1A = _BV(COM1A1) | _BV(WGM10); // Clear on match, 8-bit fast PWM
|
||||||
|
TCCR1B = _BV(WGM12) | _BV(CS10); // No prescaler
|
||||||
|
OCR1A = 128; // 50% = silence for unsigned 8-bit
|
||||||
|
|
||||||
|
// Timer2: CTC mode for sample rate interrupt
|
||||||
|
// 8MHz / 8 / 125 = 8000 Hz
|
||||||
|
TCCR2A = _BV(WGM21); // CTC mode
|
||||||
|
TCCR2B = _BV(CS21); // prescaler /8
|
||||||
|
OCR2A = 124; // 8000000/8/(124+1) = 8000 Hz
|
||||||
|
TIMSK2 = 0; // interrupt disabled until playing
|
||||||
|
}
|
||||||
|
|
||||||
|
void audioStart(uint8_t trackNum) {
|
||||||
|
if (trackNum >= g_numTracks) return;
|
||||||
|
|
||||||
|
g_currentTrack = trackNum;
|
||||||
|
g_playPos = g_trackStart[trackNum];
|
||||||
|
g_playEnd = g_playPos + g_trackLen[trackNum];
|
||||||
|
|
||||||
|
// Pre-fill both buffers
|
||||||
|
flashReadBytes(g_playPos, g_audioBuf[0], AUDIO_BUF_SIZE);
|
||||||
|
g_playPos += AUDIO_BUF_SIZE;
|
||||||
|
if (g_playPos < g_playEnd) {
|
||||||
|
flashReadBytes(g_playPos, g_audioBuf[1], AUDIO_BUF_SIZE);
|
||||||
|
g_playPos += AUDIO_BUF_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_activeBuf = 0;
|
||||||
|
g_bufPos = 0;
|
||||||
|
g_bufReady[0] = true;
|
||||||
|
g_bufReady[1] = true;
|
||||||
|
g_nextReadAddr = g_playPos;
|
||||||
|
|
||||||
|
// Enable amp
|
||||||
|
digitalWrite(PIN_AMP_SD, HIGH);
|
||||||
|
delay(10); // amp startup time
|
||||||
|
|
||||||
|
g_playing = true;
|
||||||
|
TIMSK2 = _BV(OCIE2A); // enable sample rate interrupt
|
||||||
|
}
|
||||||
|
|
||||||
|
void audioStop() {
|
||||||
|
TIMSK2 = 0; // disable interrupt
|
||||||
|
OCR1A = 128; // silence
|
||||||
|
g_playing = false;
|
||||||
|
|
||||||
|
// Disable amp to save power
|
||||||
|
digitalWrite(PIN_AMP_SD, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Timer2 Compare Match A — fires at 8000 Hz
|
||||||
|
ISR(TIMER2_COMPA_vect) {
|
||||||
|
if (!g_playing) return;
|
||||||
|
|
||||||
|
// Output sample to PWM
|
||||||
|
OCR1A = g_audioBuf[g_activeBuf][g_bufPos];
|
||||||
|
g_bufPos++;
|
||||||
|
|
||||||
|
if (g_bufPos >= AUDIO_BUF_SIZE) {
|
||||||
|
// Switch to other buffer
|
||||||
|
g_bufReady[g_activeBuf] = false; // mark for refill
|
||||||
|
g_activeBuf ^= 1;
|
||||||
|
g_bufPos = 0;
|
||||||
|
|
||||||
|
if (!g_bufReady[g_activeBuf]) {
|
||||||
|
// Buffer underrun — stop playback
|
||||||
|
g_playing = false;
|
||||||
|
OCR1A = 128;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// MOTOR CONTROL
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void motorInit() {
|
||||||
|
pinMode(PIN_MOTOR_PWM, OUTPUT);
|
||||||
|
analogWrite(PIN_MOTOR_PWM, 0); // off
|
||||||
|
}
|
||||||
|
|
||||||
|
void motorStart(uint8_t speed) {
|
||||||
|
g_motorSpeed = speed;
|
||||||
|
g_motorOn = true;
|
||||||
|
analogWrite(PIN_MOTOR_PWM, speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void motorStop() {
|
||||||
|
g_motorOn = false;
|
||||||
|
analogWrite(PIN_MOTOR_PWM, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// BUTTONS
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
const uint8_t BTN_PINS[] = {
|
||||||
|
PIN_BTN1, PIN_BTN2, PIN_BTN3, PIN_BTN4,
|
||||||
|
PIN_BTN5, PIN_BTN6, PIN_BTN7, PIN_BTN8
|
||||||
|
};
|
||||||
|
#define NUM_BUTTONS 8
|
||||||
|
|
||||||
|
void buttonsInit() {
|
||||||
|
for (uint8_t i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
pinMode(BTN_PINS[i], INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns button number 1-8, or 0 if none pressed
|
||||||
|
uint8_t buttonRead() {
|
||||||
|
for (uint8_t i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
if (digitalRead(BTN_PINS[i]) == LOW) {
|
||||||
|
delay(20); // debounce
|
||||||
|
if (digitalRead(BTN_PINS[i]) == LOW) {
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// SLEEP / WAKE
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// Pin change interrupts for wake-from-sleep
|
||||||
|
ISR(PCINT0_vect) { g_wakeFlag = true; } // PB0 (BTN8)
|
||||||
|
ISR(PCINT1_vect) { g_wakeFlag = true; } // PC0, PC1 (BTN1, BTN2)
|
||||||
|
ISR(PCINT2_vect) { g_wakeFlag = true; } // PD2-7 (BTN3-BTN7)
|
||||||
|
ISR(INT0_vect) { g_wakeFlag = true; }
|
||||||
|
ISR(INT1_vect) { g_wakeFlag = true; }
|
||||||
|
|
||||||
|
void enterSleep() {
|
||||||
|
// Stop everything
|
||||||
|
audioStop();
|
||||||
|
motorStop();
|
||||||
|
flashSleep();
|
||||||
|
digitalWrite(PIN_LED, LOW);
|
||||||
|
|
||||||
|
// Enable pin change interrupts for wake
|
||||||
|
PCICR = _BV(PCIE0) | _BV(PCIE1) | _BV(PCIE2);
|
||||||
|
PCMSK0 = _BV(PCINT0); // PB0
|
||||||
|
PCMSK1 = _BV(PCINT8) | _BV(PCINT9); // PC0, PC1
|
||||||
|
PCMSK2 = _BV(PCINT18) | _BV(PCINT19) | _BV(PCINT20) |
|
||||||
|
_BV(PCINT22) | _BV(PCINT23); // PD2,3,4,6,7
|
||||||
|
|
||||||
|
// Also enable INT0/INT1 for PD2/PD3
|
||||||
|
EICRA = 0; // LOW level trigger
|
||||||
|
EIMSK = _BV(INT0) | _BV(INT1);
|
||||||
|
|
||||||
|
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||||
|
sleep_enable();
|
||||||
|
sei();
|
||||||
|
sleep_cpu();
|
||||||
|
|
||||||
|
// --- ZZZ --- wakes up here ---
|
||||||
|
sleep_disable();
|
||||||
|
|
||||||
|
// Disable wake interrupts
|
||||||
|
PCICR = 0;
|
||||||
|
EIMSK = 0;
|
||||||
|
|
||||||
|
// Wake flash
|
||||||
|
flashWake();
|
||||||
|
|
||||||
|
g_lastActivity = millis();
|
||||||
|
g_wakeFlag = false;
|
||||||
|
|
||||||
|
// Blink LED to indicate wake
|
||||||
|
digitalWrite(PIN_LED, HIGH);
|
||||||
|
delay(100);
|
||||||
|
digitalWrite(PIN_LED, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// SERIAL FLASH PROGRAMMER
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
// Simple protocol for uploading audio over serial:
|
||||||
|
// 'I' → respond with flash JEDEC ID
|
||||||
|
// 'E' → erase entire flash chip
|
||||||
|
// 'W' addr(3 bytes) len(2 bytes) data... → write page
|
||||||
|
// 'R' addr(3 bytes) len(2 bytes) → read bytes back
|
||||||
|
// 'T' → read track table
|
||||||
|
|
||||||
|
void handleSerial() {
|
||||||
|
if (!Serial.available()) return;
|
||||||
|
|
||||||
|
uint8_t cmd = Serial.read();
|
||||||
|
|
||||||
|
switch (cmd) {
|
||||||
|
case 'I': {
|
||||||
|
uint32_t id = flashReadJEDEC();
|
||||||
|
Serial.print("JEDEC: 0x");
|
||||||
|
Serial.println(id, HEX);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'E': {
|
||||||
|
Serial.println("Erasing flash...");
|
||||||
|
flashWriteEnable();
|
||||||
|
flashSelect();
|
||||||
|
SPI.transfer(FLASH_CMD_CHIP_ERASE);
|
||||||
|
flashDeselect();
|
||||||
|
flashWaitBusy(); // takes ~40 seconds for 16MB
|
||||||
|
Serial.println("Done");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'W': {
|
||||||
|
// Wait for address (3 bytes) and length (2 bytes)
|
||||||
|
while (Serial.available() < 5) {}
|
||||||
|
uint32_t addr = (uint32_t)Serial.read() << 16;
|
||||||
|
addr |= (uint32_t)Serial.read() << 8;
|
||||||
|
addr |= Serial.read();
|
||||||
|
uint16_t len = (uint16_t)Serial.read() << 8;
|
||||||
|
len |= Serial.read();
|
||||||
|
if (len > 256) len = 256;
|
||||||
|
|
||||||
|
uint8_t buf[256];
|
||||||
|
uint16_t received = 0;
|
||||||
|
while (received < len) {
|
||||||
|
if (Serial.available()) {
|
||||||
|
buf[received++] = Serial.read();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flashPageProgram(addr, buf, len);
|
||||||
|
Serial.print("OK ");
|
||||||
|
Serial.println(addr, HEX);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'R': {
|
||||||
|
while (Serial.available() < 5) {}
|
||||||
|
uint32_t addr = (uint32_t)Serial.read() << 16;
|
||||||
|
addr |= (uint32_t)Serial.read() << 8;
|
||||||
|
addr |= Serial.read();
|
||||||
|
uint16_t len = (uint16_t)Serial.read() << 8;
|
||||||
|
len |= Serial.read();
|
||||||
|
|
||||||
|
uint8_t buf[256];
|
||||||
|
while (len > 0) {
|
||||||
|
uint16_t chunk = (len > 256) ? 256 : len;
|
||||||
|
flashReadBytes(addr, buf, chunk);
|
||||||
|
Serial.write(buf, chunk);
|
||||||
|
addr += chunk;
|
||||||
|
len -= chunk;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================
|
||||||
|
// MAIN
|
||||||
|
// ============================================================
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
// Disable unused peripherals for power saving
|
||||||
|
power_adc_disable(); // we don't use ADC
|
||||||
|
power_twi_disable(); // we don't use I2C
|
||||||
|
|
||||||
|
// Pin setup
|
||||||
|
pinMode(PIN_FLASH_CS, OUTPUT);
|
||||||
|
pinMode(PIN_AMP_SD, OUTPUT);
|
||||||
|
pinMode(PIN_LED, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(PIN_FLASH_CS, HIGH); // deselect flash
|
||||||
|
digitalWrite(PIN_AMP_SD, LOW); // amp off
|
||||||
|
digitalWrite(PIN_LED, LOW);
|
||||||
|
|
||||||
|
// Init peripherals
|
||||||
|
Serial.begin(9600);
|
||||||
|
SPI.begin();
|
||||||
|
SPI.setClockDivider(SPI_CLOCK_DIV2); // 4MHz SPI (8MHz/2)
|
||||||
|
|
||||||
|
buttonsInit();
|
||||||
|
motorInit();
|
||||||
|
audioInit();
|
||||||
|
|
||||||
|
// Init flash
|
||||||
|
flashWake();
|
||||||
|
delay(1);
|
||||||
|
|
||||||
|
uint32_t jedec = flashReadJEDEC();
|
||||||
|
if (jedec == 0xEF4018) {
|
||||||
|
// W25Q128 detected
|
||||||
|
digitalWrite(PIN_LED, HIGH);
|
||||||
|
delay(200);
|
||||||
|
digitalWrite(PIN_LED, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load track table
|
||||||
|
loadTrackTable();
|
||||||
|
|
||||||
|
g_lastActivity = millis();
|
||||||
|
|
||||||
|
Serial.print("Baby Mobile v1.0 — ");
|
||||||
|
Serial.print(g_numTracks);
|
||||||
|
Serial.println(" tracks loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// ---- Handle serial commands (for programming) ----
|
||||||
|
handleSerial();
|
||||||
|
|
||||||
|
// ---- Refill audio buffer in main loop ----
|
||||||
|
if (g_playing) {
|
||||||
|
for (uint8_t b = 0; b < 2; b++) {
|
||||||
|
if (!g_bufReady[b] && g_nextReadAddr < g_playEnd) {
|
||||||
|
uint32_t remaining = g_playEnd - g_nextReadAddr;
|
||||||
|
uint16_t toRead = (remaining > AUDIO_BUF_SIZE) ? AUDIO_BUF_SIZE : remaining;
|
||||||
|
|
||||||
|
flashReadBytes(g_nextReadAddr, g_audioBuf[b], toRead);
|
||||||
|
// Zero-pad if short
|
||||||
|
for (uint16_t i = toRead; i < AUDIO_BUF_SIZE; i++) {
|
||||||
|
g_audioBuf[b][i] = 128; // silence
|
||||||
|
}
|
||||||
|
g_nextReadAddr += toRead;
|
||||||
|
g_bufReady[b] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if playback finished
|
||||||
|
if (!g_bufReady[0] && !g_bufReady[1]) {
|
||||||
|
audioStop();
|
||||||
|
// Auto-advance to next track or loop
|
||||||
|
g_currentTrack = (g_currentTrack + 1) % g_numTracks;
|
||||||
|
audioStart(g_currentTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Read buttons ----
|
||||||
|
uint8_t btn = buttonRead();
|
||||||
|
if (btn > 0) {
|
||||||
|
g_lastActivity = millis();
|
||||||
|
|
||||||
|
switch (btn) {
|
||||||
|
case 1: // Play / Pause
|
||||||
|
if (g_playing) {
|
||||||
|
audioStop();
|
||||||
|
} else {
|
||||||
|
audioStart(g_currentTrack);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: // Next track
|
||||||
|
if (g_numTracks > 0) {
|
||||||
|
g_currentTrack = (g_currentTrack + 1) % g_numTracks;
|
||||||
|
if (g_playing) {
|
||||||
|
audioStop();
|
||||||
|
audioStart(g_currentTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // Previous track
|
||||||
|
if (g_numTracks > 0) {
|
||||||
|
g_currentTrack = (g_currentTrack == 0) ? g_numTracks - 1 : g_currentTrack - 1;
|
||||||
|
if (g_playing) {
|
||||||
|
audioStop();
|
||||||
|
audioStart(g_currentTrack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // Motor toggle
|
||||||
|
if (g_motorOn) {
|
||||||
|
motorStop();
|
||||||
|
} else {
|
||||||
|
motorStart(g_motorSpeed);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // Motor speed up
|
||||||
|
if (g_motorSpeed < 235) g_motorSpeed += 20;
|
||||||
|
if (g_motorOn) analogWrite(PIN_MOTOR_PWM, g_motorSpeed);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6: // Motor speed down
|
||||||
|
if (g_motorSpeed > 80) g_motorSpeed -= 20;
|
||||||
|
if (g_motorOn) analogWrite(PIN_MOTOR_PWM, g_motorSpeed);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7: // Play all (music + motor)
|
||||||
|
motorStart(g_motorSpeed);
|
||||||
|
if (!g_playing) audioStart(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8: // Stop all
|
||||||
|
audioStop();
|
||||||
|
motorStop();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for button release
|
||||||
|
while (buttonRead() == btn) { delay(10); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Auto shutoff ----
|
||||||
|
if (millis() - g_lastActivity > AUTO_OFF_MS) {
|
||||||
|
enterSleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Sleep if idle (no audio, no motor) ----
|
||||||
|
if (!g_playing && !g_motorOn && (millis() - g_lastActivity > 60000)) {
|
||||||
|
enterSleep();
|
||||||
|
}
|
||||||
|
}
|
||||||
+233
@@ -0,0 +1,233 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
flash_upload.py — Upload audio files to the Baby Mobile's W25Q128 flash.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 flash_upload.py /dev/ttyUSB0 song1.raw song2.raw song3.raw ...
|
||||||
|
|
||||||
|
Audio files must be raw unsigned 8-bit PCM at 8000 Hz mono.
|
||||||
|
Convert with ffmpeg:
|
||||||
|
ffmpeg -i song.mp3 -ar 8000 -ac 1 -f u8 -acodec pcm_u8 song.raw
|
||||||
|
|
||||||
|
The script writes a track table to sector 0, then audio data starting
|
||||||
|
at sector 1 (address 0x1000).
|
||||||
|
"""
|
||||||
|
|
||||||
|
import serial
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
BAUD = 9600
|
||||||
|
PAGE_SIZE = 256
|
||||||
|
SECTOR_SIZE = 4096
|
||||||
|
AUDIO_START = 0x1000
|
||||||
|
MAX_TRACKS = 32
|
||||||
|
FLASH_SIZE = 16 * 1024 * 1024 # 16MB
|
||||||
|
|
||||||
|
|
||||||
|
def open_serial(port):
|
||||||
|
ser = serial.Serial(port, BAUD, timeout=2)
|
||||||
|
time.sleep(2) # wait for Arduino reset
|
||||||
|
# Flush
|
||||||
|
ser.read(ser.in_waiting)
|
||||||
|
return ser
|
||||||
|
|
||||||
|
|
||||||
|
def flash_identify(ser):
|
||||||
|
ser.write(b'I')
|
||||||
|
line = ser.readline().decode().strip()
|
||||||
|
print(f" {line}")
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
def flash_erase(ser):
|
||||||
|
print(" Erasing entire flash (takes ~40 seconds)...")
|
||||||
|
ser.write(b'E')
|
||||||
|
line = ser.readline().decode().strip()
|
||||||
|
while "Done" not in line:
|
||||||
|
line = ser.readline().decode().strip()
|
||||||
|
if line:
|
||||||
|
print(f" {line}")
|
||||||
|
print(" Erase complete.")
|
||||||
|
|
||||||
|
|
||||||
|
def flash_write_page(ser, addr, data):
|
||||||
|
"""Write up to 256 bytes to flash."""
|
||||||
|
assert len(data) <= 256
|
||||||
|
cmd = b'W'
|
||||||
|
cmd += struct.pack('>I', addr)[1:] # 3 bytes address
|
||||||
|
cmd += struct.pack('>H', len(data))
|
||||||
|
ser.write(cmd)
|
||||||
|
ser.write(data)
|
||||||
|
resp = ser.readline().decode().strip()
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
def flash_write_data(ser, start_addr, data, label=""):
|
||||||
|
"""Write arbitrary length data, page by page."""
|
||||||
|
total = len(data)
|
||||||
|
written = 0
|
||||||
|
addr = start_addr
|
||||||
|
|
||||||
|
while written < total:
|
||||||
|
chunk = data[written:written + PAGE_SIZE]
|
||||||
|
# Pad last page
|
||||||
|
if len(chunk) < PAGE_SIZE:
|
||||||
|
chunk = chunk + b'\x80' * (PAGE_SIZE - len(chunk)) # 0x80 = silence
|
||||||
|
|
||||||
|
flash_write_page(ser, addr, chunk)
|
||||||
|
written += PAGE_SIZE
|
||||||
|
addr += PAGE_SIZE
|
||||||
|
|
||||||
|
pct = min(100, written * 100 // total)
|
||||||
|
print(f"\r Writing {label}: {pct}% ({written}/{total} bytes)", end="", flush=True)
|
||||||
|
|
||||||
|
print()
|
||||||
|
return addr
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_raw(input_path):
|
||||||
|
"""Convert any audio file to 8kHz 8-bit unsigned PCM using ffmpeg."""
|
||||||
|
raw_path = input_path + ".raw"
|
||||||
|
|
||||||
|
if input_path.endswith('.raw'):
|
||||||
|
return input_path
|
||||||
|
|
||||||
|
if not shutil.which('ffmpeg'):
|
||||||
|
print(f"ERROR: ffmpeg not found. Please convert manually:")
|
||||||
|
print(f" ffmpeg -i {input_path} -ar 8000 -ac 1 -f u8 -acodec pcm_u8 {raw_path}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print(f" Converting {os.path.basename(input_path)} to 8kHz/8bit PCM...")
|
||||||
|
subprocess.run([
|
||||||
|
'ffmpeg', '-y', '-i', input_path,
|
||||||
|
'-ar', '8000', '-ac', '1', '-f', 'u8', '-acodec', 'pcm_u8',
|
||||||
|
raw_path
|
||||||
|
], capture_output=True)
|
||||||
|
|
||||||
|
return raw_path
|
||||||
|
|
||||||
|
|
||||||
|
def build_track_table(tracks):
|
||||||
|
"""Build the track index (stored in sector 0 of flash).
|
||||||
|
|
||||||
|
Format:
|
||||||
|
byte 0: num_tracks (uint8)
|
||||||
|
bytes 1-3: padding
|
||||||
|
bytes 4+: track_start[MAX_TRACKS] as uint32 big-endian
|
||||||
|
then: track_length[MAX_TRACKS] as uint32 big-endian
|
||||||
|
"""
|
||||||
|
num = len(tracks)
|
||||||
|
table = struct.pack('B', num) + b'\x00' * 3
|
||||||
|
|
||||||
|
# Start addresses
|
||||||
|
for start, length in tracks:
|
||||||
|
table += struct.pack('>I', start)
|
||||||
|
for _ in range(MAX_TRACKS - num):
|
||||||
|
table += struct.pack('>I', 0)
|
||||||
|
|
||||||
|
# Lengths
|
||||||
|
for start, length in tracks:
|
||||||
|
table += struct.pack('>I', length)
|
||||||
|
for _ in range(MAX_TRACKS - num):
|
||||||
|
table += struct.pack('>I', 0)
|
||||||
|
|
||||||
|
# Pad to sector size
|
||||||
|
table += b'\xFF' * (SECTOR_SIZE - len(table))
|
||||||
|
return table
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print("Usage: python3 flash_upload.py <serial_port> <audio_file> [audio_file ...]")
|
||||||
|
print()
|
||||||
|
print("Supported input formats: .raw (8kHz/8bit/unsigned), .mp3, .wav, .ogg, .flac")
|
||||||
|
print("Non-.raw files will be converted automatically using ffmpeg.")
|
||||||
|
print()
|
||||||
|
print("Example:")
|
||||||
|
print(" python3 flash_upload.py /dev/ttyUSB0 lullaby.mp3 twinkle.wav brahms.mp3")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
port = sys.argv[1]
|
||||||
|
audio_files = sys.argv[2:]
|
||||||
|
|
||||||
|
if len(audio_files) > MAX_TRACKS:
|
||||||
|
print(f"ERROR: Maximum {MAX_TRACKS} tracks supported.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Convert files to raw PCM
|
||||||
|
print("=== Preparing audio files ===")
|
||||||
|
raw_files = []
|
||||||
|
for f in audio_files:
|
||||||
|
raw = convert_to_raw(f)
|
||||||
|
size = os.path.getsize(raw)
|
||||||
|
duration = size / 8000
|
||||||
|
print(f" {os.path.basename(f)}: {size} bytes ({duration:.1f} seconds)")
|
||||||
|
raw_files.append(raw)
|
||||||
|
|
||||||
|
# Check total size
|
||||||
|
total_audio = sum(os.path.getsize(f) for f in raw_files)
|
||||||
|
available = FLASH_SIZE - AUDIO_START
|
||||||
|
if total_audio > available:
|
||||||
|
print(f"ERROR: Audio ({total_audio} bytes) exceeds flash capacity ({available} bytes)")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
total_duration = total_audio / 8000
|
||||||
|
print(f"\n Total: {total_audio} bytes ({total_duration:.1f} seconds / {total_duration/60:.1f} minutes)")
|
||||||
|
print(f" Flash usage: {(total_audio + AUDIO_START) * 100 // FLASH_SIZE}%")
|
||||||
|
|
||||||
|
# Connect
|
||||||
|
print(f"\n=== Connecting to {port} ===")
|
||||||
|
ser = open_serial(port)
|
||||||
|
flash_identify(ser)
|
||||||
|
|
||||||
|
# Erase
|
||||||
|
print("\n=== Erasing flash ===")
|
||||||
|
flash_erase(ser)
|
||||||
|
|
||||||
|
# Write audio data and build track list
|
||||||
|
print("\n=== Writing audio ===")
|
||||||
|
tracks = []
|
||||||
|
addr = AUDIO_START
|
||||||
|
|
||||||
|
for i, raw_path in enumerate(raw_files):
|
||||||
|
with open(raw_path, 'rb') as f:
|
||||||
|
data = f.read()
|
||||||
|
|
||||||
|
start = addr
|
||||||
|
length = len(data)
|
||||||
|
tracks.append((start, length))
|
||||||
|
|
||||||
|
name = os.path.basename(audio_files[i])
|
||||||
|
addr = flash_write_data(ser, start, data, label=f"Track {i+1} ({name})")
|
||||||
|
|
||||||
|
# Align to sector boundary for clean layout
|
||||||
|
if addr % SECTOR_SIZE != 0:
|
||||||
|
addr = ((addr // SECTOR_SIZE) + 1) * SECTOR_SIZE
|
||||||
|
|
||||||
|
# Write track table to sector 0
|
||||||
|
print("\n=== Writing track table ===")
|
||||||
|
table = build_track_table(tracks)
|
||||||
|
flash_write_data(ser, 0, table, label="Track table")
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
print("\n=== Upload complete! ===")
|
||||||
|
print(f" {len(tracks)} tracks written")
|
||||||
|
for i, (start, length) in enumerate(tracks):
|
||||||
|
print(f" Track {i+1}: addr=0x{start:06X}, {length} bytes ({length/8000:.1f}s)")
|
||||||
|
print(f"\n Reset the board to start playback.")
|
||||||
|
|
||||||
|
# Cleanup temp files
|
||||||
|
for raw, orig in zip(raw_files, audio_files):
|
||||||
|
if raw != orig and os.path.exists(raw):
|
||||||
|
os.remove(raw)
|
||||||
|
|
||||||
|
ser.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,614 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Generate KiCad 7 schematic and project files for Baby Mobile Audio Board.
|
||||||
|
|
||||||
|
Design: ATmega328P + W25Q128 SPI Flash + PAM8302A Class-D Amp + MOSFET motor driver
|
||||||
|
Power: 2x AA batteries (1.8V-3.3V), optimized for long runtime
|
||||||
|
Audio: 30+ min at 8kHz/8-bit mono via 16MB SPI flash
|
||||||
|
"""
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
|
||||||
|
def uid():
|
||||||
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# SCHEMATIC GENERATION
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
def generate_schematic():
|
||||||
|
"""Generate the complete .kicad_sch file."""
|
||||||
|
|
||||||
|
# We use net labels for connections instead of routing every wire.
|
||||||
|
# This keeps the schematic clean and KiCad resolves connectivity by label name.
|
||||||
|
|
||||||
|
sch = []
|
||||||
|
sch.append(f"""(kicad_sch (version 20230121) (generator "custom_generator")
|
||||||
|
|
||||||
|
(uuid "{uid()}")
|
||||||
|
(paper "A3")
|
||||||
|
|
||||||
|
(title_block
|
||||||
|
(title "Baby Mobile Audio Board")
|
||||||
|
(date "2026-03-08")
|
||||||
|
(rev "1.0")
|
||||||
|
(comment 1 "ATmega328P + W25Q128 + PAM8302A")
|
||||||
|
(comment 2 "2xAA Battery Powered - Long Runtime Design")
|
||||||
|
(comment 3 "8-ohm 0.25W Speaker, DC Motor, 8 Buttons")
|
||||||
|
(comment 4 "Arduino Compatible (8MHz Internal Osc)")
|
||||||
|
)
|
||||||
|
""")
|
||||||
|
|
||||||
|
# ---- LIB_SYMBOLS ----
|
||||||
|
sch.append(" (lib_symbols")
|
||||||
|
sch.append(_sym_atmega328p())
|
||||||
|
sch.append(_sym_w25q128())
|
||||||
|
sch.append(_sym_pam8302a())
|
||||||
|
sch.append(_sym_nmos())
|
||||||
|
sch.append(_sym_capacitor())
|
||||||
|
sch.append(_sym_resistor())
|
||||||
|
sch.append(_sym_diode_schottky())
|
||||||
|
sch.append(_sym_inductor())
|
||||||
|
sch.append(_sym_switch())
|
||||||
|
sch.append(_sym_conn2())
|
||||||
|
sch.append(_sym_conn3())
|
||||||
|
sch.append(_sym_conn6())
|
||||||
|
sch.append(_sym_led())
|
||||||
|
sch.append(_sym_pwr_flag())
|
||||||
|
sch.append(" )") # end lib_symbols
|
||||||
|
|
||||||
|
# ---- COMPONENT INSTANCES ----
|
||||||
|
# Layout regions (KiCad uses mm, origin top-left):
|
||||||
|
# Power supply section: x=30, y=30
|
||||||
|
# MCU (ATmega328P): x=130, y=90
|
||||||
|
# SPI Flash (W25Q128): x=230, y=60
|
||||||
|
# Audio section (PAM8302A): x=230, y=140
|
||||||
|
# Motor driver: x=130, y=190
|
||||||
|
# Buttons (8x): x=30, y=80-180
|
||||||
|
# ISP Header: x=230, y=200
|
||||||
|
# Serial Header: x=30, y=200
|
||||||
|
|
||||||
|
# ---- POWER SUPPLY SECTION ----
|
||||||
|
# Battery connector J1
|
||||||
|
sch.append(_instance("baby_mobile:Conn_2Pin", "J1", "BATTERY", "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal",
|
||||||
|
25, 35, 0))
|
||||||
|
# Main decoupling C1: 100uF electrolytic
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C1", "100uF", "Capacitor_THT:CP_Radial_D5.0mm_P2.00mm",
|
||||||
|
55, 35, 0))
|
||||||
|
# Decoupling C2: 100nF ceramic near MCU VCC
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C2", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
||||||
|
100, 30, 0))
|
||||||
|
# Decoupling C3: 100nF ceramic near MCU AVCC
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C3", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
||||||
|
115, 30, 0))
|
||||||
|
# Power switch SW_PWR
|
||||||
|
sch.append(_instance("baby_mobile:Switch", "SW9", "PWR", "Button_Switch_THT:SW_SPDT_CK-JS102011SAQN",
|
||||||
|
40, 25, 0))
|
||||||
|
|
||||||
|
# ---- MCU: ATmega328P-AU ----
|
||||||
|
sch.append(_instance("baby_mobile:ATmega328P-AU", "U1", "ATmega328P-AU", "Package_QFP:TQFP-32_7x7mm_P0.8mm",
|
||||||
|
130, 90, 0))
|
||||||
|
# Reset pullup R_RST: 10K
|
||||||
|
sch.append(_instance("baby_mobile:Resistor", "R1", "10K", "Resistor_SMD:R_0805_2012Metric",
|
||||||
|
95, 55, 0))
|
||||||
|
# Reset capacitor C_RST: 100nF
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C4", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
||||||
|
95, 65, 0))
|
||||||
|
|
||||||
|
# ---- SPI FLASH: W25Q128JVSIQ ----
|
||||||
|
sch.append(_instance("baby_mobile:W25Q128", "U2", "W25Q128JVSIQ", "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",
|
||||||
|
230, 60, 0))
|
||||||
|
# Flash decoupling C5: 100nF
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C5", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
||||||
|
255, 50, 0))
|
||||||
|
|
||||||
|
# ---- AUDIO AMP: PAM8302A ----
|
||||||
|
sch.append(_instance("baby_mobile:PAM8302A", "U3", "PAM8302A", "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",
|
||||||
|
230, 140, 0))
|
||||||
|
# Input coupling cap C6: 1uF
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C6", "1uF", "Capacitor_SMD:C_0805_2012Metric",
|
||||||
|
200, 135, 0))
|
||||||
|
# RC low-pass filter on PWM: R_LPF + C_LPF
|
||||||
|
# f_c = 1/(2*pi*R*C) ~ 3.4kHz with 4.7K + 10nF
|
||||||
|
sch.append(_instance("baby_mobile:Resistor", "R2", "4.7K", "Resistor_SMD:R_0805_2012Metric",
|
||||||
|
185, 135, 0))
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C7", "10nF", "Capacitor_SMD:C_0805_2012Metric",
|
||||||
|
192, 145, 0))
|
||||||
|
# Amp supply bypass C8: 10uF
|
||||||
|
sch.append(_instance("baby_mobile:Capacitor", "C8", "10uF", "Capacitor_SMD:C_0805_2012Metric",
|
||||||
|
255, 130, 0))
|
||||||
|
# Speaker connector J2
|
||||||
|
sch.append(_instance("baby_mobile:Conn_2Pin", "J2", "SPEAKER", "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal",
|
||||||
|
265, 145, 0))
|
||||||
|
# Shutdown pulldown R_SD: 100K (default ON, MCU can shut down)
|
||||||
|
sch.append(_instance("baby_mobile:Resistor", "R3", "100K", "Resistor_SMD:R_0805_2012Metric",
|
||||||
|
210, 150, 0))
|
||||||
|
|
||||||
|
# ---- MOTOR DRIVER ----
|
||||||
|
# N-ch MOSFET Q1
|
||||||
|
sch.append(_instance("baby_mobile:NMOS", "Q1", "AO3400A", "Package_TO_SOT_SMD:SOT-23",
|
||||||
|
140, 190, 0))
|
||||||
|
# Gate resistor R_GATE: 100 ohm
|
||||||
|
sch.append(_instance("baby_mobile:Resistor", "R4", "100R", "Resistor_SMD:R_0805_2012Metric",
|
||||||
|
120, 190, 0))
|
||||||
|
# Gate pulldown R_GPD: 100K
|
||||||
|
sch.append(_instance("baby_mobile:Resistor", "R5", "100K", "Resistor_SMD:R_0805_2012Metric",
|
||||||
|
130, 200, 0))
|
||||||
|
# Flyback diode D1
|
||||||
|
sch.append(_instance("baby_mobile:Diode_Schottky", "D1", "SS14", "Diode_SMD:D_SMA",
|
||||||
|
155, 180, 90))
|
||||||
|
# Motor connector J3
|
||||||
|
sch.append(_instance("baby_mobile:Conn_2Pin", "J3", "MOTOR", "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal",
|
||||||
|
160, 170, 0))
|
||||||
|
|
||||||
|
# ---- 8 BUTTONS ----
|
||||||
|
button_pins = ["BTN1", "BTN2", "BTN3", "BTN4", "BTN5", "BTN6", "BTN7", "BTN8"]
|
||||||
|
for i, name in enumerate(button_pins):
|
||||||
|
y = 75 + i * 15
|
||||||
|
sch.append(_instance("baby_mobile:Switch", f"SW{i+1}", name, "Button_Switch_SMD:SW_SPST_TL3342",
|
||||||
|
30, y, 0))
|
||||||
|
|
||||||
|
# ---- STATUS LED ----
|
||||||
|
sch.append(_instance("baby_mobile:LED", "D2", "LED", "LED_SMD:LED_0805_2012Metric",
|
||||||
|
85, 190, 0))
|
||||||
|
sch.append(_instance("baby_mobile:Resistor", "R6", "1K", "Resistor_SMD:R_0805_2012Metric",
|
||||||
|
75, 190, 0))
|
||||||
|
|
||||||
|
# ---- ISP HEADER (2x3) ----
|
||||||
|
sch.append(_instance("baby_mobile:Conn_6Pin", "J4", "ISP", "Connector_PinHeader_2.54mm:PinHeader_2x03_P2.54mm_Vertical",
|
||||||
|
250, 200, 0))
|
||||||
|
|
||||||
|
# ---- SERIAL HEADER (3-pin: GND, TX, RX) ----
|
||||||
|
sch.append(_instance("baby_mobile:Conn_3Pin", "J5", "SERIAL", "Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical",
|
||||||
|
30, 210, 0))
|
||||||
|
|
||||||
|
# ---- NET LABELS ----
|
||||||
|
# Power nets
|
||||||
|
net_labels = [
|
||||||
|
# Power distribution
|
||||||
|
("VCC", 55, 25), ("VCC", 100, 25), ("VCC", 115, 25),
|
||||||
|
("VCC", 130, 50), ("VCC", 255, 45), ("VCC", 255, 125),
|
||||||
|
("VCC", 95, 50), ("VCC", 160, 165),
|
||||||
|
("GND", 55, 45), ("GND", 100, 40), ("GND", 115, 40),
|
||||||
|
("GND", 130, 130), ("GND", 255, 70), ("GND", 255, 155),
|
||||||
|
("GND", 95, 70), ("GND", 140, 205), ("GND", 192, 155),
|
||||||
|
|
||||||
|
# SPI bus
|
||||||
|
("SPI_MOSI", 165, 85), ("SPI_MOSI", 215, 55),
|
||||||
|
("SPI_MISO", 165, 90), ("SPI_MISO", 215, 60),
|
||||||
|
("SPI_SCK", 165, 95), ("SPI_SCK", 215, 65),
|
||||||
|
("FLASH_CS", 165, 80), ("FLASH_CS", 215, 50),
|
||||||
|
|
||||||
|
# Audio
|
||||||
|
("AUDIO_PWM", 165, 100), ("AUDIO_PWM", 175, 135),
|
||||||
|
("AMP_SD", 165, 105), ("AMP_SD", 210, 145),
|
||||||
|
|
||||||
|
# Motor
|
||||||
|
("MOTOR_PWM", 165, 110), ("MOTOR_PWM", 110, 190),
|
||||||
|
|
||||||
|
# Buttons (directly named for MCU pins mapping)
|
||||||
|
("BTN1", 45, 75), ("BTN1", 95, 85),
|
||||||
|
("BTN2", 45, 90), ("BTN2", 95, 90),
|
||||||
|
("BTN3", 45, 105), ("BTN3", 95, 95),
|
||||||
|
("BTN4", 45, 120), ("BTN4", 95, 100),
|
||||||
|
("BTN5", 45, 135), ("BTN5", 95, 105),
|
||||||
|
("BTN6", 45, 150), ("BTN6", 95, 110),
|
||||||
|
("BTN7", 45, 165), ("BTN7", 95, 115),
|
||||||
|
("BTN8", 45, 180), ("BTN8", 95, 120),
|
||||||
|
|
||||||
|
# ISP
|
||||||
|
("SPI_MOSI", 240, 195), ("SPI_MISO", 240, 200),
|
||||||
|
("SPI_SCK", 240, 205), ("RESET", 240, 210),
|
||||||
|
("RESET", 95, 60),
|
||||||
|
|
||||||
|
# Serial
|
||||||
|
("TXD", 40, 210), ("RXD", 40, 215),
|
||||||
|
("TXD", 95, 75), ("RXD", 95, 80),
|
||||||
|
|
||||||
|
# LED
|
||||||
|
("LED_OUT", 65, 190), ("LED_OUT", 95, 125),
|
||||||
|
]
|
||||||
|
|
||||||
|
for name, x, y in net_labels:
|
||||||
|
sch.append(f""" (label "{name}" (at {x} {y} 0) (effects (font (size 1.27 1.27))) (uuid "{uid()}"))""")
|
||||||
|
|
||||||
|
# ---- TEXT NOTES ----
|
||||||
|
notes = [
|
||||||
|
(15, 15, "POWER: 2xAA (1.8V-3.3V) → Long runtime design"),
|
||||||
|
(15, 18, "MCU: ATmega328P-AU @ 8MHz internal osc, Arduino compatible"),
|
||||||
|
(200, 15, "FLASH: W25Q128 16MB = ~33 min @ 8kHz 8-bit PCM"),
|
||||||
|
(200, 18, "AMP: PAM8302A Class-D, 90% efficient, Vmin=2.0V"),
|
||||||
|
(15, 220, "BUTTONS: Internal pull-ups, active LOW, PCINT wake-from-sleep"),
|
||||||
|
(120, 220, "MOTOR: AO3400A logic-level N-MOSFET, PWM speed control"),
|
||||||
|
(15, 225, "ESTIMATED RUNTIME: Audio+Motor ~23h, Audio only ~200h, Sleep ~years"),
|
||||||
|
]
|
||||||
|
for x, y, text in notes:
|
||||||
|
sch.append(f""" (text "{text}" (at {x} {y} 0)
|
||||||
|
(effects (font (size 1.5 1.5)) (justify left))
|
||||||
|
(uuid "{uid()}")
|
||||||
|
)""")
|
||||||
|
|
||||||
|
sch.append(")") # end kicad_sch
|
||||||
|
return "\n".join(sch)
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# SYMBOL DEFINITIONS
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
def _sym_atmega328p():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:ATmega328P-AU" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "U" (at 0 26 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "ATmega328P-AU" (at 0 24 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_QFP:TQFP-32_7x7mm_P0.8mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:ATmega328P-AU_0_1"
|
||||||
|
(rectangle (start -17 23) (end 17 -23) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:ATmega328P-AU_1_1"
|
||||||
|
(pin power_in line (at -7 -26 90) (length 3) (name "GND" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -5 -26 90) (length 3) (name "GND2" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -3 26 270) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -1 26 270) (length 3) (name "AVCC" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 1 26 270) (length 3) (name "AREF" (effects (font (size 1 1)))) (number "21" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 15 0) (length 3) (name "PD0/RXD" (effects (font (size 1 1)))) (number "30" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 12.5 0) (length 3) (name "PD1/TXD" (effects (font (size 1 1)))) (number "31" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 10 0) (length 3) (name "PD2/INT0" (effects (font (size 1 1)))) (number "32" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 7.5 0) (length 3) (name "PD3/INT1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 5 0) (length 3) (name "PD4" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 2.5 0) (length 3) (name "PD5/OC0B" (effects (font (size 1 1)))) (number "9" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 0 0) (length 3) (name "PD6/OC0A" (effects (font (size 1 1)))) (number "10" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at -20 -2.5 0) (length 3) (name "PD7" (effects (font (size 1 1)))) (number "11" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 15 180) (length 3) (name "PB0" (effects (font (size 1 1)))) (number "12" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 12.5 180) (length 3) (name "PB1/OC1A" (effects (font (size 1 1)))) (number "13" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 10 180) (length 3) (name "PB2/SS" (effects (font (size 1 1)))) (number "14" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 7.5 180) (length 3) (name "PB3/MOSI" (effects (font (size 1 1)))) (number "15" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 5 180) (length 3) (name "PB4/MISO" (effects (font (size 1 1)))) (number "16" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 2.5 180) (length 3) (name "PB5/SCK" (effects (font (size 1 1)))) (number "17" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -2.5 180) (length 3) (name "PC0/ADC0" (effects (font (size 1 1)))) (number "23" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -5 180) (length 3) (name "PC1/ADC1" (effects (font (size 1 1)))) (number "24" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -7.5 180) (length 3) (name "PC2/ADC2" (effects (font (size 1 1)))) (number "25" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -10 180) (length 3) (name "PC3/ADC3" (effects (font (size 1 1)))) (number "26" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -12.5 180) (length 3) (name "PC4/SDA" (effects (font (size 1 1)))) (number "27" (effects (font (size 1 1)))))
|
||||||
|
(pin bidirectional line (at 20 -15 180) (length 3) (name "PC5/SCL" (effects (font (size 1 1)))) (number "28" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -20 -10 0) (length 3) (name "~{{RESET}}" (effects (font (size 1 1)))) (number "29" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -20 -15 0) (length 3) (name "XTAL1" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at -20 -17.5 0) (length 3) (name "XTAL2" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_w25q128():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:W25Q128" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "U" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "W25Q128JVSIQ" (at 0 7 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:W25Q128_0_1"
|
||||||
|
(rectangle (start -7 6) (end 7 -6) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:W25Q128_1_1"
|
||||||
|
(pin input line (at -10 4 0) (length 3) (name "~{{CS}}" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at -10 1.5 0) (length 3) (name "DO/IO1" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -10 -1.5 0) (length 3) (name "~{{WP}}/IO2" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -10 -4 0) (length 3) (name "GND" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at 10 -4 180) (length 3) (name "DI/IO0" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at 10 -1.5 180) (length 3) (name "CLK" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at 10 1.5 180) (length 3) (name "~{{HOLD}}/IO3" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at 10 4 180) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_pam8302a():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:PAM8302A" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "U" (at 0 11 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "PAM8302A" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:PAM8302A_0_1"
|
||||||
|
(rectangle (start -8 8) (end 8 -8) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:PAM8302A_1_1"
|
||||||
|
(pin input line (at -11 5 0) (length 3) (name "~{{SD}}" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -11 2 0) (length 3) (name "VDD" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at -11 -1 0) (length 3) (name "GND" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -11 -4 0) (length 3) (name "A+" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -11 -7 0) (length 3) (name "A-" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at 11 2 180) (length 3) (name "VO+" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
||||||
|
(pin output line (at 11 -1 180) (length 3) (name "VO-" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
||||||
|
(pin power_in line (at 11 -4 180) (length 3) (name "PAD" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_nmos():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:NMOS" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "Q" (at 3 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "AO3400A" (at 5 -2.5 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Package_TO_SOT_SMD:SOT-23" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:NMOS_0_1"
|
||||||
|
(polyline (pts (xy -0.5 0.5) (xy -0.5 -0.5)) (stroke (width 0.33) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -0.5 -2) (xy -0.5 2)) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy 0 -2.5) (xy 0 -1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy 0 1.5) (xy 0 2.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy 0 0) (xy -1.5 0)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:NMOS_1_1"
|
||||||
|
(pin passive line (at 0 5 270) (length 2.5) (name "D" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin input line (at -4 0 0) (length 2.5) (name "G" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -5 90) (length 2.5) (name "S" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_capacitor():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Capacitor" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "C" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "C" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Capacitor_0_1"
|
||||||
|
(polyline (pts (xy -1.5 1) (xy 1.5 1)) (stroke (width 0.4) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.4) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Capacitor_1_1"
|
||||||
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_resistor():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Resistor" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "R" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "R" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Resistor_0_1"
|
||||||
|
(rectangle (start -1 2.5) (end 1 -2.5) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Resistor_1_1"
|
||||||
|
(pin passive line (at 0 5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_diode_schottky():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Diode_Schottky" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "D" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "SS14" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "Diode_SMD:D_SMA" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Diode_Schottky_0_1"
|
||||||
|
(polyline (pts (xy -1.5 1) (xy 0 -1) (xy 1.5 1) (xy -1.5 1)) (stroke (width 0.2) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.3) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Diode_Schottky_1_1"
|
||||||
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "A" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "K" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_inductor():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Inductor" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "L" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "L" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Inductor_0_1"
|
||||||
|
(arc (start 0 2.5) (mid 0.75 1.875) (end 0 1.25) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(arc (start 0 1.25) (mid 0.75 0.625) (end 0 0) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(arc (start 0 0) (mid 0.75 -0.625) (end 0 -1.25) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
(arc (start 0 -1.25) (mid 0.75 -1.875) (end 0 -2.5) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Inductor_1_1"
|
||||||
|
(pin passive line (at 0 5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_switch():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Switch" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "SW" (at 0 3 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "SW" (at 0 -3 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Switch_0_1"
|
||||||
|
(circle (center -2 0) (radius 0.4) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(circle (center 2 0) (radius 0.4) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.6 0) (xy 1.6 1)) (stroke (width 0.254) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Switch_1_1"
|
||||||
|
(pin passive line (at -5 0 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 5 0 180) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_conn2():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Conn_2Pin" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "J" (at 0 4 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "Conn_2" (at 0 -4 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Conn_2Pin_0_1"
|
||||||
|
(rectangle (start -2 3) (end 2 -3) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Conn_2Pin_1_1"
|
||||||
|
(pin passive line (at -5 1.5 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -5 -1.5 0) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_conn3():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Conn_3Pin" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "J" (at 0 5.5 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "Conn_3" (at 0 -5.5 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Conn_3Pin_0_1"
|
||||||
|
(rectangle (start -2 4) (end 2 -4) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Conn_3Pin_1_1"
|
||||||
|
(pin passive line (at -5 2.5 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -5 0 0) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -5 -2.5 0) (length 3) (name "3" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_conn6():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:Conn_6Pin" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "J" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "ISP_2x3" (at 0 -9 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:Conn_6Pin_0_1"
|
||||||
|
(rectangle (start -3 8) (end 3 -8) (stroke (width 0.254) (type default)) (fill (type background)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:Conn_6Pin_1_1"
|
||||||
|
(pin passive line (at -6 5 0) (length 3) (name "MISO" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 6 5 180) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -6 0 0) (length 3) (name "SCK" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 6 0 180) (length 3) (name "MOSI" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at -6 -5 0) (length 3) (name "~{{RST}}" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 6 -5 180) (length 3) (name "GND" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_led():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:LED" (in_bom yes) (on_board yes)
|
||||||
|
(property "Reference" "D" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "LED" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:LED_0_1"
|
||||||
|
(polyline (pts (xy -1.5 1) (xy 0 -1) (xy 1.5 1) (xy -1.5 1)) (stroke (width 0.2) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.3) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:LED_1_1"
|
||||||
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "A" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "K" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
def _sym_pwr_flag():
|
||||||
|
return f"""
|
||||||
|
(symbol "baby_mobile:PWR_FLAG" (power) (in_bom no) (on_board no)
|
||||||
|
(property "Reference" "#FLG" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Value" "PWR_FLAG" (at 0 3 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(symbol "baby_mobile:PWR_FLAG_0_1"
|
||||||
|
(polyline (pts (xy 0 0) (xy 0 1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
(polyline (pts (xy -1 1.5) (xy 0 3) (xy 1 1.5) (xy -1 1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
||||||
|
)
|
||||||
|
(symbol "baby_mobile:PWR_FLAG_1_1"
|
||||||
|
(pin power_out line (at 0 0 90) (length 0) (name "pwr" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
||||||
|
)
|
||||||
|
)"""
|
||||||
|
|
||||||
|
|
||||||
|
def _instance(lib_id, ref, value, footprint, x, y, angle):
|
||||||
|
"""Generate a component instance."""
|
||||||
|
return f""" (symbol (lib_id "{lib_id}") (at {x} {y} {angle}) (unit 1)
|
||||||
|
(in_bom yes) (on_board yes) (dnp no)
|
||||||
|
(uuid "{uid()}")
|
||||||
|
(property "Reference" "{ref}" (at {x} {y-3} 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Value" "{value}" (at {x} {y+3} 0) (effects (font (size 1.27 1.27))))
|
||||||
|
(property "Footprint" "{footprint}" (at {x} {y} 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
(property "Datasheet" "" (at {x} {y} 0) (effects (font (size 1.27 1.27)) hide))
|
||||||
|
)"""
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# PROJECT FILE
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
def generate_project():
|
||||||
|
return json.dumps({
|
||||||
|
"meta": {
|
||||||
|
"filename": "baby-mobile.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"board": {
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"board_outline_line_width": 0.1,
|
||||||
|
"copper_line_width": 0.2,
|
||||||
|
"copper_text_size_h": 1.5,
|
||||||
|
"copper_text_size_v": 1.5,
|
||||||
|
"other_line_width": 0.15
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"min_copper_edge_clearance": 0.3,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_track_width": 0.2,
|
||||||
|
"min_via_annular_width": 0.13,
|
||||||
|
"min_via_diameter": 0.6,
|
||||||
|
"solder_mask_to_copper_clearance": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"layer_presets": []
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.3,
|
||||||
|
"via_diameter": 0.6,
|
||||||
|
"via_drill": 0.3,
|
||||||
|
"wire_width": 6
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": []
|
||||||
|
},
|
||||||
|
"sheets": [["", ""]]
|
||||||
|
}, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================
|
||||||
|
# MAIN
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
outdir = "/home/claude/baby-mobile-pcb"
|
||||||
|
|
||||||
|
# Generate schematic
|
||||||
|
sch = generate_schematic()
|
||||||
|
with open(os.path.join(outdir, "baby-mobile.kicad_sch"), "w") as f:
|
||||||
|
f.write(sch)
|
||||||
|
print(f"Written: baby-mobile.kicad_sch ({len(sch)} bytes)")
|
||||||
|
|
||||||
|
# Generate project file
|
||||||
|
proj = generate_project()
|
||||||
|
with open(os.path.join(outdir, "baby-mobile.kicad_pro"), "w") as f:
|
||||||
|
f.write(proj)
|
||||||
|
print(f"Written: baby-mobile.kicad_pro ({len(proj)} bytes)")
|
||||||
|
|
||||||
|
print("Done! Open baby-mobile.kicad_pro in KiCad 7+")
|
||||||
Reference in New Issue
Block a user