From 8cba579780baf51c91020b2e7bd8994317f08a12 Mon Sep 17 00:00:00 2001 From: zyphlar Date: Sat, 4 Jul 2026 03:28:14 -0700 Subject: [PATCH] fixed most upload issues, updated schematic --- app/app.js | 138 ++- app/ble.js | 56 +- app/index.html | 17 +- app/styles.css | 15 +- app/sw.js | 2 +- app/wav.js | 25 +- baby-mobile-v5.kicad_pcb | 1516 ++++++++++++++--------------- baby-mobile-v5.kicad_sch | 298 ++++-- baby_mobile_v2/baby_mobile_v2.ino | 212 +++- upload_track.py | 46 +- 10 files changed, 1305 insertions(+), 1020 deletions(-) diff --git a/app/app.js b/app/app.js index deb009b..5cbf849 100644 --- a/app/app.js +++ b/app/app.js @@ -1,6 +1,6 @@ // app.js — UI glue for the BabyMobile manager PWA. import { BabyMobile, isSupported, MAX_TRACKS } from './ble.js'; -import { fileToWav, RATES, BITS } from './wav.js'; +import { decodeFileToMono, encodeWav, trimSamples, RATES, BITS } from './wav.js'; const $ = (id) => document.getElementById(id); const dev = new BabyMobile(); @@ -12,6 +12,8 @@ let slots = loadSlots(); let pendingWav = null; // { wav, durationSec, rate, bits, name } let deviceTracks = null; // last result of dev.listTracks(), or null +let currentFile = null; // the picked File +let decoded = null; // { samples, rate, srcRate } cached decode of currentFile function loadSlots() { try { return JSON.parse(localStorage.getItem(SLOTS_KEY)) || {}; } @@ -67,35 +69,93 @@ $('drop').addEventListener('drop', (e) => { }); fileInput.addEventListener('change', () => { if (fileInput.files.length) handleFile(fileInput.files[0]); }); +// Decode the file (expensive) once per file/rate, then re-encode cheaply when +// the user tweaks bit-depth or trim. async function handleFile(file) { - const rate = parseInt($('rate').value, 10); - const bits = parseInt($('bits').value, 10); - $('convert-info').textContent = `Converting "${file.name}"…`; + stopPreview(); + currentFile = file; + decoded = null; pendingWav = null; $('btn-upload').disabled = true; + $('btn-preview').disabled = true; + $('trim').hidden = true; + $('convert-info').textContent = `Decoding "${file.name}"…`; try { - const res = await fileToWav(file, { rate, bits }); - pendingWav = { ...res, name: file.name }; - const sec = res.durationSec.toFixed(1); - $('convert-info').innerHTML = - `${file.name} → ${bits}-bit ${rate / 1000} kHz mono
` + - `${sec}s · ${fmtBytes(res.wav.byteLength)} (incl. 44-byte WAV header)`; - $('btn-upload').disabled = !dev.connected; + const rate = parseInt($('rate').value, 10); + decoded = await decodeFileToMono(file, rate); + $('trim-start').value = '0'; + $('trim-end').value = '0'; + $('trim').hidden = false; + reEncode(); } catch (err) { $('convert-info').textContent = 'Could not decode this file: ' + (err.message || err) + '. Try a WAV/MP3/M4A the browser can decode.'; } } -// Re-convert if the format options change while a file is staged. -['rate', 'bits'].forEach((id) => $(id).addEventListener('change', () => { - if (fileInput.files.length) handleFile(fileInput.files[0]); -})); +function trimValues() { + return { + trimStart: Math.max(0, parseFloat($('trim-start').value) || 0), + trimEnd: Math.max(0, parseFloat($('trim-end').value) || 0), + }; +} + +// Re-encode the staged WAV from the cached decode (no re-decode). +function reEncode() { + if (!decoded || !currentFile) return; + const bits = parseInt($('bits').value, 10); + const { trimStart, trimEnd } = trimValues(); + const fullDur = decoded.samples.length / decoded.rate; + const { wav, durationSec } = encodeWav(decoded.samples, decoded.rate, bits, { trimStart, trimEnd }); + pendingWav = { wav, durationSec, rate: decoded.rate, bits, name: currentFile.name }; + + const trimmed = (trimStart || trimEnd) ? ` (trimmed from ${fullDur.toFixed(1)}s)` : ''; + $('convert-info').innerHTML = + `${currentFile.name} → ${bits}-bit ${decoded.rate / 1000} kHz mono
` + + `${durationSec.toFixed(1)}s${trimmed} · ${fmtBytes(wav.byteLength)} (incl. 44-byte WAV header)`; + $('btn-upload').disabled = !dev.connected || durationSec <= 0; + $('btn-preview').disabled = durationSec <= 0; +} + +// Changing the rate needs a fresh decode; bits/trim only need a re-encode. +$('rate').addEventListener('change', () => { if (currentFile) handleFile(currentFile); }); +['bits', 'trim-start', 'trim-end'].forEach((id) => $(id).addEventListener('input', () => { stopPreview(); reEncode(); })); + +// ---- local preview of the trimmed clip ---- +let previewCtx = null; +let previewSrc = null; +function stopPreview() { + if (previewSrc) { try { previewSrc.stop(); } catch {} previewSrc = null; } + if (previewCtx) { try { previewCtx.close(); } catch {} previewCtx = null; } + $('btn-preview').textContent = '▶ Preview'; +} +$('btn-preview').addEventListener('click', () => { + if (previewSrc) { stopPreview(); return; } + if (!decoded) return; + const { trimStart, trimEnd } = trimValues(); + const slice = trimSamples(decoded.samples, decoded.rate, trimStart, trimEnd); + if (!slice.length) return; + const AC = window.AudioContext || window.webkitAudioContext; + previewCtx = new AC(); + const buf = previewCtx.createBuffer(1, slice.length, decoded.rate); + buf.getChannelData(0).set(slice); + previewSrc = previewCtx.createBufferSource(); + previewSrc.buffer = buf; + previewSrc.connect(previewCtx.destination); + previewSrc.onended = stopPreview; + previewSrc.start(); + $('btn-preview').textContent = '⏹ Stop'; +}); // ---- upload ---- $('btn-upload').addEventListener('click', async () => { if (!pendingWav) return; const track = parseInt($('upload-slot').value, 10); + if (occupiedSlots().has(track)) { + const name = slots[track]?.name; + if (!confirm(`Slot ${track} already holds ${name ? `"${name}"` : 'a track'}. Overwrite it?`)) return; + } + stopPreview(); $('btn-upload').disabled = true; const bar = $('upload-bar'); bar.style.width = '0%'; @@ -120,10 +180,6 @@ $('btn-upload').addEventListener('click', async () => { } }); -// ---- playback ---- -$('btn-play').addEventListener('click', () => dev.play(parseInt($('play-slot').value, 10)).catch((e) => log('' + e))); -$('btn-stop').addEventListener('click', () => dev.stop().catch((e) => log('' + e))); - // ---- track list ---- $('btn-refresh').addEventListener('click', () => refresh()); @@ -138,8 +194,10 @@ async function refresh() { } } -async function onDelete(idx, onDevice) { +async function onDelete(idx, onDevice, name) { + const label = name ? `"${name}"` : `the track in slot ${idx}`; if (onDevice) { + if (!confirm(`Delete ${label} from the device? This can't be undone.`)) return; try { const r = await dev.deleteTrack(idx); if (r.success) { @@ -153,6 +211,7 @@ async function onDelete(idx, onDevice) { log('Delete failed: ' + (err.message || err)); } } else { + if (!confirm(`Forget ${label} from this browser's list? (It only clears the local record.)`)) return; delete slots[idx]; saveSlots(); renderSlots(); } } @@ -171,6 +230,8 @@ function renderSlots() { durationSec: slots[k].durationSec, name: slots[k].name, })); + updateUploadSlotOptions(); // keep the upload picker's "next free" in sync + if (!rows.length) { list.innerHTML = `
  • ${onDevice ? 'No tracks on the device yet.' : 'Connect to list device tracks.'}
  • `; return; @@ -185,11 +246,12 @@ function renderSlots() { const actions = document.createElement('div'); actions.className = 'slot-actions'; const playBtn = btn('▶', 'Play', () => dev.play(t.idx).catch((e) => log('' + e))); - playBtn.dataset.needsConn = ''; - playBtn.disabled = !dev.connected; + const stopBtn = btn('⏹', 'Stop', () => dev.stop().catch((e) => log('' + e))); + playBtn.dataset.needsConn = ''; stopBtn.dataset.needsConn = ''; + playBtn.disabled = stopBtn.disabled = !dev.connected; const delBtn = btn('🗑', onDevice ? 'Delete from device' : 'Forget (local only)', - () => onDelete(t.idx, onDevice)); - actions.append(playBtn, delBtn); + () => onDelete(t.idx, onDevice, t.name)); + actions.append(playBtn, stopBtn, delBtn); li.append(actions); list.append(li); } @@ -213,9 +275,33 @@ function fillSelect(sel, values, fmt, selected) { } fillSelect($('rate'), RATES, (v) => `${v / 1000} kHz`, 8000); fillSelect($('bits'), BITS, (v) => `${v}-bit`, 8); -for (const sel of [$('upload-slot'), $('play-slot')]) { - fillSelect(sel, Array.from({ length: MAX_TRACKS }, (_, i) => i), (v) => `Slot ${v}`, 0); +fillSelect($('play-slot'), Array.from({ length: MAX_TRACKS }, (_, i) => i), (v) => `Slot ${v}`, 0); + +// Which slots currently hold a track: device truth when connected, else local memory. +function occupiedSlots() { + if (dev.connected && Array.isArray(deviceTracks)) return new Set(deviceTracks.map((t) => t.idx)); + return new Set(Object.keys(slots).map(Number)); } +function nextFreeSlot() { + const occ = occupiedSlots(); + for (let i = 0; i < MAX_TRACKS; i++) if (!occ.has(i)) return i; + return MAX_TRACKS - 1; // all full → default to the last slot +} +// Rebuild the upload-slot picker, label occupied slots, and default to next free. +function updateUploadSlotOptions() { + const occ = occupiedSlots(); + const sel = $('upload-slot'); + sel.innerHTML = ''; + for (let i = 0; i < MAX_TRACKS; i++) { + const o = document.createElement('option'); + o.value = i; + const name = slots[i]?.name; + o.textContent = occ.has(i) ? `Slot ${i} — in use${name ? `: ${name}` : ''}` : `Slot ${i} — free`; + sel.append(o); + } + sel.value = String(nextFreeSlot()); +} +updateUploadSlotOptions(); // ---- support banner ---- if (!isSupported()) { diff --git a/app/ble.js b/app/ble.js index 01109e1..387a057 100644 --- a/app/ble.js +++ b/app/ble.js @@ -34,9 +34,9 @@ const TAG_DELETE = 0xd0; export const MAX_TRACKS = 32; -// Keep below ATT MTU - 3. The firmware calls configPrphBandwidth(BANDWIDTH_MAX) -// so Chrome typically negotiates MTU 247 (244-byte payload). 180 stays well clear. -const DATA_CHUNK = 180; +// ATT MTU is negotiated to 247 (firmware requests via requestMtuExchange(247)). +// Write-without-response payload = MTU - 3 = 244 bytes. +const DATA_CHUNK = 244; export function isSupported() { return typeof navigator !== 'undefined' && !!navigator.bluetooth; @@ -231,40 +231,60 @@ export class BabyMobile extends EventTarget { }); } - // Stream a complete WAV file to a slot. `onProgress(sent, total)` is called as - // the firmware acknowledges bytes via the status characteristic. + // Stream a complete WAV file to a slot. `onProgress(shown, total)` reports a + // single monotonic value combining the locally-sent count and the device's + // acknowledged count. async upload(track, wavBytes, onProgress) { this._requireConnected(); const total = wavBytes.byteLength; this._statBytes = 0; let acked = 0; - const progressHandler = (ev) => { - acked = ev.detail.bytes; - if (onProgress) onProgress(Math.min(acked, total), total); + // The optimistic local "sent" count races ahead of the device's ack + // notifications, and the two arrive interleaved (and acks can lag badly over + // a slow mobile link). Reporting both directly makes the bar jump forward then + // snap backward. Clamp to a high-water mark so progress only ever advances. + let shown = 0; + const report = (n) => { + const v = Math.min(Math.max(0, n), total); + if (v > shown) { shown = v; if (onProgress) onProgress(shown, total); } }; + + const progressHandler = (ev) => { acked = ev.detail.bytes; report(acked); }; this.addEventListener('progress', progressHandler); try { this._log(`Starting upload of ${total} bytes to slot ${track}…`); await this._writeCmd([CMD_UPLOAD_START, track & 0xff]); - // Send all data chunks. Progress is tracked client-side (bytes sent). - // The firmware queues bytes into a ring buffer; actual flash writes happen - // in the background. We do NOT poll per-packet notifications here — that - // caused BLE notification-buffer overflow for large files. - for (let off = 0; off < total; off += DATA_CHUNK) { - const chunk = wavBytes.subarray(off, Math.min(off + DATA_CHUNK, total)); - await this.data.writeValueWithoutResponse(chunk); - if (onProgress) onProgress(off + chunk.length, total); + // Send all data chunks in pipelined batches. Chrome on Windows serialises + // individually-awaited writeValueWithoutResponse calls (one Promise per OS + // event loop tick), which limits throughput to ~one packet per ~50 ms and + // turns a 1.4 MB upload into a 6-minute ordeal. Firing PIPE writes before + // awaiting them all fills multiple BLE connection events per await, saturating + // the link. The firmware's 32 KB ring buffer absorbs bursts comfortably. + const PIPE = 6; // packets in flight before each await (~1 KB per batch) + for (let off = 0; off < total; off += DATA_CHUNK * PIPE) { + const batch = []; + for (let i = 0; i < PIPE && off + i * DATA_CHUNK < total; i++) { + const s = off + i * DATA_CHUNK; + batch.push(this.data.writeValueWithoutResponse( + wavBytes.subarray(s, Math.min(s + DATA_CHUNK, total)))); + } + await Promise.all(batch); + // Cap the optimistic local count at 99%; the final 1% is filled only when + // the device's finalize ack confirms the bytes actually landed in flash. + report(Math.min(off + DATA_CHUNK * PIPE, Math.floor(total * 0.99))); } // Tell the firmware we're done. It will drain its ring buffer, write the // track table, then send ONE finalize notification with the total byte count. await this._writeCmd([CMD_UPLOAD_END]); - // Wait for that single finalize notification (up to 20 s to allow flash writes). - await this._waitForAck(total, 20000); + // Wait for that single finalize notification. Allow up to 60 s: at 300 ms/sector + // worst-case, a 1.4 MB file has ~350 sectors = 105 s of erase time. In practice + // most sectors erase in ~30 ms so finalization completes in well under 60 s. + await this._waitForAck(total, 60000); const ok = acked >= total; if (ok) { this._log(`✅ Upload complete: ${acked}/${total} bytes acknowledged.`); diff --git a/app/index.html b/app/index.html index 3a7df39..f4c72d1 100644 --- a/app/index.html +++ b/app/index.html @@ -13,8 +13,7 @@
    - -

    BabyMobile

    + BabyMobile
    @@ -40,6 +39,11 @@
    +

    No file selected.

    @@ -48,15 +52,6 @@
    -
    -

    2 · Play

    -
    - - - -
    -
    -

    Tracks on device

    diff --git a/app/styles.css b/app/styles.css index a341ed5..33852ea 100644 --- a/app/styles.css +++ b/app/styles.css @@ -16,6 +16,7 @@ body { background: linear-gradient(160deg, var(--bg), var(--bg2)); color: var(--text); min-height: 100vh; + overflow-x: hidden; -webkit-tap-highlight-color: transparent; } header { @@ -48,11 +49,14 @@ button:disabled { opacity: .4; cursor: not-allowed; } button.primary { background: linear-gradient(135deg, var(--accent2), var(--accent)); border: none; color: #1a0f3a; font-weight: 600; } button.mini { padding: 6px 10px; border-radius: 8px; } -select { +select, input[type=number] { font: inherit; background: #1c123e; color: var(--text); border: 1px solid var(--line); border-radius: 8px; padding: 8px 10px; } +input[type=number] { width: 4.5rem; } label { display: inline-flex; align-items: center; gap: 8px; font-size: .9rem; color: var(--muted); } +.trim { align-items: center; } +.trim .unit { color: var(--muted); margin-left: -4px; } .drop { border: 2px dashed var(--line); border-radius: 14px; padding: 26px 16px; @@ -87,3 +91,12 @@ label { display: inline-flex; align-items: center; gap: 8px; font-size: .9rem; c font-size: .78rem; color: var(--muted); max-height: 200px; overflow: auto; white-space: pre-wrap; margin: 0; } footer { text-align: center; color: var(--muted); font-size: .78rem; padding: 8px 16px calc(24px + env(safe-area-inset-bottom)); } footer a { color: var(--accent); } + +@media (max-width: 480px) { + header { padding: 12px 12px calc(12px + env(safe-area-inset-top)); } + .conn { gap: 6px; font-size: .8rem; } + main { padding: 12px; gap: 12px; } + .card { padding: 14px; border-radius: 14px; } + .opts { gap: 12px; } + .slot-meta b { max-width: 42vw; } +} diff --git a/app/sw.js b/app/sw.js index a92e1cb..0763084 100644 --- a/app/sw.js +++ b/app/sw.js @@ -1,5 +1,5 @@ // sw.js — minimal offline cache so the PWA launches without a network. -const CACHE = 'babymobile-v3'; +const CACHE = 'babymobile-v5'; const ASSETS = [ './', './index.html', './styles.css', './app.js', './ble.js', './wav.js', diff --git a/app/wav.js b/app/wav.js index 440935d..e95c760 100644 --- a/app/wav.js +++ b/app/wav.js @@ -72,11 +72,26 @@ function buildWav(pcm, rate, bits) { return u8; } -// Returns { wav: Uint8Array, durationSec, rate, bits, srcRate }. -export async function fileToWav(file, { rate = 8000, bits = 8 } = {}) { +// Decode a file to mono Float32 samples at `rate`. This is the expensive step, +// so callers cache the result and re-encode cheaply when bits/trim change. +// Returns { samples, rate, srcRate }. +export async function decodeFileToMono(file, rate = 8000) { const arrayBuffer = await file.arrayBuffer(); const { samples, srcRate } = await decodeMono(arrayBuffer, rate); - const pcm = floatToPcm(samples, bits); - const wav = buildWav(pcm, rate, bits); - return { wav, durationSec: samples.length / rate, rate, bits, srcRate }; + return { samples, rate, srcRate }; +} + +// Slice [trimStart, end-trimEnd] off the mono samples and return that range. +export function trimSamples(samples, rate, trimStart = 0, trimEnd = 0) { + const start = Math.max(0, Math.min(samples.length, Math.floor(trimStart * rate))); + const end = Math.max(start, samples.length - Math.max(0, Math.floor(trimEnd * rate))); + return samples.subarray(start, end); +} + +// Encode mono Float32 samples to a WAV. Returns { wav, durationSec }. +export function encodeWav(samples, rate, bits, { trimStart = 0, trimEnd = 0 } = {}) { + const sliced = trimSamples(samples, rate, trimStart, trimEnd); + const pcm = floatToPcm(sliced, bits); + const wav = buildWav(pcm, rate, bits); + return { wav, durationSec: sliced.length / rate }; } diff --git a/baby-mobile-v5.kicad_pcb b/baby-mobile-v5.kicad_pcb index 18ce224..0d22101 100644 --- a/baby-mobile-v5.kicad_pcb +++ b/baby-mobile-v5.kicad_pcb @@ -125,7 +125,7 @@ (net 8 "/SPI_SCK") (net 9 "/SPI_MISO") (net 10 "unconnected-(U3-VBUS-Pad14)") - (net 11 "unconnected-(U3-P1.11_D6_TX-Pad7)") + (net 11 "unconnected-(C5-Pad2)") (net 12 "unconnected-(U3-P1.12_D7_RX-Pad8)") (net 13 "/LED1") (net 14 "/LED2") @@ -168,10 +168,12 @@ (net 51 "unconnected-(U2-RESET#{slash}NC-Pad3)") (net 52 "unconnected-(U2-NC-Pad4)") (net 53 "unconnected-(U2-NC-Pad6)") + (net 54 "Net-(C9-Pad1)") + (net 55 "/AMP_SD") (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "19dffe75-85fb-4169-9e23-0d9e037b620e") - (at 208.8 73.95 90) + (at 179.862 88.52 90) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C6" @@ -371,7 +373,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "1adb5712-61a5-425d-981c-5ae2e953bb58") - (at 189.5 93.5) + (at 161.23 93.532857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP5" @@ -572,7 +574,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "1ddd6df5-edd1-46e5-8442-605a5af63e0e") - (at 189.5 103.6) + (at 161.23 103.632857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP13" @@ -773,7 +775,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "3aa28a00-adaf-4cb3-9cc0-b8610a90a57e") - (at 189.5 96.4) + (at 161.23 96.432857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP7" @@ -971,10 +973,185 @@ ) (embedded_fonts no) ) + (footprint "Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical" + (layer "F.Cu") + (uuid "531694f2-d6bb-4a3e-85f6-687b1aa62663") + (at 183.732 91.45 -90) + (descr "Resistor, Axial_DIN0204 series, Axial, Vertical, pin pitch=1.9mm, 0.167W, length*diameter=3.6*1.6mm^2, http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf") + (tags "Resistor Axial_DIN0204 series Axial Vertical pin pitch 1.9mm 0.167W length 3.6mm diameter 1.6mm") + (property "Reference" "R5" + (at 0.95 -1.92 90) + (layer "F.SilkS") + (uuid "5d2cee1b-3f4d-4bb7-8a58-23918f456dfc") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "1K" + (at 0.95 1.92 90) + (layer "F.Fab") + (uuid "a57bded0-5d75-496f-8089-6d96acd893bc") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 270) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "17dcbae0-45f1-41a9-b5e4-1d7eda3ca0b2") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "Resistor" + (at 0 0 270) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "0413e443-16e7-40b5-94ae-a872a7c5fd7a") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property ki_fp_filters "R_*") + (path "/07a6ad63-d769-4a1d-a5f8-ac0dbcfcf37c") + (sheetname "/") + (sheetfile "baby-mobile-v5.kicad_sch") + (attr through_hole) + (fp_arc + (start 0.320095 0.749359) + (mid -0.813042 -0.054435) + (end 0.417133 -0.7) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "b4f6897b-69f1-4d92-859f-0fc2c4fb28b2") + ) + (fp_line + (start -1.05 1.05) + (end 2.86 1.05) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "517a6e3a-6d22-4d05-b279-08d6a54c43c0") + ) + (fp_line + (start 2.86 1.05) + (end 2.86 -1.05) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "c96e0497-027e-483f-ad48-156ed3c921de") + ) + (fp_line + (start -1.05 -1.05) + (end -1.05 1.05) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "e1aaee5b-a66b-4c31-8b20-77f5ac8e61a3") + ) + (fp_line + (start 2.86 -1.05) + (end -1.05 -1.05) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "af2d5dda-e60b-4cb1-9697-24e2e6818103") + ) + (fp_line + (start 0 0) + (end 1.9 0) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "82664d04-b170-4d01-a929-68cdc7c9180b") + ) + (fp_circle + (center 0 0) + (end 0.8 0) + (stroke + (width 0.1) + (type solid) + ) + (fill no) + (layer "F.Fab") + (uuid "f601459c-9588-4ae0-aba7-172a18d923f6") + ) + (fp_text user "${REFERENCE}" + (at 0.95 -1.92 90) + (layer "F.Fab") + (uuid "0a1d7b20-1960-4156-810e-8c3977513e59") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (pad "1" thru_hole circle + (at 0 0 270) + (size 1.4 1.4) + (drill 0.7) + (layers "*.Cu" "*.Mask") + (remove_unused_layers no) + (net 54 "Net-(C9-Pad1)") + (pintype "passive") + (uuid "b770a89f-fd13-4372-9f67-e10863ae0edf") + ) + (pad "2" thru_hole oval + (at 1.9 0 270) + (size 1.4 1.4) + (drill 0.7) + (layers "*.Cu" "*.Mask") + (remove_unused_layers no) + (net 5 "/AUDIO_PWM") + (pintype "passive") + (uuid "d44cb973-7544-40f1-b50c-069bb5f7e46e") + ) + (embedded_fonts no) + (model "${KICAD9_3DMODEL_DIR}/Resistor_THT.3dshapes/R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical.wrl" + (offset + (xyz 0 0 0) + ) + (scale + (xyz 1 1 1) + ) + (rotate + (xyz 0 0 0) + ) + ) + ) (footprint "EasyEDA_Lib:MSOP-8_L3.0-W3.0-P0.65-LS5.0-BL" (layer "F.Cu") (uuid "54051b75-7f88-4c41-ad0e-7ae730e3b009") - (at 203.954 77.825 90) + (at 175.016 92.395 90) (property "Reference" "U4" (at -0.062 -3.692 90) (layer "F.SilkS") @@ -986,7 +1163,7 @@ ) ) ) - (property "Value" "~" + (property "Value" "PAM8302AASCR" (at -0.062 3.692 90) (layer "F.Fab") (uuid "0f3a1d9f-f574-40a3-a4cf-d9adfa4469d6") @@ -1535,7 +1712,7 @@ (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "54bc34fd-fdf9-4f20-b777-8a3928f50b5c") - (at 222.2 120.9 -90) + (at 183.49 105.51 -90) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C2" @@ -1735,7 +1912,7 @@ (footprint "Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical" (layer "F.Cu") (uuid "55524686-58b3-470c-9a3f-30a84733482f") - (at 210.279 76.979 -90) + (at 181.302 93.32 90) (descr "Resistor, Axial_DIN0204 series, Axial, Vertical, pin pitch=1.9mm, 0.167W, length*diameter=3.6*1.6mm^2, http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf") (tags "Resistor Axial_DIN0204 series Axial Vertical pin pitch 1.9mm 0.167W length 3.6mm diameter 1.6mm") (property "Reference" "R4" @@ -1761,7 +1938,7 @@ ) ) (property "Datasheet" "" - (at 0 0 270) + (at 0 0 90) (unlocked yes) (layer "F.Fab") (hide yes) @@ -1774,7 +1951,7 @@ ) ) (property "Description" "Resistor" - (at 0 0 270) + (at 0 0 90) (unlocked yes) (layer "F.Fab") (hide yes) @@ -1786,6 +1963,19 @@ ) ) ) + (property "Todo" "Is this necessary?" + (at 0 0 90) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "2adaa823-f037-42e3-8b78-d8b58cb267d0") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) (property ki_fp_filters "R_*") (path "/90218aa1-4311-468c-8ce8-89d467c4ac29") (sheetname "/") @@ -1803,24 +1993,14 @@ (uuid "72bead70-037b-472c-ae7c-30ce26e2018b") ) (fp_line - (start -1.05 1.05) - (end 2.86 1.05) + (start 2.86 -1.05) + (end -1.05 -1.05) (stroke (width 0.05) (type solid) ) (layer "F.CrtYd") - (uuid "61914c92-b558-43ca-bfa1-abd22e5d4482") - ) - (fp_line - (start 2.86 1.05) - (end 2.86 -1.05) - (stroke - (width 0.05) - (type solid) - ) - (layer "F.CrtYd") - (uuid "b97ad935-f880-4323-aefa-4c8f20a202c1") + (uuid "84208710-ab10-443f-95f5-f4adc40b8997") ) (fp_line (start -1.05 -1.05) @@ -1833,14 +2013,24 @@ (uuid "783fd173-aad3-42e0-83f5-dbe667cc91fd") ) (fp_line - (start 2.86 -1.05) - (end -1.05 -1.05) + (start 2.86 1.05) + (end 2.86 -1.05) (stroke (width 0.05) (type solid) ) (layer "F.CrtYd") - (uuid "84208710-ab10-443f-95f5-f4adc40b8997") + (uuid "b97ad935-f880-4323-aefa-4c8f20a202c1") + ) + (fp_line + (start -1.05 1.05) + (end 2.86 1.05) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "61914c92-b558-43ca-bfa1-abd22e5d4482") ) (fp_line (start 0 0) @@ -1875,17 +2065,17 @@ ) ) (pad "1" thru_hole circle - (at 0 0 270) + (at 0 0 90) (size 1.4 1.4) (drill 0.7) (layers "*.Cu" "*.Mask") (remove_unused_layers no) - (net 45 "/V_BAT") + (net 55 "/AMP_SD") (pintype "passive") (uuid "db47d0a2-4260-4f51-91ee-4243f311328b") ) (pad "2" thru_hole oval - (at 1.9 0 270) + (at 1.9 0 90) (size 1.4 1.4) (drill 0.7) (layers "*.Cu" "*.Mask") @@ -1910,7 +2100,7 @@ (footprint "EasyEDA_Lib:SOIC-16_L10.3-W7.4-P1.27-LS10.3-BL" (layer "F.Cu") (uuid "596fe854-7637-42a4-8d94-516eb0c9c399") - (at 196.9505 121.855 -90) + (at 195.0905 95.655 -90) (property "Reference" "U2" (at -0.00025 -6.65075 90) (layer "F.SilkS") @@ -1922,7 +2112,7 @@ ) ) ) - (property "Value" "~" + (property "Value" "IS25LP128F-RMLE-TR" (at -0.00025 6.65075 90) (layer "F.Fab") (uuid "65d67432-203a-451d-b145-601b1ff76290") @@ -2715,7 +2905,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "5b55a49d-376a-40c7-8f86-d84e2a5948f6") - (at 189.5 97.85) + (at 161.23 97.882857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP8" @@ -2916,7 +3106,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "71be0b29-6923-4e9d-98fc-c607530c1fef") - (at 189.5 100.7) + (at 161.23 100.732857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP15" @@ -3117,7 +3307,7 @@ (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "7c96a877-bbc7-4fcd-a04e-96040626df96") - (at 198.8 130.1) + (at 196.94 103.9) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C3" @@ -3578,7 +3768,7 @@ (size 2.432 1.524) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.1) - (net 4 "/C_BTN1") + (net 5 "/AUDIO_PWM") (pinfunction "P0.02_A0_D0") (pintype "passive") (thermal_bridge_angle 45) @@ -3590,7 +3780,7 @@ (drill 0.889) (layers "*.Cu" "*.Mask") (remove_unused_layers no) - (net 4 "/C_BTN1") + (net 5 "/AUDIO_PWM") (pinfunction "P0.02_A0_D0") (pintype "passive") (uuid "1f12616a-2b4a-4a79-8974-8b0dfc806b06") @@ -3600,7 +3790,7 @@ (size 2.432 1.524) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.1) - (net 13 "/LED1") + (net 4 "/C_BTN1") (pinfunction "P0.03_A1_D1") (pintype "passive") (thermal_bridge_angle 45) @@ -3612,7 +3802,7 @@ (drill 0.889) (layers "*.Cu" "*.Mask") (remove_unused_layers no) - (net 13 "/LED1") + (net 4 "/C_BTN1") (pinfunction "P0.03_A1_D1") (pintype "passive") (uuid "b9077111-3ede-4a1f-93bc-8a2024a4db87") @@ -3688,7 +3878,7 @@ (size 2.432 1.524) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.1) - (net 5 "/AUDIO_PWM") + (net 13 "/LED1") (pinfunction "P0.05_A5_D5_SCL") (pintype "passive") (thermal_bridge_angle 45) @@ -3700,7 +3890,7 @@ (drill 0.889) (layers "*.Cu" "*.Mask") (remove_unused_layers no) - (net 5 "/AUDIO_PWM") + (net 13 "/LED1") (pinfunction "P0.05_A5_D5_SCL") (pintype "passive") (uuid "5ae6d46d-91c9-4ad4-93fa-f4a307b04650") @@ -3710,7 +3900,7 @@ (size 2.432 1.524) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.1) - (net 11 "unconnected-(U3-P1.11_D6_TX-Pad7)") + (net 55 "/AMP_SD") (pinfunction "P1.11_D6_TX") (pintype "passive") (thermal_bridge_angle 45) @@ -3722,7 +3912,7 @@ (drill 0.889) (layers "*.Cu" "*.Mask") (remove_unused_layers no) - (net 11 "unconnected-(U3-P1.11_D6_TX-Pad7)") + (net 55 "/AMP_SD") (pinfunction "P1.11_D6_TX") (pintype "passive") (uuid "138859d1-3dbe-48be-a327-a28796c9f972") @@ -3945,7 +4135,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "834d24f8-2620-4a44-a10b-75a6853de0a4") - (at 189.5 102.15) + (at 161.23 102.182857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP14" @@ -4146,7 +4336,7 @@ (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "8b1a4748-1b4f-4f28-a448-fe13ac5c82cf") - (at 204.1 73.95 90) + (at 175.162 88.52 90) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C7" @@ -4346,7 +4536,7 @@ (footprint "EasyEDA_Lib:UMAX-10_L3.0-W3.0-P0.50-LS4.9-BL" (layer "F.Cu") (uuid "91fbc178-a689-4193-b8f8-95eb88f5c09b") - (at 215.9 122.6 -90) + (at 176.32 105.5 -90) (property "Reference" "U1" (at 0 0 90) (layer "F.SilkS") @@ -4953,7 +5143,7 @@ (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "9da477d3-786c-47b9-8ecb-760e22cd855b") - (at 211.3 122.6 -90) + (at 171.72 105.5 -90) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C1" @@ -5150,10 +5340,210 @@ ) ) ) + (footprint "Capacitor_SMD:C_0805_2012Metric" + (layer "F.Cu") + (uuid "9ea8b95a-0d92-41c5-bfb8-7f4aaa2bef6f") + (at 183.732 88.45 90) + (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags "capacitor") + (property "Reference" "C9" + (at 0 -1.68 90) + (layer "F.SilkS") + (uuid "493dadd4-c866-4cfb-a6e5-37a269d80084") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "1nF" + (at 0 1.68 90) + (layer "F.Fab") + (uuid "40327e2e-00ef-44d7-a322-2abb5f07974e") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 90) + (layer "F.Fab") + (hide yes) + (uuid "a2be8c58-177a-49f3-9317-21cf69f94620") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "" + (at 0 0 90) + (layer "F.Fab") + (hide yes) + (uuid "6bca86c3-e4bb-4e46-8868-ed5a2c500fe1") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (path "/248137b6-5edd-42cd-819b-f475cf23c6e8") + (sheetname "/") + (sheetfile "baby-mobile-v5.kicad_sch") + (attr smd) + (fp_line + (start -0.261252 -0.735) + (end 0.261252 -0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "49ea3eb1-6e65-49ce-8bb9-325205141f97") + ) + (fp_line + (start -0.261252 0.735) + (end 0.261252 0.735) + (stroke + (width 0.12) + (type solid) + ) + (layer "F.SilkS") + (uuid "3775fcba-7862-497a-9335-9c4eb735a122") + ) + (fp_line + (start 1.7 -0.98) + (end 1.7 0.98) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "70f4ab7e-e6da-4c77-8a32-ded727c1308a") + ) + (fp_line + (start -1.7 -0.98) + (end 1.7 -0.98) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "c46a5403-969b-4a8a-8c91-03b51c97983b") + ) + (fp_line + (start 1.7 0.98) + (end -1.7 0.98) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "5d28ab76-66b4-4bca-b4d6-6a12d799a249") + ) + (fp_line + (start -1.7 0.98) + (end -1.7 -0.98) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "57cf4eb5-63ad-4735-b5af-75ff91aa3760") + ) + (fp_line + (start 1 -0.625) + (end 1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "4ba398f7-edb5-497f-82b0-43814cfb10cd") + ) + (fp_line + (start -1 -0.625) + (end 1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "8f91eee2-2e85-407f-abf8-43630e04af4b") + ) + (fp_line + (start 1 0.625) + (end -1 0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "343e4bb9-1d97-424f-9ec5-ed6c66a6a6b2") + ) + (fp_line + (start -1 0.625) + (end -1 -0.625) + (stroke + (width 0.1) + (type solid) + ) + (layer "F.Fab") + (uuid "a6135b21-5cf9-4e83-a54d-da15e5efb2b4") + ) + (fp_text user "${REFERENCE}" + (at 0 0 90) + (layer "F.Fab") + (uuid "7d8f7d37-8c3f-4309-aa9a-95e3569995a2") + (effects + (font + (size 0.5 0.5) + (thickness 0.08) + ) + ) + ) + (pad "1" smd roundrect + (at -0.95 0 90) + (size 1 1.45) + (layers "F.Cu" "F.Mask" "F.Paste") + (roundrect_rratio 0.25) + (net 54 "Net-(C9-Pad1)") + (pinfunction "1") + (pintype "passive") + (uuid "966628e9-52db-4d2f-b785-a1982d7bb1b4") + ) + (pad "2" smd roundrect + (at 0.95 0 90) + (size 1 1.45) + (layers "F.Cu" "F.Mask" "F.Paste") + (roundrect_rratio 0.25) + (net 1 "/GND") + (pinfunction "2") + (pintype "passive") + (uuid "f08a9eac-55a0-4600-a953-827a69f9b546") + ) + (embedded_fonts no) + (model "${KICAD9_3DMODEL_DIR}/Capacitor_SMD.3dshapes/C_0805_2012Metric.wrl" + (offset + (xyz 0 0 0) + ) + (scale + (xyz 1 1 1) + ) + (rotate + (xyz 0 0 0) + ) + ) + ) (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "aa548006-62a9-41f6-8421-a6a12065ca63") - (at 189.5 99.25) + (at 161.23 99.282857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP16" @@ -5651,13 +6041,13 @@ (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "d1b21900-f4b9-4e66-a4ec-4300437cc968") - (at 220.4 124.8 -90) + (at 181.22 105.46 -90) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C4" (at 0 -1.68 90) (layer "F.SilkS") - (uuid "f93fc541-6883-4f09-a82f-bdd41a6477f8") + (uuid "23df86a8-57b3-4576-aec0-4169a3dab66b") (effects (font (size 1 1) @@ -5668,7 +6058,7 @@ (property "Value" "0.33uF" (at 4.3 0 90) (layer "F.Fab") - (uuid "768319c8-6c38-42a1-8e92-aa73fd9733d5") + (uuid "34c5693c-89a3-4d4d-9328-2028efe43a30") (effects (font (size 1 1) @@ -5680,7 +6070,7 @@ (at 0 0 90) (layer "F.Fab") (hide yes) - (uuid "045b139c-453d-40c2-8c59-35821a821fff") + (uuid "ff6930f2-c01e-43cb-a93e-3e2c2c7bfa96") (effects (font (size 1.27 1.27) @@ -5692,7 +6082,7 @@ (at 0 0 90) (layer "F.Fab") (hide yes) - (uuid "8a32fdf2-92fc-4078-81b5-11ce9fc6f19a") + (uuid "976274dd-e20c-49a4-a8cd-37a9d3e3d89d") (effects (font (size 1.27 1.27) @@ -5851,7 +6241,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "F.Cu") (uuid "e315bd4c-0f76-48d9-b452-2bc0bf0821b9") - (at 189.5 94.95) + (at 161.23 94.982857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP6" @@ -6052,7 +6442,7 @@ (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "e4096db0-31a3-4cfb-a1e6-33f9e044979b") - (at 207.95 81) + (at 179.012 95.57) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C5" @@ -6231,7 +6621,7 @@ (size 1 1.45) (layers "F.Cu" "F.Mask" "F.Paste") (roundrect_rratio 0.25) - (net 5 "/AUDIO_PWM") + (net 11 "unconnected-(C5-Pad2)") (pinfunction "2") (pintype "passive") (uuid "49f5d48f-8e1f-489b-9e73-4ab9853a165c") @@ -6252,11 +6642,11 @@ (footprint "Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical" (layer "F.Cu") (uuid "e954f4de-5532-46a4-8315-6520b5709c0e") - (at 219.2 117.8 -90) + (at 175.38 101.66) (descr "Resistor, Axial_DIN0204 series, Axial, Vertical, pin pitch=1.9mm, 0.167W, length*diameter=3.6*1.6mm^2, http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf") (tags "Resistor Axial_DIN0204 series Axial Vertical pin pitch 1.9mm 0.167W length 3.6mm diameter 1.6mm") (property "Reference" "R3" - (at -2.1 -0.1 90) + (at -2.1 -0.1 0) (layer "F.SilkS") (uuid "1f83438c-f2d0-4a93-825d-e8c4034b42a5") (effects @@ -6267,7 +6657,7 @@ ) ) (property "Value" "100K" - (at 0.95 1.92 90) + (at 0.95 1.92 0) (layer "F.Fab") (uuid "bf726bee-988d-405f-8af8-00b52b5f3389") (effects @@ -6278,7 +6668,7 @@ ) ) (property "Datasheet" "" - (at 0 0 270) + (at 0 0 0) (unlocked yes) (layer "F.Fab") (hide yes) @@ -6291,7 +6681,7 @@ ) ) (property "Description" "Resistor" - (at 0 0 270) + (at 0 0 0) (unlocked yes) (layer "F.Fab") (hide yes) @@ -6319,26 +6709,6 @@ (layer "F.SilkS") (uuid "33fe7acc-5963-475c-a864-88a1bfb435ff") ) - (fp_line - (start -1.05 1.05) - (end 2.86 1.05) - (stroke - (width 0.05) - (type solid) - ) - (layer "F.CrtYd") - (uuid "6dfa58d1-bfe1-4670-b797-1f5b711d24b6") - ) - (fp_line - (start 2.86 1.05) - (end 2.86 -1.05) - (stroke - (width 0.05) - (type solid) - ) - (layer "F.CrtYd") - (uuid "c7379281-7e49-40c7-a6a8-55ec740f9200") - ) (fp_line (start -1.05 -1.05) (end -1.05 1.05) @@ -6349,6 +6719,16 @@ (layer "F.CrtYd") (uuid "4c30d52a-ad4f-4aa8-83a1-7717421c4b84") ) + (fp_line + (start -1.05 1.05) + (end 2.86 1.05) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "6dfa58d1-bfe1-4670-b797-1f5b711d24b6") + ) (fp_line (start 2.86 -1.05) (end -1.05 -1.05) @@ -6359,6 +6739,16 @@ (layer "F.CrtYd") (uuid "eea8e84b-d6a6-4858-9a5e-02107af31d35") ) + (fp_line + (start 2.86 1.05) + (end 2.86 -1.05) + (stroke + (width 0.05) + (type solid) + ) + (layer "F.CrtYd") + (uuid "c7379281-7e49-40c7-a6a8-55ec740f9200") + ) (fp_line (start 0 0) (end 1.9 0) @@ -6381,7 +6771,7 @@ (uuid "c055180b-01ac-4554-8e9f-986d7fdc795d") ) (fp_text user "${REFERENCE}" - (at -2.1 -0.2 90) + (at -2.1 -0.2 0) (layer "F.Fab") (uuid "1728ee15-3fc4-4bd8-8e63-7b43ea7e616d") (effects @@ -6392,7 +6782,7 @@ ) ) (pad "1" thru_hole circle - (at 0 0 270) + (at 0 0) (size 1.4 1.4) (drill 0.7) (layers "*.Cu" "*.Mask") @@ -6402,7 +6792,7 @@ (uuid "daf722ff-e07e-4881-804a-663261c29257") ) (pad "2" thru_hole oval - (at 1.9 0 270) + (at 1.9 0) (size 1.4 1.4) (drill 0.7) (layers "*.Cu" "*.Mask") @@ -6427,7 +6817,7 @@ (footprint "Resistor_SMD:R_0805_2012Metric" (layer "F.Cu") (uuid "f7f360e7-11f5-4158-a234-e75c1d3cfa62") - (at 193.9 130.1) + (at 192.04 103.9) (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 72, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf), generated with kicad-footprint-generator") (tags "resistor") (property "Reference" "R2" @@ -6627,7 +7017,7 @@ (footprint "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (uuid "fd2b682c-5ff3-40ea-b718-2527000d2263") - (at 199.4 73.95 90) + (at 170.462 88.52 90) (descr "Capacitor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC-7351 nominal, (Body size source: IPC-SM-782 page 76, https://www.pcb-3d.com/wordpress/wp-content/uploads/ipc-sm-782a_amendment_1_and_2.pdf, https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") (tags "capacitor") (property "Reference" "C8" @@ -6827,7 +7217,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "3a2c8639-cf28-4840-9acb-d2b6712159e8") - (at 191.75 97.828571) + (at 163.48 97.861428) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP4" @@ -7031,7 +7421,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "46b3f07b-ef62-4ff6-b0d2-8074f343ed0b") - (at 191.75 96.385714) + (at 163.48 96.418571) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP3" @@ -7235,7 +7625,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "4d31da7b-9f4c-4fef-ae23-14671edf51c8") - (at 191.75 100.714286) + (at 163.48 100.747143) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP11" @@ -7439,7 +7829,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "6046ba29-f776-4a4b-af51-e2777e502b13") - (at 191.75 93.5) + (at 163.48 93.532857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP1" @@ -7643,7 +8033,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "71c9cdf3-d340-4243-b1c8-70e24618639e") - (at 191.75 103.6) + (at 163.48 103.632857) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP9" @@ -7847,7 +8237,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "a9c2de0e-4082-4e39-b749-79df7e4d6376") - (at 191.75 94.942857) + (at 163.48 94.975714) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP2" @@ -8051,7 +8441,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "ada5fbc0-70b6-43e9-974b-4e4a9d0d09c0") - (at 191.75 99.271429) + (at 163.48 99.304286) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP12" @@ -8255,7 +8645,7 @@ (footprint "Library:SolderJumper-2_P1.0mm_Bridged_RoundedPad1.8x0.4mm" (layer "B.Cu") (uuid "dc6d2921-0565-4538-be8a-c6188065328a") - (at 191.75 102.157143) + (at 163.48 102.19) (descr "SMD Solder Jumper, 1x1.5mm, rounded Pads, 0.3mm gap, bridged with 1 copper strip") (tags "net tie solder jumper bridged") (property "Reference" "JP10" @@ -8477,7 +8867,7 @@ (uuid "68617254-1779-4798-8930-6d817633b5b8") ) (gr_line - (start 182 85) + (start 156.13 85) (end 225 85) (stroke (width 0.05) @@ -8488,7 +8878,7 @@ ) (gr_line (start 77.308542 100.78) - (end 182 100.78) + (end 156.13 100.78) (stroke (width 0.05) (type solid) @@ -8497,8 +8887,8 @@ (uuid "9dd8891b-e2b0-4923-aa2f-67c2a57e3231") ) (gr_line - (start 182 85) - (end 182 96.38) + (start 156.13 85) + (end 156.13 96.38) (stroke (width 0.05) (type default) @@ -8508,7 +8898,7 @@ ) (gr_line (start 225 111) - (end 182 111) + (end 156.13 111) (stroke (width 0.05) (type solid) @@ -8517,8 +8907,8 @@ (uuid "b6a3f7d2-4c68-4ecc-b5c3-5fb65b525c78") ) (gr_line - (start 182 111) - (end 182 100.78) + (start 156.13 111) + (end 156.13 100.78) (stroke (width 0.05) (type solid) @@ -8528,7 +8918,7 @@ ) (gr_line (start 77.308542 96.38) - (end 182 96.38) + (end 156.13 96.38) (stroke (width 0.05) (type solid) @@ -8562,127 +8952,111 @@ ) ) (segment - (start 192.578571 97.828571) - (end 193 98.25) + (start 164.308571 97.861428) + (end 164.73 98.282857) (width 0.2) (layer "B.Cu") (net 1) (uuid "161573ba-b28b-4cef-8332-9d47adad12f7") ) (segment - (start 192.566587 102.157143) - (end 196.829722 106.420278) - (width 0.2) - (layer "B.Cu") - (net 1) - (uuid "2e47978e-875c-40e6-bb4e-f526346dc5a2") - ) - (segment - (start 193 98.521429) - (end 192.25 99.271429) + (start 164.73 98.554286) + (end 163.98 99.304286) (width 0.2) (layer "B.Cu") (net 1) (uuid "7481727c-536d-4f0a-9ca8-14d0268fc9ae") ) (segment - (start 192.25 102.157143) - (end 192.951 101.456143) + (start 163.98 102.19) + (end 164.681 101.489) (width 0.2) (layer "B.Cu") (net 1) (uuid "928f29f5-0a00-4a4e-ab68-eaf453fab367") ) (segment - (start 192.951 99.972429) - (end 192.25 99.271429) + (start 164.681 100.005286) + (end 163.98 99.304286) (width 0.2) (layer "B.Cu") (net 1) (uuid "a6d8cbae-f37d-4b48-8ed5-a6db04d38e9f") ) (segment - (start 193 98.25) - (end 193 98.521429) + (start 164.73 98.282857) + (end 164.73 98.554286) (width 0.2) (layer "B.Cu") (net 1) (uuid "b0ccaa51-9a41-4023-b444-78f7807d07a1") ) (segment - (start 192.25 97.828571) - (end 192.578571 97.828571) + (start 163.98 97.861428) + (end 164.308571 97.861428) (width 0.2) (layer "B.Cu") (net 1) (uuid "b1154282-403c-44be-8ed5-25f23234f601") ) (segment - (start 192.25 102.157143) - (end 192.566587 102.157143) + (start 163.98 102.19) + (end 164.296587 102.19) (width 0.2) (layer "B.Cu") (net 1) (uuid "e66fb862-99ad-437f-af8b-592ace737820") ) (segment - (start 192.951 101.456143) - (end 192.951 99.972429) + (start 164.681 101.489) + (end 164.681 100.005286) (width 0.2) (layer "B.Cu") (net 1) (uuid "ef251e4d-d27f-49e6-b7dd-59de64a9e9c2") ) (segment - (start 196.829722 106.420278) - (end 197.134444 106.725) - (width 0.2) - (layer "B.Cu") - (net 1) - (uuid "fc99a9a7-3711-41d7-981c-3afa81efa493") - ) - (segment - (start 193.25 92.75) - (end 190.75 92.75) + (start 164.98 92.782857) + (end 162.48 92.782857) (width 0.2) (layer "F.Cu") (net 2) (uuid "0d2a5217-d403-4d67-b509-9f0a5edacbff") ) (segment - (start 190 103.6) - (end 190.9 104.5) + (start 161.73 103.632857) + (end 162.63 104.532857) (width 0.2) (layer "F.Cu") (net 2) (uuid "9634c5ba-2da9-4d5d-bf38-325f0bb569f8") ) (segment - (start 190.75 92.75) - (end 190 93.5) + (start 162.48 92.782857) + (end 161.73 93.532857) (width 0.2) (layer "F.Cu") (net 2) (uuid "a8710678-1cdc-46db-b3a4-07e7b6322f43") ) (segment - (start 194 93.5) - (end 193.25 92.75) + (start 165.73 93.532857) + (end 164.98 92.782857) (width 0.2) (layer "F.Cu") (net 2) (uuid "ca49ee7a-b2bc-4ccc-870d-4c9c727a3177") ) (segment - (start 190.9 104.5) - (end 196.473 104.5) + (start 162.63 104.532857) + (end 168.203 104.532857) (width 0.2) (layer "F.Cu") (net 2) (uuid "da341dd0-92bd-4439-85a1-725356961d23") ) (via - (at 196.473 104.5) + (at 168.203 104.532857) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") @@ -8690,7 +9064,7 @@ (uuid "05b6f77d-c451-44df-851e-324f771a905a") ) (via - (at 194 93.5) + (at 165.73 93.532857) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") @@ -8698,71 +9072,71 @@ (uuid "1179dd96-b951-45c3-9ad0-ff933e0f8631") ) (segment - (start 194 102.027) - (end 194 93.5) + (start 165.73 102.059857) + (end 165.73 93.532857) (width 0.2) (layer "B.Cu") (net 2) (uuid "5c5952df-6282-436f-bd11-ab1d316e0023") ) (segment - (start 196.473 104.5) - (end 194 102.027) + (start 168.203 104.532857) + (end 165.73 102.059857) (width 0.2) (layer "B.Cu") (net 2) (uuid "dda38ba8-6fdd-4931-989f-9a6ecf1e80d2") ) (segment - (start 196.475 104.601) - (end 196.475 104.502) + (start 168.205 104.633857) + (end 168.205 104.534857) (width 0.2) (layer "B.Cu") (net 2) (uuid "f26c12af-191b-4cca-96c5-39c51972a26d") ) (segment - (start 196.475 104.502) - (end 196.473 104.5) + (start 168.205 104.534857) + (end 168.203 104.532857) (width 0.2) (layer "B.Cu") (net 2) (uuid "f5123e3a-f535-4e4b-8cfc-161cd4d369d5") ) (segment - (start 191 95.5) - (end 192 95.5) + (start 162.73 95.532857) + (end 163.73 95.532857) (width 0.2) (layer "F.Cu") (net 4) (uuid "1b9bade1-9145-49ef-a83a-4346216b6870") ) (segment - (start 192 95.5) - (end 192.11749 95.5) + (start 163.73 95.532857) + (end 163.84749 95.532857) (width 0.2) (layer "F.Cu") (net 4) (uuid "3c07382b-2084-4cd2-9c09-e2e4e93f4891") ) (segment - (start 190.1 96.4) - (end 191 95.5) + (start 161.83 96.432857) + (end 162.73 95.532857) (width 0.2) (layer "F.Cu") (net 4) (uuid "4ed19ba3-01c7-441d-86db-5a0e75661a3f") ) (segment - (start 190 96.4) - (end 190.1 96.4) + (start 161.73 96.432857) + (end 161.83 96.432857) (width 0.2) (layer "F.Cu") (net 4) (uuid "f80b9444-844a-4969-a1cc-826d72f2d4b8") ) (via - (at 192 95.5) + (at 163.73 95.532857) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") @@ -8770,59 +9144,99 @@ (uuid "e0a244d3-4fa3-414d-8efb-69deb3eb6c23") ) (segment - (start 192.25 94.942857) - (end 192.25 95.25) + (start 163.98 94.975714) + (end 163.98 95.282857) (width 0.2) (layer "B.Cu") (net 4) (uuid "11f83659-0b07-4177-bee6-9f6d10159ec8") ) (segment - (start 193.034444 93.5) - (end 192.25 93.5) + (start 164.764444 93.532857) + (end 163.98 93.532857) (width 0.2) (layer "B.Cu") (net 4) (uuid "2ee1b29b-1190-40e7-aa3e-98c314e201d4") ) (segment - (start 196.25 90.284444) - (end 193.034444 93.5) + (start 218.5 86.002) + (end 197.8901 86.002) (width 0.2) (layer "B.Cu") (net 4) - (uuid "313a2de6-ff40-4fab-84c6-25807fdb72c0") + (uuid "3465ec80-a603-4d2a-ad8d-1997f387d547") ) (segment - (start 196.25 87.075) - (end 196.25 90.284444) - (width 0.2) - (layer "B.Cu") - (net 4) - (uuid "364e1fd3-6171-4505-b03a-898756e8d569") - ) - (segment - (start 192.807143 94.942857) - (end 193 94.75) + (start 164.537143 94.975714) + (end 164.73 94.782857) (width 0.2) (layer "B.Cu") (net 4) (uuid "4a687405-d2c8-4444-b88c-fe194b6e7233") ) (segment - (start 192.25 94.942857) - (end 192.807143 94.942857) + (start 163.98 94.975714) + (end 164.537143 94.975714) (width 0.2) (layer "B.Cu") (net 4) (uuid "7e171693-a38c-41e8-923e-7a96f21ccdb5") ) + (segment + (start 197.8901 86.002) + (end 196.95855 86.93355) + (width 0.2) + (layer "B.Cu") + (net 4) + (uuid "87ebb558-5e71-4153-9009-5f641b64d27e") + ) + (segment + (start 163.98 93.532857) + (end 164.73 94.282857) + (width 0.2) + (layer "B.Cu") + (net 4) + (uuid "c44a6522-334f-44a8-a599-8fcd510f6e79") + ) + (segment + (start 219.46 88.76) + (end 219.46 86.962) + (width 0.2) + (layer "B.Cu") + (net 4) + (uuid "df8caa6f-660a-4ac4-a198-8cd04fd760b4") + ) + (segment + (start 219.46 86.962) + (end 218.5 86.002) + (width 0.2) + (layer "B.Cu") + (net 4) + (uuid "e6931753-cb03-43a8-8801-74d236c584db") + ) + (segment + (start 164.73 94.782857) + (end 164.73 94.282857) + (width 0.2) + (layer "B.Cu") + (net 4) + (uuid "fa9422da-74ab-4cc9-9e3d-aa16b2e52936") + ) + (segment + (start 163.98 95.282857) + (end 163.73 95.532857) + (width 0.2) + (layer "B.Cu") + (net 4) + (uuid "fbd7d886-1bb4-495b-88df-b49ce4f05b1b") + ) (segment (start 222 88.76) (end 222 86.351) (width 0.2) (layer "B.Cu") - (net 4) + (net 5) (uuid "826ccd54-1573-46ed-998e-e9da1c581e5d") ) (segment @@ -8830,7 +9244,7 @@ (end 221.25 85.601) (width 0.2) (layer "B.Cu") - (net 4) + (net 5) (uuid "9760707a-b770-4191-9388-8ff999e8674d") ) (segment @@ -8838,73 +9252,17 @@ (end 197.724 85.601) (width 0.2) (layer "B.Cu") - (net 4) + (net 5) (uuid "afa206b7-d7eb-4416-b526-ed5edaa3ce84") ) - (segment - (start 192.25 93.5) - (end 193 94.25) - (width 0.2) - (layer "B.Cu") - (net 4) - (uuid "c44a6522-334f-44a8-a599-8fcd510f6e79") - ) - (segment - (start 193 94.75) - (end 193 94.25) - (width 0.2) - (layer "B.Cu") - (net 4) - (uuid "fa9422da-74ab-4cc9-9e3d-aa16b2e52936") - ) (segment (start 197.724 85.601) (end 196.25 87.075) (width 0.2) (layer "B.Cu") - (net 4) + (net 5) (uuid "fbb1912c-4b8b-48a9-acc4-e0980953fd97") ) - (segment - (start 192.25 95.25) - (end 192 95.5) - (width 0.2) - (layer "B.Cu") - (net 4) - (uuid "fbd7d886-1bb4-495b-88df-b49ce4f05b1b") - ) - (segment - (start 207.427 89.823) - (end 205.323 89.823) - (width 0.2) - (layer "F.Cu") - (net 5) - (uuid "21b53762-a94b-4cb2-a7f1-f4d370ac6d4d") - ) - (segment - (start 209.3 87.925) - (end 207.5 89.725) - (width 0.2) - (layer "F.Cu") - (net 5) - (uuid "6d193e90-9a9c-49d4-8ca8-26d5425fba88") - ) - (segment - (start 207.5 89.75) - (end 207.427 89.823) - (width 0.2) - (layer "F.Cu") - (net 5) - (uuid "742718e0-13e0-46c4-afd1-cb878e0bcd78") - ) - (segment - (start 207.5 89.725) - (end 207.5 89.75) - (width 0.2) - (layer "F.Cu") - (net 5) - (uuid "f19409c5-d04d-4e8a-a3f7-5245049b02e7") - ) (segment (start 206.35 94.25) (end 206.25 94.25) @@ -8986,23 +9344,55 @@ (uuid "3b36996d-e0f2-4742-8324-bc1216e80cae") ) (segment - (start 191.15 97.85) - (end 190 97.85) + (start 162.88 97.882857) + (end 161.73 97.882857) (width 0.2) (layer "F.Cu") (net 13) (uuid "05f03d58-5210-4f5f-983d-a7abf5531e7e") ) (segment - (start 194.75 94.25) - (end 191.15 97.85) + (start 207.427 89.823) + (end 205.323 89.823) + (width 0.2) + (layer "F.Cu") + (net 13) + (uuid "21b53762-a94b-4cb2-a7f1-f4d370ac6d4d") + ) + (segment + (start 209.3 87.925) + (end 207.5 89.725) + (width 0.2) + (layer "F.Cu") + (net 13) + (uuid "6d193e90-9a9c-49d4-8ca8-26d5425fba88") + ) + (segment + (start 207.5 89.75) + (end 207.427 89.823) + (width 0.2) + (layer "F.Cu") + (net 13) + (uuid "742718e0-13e0-46c4-afd1-cb878e0bcd78") + ) + (segment + (start 166.48 94.282857) + (end 162.88 97.882857) (width 0.2) (layer "F.Cu") (net 13) (uuid "aa57da12-0435-4e3f-952e-8dca29e41f3d") ) + (segment + (start 207.5 89.725) + (end 207.5 89.75) + (width 0.2) + (layer "F.Cu") + (net 13) + (uuid "f19409c5-d04d-4e8a-a3f7-5245049b02e7") + ) (via - (at 194.75 94.25) + (at 166.48 94.282857) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") @@ -9010,87 +9400,47 @@ (uuid "8ea87711-0b8f-4ed7-bd9a-297ed6967174") ) (segment - (start 194.715 94.316667) - (end 194.715 94.285) + (start 166.445 94.349524) + (end 166.445 94.317857) (width 0.2) (layer "B.Cu") (net 13) (uuid "340c4a80-ac8a-4d62-9332-6e7950e5ddd8") ) (segment - (start 218.5 86.002) - (end 197.8901 86.002) - (width 0.2) - (layer "B.Cu") - (net 13) - (uuid "3465ec80-a603-4d2a-ad8d-1997f387d547") - ) - (segment - (start 194.715 94.285) - (end 194.75 94.25) + (start 166.445 94.317857) + (end 166.48 94.282857) (width 0.2) (layer "B.Cu") (net 13) (uuid "5975d8f4-d164-40e7-9976-0c300a5a6992") ) (segment - (start 196.95855 86.93355) - (end 196.95855 92.073117) - (width 0.2) - (layer "B.Cu") - (net 13) - (uuid "849aa4b0-684e-422e-ac1f-30bad991bc79") - ) - (segment - (start 197.8901 86.002) - (end 196.95855 86.93355) - (width 0.2) - (layer "B.Cu") - (net 13) - (uuid "87ebb558-5e71-4153-9009-5f641b64d27e") - ) - (segment - (start 196.95855 92.073117) - (end 194.715 94.316667) + (start 168.68855 92.105974) + (end 166.445 94.349524) (width 0.2) (layer "B.Cu") (net 13) (uuid "cda5ef32-32e5-4365-92e1-b8dedc60cb51") ) (segment - (start 219.46 88.76) - (end 219.46 86.962) - (width 0.2) - (layer "B.Cu") - (net 13) - (uuid "df8caa6f-660a-4ac4-a198-8cd04fd760b4") - ) - (segment - (start 219.46 86.962) - (end 218.5 86.002) - (width 0.2) - (layer "B.Cu") - (net 13) - (uuid "e6931753-cb03-43a8-8801-74d236c584db") - ) - (segment - (start 192.25 99.25) - (end 190 99.25) + (start 163.98 99.282857) + (end 161.73 99.282857) (width 0.2) (layer "F.Cu") (net 14) (uuid "ae694957-1f72-493e-ba28-e76926e3a1f5") ) (segment - (start 194.75 96.75) - (end 192.25 99.25) + (start 166.48 96.782857) + (end 163.98 99.282857) (width 0.2) (layer "F.Cu") (net 14) (uuid "f2a56a06-5626-4d70-b76b-fe1da9f058b9") ) (via - (at 194.75 96.75) + (at 166.48 96.782857) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") @@ -9114,16 +9464,16 @@ (uuid "340c1805-9aac-4114-9f5a-4caab9b255be") ) (segment - (start 194.715 96.813889) - (end 194.715 96.785) + (start 166.445 96.846746) + (end 166.445 96.817857) (width 0.2) (layer "B.Cu") (net 14) (uuid "68e932a3-3c0f-4cfb-be96-90d90c019509") ) (segment - (start 194.715 96.785) - (end 194.75 96.75) + (start 166.445 96.817857) + (end 166.48 96.782857) (width 0.2) (layer "B.Cu") (net 14) @@ -9138,21 +9488,13 @@ (uuid "a5a3d138-d86c-4e24-a15d-443a8ea17cc9") ) (segment - (start 197.35955 94.169339) - (end 194.715 96.813889) + (start 169.08955 94.202196) + (end 166.445 96.846746) (width 0.2) (layer "B.Cu") (net 14) (uuid "a6918495-0e8f-41cc-b8ce-96003735e54f") ) - (segment - (start 197.35955 87.09965) - (end 197.35955 94.169339) - (width 0.2) - (layer "B.Cu") - (net 14) - (uuid "af5cff23-8421-4abb-b4e1-3701c4194b2d") - ) (segment (start 216.92 87.573) (end 215.75 86.403) @@ -9162,23 +9504,23 @@ (uuid "bce42478-6cf6-439c-8e4d-2d96162f8845") ) (segment - (start 193.3 100.7) - (end 190 100.7) + (start 165.03 100.732857) + (end 161.73 100.732857) (width 0.2) (layer "F.Cu") (net 15) (uuid "2bb9caf3-ec8e-47a0-a7e7-47436a24dd37") ) (segment - (start 194.75 99.25) - (end 193.3 100.7) + (start 166.48 99.282857) + (end 165.03 100.732857) (width 0.2) (layer "F.Cu") (net 15) (uuid "e402f8aa-4d8c-4ea0-8deb-0fa56593f2f2") ) (via - (at 194.75 99.25) + (at 166.48 99.282857) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") @@ -9194,21 +9536,13 @@ (uuid "2e55b915-80ac-49a6-b986-27306278db37") ) (segment - (start 194.715 99.285) - (end 194.75 99.25) + (start 166.445 99.317857) + (end 166.48 99.282857) (width 0.2) (layer "B.Cu") (net 15) (uuid "4110930c-d73b-46bc-92ca-8ed238a3d9e1") ) - (segment - (start 194.715 99.311111) - (end 201.776111 92.25) - (width 0.2) - (layer "B.Cu") - (net 15) - (uuid "7bcd2467-c0e1-43f5-a8a9-45524d680f77") - ) (segment (start 212.375 92.25) (end 214.38 90.245) @@ -9226,29 +9560,13 @@ (uuid "8a95be3b-a21b-404f-9c42-2d0a72e2bbe1") ) (segment - (start 194.715 99.311111) - (end 194.715 99.285) + (start 166.445 99.343968) + (end 166.445 99.317857) (width 0.2) (layer "B.Cu") (net 15) (uuid "b3ce3984-21fb-4831-bee9-941cb0ca2e43") ) - (segment - (start 187 97.273) - (end 178.25 97.273) - (width 0.2) - (layer "B.Cu") - (net 16) - (uuid "148185f3-3681-455c-b0ea-312a678ff43f") - ) - (segment - (start 88.584 97.273) - (end 179.523 97.273) - (width 0.2) - (layer "B.Cu") - (net 16) - (uuid "153b7cbe-a1c6-4a1d-8667-40c00bd91bbd") - ) (segment (start 86.92 96.38) (end 87.817 97.277) @@ -9257,14 +9575,6 @@ (net 16) (uuid "173d5279-964f-4167-8282-4e2a872357cb") ) - (segment - (start 178.25 97.273) - (end 178.75 97.273) - (width 0.2) - (layer "B.Cu") - (net 16) - (uuid "46c0ebc2-54ba-402b-bc84-729d5ca84776") - ) (segment (start 88.58 97.277) (end 88.584 97.273) @@ -9274,16 +9584,16 @@ (uuid "59f19843-7a8d-4816-97e3-5b7505f054aa") ) (segment - (start 187.477 97.273) - (end 187 97.273) + (start 159.207 97.305857) + (end 158.73 97.305857) (width 0.2) (layer "B.Cu") (net 16) (uuid "d8cf41f8-a64e-48e1-a704-1198c45a366e") ) (segment - (start 191.25 93.5) - (end 187.477 97.273) + (start 162.98 93.532857) + (end 159.207 97.305857) (width 0.2) (layer "B.Cu") (net 16) @@ -9298,16 +9608,8 @@ (uuid "e8083a1c-3db0-454e-8473-c4ea7846b68a") ) (segment - (start 189.816714 99.281) - (end 85.879 99.281) - (width 0.2) - (layer "B.Cu") - (net 17) - (uuid "29cb09c3-a61c-409c-9288-ccb55900412c") - ) - (segment - (start 191.25 100.714286) - (end 189.816714 99.281) + (start 162.98 100.747143) + (end 161.546714 99.313857) (width 0.2) (layer "B.Cu") (net 17) @@ -9330,24 +9632,16 @@ (uuid "15dfcd0a-9b50-4260-a157-0e4d28bcbf27") ) (segment - (start 190.858571 98.88) - (end 85.01 98.88) - (width 0.2) - (layer "B.Cu") - (net 18) - (uuid "60f07d3f-0c07-447d-902d-877f2139259b") - ) - (segment - (start 191.25 99.271429) - (end 190.858571 98.88) + (start 162.98 99.304286) + (end 162.588571 98.912857) (width 0.2) (layer "B.Cu") (net 18) (uuid "a379dd26-5102-4f64-825e-1e419ed3ea17") ) (segment - (start 187.322 98.078) - (end 189 96.4) + (start 159.052 98.110857) + (end 160.73 96.432857) (width 0.2) (layer "F.Cu") (net 19) @@ -9361,14 +9655,6 @@ (net 19) (uuid "2754e3cf-7db2-4cf9-bcb5-2551df06142d") ) - (segment - (start 81.6 98.078) - (end 187.322 98.078) - (width 0.2) - (layer "F.Cu") - (net 19) - (uuid "5ab1b27e-0a69-4699-a0f7-6cfe2cb410d2") - ) (segment (start 79.3 96.38) (end 80.998 98.078) @@ -9386,24 +9672,16 @@ (uuid "77376b60-4282-41b5-b6b3-5245966689eb") ) (segment - (start 82.696 97.276) - (end 185.25 97.276) - (width 0.2) - (layer "F.Cu") - (net 20) - (uuid "80476c5c-5e17-4464-bd3a-33276b93161c") - ) - (segment - (start 185.224 97.276) - (end 189 93.5) + (start 156.954 97.308857) + (end 160.73 93.532857) (width 0.2) (layer "F.Cu") (net 20) (uuid "9f287f1e-468e-426f-b96f-d1662e7d1a72") ) (segment - (start 185 97.276) - (end 185.224 97.276) + (start 156.73 97.308857) + (end 156.954 97.308857) (width 0.2) (layer "F.Cu") (net 20) @@ -9418,8 +9696,8 @@ (uuid "15d660b4-5533-4fdb-add7-69336d0e7c2d") ) (segment - (start 191.25 97.828571) - (end 190.599571 98.479) + (start 162.98 97.861428) + (end 162.329571 98.511857) (width 0.2) (layer "B.Cu") (net 21) @@ -9449,14 +9727,6 @@ (net 21) (uuid "96dc97a4-22e0-41e9-b8cc-fcbfbe23a712") ) - (segment - (start 190.599571 98.479) - (end 115.983 98.479) - (width 0.2) - (layer "B.Cu") - (net 21) - (uuid "a186835b-30d9-4a06-8d05-04c97af57eb5") - ) (segment (start 89.484 98.476) (end 89.48 98.48) @@ -9466,8 +9736,8 @@ (uuid "f819c4d4-24c9-40b7-a4c8-373388fe0613") ) (segment - (start 188.8 100.7) - (end 189 100.7) + (start 160.53 100.732857) + (end 160.73 100.732857) (width 0.2) (layer "F.Cu") (net 22) @@ -9481,14 +9751,6 @@ (net 22) (uuid "7dc9549f-6559-467d-a182-67dda5dd6aed") ) - (segment - (start 81.8 99.281) - (end 187.381 99.281) - (width 0.2) - (layer "F.Cu") - (net 22) - (uuid "b573c6a4-da63-4d0b-ab04-2a0a3ebfc522") - ) (segment (start 79.3 100.78) (end 80.799 99.281) @@ -9498,21 +9760,13 @@ (uuid "c2bf60a3-ae96-471a-a2fc-0663f28fd054") ) (segment - (start 187.381 99.281) - (end 188.8 100.7) + (start 159.111 99.313857) + (end 160.53 100.732857) (width 0.2) (layer "F.Cu") (net 22) (uuid "dcba1b69-35af-4bf3-a53d-39f00a3e1824") ) - (segment - (start 79.89 98.88) - (end 188.63 98.88) - (width 0.2) - (layer "F.Cu") - (net 23) - (uuid "612549eb-ae40-4923-a601-47417c1fb83c") - ) (segment (start 77.99 100.78) (end 79.89 98.88) @@ -9522,8 +9776,8 @@ (uuid "804602e9-8cb8-42c3-8a80-9e0f186b4fdb") ) (segment - (start 188.63 98.88) - (end 189 99.25) + (start 160.36 98.912857) + (end 160.73 99.282857) (width 0.2) (layer "F.Cu") (net 23) @@ -9538,8 +9792,8 @@ (uuid "09cf8452-84fc-4b49-b7d3-963fd9bb8d93") ) (segment - (start 189 97.85) - (end 188.371 98.479) + (start 160.73 97.882857) + (end 160.101 98.511857) (width 0.2) (layer "F.Cu") (net 24) @@ -9554,29 +9808,13 @@ (uuid "d0d5ceb0-ec2a-441f-97e8-f8c236285e75") ) (segment - (start 188.371 98.479) - (end 80.089 98.479) - (width 0.2) - (layer "F.Cu") - (net 24) - (uuid "fb4b17bf-7000-477b-8213-e2165e0a3aa6") - ) - (segment - (start 188.518857 97.674) - (end 191.25 94.942857) + (start 160.248857 97.706857) + (end 162.98 94.975714) (width 0.2) (layer "B.Cu") (net 25) (uuid "1a8e769b-8572-41a3-81c3-cd62970ba2f6") ) - (segment - (start 178.75 97.674) - (end 188.518857 97.674) - (width 0.2) - (layer "B.Cu") - (net 25) - (uuid "53bf7a98-bae5-43f3-b840-7934f95ef4fb") - ) (segment (start 88.88 97.678) (end 88.884 97.674) @@ -9585,14 +9823,6 @@ (net 25) (uuid "a621a15a-bda2-44bd-847d-643bd5ff0005") ) - (segment - (start 88.884 97.674) - (end 180.5 97.674) - (width 0.2) - (layer "B.Cu") - (net 25) - (uuid "b2c879b1-c112-48ac-b01c-7305730541e9") - ) (segment (start 86.948 97.678) (end 88.88 97.678) @@ -9618,24 +9848,16 @@ (uuid "7ac44652-cf39-4f2f-9339-e35ad6d6f055") ) (segment - (start 81.827 97.677) - (end 186.4 97.677) - (width 0.2) - (layer "F.Cu") - (net 26) - (uuid "9190f2fb-e30f-4dab-a1fd-e8fde5c6a2bd") - ) - (segment - (start 186.4 97.677) - (end 189 95.077) + (start 158.13 97.709857) + (end 160.73 95.109857) (width 0.2) (layer "F.Cu") (net 26) (uuid "a309fb37-8606-4cb6-98a9-b9d60de89feb") ) (segment - (start 189 95.077) - (end 189 94.95) + (start 160.73 95.109857) + (end 160.73 94.982857) (width 0.2) (layer "F.Cu") (net 26) @@ -9650,16 +9872,8 @@ (uuid "1d3dc7c8-f043-4ea7-a00b-172d17cc15f1") ) (segment - (start 188.774857 99.682) - (end 86.748 99.682) - (width 0.2) - (layer "B.Cu") - (net 27) - (uuid "b9135e8f-771d-404f-a976-f631e53c87c2") - ) - (segment - (start 191.25 102.157143) - (end 188.774857 99.682) + (start 162.98 102.19) + (end 160.504857 99.714857) (width 0.2) (layer "B.Cu") (net 27) @@ -9682,21 +9896,13 @@ (uuid "744e316b-156b-49bb-9552-3775b0f7644f") ) (segment - (start 191.25 103.6) - (end 187.733 100.083) + (start 162.98 103.632857) + (end 159.463 100.115857) (width 0.2) (layer "B.Cu") (net 28) (uuid "8d86d583-5ba1-4b52-b210-ad4a9e1cc79a") ) - (segment - (start 187.733 100.083) - (end 87.167001 100.083) - (width 0.2) - (layer "B.Cu") - (net 28) - (uuid "9510eb8e-cfed-4f0c-9b23-d8f3bb3f694f") - ) (segment (start 86.079 98.079) (end 89.18 98.079) @@ -9705,14 +9911,6 @@ (net 29) (uuid "25537c8d-e6fd-4b14-8cee-b2e4e25e1f22") ) - (segment - (start 179.75 98.078) - (end 181.25 98.078) - (width 0.2) - (layer "B.Cu") - (net 29) - (uuid "3222ff57-88b2-4b74-bfb2-c1d476222ffe") - ) (segment (start 84.38 96.38) (end 86.079 98.079) @@ -9746,37 +9944,13 @@ (uuid "62038ce5-6352-49f7-a7fb-e52eea96441d") ) (segment - (start 191.25 96.385714) - (end 189.557714 98.078) + (start 162.98 96.418571) + (end 161.287714 98.110857) (width 0.2) (layer "B.Cu") (net 29) (uuid "bd753f0a-c2b7-4d39-a3a0-653bbe9fdcf4") ) - (segment - (start 181.247 98.075) - (end 115.5 98.075) - (width 0.2) - (layer "B.Cu") - (net 29) - (uuid "d0090d10-9202-48aa-a500-68cfc653a287") - ) - (segment - (start 189.557714 98.078) - (end 179.75 98.078) - (width 0.2) - (layer "B.Cu") - (net 29) - (uuid "d21ffcc7-15c1-4581-add5-4aeaa5fd76f1") - ) - (segment - (start 181.25 98.078) - (end 181.247 98.075) - (width 0.2) - (layer "B.Cu") - (net 29) - (uuid "d7e42669-c65c-4fb1-bc4a-78ce1406e732") - ) (segment (start 115.5 98.075) (end 115.68 98.075) @@ -9786,16 +9960,8 @@ (uuid "fb380dd9-c8e9-4c57-95eb-5df1b3bad929") ) (segment - (start 82.497 100.083) - (end 185.283 100.083) - (width 0.2) - (layer "F.Cu") - (net 30) - (uuid "06e69fff-2ab3-4f40-96dd-e7c766e46218") - ) - (segment - (start 185.283 100.083) - (end 188.8 103.6) + (start 157.013 100.115857) + (end 160.53 103.632857) (width 0.2) (layer "F.Cu") (net 30) @@ -9810,21 +9976,13 @@ (uuid "6b338183-16a8-4ad6-a2f3-8da2e65a565b") ) (segment - (start 188.8 103.6) - (end 189 103.6) + (start 160.53 103.632857) + (end 160.73 103.632857) (width 0.2) (layer "F.Cu") (net 30) (uuid "c34ab96c-1884-409e-9bc0-3991fc60dfc7") ) - (segment - (start 81.628 99.682) - (end 186.532 99.682) - (width 0.2) - (layer "F.Cu") - (net 31) - (uuid "00c7d606-37ff-4059-9688-778c3ea6ecdf") - ) (segment (start 80.53 100.78) (end 81.628 99.682) @@ -9834,31 +9992,31 @@ (uuid "d4f6d2ce-7133-4ec1-bd7f-8b89a11639df") ) (segment - (start 186.532 99.682) - (end 189 102.15) + (start 158.262 99.714857) + (end 160.73 102.182857) (width 0.2) (layer "F.Cu") (net 31) (uuid "edca0e65-e810-4dd8-87c1-796f498c79ce") ) (segment - (start 192.190021 100.059979) - (end 192.289964 100.059979) + (start 163.920021 100.092836) + (end 164.019964 100.092836) (width 0.2) (layer "F.Cu") (net 44) (uuid "244effc7-13f2-4f9c-bddc-e283cfce6010") ) (segment - (start 192.289964 100.059979) - (end 195.75 96.599943) + (start 164.019964 100.092836) + (end 167.48 96.6328) (width 0.2) (layer "F.Cu") (net 44) (uuid "e3a5d3f4-ae34-4ff8-ac3f-cade84480f11") ) (via - (at 192.190021 100.059979) + (at 163.920021 100.092836) (size 0.6) (drill 0.3) (layers "F.Cu" "B.Cu") @@ -9866,16 +10024,16 @@ (uuid "ac657321-f2a7-48b0-bf19-48424ec97a21") ) (segment - (start 192.25 100.714286) - (end 192.25 100) + (start 163.98 100.747143) + (end 163.98 100.032857) (width 0.2) (layer "B.Cu") (net 44) (uuid "3860c428-d283-4aab-a2ff-f9f25363bd3d") ) (segment - (start 192.25 100) - (end 192.190021 100.059979) + (start 163.98 100.032857) + (end 163.920021 100.092836) (width 0.2) (layer "B.Cu") (net 44) @@ -9892,255 +10050,13 @@ ) (min_thickness 0.25) (filled_areas_thickness no) - (fill yes + (fill (thermal_gap 0.5) (thermal_bridge_width 0.5) ) (polygon (pts - (xy 224.5 85.5) (xy 224.5 110.5) (xy 182.5 110.5) (xy 182.5 85.5) - ) - ) - (filled_polygon - (layer "B.Cu") - (pts - (xy 224.442539 85.520185) (xy 224.488294 85.572989) (xy 224.4995 85.6245) (xy 224.4995 110.3755) - (xy 224.479815 110.442539) (xy 224.427011 110.488294) (xy 224.3755 110.4995) (xy 182.6245 110.4995) - (xy 182.557461 110.479815) (xy 182.511706 110.427011) (xy 182.5005 110.3755) (xy 182.5005 100.8075) - (xy 182.520185 100.740461) (xy 182.572989 100.694706) (xy 182.6245 100.6835) (xy 187.432903 100.6835) - (xy 187.499942 100.703185) (xy 187.520584 100.719819) (xy 190.313181 103.512416) (xy 190.346666 103.573739) - (xy 190.3495 103.600097) (xy 190.3495 103.668993) (xy 190.3495 103.668995) (xy 190.349499 103.668995) - (xy 190.376418 103.804322) (xy 190.376421 103.804332) (xy 190.429221 103.931804) (xy 190.429228 103.931817) - (xy 190.505885 104.046541) (xy 190.505888 104.046545) (xy 190.603454 104.144111) (xy 190.603458 104.144114) - (xy 190.718182 104.220771) (xy 190.718195 104.220778) (xy 190.828603 104.26651) (xy 190.845672 104.27358) - (xy 190.845676 104.27358) (xy 190.845677 104.273581) (xy 190.981004 104.3005) (xy 190.981007 104.3005) - (xy 191.518995 104.3005) (xy 191.610041 104.282389) (xy 191.654328 104.27358) (xy 191.702546 104.253606) - (xy 191.772015 104.246137) (xy 191.797451 104.253606) (xy 191.814646 104.260728) (xy 191.845666 104.273578) - (xy 191.845669 104.273578) (xy 191.845672 104.27358) (xy 191.845676 104.27358) (xy 191.845677 104.273581) - (xy 191.981004 104.3005) (xy 191.981007 104.3005) (xy 192.518995 104.3005) (xy 192.610041 104.282389) - (xy 192.654328 104.27358) (xy 192.781811 104.220775) (xy 192.896542 104.144114) (xy 192.994114 104.046542) - (xy 193.070775 103.931811) (xy 193.12358 103.804328) (xy 193.144432 103.6995) (xy 193.1505 103.668995) - (xy 193.1505 103.531004) (xy 193.123581 103.395677) (xy 193.12358 103.395676) (xy 193.12358 103.395672) - (xy 193.123578 103.395667) (xy 193.070778 103.268195) (xy 193.070771 103.268182) (xy 192.994114 103.153458) - (xy 192.994111 103.153454) (xy 192.896545 103.055888) (xy 192.896541 103.055885) (xy 192.785025 102.981372) - (xy 192.74022 102.92776) (xy 192.731513 102.858435) (xy 192.761668 102.795407) (xy 192.785026 102.775167) - (xy 192.896228 102.700864) (xy 192.896229 102.700864) (xy 192.993724 102.603369) (xy 193.070328 102.488722) - (xy 193.070335 102.488709) (xy 193.123097 102.361328) (xy 193.12393 102.357143) (xy 192.374 102.357143) - (xy 192.365314 102.354592) (xy 192.356353 102.355881) (xy 192.332312 102.344902) (xy 192.306961 102.337458) - (xy 192.301033 102.330617) (xy 192.292797 102.326856) (xy 192.278507 102.304621) (xy 192.261206 102.284654) - (xy 192.258918 102.274139) (xy 192.255023 102.268078) (xy 192.25 102.233143) (xy 192.25 102.081143) - (xy 192.269685 102.014104) (xy 192.322489 101.968349) (xy 192.374 101.957143) (xy 193.12393 101.957143) - (xy 193.123097 101.952957) (xy 193.070335 101.825576) (xy 193.070328 101.825563) (xy 192.993724 101.710916) - (xy 192.896229 101.613421) (xy 192.896222 101.613415) (xy 192.785026 101.539117) (xy 192.74022 101.485505) - (xy 192.731513 101.41618) (xy 192.761667 101.353153) (xy 192.785026 101.332913) (xy 192.863467 101.2805) - (xy 192.896542 101.2584) (xy 192.994114 101.160828) (xy 193.070775 101.046097) (xy 193.12358 100.918614) - (xy 193.132389 100.874327) (xy 193.1505 100.783281) (xy 193.1505 100.64529) (xy 193.123581 100.509963) - (xy 193.12358 100.509962) (xy 193.12358 100.509958) (xy 193.123578 100.509953) (xy 193.070778 100.382481) - (xy 193.070771 100.382468) (xy 193.000119 100.276731) (xy 192.979241 100.210054) (xy 192.981604 100.183647) - (xy 192.990521 100.138822) (xy 192.990521 99.981134) (xy 192.96877 99.871789) (xy 192.960385 99.829634) - (xy 192.966612 99.760044) (xy 192.990806 99.723129) (xy 192.990253 99.722675) (xy 192.994116 99.717968) - (xy 193.070771 99.603246) (xy 193.070771 99.603245) (xy 193.070775 99.60324) (xy 193.12358 99.475757) - (xy 193.132389 99.43147) (xy 193.1505 99.340424) (xy 193.1505 99.202433) (xy 193.123581 99.067106) - (xy 193.12358 99.067105) (xy 193.12358 99.067101) (xy 193.103331 99.018215) (xy 193.070778 98.939624) - (xy 193.070771 98.939611) (xy 192.994114 98.824887) (xy 192.994111 98.824883) (xy 192.896545 98.727317) - (xy 192.896541 98.727314) (xy 192.785025 98.652801) (xy 192.74022 98.599189) (xy 192.731513 98.529864) - (xy 192.761668 98.466836) (xy 192.785026 98.446597) (xy 192.896222 98.372298) (xy 192.896229 98.372292) - (xy 192.993724 98.274797) (xy 193.070328 98.16015) (xy 193.070335 98.160137) (xy 193.123097 98.032756) - (xy 193.12393 98.028571) (xy 192.374 98.028571) (xy 192.365314 98.02602) (xy 192.356353 98.027309) - (xy 192.332312 98.01633) (xy 192.306961 98.008886) (xy 192.301033 98.002045) (xy 192.292797 97.998284) - (xy 192.278507 97.976049) (xy 192.261206 97.956082) (xy 192.258918 97.945567) (xy 192.255023 97.939506) - (xy 192.25 97.904571) (xy 192.25 97.752571) (xy 192.269685 97.685532) (xy 192.322489 97.639777) - (xy 192.374 97.628571) (xy 193.12393 97.628571) (xy 193.123097 97.624385) (xy 193.070335 97.497004) - (xy 193.070328 97.496991) (xy 192.993724 97.382344) (xy 192.896229 97.284849) (xy 192.896222 97.284843) - (xy 192.785026 97.210545) (xy 192.74022 97.156933) (xy 192.731513 97.087608) (xy 192.761667 97.024581) - (xy 192.785026 97.004341) (xy 192.826235 96.976805) (xy 192.896542 96.929828) (xy 192.994114 96.832256) - (xy 193.070775 96.717525) (xy 193.12358 96.590042) (xy 193.1505 96.454707) (xy 193.1505 96.316721) - (xy 193.1505 96.316718) (xy 193.123581 96.181391) (xy 193.12358 96.18139) (xy 193.12358 96.181386) - (xy 193.123578 96.181381) (xy 193.070778 96.053909) (xy 193.070771 96.053896) (xy 192.994114 95.939172) - (xy 192.994111 95.939168) (xy 192.896542 95.841599) (xy 192.834523 95.80016) (xy 192.821704 95.784822) - (xy 192.805489 95.773129) (xy 192.799757 95.75856) (xy 192.789718 95.746548) (xy 192.787226 95.726712) - (xy 192.779908 95.708111) (xy 192.781398 95.680306) (xy 192.781011 95.677223) (xy 192.781797 95.672867) - (xy 192.788108 95.641139) (xy 192.820492 95.579228) (xy 192.878539 95.546173) (xy 192.878349 95.545461) - (xy 192.881072 95.544731) (xy 192.881208 95.544654) (xy 192.88169 95.544565) (xy 192.886194 95.543358) - (xy 192.8862 95.543358) (xy 193.038928 95.502434) (xy 193.098377 95.468111) (xy 193.175859 95.423377) - (xy 193.187819 95.411417) (xy 193.249142 95.377932) (xy 193.318834 95.382916) (xy 193.374767 95.424788) - (xy 193.399184 95.490252) (xy 193.3995 95.499098) (xy 193.3995 101.94033) (xy 193.399499 101.940348) - (xy 193.399499 102.106054) (xy 193.399498 102.106054) (xy 193.399499 102.106057) (xy 193.440423 102.258785) - (xy 193.445788 102.268078) (xy 193.469358 102.3089) (xy 193.469359 102.308904) (xy 193.46936 102.308904) - (xy 193.499626 102.361328) (xy 193.519479 102.395714) (xy 193.519481 102.395717) (xy 193.638349 102.514585) - (xy 193.638355 102.51459) (xy 195.638425 104.51466) (xy 195.67191 104.575983) (xy 195.672361 104.578149) - (xy 195.703261 104.733491) (xy 195.703264 104.733501) (xy 195.763602 104.879172) (xy 195.763609 104.879185) - (xy 195.85121 105.010288) (xy 195.851213 105.010292) (xy 195.962707 105.121786) (xy 195.962711 105.121789) - (xy 196.093814 105.20939) (xy 196.093827 105.209397) (xy 196.220824 105.262) (xy 196.239503 105.269737) - (xy 196.394153 105.300499) (xy 196.394156 105.3005) (xy 196.394158 105.3005) (xy 196.551844 105.3005) - (xy 196.551845 105.300499) (xy 196.706497 105.269737) (xy 196.852179 105.209394) (xy 196.983289 105.121789) - (xy 197.094789 105.010289) (xy 197.182394 104.879179) (xy 197.242737 104.733497) (xy 197.2735 104.578842) - (xy 197.2735 104.421158) (xy 197.2735 104.421155) (xy 197.273499 104.421153) (xy 197.244145 104.273581) - (xy 197.242737 104.266503) (xy 197.223796 104.220775) (xy 197.182397 104.120827) (xy 197.18239 104.120814) - (xy 197.094789 103.989711) (xy 197.094786 103.989707) (xy 196.983292 103.878213) (xy 196.983288 103.87821) - (xy 196.852185 103.790609) (xy 196.852172 103.790602) (xy 196.706501 103.730264) (xy 196.706491 103.730261) - (xy 196.551149 103.699361) (xy 196.489238 103.666976) (xy 196.48766 103.665425) (xy 194.636819 101.814584) - (xy 194.603334 101.753261) (xy 194.6005 101.726903) (xy 194.6005 100.1745) (xy 194.620185 100.107461) - (xy 194.672989 100.061706) (xy 194.7245 100.0505) (xy 194.828844 100.0505) (xy 194.828845 100.050499) - (xy 194.983497 100.019737) (xy 195.129179 99.959394) (xy 195.260289 99.871789) (xy 195.371789 99.760289) - (xy 195.459394 99.629179) (xy 195.519737 99.483497) (xy 195.544154 99.360744) (xy 195.56073 99.329054) - (xy 203.149498 99.329054) (xy 203.15799 99.360745) (xy 203.190423 99.481785) (xy 203.269481 99.618716) - (xy 203.269483 99.618718) (xy 205.915425 102.26466) (xy 205.94891 102.325983) (xy 205.949361 102.328149) - (xy 205.980261 102.483491) (xy 205.980264 102.483501) (xy 206.040602 102.629172) (xy 206.040609 102.629185) - (xy 206.124135 102.75419) (xy 206.145013 102.820868) (xy 206.126528 102.888248) (xy 206.093919 102.923399) - (xy 205.937534 103.03702) (xy 205.797021 103.177533) (xy 205.680213 103.338305) (xy 205.589994 103.515367) - (xy 205.589993 103.51537) (xy 205.528587 103.704362) (xy 205.4975 103.900639) (xy 205.4975 104.09936) - (xy 205.528587 104.295637) (xy 205.589993 104.484629) (xy 205.589994 104.484632) (xy 205.680074 104.661422) - (xy 205.680213 104.661694) (xy 205.797019 104.822464) (xy 205.937536 104.962981) (xy 206.098306 105.079787) - (xy 206.180733 105.121786) (xy 206.275367 105.170005) (xy 206.27537 105.170006) (xy 206.369866 105.200709) - (xy 206.464364 105.231413) (xy 206.660639 105.2625) (xy 206.66064 105.2625) (xy 206.85936 105.2625) - (xy 206.859361 105.2625) (xy 207.055636 105.231413) (xy 207.244632 105.170005) (xy 207.421694 105.079787) - (xy 207.582464 104.962981) (xy 207.722981 104.822464) (xy 207.839787 104.661694) (xy 207.919515 104.505218) - (xy 207.96749 104.454423) (xy 208.035311 104.437628) (xy 208.101446 104.460165) (xy 208.140484 104.505218) - (xy 208.220213 104.661694) (xy 208.337019 104.822464) (xy 208.477536 104.962981) (xy 208.638306 105.079787) - (xy 208.720733 105.121786) (xy 208.815367 105.170005) (xy 208.81537 105.170006) (xy 208.909866 105.200709) - (xy 209.004364 105.231413) (xy 209.200639 105.2625) (xy 209.20064 105.2625) (xy 209.39936 105.2625) - (xy 209.399361 105.2625) (xy 209.595636 105.231413) (xy 209.784632 105.170005) (xy 209.961694 105.079787) - (xy 210.122464 104.962981) (xy 210.262981 104.822464) (xy 210.379787 104.661694) (xy 210.459515 104.505218) - (xy 210.50749 104.454423) (xy 210.575311 104.437628) (xy 210.641446 104.460165) (xy 210.680484 104.505218) - (xy 210.760213 104.661694) (xy 210.877019 104.822464) (xy 211.017536 104.962981) (xy 211.178306 105.079787) - (xy 211.260733 105.121786) (xy 211.355367 105.170005) (xy 211.35537 105.170006) (xy 211.449866 105.200709) - (xy 211.544364 105.231413) (xy 211.740639 105.2625) (xy 211.74064 105.2625) (xy 211.93936 105.2625) - (xy 211.939361 105.2625) (xy 212.135636 105.231413) (xy 212.324632 105.170005) (xy 212.501694 105.079787) - (xy 212.662464 104.962981) (xy 212.802981 104.822464) (xy 212.919787 104.661694) (xy 212.999515 104.505218) - (xy 213.04749 104.454423) (xy 213.115311 104.437628) (xy 213.181446 104.460165) (xy 213.220484 104.505218) - (xy 213.300213 104.661694) (xy 213.417019 104.822464) (xy 213.557536 104.962981) (xy 213.718306 105.079787) - (xy 213.800733 105.121786) (xy 213.895367 105.170005) (xy 213.89537 105.170006) (xy 213.989866 105.200709) - (xy 214.084364 105.231413) (xy 214.280639 105.2625) (xy 214.28064 105.2625) (xy 214.47936 105.2625) - (xy 214.479361 105.2625) (xy 214.675636 105.231413) (xy 214.864632 105.170005) (xy 215.041694 105.079787) - (xy 215.202464 104.962981) (xy 215.342981 104.822464) (xy 215.459787 104.661694) (xy 215.539515 104.505218) - (xy 215.58749 104.454423) (xy 215.655311 104.437628) (xy 215.721446 104.460165) (xy 215.760484 104.505218) - (xy 215.840213 104.661694) (xy 215.957019 104.822464) (xy 216.097536 104.962981) (xy 216.258306 105.079787) - (xy 216.340733 105.121786) (xy 216.435367 105.170005) (xy 216.43537 105.170006) (xy 216.529866 105.200709) - (xy 216.624364 105.231413) (xy 216.820639 105.2625) (xy 216.82064 105.2625) (xy 217.01936 105.2625) - (xy 217.019361 105.2625) (xy 217.215636 105.231413) (xy 217.404632 105.170005) (xy 217.581694 105.079787) - (xy 217.742464 104.962981) (xy 217.882981 104.822464) (xy 217.999787 104.661694) (xy 218.079796 104.504667) - (xy 218.127769 104.453872) (xy 218.19559 104.437077) (xy 218.261725 104.459614) (xy 218.300765 104.504668) - (xy 218.380641 104.661432) (xy 218.40773 104.698715) (xy 218.407731 104.698716) (xy 219.022352 104.084094) - (xy 219.045792 104.171571) (xy 219.104311 104.27293) (xy 219.18707 104.355689) (xy 219.288429 104.414208) - (xy 219.375905 104.437647) (xy 218.761283 105.052268) (xy 218.761283 105.052269) (xy 218.798567 105.079358) - (xy 218.975562 105.169542) (xy 219.164477 105.230924) (xy 219.360679 105.262) (xy 219.559321 105.262) - (xy 219.75552 105.230924) (xy 219.755523 105.230924) (xy 219.944437 105.169542) (xy 220.121425 105.079362) - (xy 220.158716 105.052268) (xy 219.544095 104.437647) (xy 219.631571 104.414208) (xy 219.73293 104.355689) - (xy 219.815689 104.27293) (xy 219.874208 104.171571) (xy 219.897647 104.084094) (xy 220.512268 104.698715) - (xy 220.539364 104.661422) (xy 220.619234 104.504669) (xy 220.667208 104.453872) (xy 220.735029 104.437077) - (xy 220.801164 104.459614) (xy 220.840203 104.504667) (xy 220.920213 104.661694) (xy 221.037019 104.822464) - (xy 221.177536 104.962981) (xy 221.338306 105.079787) (xy 221.420733 105.121786) (xy 221.515367 105.170005) - (xy 221.51537 105.170006) (xy 221.609866 105.200709) (xy 221.704364 105.231413) (xy 221.900639 105.2625) - (xy 221.90064 105.2625) (xy 222.09936 105.2625) (xy 222.099361 105.2625) (xy 222.295636 105.231413) - (xy 222.484632 105.170005) (xy 222.661694 105.079787) (xy 222.822464 104.962981) (xy 222.962981 104.822464) - (xy 223.079787 104.661694) (xy 223.170005 104.484632) (xy 223.231413 104.295636) (xy 223.2625 104.099361) - (xy 223.2625 103.900639) (xy 223.231413 103.704364) (xy 223.177954 103.539833) (xy 223.170006 103.51537) - (xy 223.170005 103.515367) (xy 223.109019 103.395677) (xy 223.079787 103.338306) (xy 222.962981 103.177536) - (xy 222.822464 103.037019) (xy 222.661694 102.920213) (xy 222.621043 102.8995) (xy 222.484632 102.829994) - (xy 222.484629 102.829993) (xy 222.295637 102.768587) (xy 222.145596 102.744823) (xy 222.099361 102.7375) - (xy 221.900639 102.7375) (xy 221.854404 102.744823) (xy 221.704362 102.768587) (xy 221.51537 102.829993) - (xy 221.515367 102.829994) (xy 221.338305 102.920213) (xy 221.177533 103.037021) (xy 221.037021 103.177533) - (xy 220.920213 103.338305) (xy 220.840204 103.495331) (xy 220.792229 103.546127) (xy 220.724408 103.562922) - (xy 220.658273 103.540384) (xy 220.619234 103.495331) (xy 220.539358 103.338567) (xy 220.512268 103.301283) - (xy 219.897647 103.915904) (xy 219.874208 103.828429) (xy 219.815689 103.72707) (xy 219.73293 103.644311) - (xy 219.631571 103.585792) (xy 219.544094 103.562352) (xy 220.158716 102.947731) (xy 220.158715 102.94773) - (xy 220.121432 102.920641) (xy 219.944437 102.830457) (xy 219.755522 102.769075) (xy 219.559321 102.738) - (xy 219.360679 102.738) (xy 219.164479 102.769075) (xy 219.164476 102.769075) (xy 218.975562 102.830457) - (xy 218.798564 102.920643) (xy 218.761283 102.947729) (xy 218.761282 102.94773) (xy 219.375906 103.562352) - (xy 219.288429 103.585792) (xy 219.18707 103.644311) (xy 219.104311 103.72707) (xy 219.045792 103.828429) - (xy 219.022352 103.915905) (xy 218.40773 103.301282) (xy 218.407729 103.301283) (xy 218.380641 103.338566) - (xy 218.300764 103.495332) (xy 218.25279 103.546127) (xy 218.184969 103.562922) (xy 218.118834 103.540384) - (xy 218.079796 103.495332) (xy 217.999787 103.338306) (xy 217.882981 103.177536) (xy 217.742464 103.037019) - (xy 217.581694 102.920213) (xy 217.541043 102.8995) (xy 217.404632 102.829994) (xy 217.404629 102.829993) - (xy 217.215637 102.768587) (xy 217.065596 102.744823) (xy 217.019361 102.7375) (xy 216.820639 102.7375) - (xy 216.774404 102.744823) (xy 216.624362 102.768587) (xy 216.43537 102.829993) (xy 216.435367 102.829994) - (xy 216.258305 102.920213) (xy 216.097533 103.037021) (xy 215.957021 103.177533) (xy 215.840213 103.338305) - (xy 215.760485 103.49478) (xy 215.71251 103.545576) (xy 215.644689 103.562371) (xy 215.578554 103.539833) - (xy 215.539515 103.49478) (xy 215.489019 103.395677) (xy 215.459787 103.338306) (xy 215.342981 103.177536) - (xy 215.202464 103.037019) (xy 215.041694 102.920213) (xy 215.001043 102.8995) (xy 214.864632 102.829994) - (xy 214.864629 102.829993) (xy 214.675637 102.768587) (xy 214.525596 102.744823) (xy 214.479361 102.7375) - (xy 214.280639 102.7375) (xy 214.234404 102.744823) (xy 214.084362 102.768587) (xy 213.89537 102.829993) - (xy 213.895367 102.829994) (xy 213.718305 102.920213) (xy 213.557533 103.037021) (xy 213.417021 103.177533) - (xy 213.300213 103.338305) (xy 213.220485 103.49478) (xy 213.17251 103.545576) (xy 213.104689 103.562371) - (xy 213.038554 103.539833) (xy 212.999515 103.49478) (xy 212.949019 103.395677) (xy 212.919787 103.338306) - (xy 212.802981 103.177536) (xy 212.662464 103.037019) (xy 212.501694 102.920213) (xy 212.461043 102.8995) - (xy 212.324632 102.829994) (xy 212.324629 102.829993) (xy 212.135637 102.768587) (xy 211.985596 102.744823) - (xy 211.939361 102.7375) (xy 211.740639 102.7375) (xy 211.694404 102.744823) (xy 211.544362 102.768587) - (xy 211.35537 102.829993) (xy 211.355367 102.829994) (xy 211.178305 102.920213) (xy 211.017533 103.037021) - (xy 210.877021 103.177533) (xy 210.760213 103.338305) (xy 210.680485 103.49478) (xy 210.63251 103.545576) - (xy 210.564689 103.562371) (xy 210.498554 103.539833) (xy 210.459515 103.49478) (xy 210.409019 103.395677) - (xy 210.379787 103.338306) (xy 210.262981 103.177536) (xy 210.122464 103.037019) (xy 209.961694 102.920213) - (xy 209.921043 102.8995) (xy 209.784632 102.829994) (xy 209.784629 102.829993) (xy 209.595637 102.768587) - (xy 209.445596 102.744823) (xy 209.399361 102.7375) (xy 209.200639 102.7375) (xy 209.154404 102.744823) - (xy 209.004362 102.768587) (xy 208.81537 102.829993) (xy 208.815367 102.829994) (xy 208.638305 102.920213) - (xy 208.477533 103.037021) (xy 208.337021 103.177533) (xy 208.220213 103.338305) (xy 208.140485 103.49478) - (xy 208.09251 103.545576) (xy 208.024689 103.562371) (xy 207.958554 103.539833) (xy 207.919515 103.49478) - (xy 207.869019 103.395677) (xy 207.839787 103.338306) (xy 207.722981 103.177536) (xy 207.582464 103.037019) - (xy 207.421694 102.920213) (xy 207.421691 102.920211) (xy 207.420436 102.919442) (xy 207.420058 102.919024) - (xy 207.417752 102.917349) (xy 207.418104 102.916864) (xy 207.37356 102.867631) (xy 207.362137 102.798701) - (xy 207.382123 102.744823) (xy 207.45939 102.629185) (xy 207.45939 102.629184) (xy 207.459394 102.629179) - (xy 207.519737 102.483497) (xy 207.5505 102.328842) (xy 207.5505 102.171158) (xy 207.5505 102.171155) - (xy 207.550499 102.171153) (xy 207.519737 102.016503) (xy 207.499791 101.968349) (xy 207.459397 101.870827) - (xy 207.45939 101.870814) (xy 207.371789 101.739711) (xy 207.371786 101.739707) (xy 207.260292 101.628213) - (xy 207.260288 101.62821) (xy 207.129185 101.540609) (xy 207.129172 101.540602) (xy 206.983501 101.480264) - (xy 206.983491 101.480261) (xy 206.828151 101.449362) (xy 206.766241 101.416977) (xy 206.764662 101.415426) - (xy 204.118718 98.769483) (xy 204.118716 98.769481) (xy 203.981785 98.690423) (xy 203.829057 98.649499) - (xy 203.670943 98.649499) (xy 203.556397 98.680192) (xy 203.518214 98.690423) (xy 203.381284 98.769481) - (xy 203.381281 98.769483) (xy 203.269483 98.881281) (xy 203.269481 98.881284) (xy 203.190423 99.018214) - (xy 203.190423 99.018215) (xy 203.149499 99.170943) (xy 203.149499 99.170945) (xy 203.149499 99.329054) - (xy 203.149498 99.329054) (xy 195.56073 99.329054) (xy 195.576538 99.298834) (xy 195.578032 99.297313) - (xy 200.704193 94.171153) (xy 205.4495 94.171153) (xy 205.4495 94.328846) (xy 205.480261 94.483489) - (xy 205.480264 94.483501) (xy 205.540602 94.629172) (xy 205.540609 94.629185) (xy 205.62821 94.760288) - (xy 205.628213 94.760292) (xy 205.739707 94.871786) (xy 205.739711 94.871789) (xy 205.870814 94.95939) - (xy 205.870827 94.959397) (xy 206.016498 95.019735) (xy 206.016503 95.019737) (xy 206.171153 95.050499) - (xy 206.171156 95.0505) (xy 206.171158 95.0505) (xy 206.328844 95.0505) (xy 206.328845 95.050499) - (xy 206.483497 95.019737) (xy 206.629179 94.959394) (xy 206.760289 94.871789) (xy 206.871789 94.760289) - (xy 206.959394 94.629179) (xy 207.019737 94.483497) (xy 207.0505 94.328842) (xy 207.0505 94.171158) - (xy 207.0505 94.171155) (xy 207.050499 94.171153) (xy 207.019738 94.01651) (xy 207.019737 94.016503) - (xy 207.019735 94.016498) (xy 206.959397 93.870827) (xy 206.95939 93.870814) (xy 206.871789 93.739711) - (xy 206.871786 93.739707) (xy 206.760292 93.628213) (xy 206.760288 93.62821) (xy 206.629185 93.540609) - (xy 206.629172 93.540602) (xy 206.483501 93.480264) (xy 206.483489 93.480261) (xy 206.328845 93.4495) - (xy 206.328842 93.4495) (xy 206.171158 93.4495) (xy 206.171155 93.4495) (xy 206.01651 93.480261) - (xy 206.016498 93.480264) (xy 205.870827 93.540602) (xy 205.870814 93.540609) (xy 205.739711 93.62821) - (xy 205.739707 93.628213) (xy 205.628213 93.739707) (xy 205.62821 93.739711) (xy 205.540609 93.870814) - (xy 205.540602 93.870827) (xy 205.480264 94.016498) (xy 205.480261 94.01651) (xy 205.4495 94.171153) - (xy 200.704193 94.171153) (xy 201.988527 92.886819) (xy 202.04985 92.853334) (xy 202.076208 92.8505) - (xy 212.288331 92.8505) (xy 212.288347 92.850501) (xy 212.295943 92.850501) (xy 212.454054 92.850501) - (xy 212.454057 92.850501) (xy 212.606785 92.809577) (xy 212.656904 92.780639) (xy 212.743716 92.73052) - (xy 212.85552 92.618716) (xy 212.85552 92.618714) (xy 212.865728 92.608507) (xy 212.86573 92.608504) - (xy 214.738506 90.735728) (xy 214.738511 90.735724) (xy 214.748714 90.72552) (xy 214.748716 90.72552) - (xy 214.86052 90.613716) (xy 214.916804 90.516228) (xy 214.939577 90.476785) (xy 214.9805 90.324058) - (xy 214.9805 90.165943) (xy 214.9805 89.94673) (xy 215.000185 89.879691) (xy 215.037866 89.842808) - (xy 215.037752 89.842651) (xy 215.038823 89.841872) (xy 215.039715 89.841) (xy 215.04169 89.839789) - (xy 215.041689 89.839789) (xy 215.041694 89.839787) (xy 215.202464 89.722981) (xy 215.342981 89.582464) - (xy 215.459787 89.421694) (xy 215.539515 89.265218) (xy 215.58749 89.214423) (xy 215.655311 89.197628) - (xy 215.721446 89.220165) (xy 215.760484 89.265218) (xy 215.840213 89.421694) (xy 215.957019 89.582464) - (xy 216.097536 89.722981) (xy 216.258306 89.839787) (xy 216.3195 89.870967) (xy 216.435367 89.930005) - (xy 216.43537 89.930006) (xy 216.529866 89.960709) (xy 216.624364 89.991413) (xy 216.820639 90.0225) - (xy 216.82064 90.0225) (xy 217.01936 90.0225) (xy 217.019361 90.0225) (xy 217.215636 89.991413) - (xy 217.404632 89.930005) (xy 217.581694 89.839787) (xy 217.742464 89.722981) (xy 217.882981 89.582464) - (xy 217.999787 89.421694) (xy 218.079515 89.265218) (xy 218.12749 89.214423) (xy 218.195311 89.197628) - (xy 218.261446 89.220165) (xy 218.300484 89.265218) (xy 218.380213 89.421694) (xy 218.497019 89.582464) - (xy 218.637536 89.722981) (xy 218.798306 89.839787) (xy 218.8595 89.870967) (xy 218.975367 89.930005) - (xy 218.97537 89.930006) (xy 219.069866 89.960709) (xy 219.164364 89.991413) (xy 219.360639 90.0225) - (xy 219.36064 90.0225) (xy 219.55936 90.0225) (xy 219.559361 90.0225) (xy 219.755636 89.991413) - (xy 219.944632 89.930005) (xy 220.121694 89.839787) (xy 220.282464 89.722981) (xy 220.422981 89.582464) - (xy 220.539787 89.421694) (xy 220.619515 89.265218) (xy 220.66749 89.214423) (xy 220.735311 89.197628) - (xy 220.801446 89.220165) (xy 220.840484 89.265218) (xy 220.920213 89.421694) (xy 221.037019 89.582464) - (xy 221.177536 89.722981) (xy 221.338306 89.839787) (xy 221.3995 89.870967) (xy 221.515367 89.930005) - (xy 221.51537 89.930006) (xy 221.609866 89.960709) (xy 221.704364 89.991413) (xy 221.900639 90.0225) - (xy 221.90064 90.0225) (xy 222.09936 90.0225) (xy 222.099361 90.0225) (xy 222.295636 89.991413) - (xy 222.484632 89.930005) (xy 222.661694 89.839787) (xy 222.822464 89.722981) (xy 222.962981 89.582464) - (xy 223.079787 89.421694) (xy 223.170005 89.244632) (xy 223.231413 89.055636) (xy 223.2625 88.859361) - (xy 223.2625 88.660639) (xy 223.231413 88.464364) (xy 223.170005 88.275368) (xy 223.170005 88.275367) - (xy 223.079786 88.098305) (xy 222.962981 87.937536) (xy 222.822464 87.797019) (xy 222.661694 87.680213) - (xy 222.66169 87.68021) (xy 222.659715 87.679) (xy 222.659121 87.678343) (xy 222.657752 87.677349) - (xy 222.65796 87.677061) (xy 222.612837 87.62719) (xy 222.6005 87.57327) (xy 222.6005 86.271945) - (xy 222.6005 86.271943) (xy 222.581625 86.2015) (xy 222.559577 86.119215) (xy 222.510542 86.034284) - (xy 222.48052 85.982284) (xy 222.368716 85.87048) (xy 222.368715 85.870479) (xy 222.364385 85.866149) - (xy 222.364374 85.866139) (xy 222.210416 85.712181) (xy 222.176931 85.650858) (xy 222.181915 85.581166) - (xy 222.223787 85.525233) (xy 222.289251 85.500816) (xy 222.298097 85.5005) (xy 224.3755 85.5005) + (xy 224.5 85.5) (xy 224.5 110.5) (xy 156.54 110.5) (xy 156.54 85.5) ) ) ) diff --git a/baby-mobile-v5.kicad_sch b/baby-mobile-v5.kicad_sch index a70f515..bfd7c32 100644 --- a/baby-mobile-v5.kicad_sch +++ b/baby-mobile-v5.kicad_sch @@ -2872,10 +2872,10 @@ (uuid "017eac50-3406-4cc1-bd32-b83e5696234a") ) (junction - (at 311.16 90.17) + (at 71.12 153.67) (diameter 0) (color 0 0 0 0) - (uuid "19afce19-eefe-43da-9ff9-594d5e7450df") + (uuid "17e89eec-f620-4c7a-8887-8563a7dca664") ) (junction (at 330.2 145.97) @@ -2896,10 +2896,28 @@ (uuid "6d7a0476-c2d8-409f-acf0-c51d5cc44c54") ) (junction - (at 311.16 87.63) + (at 309.89 87.63) (diameter 0) (color 0 0 0 0) - (uuid "eb2c5735-191b-4d6e-b9b7-6f9a1ba9da7c") + (uuid "7f9aeab0-b298-49b0-95a9-13f903c592bd") + ) + (junction + (at 311.16 90.17) + (diameter 0) + (color 0 0 0 0) + (uuid "b41da60f-ed92-4caa-94b4-a8f17f7b37f7") + ) + (junction + (at 309.88 87.63) + (diameter 0) + (color 0 0 0 0) + (uuid "b4ef88db-519f-48de-b199-16343987ba1f") + ) + (junction + (at 67.31 166.37) + (diameter 0) + (color 0 0 0 0) + (uuid "e2984591-bbbd-47a7-b9f3-f6e744a0177d") ) (junction (at 207.01 204.47) @@ -2913,6 +2931,12 @@ (color 0 0 0 0) (uuid "ef3a8681-bfa6-40af-9816-ec3346f9cb23") ) + (junction + (at 304.8 87.63) + (diameter 0) + (color 0 0 0 0) + (uuid "fa1bd6ee-5560-42cc-8cc4-182475fa5265") + ) (no_connect (at 223.52 234.95) (uuid "519c324a-3d40-42a9-a963-f53dd2b596c0") @@ -2953,6 +2977,16 @@ ) (uuid "0a315227-f5b7-4de4-9dc2-5a9da0d1e499") ) + (wire + (pts + (xy 304.8 91.44) (xy 304.72 91.44) + ) + (stroke + (width 0) + (type default) + ) + (uuid "0e7e7f7d-d9d1-48e4-b0a4-efa3065d2db0") + ) (wire (pts (xy 342.9 92.69) (xy 342.9 92.61) @@ -3005,13 +3039,23 @@ ) (wire (pts - (xy 311.16 87.63) (xy 312.43 87.63) + (xy 67.31 166.37) (xy 67.31 171.45) ) (stroke (width 0) (type default) ) - (uuid "24800943-9fa3-42fe-8fc7-e4e93239651c") + (uuid "1e67db82-9086-4cc6-acee-2e0c4028091c") + ) + (wire + (pts + (xy 62.23 166.37) (xy 67.31 166.37) + ) + (stroke + (width 0) + (type default) + ) + (uuid "1fbb2173-f466-4fb3-a1e1-1fd99f26203e") ) (wire (pts @@ -3053,6 +3097,16 @@ ) (uuid "33cecf5c-c05b-46be-b395-224afca830f4") ) + (wire + (pts + (xy 304.8 87.63) (xy 297.18 87.63) + ) + (stroke + (width 0) + (type default) + ) + (uuid "34fe1a69-5ff4-4a92-871e-1af3f56feee9") + ) (wire (pts (xy 330.2 148.59) (xy 330.2 149.86) @@ -3233,6 +3287,16 @@ ) (uuid "7a32a98d-a07b-4e23-97a7-ff5c2761b4a9") ) + (wire + (pts + (xy 67.31 171.45) (xy 65.96 171.45) + ) + (stroke + (width 0) + (type default) + ) + (uuid "7a5c76e9-bfde-4599-a03c-144047a97246") + ) (wire (pts (xy 207.01 201.93) (xy 223.52 201.93) @@ -3243,6 +3307,16 @@ ) (uuid "7b09f59c-2799-44c6-bf90-c378030ea9b1") ) + (wire + (pts + (xy 62.23 153.67) (xy 71.12 153.67) + ) + (stroke + (width 0) + (type default) + ) + (uuid "83ec5324-e898-46e6-9fe2-31d9a05b3da0") + ) (wire (pts (xy 334.01 90.15) (xy 334.01 90.17) @@ -3273,6 +3347,16 @@ ) (uuid "8b2e0b76-8ce1-43a5-b900-90897c8f6ac4") ) + (wire + (pts + (xy 71.12 153.67) (xy 71.12 157.48) + ) + (stroke + (width 0) + (type default) + ) + (uuid "8cbf3c35-fa13-44b4-bcf4-21252fe25fcb") + ) (wire (pts (xy 231.14 207.01) (xy 243.84 207.01) @@ -3283,6 +3367,26 @@ ) (uuid "8f5e7827-d21e-468e-b028-9b178eb97914") ) + (wire + (pts + (xy 304.8 87.63) (xy 304.8 91.44) + ) + (stroke + (width 0) + (type default) + ) + (uuid "8fbf48d3-9d5a-45d9-8e37-a4596be807cd") + ) + (wire + (pts + (xy 309.89 87.63) (xy 309.88 87.63) + ) + (stroke + (width 0) + (type default) + ) + (uuid "930181c0-0f67-43b3-8e66-2256b00ebbc0") + ) (wire (pts (xy 302.26 162.56) (xy 299.72 162.56) @@ -3303,6 +3407,16 @@ ) (uuid "968c6461-fd30-4fe2-9334-56f61262ca7c") ) + (wire + (pts + (xy 67.31 166.37) (xy 78.74 166.37) + ) + (stroke + (width 0) + (type default) + ) + (uuid "9a505b6a-5abe-47a4-9e70-9865514e51a2") + ) (wire (pts (xy 312.43 90.17) (xy 311.16 90.17) @@ -3325,7 +3439,7 @@ ) (wire (pts - (xy 311.16 90.17) (xy 309.89 90.17) + (xy 309.89 90.17) (xy 311.16 90.17) ) (stroke (width 0) @@ -3383,6 +3497,16 @@ ) (uuid "b103c0d7-a6ac-40b0-9282-0e3442120b6c") ) + (wire + (pts + (xy 309.88 87.63) (xy 304.8 87.63) + ) + (stroke + (width 0) + (type default) + ) + (uuid "b4e0a463-68c6-49f4-96e9-2451c3680296") + ) (wire (pts (xy 223.52 217.17) (xy 207.01 217.17) @@ -3473,6 +3597,26 @@ ) (uuid "cf357f80-93fc-47ae-8a9d-c3f2a82281d2") ) + (wire + (pts + (xy 309.88 85.09) (xy 311.16 85.09) + ) + (stroke + (width 0) + (type default) + ) + (uuid "d23b020f-474a-44c7-aa50-5d2d6a637b91") + ) + (wire + (pts + (xy 71.12 157.48) (xy 71.04 157.48) + ) + (stroke + (width 0) + (type default) + ) + (uuid "d5374591-14af-4a6a-a74f-9e6b20508561") + ) (wire (pts (xy 231.14 237.49) (xy 243.84 237.49) @@ -3523,6 +3667,16 @@ ) (uuid "dc56447b-2913-4073-a3e6-ae9a14e1130a") ) + (wire + (pts + (xy 71.12 153.67) (xy 78.74 153.67) + ) + (stroke + (width 0) + (type default) + ) + (uuid "dce908f3-84d4-4a63-89a0-3e8809dbb8a5") + ) (wire (pts (xy 334.01 90.17) (xy 334.02 90.17) @@ -3563,6 +3717,16 @@ ) (uuid "f96fe0e4-f1ba-4802-b049-1ac2454eeab6") ) + (wire + (pts + (xy 309.88 87.63) (xy 309.88 85.09) + ) + (stroke + (width 0) + (type default) + ) + (uuid "f9b0891a-84da-4d7e-9086-65a34b6b7d6f") + ) (wire (pts (xy 339.09 76.18) (xy 339.17 76.18) @@ -3654,7 +3818,7 @@ (uuid "21f44609-2138-4f22-9db6-f9e7fee8972d") ) (label "C_3V3" - (at 159.58 167.43 270) + (at 55.96 171.45 180) (effects (font (size 1.27 1.27) @@ -3693,7 +3857,7 @@ ) (uuid "39dfef0c-d7a2-4482-bca9-5affd0a9afcc") ) - (label "AUDIO_PWM" + (label "LED1" (at 85.09 95.25 180) (effects (font @@ -3813,7 +3977,7 @@ ) (uuid "7e061299-bff5-40d1-8f87-e3efcbd5b5b0") ) - (label "LED1" + (label "C_BTN1" (at 85.09 80.01 180) (effects (font @@ -3824,7 +3988,7 @@ (uuid "82233f70-9329-4389-8977-125c2201a8e6") ) (label "FLASH_CS" - (at 78.74 166.37 180) + (at 62.23 166.37 180) (effects (font (size 1.27 1.27) @@ -3844,7 +4008,7 @@ (uuid "848da8f0-b353-4b3c-9a06-b30dcd05db07") ) (label "GND" - (at 151.14 167.58 270) + (at 61.04 157.48 180) (effects (font (size 1.27 1.27) @@ -3873,15 +4037,15 @@ ) (uuid "94725878-e74f-4b21-aae5-a56d4b5f5068") ) - (label "GND" - (at 322.59 95.25 270) + (label "AMP_SD" + (at 85.09 99.06 180) (effects (font (size 1.27 1.27) ) (justify right bottom) ) - (uuid "9ba0110e-0516-473b-b196-7a8965125707") + (uuid "968fcbdf-0690-43cd-87a6-f65d215b6d57") ) (label "VO+" (at 340.36 160.02 0) @@ -3924,7 +4088,7 @@ (uuid "b0235f9d-665c-4f41-be2f-d227623085bc") ) (label "GND" - (at 295.91 95.15 270) + (at 294.72 91.44 180) (effects (font (size 1.27 1.27) @@ -3964,7 +4128,7 @@ (uuid "ba54329f-b24b-491c-af5b-8195107bd63a") ) (label "C_VBAT" - (at 312.43 87.63 180) + (at 297.18 87.63 180) (effects (font (size 1.27 1.27) @@ -3983,7 +4147,7 @@ ) (uuid "bf9261b2-0bea-41a0-aa2a-4209adebed25") ) - (label "C_BTN1" + (label "AUDIO_PWM" (at 85.09 76.2 180) (effects (font @@ -4023,16 +4187,6 @@ ) (uuid "debd7b52-0059-4c0b-bf7c-967d3c2772e8") ) - (label "FLASH_CS" - (at 159.58 157.43 90) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "e2af49fb-22e1-4190-a130-4ab73a10b921") - ) (label "GND" (at 308.53 157.48 180) (effects @@ -4044,17 +4198,7 @@ (uuid "e7b3cd1a-4907-40c3-92a2-ed993d774d88") ) (label "C_3V3" - (at 151.14 157.58 90) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "efd4637c-fa54-44ce-86ca-590813c3a03a") - ) - (label "C_3V3" - (at 78.74 153.67 180) + (at 62.23 153.67 180) (effects (font (size 1.27 1.27) @@ -4063,26 +4207,6 @@ ) (uuid "f1103770-6762-4d62-b659-6b7212eb3807") ) - (label "C_VBAT" - (at 311.16 85.09 180) - (effects - (font - (size 1.27 1.27) - ) - (justify right bottom) - ) - (uuid "f1a32f8a-5ce2-4e1f-9c31-201dda2521a1") - ) - (label "C_VBAT" - (at 295.91 85.15 90) - (effects - (font - (size 1.27 1.27) - ) - (justify left bottom) - ) - (uuid "f4e3eb90-54e4-46d9-ab89-62e9cba84a0b") - ) (label "SPI_SCK" (at 125.73 95.25 0) (effects @@ -4093,7 +4217,7 @@ ) (uuid "fa336a55-f4b8-4536-98b8-03cd9dc53b95") ) - (label "V_BAT" + (label "AMP_SD" (at 307.34 148.59 180) (effects (font @@ -4789,7 +4913,7 @@ ) (symbol (lib_id "bm:C") - (at 151.14 162.58 0) + (at 66.04 157.48 270) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4797,7 +4921,7 @@ (dnp no) (uuid "4ea7caff-53f9-4c00-bf01-2c0cfc1ebd9c") (property "Reference" "C3" - (at 154.14 159.58 0) + (at 69.04 160.48 0) (effects (font (size 1.27 1.27) @@ -4805,7 +4929,7 @@ ) ) (property "Value" "100nF" - (at 154.14 165.58 0) + (at 63.04 160.48 0) (effects (font (size 1.27 1.27) @@ -4813,7 +4937,7 @@ ) ) (property "Footprint" "Capacitor_SMD:C_0805_2012Metric" - (at 151.14 162.58 0) + (at 66.04 157.48 0) (effects (font (size 1.27 1.27) @@ -4822,7 +4946,7 @@ ) ) (property "Datasheet" "" - (at 151.14 162.58 0) + (at 66.04 157.48 0) (effects (font (size 1.27 1.27) @@ -4831,7 +4955,7 @@ ) ) (property "Description" "" - (at 151.14 162.58 0) + (at 66.04 157.48 0) (effects (font (size 1.27 1.27) @@ -4923,7 +5047,7 @@ ) (symbol (lib_id "bm:R") - (at 159.58 162.43 0) + (at 60.96 171.45 270) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -4931,7 +5055,7 @@ (dnp no) (uuid "696b8ca8-97f4-4851-97cc-70c56c8f54f5") (property "Reference" "R2" - (at 162.58 159.43 0) + (at 63.96 174.45 0) (effects (font (size 1.27 1.27) @@ -4939,7 +5063,7 @@ ) ) (property "Value" "10K" - (at 162.58 165.43 0) + (at 57.96 174.45 0) (effects (font (size 1.27 1.27) @@ -4947,7 +5071,7 @@ ) ) (property "Footprint" "Resistor_SMD:R_0805_2012Metric" - (at 159.58 162.43 0) + (at 60.96 171.45 0) (effects (font (size 1.27 1.27) @@ -4956,7 +5080,7 @@ ) ) (property "Datasheet" "" - (at 159.58 162.43 0) + (at 60.96 171.45 0) (effects (font (size 1.27 1.27) @@ -4965,7 +5089,7 @@ ) ) (property "Description" "" - (at 159.58 162.43 0) + (at 60.96 171.45 0) (effects (font (size 1.27 1.27) @@ -5555,7 +5679,6 @@ (in_bom yes) (on_board yes) (dnp no) - (fields_autoplaced yes) (uuid "90218aa1-4311-468c-8ce8-89d467c4ac29") (property "Reference" "R4" (at 311.15 142.24 90) @@ -5600,6 +5723,15 @@ (hide yes) ) ) + (property "Todo" "Is this necessary?" + (at 310.896 140.462 90) + (effects + (font + (size 1.27 1.27) + (italic yes) + ) + ) + ) (pin "1" (uuid "0b135b1d-91e6-4233-b45c-8d0fafdbdcfb") ) @@ -5788,7 +5920,7 @@ ) ) (property "Value" "0.33uF" - (at 345.9 90.61 0) + (at 347.726 90.17 0) (effects (font (size 1.27 1.27) @@ -5814,7 +5946,7 @@ ) ) (property "Description" "Ceramic" - (at 342.9 87.61 0) + (at 348.234 87.63 0) (effects (font (size 1.27 1.27) @@ -5922,7 +6054,7 @@ ) ) (property "Value" "10uF" - (at 347.17 73.18 0) + (at 347.218 71.882 0) (effects (font (size 1.27 1.27) @@ -5948,7 +6080,7 @@ ) ) (property "Description" "Ceramic" - (at 344.17 76.18 0) + (at 344.424 71.12 0) (effects (font (size 1.27 1.27) @@ -6309,7 +6441,7 @@ ) (symbol (lib_id "bm:C") - (at 295.91 90.15 0) + (at 299.72 91.44 270) (unit 1) (exclude_from_sim no) (in_bom yes) @@ -6317,7 +6449,7 @@ (dnp no) (uuid "d225c3fa-9586-478d-a854-6d14dbaa4bfd") (property "Reference" "C1" - (at 298.91 87.15 0) + (at 302.72 94.44 0) (effects (font (size 1.27 1.27) @@ -6325,7 +6457,7 @@ ) ) (property "Value" "10uF" - (at 298.91 93.15 0) + (at 296.72 94.44 0) (effects (font (size 1.27 1.27) @@ -6333,7 +6465,7 @@ ) ) (property "Footprint" "Capacitor_SMD:C_0805_2012Metric" - (at 295.91 90.15 0) + (at 299.72 91.44 0) (effects (font (size 1.27 1.27) @@ -6342,7 +6474,7 @@ ) ) (property "Datasheet" "" - (at 295.91 90.15 0) + (at 299.72 91.44 0) (effects (font (size 1.27 1.27) @@ -6351,7 +6483,7 @@ ) ) (property "Description" "Ceramic" - (at 295.91 90.15 0) + (at 299.466 97.028 0) (effects (font (size 1.27 1.27) diff --git a/baby_mobile_v2/baby_mobile_v2.ino b/baby_mobile_v2/baby_mobile_v2.ino index 77cba04..44d871f 100644 --- a/baby_mobile_v2/baby_mobile_v2.ino +++ b/baby_mobile_v2/baby_mobile_v2.ino @@ -183,7 +183,8 @@ BLECharacteristic audioCmd = BLECharacteristic("12340002-0000-1000-8000-00805f9 BLECharacteristic audioData = BLECharacteristic("12340003-0000-1000-8000-00805f9b34fb"); BLECharacteristic audioStat = BLECharacteristic("12340004-0000-1000-8000-00805f9b34fb"); -// BLE upload state +// BLE connection / upload state +volatile bool g_bleConnected = false; // true while a GATT connection is active volatile bool g_bleUploading = false; volatile uint32_t g_bleWriteLen = 0; @@ -192,17 +193,20 @@ File g_pocFile(InternalFS); // open file handle (read or write) uint8_t g_pocWriteTrack = 0; // track slot being written via BLE #else // Ring buffer between BLE callbacks and loop() flash writes. -// Callbacks return immediately; flash I/O (especially sector erase ~100ms) -// happens in loop() so the SoftDevice receive buffer never stalls. -// Size: IS25LP128F sector erase takes up to 300 ms; at ~56 KB/s upload rate -// that is ~17 KB of incoming data. 32 KB covers it with margin. -#define BLE_FLASH_BUF 32768u +// Callbacks return immediately; flash I/O happens in loop() so the SoftDevice +// receive buffer never stalls. Sector erase is async (non-blocking): bleFlashTick() +// kicks off the erase and returns; loop() polls completion each iteration. This +// prevents the ring buffer from filling during the ~30–300 ms erase window. +// Buffer: 64 KB handles worst-case 300 ms erase at up to ~200 KB/s BLE throughput. +#define BLE_FLASH_BUF 65536u static uint8_t g_bleBuf[BLE_FLASH_BUF]; static volatile uint32_t g_bleBufHead = 0; // advanced by BLE callback static volatile uint32_t g_bleBufTail = 0; // advanced by loop() static uint32_t g_bleFlashAddr = 0; // current flash write head static uint32_t g_bleFlashStart = 0; // address where this upload began -static uint32_t g_bleFlashErased = 0; // end of last erased sector +static uint32_t g_bleFlashErased = 0; // upper boundary of erased flash +static bool g_bleErasing = false; // async sector erase in progress +static uint32_t g_bleNotifyThresh = 0; // next addr to send progress notify static uint8_t g_bleWriteTrack = 0; static volatile bool g_bleFinalizing = false; @@ -306,6 +310,17 @@ void flashWaitBusy() { SPI.endTransaction(); } +// Non-blocking busy check: reads the WIP bit without spinning. +bool flashIsBusy() { + SPI.beginTransaction(flashSPI); + flashSelect(); + SPI.transfer(CMD_READ_SR1); + uint8_t sr = SPI.transfer(0); + flashDeselect(); + SPI.endTransaction(); + return (sr & 0x01) != 0; +} + void flashWriteEnable() { SPI.beginTransaction(flashSPI); flashSelect(); @@ -564,12 +579,26 @@ bool msc_start_stop_cb(uint8_t power_condition, bool start, bool load_eject) { void ble_connect_cb(uint16_t conn_handle) { Serial.println("BLE connected"); + g_bleConnected = true; g_lastActivity = millis(); + + // Request fast connection parameters and maximum throughput features. + // The central may accept, renegotiate, or ignore these — all safe. + BLEConnection* conn = Bluefruit.Connection(conn_handle); + if (conn) { + conn->requestConnectionParameter(6); // 6×1.25ms = 7.5ms interval + conn->requestMtuExchange(247); // 244-byte ATT payload + conn->requestDataLengthUpdate(); // LE Data Length Extension + conn->requestPHY(BLE_GAP_PHY_2MBPS); // 2M PHY if supported + } } void ble_disconnect_cb(uint16_t conn_handle, uint8_t reason) { Serial.println("BLE disconnected"); - g_bleUploading = false; + g_bleConnected = false; + g_bleUploading = false; + g_bleFinalizing = false; + g_bleErasing = false; // stop tracking the in-progress erase; it will finish in HW } // BLE command characteristic: receives commands @@ -626,9 +655,11 @@ void audioCmd_write_cb(uint16_t conn_handle, BLECharacteristic* chr, g_bleWriteTrack = data[1]; // Track 0 resets allocation; subsequent tracks append if (g_bleWriteTrack == 0) g_flashNextFree = AUDIO_START_ADDR; - g_bleFlashAddr = g_flashNextFree; - g_bleFlashStart = g_bleFlashAddr; // save start for finalize - g_bleFlashErased = g_bleFlashAddr; // nothing erased yet + g_bleFlashAddr = g_flashNextFree; + g_bleFlashStart = g_bleFlashAddr; + g_bleFlashErased = g_bleFlashAddr; // nothing erased yet + g_bleErasing = false; + g_bleNotifyThresh = g_bleFlashAddr; g_bleBufHead = g_bleBufTail = 0; g_bleFinalizing = false; g_bleUploading = true; @@ -763,37 +794,92 @@ void audioData_write_cb(uint16_t conn_handle, BLECharacteristic* chr, // and writes the track table). } -// Drain the BLE ring buffer to SPI flash one page at a time. -// Called from loop() to keep flash I/O off the BLE callback thread. +// Drain the BLE ring buffer to SPI flash. +// Sector erases are asynchronous: we issue the erase command and return immediately +// so loop() keeps running (and the ring buffer keeps draining from BLE callbacks). +// On the next call we poll the WIP bit to confirm completion before writing. +// This prevents the 30–300 ms erase window from filling the ring buffer. +// A pre-erase is also kicked off as soon as we start writing each sector so +// the next sector is ready before we reach it. Writes stop while any erase is +// in progress because the flash ignores page-program when WIP=1. #ifndef POC_INTERNAL_FLASH static void bleFlashTick() { - // Drain as much as we can without blocking too long + if (!g_bleUploading && !g_bleFinalizing) return; + + // Poll async sector erase completion. + if (g_bleErasing && !flashIsBusy()) { + g_bleErasing = false; + g_bleFlashErased += FLASH_SECTOR; + } + + // Drain all available ring-buffer data into flash, one page per iteration. while (g_bleBufHead != g_bleBufTail) { - uint32_t avail = (g_bleBufHead - g_bleBufTail + BLE_FLASH_BUF) % BLE_FLASH_BUF; + if (g_bleErasing) break; // never write while an erase is in progress + uint32_t avail = (g_bleBufHead - g_bleBufTail + BLE_FLASH_BUF) % BLE_FLASH_BUF; uint16_t pageOff = (uint16_t)(g_bleFlashAddr % FLASH_PAGE); - uint16_t chunk = (uint16_t)min((uint32_t)(FLASH_PAGE - pageOff), avail); + uint16_t chunk = (uint16_t)min((uint32_t)(FLASH_PAGE - pageOff), avail); if (chunk == 0) break; - // Lazy erase: erase the next sector just before we write into it - while (g_bleFlashAddr + chunk > g_bleFlashErased) { - flashEraseSector(g_bleFlashErased); - g_bleFlashErased += FLASH_SECTOR; + if (g_bleFlashAddr + chunk > g_bleFlashErased) { + // Write pointer has reached the erased boundary — need another sector erased. + if (!g_bleErasing) { + flashWriteEnable(); + SPI.beginTransaction(flashSPI); + flashSelect(); + SPI.transfer(CMD_SECT_ERASE); + SPI.transfer((g_bleFlashErased >> 16) & 0xFF); + SPI.transfer((g_bleFlashErased >> 8) & 0xFF); + SPI.transfer( g_bleFlashErased & 0xFF); + flashDeselect(); + SPI.endTransaction(); + g_bleErasing = true; + // Do NOT advance g_bleFlashErased — wait for WIP confirmation next call. + } + break; // return to loop(); erase runs in HW, ring buffer fills freely } - // Copy chunk from ring buffer into a temp page buffer + // Erase boundary is ahead — safe to program this page. uint8_t tmp[FLASH_PAGE]; for (uint16_t i = 0; i < chunk; i++) { tmp[i] = g_bleBuf[(g_bleBufTail + i) % BLE_FLASH_BUF]; } - flashPageProgram(g_bleFlashAddr, tmp, chunk); - g_bleBufTail = (g_bleBufTail + chunk) % BLE_FLASH_BUF; - g_bleFlashAddr += chunk; + flashPageProgram(g_bleFlashAddr, tmp, chunk); // ~0.5 ms blocking + g_bleBufTail = (g_bleBufTail + chunk) % BLE_FLASH_BUF; + g_bleFlashAddr += chunk; - // Yield after each page so the rest of loop() stays responsive - break; + // Pre-erase: kick off the next sector erase as soon as we start writing + // the current sector so the erase (~30 ms typ) completes before we need it. + // Break immediately — never write while an async erase is in progress since + // the flash chip silently ignores page-program commands when WIP=1. + if (!g_bleErasing && g_bleFlashAddr > g_bleFlashErased - FLASH_SECTOR) { + flashWriteEnable(); + SPI.beginTransaction(flashSPI); + flashSelect(); + SPI.transfer(CMD_SECT_ERASE); + SPI.transfer((g_bleFlashErased >> 16) & 0xFF); + SPI.transfer((g_bleFlashErased >> 8) & 0xFF); + SPI.transfer( g_bleFlashErased & 0xFF); + flashDeselect(); + SPI.endTransaction(); + g_bleErasing = true; + break; // wait for erase; ring buffer fills freely in the meantime + } + + // Periodic progress notification — keeps the Windows BLE stack from + // dropping the connection during long silent uploads, and gives the + // client real flash-write progress (not just BLE-send progress). + if (g_bleConnected && g_bleFlashAddr - g_bleNotifyThresh >= 4096u) { + g_bleNotifyThresh = g_bleFlashAddr; + uint32_t written = g_bleFlashAddr - g_bleFlashStart; + uint8_t stat[4] = { + (uint8_t)(written >> 24), (uint8_t)(written >> 16), + (uint8_t)(written >> 8), (uint8_t)(written) + }; + audioStat.notify(stat, 4); + } } - // Finalize when CMD 0x03 received and ring buffer is empty + // Finalize when CMD 0x03 received and ring buffer is fully drained. if (g_bleFinalizing && g_bleBufHead == g_bleBufTail) { uint32_t startAddr = g_bleFlashStart; uint32_t bytesStored = g_bleFlashAddr - g_bleFlashStart; @@ -806,6 +892,7 @@ static void bleFlashTick() { g_bleUploading = false; g_bleFinalizing = false; + g_bleErasing = false; // pre-erase of unused sector, if any, will finish in HW writeTrackTable(); loadTrackTable(); Serial.printf("BLE: Upload finalized — start=0x%08lX stored=%lu bytes\n", startAddr, bytesStored); @@ -856,11 +943,15 @@ void setupBLE() { audioStat.setMaxLen(4); audioStat.begin(); - // Start advertising + // Start advertising. + // The 128-bit service UUID (18 bytes) plus flags + TxPower nearly fills the + // 31-byte advertisement, leaving room for only ~5 name characters — which + // truncated the name to "BabyM" over the air. Put the full name in the scan + // response (its own separate 31 bytes) so scanners see "BabyMobile" intact. Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE); Bluefruit.Advertising.addTxPower(); Bluefruit.Advertising.addService(audioSvc); - Bluefruit.Advertising.addName(); + Bluefruit.ScanResponse.addName(); // full name here, not in the ad packet Bluefruit.Advertising.restartOnDisconnect(true); Bluefruit.Advertising.setInterval(160, 320); // 100-200ms Bluefruit.Advertising.start(0); // advertise forever @@ -1401,22 +1492,46 @@ static void serUploadTick() { Serial.println("REBOOT"); delay(10); NVIC_SystemReset(); -#ifdef POC_INTERNAL_FLASH - } else if (sscanf(g_serLineBuf, "DELETE %u", &utrk) == 1) { - char fname[16]; - pocFilename((uint8_t)utrk, fname); - if (InternalFS.remove(fname)) { - Serial.print("DELETED "); Serial.println(fname); - } else { - Serial.print("ERR no file "); Serial.println(fname); - } - loadTrackTable(); } else if (strcmp(g_serLineBuf, "FORMAT") == 0) { audioStop(); +#ifdef POC_INTERNAL_FLASH Serial.println("Formatting LittleFS..."); InternalFS.format(); g_numTracks = 0; +#else + Serial.println("Clearing track table..."); + g_numTracks = 0; + g_flashNextFree = AUDIO_START_ADDR; + writeTrackTable(); + loadTrackTable(); +#endif Serial.println("FORMAT OK"); + } else if (sscanf(g_serLineBuf, "DELETE %u", &utrk) == 1) { +#ifdef POC_INTERNAL_FLASH + char fname[16]; + pocFilename((uint8_t)utrk, fname); + if (InternalFS.remove(fname)) { + Serial.print("DELETED "); Serial.println(utrk); + } else { + Serial.print("ERR no file "); Serial.println(utrk); + } + loadTrackTable(); +#else + if ((uint8_t)utrk < g_numTracks) { + for (uint8_t j = (uint8_t)utrk; j < g_numTracks - 1; j++) { + g_trackStart[j] = g_trackStart[j+1]; + g_trackLen[j] = g_trackLen[j+1]; + g_trackBits[j] = g_trackBits[j+1]; + g_trackRate[j] = g_trackRate[j+1]; + g_trackDataOff[j] = g_trackDataOff[j+1]; + } + g_numTracks--; + writeTrackTable(); + loadTrackTable(); + Serial.print("DELETED "); Serial.println(utrk); + } else { + Serial.print("ERR no track "); Serial.println(utrk); + } #endif } else { Serial.print("ERR bad cmd: "); @@ -1430,6 +1545,7 @@ static void serUploadTick() { } } } else { // SER_RECEIVING + g_lastActivity = millis(); // keep device awake during long transfers uint8_t chunk[64]; while (Serial.available() && g_serBytesReceived < g_serBytesExpected) { int n = Serial.readBytes(chunk, min((int)sizeof(chunk), @@ -1498,7 +1614,7 @@ static void serUploadTick() { } void loop() { - if (g_playing) g_lastActivity = millis(); + if (g_playing || g_bleUploading) g_lastActivity = millis(); // ---- Serial upload ---- serUploadTick(); @@ -1592,14 +1708,18 @@ void loop() { } // ---- Auto shutoff / idle sleep ---- - if (millis() - g_lastActivity > AUTO_OFF_MS) { - enterDeepSleep(); - } - - if (!g_playing && !g_motorOn && !g_usbConnected && !g_bleUploading) { - if (millis() - g_lastActivity > IDLE_SLEEP_MS) { + // Never sleep while BLE is connected — upload may be in progress or about + // to begin, and the CMD callback sets g_bleUploading asynchronously. + if (!g_bleConnected) { + if (millis() - g_lastActivity > AUTO_OFF_MS) { enterDeepSleep(); } + + if (!g_playing && !g_motorOn && !g_usbConnected) { + if (millis() - g_lastActivity > IDLE_SLEEP_MS) { + enterDeepSleep(); + } + } } } diff --git a/upload_track.py b/upload_track.py index 0a4057f..2f989cc 100644 --- a/upload_track.py +++ b/upload_track.py @@ -7,9 +7,9 @@ Usage: Supported formats: .wav, .mp3, .ogg, .flac, .aac, .m4a, .raw (anything ffmpeg handles) -Output format: 16-bit signed PCM WAV, 16 kHz, mono (WAV header included). +Output format: 8-bit unsigned PCM WAV, 8 kHz, mono (WAV header included). - Already-conformant WAV files (PCM, mono, 8 or 16-bit, 8/16/32 kHz) are sent as-is. - - All other formats are converted via ffmpeg to 16-bit 16 kHz mono WAV. + - All other formats are converted via ffmpeg to 8-bit 8 kHz mono WAV. - .raw files are treated as legacy 8-bit unsigned 16 kHz and wrapped in a WAV header. Requires: pyserial (pip install pyserial) @@ -24,7 +24,7 @@ import subprocess import serial import time -CHUNK_SIZE = 512 +CHUNK_SIZE = 4096 BAUD_RATE = 115200 TIMEOUT_S = 10.0 @@ -92,10 +92,10 @@ def load_wav(path: str) -> bytes: f" ffmpeg -i \"{path}\" -ar 16000 -ac 1 -acodec pcm_s16le out.wav" ) - print(f"Converting {os.path.basename(path)} via ffmpeg -> 16-bit 16 kHz mono WAV...") + print(f"Converting {os.path.basename(path)} via ffmpeg -> 8-bit 8 kHz mono WAV...") result = subprocess.run( ['ffmpeg', '-y', '-i', path, - '-ar', '16000', '-ac', '1', '-f', 'wav', '-acodec', 'pcm_s16le', 'pipe:1'], + '-ar', '8000', '-ac', '1', '-f', 'wav', '-acodec', 'pcm_u8', 'pipe:1'], capture_output=True ) if result.returncode != 0: @@ -141,41 +141,29 @@ def upload(port: str, track_num: int, wav: bytes) -> None: if line: print(f" firmware: {line}") - # Stream WAV data in chunks; poll for ERR + # Stream WAV data without per-chunk polling — the firmware only ever sends + # ERR mid-transfer on a flash write failure (very rare); polling after every + # chunk adds 50 ms of readline timeout overhead per packet, which for a large + # file at USB CDC speeds amounts to many minutes of wasted time. sent = 0 - err_line = None - ser.timeout = 0.05 + ser.timeout = 0 # non-blocking reads while sending while sent < total: chunk = wav[sent:sent + CHUNK_SIZE] ser.write(chunk) sent += len(chunk) pct = sent * 100 // total print(f"\r {sent}/{total} bytes ({pct}%) ", end="", flush=True) - line = ser.readline().decode(errors="replace").strip() + # Drain any early ERR the firmware might have sent + line = ser.read(ser.in_waiting).decode(errors="replace").strip() if line.startswith("ERR"): - err_line = line - break + print() + print(f"ERROR from firmware: {line}") + sys.exit(1) print() ser.timeout = 2.0 - if err_line: - print(f"ERROR from firmware: {err_line}") - if "at=" in err_line: - accepted = int(err_line.split("at=")[1].split()[0]) - safe = int(accepted * 0.9) - # estimate audio bytes (subtract header) - audio_accepted = max(0, safe - 44) - bits = struct.unpack_from('= 44 else 16 - rate = struct.unpack_from('= 44 else 16000 - max_s = audio_accepted / (bits // 8) / rate - print(f" LittleFS accepted {accepted} bytes before full.") - print(f" Safe clip length: ~{max_s:.1f}s") - print(f" Trim with: ffmpeg -i input.mp3 -t {max_s:.0f} -ar 16000 -ac 1 " - f"-acodec pcm_s16le out.wav") - sys.exit(1) - - # Wait for OK - deadline = time.time() + TIMEOUT_S + # Wait for OK — allow up to 60 s for the final sector erase + flash writes + deadline = time.time() + 60.0 while True: if time.time() > deadline: sys.exit("Timed out waiting for OK")