Files
vtech/vtech.org
2026-04-20 13:09:27 -04:00

18627 lines
155 KiB
Org Mode
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
C:\Users\moses\Documents\Arduino\
migrated from notes.org [2026-04-19 Sun]
* ESP32-DEVKIT-V1
** diagram
-----------------
EN | |_|̅ |_|̅ |_|̅ |_| | D23
VP | | D22 GPIO22 I2C_SCL
VN | ┌─────────────┐ | TX0 UART
D34 | │ │ | RXO UART
D35 | │ │ | D21 GPIO21 I2C_SDA
D32 | │ │ | D19
GPIO33 D33 | │ │ | D18
GPIO25 D25 | │ │ | D5
GPIO26 D26 | └─────────────┘ | TX2
D27 | | RX2
D14 | | D4
D12 | | D2
D13 | | D15
GND | | GND
VN | | 3V3
| |
-----------------
en usb boot
** pinlist
EN,VP,VN,D34,D35,D32,D33,D25,D26,D27,D14,D12,D13,GND,VN,3V3,GND,D15,D2,D4,RX2,TX2,D5,D18,D19,D21,RX0,TX0,D22,D23
** vertical pins
EN
VP
VN
D34
D35
D32
D33
D25
D26
D27
D14
D12
D13
GND
VN
3V3
GND
D15
D2
D4
RX2
TX2
D5
D18
D19
D21
RX0
TX0
D22
D23
* Instructions
Plug-in ESP32 to PC
Launch arduino IDE - load "ESP32 Dev Module"
Upload sketch, will parse/compile/upload
paladin defaults to COM3 (recall this workin in emacs but i forget)
~plink -serial COM3 -sercfg 115200 | tee-object -FilePath "plink.log"~
~plink -serial COM3 -sercfg 115200 | tee-object -FilePath "plink.log"~
* Project Expl
#+DATE: [2026-04-20 Mon]
intake raw sample words
clock in, chop into frames
convert sample rate/format
wrap in rtp/udp
send on schedule
* === Running notes ===
* esp32 + vtech baby monitor [2025-07-27 Sun]
tap speaker to gpio36
need to power (vtech is 6V)
esp32wroom vreg is 11 17c / 33 d323; it shoudl be able to take 6v ok
consider adding a button to turn on/off the esp32
then add voltage divider bt
* baby monitor [2025-09-03 Wed]
this baby monitor (vtech dm221-2) runs at 6V DC, i want to tap a 3V or 5V pin to run an esp32 so i can tap the speaker on an ADC and broadcast it over wifi. here's a pic of the board - i tested some pads and components:
SOT23-3 package: (1pin on top, two on bottom), commong for transistors, diodes, vreg
Q1 lone pin is 3.7V
Q6 bottom pins are 3.17V (L) and 3.6V (R)
TP20: 3.17V
TP12: 3.17V
TP21: 3.77V
i might be able to tap an LED? but those are more likely to be current limited right
- look for 3-pin regulators (SOT23) - middle pin is usually output
- check caps near the main processor - usually fed by the clean 3.3V rail
- that U401 chip in the upper section might be a regulator too
also maybe add a small decoupling cap (10uF) close to your tap point bc esp32s are kinda noisy when they boot
https://randomnerdtutorials.com/esp32-pinout-reference-gpios/
https://discord.com/api/webhooks/1411806429576429799/zRFcDio3B_BSxFQ8Rus2gMrJhkpC6olXCGgdZ71L3_7zAxsm2Cy86VBynUxcPNfwq4Xg
** wireshark packets
https://support.adder.com/tiki/tiki-index.php?page=Network%3A+Using+Wireshark+to+check+if+IGMP+is+configured
- start collection on Ethernet3
- _Do NOT leave this running!!_ Collect and STOP to analyze
- DisplayFilter is not CaptureFilter; default is collect all and display some!
CaptureFilter syntax: https://wiki.wireshark.org/CaptureFilters#capture-filter-is-not-a-display-filter
- Create a CaptureFilter eg "src 192.168.1.145 and port 5004"
- DisplayFilter syntax eg "udp.port==5004 && ip.src==192.268.1.145"
add filter: ip.dst==224.0.0.0/4
IGMP should ounly show traffic to dest 239.255.x.x if someone's listening (me).
- first few bytes are packet headers! src/dest. bottom left pane, see "Data (172 bytes)" and click, it will highlight the bytes on the right pane. THIS is where your datagram headers are.
RTP headers:
byte 0: 0x80 (v=2, p=0, x=0, cc=0)
byte 1: 0x00 (m=0, pt=0 → pcmu)
byte 2-3: sequence number (big endian)
byte 4-7: timestamp (big endian)
byte 8-11: ssrc (big endian, arbitrary)
first packet might look like (seq=1,ts=0,ssrc=0x12345678):
80 00 00 01 00 00 00 00 12 34 56 78
** my first headers look like _WRONG! this was 0000, 0010, not 0000 0001_
d8 43 ae 28 55 33 6c c8 00 c8 d3 df
after manual construction of headers:
d8 43 ae 28 55 33 6c c8 00 c8 b4 b4
should be
0x80 0x00 00 01 00 00 00 01 12 34 56 78
d8 43 ae 28 55 33 6c c8 40 8a bd 80 08 00 45 00
** sample - data begins on byte 6!
0000 d8 43 ae 28 55 33 6c c8 40 8a bd 80 08 00 45 00
0010 00 c8 94 45 00 00 40 11 61 9a c0 a8 01 91 c0 a8
0020 01 64 13 8c 13 8c 00 b4 2b 5b 80 00 94 43 00 fc
0030 a9 e0 12 34 56 78 ff ff ff ff ff ff ff ff ff ff
0040 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0050 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0060 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0070 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0080 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
0090 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
00a0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
00b0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
00c0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
00d0 ff ff ff ff ff ff ......
DOIT ESP32 DEVKIT V1
Serial: baud 115200
htons() "host-to-network short" converts a short integer from host byte order to network byte order, swapping bytes if needed, for 16-bit values.
htonl() "host-to-network long" converts u_long from host to TCP/IP network order (big-endian)
https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32/api-reference/peripherals/adc.html
For ADC1, configure desired precision and attenuation by calling functions adc1_config_width() and adc1_config_channel_atten().
PCM5102 I2S DAC board?
8000d10f0122a96012345678a198929091969eb33f2319131011161e2fc7a599939091959dad4f261a131011151c2bdda89b949091949baaf92a1b141110141b285aac9c959190939aa6cd2e1d15111013192445b09e9691909398a2be341f1712101218213bb79f97929092979fb73b211
8000d1100122aa00123456781a264dae9d9591909399a4c5301e1611101318223eb49f9792909298a1bb371f17121012171f37bba198929091969eb33f2319131011161e2fc7a599939091959dad4f261a131011151c2bdda89b949091949baaf92a1b141110141b285aac9c959190939aa
8000d1110122aaa012345678131011151d2dcfa69a939091959cab5d281b141011141b2a79aa9b949190949ba8da2c1c151110131a264dae9d9591909399a4c5301e1611101318223eb49f9792909298a1bb371f17121012171f37bba198929091969eb33f2319131011161e2fc7a599939
*** packet analysis
you lost me. I'm seeing these two bits increment per-packet in byte 6 (first two bits belong to UDP header/checksum):
[] [] 80 00 55 fe 00 35
[] [] 80 00 55 ff 00 35
[] [] 80 00 56 00 00 35
[] [] 80 00 56 00 01 35
this looks like bits 2-3 are simply incrementing per packet, which is exactly what our code says ("hdr->seq = htons(seq++)"), only q is whether that's correct?
here's what i'm seeing in the serial out:
80 00 00 00 00 00 00 00 12 34 56 78
80 00 00 01 00 00 00 a0 12 34 56 78
80 00 00 02 00 00 01 40 12 34 56 78
80 00 00 03 00 00 01 e0 12 34 56 78
80 00 00 04 00 00 02 80 12 34 56 78
80 00 00 05 00 00 03 20 12 34 56 78
80 00 00 06 00 00 03 c0 12 34 56 78
80 00 00 07 00 00 04 60 12 34 56 78
80 00 00 08 00 00 05 00 12 34 56 78
another few lines from WS (obv not the same packets):
80 00 08 61 00 05 3c a0 12 34 56 78
80 00 08 62 00 05 3d 40 12 34 56 78
80 00 08 63 00 05 3d e0 12 34 56 78
** vlc sdp file - this never worked!
use rtp://192.168.1.100:5004
** file
v=0
o=- 0 0 IN IP4 192.168.1.100
s=ESP32 Tone
c=IN IP4 192.168.1.100
t=0 0
m=audio 5004 RTP/AVP 0
a=rtpmap:0 PCMU/8000
a=sendonly
* new notes vtech [2025-09-04 Thu]
tone2 - claude claude tone works!
check the ulaw function deeply, and packet vs payload formation - i dont see memcpy in the functioning tonegen code, just a raw feeding of the packet into the ulaw function, appending header, and firing it off?
Checklist:
- first 12 bytes: 80 00 SS SS TT TT TT TT XX XX XX XX
- packet length: 12 + 160 = 172 bytes
- inter-packet gap: ~20 ms
- seq monotonic +1; ts monotonic +160; stable ssrc
- vlc opens via rtp://@:5004 or sdp with a=rtpmap:0 PCMU/8000
** working udp-tone2 claude
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/adc.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.100";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz
const int FRAME_SIZE = 160; // 20ms frames
const float TONE_HZ = 440.0;
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
}
float phase = 0;
const float phase_inc = 2.0 * M_PI * TONE_HZ / OUTPUT_RATE;
void loop() {
static unsigned long last_send = 0;
static const unsigned long FRAME_INTERVAL = 20; // 20ms
// only send if it's time
unsigned long now = millis();
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
// generate 20ms tone
for (int i=0; i<FRAME_SIZE; i++){
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase += phase_inc;
if (phase > 2*M_PI) phase -= 2*M_PI;
}
// µ-law encode
for (int i=0; i<FRAME_SIZE; i++) packet[12+i] = linear2ulaw(samples[i]);
// build rtp header (fixed)
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80; // v=2, p=0, x=0, cc=0
hdr->mpt = 0x00; // m=0, pt=0 (PCMU)
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
// send packet
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
** orig file to integrate
#include <WiFi.h>
// #include <esp_wifi.h>
#include <driver/i2s.h>
// #include <lwip/sockets.h>
#include <WiFiUdp.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* MULTICAST_IP = "239.255.0.1";
const char* DEST_IP = "192.168.1.100";
const int UDP_PORT = 5004;
const int SAMPLE_RATE = 32000;
const int OUTPUT_RATE = 8000;
const int FRAME_SIZE = 160;
static bool blink = false;
const i2s_port_t I2S_PORT = I2S_NUM_0;
const adc1_channel_t ADC_CHANNEL = ADC1_CHANNEL_0; //gpio36
char id_str[17];
char status_id[32];
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
// rtp header struct (minimal)
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
// µ-law encode
uint8_t linear2ulaw(int16_t pcm_val) {
const int BIAS = 0x84;
const int CLIP = 32635;
int mask, seg, uval;
pcm_val = pcm_val >> 2; // bitshift right 2^arg (2), unsure if this works? if pcm value is encoded
if (pcm_val < 0) {
pcm_val = -pcm_val;
mask = 0x7F;
} else mask = 0xFF;
if (pcm_val > CLIP) pcm_val = CLIP;
pcm_val += BIAS;
seg = 7;
for (int v = pcm_val; v > 0x3F; v >>= 1) seg--;
uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF);
return (uval ^ mask);
}
void setup_i2s() {
i2s_config_t cfg = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = 0,
.dma_buf_count = 4,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = true
};
i2s_driver_install(I2S_PORT, &cfg, 0, NULL);
i2s_set_adc_mode(ADC_UNIT_1, ADC_CHANNEL);
i2s_adc_enable(I2S_PORT);
}
void setup() {
uint64_t chipid = ESP.getEfuseMac();
snprintf(id_str, sizeof(id_str), "%04X", (uint16_t)(chipid >>32));
Serial.begin(115200); //begin serial connection for debugging
// delay(200); // pause for usb host
WiFi.begin(ssid, password);
Serial.printf("[wifi] ");
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf(" connected %s with ip %s\n", id_str, WiFi.localIP().toString().c_str());
setup_i2s();
Serial.printf("[udp] ");
if (udp.begin(UDP_PORT)) {
Serial.printf("listening on port %d\n", UDP_PORT);
} else {
Serial.println(" failed to bind\n");
}
}
void loop() {
int16_t samples[FRAME_SIZE*2]; // 320 samples @ 16kHz = 20ms; adc is tied to clock speed
size_t bytes_read;
i2s_read(I2S_PORT, (char*)samples, sizeof(samples), &bytes_read, portMAX_DELAY);
if (bytes_read == 0) { Serial.println("[i2s] no samples read\n"); return; }
uint8_t payload[FRAME_SIZE];
for (int i=0;i<FRAME_SIZE;i++) {
payload[i] = linear2ulaw(samples[i*2]); // take every other sample to keep rtp stream at 8khz
}
uint8_t packet[12+FRAME_SIZE];
// rtp_hdr *hdr = (rtp_hdr*)packet;
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80; // v=2
hdr->mpt = 0x00; // payload type 0 = PCMU
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
memcpy(packet+12, payload, FRAME_SIZE);
if (udp.beginPacket(DEST_IP, UDP_PORT)) {
udp.write(packet, sizeof(packet));
udp.endPacket();
Serial.print("\r");
Serial.print(blink ? '.' : ' ');
Serial.flush();
blink = !blink;
};
ts += FRAME_SIZE; // 20ms worth of samples
}
** compairson bt tonegen and original:
loop()
+ last_send, frame interval
samples[ framesize]
** TODO variant tonegen with multicast
* circuit descr
the adc (GPIO36) is connected to a vtech pm221 speaker through an RC circuit w/ voltage divider:
SP+ to C1 to node A to R1 to node B to Rf to GPIO36;
Node B to R2 to node c to SP-;
Cf connects node c and node a.
GPIO36 is biased with two 1M resistors connected to 3V3 and GND pins.
C1 = 1 uF, Cf = 4.7nF, R1 = 22k, R2 = 10k, Rf = 1k
SP+ --- C1 --- a --- R1 --- b --- Rf --- GPIO --- d --- 1M --- GND
| | |
SP- --------- C2 --------- R2 1M --- 3V3
* prompt
gravity check this:
esp32 script streams udp data (rtp)
mode 1: send 440hz default on launch (works)
mode 2: (toggle mode on tapping pin) stream from ADC pin
the adc (GPIO36) is connected to a vtech pm221 speaker through an RC circuit w/ voltage divider:
SP+ to C1 to node A to R1 to node B to Rf to GPIO36;
Node B to R2 to node c to SP-;
Cf connects node c and node a.
GPIO36 is biased with two 1M resistors connected to 3V3 and GND pins.
C1 = 1 uF, Cf = 4.7nF, R1 = 22k, R2 = 10k, Rf = 1k
```
SP+ --- C1 --- a --- R1 --- b --- Rf --- GPIO --- d --- 1M --- GND
| | |
SP- --------- Cf --------- R2 1M --- 3V3
```
need to troubleshoot this, either the circuit is wrong, or the ADC implementation.
before i redesign the circuit again, i'd like to know how i can test the ADC to be sure it's working; how would i create a 440Hz tone i can feed to the ADC that would be interpreted by our algorithm?
the program is right, because I can send the 440hz sine wave through it and it works!
so it's almost certainly an issue with the cercuit.
* voltage/adc test 1 [2025-09-02 Tue]
- GND and 43V3 show 4095 range is good! and we're sitting at the midpoint
- voltage is confirmed (3.3v at 3V3 and 0V at GND)
- SP+ and SP- sit at 1.6V; ADC sits at 1.6V when idle
** data
switched to mic mode
4039-4095
3997-4095
3951-4095
4023-4095
4095-4095
0-1994
0-366
0-366
0-0
0-0
0-0
0-0
0-0
0-0
0-1087
1489-2135
1456-2150
1493-2257
1465-2636
1299-2598
1463-2177
1522-2191
1535-2261
** test2
...
connected, ip=192.168.1.145
tap pin 4 to switch modes
switched to mic mode
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:2698-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-1690(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-512(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:375-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-3909(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:3101-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryfcircuitworks)
adcrange:0-3101(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
adcrange:509-4095(shouldvaryifcircuitworks)
adcrange:0-4095(shouldvaryifcircuitworks)
** after 1M bias both directions
948-2559
1376-2645
1776-2866
1535-2976
1411-2640
895-2093
921-2638
1119-2496
1719-2878
1422-3535
1383-2812
1041-2290
991-2496
956-2641
1503-2837
1731-2797
1307-2951
1055-2778
976-2686
983-2559
1535-2870
1475-2987
1452-2896
812-2272
1019-2096
852-2596
1616-2867
1739-2805
1417-2734
951-2380
911-2245
855-2549
1611-2992
1733-3344
1236-2799
976-2190
1011-2503
959-2526
1702-2976
1489-2839
1215-3424
959-2206
956-2691
1214-2480
1645-2801
1437-2989
847-2551
1126-2176
849-2590
1486-2879
1655-2837
1424-2881
763-2232
976-2128
975-2734
1555-2876
1711-3258
1232-3037
1104-2457
808-2144
799-2854
1535-3453
1653-3236
1313-2811
934-2172
1006-2784
969-2588
1525-3474
1573-2872
1329-3504
829-2864
921-2156
1040-2542
1136-2985
1682-2921
1495-2895
1033-2694(shouldvar
yifcircuitworks)
912-2123
998-2606
1294-2541
1617-3219
1390-3737
1383-2992
1023-2309
948-2391
1043-2490
1731-2804
1567-2835
1391-2976
917-2224
884-2262
1111-2534
1725-2976
1500-2797
1406-2653
787-2205
1023-2486
1189-2517
1580-2915
1509-2954
** after circuit swap (this is way worse)
adc range: 0-602 (should vary if circuit works)
adc range: 0-487 (should vary if circuit works)
adc range: 0-400 (should vary if circuit works)
adc range: 0-112 (should vary if circuit works)
adc range: 0-621 (should vary if circuit works)
adc range: 0-570 (should vary if circuit works)
adc range: 0-659 (should vary if circuit works)
adc range: 0-325 (should vary if circuit works)
adc range: 0-63 (should vary if circuit works)
adc range: 0-418 (should vary if circuit works)
* [2025-09-03 Wed]
1687/1746 to 2041
...
connected, ip=192.168.1.145
tap pin 4 to switch modes
switched to mic mode
adc range: 1746-1971 (should vary if circuit works)
adc range: 1733-1966 (should vary if circuit works)
adc range: 1754-1965 (should vary if circuit works)
adc range: 1755-1965 (should vary if circuit works)
adc range: 1702-2009 (should vary if circuit works)
adc range: 1675-1957 (should vary if circuit works)
adc range: 1696-2041 (should vary if circuit works)
adc range: 1686-1962 (should vary if circuit works)
adc range: 1741-2004 (should vary if circuit works)
adc range: 1687-1965 (should vary if circuit works)
adc range: 1735-1957 (should vary if circuit works)
adc range: 1718-2031 (should vary if circuit works)
adc range: 1714-2000 (should vary if circuit works)
** funcgen
FG- to ESP32 ground
FG+ to GPIO36, then to SP+
recognizable tone once DC offset turned on (~halfway bt 0/+)
(anything above this resets ESP32)
amplitude knob made little/no difference
(too high resets the ESP32)
tone very choppy and _not_ 440Hz
no tone difference bt GPIO and SP+;
either wired wrong (possible) or
circuit is functioning (not impacting input)
i'm thinking, we shouldnt expect adc serialout to be useful, unless i send a value ~1Hz
so let's generate that first: add a function to generate a 0.5 or .25Hz wave,
so that we can see the ADC values change in the serial out;
we should see values fluctuate between 0 and 4096,
and if we sync the timing right, should get a proper sense of the range right?
** ok ran some basic tests
- ADC confirmed w dmm: 3.3v when ADC-3V3 and 0V when ADC-GND
- SP+ and SP- sit at 1.6V; ADC sits at 1.6V when idle
- ADC shows 0 at GND and 4095 at 3V3; midpoint ~2k when idle, with some noise
- FG- to ESP32 ground; FG+ to GPIO36, then to SP+.
recognizable tone once DC offset turned on (~halfway bt "0"/"+")
tone very choppy and _not_ 440Hz, still comes in pulses where the audio cuts ~twice/sec. no tone difference bt connecting FG+ to GPIO vs SP+, indicating the code has more impact than the circuit. Upping to 540 and 640 Hz, I _can_ hear streaming tone go up - good sign! However the ESP-generated 440Hz tone in tone_mode also walks around a bit - this could be another (separate) problem in the ulaw/packetization logic.
i removed the sampling limiter and moved the print to output adv_val directly after: samples[i] = int16_t)((adv_val-2048)*16);
So this is actually _upstream_ of packetization... but it's still crazy noisy, here's some data:
- 0.1Hz wave ranges from ~2100-2650, with noise usually +/-80, but spikes as big as 150 in both directions
- 1Hz wave ranges from ~2075-2650, with noise usually +/-80
- 440Hz wave is essentially unrecognizable, though sample rate is def playing a role; range is the same (2075-2750).
So we're currently using 25% of available bandwidth; need to scale ADC better. First, we need to look closely at the ADC reader/scale at lines 115-125: is this doing what we want?
#+begin_src c++
static int debug_counter = 0;
int min_val = 4095, max_val = 0;
for (int i = 0; i < FRAME_SIZE; i++) {
int adc_val = adc1_get_raw(ADC1_CHANNEL_0);
if (adc_val < min_val) min_val = adc_val;
if (adc_val > max_val) max_val = adc_val;
// convert 12-bit adc (0-4095) to signed 16-bit (-32768 to 32767)
samples[i] = (int16_t)((adc_val - 2048) * 16); // center around 0, scale up
Serial.printf("%d\n", adc_val); //remove
}
#+end_src
Then, at the ulaw encoder:
#+begin_src c++
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
#+end_src
claude_v3_functionaladc - decent 440hz tone, still walks a little; music playing through monitor is audible but chops every ~1s, and a high-pitched whiny tone is on top
** python plot simple - see final version ~/Documents/Arduino/udp-tone-ai/plots
#+begin_src python
s = <data>
title = ""
import plotly.graph_objects as go
import pandas as pd
data = [(int(x.split(',')[0]), int(x.split(',')[1])) for x in s.split('\n')]
lows, highs = zip(*data)
x = list(range(len(data)))
go.Figure([go.Scatter(x=x, y=lows, name='low'),go.Scatter(x=x, y=highs, name='high')],title=title).show()
#+end_src
** putty output
# use Tee-Object to output to console AND a file
$ plink -serial COM3 -sercfg 115200 | tee-object -FilePath "plink.log"
this is the winner!
*** _other variants_ untested
putty -serial COM3 -sercfg 115200,8,n,1,N | -sessionlog C:\users\moses\putty.log -logoverwrite
plink -serial COM3 -sercfg 115200 > plink.log
#+begin_src powershell
$port = new-Object System.IO.Ports.SerialPort COM3,115200,None,8,one
$port.Open()
while($true) {
if($port.BytesToRead -gt 0) {
$data = $port.ReadLine()
"$data" | Tee-Object -Append -FilePath serial.log
}
}
#+end_src
** data
2096
2073
2095
2081
2095
2096
2095
2086
2096
2096
2083
2093
2083
2080
2073
2078
2098
2077
2096
2093
2096
2101
2006
2096
2160
2096
2079
2090
2093
2077
2097
2064
2096
2092
2076
2085
2087
2096
2090
2086
2096
2082
2135
2183
2087
2090
2087
2058
2091
2091
2082
2151
2088
2083
2105
2082
2094
2077
2095
2091
2085
2066
2086
2096
2139
2078
2096
2096
2097
2098
2093
2109
2096
2098
2096
2085
2096
2075
2076
2096
2094
2095
2095
2067
2097
2083
2089
2107
2134
2107
2080
2096
2094
2197
2043
2176
2133
2007
2032
2045
2114
2075
2117
2087
2145
2104
2106
2096
2086
2065
2096
2117
2094
2108
2109
2105
2097
2097
2096
2087
2079
2096
2007
2101
2111
2096
2089
1990
2087
2081
2082
2100
2101
2089
2097
2097
2092
2105
2091
2071
2096
2057
2096
2098
2095
2096
2096
2085
2093
2123
2080
2090
2096
2089
2089
2119
2087
2083
2071
2087
2010
2046
2084
2074
2083
2085
2096
2079
2064
2080
2095
2094
2139
2090
2085
2081
2089
2075
2095
2090
2032
2090
2096
2090
2082
2085
2097
2096
2074
2083
2075
2115
2079
2125
2096
2082
2192
2091
2103
2080
2174
2083
2093
2096
2097
2096
2086
2100
2061
2092
2091
2094
2096
2091
2085
2092
2085
1977
2092
2102
2091
2079
2096
2002
2096
2103
2065
2083
2096
2094
2171
2088
2098
2112
2096
2095
2090
2105
2054
2096
1972
2119
2096
2083
2103
2078
2036
2097
2083
2090
2066
2091
2099
2080
2112
2082
2104
2099
2160
2097
2109
2093
2093
2096
2087
2117
1984
2096
2063
2061
2096
2112
2078
2102
2099
2081
2099
2103
2066
2098
2103
2187
2102
2095
2097
2093
2086
2126
2063
2088
2096
2043
2106
2073
2105
2114
2099
2099
2107
2096
2086
2100
2103
2215
2101
2119
2102
2055
2096
2101
2086
2101
2128
2061
2099
2109
2109
2100
2097
2115
2046
2055
2093
2083
2135
2081
1997
2073
2096
2103
2098
2081
2085
2096
2099
2103
2081
2096
2096
2100
2074
2100
2105
2096
2073
2069
2097
2097
2068
2085
2096
2096
2091
2095
2137
2095
2096
2096
2096
2096
2097
2089
2116
2106
2111
2096
2111
2044
2112
2080
2075
2097
2106
2064
2105
2093
2032
2114
2076
2083
2095
2103
2160
2112
2098
2098
2098
2102
2091
2089
2096
2096
2115
2091
2094
2074
2112
2090
2096
2096
2116
2083
2094
2096
2091
2094
2129
2089
2105
2116
2096
2098
2085
2096
2087
2135
2085
2096
2101
2093
2115
2101
2101
2103
2107
2106
2080
1989
2070
2097
2144
2099
2117
2064
2096
2038
2106
2096
2120
2097
2096
2205
2113
2099
2103
2096
2098
2108
2087
2108
2097
2106
2109
2110
2097
2107
2111
2188
2130
2105
2206
2112
2101
2112
2089
2095
2112
2098
2103
2121
2072
2119
2114
2100
2106
2113
2112
2119
2103
2098
2104
2119
2103
2041
2143
2096
2112
2105
2106
2109
2097
2091
2055
2128
2109
2101
2097
2135
2064
2057
2094
2106
2096
2092
2090
2143
2090
2097
2094
2092
2074
2118
2113
2119
2112
2107
2128
2095
2096
2158
2094
2106
2112
2092
2073
2085
2041
2098
2095
2096
2202
2074
2110
2103
2105
2126
2096
2122
2163
2071
2109
2115
2109
2068
2096
2037
2105
2108
2133
2128
2085
2107
2105
2194
2065
2103
2112
2093
2079
2118
2103
2103
2107
2070
2113
2091
2105
2085
2090
2111
2112
2192
2110
2097
2098
2107
2087
2121
2091
2114
2108
2094
2096
2128
2110
2117
2109
1971
2145
2092
2098
2078
2086
2093
2079
2107
2096
2161
2111
2096
2102
2097
2102
2096
2015
2107
2094
2034
2101
2032
2141
2097
2090
2085
2000
2107
2175
2005
2105
2220
2096
2123
2117
2112
2122
2103
2089
2113
2124
2025
2147
2117
2111
2058
2102
2102
2096
2106
2109
2111
2111
2112
2094
2112
2109
2095
2118
2106
2091
2098
2111
2033
2105
2106
2109
2093
2114
2096
2100
2112
2109
2106
2109
2117
2066
2070
2065
2110
2080
2129
2093
2100
2106
2111
2115
2142
2124
2101
2045
2125
2212
2139
2105
2128
2103
2121
2104
2107
2102
2117
2107
2096
2094
2106
2105
2110
2128
2103
2084
2099
2096
2250
2119
2099
2107
2109
2096
2121
2108
2091
2097
2122
2043
2095
2102
2119
2112
2097
2108
2103
2105
2105
2192
2084
2116
2098
2110
2081
2096
2125
2146
2227
2099
2114
2112
2131
2087
2112
2207
2112
2096
2084
2096
2112
2108
2097
2137
2113
2145
2123
2112
2133
2097
2102
2231
2098
2098
2118
2119
2106
2111
2103
2097
2128
2155
2112
2140
2109
2111
2099
2116
2096
2103
2113
2107
2111
2110
2002
2105
2115
2159
2109
2102
2112
2110
2125
2131
2117
2116
2110
2110
2131
2021
2112
2122
2097
2130
2116
2112
2109
2043
2113
2113
2128
2096
2119
2114
2093
2109
2122
2096
2099
2118
2115
2112
2112
2071
2127
2139
2128
2137
2094
2108
2117
2115
2096
2116
2094
2127
2113
2231
2111
2112
2105
2087
2112
2128
2045
2110
2095
2114
2115
2127
2150
2111
2099
2119
2119
2112
2124
2244
2119
2127
2067
2112
2007
2107
2046
2024
2125
2064
2114
2109
2114
2118
2117
2112
2210
2251
2125
2125
2115
2123
2031
2110
2111
2114
2117
2103
2112
2112
2121
2098
2112
2108
2112
2096
2121
2103
2112
2111
2064
2113
2107
2096
2106
2237
2110
2101
2091
2104
2115
2117
2128
2114
2121
2114
2102
2064
2068
2131
2096
2144
2091
2118
2167
2095
2123
2093
2119
2115
2146
2112
2115
2139
2102
2126
2093
2130
2016
2103
2015
2119
2125
2119
2112
2117
2118
2124
2044
2117
2111
2119
2113
2126
2113
2115
2110
2103
2118
2114
2106
2121
2102
2092
2116
2176
2216
2127
2112
2146
2128
2094
2115
2112
2126
2128
2110
2111
2143
2130
2125
2117
2127
2124
2128
2117
2064
2109
2107
2148
2117
1929
2096
2133
2121
2112
2128
2114
2128
2129
2116
2112
2126
2114
2130
2111
2042
2122
2119
2127
2123
2166
2198
2118
2130
2105
2174
2062
2125
2155
2116
2137
2119
2104
2125
2119
2127
2113
2119
2102
2131
2119
2113
2127
2112
2111
2117
2128
2126
2114
2125
2129
2122
2255
2114
2139
2119
2126
2126
2123
2091
1969
2115
2111
2118
2109
2089
2144
2148
2127
2069
2116
2118
2084
2091
2123
2112
2114
2126
2117
2128
2130
2087
2111
2125
2163
2126
2127
2128
2125
2122
2128
2221
2096
2118
2119
2107
2128
2125
2123
2131
2122
2128
2122
2175
2128
2162
2142
2102
2121
2127
2113
2123
2118
2128
2116
2128
2119
2126
2138
2129
2128
2158
2153
2141
2121
2120
2125
2114
2092
2128
2151
2128
2128
2128
2121
2122
2137
2118
2098
2127
2125
2129
2123
2124
2095
2119
2107
2107
2126
2129
2125
2084
2103
2124
2118
2169
2112
2128
2118
2123
2125
2128
2119
2138
2144
2067
2127
2107
2115
2113
2139
2139
2126
2129
2101
2081
2128
2147
2128
2141
2129
2128
2112
2158
2131
2123
2102
2176
2130
2121
2101
2131
2133
2122
2095
2114
2202
2128
2125
2101
2128
2096
2131
2128
2128
2137
2131
2121
2128
2137
2102
2115
2129
2127
2131
2153
2127
2128
2133
2109
2129
2127
2013
2137
2109
2134
2148
2105
2125
2151
2128
2117
2124
2113
2101
2128
2131
2144
2126
2025
2125
2119
2130
2130
2138
2125
2126
2118
2131
2124
2117
2136
2125
2097
2126
2133
2111
2121
2118
2126
2131
2131
2144
2131
2129
2132
2128
2155
2127
2145
2171
2128
2135
2145
2151
2149
2140
2138
2167
2128
2137
2105
2150
2127
2134
2137
2128
2133
2073
2154
2114
2136
2142
2135
2146
2150
2182
2122
2118
2147
2128
2107
2125
2129
2119
2123
2118
2128
2138
2134
2125
2149
2135
2129
2138
2111
2138
2134
2142
2146
2094
2069
2141
2128
2174
2128
2127
2128
2136
2075
2115
2135
2148
2143
2064
2128
2133
2134
2129
2140
2133
2100
2030
2150
2043
2129
2135
2146
2142
2116
2132
2146
2138
2138
2177
2089
2145
2146
2138
2256
2157
2131
2189
2134
2151
2144
2141
2139
2148
2148
2145
2134
2033
2157
2145
2064
2132
2132
2181
2137
2144
2135
2125
2141
2118
2165
2143
2157
2150
2133
2131
2150
2138
2146
2129
2240
2145
2133
2129
2099
2115
2160
2143
2160
2128
2160
2069
2142
2133
2149
2134
2125
2147
2142
2139
2151
2066
2135
2143
2133
2128
2128
2140
2140
2147
2122
2149
2147
2156
2144
2150
2071
2141
2063
2144
2141
2141
2151
2145
2141
2143
2151
2142
2147
2147
2139
2081
2155
2147
2091
2154
2147
2149
2142
2128
2130
2159
2154
2149
2146
2120
2111
2134
2133
2144
2133
2147
2156
2162
2145
2139
2149
2133
2141
2150
2107
2166
2142
2174
2148
2155
2129
2128
2151
2136
2149
2153
2054
2129
2149
2174
2191
2155
2146
2167
2158
2036
2142
2130
2149
2141
2130
2145
2139
2138
2151
2142
2150
2145
2161
2145
2145
2145
2145
2180
2127
2143
2143
2155
2107
2145
2148
2143
2143
2149
2131
2147
2128
2226
2145
2146
2193
2071
2158
2155
2142
2160
2290
2137
2146
2141
2143
2144
2081
2160
2145
2150
2137
2143
2128
2160
2135
2160
2150
2127
2174
2161
2131
2140
2166
2157
2128
2141
2145
2194
2128
2160
2160
2141
2221
2150
2157
2148
2148
2128
2136
2148
2182
2146
2153
2155
2094
2208
2143
2158
2158
2137
2172
2155
2265
2139
2154
2151
2149
2139
2136
2148
2146
2137
2167
2155
2143
2160
2159
2174
2157
2154
2151
2162
2032
2159
2202
2128
2148
2176
2160
2153
2196
2143
2157
2158
2142
2149
2155
2128
2164
2156
2157
2162
2144
2158
2160
2156
2191
2144
2151
2133
2243
2173
2143
2146
2183
2154
2151
2167
2158
2088
2150
2129
2175
2227
2147
2155
2151
2155
2149
2192
2159
2152
2156
2150
2160
2111
2160
2160
2156
2140
2158
2162
2148
2159
2118
2139
2117
2128
2163
2148
2156
2171
2147
2138
2160
2149
2251
2151
2147
2155
2153
2159
2155
2160
2149
2155
2114
2154
2085
2212
2160
2160
2137
2165
2155
2160
2179
2027
2143
2167
2156
2164
2072
2158
2160
2167
2165
2161
2159
2157
2161
2173
2178
2158
2179
2141
2165
2171
2169
2133
2161
2160
2160
2198
2160
2154
2160
2171
2160
2160
2160
2170
2159
2135
2157
2104
2147
2111
2141
2256
2147
2147
2169
2148
2157
2170
2174
2160
2149
2135
2159
2143
2162
2214
2189
2160
2160
2165
2130
2169
2154
2186
2158
2186
2160
2144
2160
2170
2169
2171
2161
2143
2157
2160
2160
2176
2173
2155
2178
2160
2158
2143
2154
2143
2129
2160
2157
2163
2195
2161
2167
2155
2170
2173
2171
2160
2039
2089
2161
2201
2175
2163
2285
2173
2155
2158
2157
2102
2169
2122
2160
2160
2174
2167
2163
2170
2176
2133
2160
2166
2117
2164
2163
2161
2151
2172
2139
2165
2185
2173
2120
2177
2164
2156
2176
2163
2160
2160
2161
2164
2177
2160
2185
2160
2168
2143
2173
2157
2195
2161
2163
2163
2162
2142
2131
2175
2174
2166
2160
2154
2147
2171
2164
1974
2160
2039
2160
2160
2176
2175
2163
2157
2157
2187
2182
2161
2171
2166
2152
2165
2164
2179
2162
2138
2171
2176
2162
2170
2160
2162
2162
2180
2160
2155
2166
2165
2174
2173
2160
2153
2138
2165
2185
2167
2153
2174
2175
2131
2165
2174
2167
2289
2180
2170
2171
2301
2187
2176
2123
2170
2175
2175
2154
2178
2158
2174
2107
2185
2112
2127
2159
2171
2170
2171
2268
2176
2190
2169
2189
2161
2161
2168
2170
2170
2176
2170
2179
2167
2158
2160
2154
2098
2160
2167
2077
2192
2160
2176
2160
2150
2135
2157
2158
2166
2148
2169
2167
2187
2198
2176
2173
2170
2160
2206
2160
2175
2160
2177
2187
2174
2175
2164
2185
2161
2175
2173
2171
2182
2177
2175
2165
2178
2176
2175
2178
2165
2170
2178
2173
2155
2161
2171
2189
2175
2173
2162
2191
2169
2162
2186
2137
2162
2180
2175
2209
2173
2176
2165
2171
2037
2178
2175
2166
2174
2167
2174
2171
2187
2085
2186
2165
2163
2175
2182
2171
2148
2160
2167
2181
2214
2160
2176
2179
2160
2179
2166
2168
2178
2187
2176
2118
2171
2162
2161
2183
2191
2187
2160
2170
2181
2098
2191
2176
2144
2160
2178
2190
2182
2170
2179
2181
2177
2190
2176
2224
2192
2169
2192
2190
2126
2193
2164
2170
2177
2139
2181
2176
2182
2183
2180
2185
2201
2195
2161
2191
2181
2176
2173
2170
2186
2256
2178
2275
2174
2177
2182
2166
2172
2173
2131
2166
2183
2169
2183
2160
2179
2179
2171
2187
2189
2183
2174
2121
2166
2173
2096
2160
2176
2163
2117
2160
2178
2179
2189
2190
2178
2171
2221
2174
2179
2176
2170
2192
2188
2261
2196
2175
2190
2201
2194
2185
2186
2127
2171
2288
2188
2192
2192
2174
2102
2149
2186
2187
2187
2192
2173
2177
2231
2169
2183
2178
2011
2189
2225
2182
2147
2137
2221
2103
2182
2083
2183
2196
2190
2192
2187
2186
2199
2181
2187
2185
2180
2193
2192
2192
2179
2192
2199
2176
2202
2188
2186
2195
2190
2176
2163
2183
2176
2192
2195
2190
2174
2192
2185
2311
2218
2169
2194
2186
2197
2155
2259
2192
2190
2209
2191
2177
2196
2181
2200
2196
2181
2240
2192
2282
2259
2189
2195
2204
2200
2176
2161
2191
2237
2186
2182
2076
2197
2198
2187
2207
2190
2213
2177
2178
2173
2142
2192
2185
2186
2187
2192
2174
2182
2194
2215
2170
2191
2194
2192
2176
2188
2210
2173
2192
2164
2145
2191
2182
2182
2194
2227
2082
2206
2191
2173
2174
2206
2192
2183
2187
2192
2160
2239
2208
2194
2151
2192
2196
2190
2187
2185
2192
2190
2201
2187
2223
2193
2191
2182
2185
2195
2192
2135
2160
2286
2176
2192
2191
2192
2234
2195
2226
2223
2020
2198
2203
2199
2202
2182
2199
2185
2193
2237
2197
2192
2192
2188
2192
2176
2197
2203
2156
2204
2174
2192
2197
2194
2181
2192
2180
2192
2245
2196
2188
2195
2198
2242
2166
2192
2099
2192
2196
2191
2203
2176
2196
2180
2194
2205
2192
2192
2192
2197
2192
2219
2192
2166
2215
2194
2203
2214
2200
2196
2241
2197
2240
2223
2205
2139
2187
2192
2171
2201
2185
2198
2187
2213
2192
2194
2193
2208
2202
2131
2203
2197
2194
2180
2198
2194
2182
2204
2172
2158
2192
2203
2197
2198
2204
2181
2240
2265
2208
2202
2214
2187
2176
2241
2099
2163
2209
2196
2205
2190
2238
2215
2205
2205
2197
2199
2218
2224
2212
2197
2207
2294
2199
2288
2309
2192
2209
2135
2203
2192
2203
2198
2147
2170
2203
2206
2197
2162
2193
2205
2199
2206
2332
2199
2207
2194
2191
2151
2288
2206
2206
2192
2219
2198
2187
2224
2201
2211
2210
2195
2192
2201
2202
2211
2199
2201
2174
2198
2206
2176
2222
2205
2209
2192
2205
2192
2205
2192
2188
2209
2213
2210
2192
2206
2212
2205
2203
2208
2228
2208
2224
2209
2204
2212
2205
2278
2210
2202
2200
2193
2203
2224
2254
2197
2212
2210
2222
2224
2207
2227
2204
2203
2213
2204
2192
2208
2176
2192
2199
2203
2219
2203
2192
2195
2206
2207
2215
2224
2224
2197
2203
2200
2181
2194
2188
2204
2207
2131
2192
2206
2198
2203
2204
2221
2213
2224
2207
2203
2182
2199
2166
2191
2195
2215
2203
2208
2252
2186
2207
2224
2195
2224
2247
2315
2181
2369
2192
2203
2117
2206
2226
2229
2214
2218
2224
2199
2214
2193
2209
2206
2208
2217
2240
2211
2202
2208
2211
2217
2208
2229
2240
2215
2222
2192
2213
2199
2198
2192
2207
2206
2215
2224
2267
2208
2340
2213
2218
2211
2173
2214
2241
2220
2224
2208
2213
2198
2209
2224
2213
2223
2240
2213
2219
2215
2219
2201
2213
2202
2215
2208
2208
2213
2163
2185
2230
2217
2215
2224
2181
2224
2225
2205
2236
2253
2225
2215
2192
2225
2209
2203
2207
2210
2222
2207
2222
2222
2199
2237
2223
2224
2224
2204
2209
2224
2231
2231
2210
2224
2217
2219
2219
2224
2256
2218
2215
2209
2198
2224
2231
2222
2221
2236
2274
2187
2149
2254
2223
2210
2240
2187
2201
2220
2207
2224
2213
2150
2199
2192
2224
2235
2213
2215
2222
2224
2237
2224
2240
2316
2223
2303
2241
2171
2191
2221
2211
2190
2192
2187
2217
2220
2221
2225
2215
2215
2222
2219
2224
2255
2223
2209
2205
2218
2285
2219
2195
2198
2145
2211
2224
2224
2223
2215
2202
2224
2224
2240
2223
2206
2219
2224
2202
2192
2256
2223
2222
2227
2224
2142
2218
2320
2209
2215
2162
2223
2227
2214
2226
2221
2159
2255
2224
2227
2224
2218
2226
2240
2228
2229
2230
2277
2206
2255
2231
2254
2212
2223
2275
2237
2224
2207
2203
2225
2225
2222
2257
2230
2154
2229
2222
2220
2218
2227
2227
2224
2209
2209
2192
2219
2239
2255
2206
2218
2224
2213
2192
2230
2219
2229
2246
2223
2224
2239
2141
2232
2226
2207
2223
2202
2336
2224
2146
2223
2216
2217
2235
2222
2272
2242
2228
2227
2240
2229
2256
2223
2225
2161
2245
2251
2198
2234
2160
2224
2226
2240
2229
2215
2243
2243
2138
2224
2226
2229
2228
2217
2234
2222
2233
2229
2224
2240
2194
2223
2231
2230
2167
2236
2226
2231
2225
2235
2307
2240
2235
2234
2256
2234
2217
2227
2224
2239
2230
2254
2228
2254
2231
2224
2192
2224
2229
2226
2303
2229
2224
2259
2227
2225
2240
2321
2224
2225
2223
2231
2224
2230
2231
2227
2235
2251
2224
2224
2223
2269
2232
2229
2231
2199
2235
2240
2193
2206
2274
2244
2282
2236
2241
2256
2240
2240
2235
2234
2234
2219
2253
2227
2238
2256
2182
2229
2184
2244
2207
2241
2246
2238
2274
2233
2224
2230
2240
2256
2235
2354
2240
2235
2239
2254
2256
2240
2288
2238
2237
2238
2241
2240
2238
2246
2240
2242
2250
2243
2230
2253
2224
2277
2238
2234
2228
2241
2256
2256
2230
2223
2233
2239
2207
2240
2233
2162
2097
2240
2237
2190
2185
2231
2230
2359
2241
2215
2241
2224
2226
2235
2239
2245
2240
2246
2256
2266
2244
2271
2275
2252
2240
2242
2245
2236
2264
2253
2245
2380
2193
2246
2261
2237
2253
2221
2251
2243
2246
2246
2249
2249
2254
2246
2256
2254
2246
2240
2253
2244
2238
2162
2135
2256
2308
2256
2247
2240
2220
2241
2250
2246
2225
2243
2242
2224
2255
2262
2267
2239
2239
2229
2240
2318
2240
2245
2203
2237
2205
2190
2239
2266
2293
2349
2247
2195
2253
2222
2244
2250
2256
2222
2245
2231
2243
2227
2256
2290
2222
2227
2247
2245
2347
2241
2249
2224
2250
2245
2245
2271
2239
2256
2238
2255
2268
2255
2235
2247
2250
2245
2236
2240
2253
2255
2259
2245
2259
2265
2253
2251
2257
2241
2256
2256
2253
2246
2261
2239
2275
2241
2256
2243
2216
2222
2246
2253
2246
2246
2275
2269
2250
2286
2240
2253
2265
2254
2261
2256
2285
2249
2250
2256
2238
2253
2253
2256
2256
2272
2259
2254
2367
2262
2246
2263
2358
2306
2267
2263
2202
2257
2256
2256
2212
2262
2271
2257
2259
2261
2257
2240
2251
2236
2152
2258
2259
2240
2229
2257
2257
2259
2254
2345
2240
2256
2256
2255
2256
2254
2252
2242
2256
2246
2217
2256
2256
2235
2267
2271
2254
2245
2249
2247
2254
2257
2271
2220
2256
2255
2247
2250
2262
2257
2219
2259
2257
2258
2288
2256
2253
2256
2262
2247
2272
2262
2269
2259
2166
2263
2287
2247
2256
2255
2259
2229
2247
2244
2263
2233
2272
2236
2256
2256
2256
2261
2240
2253
2250
2234
2251
2255
2263
2258
2294
2256
2256
2256
2165
2243
2264
2256
2261
2257
2228
2253
2250
2283
2242
2259
2268
2273
2353
2163
2258
2250
2271
2267
2270
2385
2243
2261
2263
2273
2305
2273
2247
2315
2256
2231
2301
2262
2256
2256
2295
2293
2316
2256
2241
2265
2257
2262
2257
2247
2251
2256
2271
2274
2260
2394
2209
2260
2269
2261
2247
2260
2257
2263
2260
2273
2253
2256
2253
2272
2235
2265
2263
2309
2269
2262
2277
2279
2267
2254
2310
2279
2218
2263
2307
2260
2276
2267
2267
2286
2273
2270
2243
2380
2274
2271
2267
2261
2194
2283
2291
2273
2270
2268
2285
2289
2261
2231
2271
2270
2279
2273
2243
2260
2267
2320
2278
2263
2253
2265
2336
2281
2253
2271
2267
2273
2256
2256
2265
2261
2195
2259
2271
2311
2263
2160
2347
2278
2185
2302
2259
2265
2273
2208
2302
2259
2256
2267
2269
2246
2254
2267
2271
2193
2265
2272
2236
2266
2260
2265
2339
2263
2346
2261
2273
2278
2256
2281
2272
2305
2257
2274
2279
2278
2258
2242
2270
2256
2271
2256
2274
2273
2272
2255
2283
2275
2256
2281
2303
2213
2283
2261
2268
2267
2279
2244
2267
2265
2279
2389
2340
2281
2276
2275
2256
2290
2278
2268
2278
2305
2320
2271
2348
2298
2295
2283
2282
2256
2290
2277
2263
2251
2277
2279
2225
2288
2282
2289
2227
2282
2224
2286
2291
2288
2276
2284
2254
2271
2267
2270
2286
2276
2277
2287
2254
2285
2277
2271
2265
2269
2288
2355
2267
2285
2307
2365
2286
2277
2311
2269
2283
2273
2289
2285
2287
2275
2286
2288
2272
2278
2239
2293
2283
2286
2288
2272
2227
2271
2295
2289
2285
2287
2253
2292
2282
2285
2284
2281
2288
2285
2277
2267
2405
2327
2267
2305
2320
2361
2275
2288
2281
2288
2289
2275
2283
2267
2312
2288
2292
2283
2274
2285
2277
2295
2279
2321
2282
2283
2274
2291
2274
2287
2277
2289
2268
2288
2277
2282
2284
2283
2420
2257
2283
2282
2278
2352
2272
2288
2294
2285
2269
2290
2290
2306
2293
2241
2284
2267
2298
2266
2272
2261
2287
2303
2284
2314
2273
2283
2287
2311
2278
2284
2284
2280
2259
2285
2297
2151
2246
2285
2288
2279
2294
2288
2286
2341
2299
2297
2294
2399
2287
2289
2285
2335
2274
2291
2337
2288
2285
2295
2334
2302
2277
2290
2275
2288
2288
2289
2283
2217
2275
2290
2306
2300
2348
2288
2293
2288
2298
2295
2303
2297
2289
2299
2292
2286
2280
2295
2288
2288
2303
2288
2281
2290
2291
2295
2285
2281
2233
2282
2301
2268
2338
2289
2290
2281
2284
2291
2291
2286
2280
2296
2301
2310
2305
2330
2292
2271
2398
2299
2195
2187
2349
2304
2287
2273
2291
2289
2296
2289
2305
2299
2290
2304
2250
2272
2311
2311
2295
2295
2240
2299
2299
2293
2301
2369
2298
2300
2406
2295
2245
2337
2301
2383
2302
2307
2311
2299
2331
2306
2290
2287
2303
2297
2295
2283
2294
2302
2292
2330
2288
2315
2298
2339
2317
2289
2314
2293
2289
2301
2303
2290
2299
2292
2292
2317
2290
2316
2320
2298
2256
2289
2321
2323
2320
2309
2311
2298
2304
2427
2314
2305
2415
2319
2305
2331
2295
2303
2304
2303
2290
2314
2293
2318
2286
2320
2304
2288
2313
2304
2307
2321
2341
2300
2310
2357
2299
2420
2309
2320
2256
2299
2349
2307
2304
2244
2293
2304
2299
2227
2291
2307
2311
2293
2304
2303
2306
2306
2319
2335
2305
2307
2309
2306
2301
2311
2412
2311
2295
2256
2306
2323
2310
2320
2301
2301
2285
2313
2293
2306
2304
2304
2320
2304
2306
2283
2331
2327
2321
2298
2313
2316
2322
2297
2465
2338
2306
2305
2331
2346
2303
2311
2316
2317
2317
2305
2304
2313
2311
2346
2295
2311
2319
2320
2270
2310
2308
2245
2322
2284
2299
2307
2290
2302
2327
2298
2306
2318
2287
2320
2313
2309
2310
2283
2303
2317
2304
2215
2307
2327
2315
2341
2308
2319
2304
2309
2334
2320
2309
2319
2310
2426
2304
2295
2316
2298
2287
2318
2314
2311
2322
2307
2274
2319
2295
2311
2330
2318
2320
2311
2319
2320
2319
2311
2306
2320
2314
2398
2308
2315
2323
2301
2320
2309
2428
2320
2320
2315
2366
2321
2334
2317
2321
2309
2317
2304
2320
2245
2319
2320
2318
2321
2321
2329
2351
2319
2315
2320
2325
2331
2320
2312
2352
2306
2307
2315
2320
2288
2320
2286
2320
2327
2325
2313
2314
2320
2289
2354
2320
2317
2323
2417
2325
2298
2331
2317
2323
2330
2331
2317
2327
2319
2301
2317
2320
2291
2323
2317
2325
2311
2316
2309
2325
2336
2315
2305
2321
2311
2320
2290
2331
2335
2205
2346
2319
2320
2314
2236
2320
2323
2311
2334
2320
2350
2326
2322
2321
2317
2363
2323
2314
2318
2335
2316
2325
2343
2336
2328
2327
2333
2335
2330
2287
2323
2325
2325
2333
2330
2333
2323
2325
2297
2325
2325
2238
2289
2335
2318
2326
2305
2310
2455
2317
2337
2329
2320
2322
2275
2335
2333
2322
2334
2358
2335
2400
2320
2322
2225
2326
2325
2321
2347
2323
2323
2339
2350
2327
2336
2352
2323
2331
2350
2335
2337
2333
2322
2461
2303
2343
2329
2347
2233
2341
2241
2351
2334
2333
2329
2342
2326
2319
2330
2350
2322
2337
2331
2325
2333
2320
2321
2325
2325
2326
2336
2333
2419
2349
2446
2302
2331
2335
2339
2328
2335
2321
2288
2333
2320
2373
2334
2329
2325
2353
2330
2367
2270
2329
2331
2329
2329
2347
2327
2334
2331
2281
2322
2337
2335
2331
2341
2334
2343
2333
2341
2330
2338
2339
2330
2346
2331
2337
2329
2323
2356
2315
2329
2310
2333
2336
2352
2350
2327
2320
2338
2428
2332
2325
2335
2332
2331
2325
2327
2323
2351
2320
2333
2345
2332
2263
2341
2331
2323
2334
2316
2309
2337
2363
2366
2285
2346
2311
2339
2323
2225
2335
2330
2346
2337
2357
2352
2343
2334
2332
2331
2350
2349
2320
2340
2321
2321
2305
2339
2343
2353
2279
2331
2345
2352
2341
2336
2339
2352
2361
2338
2346
2361
2355
2389
2334
2342
2333
2342
2341
2352
2333
2357
2355
2300
2343
2338
2337
2341
2331
2352
2322
2477
2346
2339
2329
2311
2347
2345
2345
2287
2338
2352
2354
2342
2346
2346
2407
2339
2343
2342
2352
2307
2342
2347
2333
2485
2350
2352
2336
2334
2336
2477
2255
2333
2347
2338
2336
2338
2337
2363
2346
2354
2362
2286
2330
2340
2345
2331
2343
2406
2345
2363
2446
2346
2342
2337
2296
2320
2347
2363
2349
2356
2349
2352
2343
2342
2433
2352
2348
2343
2350
2343
2302
2352
2382
2352
2334
2383
2349
2362
2366
2347
2351
2352
2359
2337
2342
2352
2352
2341
2357
2347
2355
2347
2315
2348
2353
2379
2257
2366
2338
2291
2478
2293
2371
2353
2353
2374
2352
2340
2295
2347
2417
2336
2365
2339
2356
2363
2352
2364
2349
2356
2519
2333
2355
2357
2359
2305
2351
2359
2353
2368
2353
2371
2354
2341
2352
2352
2356
2351
2363
2359
2358
2299
2378
2326
2377
2351
2357
2365
2390
2352
2382
2351
2331
2301
2339
2353
2350
2357
2353
2352
2332
2357
2338
2352
2334
2350
2354
2352
2299
2314
2347
2342
2371
2333
2352
2350
2379
2359
2390
2352
2299
2353
2343
2353
2358
2363
2352
2363
2353
2331
2373
2357
2343
2353
2367
2363
2368
2352
2341
2411
2353
2361
2364
2354
2514
2353
2352
2353
2355
2350
2356
2351
2355
2356
2358
2350
2288
2355
2358
2349
2364
2370
2366
2346
2353
2374
2435
2410
2351
2357
2361
2354
2371
2369
2361
2367
2358
2364
2341
2367
2352
2326
2378
2370
2346
2352
2353
2352
2361
2350
2394
2368
2354
2369
2357
2286
2359
2361
2380
2363
2368
2352
2349
2368
2367
2377
2358
2311
2341
2362
2365
2361
2367
2355
2352
2372
2589
2368
2352
2350
2352
2359
2383
2370
2363
2384
2363
2364
2345
2368
2372
2353
2358
2341
2277
2379
2373
2368
2377
2378
2371
2384
2368
2367
2375
2369
2335
2389
2375
2371
2377
2417
2378
2370
2384
2332
2195
2388
2369
2409
2377
2355
2289
2365
2369
2372
2397
2503
2366
2339
2365
2366
2368
2384
2366
2369
2450
2367
2367
2371
2342
2366
2377
2368
2354
2367
2371
2366
2219
2381
2352
2368
2352
2379
2368
2271
2487
2369
2295
2356
2349
2342
2384
2369
2368
2415
2320
2362
2287
2451
2368
2368
2365
2320
2384
2356
2357
2365
2376
2345
2346
2351
2369
2352
2365
2352
2365
2364
2353
2368
2366
2371
2378
2374
2377
2372
2320
2370
2368
2400
2364
2369
2543
2358
2304
2368
2395
2321
2368
2383
2372
2371
2375
2321
2382
2386
2382
2307
2366
2379
2372
2368
2382
2365
2374
2374
2379
2321
2294
2371
2372
2365
2304
2371
2386
2369
2367
2375
2386
2374
2372
2375
2386
2361
2378
2368
2375
2378
2363
2381
2384
2385
2383
2390
2384
2387
2386
2348
2375
2422
2373
2386
2358
2327
2362
2384
2384
2402
2389
2378
2370
2379
2368
2386
2382
2393
2423
2381
2401
2378
2359
2359
2379
2395
2359
2382
2384
2365
2363
2384
2395
2381
2371
2480
2420
2379
2342
2383
2357
2379
2382
2340
2372
2391
2351
2386
2430
2354
2375
2383
2368
2389
2361
2380
2374
2398
2373
2386
2375
2363
2395
2385
2459
2373
2384
2377
2384
2373
2379
2372
2381
2389
2378
2380
2384
2387
2376
2403
2379
2371
2395
2378
2384
2381
2378
2291
2387
2378
2359
2386
2398
2379
2372
2290
2382
2389
2391
2385
2368
2381
2373
2404
2385
2382
2386
2375
2493
2336
2397
2387
2428
2391
2413
2403
2391
2430
2401
2398
2384
2384
2367
2389
2416
2377
2387
2377
2385
2363
2386
2391
2385
2391
2396
2398
2391
2386
2378
2384
2384
2382
2386
2387
2383
2382
2373
2411
2420
2385
2383
2384
2384
2389
2366
2384
2386
2401
2350
2386
2397
2400
2384
2391
2389
2382
2386
2377
2383
2414
2390
2366
2390
2391
2383
2389
2402
2388
2395
2401
2326
2394
2390
2387
2415
2382
2384
2384
2382
2375
2386
2387
2368
2384
2368
2386
2383
2452
2379
2416
2379
2384
2385
2384
2478
2408
2390
2402
2388
2398
2444
2365
2384
2387
2369
2399
2393
2419
2393
2385
2378
2374
2398
2399
2389
2398
2374
2389
2394
2526
2391
2391
2407
2401
2388
2397
2387
2394
2393
2386
2394
2339
2398
2384
2397
2400
2387
2384
2399
2394
2394
2385
2394
2425
2421
2405
2402
2397
2395
2379
2397
2419
2409
2387
2405
2384
2390
2384
2372
2395
2348
2385
2415
2403
2401
2385
2395
2399
2384
2400
2396
2405
2384
2386
2355
2384
2421
2395
2401
2397
2398
2416
2313
2448
2413
2413
2403
2416
2320
2406
2385
2417
2433
2403
2405
2406
2399
2419
2402
2389
2222
2403
2405
2403
2398
2400
2416
2416
2384
2398
2415
2389
2438
2411
2411
2409
2372
2415
2373
2421
2387
2401
2395
2395
2418
2410
2416
2352
2409
2432
2397
2413
2404
2395
2393
2355
2400
2403
2393
2402
2542
2416
2402
2398
2433
2326
2395
2416
2391
2375
2454
2410
2384
2415
2395
2397
2395
2412
2378
2403
2397
2389
2416
2393
2352
2378
2394
2399
2395
2374
2418
2382
2406
2395
2401
2416
2407
2434
2352
2419
2397
2403
2449
2404
2352
2409
2411
2403
2382
2311
2314
2365
2400
2404
2417
2422
2416
2405
2416
2411
2402
2429
2406
2416
2416
2490
2462
2416
2405
2416
2355
2450
2420
2414
2342
2402
2337
2538
2386
2519
2416
2419
2417
2416
2416
2395
2329
2411
2416
2390
2399
2427
2418
2406
2421
2417
2407
2396
2417
2401
2411
2406
2354
2397
2412
2415
2419
2416
2350
2409
2417
2400
2405
2402
2410
2389
2415
2406
2416
2388
2406
2419
2450
2432
2416
2427
2413
2418
2413
2324
2341
2390
2494
2427
2420
2414
2422
2417
2421
2397
2399
2427
2373
2416
2419
2422
2419
2416
2415
2428
2420
2434
2368
2447
2430
2388
2403
2413
2433
2423
2416
2422
2416
2415
2431
2434
2415
2402
2421
2431
2409
2420
2416
2423
2435
2418
2412
2419
2412
2395
2411
2437
2410
2415
2432
2417
2399
2417
2416
2420
2427
2489
2416
2482
2422
2414
2415
2416
2432
2514
2411
2380
2418
2399
2411
2423
2415
2414
2411
2421
2439
2432
2465
2430
2483
2416
2410
2416
2416
2437
2415
2416
2449
2417
2425
2417
2458
2351
2422
2431
2400
2419
2426
2423
2421
2431
2416
2442
2425
2403
2421
2419
2462
2430
2423
2416
2431
2441
2439
2432
2437
2421
2510
2426
2421
2432
2406
2427
2414
2396
2480
2461
2427
2352
2418
2421
2445
2423
2441
2437
2416
2419
2425
2427
2433
2425
2435
2431
2414
2424
2432
2433
2421
2425
2430
2425
2374
2385
2434
2418
2401
2423
2416
2607
2439
2427
2479
2416
2448
2359
2429
2405
2429
2430
2435
2460
2460
2430
2423
2433
2416
2416
2421
2448
2429
2448
2512
2431
2420
2402
2429
2455
2423
2423
2434
2421
2432
2415
2443
2426
2435
2371
2417
2421
2430
2439
2434
2434
2431
2423
2422
2408
2432
2433
2428
2435
2475
2427
2426
2469
2413
2440
2457
2420
2438
2439
2441
2443
2429
2416
2444
2480
2427
2429
2433
2450
2427
2416
2433
2424
2447
2432
2422
2403
2423
2433
2414
2516
2414
2435
2431
2393
2433
2428
2441
2434
2362
2429
2434
2445
2434
2432
2400
2431
2442
2426
2435
2429
2433
2420
2435
2416
2416
2441
2494
2363
2443
2399
2434
2439
2533
2423
2438
2433
2453
2426
2466
2448
2430
2435
2534
2436
2439
2445
2443
2438
2442
2435
2539
2434
2431
2427
2422
2430
2441
2438
2420
2443
2436
2429
2436
2435
2443
2444
2447
2438
2433
2459
2440
2446
2437
2418
2445
2486
2444
2432
2459
2447
2449
2449
2439
2470
2439
2438
2419
2436
2439
2438
2448
2450
2448
2439
2436
2453
2419
2416
2447
2447
2447
2418
2476
2447
2442
2447
2433
2439
2426
2439
2432
2433
2369
2442
2445
2459
2478
2407
2447
2384
2477
2443
2446
2437
2459
2441
2442
2448
2483
2439
2387
2442
2403
2454
2433
2437
2421
2438
2439
2442
2430
2585
2440
2450
2441
2413
2450
2427
2444
2450
2459
2445
2469
2423
2429
2446
2441
2477
2448
2445
2448
2434
2460
2448
2431
2431
2395
2431
2444
2416
2442
2439
2445
2448
2438
2448
2443
2480
2432
2439
2448
2384
2344
2438
2404
2446
2448
2602
2445
2446
2443
2440
2461
2448
2448
2447
2448
2461
2438
2461
2448
2516
2441
2464
2347
2448
2473
2446
2460
2462
2455
2459
2448
2435
2437
2448
2432
2434
2453
2425
2443
2432
2439
2412
2454
2465
2504
2455
2446
2351
2447
2448
2469
2448
2486
2473
2466
2465
2448
2445
2455
2434
2449
2448
2385
2460
2446
2466
2454
2405
2449
2448
2378
2449
2435
2453
2442
2450
2450
2451
2469
2448
2458
2465
2462
2461
2552
2351
2496
2448
2411
2453
2469
2453
2557
2471
2470
2389
2489
2448
2449
2448
2451
2454
2448
2452
2455
2461
2451
2459
2438
2448
2356
2443
2466
2491
2406
2448
2465
2459
2462
2505
2454
2442
2443
2474
2457
2451
2471
2471
2459
2529
2453
2384
2453
2442
2451
2435
2457
2437
2454
2413
2450
2448
2450
2446
2448
2469
2480
2369
2457
2458
2468
2448
2438
2452
2445
2442
2453
2513
2454
2463
2457
2448
2373
2458
2496
2458
2453
2428
2462
2459
2451
2450
2461
2448
2463
2448
2459
2464
2442
2448
2453
2448
2455
2496
2463
2457
2459
2453
2496
2459
2450
2465
2463
2473
2473
2472
2391
2469
2444
2455
2400
2490
2496
2458
2459
2452
2443
2421
2387
2463
2390
2426
2489
2451
2455
2480
2470
2466
2476
2469
2458
2497
2448
2385
2454
2462
2464
2453
2455
2458
2461
2471
2464
2454
2454
2481
2527
2544
2449
2468
2480
2423
2459
2476
2521
2491
2479
2451
2435
2461
2460
2458
2434
2447
2465
2559
2451
2451
2461
2436
2448
2475
2465
2477
2473
2448
2470
2470
2458
2467
2452
2463
2403
2459
2475
2475
2374
2466
2489
2493
2463
2454
2397
2464
2461
2467
2462
2455
2447
2543
2467
2481
2483
2481
2383
2469
2479
2474
2469
2462
2380
2458
2595
2416
2458
2463
2480
2466
2551
2479
2466
2445
2487
2598
2478
2478
2480
2467
2473
2475
2449
2468
2479
2462
2462
2473
2463
2468
2508
2467
2497
2470
2471
2469
2423
2448
2489
2461
2463
2555
2465
2480
2480
2453
2471
2465
2476
2480
2458
2476
2464
2479
2480
2423
2453
2384
2477
2475
2450
2487
2473
2473
2398
2466
2474
2413
2492
2498
2501
2477
2496
2494
2463
2473
2448
2480
2481
2502
2478
2479
2480
2485
2467
2533
2478
2477
2479
2434
2487
2489
2493
2467
2483
2480
2442
2478
2467
2479
2467
2469
2482
2467
2480
2466
2482
2448
2462
2475
2480
2480
2480
2417
2462
2455
2474
2479
2465
2500
2477
2478
2597
2465
2477
2463
2470
2495
2475
2458
2471
2483
2474
2433
2470
2471
2471
2475
2467
2469
2486
2471
2477
2481
2485
2419
2481
2460
2471
2479
2499
2490
2463
2480
2494
2489
2469
2485
2480
2479
2416
2489
2482
2451
2484
2497
2512
2485
2487
2420
2484
2497
2483
2483
2579
2473
2554
2466
2506
2482
2474
2502
2481
2453
2478
2374
2448
2490
2495
2500
2503
2528
2474
2502
2480
2473
2480
2487
2480
2483
2493
2480
2467
2407
2485
2503
2480
2484
2489
2480
2479
2482
2502
2506
2480
2487
2463
2486
2471
2493
2490
2544
2486
2478
2479
2480
2496
2483
2485
2481
2483
2491
2474
2480
2486
2481
2475
2487
2502
2484
2492
2510
2495
2464
2493
2498
2482
2474
2496
2495
2526
2498
2496
2485
2500
2467
2461
2466
2503
2494
2517
2427
2510
2483
2487
2480
2455
2505
2626
2483
2485
2495
2493
2487
2544
2478
2498
2487
2479
2496
2480
2550
2471
2501
2480
2506
2481
2496
2504
2482
2491
2495
2418
2494
2491
2493
2493
2496
2526
2492
2490
2486
2486
2470
2418
2496
2490
2510
2490
2472
2503
2480
2482
2330
2530
2495
2486
2603
2478
2485
2490
2519
2501
2489
2502
2497
2419
2486
2482
2500
2503
2493
2537
2497
2516
2496
2496
2495
2508
2443
2490
2502
2559
2496
2487
2499
2516
2491
2497
2494
2497
2483
2497
2497
2532
2515
2512
2500
2501
2491
2499
2493
2501
2509
2505
2501
2503
2503
2522
2512
2635
2493
2506
2508
2487
2496
2465
2512
2496
2425
2499
2479
2503
2503
2498
2494
2505
2512
2652
2480
2528
2493
2503
2581
2501
2489
2509
2384
2515
2503
2509
2506
2512
2515
2516
2502
2559
2514
2506
2517
2511
2610
2515
2498
2499
2458
2511
2521
2513
2496
2507
2544
2507
2528
2501
2559
2491
2515
2489
2496
2517
2509
2485
2512
2461
2503
2502
2457
2513
2531
2499
2495
2502
2499
2506
2511
2416
2510
2529
2506
2503
2494
2499
2512
2497
2506
2498
2512
2499
2507
2496
2507
2512
2518
2521
2506
2475
2509
2513
2605
2505
2495
2509
2501
2503
2481
2511
2511
2503
2499
2506
2375
2505
2505
2506
2543
2533
2501
2593
2499
2608
2512
2510
2516
2510
2501
2505
2512
2512
2512
2506
2507
2500
2416
2512
2509
2512
2451
2523
2502
2500
2457
2515
2496
2513
2506
2534
2585
2599
2512
2498
2506
2523
2505
2503
2509
2535
2513
2517
2471
2537
2502
2512
2503
2379
2494
2502
2514
2512
2518
2512
2507
2511
2501
2448
2587
2507
2512
2405
2506
2493
2507
2496
2507
2512
2505
2510
2525
2506
2531
2506
2498
2501
2517
2493
2514
2511
2515
2516
2512
2497
2512
2641
2529
2503
2518
2492
2513
2512
2450
2515
2489
2507
2496
2508
2512
2499
2504
2404
2523
2593
2515
2513
2516
2511
2509
2511
2496
2512
2529
2529
2512
2518
2524
2505
2464
2512
2507
2513
2559
2511
2491
2514
2516
2523
2448
2519
2517
2502
2512
2513
2589
2539
2503
2517
2533
2510
2559
2527
2512
2506
2653
2505
2515
2511
2512
2517
2528
2509
2518
2501
2512
2508
2482
2525
2435
2531
2512
2495
2463
2513
2516
2448
2542
2529
2507
2507
2512
2527
2507
2516
2512
2530
2497
2512
2509
2513
2519
2473
2512
2529
2521
2513
2517
2517
2517
2662
2523
2522
2530
2513
2516
2514
2540
2526
2517
2515
2524
2512
2512
2512
2534
2527
2514
2531
2528
2518
2519
2537
2477
2508
2542
2535
2610
2522
2528
2507
2593
2532
2522
2521
2510
2526
2529
2559
2545
2513
2508
2522
2559
2532
2608
2518
2523
2512
2502
2439
2502
2535
2511
2538
2526
2526
2513
2588
2541
2496
2511
2527
2515
2551
2544
2515
2591
2486
2511
2546
2548
2497
2519
2448
2517
2516
2559
2524
2507
2509
2528
2512
2521
2529
2519
2498
2496
2518
2701
2546
2525
2528
2512
2531
2518
2511
2487
2532
2481
2525
2527
2501
2514
2559
2526
2529
2502
2539
2515
2514
2515
2542
2519
2522
2543
2531
2538
2540
2512
2533
2532
2519
2522
2515
2523
2518
2530
2535
2517
2534
2525
2537
2538
2531
2462
2537
2492
2433
2528
2512
2523
2512
2519
2555
2508
2543
2527
2583
2527
2526
2533
2502
2553
2542
2551
2577
2522
2559
2544
2454
2480
2530
2529
2512
2519
2524
2530
2511
2533
2469
2513
2509
2512
2531
2538
2523
2531
2499
2512
2523
2513
2524
2524
2535
2541
2537
2542
2514
2544
2555
2531
2506
2529
2515
2523
2544
2463
2528
2590
2535
2559
2538
2535
2545
2531
2529
2535
2609
2543
2555
2555
2531
2553
2544
2528
2535
2529
2530
2526
2544
2514
2528
2515
2535
2553
2542
2529
2531
2498
2541
2466
2529
2495
2541
2586
2543
2526
2482
2531
2537
2544
2521
2525
2540
2527
2536
2540
2518
2530
2526
2544
2517
2526
2539
2531
2529
2535
2528
2538
2543
2531
2545
2533
2529
2529
2533
2533
2537
2542
2543
2541
2544
2537
2489
2595
2542
2521
2518
2613
2554
2544
2529
2544
2559
2535
2540
2538
2544
2534
2548
2535
2537
2593
2525
2559
2530
2541
2640
2535
2532
2549
2531
2535
2544
2529
2555
2513
2559
2544
2543
2559
2555
2526
2559
2537
2545
2544
2544
2544
2480
2547
2517
2537
2559
2531
2559
2541
2462
2586
2538
2534
2545
2457
2539
2543
2544
2544
2533
2559
2542
2687
2533
2512
2555
2549
2645
2535
2544
2545
2535
2549
2541
2448
2585
2543
2544
2554
2545
2557
2581
2555
2556
2554
2557
2544
2551
2539
2607
2555
2551
2610
2544
2546
2605
2531
2550
2552
2494
2557
2541
2523
2528
2547
2548
2544
2505
2550
2539
2539
2540
2521
2547
2541
2544
2543
2535
2546
2537
2467
2539
2544
2516
2544
2559
2533
2547
2538
2559
2545
2542
2538
2559
2528
2545
2549
2551
2559
2534
2486
2559
2559
2551
2544
2457
2542
2519
2538
2543
2548
2530
2544
2532
2545
2544
2557
2526
2550
2554
2678
2559
2544
2528
2539
2535
2538
2539
2555
2506
2531
2549
2555
2559
2559
2554
2557
2543
2549
2555
2559
2510
2549
2543
2544
2538
2554
2549
2541
2559
2539
2460
2544
2547
2553
2559
2555
2550
2550
2479
2496
2528
2543
2527
2537
2554
2557
2556
2542
2518
2543
2599
2544
2545
2551
2547
2559
2553
2549
2519
2544
2466
2557
2544
2686
2559
2559
2554
2557
2555
2556
2559
2449
2592
2559
2541
2544
2519
2550
2640
2525
2559
2559
2559
2559
2559
2550
2559
2582
2559
2559
2544
2550
2544
2545
2555
2559
2559
2544
2559
2614
2547
2608
2553
2534
2559
2555
2559
2522
2547
2559
2559
2555
2586
2557
2559
2559
2537
2519
2558
2554
2546
2544
2558
2528
2550
2496
2534
2467
2550
2558
2544
2558
2559
2546
2557
2545
2490
2546
2545
2549
2559
2552
2559
2547
2547
2559
2557
2546
2544
2550
2474
2544
2549
2587
2544
2551
2597
2559
2512
2555
2559
2556
2545
2559
2558
2559
2547
2626
2469
2559
2431
2559
2558
2546
2543
2448
2548
2601
2550
2545
2549
2543
2559
2501
2559
2559
2554
2559
2613
2559
2559
2559
2559
2543
2559
2549
2559
2559
2559
2554
2559
2546
2559
2559
2581
2611
2544
2557
2579
2559
2559
2555
2559
2540
2555
2559
2559
2559
2559
2559
2559
2559
2614
2511
2624
2559
2544
2559
2559
2591
2580
2555
2544
2544
2599
2559
2507
2543
2545
2559
2559
2559
2580
2559
2559
2559
2581
2559
2559
2559
2548
2559
2559
2559
2559
2559
2608
2606
2559
2554
2559
2559
2555
2549
2551
2529
2547
2455
2558
2523
2602
2549
2558
2550
2558
2559
2559
2556
2559
2559
2559
2557
2559
2559
2559
2491
2559
2559
2559
2559
2589
2512
2559
2559
2559
2559
2559
2559
2559
2559
2554
2524
2559
2555
2502
2545
2547
2559
2581
2558
2559
2581
2555
2673
2540
2559
2558
2559
2596
2587
2553
2559
2556
2603
2519
2552
2559
2559
2559
2559
2590
2554
2557
2559
2559
2547
2559
2586
2554
2482
2559
2559
2611
2583
2559
2587
2559
2559
2559
2541
2559
2583
2558
2559
2559
2559
2559
2559
2494
2559
2559
2551
2512
2559
2559
2594
2559
2587
2503
2581
2559
2559
2559
2559
2559
2559
2548
2545
2559
2602
2559
2559
2559
2591
2559
2487
2559
2559
2539
2559
2559
2559
2589
2604
2559
2583
2587
2583
2556
2736
2586
2591
2587
2539
2585
2559
2559
2559
2604
2513
2559
2583
2559
2583
2558
2599
2582
2559
2555
2605
2559
2590
2527
2559
2499
2559
2559
2559
2559
2613
2559
2559
2591
2559
2590
2559
2559
2590
2581
2558
2579
2724
2593
2583
2622
2559
2559
2582
2559
2583
2559
2559
2608
2609
2559
2557
2608
2582
2593
2581
2589
2704
2591
2559
2559
2533
2587
2593
2559
2503
2618
2593
2592
2559
2556
2559
2585
2559
2589
2549
2582
2614
2622
2559
2559
2551
2559
2559
2693
2607
2581
2583
2617
2559
2559
2559
2559
2598
2559
2587
2583
2559
2704
2581
2585
2591
2581
2592
2559
2589
2588
2582
2512
2622
2524
2559
2586
2559
2555
2592
2554
2583
2559
2605
2559
2559
2610
2583
2579
2559
2592
2559
2597
2559
2559
2559
2603
2586
2559
2590
2589
2591
2559
2534
2585
2581
2606
2559
2535
2602
2582
2628
2587
2587
2597
2559
2559
2587
2591
2608
2583
2592
2588
2590
2602
2625
2597
2559
2587
2559
2619
2614
2604
2630
2598
2594
2590
2553
2595
2603
2583
2546
2608
2590
2559
2559
2624
2581
2581
2559
2559
2608
2587
2592
2585
2582
2593
2590
2559
2588
2619
2583
2593
2544
2559
2604
2595
2557
2647
2559
2582
2589
2583
2588
2579
2593
2590
2588
2582
2582
2559
2586
2590
2595
2592
2501
2559
2619
2591
2585
2583
2559
2559
2608
2559
2559
2598
2539
2601
2559
2621
2559
2559
2689
2585
2559
2609
2605
2553
2589
2608
2559
2581
2593
2581
2642
2594
2589
2597
2592
2623
2608
2592
2622
2599
2599
2601
2585
2559
2587
2524
2585
2582
2559
2582
2559
2585
2594
2624
2609
2587
2589
2559
2582
2608
2599
2608
2585
2584
2590
2598
2503
2648
2559
2610
2597
2602
2559
2592
2505
2597
2559
2599
2591
2559
2588
2559
2593
2601
2598
2591
2559
2608
2559
2535
2595
2611
2589
2591
2592
2594
2755
2602
2591
2601
2604
2608
2559
2599
2590
2624
2598
2608
2615
2607
2599
2612
2599
2600
2599
2587
2492
2602
2607
2602
2592
2608
2608
2594
2592
2559
2602
2589
2521
2594
2624
2521
2624
2687
2595
2592
2590
2588
2507
2608
2527
2603
2601
2496
2602
2624
2559
2599
2598
2587
2587
2595
2598
2586
2611
2595
2595
2599
2606
2589
2745
2615
2587
2599
2715
2603
2710
2599
2559
2653
2594
2595
2545
2653
2607
2599
2597
2583
2590
2599
2595
2619
2554
2587
2559
2513
2589
2590
2559
2607
2607
2598
2606
2559
2587
2559
2624
2608
2602
2595
2691
2592
2613
2598
2609
2608
2595
2559
2512
2605
2603
2590
2591
2597
2602
2601
2519
2586
2593
2587
2588
2586
2603
2595
2602
2559
2609
2603
2559
2596
2599
2594
2602
2704
2624
2591
2617
2600
2477
2598
2622
2600
2604
2559
2602
2596
2586
2583
2593
2590
2608
2608
2608
2593
2582
2608
2596
2593
2609
2597
2587
2599
2559
2613
2580
2604
2596
2589
2531
2608
2595
2607
2603
2597
2606
2602
2610
2541
2614
2552
2672
2603
2674
2598
2599
2599
2559
2608
2608
2607
2608
2607
2624
2610
2608
2597
2603
2606
2596
2606
2615
2604
2589
2606
2609
2605
2607
2608
2609
2607
2583
2550
2607
2603
2716
2608
2559
2595
2600
2624
2607
2595
2609
2608
2599
2619
2695
2559
2603
2622
2595
2589
2603
2606
2742
2608
2606
2620
2603
2608
2618
2601
2608
2610
2601
2606
2604
2601
2601
2613
2602
2619
2609
2609
2448
2607
2608
2597
2607
2601
2606
2611
2595
2606
2624
2624
2611
2607
2597
2592
2595
2591
2612
2621
2621
2619
2607
2595
2539
2614
2609
2626
2589
2611
2615
2603
2559
2615
2622
2615
2599
2611
2547
2615
2587
2613
2608
2619
2621
2554
2611
2599
2623
2599
2616
2614
2607
2613
2617
2559
2626
2597
2608
2608
2625
2597
2613
2608
2617
2613
2595
2608
2608
2624
2640
2619
2524
2537
2619
2619
2615
2608
2614
2609
2610
2603
2610
2512
2609
2598
2626
2559
2613
2609
2701
2605
2615
2608
2619
2637
2598
2583
2625
2603
2590
2608
2587
2605
2612
2622
2643
2612
2610
2609
2619
2611
2599
2619
2621
2594
2614
2639
2615
2608
2603
2630
2615
2632
2585
2630
2619
2615
2608
2598
2608
2601
2615
2625
2615
2625
2612
2736
2644
2586
2619
2510
2595
2617
2614
2611
2614
2619
2608
2697
2609
2627
2637
2606
2608
2605
2612
2610
2599
2627
2605
2619
2594
2609
2621
2622
2657
2627
2614
2627
2623
2608
2606
2594
2559
2624
2607
2667
2724
2608
2615
2613
2537
2605
2611
2627
2669
2605
2609
2585
2606
2604
2625
2613
2607
2619
2624
2598
2631
2610
2665
2618
2608
2637
2613
2609
2630
2704
2642
2606
2611
2620
2734
2590
2624
2603
2611
2618
2611
2607
2620
2615
2617
2549
2614
2595
2591
2736
2634
2627
2608
2608
2612
2686
2607
2610
2606
2624
2585
2647
2612
2608
2610
2640
2594
2607
2559
2611
2621
2623
2596
2627
2613
2613
2607
2611
2559
2538
2665
2608
2614
2618
2624
2608
2586
2624
2614
2608
2615
2612
2624
2625
2610
2611
2608
2619
2734
2611
2644
2608
2630
2640
2608
2625
2611
2589
2615
2602
2624
2618
2615
2559
2619
2623
2621
2614
2615
2618
2635
2624
2625
2642
2622
2635
2557
2630
2599
2624
2595
2615
2608
2624
2619
2608
2614
2623
2642
2608
2617
2618
2618
2635
2615
2627
2615
2625
2607
2624
2555
2624
2608
2613
2622
2640
2627
2615
2626
2623
2634
2623
2623
2549
2611
2617
2640
2605
2621
2622
2613
2629
2645
2620
2621
2624
2623
2710
2591
2621
2612
2641
2631
2625
2619
2626
2620
2619
2783
2640
2582
2592
2559
2625
2614
2637
2608
2624
2608
2640
2559
2622
2622
2625
2631
2631
2631
2640
2636
2637
2558
2639
2617
2743
2631
2647
2616
2645
2625
2633
2647
2605
2552
2609
2624
2613
2559
2640
2623
2624
2612
2619
2545
2610
2625
2627
2628
2644
2619
2626
2624
2624
2607
2626
2614
2690
2631
2630
2624
2623
2634
2635
2622
2615
2625
2623
2607
2607
2610
2630
2635
2559
2817
2639
2705
2758
2619
2603
2607
2609
2625
2608
2641
2641
2624
2581
2615
2593
2630
2629
2614
2615
2608
2628
2618
2721
2619
2608
2614
2657
2544
2609
2641
2637
2633
2582
2305
2654
2617
2608
2524
2624
2622
2640
2631
2624
2635
2651
2608
2639
2608
2628
2624
2629
2629
2624
2632
2639
2641
2613
2608
2631
2643
2624
2630
2638
2622
2626
2628
2612
2608
2624
2726
2624
2617
2641
2629
2557
2626
2636
2651
2559
2626
2601
2629
2614
2599
2631
2643
2601
2635
2633
2630
2628
2706
2629
2634
2764
2631
2627
2617
2639
2637
2593
2638
2630
2631
2634
2609
2634
2649
2608
2635
2625
2627
2559
2638
2637
2677
2631
2559
2627
2636
2546
2624
2603
2628
2607
2681
2559
2640
2619
2629
2633
2531
2646
2623
2631
2640
2634
2626
2637
2671
2620
2679
2617
2639
2559
2624
2623
2637
2624
2651
2613
2633
2639
2589
2663
2619
2615
2500
2631
2414
2608
2609
2615
2624
2624
2641
2622
2591
2635
2647
2625
2623
2627
2663
2614
2655
2603
2593
2635
2633
2648
2639
2624
2800
2636
2637
2749
2621
2636
2770
2625
2622
2633
2671
2640
2636
2631
2618
2615
2635
2631
2663
2630
2587
2630
2638
2641
2640
2630
2506
2633
2559
2628
2647
2639
2597
2608
2630
2598
2638
2609
2633
2542
2631
2637
2636
2647
2640
2624
2670
2627
2633
2874
2629
2642
2638
2637
2645
2639
2647
2625
2637
2639
2652
2640
2640
2558
2672
2641
2583
2635
2636
2635
2612
2634
2639
2613
2631
2617
2639
2624
2644
2639
2763
2634
2662
2559
2624
2507
2645
2647
2638
2588
2630
2629
2645
2593
2615
2634
2633
2628
2545
2627
2663
2634
2627
2641
2621
2642
2628
2635
2640
2627
2640
2626
2614
2608
2640
2646
2623
2635
2640
2621
2623
2615
2642
2645
2643
2665
2642
2634
2640
2641
2640
2640
2634
2635
2640
2632
2618
2559
2633
2631
2627
2638
2639
2642
2667
2551
2687
2629
2613
2640
2655
2626
2632
2640
2554
2625
2512
2640
2634
2632
2630
2636
2663
2623
2633
2644
2559
2625
2630
2651
2641
2642
2639
2640
2631
2633
2634
2636
2624
2639
2622
2641
2640
2643
2634
2643
2628
2613
2636
2644
2544
2647
2640
2642
2653
2541
2631
2652
2641
2633
2630
2559
2646
2663
2641
2756
2608
2640
2642
2638
2639
2630
2637
2638
2655
2655
2644
2623
2635
2656
2623
2655
2651
2647
2627
2630
2640
2638
2642
2627
2653
2636
2641
2641
2626
2626
2717
2544
2641
2642
2639
2754
2649
2656
2639
2621
2640
2605
2559
2633
2636
2644
2640
2624
2645
2635
2624
2647
2640
2631
2634
2550
2625
2701
2625
2639
2644
2667
2667
2632
2628
2624
2639
2618
2634
2646
2647
2633
2640
2635
2642
2657
2633
2590
2643
2626
2641
2638
2654
2643
2640
2646
2611
2629
2642
2634
2559
2694
2639
2650
2640
2620
2637
2646
2645
2641
2641
2642
2644
2639
2669
2620
2636
2660
2663
2755
2592
2640
2640
2635
2624
2637
2640
2640
2633
2619
2647
2643
2627
2618
2629
2642
2636
2636
2641
2643
2640
2657
2611
2626
2641
2624
2643
2654
2639
2640
2656
2635
2640
2637
2647
2645
2671
2644
2637
2622
2638
2639
2641
2641
2716
2631
2639
2649
2637
2640
2626
2651
2668
2646
2646
2645
2640
2653
2640
2640
2634
2646
2641
2646
2640
2649
2653
2663
2645
2653
2631
2646
2656
2661
2753
2701
2655
2645
2647
2672
2655
2656
2693
2655
2659
2649
2646
2653
2640
2652
2653
2640
2640
2659
2670
2647
2650
2654
2621
2639
2646
2630
2657
2638
2642
2647
2672
2665
2684
2640
2661
2647
2643
2667
2656
2650
2798
2641
2667
2656
2639
2637
2651
2644
2642
2626
2637
2646
2652
2627
2651
2637
2642
2642
2661
2641
2657
2640
2591
2634
2640
2651
2713
2800
2640
2645
2646
2645
2559
2644
2646
2653
2645
2640
2652
2554
2654
2647
2640
2640
2643
2657
2659
2657
2643
2653
2663
2629
2602
2602
2661
2683
2661
2640
2651
2654
2537
2647
2641
2669
2642
2755
2668
2651
2637
2628
2624
2640
2646
2652
2647
2681
2636
2645
2627
2648
2636
2628
2650
2645
2648
2640
2651
2654
2645
2654
2653
2656
2653
2559
2646
2634
2642
2651
2611
2663
2657
2639
2640
2659
2665
2640
2640
2645
2559
2627
2695
2640
2645
2658
2640
2649
2655
2653
2646
2662
2647
2640
2647
2641
2644
2672
2659
2669
2659
2647
2710
2637
2656
2667
2662
2652
2672
2653
2635
2651
2702
2663
2642
2647
2678
2665
2663
2645
2643
2640
2649
2655
2656
2653
2658
2682
2662
2627
2653
2643
2636
2731
2640
2662
2674
2635
2662
2641
2626
2640
2655
2622
2647
2645
2640
2672
2655
2586
2649
2655
2626
2657
2645
2674
2671
2647
2657
2667
2629
2640
2647
2651
2743
2677
2640
2657
2650
2661
2666
2650
2656
2550
2643
2663
2643
2644
2641
2688
2592
2646
2559
2635
2659
2651
2649
2659
2661
2643
2647
2647
2647
2651
2655
2631
2661
2658
2640
2642
2585
2669
2650
2647
2650
2640
2599
2652
2663
2655
2649
2611
2666
2662
2671
2668
2649
2656
2646
2632
2657
2661
2672
2634
2629
2653
2639
2644
2723
2659
2671
2694
2653
2653
2651
2653
2647
2658
2648
2643
2667
2650
2657
2634
2743
2655
2663
2641
2666
2652
2559
2637
2688
2643
2643
2646
2657
2651
2636
2640
2664
2640
2669
2646
2657
2677
2667
2668
2642
2655
2646
2673
2683
2656
2670
2652
2660
2669
2654
2656
2653
2659
2672
2649
2653
2646
2650
2653
2672
2653
2658
2591
2624
2663
2654
2661
2648
2651
2672
2667
2652
2657
2655
2662
2666
2606
2686
2615
2642
2656
2655
2647
2627
2658
2643
2671
2694
2639
2655
2645
2642
2635
2636
2555
2656
2645
2651
2659
2598
2556
2606
2635
2634
2674
2642
2655
2649
2643
2649
2645
2659
2647
2669
2559
2635
2660
2658
2673
2674
2655
2653
2653
2658
2665
2639
2642
2621
2657
2643
2637
2670
2786
2653
2645
2655
2665
2654
2607
2637
2666
2608
2656
2636
2667
2652
2657
2669
2683
2637
2621
2652
2674
2675
2649
2645
2657
2638
2582
2652
2632
2679
2672
2641
2651
2682
2672
2666
2629
2654
2657
2677
2672
2672
2750
2654
2663
2738
2640
2480
2768
2641
2707
2665
2676
2682
2672
2649
2659
2663
2653
2670
2628
2667
2659
2654
2665
2658
2659
2660
2634
2654
2661
2623
2661
2653
2656
2674
2653
2633
2655
2657
2559
2655
2646
2639
2663
2663
2672
2677
2653
2654
2689
2672
2643
2665
2654
2668
2671
2656
2646
2656
2651
2559
2672
2657
2656
2662
2635
2667
2650
2651
2636
2687
2655
2647
2605
2704
2654
2649
2681
2663
2786
2659
2656
2657
2626
2656
2656
2634
2663
2730
2682
2647
2646
2635
2656
2644
2666
2652
2644
2653
2651
2643
2640
2643
2650
2665
2609
2653
2655
2662
2665
2679
2655
2656
2655
2661
2695
2668
2658
2678
2656
2622
2649
2646
2662
2655
2653
2641
2644
2663
2667
2664
2642
2646
2619
2658
2672
2661
2656
2658
2653
2743
2672
2649
2666
2676
2645
2642
2671
2672
2658
2648
2587
2663
2646
2647
2652
2655
2642
2672
2654
2653
2684
2608
2663
2661
2672
2626
2781
2659
2658
2663
2606
2646
2650
2658
2642
2665
2661
2662
2663
2675
2663
2663
2663
2716
2625
2639
2643
2663
2635
2637
2663
2657
2688
2663
2693
2702
2640
2662
2655
2635
2719
2658
2653
2658
2559
2671
2640
2663
2666
2646
2640
2674
2663
2651
2621
2691
2661
2673
2651
2659
2640
2666
2662
2658
2640
2647
2620
2662
2650
2608
2675
2690
2672
2650
2634
2656
2659
2615
2635
2653
2661
2622
2662
2674
2669
2656
2650
2667
2676
2671
2654
2654
2657
2661
2696
2667
2673
2654
2635
2672
2654
2662
2652
2653
2636
2672
2759
2623
2649
2667
2630
2693
2701
2672
2655
2651
2641
2611
2661
2640
2639
2653
2667
2631
2646
2663
2643
2667
2655
2720
2717
2671
2653
2658
2622
2559
2657
2704
2651
2663
2649
2666
2693
2645
2658
2634
2657
2665
2625
2658
2642
2657
2654
2657
2659
2734
2602
2647
2659
2641
2615
2655
2671
2663
2651
2650
2599
2654
2667
2695
2663
2708
2640
2688
2667
2672
2671
2669
2682
2659
2630
2665
2701
2660
2681
2673
2657
2666
2671
2558
2658
2660
2646
2658
2641
2611
2757
2629
2651
2655
2610
2661
2653
2674
2656
2621
2677
2667
2608
2663
2666
2639
2655
2662
2790
2658
2658
2640
2677
2654
2700
2669
2647
2640
2655
2685
2631
2595
2659
2656
2663
2671
2655
2633
2670
2594
2615
2662
2676
2655
2669
2656
2658
2653
2665
2659
2671
2658
2653
2667
2653
2669
2657
2661
2647
2656
2629
2650
2765
2659
2769
2653
2640
2645
2671
2645
2699
2656
2646
2662
2658
2659
2657
2652
2646
2658
2650
2661
2707
2559
2665
2788
2666
2590
2653
2668
2640
2605
2661
2640
2669
2648
2624
2635
2646
2661
2658
2683
2661
2647
2663
2662
2631
2672
2661
2660
2670
2651
2670
2653
2658
2665
2654
2671
2672
2688
2655
2637
2647
2661
2661
2659
2659
2679
2688
2686
2659
2666
2655
2623
2681
2672
2663
2659
2659
2665
2675
2637
2665
2688
2652
2704
2626
2607
2656
2667
2671
2665
2647
2650
2670
2644
2671
2629
2651
2640
2639
2649
2661
2656
2640
2580
2663
2671
2688
2655
2650
2647
2653
2662
2662
2716
2659
2611
2669
2652
2657
2660
2672
2667
2639
2645
2640
2676
2654
2643
2662
2684
2672
2669
2666
2714
2659
2654
2659
2666
2663
2672
2658
2641
2661
2740
2659
2658
2673
2655
2659
2667
2656
2737
2655
2665
2660
2655
2620
2657
2667
2655
2662
2586
2654
2662
2670
2665
2661
2663
2656
2655
2663
2668
2651
2677
2660
2654
2638
2661
2674
2643
2642
2654
2667
2652
2679
2674
2649
2647
2662
2683
2643
2734
2673
2651
2559
2666
2662
2654
2650
2661
2653
2657
2649
2662
2656
2659
2669
2658
2703
2662
2735
2675
2640
2678
2666
2655
2655
2671
2780
2665
2661
2657
2654
2623
2602
2652
2672
2662
2648
2722
2663
2655
2644
2666
2607
2624
2667
2655
2678
2448
2659
2670
2559
2655
2635
2668
2668
2672
2685
2589
2661
2663
2666
2678
2677
2646
2649
2657
2651
2647
2663
2645
2646
2653
2662
2579
2670
2653
2645
2646
2650
2649
2544
2647
2690
2655
2654
2590
2591
2657
2667
2661
2639
2679
2659
2646
2418
2671
2640
2669
2651
2663
2629
2654
2665
2640
2675
2661
2669
2666
2659
2673
2657
2659
2671
2658
2666
2671
2653
2658
2654
2693
2655
2655
2722
2656
2667
2659
2672
2661
2667
2655
2663
2819
2655
2669
2655
2658
2663
2643
2675
2661
2653
2661
2702
2657
2658
2634
2640
2727
2661
2663
2666
2667
2663
2663
2657
2676
2658
2625
2657
2644
2635
2659
2646
2669
2669
2706
2647
2659
2653
2688
2651
2659
2658
2642
2663
2658
2658
2668
2666
2669
2653
2666
2652
2672
2662
2670
2640
2651
2673
2657
2657
2589
2658
2655
2661
2663
2654
2656
2659
2643
2641
2667
2654
2649
2651
2669
2640
2640
2559
2670
2667
2666
2861
2691
2672
2669
2666
2652
2654
2640
2669
2640
2671
2682
2661
2588
2690
2643
2662
2667
2602
2660
2642
2666
2663
2657
2629
2663
2748
2658
2640
2669
2647
2655
2646
2649
2672
2672
2670
2690
2659
2647
2663
2652
2657
2741
2642
2655
2663
2662
2642
2663
2656
2658
2662
2645
2647
2661
2656
2646
2665
2608
2624
2775
2659
2669
2670
2655
2654
2656
2640
2653
2674
2660
2656
2660
2675
2672
2593
2658
2678
2662
2666
2652
2663
2668
2644
2646
2651
2657
2655
2679
2663
2665
2657
2671
2676
2651
2654
2657
2655
2559
2650
2647
2544
2651
2687
2637
2658
2523
2678
2671
2666
2659
2656
2652
2667
2649
2658
2657
2649
2652
2661
2674
2663
2658
2733
2673
2683
2699
2647
2692
2659
2667
2612
2655
2666
2657
2666
2670
2655
2669
2672
2669
2675
2664
2687
2657
2695
2704
2693
2662
2639
2657
2627
2672
2666
2672
2663
2681
2649
2672
2681
2663
2643
2671
2670
2597
2659
2667
2649
2659
2681
2637
2667
2672
2662
2654
2764
2638
2649
2661
2650
2649
2675
2661
2679
2656
2677
2663
2596
2647
2659
2623
2663
2687
2667
2665
2662
2640
2639
2662
2646
2655
2639
2669
2661
2670
2655
2672
2659
2675
2639
2665
2659
2661
2605
2590
2624
2662
2663
2614
2657
2678
2662
2670
2654
2656
2672
2672
2663
2667
2651
2662
2676
2649
2678
2649
2670
2672
2662
2640
2659
2656
2665
2656
2734
2672
2670
2703
2660
2559
2657
2658
2647
2662
2657
2669
2618
2651
2655
2661
2657
2670
2672
2665
2662
2641
2593
2674
2658
2667
2672
2663
2666
2620
2662
2669
2659
2657
2695
2655
2591
2641
2658
2661
2640
2670
2790
2657
2655
2768
2653
2667
2671
2662
2640
2654
2743
2658
2659
2657
2779
2651
2650
2670
2647
2660
2663
2675
2690
2654
2652
2655
2646
2647
2665
2525
2669
2650
2654
2659
2666
2650
2672
2602
2666
2659
2659
2674
2658
2666
2679
2667
2665
2624
2658
2688
2661
2656
2674
2651
2704
2658
2666
2646
2661
2652
2653
2662
2655
2643
2677
2646
2611
2704
2663
2653
2665
2647
2658
2641
2671
2659
2637
2653
2624
2641
2666
2666
2678
2653
2661
2657
2644
2661
2662
2662
2656
2657
2653
2593
2644
2651
2654
2659
2665
2640
2656
2672
2657
2601
2653
2640
2661
2659
2629
2642
2671
2662
2591
2663
2641
2677
2687
2639
2648
2704
2559
2671
2559
2647
2623
2649
2657
2640
2667
2663
2657
2649
2585
2559
2659
2666
2627
2674
2658
2647
2667
2650
2661
2918
2672
2661
2599
2663
2657
2657
2646
2660
2665
2644
2657
2661
2653
2645
2658
2601
2641
2666
2659
2653
2670
2661
2671
2647
2661
2559
2647
2701
2669
2647
2663
2645
2655
2662
2670
2674
2674
2669
2667
2620
2693
2751
2662
2660
2656
2659
2559
2662
2668
2654
2678
2661
2656
2629
2662
2683
2666
2661
2669
2631
2642
2645
2667
2702
2656
2631
2647
2673
2647
2667
2608
2663
2653
2658
2635
2645
2640
2661
2658
2644
2665
2647
2666
2672
2639
2655
2658
2670
2669
2531
2655
2667
2651
2559
2650
2646
2646
2651
2718
2669
2639
2664
2664
2655
2784
2655
2681
2672
2658
2662
2635
2643
2669
2662
2656
2651
2646
2640
2660
2657
2659
2662
2659
2640
2663
2662
2656
2559
2622
2638
2642
2652
2614
2661
2666
2657
2656
2704
2662
2653
2640
2645
2635
2655
2608
2657
2666
2634
2659
2661
2655
2638
2653
2653
2646
2673
2658
2656
2677
2624
2671
2653
2653
2593
2667
2703
2653
2768
2640
2641
2631
2659
2651
2640
2658
2659
2659
2654
2703
2559
2672
2672
2647
2637
2646
2653
2635
2640
2663
2662
2642
2646
2659
2647
2638
2653
2635
2625
2637
2645
2652
2675
2656
2656
2627
2699
2651
2666
2651
2656
2649
2640
2626
2635
2636
2678
2651
2663
2655
2674
2643
2679
2620
2614
2526
2650
2611
2649
2641
2643
2651
2636
2632
2653
2642
2665
2665
2642
2671
2665
2654
2651
2671
2645
2672
2656
2643
2656
2645
2651
2663
2650
2652
2662
2651
2640
2651
2678
2652
2637
2589
2640
2640
2647
2657
2599
2652
2656
2647
2645
2662
2643
2650
2626
2640
2656
2608
2661
2658
2707
2606
2646
2589
2640
2603
2655
2646
2662
2636
2645
2640
2651
2659
2637
2658
2645
2658
2665
2667
2736
2670
2638
2559
2595
2666
2671
2654
2654
2689
2646
2650
2672
2654
2687
2645
2656
2667
2650
2691
2659
2590
2646
2609
2587
2640
2658
2659
2642
2656
2647
2657
2654
2651
2647
2637
2626
2675
2649
2647
2640
2667
2659
2650
2653
2667
2654
2636
2640
2639
2624
2646
2647
2649
2640
2596
2644
2650
2645
2663
2641
2642
2658
2661
2547
2657
2640
2650
2625
2651
2663
2660
2656
2652
2645
2639
2667
2652
2655
2650
2674
2646
2658
2656
2646
2651
2766
2661
2650
2638
2650
2645
2658
2615
2547
2643
2643
2658
2640
2672
2640
2643
2648
2655
2663
2663
2666
2631
2655
2642
2656
2645
2646
2656
2788
2644
2640
2650
2642
2690
2657
2641
2641
2640
2646
2631
2641
2640
2640
2650
2657
2633
2614
2602
2643
2645
2651
2637
2601
2643
2658
2635
2657
2646
2660
2593
2645
2645
2649
2647
2657
2653
2776
2652
2649
2640
2654
2640
2646
2672
2640
2651
2643
2647
2639
2618
2645
2640
2641
2702
2653
2646
2647
2647
2643
2653
2640
2649
2644
2627
2608
2630
2646
2602
2653
2654
2542
2640
2663
2660
2642
2624
2640
2646
2646
2665
2641
2624
2640
2637
2644
2641
2638
2647
2643
2632
2647
2641
2651
2624
2651
2660
2646
2671
2644
2667
2651
2647
2650
2652
2601
2633
2656
2658
2637
2637
2627
2735
2653
2595
2656
2647
2629
2640
2672
2655
2582
2640
2646
2645
2559
2643
2659
2653
2646
2743
2636
2654
2655
2654
2658
2645
2650
2655
2652
2636
2657
2639
2647
2613
2559
2665
2651
2652
2653
2642
2662
2647
2743
2662
2649
2654
2644
2674
2649
2646
2649
2714
2666
2643
2645
2647
2654
2640
2633
2639
2640
2590
2559
2645
2688
2635
2677
2638
2655
2637
2640
2608
2649
2655
2641
2641
2640
2642
2640
2640
2662
2559
2654
2655
2646
2638
2648
2611
2646
2669
2640
2649
2638
2634
2637
2668
2715
2651
2640
2659
2634
2627
2651
2630
2625
2651
2663
2640
2642
2643
2643
2637
2639
2605
2606
2653
2643
2645
2629
2647
2672
2647
2640
2638
2559
2641
2666
2670
2640
2644
2639
2643
2639
2624
2648
2651
2635
2559
2637
2614
2651
2624
2713
2607
2668
2655
2611
2644
2631
2634
2697
2640
2640
2641
2651
2658
2718
2663
2652
2640
2641
2651
2649
2644
2643
2658
2637
2699
2644
2645
2645
2643
2654
2653
2544
2645
2665
2634
2640
2640
2640
2631
2605
2623
2650
2638
2631
2749
2618
2637
2642
2654
2559
2647
2619
2559
2633
2631
2634
2644
2645
2641
2640
2628
2663
2640
2661
2639
2645
2593
2641
2640
2642
2606
2640
2640
2644
2644
2645
2594
2660
2647
2669
2639
2640
2640
2644
2649
2640
2634
2639
2639
2641
2647
2640
2642
2653
2656
2631
2641
2649
2639
2672
2637
2640
2639
2649
2645
2629
2629
2661
2656
2639
2634
2649
2640
2635
2594
2651
2633
2631
2626
2640
2644
2640
2639
2631
2634
2631
2640
2618
2642
2640
2662
2640
2646
2642
2636
2608
2637
2629
2637
2640
2646
2643
2639
2624
2603
2643
2641
2645
2643
2633
2655
2635
2613
2533
2627
2643
2559
2736
2642
2647
2606
2640
2623
2637
2671
2626
2642
2647
2639
2629
2640
2657
2640
2649
2659
2635
2641
2619
2647
2641
2651
2651
2655
2640
2640
2645
2640
2672
2635
2641
2639
2641
2640
2634
2677
2643
2590
2645
2624
2640
2640
2612
2668
2652
2663
2626
2609
2639
2634
2638
2635
2651
2636
2634
2638
2650
2634
2643
2640
2638
2635
2585
2624
2635
2652
2485
2635
2768
2631
2603
2639
2640
2638
2641
2630
2640
2654
2582
2625
2638
2625
2651
2732
2635
2634
2644
2635
2647
2639
2640
2631
2643
2678
2636
2662
2631
2629
2641
2604
2643
2640
2631
2638
2614
2635
2640
2845
2670
2638
2646
2635
2640
2596
2640
2624
2638
2628
2662
2640
2623
2623
2634
2640
2624
2640
2650
2636
2539
2633
2629
2726
2640
2659
2626
2645
2682
2599
2628
2636
2626
2640
2635
2650
2634
2625
2621
2640
2637
2640
2638
2637
2631
2617
2590
2641
2665
2634
2627
2634
2637
2640
2624
2629
2643
2630
2626
2656
2554
2615
2641
2639
2606
2657
2617
2637
2626
2647
2649
2624
2626
2634
2624
2644
2627
2640
2640
2721
2617
2639
2590
2658
2628
2628
2644
2608
2625
2670
2638
2623
2634
2694
2629
2623
2640
2608
2641
2651
2637
2633
2681
2640
2624
2608
2631
2635
2637
2608
2624
2614
2626
2630
2628
2654
2637
2637
2630
2646
2631
2639
2618
2629
2613
2610
2640
2619
2624
2623
2622
2662
2626
2634
2636
2663
2640
2614
2623
2627
2634
2637
2637
2639
2623
2559
2644
2639
2640
2646
2627
2641
2622
2675
2631
2631
2640
2581
2634
2627
2629
2608
2704
2643
2672
2624
2627
2608
2559
2613
2631
2586
2639
2634
2624
2627
2640
2630
2639
2640
2624
2640
2623
2633
2607
2739
2639
2627
2621
2756
2636
2559
2633
2607
2627
2555
2628
2639
2643
2626
2633
2637
2640
2627
2609
2626
2617
2634
2608
2637
2638
2643
2629
2634
2625
2639
2615
2643
2631
2627
2788
2643
2628
2641
2631
2647
2599
2634
2635
2624
2627
2537
2640
2627
2592
2625
2551
2633
2640
2640
2620
2627
2689
2636
2639
2559
2634
2617
2621
2640
2633
2614
2639
2630
2480
2591
2619
2628
2544
2637
2619
2636
2608
2612
2559
2586
2620
2667
2625
2627
2615
2624
2640
2639
2559
2621
2641
2620
2611
2592
2620
2603
2624
2614
2637
2631
2624
2617
2625
2614
2559
2618
2609
2615
2615
2619
2622
2618
2638
2639
2612
2581
2637
2633
2621
2624
2640
2622
2635
2730
2629
2621
2626
2591
2619
2610
2621
2618
2607
2643
2624
2621
2628
2643
2623
2630
2624
2672
2559
2608
2625
2639
2622
2608
2624
2627
2609
2762
2624
2625
2608
2559
2630
2619
2631
2625
2631
2615
2624
2625
2736
2624
2609
2611
2618
2594
2623
2615
2612
2645
2603
2619
2624
2617
2619
2619
2625
2624
2608
2579
2631
2644
2628
2631
2621
2719
2620
2618
2617
2608
2652
2544
2615
2634
2630
2622
2635
2637
2630
2631
2622
2623
2643
2636
2621
2640
2631
2640
2607
2625
2638
2671
2622
2615
2605
2608
2435
2615
2510
2624
2625
2629
2727
2615
2625
2619
2629
2614
2604
2623
2613
2747
2630
2613
2623
2418
2618
2620
2612
2608
2585
2618
2611
2608
2631
2640
2619
2590
2613
2630
2608
2622
2602
2559
2559
2640
2608
2559
2642
2620
2613
2619
2615
2606
2623
2617
2671
2593
2631
2639
2640
2582
2617
2620
2599
2637
2633
2621
2619
2626
2625
2647
2608
2618
2618
2579
2623
2606
2618
2629
2623
2617
2609
2631
2632
2639
2624
2619
2623
2607
2645
2627
2603
2613
2643
2607
2610
2619
2624
2769
2613
2559
2613
2609
2634
2618
2617
2559
2603
2611
2624
2608
2630
2548
2615
2608
2603
2605
2608
2597
2608
2608
2610
2615
2620
2617
2619
2614
2618
2538
2732
2608
2619
2601
2547
2603
2619
2602
2623
2619
2624
2628
2613
2620
2673
2617
2645
2625
2625
2624
2623
2623
2614
2608
2625
2610
2625
2589
2628
2624
2694
2624
2611
2619
2602
2611
2606
2609
2617
2624
2607
2608
2603
2527
2613
2436
2656
2593
2595
2607
2602
2607
2617
2616
2608
2559
2622
2608
2611
2619
2665
2608
2597
2659
2682
2617
2609
2583
2622
2607
2437
2621
2612
2767
2612
2608
2617
2602
2606
2612
2613
2608
2650
2610
2610
2608
2602
2612
2616
2645
2596
2608
2621
2621
2608
2603
2603
2609
2599
2598
2591
2609
2608
2594
2615
2559
2646
2596
2606
2607
2505
2617
2607
2596
2610
2601
2705
2613
2646
2605
2585
2607
2603
2559
2618
2608
2608
2534
2614
2613
2614
2626
2594
2638
2609
2612
2617
2603
2598
2606
2604
2608
2591
2607
2607
2626
2608
2603
2608
2607
2608
2596
2615
2611
2559
2637
2613
2619
2611
2606
2646
2601
2601
2527
2613
2614
2622
2617
2624
2619
2608
2614
2782
2607
2622
2624
2619
2616
2606
2620
2614
2637
2624
2601
2583
2625
2631
2630
2640
2608
2622
2603
2610
2597
2606
2588
2608
2608
2611
2614
2604
2597
2608
2613
2603
2585
2602
2583
2592
2608
2605
2603
2614
2590
2626
2606
2602
2716
2585
2587
2588
2624
2624
2608
2606
2595
2587
2611
2595
2559
2615
2606
2603
2608
2599
2542
2598
2592
2599
2608
2581
2604
2621
2602
2609
2605
2613
2609
2597
2559
2592
2616
2661
2559
2559
2613
2608
2516
2608
2559
2587
2605
2624
2599
2608
2583
2592
2585
2603
2605
2585
2608
2605
2608
2711
2609
2598
2559
2559
2603
2622
2603
2589
2594
2606
2591
2597
2515
2601
2603
2605
2496
2594
2508
2597
2559
2609
2615
2604
2592
2559
2640
2593
2599
2591
2543
2603
2630
2605
2598
2583
2623
2599
2591
2582
2608
2551
2595
2559
2658
2582
2581
2544
2664
2587
2595
2592
2627
2594
2605
2606
2596
2595
2588
2593
2559
2597
2609
2606
2590
2598
2593
2639
2615
2559
2608
2596
2593
2590
2611
2590
2595
2602
2591
2592
2559
2606
2607
2548
2559
2598
2605
2591
2591
2597
2596
2590
2608
2589
2586
2594
2595
2587
2582
2615
2603
2594
2597
2598
2597
2529
2593
2604
2757
2595
2589
2591
2554
2608
2594
2599
2593
2609
2587
2593
2608
2605
2602
2603
2592
2603
2602
2607
2598
2595
2619
2516
2592
2608
2598
2614
2559
2559
2606
2583
2594
2591
2618
2589
2522
2603
2597
2606
2613
2599
2559
2626
2605
2590
2587
2589
2600
2594
2559
2586
2641
2595
2586
2597
2599
2594
2559
2590
2587
2583
2593
2501
2590
2589
2559
2559
2585
2591
2597
2593
2613
2592
2559
2559
2585
2580
2559
2592
2641
2592
2615
2608
2618
2509
2597
2582
2593
2527
2559
2593
2596
2524
2599
2603
2585
2605
2583
2599
2682
2587
2591
2559
2539
2595
2624
2601
2624
2559
2591
2587
2559
2559
2597
2603
2594
2594
2601
2512
2591
2604
2585
2593
2559
2598
2559
2604
2601
2603
2608
2586
2594
2595
2579
2545
2591
2583
2558
2579
2585
2594
2559
2593
2559
2583
2583
2559
2660
2588
2595
2559
2585
2583
2591
2598
2705
2545
2587
2556
2583
2559
2605
2603
2559
2588
2586
2589
2559
2586
2590
2603
2606
2603
2617
2595
2619
2590
2559
2640
2587
2559
2736
2557
2555
2559
2586
2592
2602
2586
2593
2555
2598
2554
2586
2595
2592
2590
2602
2603
2605
2592
2587
2480
2596
2592
2532
2589
2602
2608
2590
2559
2589
2594
2589
2599
2626
2599
2559
2512
2594
2592
2596
2603
2655
2559
2527
2589
2594
2588
2559
2501
2559
2559
2414
2586
2590
2663
2559
2559
2559
2582
2583
2559
2554
2678
2589
2559
2474
2586
2598
2559
2594
2582
2559
2559
2590
2481
2599
2587
2692
2595
2559
2587
2586
2600
2592
2496
2579
2559
2623
2624
2559
2583
2559
2559
2485
2581
2597
2581
2559
2591
2596
2588
2582
2559
2591
2678
2583
2588
2559
2494
2608
2583
2583
2653
2586
2583
2582
2586
2524
2582
2593
2606
2559
2619
2586
2586
2585
2559
2591
2559
2559
2594
2712
2581
2533
2635
2559
2559
2589
2581
2559
2559
2559
2559
2559
2614
2581
2653
2559
2584
2583
2559
2608
2559
2559
2590
2559
2559
2580
2678
2559
2559
2544
2581
2616
2559
2534
2617
2559
2559
2557
2559
2559
2559
2683
2553
2559
2626
2559
2607
2559
2559
2679
2582
2588
2559
2581
2559
2583
2588
2581
2559
2583
2559
2589
2559
2629
2559
2559
2579
2559
2554
2558
2559
2559
2559
2590
2558
2581
2559
2559
2582
2559
2559
2583
2499
2547
2534
2491
2559
2559
2559
2559
2559
2559
2559
2549
2557
2608
2559
2591
2559
2559
2602
2559
2583
2586
2586
2587
2531
2559
2581
2559
2610
2614
2508
2559
2557
2559
2590
2558
2559
2594
2559
2541
2558
2559
2559
2551
2592
2582
2559
2608
2586
2538
2559
2559
2559
2559
2559
2559
2559
2559
2549
2559
2589
2559
2549
2559
2559
2559
2555
2555
2559
2557
2628
2559
2559
2559
2554
2473
2559
2559
2559
2556
2559
2559
2559
2582
2550
2559
2559
2586
2559
2559
2559
2475
2592
2559
2559
2557
2559
2559
2531
2559
2559
2559
2559
2559
2600
2559
2550
2551
2547
2559
2553
2589
2559
2559
2559
2559
2592
2559
2690
2468
2512
2534
2597
2558
2533
2559
2559
2559
2559
2559
2559
2559
2551
2551
2559
2547
2549
2556
2581
2559
2559
2559
2584
2559
2559
2593
2555
2545
2559
2543
2557
2559
2608
2559
2550
2559
2548
2559
2554
2559
2549
2559
2559
2559
2559
2586
2558
2559
2559
2559
2700
2559
2559
2521
2559
2550
2553
2544
2713
2559
2554
2559
2559
2533
2559
2541
2541
2559
2537
2557
2555
2451
2559
2559
2530
2559
2545
2559
2559
2543
2559
2585
2453
2557
2559
2557
2551
2594
2546
2559
2455
2480
2557
2551
2548
2523
2545
2557
2586
2511
2559
2514
2544
2559
2559
2544
2543
2555
2554
2559
2551
2559
2558
2558
2469
2559
2556
2555
2544
2515
2559
2550
2554
2553
2493
2557
2505
2558
2512
2547
2549
2546
2549
2443
2543
2550
2543
2621
2559
2559
2554
2587
2555
2554
2500
2552
2556
2559
2549
2559
2555
2538
2559
2559
2559
2559
2559
2558
2490
2556
2559
2545
2559
2559
2559
2539
2608
2545
2546
2549
2550
2549
2605
2555
2554
2544
2559
2552
2547
2557
2591
2557
2544
2548
2551
2521
2545
2448
2547
2475
2544
2559
2559
2544
2559
2559
2549
2552
2549
2546
2586
2553
2439
2551
2548
2608
2544
2480
2546
2559
2525
2555
2556
2547
2549
2546
2544
2559
2541
2544
2557
2553
2522
2544
2541
2541
2540
2531
2483
2545
2548
2559
2545
2544
2559
2559
2554
2544
2528
2549
2553
2503
2581
2542
2616
2484
2559
2544
2557
2527
2559
2523
2555
2546
2527
2590
2532
2487
2556
2530
2547
2542
2557
2480
2542
2546
2545
2583
2544
2526
2544
2559
2559
2544
2546
2544
2550
2509
2553
2539
2549
2545
2654
2542
2534
2542
2708
2551
2544
2548
2544
2546
2542
2539
2559
2559
2551
2582
2544
2543
2559
2558
2527
2544
2529
2544
2656
2539
2544
2545
2550
2491
2541
2549
2534
2554
2543
2544
2496
2551
2532
2580
2545
2544
2544
2550
2534
2559
2559
2550
2539
2546
2545
2541
2551
2656
2553
2538
2549
2528
2544
2542
2455
2540
2538
2480
2544
2518
2507
2538
2544
2544
2480
2559
2534
2525
2543
2559
2535
2531
2672
2547
2550
2533
2542
2481
2539
2530
2526
2557
2550
2535
2559
2529
2500
2591
2547
2545
2535
2597
2546
2545
2539
2473
2535
2544
2549
2548
2481
2535
2530
2544
2545
2559
2481
2463
2557
2541
2551
2531
2548
2547
2547
2558
2543
2559
2537
2537
2506
2544
2527
2550
2547
2541
2530
2477
2535
2547
2534
2527
2539
2531
2544
2534
2528
2533
2530
2527
2534
2551
2547
2548
2544
2544
2542
2493
2535
2518
2512
2527
2593
2544
2528
2535
2557
2519
2540
2541
2559
2541
2531
2534
2669
2546
2549
2539
2503
2534
2518
2538
2530
2542
2534
2512
2530
2611
2543
2528
2518
2532
2534
2402
2545
2512
2559
2544
2528
2515
2545
2525
2521
2534
2543
2525
2534
2541
2547
2535
2535
2541
2530
2534
2525
2538
2559
2523
2530
2518
2555
2543
2529
2534
2473
2495
2500
2542
2522
2495
2439
2534
2537
2527
2531
2480
2545
2539
2544
2559
2526
2512
2528
2515
2527
2527
2504
2459
2530
2517
2512
2521
2559
2526
2517
2526
2511
2538
2527
2515
2672
2523
2678
2535
2457
2509
2522
2507
2515
2416
2528
2514
2526
2608
2510
2529
2515
2507
2529
2522
2527
2533
2527
2513
2530
2525
2491
2532
2499
2524
2517
2478
2524
2474
2512
2530
2500
2531
2657
2530
2514
2539
2533
2533
2529
2554
2527
2513
2594
2531
2522
2415
2544
2529
2513
2515
2547
2530
2515
2526
2517
2530
2389
2522
2529
2559
2531
2532
2518
2526
2559
2514
2525
2499
2524
2527
2528
2512
2506
2542
2509
2533
2512
2512
2518
2497
2519
2513
2481
2522
2512
2545
2521
2545
2534
2512
2512
2518
2509
2524
2516
2541
2523
2551
2512
2477
2523
2529
2526
2493
2521
2515
2521
2545
2535
2541
2525
2519
2518
2403
2512
2514
2438
2512
2511
2528
2521
2525
2559
2507
2538
2559
2535
2523
2522
2462
2543
2524
2512
2507
2493
2516
2508
2512
2549
2538
2453
2523
2535
2522
2542
2546
2512
2515
2557
2536
2522
2531
2507
2509
2544
2502
2523
2522
2549
2522
2512
2522
2525
2521
2529
2526
2517
2526
2512
2522
2509
2512
2509
2521
2513
2512
2523
2510
2418
2497
2512
2520
2512
2516
2529
2529
2522
2519
2679
2529
2519
2527
2531
2491
2448
2501
2512
2543
2506
2529
2494
2506
2542
2509
2522
2501
2494
2491
2650
2518
2513
2512
2527
2515
2523
2538
2511
2480
2510
2517
2512
2511
2510
2505
2513
2526
2522
2504
2513
2522
2594
2539
2519
2509
2512
2544
2527
2508
2442
2513
2538
2518
2516
2511
2521
2550
2523
2513
2529
2557
2522
2505
2507
2507
2509
2507
2542
2505
2512
2509
2483
2514
2506
2516
2521
2515
2513
2505
2510
2509
2477
2512
2501
2512
2522
2511
2510
2499
2506
2498
2499
2512
2479
2489
2506
2510
2514
2557
2451
2495
2512
2502
2491
2525
2465
2512
2506
2519
2494
2502
2503
2496
2465
2512
2559
2523
2497
2495
2512
2497
2494
2486
2517
2514
2509
2519
2512
2514
2522
2508
2445
2510
2525
2503
2509
2519
2509
2496
2495
2506
2458
2510
2496
2530
2509
2506
2512
2505
2407
2506
2505
2501
2518
2494
2523
2510
2510
2501
2510
2559
2506
2512
2512
2457
2509
2512
2493
2503
2505
2494
2503
2501
2459
2491
2506
2513
2482
2426
2496
2505
2512
2495
2503
2494
2492
2499
2505
2512
2503
2498
2505
2409
2489
2516
2512
2559
2504
2487
2544
2504
2512
2499
2559
2510
2485
2531
2653
2535
2491
2502
2510
2509
2501
2481
2509
2501
2512
2512
2491
2501
2492
2511
2496
2502
2498
2559
2527
2548
2531
2512
2500
2434
2529
2498
2502
2509
2550
2491
2513
2540
2527
2544
2506
2475
2559
2502
2494
2549
2423
2502
2511
2540
2509
2495
2494
2496
2498
2583
2518
2507
2497
2501
2485
2507
2496
2496
2500
2557
2502
2497
2497
2495
2494
2486
2497
2507
2495
2498
2421
2474
2499
2496
2508
2498
2481
2493
2499
2470
2512
2491
2479
2502
2498
2497
2496
2492
2527
2455
2510
2502
2509
2531
2502
2496
2499
2500
2444
2503
2512
2512
2409
2512
2498
2499
2501
2506
2509
2526
2510
2506
2478
2463
2621
2494
2495
2491
2496
2482
2486
2508
2498
2517
2501
2496
2530
2480
2496
2508
2487
2474
2480
2485
2423
2486
2489
2624
2498
2496
2500
2490
2499
2503
2482
2490
2477
2500
2487
2493
2491
2497
2625
2467
2485
2491
2488
2497
2497
2486
2491
2486
2491
2497
2497
2512
2469
2496
2493
2513
2495
2497
2491
2506
2489
2496
2487
2490
2489
2496
2416
2525
2480
2489
2491
2487
2480
2496
2513
2497
2491
2490
2395
2491
2482
2483
2498
2471
2489
2493
2485
2490
2496
2497
2388
2483
2496
2448
2506
2473
2485
2479
2480
2480
2477
2475
2482
2522
2511
2495
2448
2489
2406
2507
2547
2486
2447
2489
2487
2476
2495
2480
2480
2427
2530
2491
2479
2481
2483
2321
2477
2480
2479
2461
2489
2478
2494
2480
2486
2489
2461
2427
2482
2508
2484
2527
2484
2482
2485
2414
2487
2487
2487
2385
2482
2482
2479
2480
2505
2497
2507
2484
2477
2507
2386
2480
2483
2481
2485
2470
2470
2486
2467
2480
2485
2493
2416
2461
2477
2482
2491
2462
2468
2487
2481
2507
2480
2480
2457
2478
2608
2459
2503
2480
2487
2517
2471
2479
2483
2471
2376
2476
2448
2484
2354
2459
2541
2448
2480
2479
2477
2477
2474
2478
2475
2480
2479
2460
2430
2495
2493
2459
2462
2475
2477
2477
2478
2485
2480
2480
2455
2416
2481
2439
2476
2467
2485
2478
2475
2474
2486
2470
2485
2461
2480
2511
2483
2482
2481
2480
2461
2465
2479
2475
2472
2487
2475
2487
2393
2481
2417
2482
2474
2419
2486
2512
2448
2471
2480
2386
2478
2642
2485
2480
2462
2492
2451
2513
2480
2469
2471
2473
2417
2477
2479
2475
2481
2503
2527
2470
2471
2473
2470
2469
2465
2480
2475
2469
2465
2480
2467
2475
2475
2468
2455
2465
2464
2480
2473
2451
2480
2479
2484
2459
2430
2480
2448
2484
2470
2435
2476
2496
2475
2480
2462
2477
2460
2467
2480
2475
2468
2495
2464
2473
2471
2466
2512
2461
2510
2466
2473
2485
2496
2471
2467
2489
2471
2454
2491
2423
2493
2461
2469
2519
2477
2469
2481
2427
2475
2471
2472
2479
2455
2471
2479
2466
2464
2475
2429
2477
2453
2384
2467
2473
2511
2415
2469
2463
2453
2463
2464
2475
2459
2380
2476
2448
2453
2465
2457
2449
2478
2467
2411
2453
2466
2469
2451
2451
2474
2465
2505
2437
2478
2433
2463
2466
2463
2486
2478
2463
2467
2470
2462
2471
2471
2483
2455
2474
2475
2461
2468
2438
2456
2389
2464
2470
2463
2451
2453
2485
2455
2448
2433
2463
2467
2468
2448
2469
2459
2463
2471
2463
2384
2468
2471
2463
2466
2475
2465
2483
2463
2469
2468
2457
2464
2414
2480
2462
2468
2458
2473
2473
2449
2469
2464
2467
2405
2443
2489
2518
2367
2464
2467
2494
2467
2403
2480
2467
2460
2374
2448
2471
2450
2448
2442
2448
2445
2539
2448
2448
2453
2448
2464
2455
2485
2448
2480
2468
2449
2466
2454
2463
2459
2455
2457
2452
2466
2481
2466
2448
2459
2481
2551
2464
2466
2458
2495
2466
2450
2455
2435
2447
2435
2434
2455
2464
2601
2469
2451
2463
2459
2447
2462
2457
2459
2332
2459
2459
2455
2434
2453
2442
2472
2463
2462
2448
2451
2461
2464
2449
2455
2461
2467
2438
2454
2454
2452
2448
2457
2474
2441
2458
2495
2458
2464
2434
2433
2418
2559
2442
2448
2449
2464
2448
2453
2450
2448
2451
2449
2416
2451
2463
2440
2559
2449
2528
2608
2452
2448
2448
2465
2384
2432
2439
2442
2419
2447
2464
2433
2451
2436
2463
2438
2444
2460
2451
2494
2450
2459
2448
2448
2461
2457
2410
2448
2399
2447
2434
2447
2454
2448
2470
2448
2445
2439
2448
2448
2402
2459
2432
2451
2463
2462
2467
2448
2450
2453
2485
2422
2535
2431
2445
2442
2449
2541
2442
2447
2441
2430
2445
2457
2447
2371
2451
2448
2430
2426
2678
2435
2367
2445
2446
2448
2434
2368
2450
2428
2442
2464
2432
2461
2546
2384
2427
2447
2476
2441
2451
2439
2416
2434
2453
2455
2534
2438
2447
2453
2439
2474
2455
2438
2441
2550
2443
2437
2437
2437
2432
2447
2431
2445
2512
2512
2448
2447
2448
2435
2482
2429
2453
2416
2448
2485
2436
2445
2423
2447
2443
2454
2448
2448
2448
2448
2545
2445
2443
2453
2429
2453
2453
2417
2432
2433
2437
2432
2442
2446
2449
2387
2427
2439
2448
2442
2433
2438
2403
2438
2451
2417
2409
2441
2443
2471
2475
2425
2439
2428
2418
2398
2437
2439
2431
2439
2395
2454
2439
2431
2422
2432
2458
2436
2422
2435
2446
2437
2428
2436
2435
2447
2437
2435
2448
2425
2442
2445
2386
2441
2441
2445
2447
2439
2449
2440
2435
2432
2437
2405
2448
2521
2494
2446
2465
2433
2470
2404
2431
2256
2431
2353
2430
2433
2432
2499
2422
2432
2414
2430
2361
2441
2430
2442
2445
2431
2432
2411
2384
2438
2396
2529
2428
2369
2416
2423
2433
2427
2408
2493
2407
2425
2436
2374
2425
2411
2395
2430
2431
2434
2446
2431
2425
2369
2423
2435
2457
2399
2431
2418
2434
2407
2418
2418
2434
2419
2417
2427
2429
2441
2467
2425
2416
2427
2441
2447
2426
2432
2428
2429
2438
2417
2426
2333
2435
2407
2422
2439
2430
2400
2438
2411
2428
2440
2451
2458
2427
2427
2426
2435
2439
2430
2371
2454
2431
2429
2470
2418
2354
2435
2439
2432
2427
2421
2416
2431
2419
2558
2416
2438
2404
2425
2441
2351
2375
2419
2427
2352
2421
2418
2423
2443
2421
2442
2420
2424
2432
2422
2432
2411
2433
2443
2439
2387
2434
2407
2441
2436
2438
2427
2399
2434
2421
2419
2432
2432
2416
2434
2421
2432
2443
2400
2414
2432
2435
2429
2423
2427
2419
2411
2427
2426
2513
2420
2391
2455
2416
2432
2432
2426
2427
2430
2415
2425
2429
2416
2414
2417
2418
2397
2412
2419
2406
2410
2414
2381
2425
2450
2407
2416
2401
2420
2416
2411
2419
2379
2416
2391
2434
2407
2397
2416
2351
2405
2426
2415
2402
2419
2415
2413
2433
2416
2427
2412
2559
2386
2416
2365
2443
2291
2397
2419
2432
2409
2415
2432
2415
2426
2377
2410
2417
2418
2452
2460
2416
2529
2404
2386
2416
2422
2423
2416
2416
2417
2416
2416
2410
2377
2401
2416
2352
2402
2414
2530
2405
2407
2403
2418
2395
2411
2311
2407
2406
2446
2411
2416
2332
2415
2413
2399
2423
2416
2417
2415
2417
2423
2421
2432
2307
2425
2415
2413
2397
2384
2410
2406
2431
2421
2416
2410
2410
2401
2394
2436
2416
2399
2400
2353
2405
2407
2398
2401
2400
2401
2413
2411
2404
2408
2411
2413
2411
2406
2422
2416
2410
2390
2416
2512
2409
2411
2326
2415
2395
2349
2423
2395
2394
2404
2397
2375
2369
2419
2414
2358
2390
2400
2406
2384
2398
2397
2395
2410
2403
2466
2430
2386
2421
2411
2397
2413
2410
2415
2380
2403
2390
2405
2391
2297
2423
2394
2470
2384
2346
2398
2405
2405
2397
2391
2399
2397
2398
2402
2389
2395
2421
2367
2375
2396
2401
2416
2404
2414
2403
2391
2302
2463
2421
2387
2425
2405
2410
2426
2401
2404
2425
2406
2395
2409
2395
2432
2407
2402
2543
2400
2417
2416
2403
2416
2351
2403
2403
2379
2379
2409
2409
2409
2425
2394
2397
2399
2503
2333
2411
2439
2401
2390
2401
2395
2517
2418
2387
2498
2402
2406
2395
2408
2362
2394
2391
2404
2403
2416
2399
2387
2405
2421
2400
2398
2284
2397
2405
2402
2398
2395
2449
2401
2410
2401
2409
2407
2378
2412
2411
2394
2402
2423
2387
2393
2382
2413
2401
2409
2388
2403
2397
2400
2395
2395
2393
2406
2326
2393
2385
2428
2389
2395
2398
2386
2387
2310
2352
2394
2393
2369
2383
2381
2403
2381
2407
2401
2393
2400
2398
2395
2370
2395
2390
2383
2429
2375
2429
2387
2385
2493
2399
2384
2385
2397
2391
2351
2416
2397
2409
2381
2393
2382
2391
2320
2384
2384
2390
2380
2380
2384
2393
2387
2384
2383
2381
2383
2507
2387
2393
2369
2392
2370
2375
2384
2384
2387
2346
2404
2384
2385
2366
2393
2395
2390
2387
2400
2394
2383
2385
2311
2382
2373
2397
2384
2386
2394
2384
2370
2389
2378
2391
2320
2384
2388
2517
2394
2389
2389
2438
2385
2421
2384
2423
2390
2390
2383
2394
2492
2384
2391
2381
2384
2418
2385
2411
2395
2389
2305
2394
2390
2389
2384
2384
2384
2397
2394
2384
2320
2526
2396
2384
2381
2524
2341
2393
2388
2403
2339
2413
2371
2400
2365
2401
2343
2405
2384
2291
2319
2397
2397
2389
2384
2364
2373
2373
2397
2339
2383
2389
2379
2375
2390
2362
2314
2398
2464
2535
2393
2402
2384
2381
2382
2381
2343
2375
2335
2394
2368
2375
2385
2359
2368
2395
2384
2383
2352
2380
2384
2391
2381
2339
2404
2386
2450
2384
2369
2484
2395
2448
2382
2377
2384
2379
2385
2370
2384
2422
2375
2455
2385
2363
2384
2385
2375
2389
2382
2374
2383
2309
2378
2374
2385
2426
2330
2379
2362
2373
2370
2377
2343
2379
2373
2372
2371
2378
2384
2281
2368
2369
2369
2374
2389
2342
2435
2368
2363
2375
2387
2373
2384
2364
2382
2373
2375
2366
2369
2375
2373
2364
2358
2342
2384
2321
2337
2383
2358
2371
2384
2307
2320
2358
2371
2379
2378
2366
2387
2368
2374
2382
2374
2367
2384
2381
2383
2352
2311
2389
2382
2397
2366
2397
2375
2384
2382
2387
2362
2377
2378
2368
2398
2258
2380
2356
2384
2408
2400
2381
2375
2384
2359
2381
2370
2349
2369
2315
2322
2371
2363
2342
2383
2361
2384
2364
2386
2365
2315
2304
2367
2354
2384
2352
2335
2370
2366
2294
2259
2367
2371
2372
2372
2355
2368
2365
2365
2382
2368
2384
2367
2373
2353
2368
2368
2384
2371
2383
2368
2359
2382
2352
2369
2363
2355
2370
2348
2366
2418
2367
2352
2434
2365
2321
2367
2347
2364
2351
2383
2384
2352
2374
2167
2371
2372
2385
2367
2385
2385
2350
2359
2379
2362
2375
2366
2305
2367
2366
2471
2361
2365
2363
2381
2357
2356
2384
2378
2390
2362
2364
2363
2352
2365
2364
2361
2353
2358
2354
2352
2358
2349
2367
2352
2358
2368
2298
2352
2368
2365
2369
2352
2384
2333
2377
2363
2311
2349
2377
2360
2352
2369
2353
2395
2357
2357
2355
2350
2366
2359
2357
2362
2367
2359
2365
2350
2361
2354
2360
2353
2285
2352
2363
2349
2355
2399
2355
2361
2352
2393
2362
2357
2351
2368
2315
2357
2360
2367
2365
2279
2357
2368
2363
2359
2361
2368
2363
2358
2480
2367
2279
2341
2366
2403
2353
2366
2309
2323
2352
2367
2336
2408
2357
2347
2358
2351
2420
2357
2369
2335
2375
2354
2373
2367
2352
2348
2355
2355
2368
2352
2377
2331
2460
2364
2336
2351
2345
2350
2301
2375
2355
2351
2323
2352
2353
2494
2354
2362
2367
2353
2482
2384
2355
2363
2352
2337
2275
2462
2354
2355
2391
2350
2352
2355
2328
2347
2278
2358
2359
2275
2365
2352
2368
2359
2353
2350
2354
2351
2359
2352
2365
2368
2333
2279
2350
2362
2353
2353
2358
2354
2375
2350
2347
2343
2353
2365
2343
2354
2363
2357
2343
2340
2345
2354
2346
2353
2355
2354
* Mic branch [2026-04-19 Sun]
INMP441
heres my overall (very messy) notes.
i need a stepwise checklist of work to do, picking up this project after 6mo.
i think broadest steps are:
1. remind myself of circuit state, how to hookup and test
2. implement inmp441 - may need to retool the circuit?
1. will this functino on the existing power (big goal)
2. remove/modify any inline circuitry to make this work?
3. ??? test?
_Goal_: replace noisy speaker-tap adc path with an inmp441 mic path
- reuse existing esp32 + wifi + rtp stack
- reuse existing 3.17v power tap
** checklist
*** Bench Check
- the exact esp32 board
- the vtech dm221-2 / pm221
- known-good firmware that can stream the 440hz tone over rtp to vlc
- the current ip/ssid/port expectations
- success = you can flash, boot, and hear tone mode again in vlc. this revalidates the network/rtp side before you perturb the input path
*** Confirm live circuit:
- take clear photos of pcb top/bottom
- mark current power tap location
- mark current speaker/adc wiring
- note whether gpio36 speaker-tap circuit is still installed
- note whether touch pin mode switching is still wired
- your notes show enough circuit churn that future-you will otherwise get gaslit by Past You.
*** Verify power in isolation:
- measure the 3.17v rail again at tp20/tp12/q6
- confirm esp32 still boots stably from that rail
- add/confirm local decoupling near esp32 power if needed
- success = stable boot, wifi connect, no brownout/reboot weirdness. you already concluded the 3.17v tap was viable and a major goal is to keep it.
*** Verify s/w baseline
keep hardware input out of it for a minute:
- flash the known-good tone generator
- confirm seq/ts behavior and vlc playback
- optionally disable wifi power save while testing
- success = tone stream sounds clean enough that any later ugliness is input-side, not transport-side.
*** hardware cutover
assume the old speaker-to-gpio36 analog front end gets bypassed or removed:
- gpio36 adc path is no longer the primary input
- the RC/divider/bias network for speaker tap is not needed for the mic path
- keep it only if you explicitly want fallback mode later
- this is the big topology change. dont half-migrate and leave yourself ambiguous failure modes. your notes already point to the speaker tap being the pain source.
*** bench-test the inmp441 off the existing esp32 power
- power inmp441 from the same esp32 3.xv rail
- wire only power + ground + i2s lines
- capture raw samples / stream audio with the mic sitting on the bench
- success = it powers and produces stable audio without resets/noise disasters.
** inmp441 table
| PIN | NAME | FUNCTION |
|-----+--------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 1 | SCK | Serial-Data Clock for I²S Interface |
| 2 | SD | Serial-Data Output for I²S Interface. This pin tri-states when not actively driving the appropriate output channel. The SD trace should have a 100 kΩ pulldown resistor to discharge the line during the time that all microphones on the bus have tri-stated their outputs. |
| 3 | WS | Serial Data-Word Select for I²S Interface |
| 4 | L/R | Left/Right Channel Select. When set low, the microphone outputs its signal in the left channel of the I²S frame. When set high, the microphone outputs its signal in the right channel. |
| 5 | GND | Ground. Connect to ground on the PCB. |
| 6 | GND | Ground. Connect to ground on the PCB. |
| 7 | VDD | Power, 1.8 V to 3.3 V. This pin should be decoupled to Pin 6 with a 0.1 μF capacitor. |
| 8 | CHIPEN | Microphone Enable. When set low (ground), the microphone is disabled and put in power-down mode. When set high (VDD), the microphone is enabled. |
| 9 | GND | Ground. Connect to ground on the PCB |
- added sketch to /proj/vtech/mic
couple caveats, bc esp32 audio loves being a goblin:
the >> 11 unpack line is the bit most likely to need fiddling on your exact board/core, and I2S_COMM_FORMAT_STAND_I2S vs one of the older enum names can vary by installed core.
*** script
#+begin_src c
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 16000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 800; // adjust as needed
// inmp441 pins - change as needed
const int I2S_WS = 25; //
const int I2S_SCK = 26; //
const int I2S_SD = 33; // data from mic to esp32
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
// init touch
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0;
static unsigned long last_touch_check = 0;
static bool last_touch_state = false;
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("switched to %s mode\n", tone_mode ? "tone" : "mic");
delay(200); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// only send if it's time
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
// read 320 mic samples @16khz, decimate by 2 -> 160 samples @8khz
int32_t mic_buf[FRAME_SIZE * 2];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
int frames_read = bytes_read / sizeof(int32_t);
if (frames_read < FRAME_SIZE * 2) {
for (int i = 0; i < FRAME_SIZE; i++) samples[i] = 0;
} else {
static float dc = 0.0f;
static float lpf = 0.0f;
for (int i = 0; i < FRAME_SIZE; i++) {
// inmp441 data is typically left-justified in 32-bit words; shift may need
// minor tweaking on your exact board/core
int32_t raw = mic_buf[i * 2] >> 14; // collapse toward 16-bit-ish range
float x = (float)raw;
dc = dc * 0.999f + x * 0.001f;
x -= dc;
lpf = lpf * 0.7f + x * 0.3f;
float y = lpf * 1.0f; // gain trim try 8.0f?
if (y > 32767.0f) y = 32767.0f;
if (y < -32768.0f) y = -32768.0f;
samples[i] = (int16_t)y;
}
//DEBUG
static unsigned long last_dbg = 0;
int16_t minv = 32767;
int16_t maxv = -32768;
for (int j = 0; j < FRAME_SIZE; j++) {
if (samples[j] < minv) minv = samples[j];
if (samples[j] > maxv) maxv = samples[j];
}
if (millis() - last_dbg > 250) {
Serial.printf("mic range: %d .. %d\n", minv, maxv);
last_dbg = millis();
}
// END DEBUG
}
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
*** script2 - simple mic processing (ln160 ff)
#+begin_src c
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 16000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 800; // adjust as needed
// inmp441 pins - change as needed
const int I2S_WS = 25; //
const int I2S_SCK = 26; //
const int I2S_SD = 33; // data from mic to esp32
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
// init touch
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0;
static unsigned long last_touch_check = 0;
static bool last_touch_state = false;
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("%s mode active\n", tone_mode ? "tone" : "mic");
delay(300); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// only send if it's time
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
// read 320 mic samples @16khz, decimate by 2 -> 160 samples @8khz
int32_t mic_buf[FRAME_SIZE * 2];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
int frames_read = bytes_read / sizeof(int32_t);
if (frames_read < FRAME_SIZE * 2) {
for (int i = 0; i < FRAME_SIZE; i++) samples[i] = 0;
} else {
static float dc = 0.0f;
static float lpf = 0.0f;
//
int16_t minv = 32767;
int16_t maxv = -32768;
static unsigned long last_dbg = 0;
for (int i = 0; i < FRAME_SIZE; i++) {
int32_t raw = mic_buf[i * 2] >> 8; // try 8 first, not 14
if (raw > 32767) raw = 32767;
if (raw < -32768) raw = -32768;
samples[i] = (int16_t)raw;
if (samples[i] < minv) minv = samples[i];
if (samples[i] > maxv) maxv = samples[i];
}
if (millis() - last_dbg > 250) {
Serial.printf("raw range: %d .. %d\n", minv, maxv);
last_dbg = millis();
}
}
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
*** script3 - hex dump version:
#+begin_src c++
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 16000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 800; // adjust as needed
// inmp441 pins - change as needed
const int I2S_WS = 25; //
const int I2S_SCK = 26; //
const int I2S_SD = 33; // data from mic to esp32
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
// init touch
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0;
static unsigned long last_touch_check = 0;
static bool last_touch_state = false;
static unsigned long last_dbg = 0;
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("%s mode active\n", tone_mode ? "tone" : "mic");
delay(300); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// only send if it's time
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
// read 320 mic samples @16khz, decimate by 2 -> 160 samples @8khz
int32_t mic_buf[FRAME_SIZE * 2];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
for (int i = 0; i < FRAME_SIZE; i++) {
samples[i] = 0;
}
if (bytes_read >= 16 * sizeof(int32_t) && millis() - last_dbg > 500) {
Serial.println("first 16 raw words:");
for (int i = 0; i < 16; i++) {
Serial.printf("%2d: 0x%08lx\n", i, (uint32_t)mic_buf[i]);
}
last_dbg = millis();
}
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
** issue
https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/
- dump is overwhelmingly 0x00000000, 0x00000001, or 0xffffffff, with only very occasional nontrivial words like 0xffbffb41. that means the esp32 is clocking something, but it is mostly seeing a line that is effectively stuck low/high or only barely transitioning, not normal audio sample words.
- in esp32 standard i2s mode, the bus is just bclk, ws, and data, and standard mode always has left/right slots. in master mode, the esp32 generates sck and ws; the mic only drives the data line.
- standard-mode format differences on esp32 are basically philips vs msb, where philips has a one-bit shift relative to ws and msb does not. so “wrong format” can cause junk, but a stream dominated by exact 0/1/-1 patterns is more consistent with bad data capture than mere gain.
* [2026-04-20 Mon]
very useful expl thanks, you're refreshign my memory on the rtp header work i did a few months ago. good insight on 440hz wandering - i didnt account for network instability inherent in the chipset, of course that makes sense.
heres the mic datasheet.
(WHT) LR GND (BLK)
(YEL) WS VDD (RED)
(WHT) SCK SD (BLUE)
gnd (WHT) LR GND (BLK)
g25 (YEL) WS VDD (RED)
g22 (WHT) SCK SD (BLUE) g21
mic outputs 24-bit signed sample, left-justified in 32-bit word
[31........8][7.....0]
sample pad
** successful hex word test of inmf441
#+begin_src c++
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 16000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 800; // adjust as needed
// inmp441 pins - change as needed
const int I2S_WS = 25; //
const int I2S_SCK = 22; //
const int I2S_SD = 21; // data from mic to esp32
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
// .communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0; // timer
static unsigned long last_touch_check = 0; // timer
static bool last_touch_state = false;
static unsigned long last_dbg = 0; // timer
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("%s mode active\n", tone_mode ? "tone" : "mic");
delay(300); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// only send if it's time
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
// read 320 mic samples @16khz, decimate by 2 -> 160 samples @8khz
int32_t mic_buf[FRAME_SIZE * 2];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
for (int i = 0; i < FRAME_SIZE; i++) {
samples[i] = 0;
}
if (bytes_read >= 16 * sizeof(int32_t) && millis() - last_dbg > 500) {
Serial.println("first 16 raw words:");
for (int i = 0; i < 16; i++) {
Serial.printf("%2d: 0x%08lx\n", i, (uint32_t)mic_buf[i]);
}
last_dbg = millis();
}
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
** to add
dc gain
dc = dc * 0.999f + x * 0.001f;
x -= dc;
low pass filter
lpf = lpf * 0.7f + x * 0.3f;
gain
float y = x * 2.0f;
before adding gains:
#+begin_src C++
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 16000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 800; // adjust as needed
// inmp441 pins - change as needed
const int I2S_WS = 25; //
const int I2S_SCK = 22; //
const int I2S_SD = 21; // data from mic to esp32
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
// .communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0; // timer
static unsigned long last_touch_check = 0; // timer
static bool last_touch_state = false;
static unsigned long last_dbg = 0; // timer
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("%s mode active\n", tone_mode ? "tone" : "mic");
delay(300); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// only send if it's time
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
// read 320 mic samples @16khz, decimate by 2 -> 160 samples @8khz
int32_t mic_buf[FRAME_SIZE * 2];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
for (int i = 0; i < FRAME_SIZE; i++) {
// decimate 16k → 8k
int32_t raw = mic_buf[i * 2] >> 16; // decimate 16k -> 8k by keeping every other sample
if (raw > 32767) raw = 32767;
if (raw < -32768) raw = -32768;
samples[i] = (int16_t)raw;
}
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
after gains SUCCESS IWTH SOUND!
#+begin_src c++
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 16000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 800; // adjust as needed
// inmp441 pins - change as needed
const int I2S_WS = 25; //
const int I2S_SCK = 22; //
const int I2S_SD = 21; // data from mic to esp32
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
// .communication_format = I2S_COMM_FORMAT_I2S_MSB,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0; // timer
static unsigned long last_touch_check = 0; // timer
static bool last_touch_state = false;
static unsigned long last_dbg = 0; // timer
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("%s mode active\n", tone_mode ? "tone" : "mic");
delay(300); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// only send if it's time
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
// read 320 mic samples @16khz, decimate by 2 -> 160 samples @8khz
int32_t mic_buf[FRAME_SIZE * 2];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
//debug
if (millis() - last_dbg > 500) {
for (int i = 0; i < 8; i++) {
Serial.printf("%d: 0x%08lx\n", i, (uint32_t)mic_buf[i]);
}
last_dbg = millis();
}
//end debug
for (int i = 0; i < FRAME_SIZE; i++) {
// decimate 16k → 8k
int32_t raw = mic_buf[i] >> 16; // full send
// int32_t raw = mic_buf[i*2] >> 16; // drop every other frame to get to 8k
samples[i] = (int16_t)raw;
}
int16_t minv = 32767;
int16_t maxv = -32768;
for (int j = 0; j < FRAME_SIZE; j++) {
if (samples[j] < minv) minv = samples[j];
if (samples[j] > maxv) maxv = samples[j];
}
//debug2
if (millis() - last_dbg > 500) {
Serial.printf("mic range: %d .. %d\n", minv, maxv);
}
//end debug2
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
likely slow bc of full send line:
: int32_t raw = mic_buf[i] >> 16; // full send
** done
#+begin_src c++
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 8000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 500;
const int I2S_WS = 25;
const int I2S_SCK = 22;
const int I2S_SD = 21;
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0; // timer
static unsigned long last_touch_check = 0; // timer
static bool last_touch_state = false;
static unsigned long last_dbg = 0; // timer
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("%s mode active\n", tone_mode ? "tone" : "mic");
delay(300); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// frame buffer
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
int32_t mic_buf[FRAME_SIZE];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
for (int i = 0; i < FRAME_SIZE; i++) {
float y = (mic_buf[i] >> 16) * 4.0f; //gain
if (y > 32767.0f) y = 32767.0f;
if (y < -32768.0f) y = -32768.0f;
samples[i] = (int16_t)y;
}
int16_t minv = 32767;
int16_t maxv = -32768;
for (int j = 0; j < FRAME_SIZE; j++) {
if (samples[j] < minv) minv = samples[j];
if (samples[j] > maxv) maxv = samples[j];
}
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
* Final Veersion mic.cpp
#+begin_src c++
#include <WiFi.h>
#include <WiFiUdp.h>
#include <math.h>
#include <driver/i2s.h>
#include <driver/touch_pad.h>
const char* ssid = "Fios-8EKF5";
const char* password = "hero816cars7050jon";
const char* DEST_IP = "192.168.1.190";
const int UDP_PORT = 5004;
const int OUTPUT_RATE = 8000; // 8kHz rtp payload rate
const int MIC_RATE = 8000; // capture rate inmp441
const int FRAME_SIZE = 160; // 20ms frames @ 8kHz
const float TONE_HZ = 440.0;
const float MIC_GAIN = 4.0f;
const touch_pad_t TOUCH_PIN = TOUCH_PAD_NUM4; // gpio13
const int TOUCH_THRESHOLD = 500;
const int I2S_WS = 25;
const int I2S_SCK = 22;
const int I2S_SD = 21;
WiFiUDP udp;
uint16_t seq = 0;
uint32_t ts = 0;
bool tone_mode = true; // start with tone
struct rtp_hdr {
uint8_t vpxcc;
uint8_t mpt;
uint16_t seq;
uint32_t ts;
uint32_t ssrc;
};
static const int16_t exp_lut[256] = {
0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
};
uint8_t linear2ulaw(int16_t pcm_val) {
int sign = (pcm_val >> 8) & 0x80;
if (sign) pcm_val = (short)-pcm_val;
if (pcm_val > 32635) pcm_val = 32635;
pcm_val = pcm_val + 0x84;
int exponent = exp_lut[(pcm_val >> 7) & 0xFF];
int mantissa = (pcm_val >> (exponent + 3)) & 0x0F;
return ~(sign | (exponent << 4) | mantissa);
}
void setup_i2s_mic() {
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = MIC_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 8,
.dma_buf_len = 256,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_SCK,
.ws_io_num = I2S_WS,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = I2S_SD
};
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_pin(I2S_NUM_0, &pin_config);
i2s_zero_dma_buffer(I2S_NUM_0);
}
void setup() {
Serial.begin(115200);
touch_pad_init();
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_1V);
touch_pad_config(TOUCH_PIN, 0);
setup_i2s_mic();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }
Serial.printf("\nconnected, ip=%s\n", WiFi.localIP().toString().c_str());
udp.begin(UDP_PORT);
Serial.println("tap pin 13 to switch modes");
}
void loop() {
static unsigned long last_send = 0; // timer
static unsigned long last_touch_check = 0; // timer
static bool last_touch_state = false;
static const unsigned long FRAME_INTERVAL = 20; // 20ms
static const unsigned long TOUCH_CHECK_INTERVAL = 50; // check every 50ms
// check touch state periodically
unsigned long now = millis();
if (now - last_touch_check > TOUCH_CHECK_INTERVAL) {
uint16_t touch_val;
touch_pad_read(TOUCH_PIN, &touch_val);
bool touched = touch_val < TOUCH_THRESHOLD;
// detect touch press (not hold)
if (touched && !last_touch_state) {
tone_mode = !tone_mode;
Serial.printf("%s mode active\n", tone_mode ? "tone" : "mic");
delay(300); // debounce
}
last_touch_state = touched;
last_touch_check = now;
}
// frame buffer
if (now - last_send < FRAME_INTERVAL) {
yield();
return;
}
uint8_t packet[12 + FRAME_SIZE];
int16_t samples[FRAME_SIZE];
if (tone_mode) {
// fixed tone generation with integer phase accumulator
static uint32_t phase_acc = 0;
const uint32_t phase_inc_int = (uint32_t)(TONE_HZ * (1ULL << 32) / OUTPUT_RATE);
for (int i = 0; i < FRAME_SIZE; i++) {
float phase = (phase_acc >> 16) * (2.0 * M_PI / 65536.0);
samples[i] = (int16_t)(16000.0 * sinf(phase));
phase_acc += phase_inc_int;
}
} else {
int32_t mic_buf[FRAME_SIZE];
size_t bytes_read = 0;
i2s_read(I2S_NUM_0, mic_buf, sizeof(mic_buf), &bytes_read, portMAX_DELAY);
if (bytes_read != sizeof(mic_buf)) {
memset(samples, 0, sizeof(samples));
} else {
for (int i = 0; i < FRAME_SIZE; i++) {
float y = (mic_buf[i] >> 16) * MIC_GAIN; //gain
if (y > 32767.0f) y = 32767.0f;
if (y < -32768.0f) y = -32768.0f;
samples[i] = (int16_t)y;
}
}
}
for (int i = 0; i < FRAME_SIZE; i++) {
packet[12 + i] = linear2ulaw(samples[i]);
}
rtp_hdr* hdr = (rtp_hdr*)packet;
hdr->vpxcc = 0x80;
hdr->mpt = 0x00;
hdr->seq = htons(seq++);
hdr->ts = htonl(ts);
hdr->ssrc = htonl(0x12345678);
udp.beginPacket(DEST_IP, UDP_PORT);
udp.write(packet, sizeof(packet));
udp.endPacket();
ts += FRAME_SIZE;
last_send = now;
yield();
}
#+end_src
** optimize:
* TODOs
- add pot knob gain, middle at 4.0f
- web server interface/config - need to load wifi creds etc
try hardcoded station connect
if fail, start softap + web portal
from portal, optionally save new ssid/pwd and switch to station mode