Compare commits
11
Commits
v1.0.0
...
3a1a095e97
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a1a095e97 | ||
|
|
cbf724db2a | ||
|
|
dcd4ef7e1b | ||
|
|
02dee65b2b | ||
|
|
fb59015fca | ||
|
|
83c0ba3e74 | ||
|
|
e92aea0c84 | ||
|
|
f6e10a293a | ||
|
|
4ad130a334 | ||
|
|
7d0edf13c4 | ||
|
|
d8323c653b |
No files matched your search
+52
-26
@@ -3,9 +3,13 @@ name: CI
|
||||
# Documentação e configuração de ferramenta não mudam nada que a suíte teste.
|
||||
# Na main não roda por push: o release.yml é quem a chama, e só quando a imagem
|
||||
# precisa ser reconstruída; rodar nos dois repetiria a mesma suíte no mesmo commit.
|
||||
# Sem gatilho de pull_request: o push da branch já valida o mesmo commit, e os
|
||||
# dois juntos rodariam tudo duas vezes (o repositório não recebe PR de fork).
|
||||
#
|
||||
# A imagem é construída aqui uma única vez, em arm64 (a arquitetura do servidor),
|
||||
# testada e publicada como inputs-<hash>. Ao fazer o merge, o release encontra
|
||||
# essa tag e só aplica os nomes novos, sem rodar nem construir nada de novo.
|
||||
on:
|
||||
pull_request:
|
||||
paths-ignore: ['**.md', 'LICENSE', '.claude/**', '.superset/**', '.wolf/**', 'scripts/release-notes.sh']
|
||||
push:
|
||||
branches-ignore: [main]
|
||||
paths-ignore: ['**.md', 'LICENSE', '.claude/**', '.superset/**', '.wolf/**', 'scripts/release-notes.sh']
|
||||
@@ -20,7 +24,7 @@ concurrency:
|
||||
|
||||
jobs:
|
||||
verificar:
|
||||
name: Lint, design e build
|
||||
name: Lint e auditorias
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
env:
|
||||
@@ -35,24 +39,11 @@ jobs:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
# Next.js guarda aqui o resultado da compilação anterior; sem isso, cada
|
||||
# execução recompila todas as páginas do zero.
|
||||
- name: Cache de build do Next
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .next/cache
|
||||
key: next-${{ runner.arch }}-${{ hashFiles('package-lock.json') }}-${{ hashFiles('app/**', 'components/**', 'lib/**') }}
|
||||
restore-keys: |
|
||||
next-${{ runner.arch }}-${{ hashFiles('package-lock.json') }}-
|
||||
next-${{ runner.arch }}-
|
||||
|
||||
- run: npm ci
|
||||
|
||||
# eslint + auditoria do design system (tokens, contraste AAA) + auditoria de páginas
|
||||
- run: npm run check
|
||||
|
||||
- run: npm run build
|
||||
|
||||
# Trivy roda pela imagem oficial: o trivy-action clona o repositório do Trivy
|
||||
# do mesmo servidor do workflow, que aqui é o Gitea, e não o GitHub.
|
||||
# O workspace do job é um volume que o daemon não enxerga, então os arquivos
|
||||
@@ -72,26 +63,61 @@ jobs:
|
||||
docker rm "$cid" >/dev/null
|
||||
exit "$status"
|
||||
|
||||
# Só começa depois das verificações baratas: um lint quebrado não gasta um
|
||||
# build de imagem. Roda no runner arm64, o mesmo tipo do servidor, então o
|
||||
# que é escaneado e testado é a imagem que vai ao ar.
|
||||
imagem:
|
||||
name: Imagem Docker
|
||||
runs-on: ubuntu-latest
|
||||
name: Imagem Docker (linux/arm64)
|
||||
needs: [verificar, seguranca]
|
||||
runs-on: ubuntu-24.04-arm
|
||||
env:
|
||||
REGISTRY: git.lucasrguerra.dev.br
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
# `docker build` simples: o cache de camadas fica no volume persistente do
|
||||
# daemon do runner, e o buildx criaria um BuildKit novo a cada job.
|
||||
|
||||
# Conteúdo já publicado (re-push, tag num commit já validado): nada a fazer.
|
||||
- id: plano
|
||||
run: scripts/plano-imagem.sh "$REGISTRY" "${{ gitea.repository }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- if: ${{ steps.plano.outputs.reuse != 'true' }}
|
||||
uses: docker/login-action@v4
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ gitea.actor }}
|
||||
password: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
# `docker build` simples, no daemon persistente do runner: as camadas e os
|
||||
# cache mounts do Dockerfile (npm e compilação do Next) sobrevivem entre
|
||||
# execuções. Um buildx criaria um BuildKit novo, e vazio, a cada job.
|
||||
- name: Build
|
||||
if: ${{ steps.plano.outputs.reuse != 'true' }}
|
||||
run: docker build -t espdocs:ci .
|
||||
|
||||
- name: Trivy na imagem
|
||||
if: ${{ steps.plano.outputs.reuse != 'true' }}
|
||||
run: |
|
||||
docker run --rm --network host -v trivy-cache:/root/.cache/ -e DOCKER_HOST=tcp://127.0.0.1:2375 aquasec/trivy:0.70.0 \
|
||||
image --severity HIGH,CRITICAL --exit-code 1 espdocs:ci
|
||||
|
||||
# Rotas por idioma, redirects e regras do livro (scripts/smoke-imagem.sh).
|
||||
# Um curl só na raiz não basta: ela redireciona, e uma página interna
|
||||
# quebrada ainda passaria.
|
||||
- name: A imagem sobe e responde
|
||||
if: ${{ steps.plano.outputs.reuse != 'true' }}
|
||||
run: |
|
||||
docker run -d --name espdocs-ci --network host -e PORT=3999 espdocs:ci
|
||||
for i in $(seq 1 30); do
|
||||
curl -fsS http://127.0.0.1:3999/ >/dev/null && ok=1 && break
|
||||
sleep 2
|
||||
done
|
||||
docker logs espdocs-ci | tail -5
|
||||
status=0
|
||||
scripts/smoke-imagem.sh http://127.0.0.1:3999 || status=1
|
||||
docker logs espdocs-ci | tail -15
|
||||
# O Next registra falhas de render no log mesmo quando responde.
|
||||
if docker logs espdocs-ci 2>&1 | grep -q '⨯'; then echo "O servidor registrou erro de render"; status=1; fi
|
||||
docker rm -f espdocs-ci >/dev/null
|
||||
test "${ok:-0}" = 1
|
||||
exit "$status"
|
||||
|
||||
# Passou em tudo: publica a mesma imagem que foi testada, sem reconstruir.
|
||||
- name: Publica inputs-<hash>
|
||||
if: ${{ steps.plano.outputs.reuse != 'true' }}
|
||||
run: |
|
||||
tag="${{ steps.plano.outputs.image }}:inputs-${{ steps.plano.outputs.inputs }}"
|
||||
docker tag espdocs:ci "$tag"
|
||||
docker push "$tag"
|
||||
@@ -18,10 +18,10 @@ env:
|
||||
|
||||
jobs:
|
||||
# A imagem só depende dos arquivos que entram no build, não da documentação nem
|
||||
# da configuração de ferramentas. Quando já existe no registro uma imagem para
|
||||
# o mesmo conteúdo (um merge só de docs, uma mudança de workflow, uma tag num
|
||||
# commit que acabou de ser publicado), não há o que construir: as tags novas
|
||||
# apontam para o manifesto existente.
|
||||
# da configuração de ferramentas. O push da branch já a construiu, testou e
|
||||
# publicou como inputs-<hash>; quando essa tag existe (o caso normal de um
|
||||
# merge, uma tag num commit validado, um merge só de docs), não há o que
|
||||
# construir: as tags novas apontam para o manifesto existente.
|
||||
plano:
|
||||
name: Plano (reaproveitar a imagem?)
|
||||
runs-on: ubuntu-latest
|
||||
@@ -32,23 +32,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: plano
|
||||
env:
|
||||
REPO: ${{ gitea.repository }}
|
||||
run: |
|
||||
inputs=$(git ls-tree -r HEAD \
|
||||
| awk -F'\t' '$2 !~ /^(\.gitea|\.github|\.claude|\.superset|docs)\// && $2 !~ /^(README.*|CLAUDE\.md|DESIGN\.md|LICENSE|\.gitignore|CHANGELOG\.md|scripts\/release-notes\.sh)$/' \
|
||||
| sha256sum | cut -c1-16)
|
||||
ns="${REPO,,}"
|
||||
token=$(curl -fsS "https://$REGISTRY/v2/token?service=container_registry&scope=repository:$ns:pull" | jq -r .token)
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' -I \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H 'Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.manifest.v1+json' \
|
||||
"https://$REGISTRY/v2/$ns/manifests/inputs-$inputs")
|
||||
echo "inputs-$inputs -> HTTP $code"
|
||||
reuse=false; [ "$code" = 200 ] && reuse=true
|
||||
echo "inputs=$inputs" >> "$GITHUB_OUTPUT"
|
||||
echo "reuse=$reuse" >> "$GITHUB_OUTPUT"
|
||||
echo "image=$REGISTRY/$ns" >> "$GITHUB_OUTPUT"
|
||||
run: scripts/plano-imagem.sh "$REGISTRY" "${{ gitea.repository }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Nada é publicado sem a suíte completa passar antes. Pulada quando a imagem é
|
||||
# reaproveitada: o mesmo conteúdo já passou por ela.
|
||||
@@ -68,6 +52,11 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# Se o ci chamado acima acabou de publicar a imagem (push direto na main),
|
||||
# o plano lá de cima está desatualizado: confere de novo antes de construir.
|
||||
- id: replano
|
||||
run: scripts/plano-imagem.sh "$REGISTRY" "${{ gitea.repository }}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- uses: docker/setup-buildx-action@v4
|
||||
|
||||
- name: Autentica no registro
|
||||
@@ -89,7 +78,7 @@ jobs:
|
||||
type=sha,format=long
|
||||
|
||||
- name: Build e push
|
||||
if: ${{ needs.plano.outputs.reuse != 'true' }}
|
||||
if: ${{ steps.replano.outputs.reuse != 'true' }}
|
||||
uses: docker/build-push-action@v7
|
||||
with:
|
||||
context: .
|
||||
@@ -104,7 +93,7 @@ jobs:
|
||||
|
||||
# Mesmo manifesto, nomes novos: nenhuma camada é lida nem escrita.
|
||||
- name: Aplica as tags à imagem existente
|
||||
if: ${{ needs.plano.outputs.reuse == 'true' }}
|
||||
if: ${{ steps.replano.outputs.reuse == 'true' }}
|
||||
run: |
|
||||
tags=$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta.outputs.json }}')
|
||||
docker buildx imagetools create $tags "${{ needs.plano.outputs.image }}:inputs-${{ needs.plano.outputs.inputs }}"
|
||||
|
||||
+45
-1
@@ -6,6 +6,49 @@ Tudo o que muda de relevante no ESPDocs está aqui. O formato segue o
|
||||
|
||||
## [Não lançado]
|
||||
|
||||
### Adicionado
|
||||
|
||||
- Infraestrutura de internacionalização com `next-intl` (Fase 1):
|
||||
- Roteamento com prefixo de idioma sob `app/[locale]/`, com 6 locales declarados (`pt`, `en`, `es`, `fr`, `de`, `zh-CN`).
|
||||
- `middleware.js` com negociação de idioma na raiz por cookie `NEXT_LOCALE` e cabeçalho `Accept-Language` (com pesos `q`), redirecionamento 308 de URLs antigas sem prefixo para `/pt/`, e retorno 404 para `/livro` fora do português.
|
||||
- Seletor de idiomas acessível no cabeçalho com atalho para os 6 idiomas, persistência via cookie `NEXT_LOCALE` e mapeamento de rota correspondente.
|
||||
- Regras de tipografia de sistema CJK para `zh-CN` e hifenização/quebra de palavras para `de` e `fr`.
|
||||
- Extração de strings e dados canônicos (Fase 2):
|
||||
- Catálogo de mensagens canônico `messages/pt.json` cobrindo 15 namespaces de páginas e componentes sem alteração de conteúdo.
|
||||
- Conjunto de dados canônicos em `data/pt/` (`series.json`, `frameworks.json`, `conexoes/*.json`) e módulos em `lib/data/pt/` (`glossario.js`, `diagnostico.js`, `componentes.js`, `topicos.js`) com carregadores por locale em `lib/data/index.js`.
|
||||
- Script automatizado de validação `check:i18n` integrado ao `npm run check`, verificando paridade de chaves, ausência de valores vazios e garantia estrita de ausência de referências ao livro fora do português.
|
||||
|
||||
### Alterado
|
||||
|
||||
- O teste de subida da imagem na CI virou `scripts/smoke-imagem.sh`: confere as
|
||||
rotas de cada idioma, a negociação de `Accept-Language`, os redirects 308 das
|
||||
URLs antigas, o 404 do livro fora do português e a metadata no `<head>`, e
|
||||
falha se o servidor registrar erro de render. O `curl` só na raiz deixou passar
|
||||
uma home quebrada.
|
||||
- A metadata (título, `canonical`, Open Graph) sempre sai no `<head>` do HTML
|
||||
inicial, para qualquer cliente, como já era antes do i18n.
|
||||
- A raiz `/` redireciona direto para `/<idioma>`, em um salto só.
|
||||
|
||||
## [1.1.0] - 2026-11-01
|
||||
|
||||
### Adicionado
|
||||
|
||||
- Busca no site, aberta pelo botão do cabeçalho ou por Ctrl/⌘+K. O índice
|
||||
(séries, frameworks, glossário, erros de diagnóstico, componentes e conexões)
|
||||
é gerado no build, em `/api/busca`.
|
||||
|
||||
### Alterado
|
||||
|
||||
- Os links do repositório do projeto (rodapé, "Sobre", dados estruturados)
|
||||
apontam para o Gitea, e o ícone do GitHub virou o do Gitea. Os links dos
|
||||
frameworks da Espressif continuam no GitHub, porque os repositórios são deles.
|
||||
- O site passou a rodar na Oracle, a partir da imagem Docker do registro do
|
||||
Gitea, em `espdocs.cienciaembarcada.com.br` e `espdocs.lucasrguerra.dev.br`.
|
||||
- CI: a imagem é construída, escaneada e testada uma vez, em arm64, no push da
|
||||
branch, e o release só aplica as tags; o gatilho `pull_request` (que repetia o
|
||||
push) e o segundo `next build` do job de lint saíram, e os caches do npm e da
|
||||
compilação do Next ficam entre as execuções.
|
||||
|
||||
## [1.0.0] - 2026-10-30
|
||||
|
||||
A primeira versão com tag. O trabalho anterior nunca foi tagueado, então esta
|
||||
@@ -60,5 +103,6 @@ entrada resume tudo desde o primeiro commit, em 2025-10-21, até a imagem Docker
|
||||
otimização de imagens (GHSA-2464-fhr4-w9xw), e `postcss` fixado acima da cópia
|
||||
embutida no `next`.
|
||||
|
||||
[Não lançado]: https://git.lucasrguerra.dev.br/lucasrguerra/ESPDocs/compare/v1.0.0...HEAD
|
||||
[Não lançado]: https://git.lucasrguerra.dev.br/lucasrguerra/ESPDocs/compare/v1.1.0...HEAD
|
||||
[1.1.0]: https://git.lucasrguerra.dev.br/lucasrguerra/ESPDocs/compare/v1.0.0...v1.1.0
|
||||
[1.0.0]: https://git.lucasrguerra.dev.br/lucasrguerra/ESPDocs/releases/tag/v1.0.0
|
||||
+4
-2
@@ -6,14 +6,16 @@ WORKDIR /app
|
||||
# O Puppeteer só é usado em scripts locais (slides, capturas): não baixa o Chrome.
|
||||
ENV PUPPETEER_SKIP_DOWNLOAD=true
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci
|
||||
# Cache do npm no daemon: dependências já baixadas não vão à rede de novo.
|
||||
RUN --mount=type=cache,target=/root/.npm npm ci
|
||||
|
||||
FROM node:22-alpine AS build
|
||||
WORKDIR /app
|
||||
ENV NEXT_TELEMETRY_DISABLED=1 NEXT_OUTPUT=standalone
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
RUN npm run build
|
||||
# Cache de compilação do Next: só as páginas que mudaram são recompiladas.
|
||||
RUN --mount=type=cache,target=/app/.next/cache npm run build
|
||||
|
||||
FROM node:22-alpine
|
||||
WORKDIR /app
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,162 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import { JetBrains_Mono, Manrope, Space_Grotesk } from "next/font/google";
|
||||
import { NextIntlClientProvider } from "next-intl";
|
||||
import { getMessages } from "next-intl/server";
|
||||
import { routing } from "@/i18n/routing";
|
||||
import "../globals.css";
|
||||
import Providers from "@/components/Providers";
|
||||
import { SITE, jsonLd } from "@/lib/seo";
|
||||
|
||||
const spaceGrotesk = Space_Grotesk({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-space-grotesk",
|
||||
display: "swap",
|
||||
weight: ["500", "600", "700"],
|
||||
});
|
||||
|
||||
const manrope = Manrope({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-manrope",
|
||||
display: "swap",
|
||||
weight: ["400", "500", "600", "700"],
|
||||
});
|
||||
|
||||
const jetbrainsMono = JetBrains_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-jetbrains",
|
||||
display: "swap",
|
||||
weight: ["400", "500", "600"],
|
||||
});
|
||||
|
||||
const LANG_MAP = {
|
||||
pt: "pt-BR",
|
||||
en: "en",
|
||||
es: "es-419",
|
||||
fr: "fr",
|
||||
de: "de",
|
||||
"zh-CN": "zh-CN",
|
||||
};
|
||||
|
||||
export function generateStaticParams() {
|
||||
return routing.locales.map((locale) => ({ locale }));
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }) {
|
||||
const { locale } = await params;
|
||||
const ogLocaleMap = {
|
||||
pt: "pt_BR",
|
||||
en: "en_US",
|
||||
es: "es_419",
|
||||
fr: "fr_FR",
|
||||
de: "de_DE",
|
||||
"zh-CN": "zh_CN",
|
||||
};
|
||||
|
||||
return {
|
||||
metadataBase: new URL(SITE.url),
|
||||
title: {
|
||||
default: "ESPDocs · Documentação do ESP32 em português",
|
||||
template: "%s · ESPDocs",
|
||||
},
|
||||
description:
|
||||
"Especificações, pinagem, comparação e seleção das 12 séries de microcontroladores ESP32, em português brasileiro. Datasheets, periféricos, segurança em hardware e diagramas de conexão.",
|
||||
applicationName: "ESPDocs",
|
||||
authors: [{ name: "Lucas Rayan Guerra", url: "https://lucasrguerra.dev.br" }],
|
||||
creator: "Lucas Rayan Guerra",
|
||||
publisher: "Ciência Embarcada",
|
||||
category: "technology",
|
||||
keywords: [
|
||||
"ESP32", "ESP32 português", "documentação ESP32", "pinout ESP32",
|
||||
"ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4", "ESP32-H2",
|
||||
"comparar ESP32", "qual ESP32 escolher", "datasheet ESP32",
|
||||
"microcontrolador", "Espressif", "ESP-IDF", "IoT", "sistemas embarcados",
|
||||
],
|
||||
alternates: { canonical: `/${locale}` },
|
||||
openGraph: {
|
||||
type: "website",
|
||||
locale: ogLocaleMap[locale] || "pt_BR",
|
||||
url: `${SITE.url}/${locale}`,
|
||||
siteName: SITE.nome,
|
||||
title: "ESPDocs · Documentação do ESP32 em português",
|
||||
description:
|
||||
"Especificações, pinagem, comparação e seleção das 12 séries de microcontroladores ESP32, em português brasileiro.",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: "ESPDocs · Documentação do ESP32 em português",
|
||||
description:
|
||||
"Especificações, pinagem, comparação e seleção das 12 séries de ESP32, em português.",
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
googleBot: {
|
||||
index: true,
|
||||
follow: true,
|
||||
"max-image-preview": "large",
|
||||
"max-snippet": -1,
|
||||
"max-video-preview": -1,
|
||||
},
|
||||
},
|
||||
icons: {
|
||||
icon: [
|
||||
{ url: "/favicon.ico", sizes: "48x48", type: "image/x-icon" },
|
||||
{ url: "/favicon-48x48.png", sizes: "48x48", type: "image/png" },
|
||||
{ url: "/favicon-32x32.png", sizes: "32x32", type: "image/png" },
|
||||
{ url: "/favicon-16x16.png", sizes: "16x16", type: "image/png" },
|
||||
{ url: "/icon-192.png", sizes: "192x192", type: "image/png" },
|
||||
{ url: "/icon-512.png", sizes: "512x512", type: "image/png" },
|
||||
{ url: "/icon.svg", type: "image/svg+xml" },
|
||||
],
|
||||
apple: [
|
||||
{ url: "/apple-touch-icon.png", sizes: "180x180", type: "image/png" },
|
||||
],
|
||||
shortcut: "/favicon.ico",
|
||||
},
|
||||
manifest: "/site.webmanifest",
|
||||
formatDetection: { telephone: false, address: false, email: false },
|
||||
};
|
||||
}
|
||||
|
||||
export const viewport = {
|
||||
themeColor: [
|
||||
{ media: "(prefers-color-scheme: light)", color: "#f5f6f8" },
|
||||
{ media: "(prefers-color-scheme: dark)", color: "#07090d" },
|
||||
],
|
||||
};
|
||||
|
||||
export default async function RootLayout({ children, params }) {
|
||||
const { locale } = await params;
|
||||
if (!routing.locales.includes(locale)) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const lang = LANG_MAP[locale] || locale;
|
||||
const messages = await getMessages();
|
||||
|
||||
return (
|
||||
<html lang={lang} className={`${spaceGrotesk.variable} ${manrope.variable} ${jetbrainsMono.variable}`} suppressHydrationWarning>
|
||||
<head>
|
||||
{/* Dados estruturados do site e da organização. É o que permite ao
|
||||
Google montar o box de busca interna e entender a autoria. */}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd.siteESociedade()) }}
|
||||
/>
|
||||
</head>
|
||||
<body className="font-sans antialiased bg-canvas text-ink overflow-x-clip" suppressHydrationWarning>
|
||||
<a
|
||||
href="#conteudo"
|
||||
className="sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[200] focus:rounded-full focus:bg-ink focus:px-5 focus:py-3 focus:text-sm focus:font-semibold focus:text-canvas"
|
||||
>
|
||||
Pular para o conteúdo
|
||||
</a>
|
||||
<NextIntlClientProvider locale={locale} messages={messages}>
|
||||
<Providers>
|
||||
{children}
|
||||
</Providers>
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { notFound } from "next/navigation";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import BookCover from "@/components/BookCover";
|
||||
@@ -16,11 +17,20 @@ import {
|
||||
Wifi,
|
||||
} from "lucide-react";
|
||||
|
||||
export const metadata = paginaMeta({
|
||||
export function generateStaticParams() {
|
||||
return [{ locale: "pt" }];
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }) {
|
||||
const { locale } = await params;
|
||||
if (locale !== "pt") {
|
||||
return {};
|
||||
}
|
||||
return paginaMeta({
|
||||
titulo: "Microcontroladores ESP32, o livro",
|
||||
descricao:
|
||||
"Conheça o livro Microcontroladores ESP32: conectividade, eficiência e desempenho. 12 partes e 78 capítulos em português sobre arquitetura, energia, rádio, periféricos e firmware.",
|
||||
caminho: "/livro",
|
||||
caminho: "/pt/livro",
|
||||
keywords: [
|
||||
"livro ESP32",
|
||||
"Microcontroladores ESP32",
|
||||
@@ -28,7 +38,8 @@ export const metadata = paginaMeta({
|
||||
"Lucas Rayan Guerra",
|
||||
"Ciência Embarcada",
|
||||
],
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const CHAPTERS = [
|
||||
{
|
||||
@@ -128,7 +139,11 @@ const FACTS = [
|
||||
["ISBN", SITE.livroIsbn],
|
||||
];
|
||||
|
||||
export default function LivroPage() {
|
||||
export default async function LivroPage({ params }) {
|
||||
const { locale } = await params;
|
||||
if (locale !== "pt") {
|
||||
notFound();
|
||||
}
|
||||
return (
|
||||
<div className="site-canvas min-h-screen">
|
||||
<script
|
||||
File renamed without changes.
@@ -5,6 +5,7 @@ import Link from "next/link";
|
||||
import seriesData from "@/public/series.json";
|
||||
import frameworksData from "@/public/frameworks.json";
|
||||
import { SITE } from "@/lib/seo";
|
||||
import { getLocalizedHref } from "@/i18n/links";
|
||||
import {
|
||||
AlertTriangle,
|
||||
ArrowRight,
|
||||
@@ -87,7 +88,11 @@ const ERRORS = [
|
||||
},
|
||||
];
|
||||
|
||||
export default function Home() {
|
||||
export default async function Home({ params }) {
|
||||
const { locale } = await params;
|
||||
const isPt = locale === "pt";
|
||||
const getLinkHref = (href) => getLocalizedHref(`/${locale}${href}`, locale);
|
||||
|
||||
const seriesCount = Object.keys(seriesData).length;
|
||||
const frameworkCount = Object.keys(frameworksData).length;
|
||||
const featured = FEATURED.map((key) => [key, seriesData[key]]).filter(([, serie]) => Boolean(serie));
|
||||
@@ -113,11 +118,11 @@ export default function Home() {
|
||||
</p>
|
||||
|
||||
<div className="mt-8 flex flex-col items-center justify-center gap-3 sm:flex-row">
|
||||
<Link href="/seletor" className="btn btn-primary w-full sm:w-auto">
|
||||
<Link href={getLinkHref("/seletor")} className="btn btn-primary w-full sm:w-auto">
|
||||
<SlidersHorizontal className="h-4 w-4" aria-hidden="true" />
|
||||
Escolher meu chip
|
||||
</Link>
|
||||
<Link href="/series" className="btn btn-ghost w-full sm:w-auto">
|
||||
<Link href={getLinkHref("/series")} className="btn btn-ghost w-full sm:w-auto">
|
||||
Explorar as {seriesCount} séries
|
||||
<ArrowRight className="h-4 w-4" aria-hidden="true" />
|
||||
</Link>
|
||||
@@ -127,10 +132,14 @@ export default function Home() {
|
||||
<span><strong className="font-semibold text-ink">{seriesCount}</strong> séries</span>
|
||||
<span aria-hidden="true" className="text-line-strong">·</span>
|
||||
<span><strong className="font-semibold text-ink">{frameworkCount}</strong> frameworks</span>
|
||||
{isPt && (
|
||||
<>
|
||||
<span aria-hidden="true" className="text-line-strong">·</span>
|
||||
<span><strong className="font-semibold text-ink">78</strong> capítulos no livro</span>
|
||||
<span aria-hidden="true" className="text-line-strong">·</span>
|
||||
<span>100% em português</span>
|
||||
</>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -176,6 +185,7 @@ export default function Home() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{isPt && (
|
||||
<section className="shell section pt-8 sm:pt-12" aria-labelledby="livro-titulo">
|
||||
<div className="relative isolate overflow-hidden rounded-[2rem] bg-[#0b0d10] ring-1 ring-white/10 dark:bg-[#05070a] dark:ring-white/15 sm:rounded-[2.5rem]">
|
||||
<div
|
||||
@@ -226,7 +236,7 @@ export default function Home() {
|
||||
Comprar impresso
|
||||
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
||||
</a>
|
||||
<Link href="/livro" className="inline-flex min-h-11 items-center justify-center gap-1.5 rounded-full px-3 text-sm font-medium text-[#a6afbd] transition-colors duration-300 hover:text-[#f4f6f8]">
|
||||
<Link href="/pt/livro" className="inline-flex min-h-11 items-center justify-center gap-1.5 rounded-full px-3 text-sm font-medium text-[#a6afbd] transition-colors duration-300 hover:text-[#f4f6f8]">
|
||||
Ficha completa
|
||||
<ArrowRight className="h-4 w-4" aria-hidden="true" />
|
||||
</Link>
|
||||
@@ -242,6 +252,7 @@ export default function Home() {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
|
||||
<section className="shell section" aria-labelledby="ferramentas-titulo">
|
||||
<div className="mx-auto max-w-2xl text-center">
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,19 +1,12 @@
|
||||
import { paginaMeta, jsonLd } from "@/lib/seo";
|
||||
import { paginaMeta, jsonLd, SITE } from "@/lib/seo";
|
||||
import Header from "@/components/Header";
|
||||
import Footer from "@/components/Footer";
|
||||
import PageHero from "@/components/PageHero";
|
||||
import Image from "next/image";
|
||||
import GiteaMark from "@/components/GiteaMark";
|
||||
import { ArrowUpRight, Code, Globe, GitCompare, Info, Languages } from "lucide-react";
|
||||
|
||||
const GITHUB = "https://github.com/lucasrguerra/ESPDocs";
|
||||
|
||||
function GithubMark({ className }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M12 .5a12 12 0 00-3.8 23.4c.6.1.8-.3.8-.6v-2.1c-3.3.7-4-1.6-4-1.6-.5-1.2-1.2-1.5-1.2-1.5-1-.7.1-.7.1-.7 1.1.1 1.7 1.1 1.7 1.1 1 .1 1.6-.7 1.9-1 .1-.8.4-1.3.8-1.6-2.6-.3-5.3-1.3-5.3-5.8 0-1.3.5-2.3 1.2-3.1-.1-.3-.5-1.6.1-3.3 0 0 1-.3 3.3 1.2a11.4 11.4 0 016 0c2.3-1.5 3.3-1.2 3.3-1.2.6 1.7.2 3 .1 3.3.8.8 1.2 1.9 1.2 3.1 0 4.5-2.7 5.5-5.3 5.8.5.4.9 1.1.9 2.2v3.2c0 .3.2.7.8.6A12 12 0 0012 .5z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
const REPOSITORIO = SITE.repositorio;
|
||||
|
||||
|
||||
export const metadata = paginaMeta({
|
||||
@@ -28,7 +21,7 @@ export default function Sobre() {
|
||||
{ icon: Languages, title: "Em português", desc: "Dados técnicos organizados e apresentados em português do Brasil." },
|
||||
{ icon: GitCompare, title: "Comparações visuais", desc: "Tabelas e diagramas para escolher a série certa sem abrir dez datasheets." },
|
||||
{ icon: Globe, title: "Acesso centralizado", desc: "Links diretos para a documentação oficial, repositórios e exemplos." },
|
||||
{ icon: Code, title: "Código aberto", desc: "Contribuições são bem-vindas no GitHub." },
|
||||
{ icon: Code, title: "Código aberto", desc: "Contribuições são bem-vindas no Gitea." },
|
||||
];
|
||||
|
||||
return (
|
||||
@@ -60,8 +53,8 @@ export default function Sobre() {
|
||||
title="Sobre o ESPDocs"
|
||||
lede="Uma plataforma não oficial, em português, que organiza as informações técnicas do ESP32 e leva você à documentação oficial da Espressif. Feita para a comunidade de hardware livre."
|
||||
>
|
||||
<a href={GITHUB} target="_blank" rel="noopener noreferrer" className="btn btn-primary">
|
||||
<GithubMark className="h-4 w-4" />
|
||||
<a href={REPOSITORIO} target="_blank" rel="noopener noreferrer" className="btn btn-primary">
|
||||
<GiteaMark className="h-4 w-4" />
|
||||
Ver o repositório
|
||||
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
||||
</a>
|
||||
@@ -108,7 +101,7 @@ export default function Sobre() {
|
||||
</p>
|
||||
<ol className="mt-6 space-y-3">
|
||||
{[
|
||||
"Faça o fork do repositório no GitHub.",
|
||||
"Faça o fork do repositório no Gitea.",
|
||||
"Implemente as melhorias e confira as referências técnicas oficiais.",
|
||||
"Abra um Pull Request descrevendo os ajustes feitos.",
|
||||
].map((passo, i) => (
|
||||
@@ -0,0 +1,12 @@
|
||||
import { construirIndiceBusca } from "@/lib/searchIndex";
|
||||
|
||||
export const dynamic = "force-static";
|
||||
|
||||
/** Índice de busca carregado sob demanda pelo diálogo de pesquisa (Ctrl/⌘+K). */
|
||||
export function GET() {
|
||||
return Response.json(construirIndiceBusca(), {
|
||||
headers: {
|
||||
"Cache-Control": "no-cache, no-store, must-revalidate",
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -759,4 +759,28 @@
|
||||
.no-scrollbar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
Tipografia e layout internacionalizados (seção 9b da spec)
|
||||
------------------------------------------------------------------------ */
|
||||
html[lang="zh-CN"] {
|
||||
font-family: "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", "Noto Sans SC", sans-serif;
|
||||
letter-spacing: 0;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
html[lang="zh-CN"] code,
|
||||
html[lang="zh-CN"] pre,
|
||||
html[lang="zh-CN"] kbd {
|
||||
font-family: var(--font-mono);
|
||||
}
|
||||
|
||||
html[lang="de"],
|
||||
html[lang="fr"] {
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
p, li, dd {
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
}
|
||||
-134
@@ -1,134 +0,0 @@
|
||||
import { JetBrains_Mono, Manrope, Space_Grotesk } from "next/font/google";
|
||||
import "./globals.css";
|
||||
import Providers from "@/components/Providers";
|
||||
import { SITE, jsonLd } from "@/lib/seo";
|
||||
|
||||
const spaceGrotesk = Space_Grotesk({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-space-grotesk",
|
||||
display: "swap",
|
||||
weight: ["500", "600", "700"],
|
||||
});
|
||||
|
||||
const manrope = Manrope({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-manrope",
|
||||
display: "swap",
|
||||
weight: ["400", "500", "600", "700"],
|
||||
});
|
||||
|
||||
const jetbrainsMono = JetBrains_Mono({
|
||||
subsets: ["latin"],
|
||||
variable: "--font-jetbrains",
|
||||
display: "swap",
|
||||
weight: ["400", "500", "600"],
|
||||
});
|
||||
|
||||
export const metadata = {
|
||||
// metadataBase é o que transforma caminhos relativos em URLs absolutas nas
|
||||
// tags canonical e og:image. Sem ele, o Google recebe og:image quebrado.
|
||||
metadataBase: new URL(SITE.url),
|
||||
|
||||
title: {
|
||||
default: "ESPDocs · Documentação do ESP32 em português",
|
||||
// Cada página fornece só o próprio nome; o sufixo entra automaticamente.
|
||||
template: "%s · ESPDocs",
|
||||
},
|
||||
description:
|
||||
"Especificações, pinagem, comparação e seleção das 12 séries de microcontroladores ESP32, em português brasileiro. Datasheets, periféricos, segurança em hardware e diagramas de conexão.",
|
||||
|
||||
applicationName: "ESPDocs",
|
||||
authors: [{ name: "Lucas Rayan Guerra", url: "https://lucasrguerra.dev.br" }],
|
||||
creator: "Lucas Rayan Guerra",
|
||||
publisher: "Ciência Embarcada",
|
||||
category: "technology",
|
||||
|
||||
keywords: [
|
||||
"ESP32", "ESP32 português", "documentação ESP32", "pinout ESP32",
|
||||
"ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4", "ESP32-H2",
|
||||
"comparar ESP32", "qual ESP32 escolher", "datasheet ESP32",
|
||||
"microcontrolador", "Espressif", "ESP-IDF", "IoT", "sistemas embarcados",
|
||||
],
|
||||
|
||||
alternates: { canonical: "/" },
|
||||
|
||||
openGraph: {
|
||||
type: "website",
|
||||
locale: "pt_BR",
|
||||
url: SITE.url,
|
||||
siteName: "ESPDocs",
|
||||
title: "ESPDocs · Documentação do ESP32 em português",
|
||||
description:
|
||||
"Especificações, pinagem, comparação e seleção das 12 séries de microcontroladores ESP32, em português brasileiro.",
|
||||
},
|
||||
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: "ESPDocs · Documentação do ESP32 em português",
|
||||
description:
|
||||
"Especificações, pinagem, comparação e seleção das 12 séries de ESP32, em português.",
|
||||
},
|
||||
|
||||
robots: {
|
||||
index: true,
|
||||
follow: true,
|
||||
googleBot: {
|
||||
index: true,
|
||||
follow: true,
|
||||
"max-image-preview": "large",
|
||||
"max-snippet": -1,
|
||||
"max-video-preview": -1,
|
||||
},
|
||||
},
|
||||
|
||||
icons: {
|
||||
icon: [
|
||||
{ url: "/favicon.ico", sizes: "48x48", type: "image/x-icon" },
|
||||
{ url: "/favicon-48x48.png", sizes: "48x48", type: "image/png" },
|
||||
{ url: "/favicon-32x32.png", sizes: "32x32", type: "image/png" },
|
||||
{ url: "/favicon-16x16.png", sizes: "16x16", type: "image/png" },
|
||||
{ url: "/icon-192.png", sizes: "192x192", type: "image/png" },
|
||||
{ url: "/icon-512.png", sizes: "512x512", type: "image/png" },
|
||||
{ url: "/icon.svg", type: "image/svg+xml" },
|
||||
],
|
||||
apple: [
|
||||
{ url: "/apple-touch-icon.png", sizes: "180x180", type: "image/png" },
|
||||
],
|
||||
shortcut: "/favicon.ico",
|
||||
},
|
||||
manifest: "/site.webmanifest",
|
||||
formatDetection: { telephone: false, address: false, email: false },
|
||||
};
|
||||
|
||||
export const viewport = {
|
||||
themeColor: [
|
||||
{ media: "(prefers-color-scheme: light)", color: "#f5f6f8" },
|
||||
{ media: "(prefers-color-scheme: dark)", color: "#07090d" },
|
||||
],
|
||||
};
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="pt-BR" className={`${spaceGrotesk.variable} ${manrope.variable} ${jetbrainsMono.variable}`} suppressHydrationWarning>
|
||||
<head>
|
||||
{/* Dados estruturados do site e da organização. É o que permite ao
|
||||
Google montar o box de busca interna e entender a autoria. */}
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd.siteESociedade()) }}
|
||||
/>
|
||||
</head>
|
||||
<body className="font-sans antialiased bg-canvas text-ink overflow-x-clip" suppressHydrationWarning>
|
||||
<a
|
||||
href="#conteudo"
|
||||
className="sr-only focus:not-sr-only focus:fixed focus:left-4 focus:top-4 focus:z-[200] focus:rounded-full focus:bg-ink focus:px-5 focus:py-3 focus:text-sm focus:font-semibold focus:text-canvas"
|
||||
>
|
||||
Pular para o conteúdo
|
||||
</a>
|
||||
<Providers>
|
||||
{children}
|
||||
</Providers>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useMemo, useRef } from "react";
|
||||
import { useState, useEffect, useMemo, useRef, Suspense } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||
import { AlertTriangle, CheckCircle, List, Grid, Search, Sliders, X, Zap } from "lucide-react";
|
||||
|
||||
/*
|
||||
@@ -41,7 +42,25 @@ const type_colors = {
|
||||
nc: "#94a3b8", // muted gray
|
||||
};
|
||||
|
||||
export default function ConnectionsDiagram({ connections, serie }) {
|
||||
/**
|
||||
* Aceita ?pinos=28,30,31&motivo=... (gerado pela busca do site): mostra só
|
||||
* esses pinos, pelo número físico, com um aviso para voltar à lista completa.
|
||||
* O Suspense é exigido por useSearchParams em páginas estáticas.
|
||||
*/
|
||||
export default function ConnectionsDiagram(props) {
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<ConnectionsDiagramInner {...props} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
function ConnectionsDiagramInner({ connections, serie }) {
|
||||
const params = useSearchParams();
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const pinosFiltro = useMemo(() => new Set((params.get("pinos") ?? "").split(",").filter(Boolean)), [params]);
|
||||
const motivoFiltro = params.get("motivo") ?? "";
|
||||
const [activeFilter, setActiveFilter] = useState("All");
|
||||
const [selectedConnection, setSelectedConnection] = useState(null);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
@@ -60,7 +79,8 @@ export default function ConnectionsDiagram({ connections, serie }) {
|
||||
searchQuery === "" ||
|
||||
connection.nome.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
||||
connection.numero.toString().toLowerCase().includes(searchQuery.toLowerCase());
|
||||
return matchesFilter && matchesSearch;
|
||||
const matchesPinos = pinosFiltro.size === 0 || pinosFiltro.has(String(connection.numero));
|
||||
return matchesFilter && matchesSearch && matchesPinos;
|
||||
};
|
||||
|
||||
const getCategoryColor = (category) => {
|
||||
@@ -70,7 +90,9 @@ export default function ConnectionsDiagram({ connections, serie }) {
|
||||
|
||||
const nomeCategoria = (cat) => (cat === "Strapping" ? "Inicialização" : cat);
|
||||
|
||||
const visibleConnections = useMemo(() => connections.filter(isConnectionVisible), [connections, activeFilter, searchQuery]);
|
||||
const visibleConnections = useMemo(() => connections.filter(isConnectionVisible), [connections, activeFilter, searchQuery, pinosFiltro]);
|
||||
|
||||
const mostrarTodos = () => router.replace(`${pathname}#connections`, { scroll: false });
|
||||
|
||||
const abrir = (connection, evento) => {
|
||||
gatilhoRef.current = evento.currentTarget;
|
||||
@@ -137,6 +159,18 @@ export default function ConnectionsDiagram({ connections, serie }) {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{pinosFiltro.size > 0 && (
|
||||
<div role="status" className="callout flex flex-wrap items-center justify-between gap-3">
|
||||
<p className="text-sm text-ink">
|
||||
<strong className="font-semibold">Filtrado pela busca:</strong> {motivoFiltro || "pinos selecionados"} ({pinosFiltro.size}{" "}
|
||||
{pinosFiltro.size === 1 ? "pino" : "pinos"})
|
||||
</p>
|
||||
<button type="button" onClick={mostrarTodos} className="btn btn-ghost btn-sm">
|
||||
Mostrar todos os pinos
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-3 sm:flex-row">
|
||||
<div className="relative flex-1">
|
||||
<label htmlFor="busca-pino" className="sr-only">Buscar conexão por nome ou número</label>
|
||||
@@ -191,7 +225,7 @@ export default function ConnectionsDiagram({ connections, serie }) {
|
||||
<Search className="mx-auto h-8 w-8 text-muted" aria-hidden="true" />
|
||||
<p className="mt-3 font-semibold text-ink">Nenhuma conexão encontrada</p>
|
||||
<p className="mt-1 text-sm text-muted">Ajuste a busca ou volte para todas as funções.</p>
|
||||
<button type="button" onClick={() => { setActiveFilter("All"); setSearchQuery(""); }} className="btn btn-primary btn-sm mt-5">
|
||||
<button type="button" onClick={() => { setActiveFilter("All"); setSearchQuery(""); if (pinosFiltro.size) mostrarTodos(); }} className="btn btn-primary btn-sm mt-5">
|
||||
Limpar busca e filtros
|
||||
</button>
|
||||
</div>
|
||||
|
||||
+27
-8
@@ -1,7 +1,12 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import Logo from "@/components/Logo";
|
||||
import GiteaMark from "@/components/GiteaMark";
|
||||
import { ArrowUpRight } from "lucide-react";
|
||||
import { SITE } from "@/lib/seo";
|
||||
import { LOCALES, getLocalizedHref } from "@/i18n/links";
|
||||
|
||||
const COLUMNS = [
|
||||
{
|
||||
@@ -34,14 +39,26 @@ const COLUMNS = [
|
||||
];
|
||||
|
||||
export default function Footer() {
|
||||
const pathname = usePathname() || "";
|
||||
const year = new Date().getFullYear();
|
||||
|
||||
const currentLocale =
|
||||
LOCALES.find((l) => pathname === `/${l.code}` || pathname.startsWith(`/${l.code}/`))?.code || "pt";
|
||||
const isPt = currentLocale === "pt";
|
||||
|
||||
const getLinkHref = (href) => getLocalizedHref(`/${currentLocale}${href}`, currentLocale);
|
||||
|
||||
const columns = COLUMNS.map((column) => ({
|
||||
...column,
|
||||
links: column.links.filter((link) => link.href !== "/livro" || isPt),
|
||||
}));
|
||||
|
||||
return (
|
||||
<footer className="mt-20 border-t border-line md:mt-28" aria-label="Rodapé do ESPDocs">
|
||||
<div className="shell py-14 md:py-20">
|
||||
<div className="grid gap-12 lg:grid-cols-[1.1fr_2fr]">
|
||||
<div>
|
||||
<Link href="/" className="inline-flex min-h-11 items-center gap-2.5" aria-label="ESPDocs, página inicial">
|
||||
<Link href={getLinkHref("/")} className="inline-flex min-h-11 items-center gap-2.5" aria-label="ESPDocs, página inicial">
|
||||
<Logo className="h-7 w-7" />
|
||||
<span className="font-display text-2xl font-semibold tracking-[-0.045em] text-ink">ESPDocs</span>
|
||||
</Link>
|
||||
@@ -50,8 +67,10 @@ export default function Footer() {
|
||||
Dados públicos, curadoria editorial e links para as fontes oficiais.
|
||||
</p>
|
||||
|
||||
{isPt && (
|
||||
<>
|
||||
<Link
|
||||
href="/livro"
|
||||
href="/pt/livro"
|
||||
className="group mt-7 grid grid-cols-[3rem_1fr_auto] items-center gap-3.5 rounded-2xl border border-line bg-surface p-3.5 transition-colors duration-300 hover:border-line-strong"
|
||||
>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
@@ -81,10 +100,12 @@ export default function Footer() {
|
||||
<ArrowUpRight className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
</a>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-8 sm:grid-cols-4">
|
||||
{COLUMNS.map((column) => (
|
||||
{columns.map((column) => (
|
||||
<nav key={column.title} aria-label={column.title}>
|
||||
<h2 className="text-sm font-semibold text-ink">{column.title}</h2>
|
||||
<ul className="mt-2 space-y-0">
|
||||
@@ -101,7 +122,7 @@ export default function Footer() {
|
||||
<ArrowUpRight className="h-3 w-3" aria-hidden="true" />
|
||||
</a>
|
||||
) : (
|
||||
<Link href={link.href} className="inline-flex min-h-11 min-w-11 items-center text-sm text-muted transition-colors hover:text-accent">
|
||||
<Link href={getLinkHref(link.href)} className="inline-flex min-h-11 min-w-11 items-center text-sm text-muted transition-colors hover:text-accent">
|
||||
{link.label}
|
||||
</Link>
|
||||
)}
|
||||
@@ -123,12 +144,10 @@ export default function Footer() {
|
||||
href={SITE.repositorio}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label="GitHub do projeto (abre em nova aba)"
|
||||
aria-label="Gitea do projeto (abre em nova aba)"
|
||||
className="grid h-11 w-11 place-items-center rounded-full border border-line text-ink transition-colors hover:border-line-strong hover:bg-surface"
|
||||
>
|
||||
<svg className="h-4 w-4" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M12 .5a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2.1c-3.3.7-4-1.6-4-1.6-.5-1.2-1.2-1.5-1.2-1.5-1-.7.1-.7.1-.7 1.1.1 1.7 1.1 1.7 1.1 1 .1 1.6-.7 1.9-1 .1-.8.4-1.3.8-1.6-2.6-.3-5.3-1.3-5.3-5.8 0-1.3.5-2.3 1.2-3.1-.1-.3-.5-1.6.1-3.3 0 0 1-.3 3.3 1.2a11.4 11.4 0 0 1 6 0c2.3-1.5 3.3-1.2 3.3-1.2.6 1.7.2 3 .1 3.3.8.8 1.2 1.9 1.2 3.1 0 4.5-2.7 5.5-5.3 5.8.5.4.9 1.1.9 2.2v3.2c0 .3.2.7.8.6A12 12 0 0 0 12 .5z" />
|
||||
</svg>
|
||||
<GiteaMark className="h-4 w-4" />
|
||||
</a>
|
||||
<a
|
||||
href={SITE.autorLinkedin}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// Marca do Gitea (Simple Icons, CC0). Troca o octocat nos links do repositório.
|
||||
export default function GiteaMark({ className }) {
|
||||
return (
|
||||
<svg className={className} viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
|
||||
<path d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
+37
-15
@@ -4,6 +4,9 @@ import { useEffect, useRef, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import Link from "next/link";
|
||||
import Logo from "@/components/Logo";
|
||||
import SearchDialog from "@/components/SearchDialog";
|
||||
import LanguageSelector from "@/components/LanguageSelector";
|
||||
import { LOCALES, getLocalizedHref } from "@/i18n/links";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useTheme } from "next-themes";
|
||||
import {
|
||||
@@ -68,12 +71,16 @@ const MOBILE_LINKS = [
|
||||
{ href: "/sobre", label: "Sobre" },
|
||||
];
|
||||
|
||||
function isActivePath(pathname, href) {
|
||||
return href === "/" ? pathname === "/" : pathname === href || String(pathname).startsWith(`${href}/`);
|
||||
function isActivePath(pathname, href, currentLocale) {
|
||||
const localized = getLocalizedHref(`/${currentLocale}${href}`, currentLocale);
|
||||
if (href === "/" || localized === `/${currentLocale}/` || localized === `/${currentLocale}`) {
|
||||
return pathname === `/${currentLocale}` || pathname === `/${currentLocale}/`;
|
||||
}
|
||||
return pathname === localized || String(pathname).startsWith(`${localized}/`);
|
||||
}
|
||||
|
||||
export default function Header() {
|
||||
const pathname = usePathname();
|
||||
const pathname = usePathname() || "";
|
||||
const [mounted, setMounted] = useState(false);
|
||||
const [openMenu, setOpenMenu] = useState(null);
|
||||
const [drawerOpen, setDrawerOpen] = useState(false);
|
||||
@@ -81,6 +88,12 @@ export default function Header() {
|
||||
const closeRef = useRef(null);
|
||||
const menuButtonRef = useRef(null);
|
||||
|
||||
const currentLocale =
|
||||
LOCALES.find((l) => pathname === `/${l.code}` || pathname.startsWith(`/${l.code}/`))?.code || "pt";
|
||||
const isPt = currentLocale === "pt";
|
||||
|
||||
const getLinkHref = (href) => getLocalizedHref(`/${currentLocale}${href}`, currentLocale);
|
||||
|
||||
useEffect(() => setMounted(true), []);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -117,18 +130,20 @@ export default function Header() {
|
||||
};
|
||||
}, [drawerOpen]);
|
||||
|
||||
const visibleMobileLinks = isPt ? MOBILE_LINKS : MOBILE_LINKS.filter((l) => l.href !== "/livro");
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 pt-3 sm:pt-4">
|
||||
<div className="shell">
|
||||
<div className="nav-pill flex h-16 items-center justify-between gap-3 rounded-full px-3 sm:px-4">
|
||||
<Link href="/" className="flex min-h-11 shrink-0 items-center gap-2.5 rounded-full pl-1 pr-2" aria-label="ESPDocs, página inicial">
|
||||
<Link href={getLinkHref("/")} className="flex min-h-11 shrink-0 items-center gap-2.5 rounded-full pl-1 pr-2" aria-label="ESPDocs, página inicial">
|
||||
<Logo className="h-[30px] w-[30px]" />
|
||||
<span className="font-display text-[1.3rem] font-semibold leading-none tracking-[-0.045em] text-ink">ESPDocs</span>
|
||||
</Link>
|
||||
|
||||
<nav ref={navRef} className="hidden items-center gap-0.5 lg:flex" aria-label="Navegação principal">
|
||||
{MENUS.map((menu) => {
|
||||
const active = menu.items.some((item) => isActivePath(pathname, item.href));
|
||||
const active = menu.items.some((item) => isActivePath(pathname, item.href, currentLocale));
|
||||
const expanded = openMenu === menu.id;
|
||||
return (
|
||||
<div key={menu.id} className="relative">
|
||||
@@ -149,12 +164,13 @@ export default function Header() {
|
||||
>
|
||||
{menu.items.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const localizedHref = getLinkHref(item.href);
|
||||
return (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
href={localizedHref}
|
||||
className="group flex items-start gap-3 rounded-2xl px-3 py-3 transition-colors hover:bg-surface-2"
|
||||
aria-current={isActivePath(pathname, item.href) ? "page" : undefined}
|
||||
aria-current={isActivePath(pathname, item.href, currentLocale) ? "page" : undefined}
|
||||
>
|
||||
<span className="mt-0.5 grid h-9 w-9 shrink-0 place-items-center rounded-xl bg-accent-soft text-accent transition-colors group-hover:bg-surface">
|
||||
<Icon className="h-4 w-4" aria-hidden="true" />
|
||||
@@ -172,19 +188,23 @@ export default function Header() {
|
||||
);
|
||||
})}
|
||||
|
||||
<Link href="/livro" className={`nav-link ${isActivePath(pathname, "/livro") ? "is-active" : ""}`} aria-current={isActivePath(pathname, "/livro") ? "page" : undefined}>
|
||||
{isPt && (
|
||||
<Link href={getLinkHref("/livro")} className={`nav-link ${isActivePath(pathname, "/livro", currentLocale) ? "is-active" : ""}`} aria-current={isActivePath(pathname, "/livro", currentLocale) ? "page" : undefined}>
|
||||
Livro
|
||||
</Link>
|
||||
<Link href="/sobre" className={`nav-link ${isActivePath(pathname, "/sobre") ? "is-active" : ""}`} aria-current={isActivePath(pathname, "/sobre") ? "page" : undefined}>
|
||||
)}
|
||||
<Link href={getLinkHref("/sobre")} className={`nav-link ${isActivePath(pathname, "/sobre", currentLocale) ? "is-active" : ""}`} aria-current={isActivePath(pathname, "/sobre", currentLocale) ? "page" : undefined}>
|
||||
Sobre
|
||||
</Link>
|
||||
</nav>
|
||||
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Link href="/seletor" className="btn btn-primary btn-sm hidden lg:inline-flex">
|
||||
<Link href={getLinkHref("/seletor")} className="btn btn-primary btn-sm hidden lg:inline-flex">
|
||||
<SlidersHorizontal className="h-4 w-4" aria-hidden="true" />
|
||||
Selecionar chip
|
||||
</Link>
|
||||
<SearchDialog />
|
||||
<LanguageSelector />
|
||||
<ThemeToggle />
|
||||
<button
|
||||
ref={menuButtonRef}
|
||||
@@ -236,9 +256,10 @@ export default function Header() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{isPt && (
|
||||
<div className="px-4 pb-2">
|
||||
<Link
|
||||
href="/livro"
|
||||
href="/pt/livro"
|
||||
onClick={() => setDrawerOpen(false)}
|
||||
className="group grid grid-cols-[3.25rem_1fr_auto] items-center gap-3 rounded-2xl bg-[#0b0d10] p-3 text-[#f4f6f8] ring-1 ring-white/10"
|
||||
>
|
||||
@@ -259,15 +280,16 @@ export default function Header() {
|
||||
<ArrowRight className="h-4 w-4 shrink-0 text-[#75cdc1] transition-transform duration-300 group-hover:translate-x-1" aria-hidden="true" />
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<nav className="flex-1 overflow-y-auto px-3 py-2" aria-label="Navegação móvel">
|
||||
{MOBILE_LINKS.map((link) => (
|
||||
{visibleMobileLinks.map((link) => (
|
||||
<Link
|
||||
key={link.href}
|
||||
href={link.href}
|
||||
href={getLinkHref(link.href)}
|
||||
onClick={() => setDrawerOpen(false)}
|
||||
className="group flex min-h-11 items-center justify-between gap-3 rounded-xl px-3 text-sm font-medium text-ink-soft transition-colors hover:bg-surface-2 hover:text-ink"
|
||||
aria-current={isActivePath(pathname, link.href) ? "page" : undefined}
|
||||
aria-current={isActivePath(pathname, link.href, currentLocale) ? "page" : undefined}
|
||||
>
|
||||
{link.label}
|
||||
<ArrowRight className="h-4 w-4 text-faint transition-transform duration-300 group-hover:translate-x-0.5 group-hover:text-accent" aria-hidden="true" />
|
||||
@@ -276,7 +298,7 @@ export default function Header() {
|
||||
</nav>
|
||||
|
||||
<div className="p-4 pt-2">
|
||||
<Link href="/seletor" onClick={() => setDrawerOpen(false)} className="btn btn-primary w-full">
|
||||
<Link href={getLinkHref("/seletor")} onClick={() => setDrawerOpen(false)} className="btn btn-primary w-full">
|
||||
<SlidersHorizontal className="h-4 w-4" aria-hidden="true" />
|
||||
Selecionar meu chip
|
||||
</Link>
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { ChevronDown, Globe } from "lucide-react";
|
||||
import { LOCALES, getLocalizedHref } from "@/i18n/links";
|
||||
|
||||
export { LOCALES, getLocalizedHref };
|
||||
|
||||
export default function LanguageSelector() {
|
||||
const pathname = usePathname() || "";
|
||||
const [open, setOpen] = useState(false);
|
||||
const [hash, setHash] = useState("");
|
||||
const containerRef = useRef(null);
|
||||
|
||||
// Detecta locale da URL atual
|
||||
const currentLocaleCode =
|
||||
LOCALES.find((l) => pathname === `/${l.code}` || pathname.startsWith(`/${l.code}/`))?.code || "pt";
|
||||
|
||||
const currentLocale = LOCALES.find((l) => l.code === currentLocaleCode) || LOCALES[0];
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window !== "undefined") {
|
||||
setHash(window.location.hash || "");
|
||||
}
|
||||
}, [pathname]);
|
||||
|
||||
useEffect(() => {
|
||||
function onPointerDown(e) {
|
||||
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
function onKeyDown(e) {
|
||||
if (e.key === "Escape") {
|
||||
setOpen(false);
|
||||
}
|
||||
}
|
||||
document.addEventListener("mousedown", onPointerDown);
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
return () => {
|
||||
document.removeEventListener("mousedown", onPointerDown);
|
||||
document.removeEventListener("keydown", onKeyDown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const handleSelect = (code) => {
|
||||
if (typeof document !== "undefined") {
|
||||
document.cookie = `NEXT_LOCALE=${code}; path=/; max-age=31536000; SameSite=Lax`;
|
||||
}
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="relative">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(!open)}
|
||||
className="flex h-11 min-w-[44px] items-center gap-1.5 rounded-full border border-line bg-surface px-3 text-sm font-semibold text-ink transition-colors hover:bg-surface-2 focus-visible:outline-2 focus-visible:outline-accent"
|
||||
aria-haspopup="listbox"
|
||||
aria-expanded={open}
|
||||
aria-label={`Idioma atual: ${currentLocale.label}. Clique para trocar de idioma.`}
|
||||
title={`Idioma: ${currentLocale.label}`}
|
||||
>
|
||||
<Globe className="h-4 w-4 text-muted" aria-hidden="true" />
|
||||
<span className="font-semibold">{currentLocale.short}</span>
|
||||
<ChevronDown
|
||||
className={`h-3 w-3 text-muted transition-transform duration-200 ${open ? "rotate-180" : ""}`}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
|
||||
{open && (
|
||||
<div
|
||||
role="listbox"
|
||||
aria-label="Idiomas disponíveis"
|
||||
className="absolute right-0 top-full mt-2 w-48 rounded-2xl border border-line bg-surface p-1.5 shadow-[0_24px_60px_-20px_rgba(15,23,42,0.35)] dark:shadow-[0_24px_60px_-20px_rgba(0,0,0,0.8)] z-50"
|
||||
>
|
||||
{LOCALES.map((loc) => {
|
||||
const isActive = loc.code === currentLocaleCode;
|
||||
const href = `${getLocalizedHref(pathname, loc.code)}${hash}`;
|
||||
|
||||
return (
|
||||
<a
|
||||
key={loc.code}
|
||||
href={href}
|
||||
lang={loc.lang}
|
||||
hrefLang={loc.lang}
|
||||
role="option"
|
||||
aria-selected={isActive}
|
||||
aria-current={isActive ? "true" : undefined}
|
||||
onClick={() => handleSelect(loc.code)}
|
||||
className={`flex min-h-[44px] items-center justify-between rounded-xl px-3 py-2 text-sm transition-colors ${
|
||||
isActive
|
||||
? "bg-accent-soft text-accent font-semibold"
|
||||
: "text-ink-soft hover:bg-surface-2 hover:text-ink"
|
||||
}`}
|
||||
>
|
||||
<span>{loc.label}</span>
|
||||
<span className={`text-xs ${isActive ? "text-accent" : "text-muted"}`}>
|
||||
{loc.short}
|
||||
</span>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,383 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef, useMemo, useCallback } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
Search,
|
||||
X,
|
||||
CornerDownLeft,
|
||||
ArrowUp,
|
||||
ArrowDown,
|
||||
FileText,
|
||||
Cpu,
|
||||
Terminal,
|
||||
BookOpen,
|
||||
AlertTriangle,
|
||||
Box,
|
||||
Sparkles,
|
||||
Plug,
|
||||
} from "lucide-react";
|
||||
import { preparar, buscar, EXEMPLOS_DE_BUSCA } from "@/lib/searchEngine";
|
||||
import { normalizar } from "@/lib/searchTopics";
|
||||
|
||||
const TIPOS = {
|
||||
resposta: { label: "Resposta", Icon: Sparkles, cor: "bg-accent text-accent-contrast" },
|
||||
pino: { label: "Pinos", Icon: Plug, cor: "bg-accent text-accent-contrast" },
|
||||
pagina: { label: "Página", Icon: FileText, cor: "bg-surface-2 text-ink-soft" },
|
||||
serie: { label: "Série", Icon: Cpu, cor: "bg-accent-soft text-accent" },
|
||||
framework: { label: "Framework", Icon: Terminal, cor: "bg-teal-soft text-teal" },
|
||||
glossario: { label: "Glossário", Icon: BookOpen, cor: "bg-copper-soft text-copper" },
|
||||
erro: { label: "Erro", Icon: AlertTriangle, cor: "bg-gold-soft text-gold" },
|
||||
componente: { label: "Componente", Icon: Box, cor: "bg-surface-2 text-ink-soft" },
|
||||
};
|
||||
|
||||
const INTELIGENTES = new Set(["resposta", "pino"]);
|
||||
|
||||
function Destaque({ texto, termos }) {
|
||||
if (!termos.length) return texto;
|
||||
// Posições do texto normalizado só valem para o original se o comprimento não mudou.
|
||||
const norm = normalizar(texto);
|
||||
if (norm.length !== texto.length) return texto;
|
||||
const marcas = new Array(texto.length).fill(false);
|
||||
for (const t of termos) {
|
||||
let i = norm.indexOf(t);
|
||||
while (i !== -1) {
|
||||
for (let k = i; k < i + t.length; k++) marcas[k] = true;
|
||||
i = norm.indexOf(t, i + t.length);
|
||||
}
|
||||
}
|
||||
const partes = [];
|
||||
let atual = "";
|
||||
let marcado = false;
|
||||
for (let i = 0; i < texto.length; i++) {
|
||||
if (marcas[i] !== marcado && atual) {
|
||||
partes.push({ t: atual, m: marcado });
|
||||
atual = "";
|
||||
}
|
||||
marcado = marcas[i];
|
||||
atual += texto[i];
|
||||
}
|
||||
if (atual) partes.push({ t: atual, m: marcado });
|
||||
return partes.map((p, i) =>
|
||||
p.m ? (
|
||||
<mark key={i} className="rounded-sm bg-accent-soft px-0.5 text-accent">
|
||||
{p.t}
|
||||
</mark>
|
||||
) : (
|
||||
<span key={i}>{p.t}</span>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function Pilula({ children, onClick, forte = false }) {
|
||||
const base = "rounded-full px-2.5 py-1 text-xs font-semibold";
|
||||
if (!onClick) return <span className={`${base} ${forte ? "bg-accent text-accent-contrast" : "bg-accent-soft text-accent"}`}>{children}</span>;
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClick}
|
||||
className={`${base} cursor-pointer border border-line bg-surface text-ink-soft transition-colors hover:border-accent hover:text-accent`}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export default function SearchDialog() {
|
||||
const [aberto, setAberto] = useState(false);
|
||||
const [montado, setMontado] = useState(false);
|
||||
const [consulta, setConsulta] = useState("");
|
||||
const [indice, setIndice] = useState(null);
|
||||
const [erro, setErro] = useState(false);
|
||||
const [ativo, setAtivo] = useState(0);
|
||||
const inputRef = useRef(null);
|
||||
const listaRef = useRef(null);
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => setMontado(true), []);
|
||||
|
||||
const fechar = useCallback(() => {
|
||||
setAberto(false);
|
||||
setConsulta("");
|
||||
setAtivo(0);
|
||||
}, []);
|
||||
|
||||
// Atalhos globais: Ctrl/⌘+K abre; "/" abre fora de campos de texto.
|
||||
useEffect(() => {
|
||||
function onKey(e) {
|
||||
const emCampo = /^(INPUT|TEXTAREA|SELECT)$/.test(e.target?.tagName) || e.target?.isContentEditable;
|
||||
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "k") {
|
||||
e.preventDefault();
|
||||
setAberto((v) => !v);
|
||||
} else if (e.key === "/" && !emCampo && !e.ctrlKey && !e.metaKey && !e.altKey) {
|
||||
e.preventDefault();
|
||||
setAberto(true);
|
||||
} else if (e.key === "Escape") {
|
||||
fechar();
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", onKey);
|
||||
return () => document.removeEventListener("keydown", onKey);
|
||||
}, [fechar]);
|
||||
|
||||
const carregarIndice = useCallback(() => {
|
||||
setErro(false);
|
||||
let cancelado = false;
|
||||
fetch("/api/busca?v=2", { cache: "no-cache" })
|
||||
.then((r) => {
|
||||
if (!r.ok) throw new Error(`HTTP ${r.status}`);
|
||||
return r.json();
|
||||
})
|
||||
.then((dados) => {
|
||||
if (!cancelado) {
|
||||
setIndice(preparar(dados));
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Erro ao carregar índice de busca:", err);
|
||||
if (!cancelado) setErro(true);
|
||||
});
|
||||
return () => {
|
||||
cancelado = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Carrega o índice (textos + especificações + pinos) na primeira abertura.
|
||||
useEffect(() => {
|
||||
if (!aberto || indice) return;
|
||||
return carregarIndice();
|
||||
}, [aberto, indice, carregarIndice]);
|
||||
|
||||
useEffect(() => {
|
||||
if (aberto) {
|
||||
document.body.style.overflow = "hidden";
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
return () => {
|
||||
document.body.style.overflow = "";
|
||||
};
|
||||
}, [aberto]);
|
||||
|
||||
const termos = useMemo(() => normalizar(consulta).split(/\s+/).filter((t) => t.length > 1), [consulta]);
|
||||
|
||||
const busca = useMemo(() => {
|
||||
if (!indice) return { resultados: [], interpretacao: { chips: [], topicos: [] }, sugestoes: [], totalRespostas: 0 };
|
||||
if (!consulta.trim()) {
|
||||
return { resultados: indice.itens.filter((i) => i.tipo === "pagina"), interpretacao: { chips: [], topicos: [] }, sugestoes: [], totalRespostas: 0 };
|
||||
}
|
||||
return buscar(indice, consulta);
|
||||
}, [indice, consulta]);
|
||||
|
||||
const { resultados, interpretacao, sugestoes } = busca;
|
||||
const vazia = !consulta.trim();
|
||||
|
||||
useEffect(() => setAtivo(0), [consulta]);
|
||||
|
||||
useEffect(() => {
|
||||
listaRef.current?.querySelector(`[data-idx="${ativo}"]`)?.scrollIntoView({ block: "nearest" });
|
||||
}, [ativo]);
|
||||
|
||||
function ir(item) {
|
||||
if (!item) return;
|
||||
fechar();
|
||||
router.push(item.href);
|
||||
// Se já estamos na página de destino, só a âncora muda: avisa quem escuta (abas da série).
|
||||
if (item.href.includes("#")) setTimeout(() => window.dispatchEvent(new HashChangeEvent("hashchange")), 80);
|
||||
}
|
||||
|
||||
function anexar(termo) {
|
||||
setConsulta((c) => `${c.trim()} ${termo}`.trim());
|
||||
inputRef.current?.focus();
|
||||
}
|
||||
|
||||
function onInputKey(e) {
|
||||
if (e.key === "ArrowDown") {
|
||||
e.preventDefault();
|
||||
setAtivo((i) => Math.min(i + 1, resultados.length - 1));
|
||||
} else if (e.key === "ArrowUp") {
|
||||
e.preventDefault();
|
||||
setAtivo((i) => Math.max(i - 1, 0));
|
||||
} else if (e.key === "Enter") {
|
||||
e.preventDefault();
|
||||
ir(resultados[ativo]);
|
||||
}
|
||||
}
|
||||
|
||||
const entendeu = interpretacao.chips.length > 0 || interpretacao.topicos.length > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
id="botao-busca"
|
||||
onClick={() => setAberto(true)}
|
||||
className="flex h-11 min-w-11 shrink-0 cursor-pointer items-center justify-center gap-2 rounded-full border border-line px-3 text-ink transition-colors hover:bg-surface-2 xl:px-4"
|
||||
aria-label="Buscar no ESPDocs (Ctrl+K)"
|
||||
>
|
||||
<Search className="h-4 w-4" aria-hidden="true" />
|
||||
<span className="hidden text-sm font-medium xl:inline">Buscar</span>
|
||||
<kbd className="hidden rounded-md border border-line bg-surface-2 px-1.5 py-0.5 font-mono text-xs font-semibold text-muted xl:inline">Ctrl K</kbd>
|
||||
</button>
|
||||
|
||||
{montado &&
|
||||
aberto &&
|
||||
createPortal(
|
||||
<div className="fixed inset-0 z-[120] flex items-start justify-center px-4 pt-[8vh]" role="dialog" aria-modal="true" aria-label="Buscar no ESPDocs">
|
||||
<div className="dialog-scrim absolute inset-0 bg-black/45 backdrop-blur-sm" onClick={fechar} />
|
||||
<div className="dialog-panel relative flex max-h-[80vh] w-full max-w-2xl flex-col overflow-hidden rounded-3xl border border-line bg-canvas shadow-2xl">
|
||||
<div className="flex items-center gap-3 border-b border-line px-5">
|
||||
<Search className="h-5 w-5 shrink-0 text-accent" aria-hidden="true" />
|
||||
<input
|
||||
ref={inputRef}
|
||||
id="campo-busca"
|
||||
type="text"
|
||||
value={consulta}
|
||||
onChange={(e) => setConsulta(e.target.value)}
|
||||
onKeyDown={onInputKey}
|
||||
placeholder="Pergunte ao ESPDocs: “flash s3”, “pinos usb c6”, “gpio0 esp32”…"
|
||||
className="flex-1 bg-transparent py-5 text-base text-ink outline-none placeholder:text-muted"
|
||||
autoComplete="off"
|
||||
spellCheck={false}
|
||||
aria-label="Termo de busca"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
onClick={fechar}
|
||||
className="grid h-9 w-9 cursor-pointer place-items-center rounded-full text-muted transition-colors hover:bg-surface-2 hover:text-ink"
|
||||
aria-label="Fechar busca"
|
||||
>
|
||||
<X className="h-4 w-4" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{entendeu && (
|
||||
<div className="flex flex-wrap items-center gap-2 border-b border-line bg-surface px-5 py-2.5">
|
||||
<span className="text-xs font-semibold text-muted">Entendi:</span>
|
||||
{interpretacao.chips.map((c) => (
|
||||
<Pilula key={c.chave} forte>{c.nome}</Pilula>
|
||||
))}
|
||||
{interpretacao.topicos.map((t) => (
|
||||
<Pilula key={t.id}>{t.nome}</Pilula>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{sugestoes.length > 0 && (
|
||||
<div className="flex flex-wrap items-center gap-2 border-b border-line px-5 py-2.5">
|
||||
<span className="text-xs font-semibold text-muted">{interpretacao.chips.length ? "Perguntar sobre:" : "Para qual chip?"}</span>
|
||||
{sugestoes.map((s) => (
|
||||
<Pilula key={s.rotulo} onClick={() => anexar(s.anexar)}>
|
||||
{s.rotulo}
|
||||
</Pilula>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div ref={listaRef} className="flex-1 overflow-y-auto p-2" role="listbox">
|
||||
{erro && (
|
||||
<div className="p-6 text-center">
|
||||
<p className="text-sm font-semibold text-danger">Não foi possível carregar o índice de busca.</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={carregarIndice}
|
||||
className="btn btn-primary btn-sm mt-3"
|
||||
>
|
||||
Tentar novamente
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{!erro && !indice && <p className="p-6 text-center text-sm text-muted">Carregando…</p>}
|
||||
|
||||
{indice && vazia && (
|
||||
<div className="px-3 pb-3 pt-1">
|
||||
<p className="text-xs font-semibold text-muted">Experimente perguntar</p>
|
||||
<div className="mt-2 flex flex-wrap gap-2">
|
||||
{EXEMPLOS_DE_BUSCA.map((ex) => (
|
||||
<Pilula key={ex} onClick={() => setConsulta(ex)}>
|
||||
{ex}
|
||||
</Pilula>
|
||||
))}
|
||||
</div>
|
||||
<p className="mt-4 text-xs font-semibold text-muted">Ir para</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{indice && !vazia && resultados.length === 0 && (
|
||||
<div className="p-8 text-center">
|
||||
<p className="font-display text-lg font-semibold text-ink">Nenhum resultado para “{consulta}”</p>
|
||||
<p className="mt-1 text-sm text-muted">Tente “brownout”, “flash s3”, “pinos usb c6” ou “LVGL”.</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{resultados.map((item, idx) => {
|
||||
const { Icon, label, cor } = TIPOS[item.tipo] ?? TIPOS.pagina;
|
||||
const sel = idx === ativo;
|
||||
const inteligente = INTELIGENTES.has(item.tipo);
|
||||
return (
|
||||
<button
|
||||
key={`${item.id}-${idx}`}
|
||||
type="button"
|
||||
role="option"
|
||||
aria-selected={sel}
|
||||
data-idx={idx}
|
||||
onMouseMove={() => setAtivo(idx)}
|
||||
onClick={() => ir(item)}
|
||||
className={`flex w-full cursor-pointer items-start gap-3 rounded-2xl p-3 text-left transition-colors ${
|
||||
sel ? "bg-surface-2" : ""
|
||||
} ${inteligente ? "my-1 border border-line" : ""}`}
|
||||
>
|
||||
<div className={`grid h-9 w-9 shrink-0 place-items-center rounded-xl ${cor}`}>
|
||||
<Icon className="h-4 w-4" aria-hidden="true" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="truncate text-sm font-semibold text-ink">
|
||||
{inteligente ? item.titulo : <Destaque texto={item.titulo} termos={termos} />}
|
||||
</span>
|
||||
<span className={`shrink-0 rounded-full px-2 py-0.5 text-xs font-semibold ${inteligente ? "bg-accent-soft text-accent" : cor}`}>{label}</span>
|
||||
</div>
|
||||
<p className="mt-0.5 line-clamp-2 text-xs leading-relaxed text-muted">
|
||||
{inteligente ? item.descricao : <Destaque texto={item.descricao} termos={termos} />}
|
||||
</p>
|
||||
|
||||
{item.linhas && (
|
||||
<dl className="mt-2 grid gap-x-4 gap-y-1 text-xs sm:grid-cols-[auto_1fr]">
|
||||
{item.linhas.map((l) => (
|
||||
<div key={l.k} className="contents">
|
||||
<dt className="font-semibold text-ink-soft">{l.k}</dt>
|
||||
<dd className="text-ink">{l.v}</dd>
|
||||
</div>
|
||||
))}
|
||||
</dl>
|
||||
)}
|
||||
|
||||
{item.chips && (
|
||||
<div className="mt-2 flex flex-wrap gap-1.5">
|
||||
{item.chips.map((c) => (
|
||||
<span key={c} className="rounded-md border border-line bg-surface px-1.5 py-0.5 font-mono text-xs text-ink-soft">
|
||||
{c}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{sel && <CornerDownLeft className="mt-2 h-4 w-4 shrink-0 text-accent" aria-hidden="true" />}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="hidden items-center gap-4 border-t border-line bg-surface px-4 py-2.5 text-xs text-muted md:flex">
|
||||
<span className="flex items-center gap-1"><ArrowUp className="h-3 w-3" /><ArrowDown className="h-3 w-3" /> navegar</span>
|
||||
<span className="flex items-center gap-1"><CornerDownLeft className="h-3 w-3" /> abrir</span>
|
||||
<span><kbd className="font-mono font-semibold">Esc</kbd> fechar</span>
|
||||
<span className="ml-auto">{vazia ? "Dica: pressione / em qualquer página" : `${resultados.length} resultado(s)`}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>,
|
||||
document.body
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "ANT",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão de antena de RF (Wi-Fi e Bluetooth)"],
|
||||
"categorias": ["Antena", "RF"],
|
||||
"avisos": ["Pino de RF dedicado. Evite traçar pistas longas ou sem casamento de impedância de 50 ohms."]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "VDDA3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação analógica de 3.3V"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão recomendada: 3.3V (3.0V a 3.6V)",
|
||||
"Fornece energia para os circuitos analógicos e de RF do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "VDDA3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação analógica de 3.3V"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão recomendada: 3.3V (3.0V a 3.6V)",
|
||||
"Fornece energia para os circuitos analógicos e de RF do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "GPIO0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 0"]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "GPIO1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"ADC1_CH1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 1"]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "GPIO2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO2",
|
||||
"ADC1_CH2",
|
||||
"FSPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Mapeado para a função SPI MISO (FSPIQ) por padrão na inicialização do flash"]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "CHIP_EN",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Habilitar o chip (Power-up / Reset)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Ativo Alto. Puxe para nível alto para inicializar o chip.",
|
||||
"Não deixe este pino flutuando. Use um circuito RC de atraso externo para inicialização estável."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "GPIO3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"ADC1_CH3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 3"]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "GPIO4",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"MTMS",
|
||||
"FSPIQ",
|
||||
"ADC1_CH4"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG",
|
||||
"SPI",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": [
|
||||
"Pino multifuncional: JTAG MTMS, SPI2 MISO e ADC1 Canal 4.",
|
||||
"Pode ser usado para depuração JTAG em conjunto com outros pinos JTAG."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "GPIO5",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"MTDI",
|
||||
"FSPIWP"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTDI e SPI2 Write Protect (FSPIWP)."]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "VDD3P3_RTC",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio de RTC e IOs de baixo consumo"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V"]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "GPIO6",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO6",
|
||||
"MTCK",
|
||||
"FSPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTCK e SPI2 Clock (FSPICLK)."]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "GPIO7",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO7",
|
||||
"MTDO",
|
||||
"FSPID"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTDO e SPI2 MOSI (FSPID)."]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "GPIO8",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": ["GPIO8"],
|
||||
"categorias": ["GPIO", "Strapping"],
|
||||
"avisos": [
|
||||
"Pino de Strapping para controle de boot.",
|
||||
"Em conjunto com o GPIO9, seleciona o modo de inicialização do SoC (deve estar em 1 durante o reset para Joint Download Boot se GPIO9=0)."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "GPIO9",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": ["GPIO9"],
|
||||
"categorias": ["GPIO", "Strapping"],
|
||||
"avisos": [
|
||||
"Pino de Strapping principal. Nível alto (1) no reset activa SPI Boot (padrão via pull-up fraco).",
|
||||
"Nível baixo (0) no reset coloca o chip no modo de download UART/SPI."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "GPIO10",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO10",
|
||||
"FSPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: SPI2 Chip Select 0 (FSPICS0)."]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "VDD3P3_CPU",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação digital da CPU e IOs correspondentes (3.3V)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V"]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "GPIO18",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": ["GPIO18"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "GPIO19",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO19",
|
||||
"U0RXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": ["Pino de recepção UART0 (Serial RX por padrão para gravação e monitoramento)."]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "GPIO20",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO20",
|
||||
"U0TXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": ["Pino de transmissão UART0 (Serial TX por padrão para gravação e monitoramento)."]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "VDDA",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação de entrada analógica de 3.3V"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão externa do cristal oscilador (Saída)"],
|
||||
"categorias": ["Clock"]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão externa do cristal oscilador (Entrada)"],
|
||||
"categorias": ["Clock"]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "VDDA",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação de entrada analógica de 3.3V"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "GND",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Pino de aterramento central (Exposed Pad)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Deve ser devidamente soldado ao plano de terra (GND) da PCB para desempenho estável e dissipação térmica."]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,533 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "LNA_IN",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada e saída dos sinais de RF (Wi-Fi e Bluetooth) para a antena"],
|
||||
"categorias": ["Antena"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "XTAL_32K_P",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"XTAL_32K_P",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "XTAL_32K_N",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"XTAL_32K_N",
|
||||
"ADC1_CH1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "GPIO2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO2",
|
||||
"ADC1_CH2",
|
||||
"FSPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Na verdade, esse pino não determina o modo de boot, mas é recomendado conectar ele com um pull-up para evitar glitches (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "CHIP_EN",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Habilitar o chip"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Colocar este pino em nível alto habilitará o funcionamento do chip",
|
||||
"Colocar este pino em nível baixo desabilitará o funcionamento do chip",
|
||||
"Não deixe este pino flutuando, utilize um resistor de pull-up externo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "GPIO3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"ADC1_CH3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "MTMS",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"ADC1_CH4",
|
||||
"FSPIHD",
|
||||
"MTMS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "MTDI",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"ADC2_CH0",
|
||||
"FSPIWP",
|
||||
"MTDI"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "VDD3P3_RTC",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio de baixo consumo e parte do domínio digital"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "MTCK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO6",
|
||||
"FSPICLK",
|
||||
"MTCK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "MTDO",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO7",
|
||||
"FSPID",
|
||||
"MTDO"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "GPIO8",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": ["GPIO8"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "GPIO9",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": ["GPIO9"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "GPIO10",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO10",
|
||||
"FSPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "VDD3P3_CPU",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio digital"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "VDD_SPI",
|
||||
"tipo": "power",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"Entrada/saída da alimentação da flash interna/externa",
|
||||
"GPIO11"
|
||||
],
|
||||
"categorias": [
|
||||
"Power",
|
||||
"GPIO"
|
||||
],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip",
|
||||
"Só pode ser utilizado como GPIO se a memória flash estiver sendo alimentada por uma fonte externa"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "SPIHD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO12",
|
||||
"SPIHD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "SPIWP",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO13",
|
||||
"SPIWP"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "SPICS0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO14",
|
||||
"SPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "SPICLK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO15",
|
||||
"SPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "SPID",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO16",
|
||||
"SPID"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "SPIQ",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO17",
|
||||
"SPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "GPIO18",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO18",
|
||||
"USB_D-"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB"
|
||||
],
|
||||
"avisos": ["Por padrão, este pino é utilizado para USB Serial/JTAG"]
|
||||
},
|
||||
{
|
||||
"numero": "26",
|
||||
"nome": "GPIO19",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO19",
|
||||
"USB_D+"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB"
|
||||
],
|
||||
"avisos": ["Por padrão, este pino é utilizado para USB Serial/JTAG"]
|
||||
},
|
||||
{
|
||||
"numero": "27",
|
||||
"nome": "U0RXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO20",
|
||||
"U0RXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "28",
|
||||
"nome": "U0TXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO21",
|
||||
"U0TXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "29",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída negativa de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.3.2 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "30",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída positiva de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.3.2 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "31",
|
||||
"nome": "VDDA",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "32",
|
||||
"nome": "VDDA",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "33",
|
||||
"nome": "GND",
|
||||
"tipo": "ground",
|
||||
"funcoes": ["Referência elétrica do circuito (terra)"],
|
||||
"categorias": ["GND"]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,776 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "VDDA6",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "GND",
|
||||
"tipo": "ground",
|
||||
"funcoes": ["Referência elétrica do circuito (terra)"],
|
||||
"categorias": ["GND"]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "VDDA7",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída negativa de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.3.3 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída positiva de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.3.3 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "VDDA8",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "CHIP_PU",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": ["Habilitar o chip"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Colocar este pino em nível alto habilitará o funcionamento do chip",
|
||||
"Colocar este pino em nível baixo desabilitará o funcionamento do chip",
|
||||
"Não deixe este pino flutuando, utilize um resistor de pull-up externo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "VDDPST1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio digital de baixo consumo"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "XTAL_32K_P",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"LP_GDIO0",
|
||||
"XTAL_32K_P",
|
||||
"LP_UART_DTRN"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"Clock",
|
||||
"UART"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "XTAL_32K_N",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"LP_GDIO1",
|
||||
"XTAL_32K_N",
|
||||
"LP_UART_DSRN",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"Clock",
|
||||
"UART",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "MTMS",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO2",
|
||||
"LP_GDIO2",
|
||||
"LP_UART_RTSN",
|
||||
"LP_I2C_SDA",
|
||||
"ADC1_CH1",
|
||||
"FSPIQ",
|
||||
"MTMS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"I2C",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"A função de I2C_SDA está disponível no modo de baixo consumo (LP)",
|
||||
"Pino utilizado para debugging",
|
||||
"Utilizado para controlar a frequência do cristal oscilador do chip (consulte o item 3.5 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "MTDI",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"LP_GDIO3",
|
||||
"LP_UART_CTSN",
|
||||
"LP_I2C_SCL",
|
||||
"ADC1_CH2",
|
||||
"MTDI"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"I2C",
|
||||
"ADC",
|
||||
"JTAG",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"A função de I2C_SDA está disponível no modo de baixo consumo (LP)",
|
||||
"Pino utilizado para debugging",
|
||||
"Utilizado para controlar a temporização do SDIO Slave (consulte o item 3.2 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "MTCK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"LP_GDIO4",
|
||||
"LP_UART_RXD",
|
||||
"ADC1_CH3",
|
||||
"FSPIHD",
|
||||
"MTCK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "MTDO",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"LP_GDIO5",
|
||||
"LP_UART_TXD",
|
||||
"ADC1_CH4",
|
||||
"FSPIWP",
|
||||
"MTDO"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "GPIO6",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO6",
|
||||
"LP_GDIO6",
|
||||
"ADC1_CH5",
|
||||
"FSPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "GPIO7",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO7",
|
||||
"FSPID",
|
||||
"SDIO_DATA1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar a fonte de sinais JTAG (consulte o item 3.4 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "GPIO8",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO8",
|
||||
"SDIO_DATA0",
|
||||
"PAD_COMP0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "GPIO9",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO9",
|
||||
"SDIO_CLK",
|
||||
"PAD_COMP1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "GPIO10",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO10",
|
||||
"FSPICS0",
|
||||
"SDIO_CMD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "U0TXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO11",
|
||||
"U0TXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "U0RXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO12",
|
||||
"U0RXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "GPIO13",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO13",
|
||||
"USB_D-",
|
||||
"SDIO_DATA3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB",
|
||||
"SD"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Por padrão, este pino é utilizado para USB Serial/JTAG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "GPIO14",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO14",
|
||||
"USB_D+",
|
||||
"SDIO_DATA4"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB",
|
||||
"SD"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno para USB ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno para USB ativado",
|
||||
"Por padrão, este pino é utilizado para USB Serial/JTAG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "VDDPST2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio digital de alto desempenho e parte do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "SPICS1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO15",
|
||||
"SPICS1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "26",
|
||||
"nome": "SPICS0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO16",
|
||||
"SPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "27",
|
||||
"nome": "SPIQ",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO17",
|
||||
"SPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "28",
|
||||
"nome": "SPIWP",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO18",
|
||||
"SPIWP"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "29",
|
||||
"nome": "VDD_SPI",
|
||||
"tipo": "power",
|
||||
"funcoes": [
|
||||
"Saída de alimentação para a flash externa",
|
||||
"GPIO19"
|
||||
],
|
||||
"categorias": [
|
||||
"Power",
|
||||
"GPIO"
|
||||
],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip",
|
||||
"Só pode ser utilizado como GPIO se a memória flash externa estiver sendo alimentada por uma fonte externa"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "30",
|
||||
"nome": "SPIHD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO20",
|
||||
"SPIHD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "31",
|
||||
"nome": "SPICLK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO21",
|
||||
"SPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "32",
|
||||
"nome": "SPID",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO22",
|
||||
"SPID"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "33",
|
||||
"nome": "GPIO23",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST3"],
|
||||
"funcoes": ["GPIO23"],
|
||||
"categorias": ["GPIO"],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "34",
|
||||
"nome": "GPIO24",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST3"],
|
||||
"funcoes": ["GPIO24"],
|
||||
"categorias": ["GPIO"],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "35",
|
||||
"nome": "GPIO25",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST3"],
|
||||
"funcoes": ["GPIO25"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar a temporização do SDIO Slave (consulte o item 3.4 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "36",
|
||||
"nome": "GPIO26",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST3"],
|
||||
"funcoes": ["GPIO26"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "37",
|
||||
"nome": "GPIO27",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST3"],
|
||||
"funcoes": ["GPIO27"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)",
|
||||
"Utilizado para controlar a exibição de mensagens ROM na UART0 (consulte o item 3.3 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "38",
|
||||
"nome": "GPIO28",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST3"],
|
||||
"funcoes": ["GPIO28"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "39",
|
||||
"nome": "VDDPST3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio digital de alto desempenho"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "40",
|
||||
"nome": "VDDA1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "41",
|
||||
"nome": "VDDA2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "42",
|
||||
"nome": "ANT_2G",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão da antena RF para a banda de 2 GHz"],
|
||||
"categorias": ["Antena"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "43",
|
||||
"nome": "GND",
|
||||
"tipo": "ground",
|
||||
"funcoes": ["Referência elétrica do circuito (terra)"],
|
||||
"categorias": ["GND"]
|
||||
},
|
||||
{
|
||||
"numero": "44",
|
||||
"nome": "VDDA3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "44",
|
||||
"nome": "VDDA4",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "45",
|
||||
"nome": "VDDA5",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "47",
|
||||
"nome": "GND",
|
||||
"tipo": "ground",
|
||||
"funcoes": ["Referência elétrica do circuito (terra)"],
|
||||
"categorias": ["GND"]
|
||||
},
|
||||
{
|
||||
"numero": "48",
|
||||
"nome": "ANT_5G",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão da antena RF para a banda de 5 GHz"],
|
||||
"categorias": ["Antena"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,715 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "ANT",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão da antena RF"],
|
||||
"categorias": ["Antena"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "VDDA3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "VDDA3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "CHIP_PU",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Habilitar o chip"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Colocar este pino em nível alto habilitará o funcionamento do chip",
|
||||
"Colocar este pino em nível baixo desabilitará o funcionamento do chip",
|
||||
"Não deixe este pino flutuando, utilize um resistor de pull-up externo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "VDDPST1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio digital de baixo consumo e parte do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "XTAL_32K_P",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"LP_GDIO0",
|
||||
"XTAL_32K_P",
|
||||
"LP_UART_DTRN",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"Clock",
|
||||
"UART"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "XTAL_32K_N",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"LP_GDIO1",
|
||||
"XTAL_32K_N",
|
||||
"LP_UART_DSRN",
|
||||
"ADC1_CH1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"Clock",
|
||||
"UART",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "GPIO2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO2",
|
||||
"LP_GDIO2",
|
||||
"LP_UART_RTSN",
|
||||
"ADC1_CH2",
|
||||
"FSPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"ADC",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "GPIO3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"LP_GDIO3",
|
||||
"LP_UART_CTSN",
|
||||
"ADC1_CH3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "MTMS",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"LP_GDIO4",
|
||||
"LP_UART_RXD",
|
||||
"ADC1_CH3",
|
||||
"FSPIHD",
|
||||
"MTMS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging",
|
||||
"Utilizado para controlar a temporização do SDIO Slave (consulte o item 3.2 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "MTDI",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"LP_GDIO5",
|
||||
"LP_UART_TXD",
|
||||
"ADC1_CH5",
|
||||
"FSPIWP",
|
||||
"MTDI"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"UART",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging",
|
||||
"Utilizado para controlar a temporização do SDIO Slave (consulte o item 3.2 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "MTCK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO6",
|
||||
"LP_GDIO6",
|
||||
"LP_I2C_SDA",
|
||||
"ADC1_CH6",
|
||||
"FSPICLK",
|
||||
"MTCK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"I2C",
|
||||
"ADC",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"A função de I2C_SDA está disponível no modo de baixo consumo (LP)",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "MTDO",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO7",
|
||||
"LP_GDIO7",
|
||||
"LP_I2C_SCL",
|
||||
"FSPID",
|
||||
"MTDO"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"I2C",
|
||||
"SPI",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"A função de I2C_SDA está disponível no modo de baixo consumo (LP)",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "GPIO8",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO8"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)",
|
||||
"Utilizado para controlar a exibição de mensagens ROM na UART0 (consulte o item 3.3 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "GPIO9",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO9"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "GPIO10",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO10"],
|
||||
"categorias": ["GPIO"],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "GPIO11",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO11"],
|
||||
"categorias": ["GPIO"],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "GPIO12",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO12",
|
||||
"USB_D-"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Por padrão, este pino é utilizado para USB Serial/JTAG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "GPIO13",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO13",
|
||||
"USB_D+"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Por padrão, este pino é utilizado para USB Serial/JTAG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "SPICS0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO24",
|
||||
"SPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "SPIQ",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO25",
|
||||
"SPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "SPIWP",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO26",
|
||||
"SPIWP"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "VDD_SPI",
|
||||
"tipo": "power",
|
||||
"funcoes": [
|
||||
"Entrada/Saída de alimentação para a memória flash",
|
||||
"GPIO27"
|
||||
],
|
||||
"categorias": [
|
||||
"Power",
|
||||
"GPIO"
|
||||
],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip",
|
||||
"Só pode ser utilizado como GPIO se a memória flash externa estiver sendo alimentada por uma fonte externa"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "SPIHD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO28",
|
||||
"SPIHD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "SPICLK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO29",
|
||||
"SPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "26",
|
||||
"nome": "SPID",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": [
|
||||
"GPIO30",
|
||||
"SPID"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado pela memória flash SPI",
|
||||
"Não é recomendado utilizar este pino como GPIO"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "27",
|
||||
"nome": "GPIO15",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO15"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar a fonte de sinais JTAG (consulte o item 3.4 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "28",
|
||||
"nome": "VDDA2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio digital de alto desempenho"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "29",
|
||||
"nome": "U0TXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO16",
|
||||
"U0TXD",
|
||||
"FSPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "30",
|
||||
"nome": "U0RXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO17",
|
||||
"U0RXD",
|
||||
"FSPICS1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "31",
|
||||
"nome": "SDIO_CMD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO18",
|
||||
"SDIO_CMD",
|
||||
"FSPICS2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "32",
|
||||
"nome": "SDIO_CLK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO19",
|
||||
"SDIO_CLK",
|
||||
"FSPICS3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "33",
|
||||
"nome": "SDIO_DATA0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO20",
|
||||
"SDIO_DATA0",
|
||||
"FSPICS4"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "34",
|
||||
"nome": "SDIO_DATA1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO21",
|
||||
"SDIO_DATA1",
|
||||
"FSPICS5"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "35",
|
||||
"nome": "SDIO_DATA2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO22",
|
||||
"SDIO_DATA2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "36",
|
||||
"nome": "SDIO_DATA3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO23",
|
||||
"SDIO_DATA3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SD"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "37",
|
||||
"nome": "VDDA1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "38",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída negativa de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "39",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída positiva de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "40",
|
||||
"nome": "VDDA2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "41",
|
||||
"nome": "GND",
|
||||
"tipo": "ground",
|
||||
"funcoes": ["Referência elétrica do circuito (terra)"],
|
||||
"categorias": ["GND"]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,536 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "ANT_2G",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão de antena de RF (Wi-Fi e Bluetooth)"],
|
||||
"categorias": ["Antena", "RF"],
|
||||
"avisos": ["Pino de RF dedicado a 2.4 GHz. Requer casamento de impedância de 50 ohms."]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "VDDA3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico de 3.3V"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V (3.0V a 3.6V). Fornece energia para circuitos de RF e clock."]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "VDDA4",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico de 3.3V"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V (3.0V a 3.6V). Fornece energia para circuitos de RF e clock."]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "CHIP_PU",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Habilitar o chip (Power-up / Reset)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Ativo Alto. Puxe para nível alto para inicializar o chip.",
|
||||
"Não deixe este pino flutuando. Recomenda-se usar um circuito RC externo para reset limpo."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "VDDPST1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação digital dos domínios HP (High Performance) e LP (Low Power)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V. Alimenta a parte digital de baixo consumo e pinos associados."]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "GPIO0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"XTAL_32K_P"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock"
|
||||
],
|
||||
"avisos": ["Pino multifuncional de baixo consumo. Pode ser conectado ao cristal oscilador de 32 kHz externo (Entrada P)."]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "GPIO1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"XTAL_32K_N",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino multifuncional. Conexão do cristal de 32 kHz externo (Saída N) e entrada analógica ADC1 Canal 0."]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "GPIO2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": ["GPIO2"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "GPIO3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"MTMS",
|
||||
"ADC1_CH1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG",
|
||||
"ADC",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Pino multifuncional: JTAG MTMS, ADC1 Canal 1 e pino de Strapping para controle de borda de clock do SDIO.",
|
||||
"Flutuante por padrão durante o reset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "GPIO4",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"MTDI",
|
||||
"ADC1_CH2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG",
|
||||
"ADC",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Pino multifuncional: JTAG MTDI, ADC1 Canal 2 e pino de Strapping para controle de borda de clock do SDIO.",
|
||||
"Flutuante por padrão durante o reset."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "GPIO5",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"MTCK",
|
||||
"ADC1_CH3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTCK e entrada analógica ADC1 Canal 3."]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "GPIO6",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO6",
|
||||
"MTDO"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": ["Pino multifuncional JTAG MTDO."]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "GPIO25",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO25",
|
||||
"SDIO_CMD",
|
||||
"FSPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino multifuncional de alta velocidade: SDIO Comando ou SPI2 Chip Select 0."]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "GPIO26",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO26",
|
||||
"SDIO_CLK",
|
||||
"FSPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino multifuncional de alta velocidade: SDIO Clock ou SPI2 Clock."]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "GPIO27",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO27",
|
||||
"SDIO_DATA0",
|
||||
"FSPID"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino multifuncional de alta velocidade: SDIO Dados 0 ou SPI2 MOSI (FSPID)."]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "GPIO28",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO28",
|
||||
"SDIO_DATA1",
|
||||
"FSPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de alta velocidade: SDIO Dados 1 ou SPI2 MISO (FSPIQ)."]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "GPIO22",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO22",
|
||||
"SDIO_DATA2",
|
||||
"FSPIWP"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de alta velocidade: SDIO Dados 2 ou SPI2 Write Protect."]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "GPIO23",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO23",
|
||||
"SDIO_DATA3",
|
||||
"FSPIHD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de alta velocidade: SDIO Dados 3 ou SPI2 Hold."]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "GPIO14",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO14",
|
||||
"SPICS1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino dedicado para Chip Select 1 da interface de memória SPI Flash/PSRAM."]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "GPIO15",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO15",
|
||||
"SPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino dedicado para Chip Select 0 da interface de memória SPI Flash."]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "VDDPST2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio digital HP (High Performance)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V (3.0V a 3.6V). Alimenta as interfaces digitais rápidas."]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "GPIO16",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO16",
|
||||
"SPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de dados Q (MISO) da interface de memória flash SPI."]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "GPIO17",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO17",
|
||||
"SPIWP"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de proteção contra escrita (Write Protect) da interface de memória flash SPI."]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "VDD_SPI",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Tensão de saída LDO gerada a partir de VDDPST2 para alimentar a flash e PSRAM"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão de saída configurável via software de acordo com as especificações da flash interna/externa (normalmente 3.3V ou 1.8V).",
|
||||
"Não deve ser usado como fonte geral de energia de alta corrente."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "GPIO19",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO19",
|
||||
"SPIHD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de controle de Hold da interface de memória flash SPI."]
|
||||
},
|
||||
{
|
||||
"numero": "26",
|
||||
"nome": "GPIO20",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO20",
|
||||
"SPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de sinal de clock da interface de memória flash SPI."]
|
||||
},
|
||||
{
|
||||
"numero": "27",
|
||||
"nome": "GPIO21",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI", "VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO21",
|
||||
"SPID"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino de dados D (MOSI) da interface de memória flash SPI."]
|
||||
},
|
||||
{
|
||||
"numero": "28",
|
||||
"nome": "GPIO12",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO12",
|
||||
"USB_D-"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB"
|
||||
],
|
||||
"avisos": ["Pino de sinal negativo do transceptor USB Serial/JTAG integrado."]
|
||||
},
|
||||
{
|
||||
"numero": "29",
|
||||
"nome": "GPIO13",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO13",
|
||||
"USB_D+"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"USB"
|
||||
],
|
||||
"avisos": [
|
||||
"Pino de sinal positivo do transceptor USB Serial/JTAG integrado.",
|
||||
"Possui resistor de pull-up integrado ativado por padrão na inicialização do USB."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "30",
|
||||
"nome": "GPIO24",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO24"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "31",
|
||||
"nome": "GPIO8",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO8"],
|
||||
"categorias": ["GPIO", "Strapping"],
|
||||
"avisos": [
|
||||
"Pino de Strapping para seleção do modo de boot e controle de impressão das mensagens da ROM.",
|
||||
"Flutuante por padrão durante o reset. Nível alto (1) ativa a impressão do log de inicialização."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "32",
|
||||
"nome": "GPIO9",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO9"],
|
||||
"categorias": ["GPIO", "Strapping"],
|
||||
"avisos": [
|
||||
"Pino de Strapping principal para seleção do modo de boot.",
|
||||
"Equipado com pull-up fraco integrado. Nível alto (1) no reset ativa SPI Boot (carrega do flash). Nível baixo (0) força o modo de Download."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "33",
|
||||
"nome": "GPIO10",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO10",
|
||||
"U0RXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": ["Recepção serial UART0 (Serial RX para gravação do firmware externa e depuração)."]
|
||||
},
|
||||
{
|
||||
"numero": "34",
|
||||
"nome": "GPIO11",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO11",
|
||||
"U0TXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART"
|
||||
],
|
||||
"avisos": ["Transmissão serial UART0 (Serial TX para gravação do firmware externa e depuração)."]
|
||||
},
|
||||
{
|
||||
"numero": "35",
|
||||
"nome": "GPIO29",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO29"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "36",
|
||||
"nome": "GPIO7",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO7"],
|
||||
"categorias": ["GPIO", "Strapping"],
|
||||
"avisos": [
|
||||
"Pino de Strapping para seleção da fonte dos sinais JTAG (inicialização precoce).",
|
||||
"Sem resistores de pull internos no reset. Deve ser mantido estável por circuito externo se usado."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "37",
|
||||
"nome": "VDDA1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico de 3.3V"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "38",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão externa do cristal oscilador de 40 MHz (Saída N)"],
|
||||
"categorias": ["Clock"]
|
||||
},
|
||||
{
|
||||
"numero": "39",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão externa do cristal oscilador de 40 MHz (Entrada P)"],
|
||||
"categorias": ["Clock"]
|
||||
},
|
||||
{
|
||||
"numero": "40",
|
||||
"nome": "VDDA2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico de 3.3V"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "41",
|
||||
"nome": "GND",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Pino de aterramento central (Exposed Pad)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Deve ser adequadamente soldado ao plano de terra (GND) da PCB para controle de RF e térmica estáveis."]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,482 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "GPIO0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"FSPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "GPIO1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"FSPICS0",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "MTMS",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"FSPIWP",
|
||||
"ADC1_CH1",
|
||||
"MTMS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"ADC",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "MTDO",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"FSPIHD",
|
||||
"ADC1_CH2",
|
||||
"MTDO"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"ADC",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "MTCK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"FSPICLK",
|
||||
"ADC1_CH3",
|
||||
"MTCK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"ADC",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "MTDI",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"FSPID",
|
||||
"ADC1_CH4",
|
||||
"MTDI"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"ADC",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "VDDPST1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio das IOs"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "GPIO8",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": ["GPIO8"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)",
|
||||
"Utilizado para controlar a exibição de mensagens ROM na UART0 (consulte o item 3.3 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "GPIO9",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": ["GPIO9"],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "GPIO10",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO10",
|
||||
"ZCD0"
|
||||
],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "GPIO11",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST1"],
|
||||
"funcoes": [
|
||||
"GPIO11",
|
||||
"ZCD1"
|
||||
],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "GPIO12",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDA_PMU", "VBAT"],
|
||||
"funcoes": ["GPIO12"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "XTAL_32K_P",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDA_PMU", "VBAT"],
|
||||
"funcoes": [
|
||||
"GPIO13",
|
||||
"XTAL_32K_P"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "XTAL_32K_N",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDA_PMU", "VBAT"],
|
||||
"funcoes": [
|
||||
"GPIO14",
|
||||
"XTAL_32K_N"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "CHIP_EN",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VBAT"],
|
||||
"funcoes": ["Habilitar o chip"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Colocar este pino em nível alto habilitará o funcionamento do chip",
|
||||
"Colocar este pino em nível baixo desabilitará o funcionamento do chip",
|
||||
"Não deixe este pino flutuando, utilize um resistor de pull-up externo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "VBAT",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico ou da bateria"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "VDDA_PMU",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "VDDPST1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio das IOs"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "GPIO22",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": ["GPIO22"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "U0RXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO23",
|
||||
"U0RXD",
|
||||
"FSPICS1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "U0TXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO24",
|
||||
"U0TXD",
|
||||
"FSPICS2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"UART",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "GPIO25",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO24",
|
||||
"FSPICS3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada",
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Utilizado para controlar a fonte de sinais JTAG (consulte o item 3.3 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "GPIO26",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO26",
|
||||
"FSPICS4",
|
||||
"USB_D-"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"USB"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Por padrão, este pino é utilizado para USB Serial/JTAG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "26",
|
||||
"nome": "GPIO27",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST2"],
|
||||
"funcoes": [
|
||||
"GPIO27",
|
||||
"FSPICS5",
|
||||
"USB_D+"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"USB"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno para USB ativado",
|
||||
"Por padrão, este pino é utilizado para USB Serial/JTAG"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "27",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "28",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída negativa de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.3.2 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "29",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Entrada/Saída positiva de clock"],
|
||||
"categorias": ["Clock"],
|
||||
"avisos": ["Consulte o item 2.3.2 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "30",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "31",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "32",
|
||||
"nome": "ANT",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão da antena RF"],
|
||||
"categorias": ["Antena"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "33",
|
||||
"nome": "GND",
|
||||
"tipo": "ground",
|
||||
"funcoes": ["Referência elétrica do circuito (terra)"],
|
||||
"categorias": ["GND"]
|
||||
}
|
||||
]
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,956 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "ANT",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão de antena de RF (Wi-Fi e Bluetooth)"],
|
||||
"categorias": ["Antena", "RF"],
|
||||
"avisos": ["Pino de RF dedicado para 2.4 GHz. Requer casamento de impedância de 50 ohms."]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "VDDA3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico (3.3V)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V (3.0V a 3.6V). Alimenta a seção de RF e clock."]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "VDDA4",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico (3.3V)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V (3.0V a 3.6V). Alimenta a seção de RF e clock."]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "CHIP_PU",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Habilitar o chip (Power-up / Reset)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Ativo Alto. Puxe para nível alto para inicializar o chip.",
|
||||
"Não deixe este pino flutuando. Recomenda-se usar um circuito RC externo de atraso para inicialização estável."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "GPIO0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"XTAL_32K_N"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock"
|
||||
],
|
||||
"avisos": ["Pino de clock de baixo consumo. Pode ser conectado ao cristal de 32.768 kHz externo (Pino N)."]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "GPIO1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"XTAL_32K_P",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino multifuncional. Cristal de 32.768 kHz externo (Pino P) e entrada analógica ADC1 Canal 0."]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "GPIO2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO2",
|
||||
"ADC1_CH1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 1."]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "GPIO3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"ADC1_CH2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 2."]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "GPIO4",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"ADC1_CH3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 3."]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "GPIO5",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"ADC1_CH4"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 4."]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "VDDPST_1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação de I/O do domínio 1 (3.3V)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão recomendada: 3.3V."]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "GPIO6",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO6",
|
||||
"ADC1_CH5"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 5."]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "GPIO7",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO7",
|
||||
"ADC1_CH6"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 6."]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "GPIO8",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO8",
|
||||
"ADC1_CH7"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 7."]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "GPIO9",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO9",
|
||||
"ADC1_CH8"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 8."]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "GPIO10",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO10",
|
||||
"ADC1_CH9"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 9."]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "GPIO11",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO11",
|
||||
"ADC1_CH10"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC1 Canal 10."]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "VREF_TOUCH",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Tensão de referência para os pinos Touch capacitivos"],
|
||||
"categorias": ["Touch"],
|
||||
"avisos": ["Pino analógico dedicado para estabilização de leitura capacitiva."]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "GPIO12",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO12",
|
||||
"ADC2_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 0."]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "GPIO13",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO13",
|
||||
"ADC2_CH1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 1."]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "GPIO14",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO14",
|
||||
"ADC2_CH2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 2."]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "GPIO15",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO15",
|
||||
"ADC2_CH3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 3."]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "GPIO16",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO16",
|
||||
"ADC2_CH4"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 4."]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "GPIO17",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO17",
|
||||
"ADC2_CH5"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 5."]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "GPIO18",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO18",
|
||||
"ADC2_CH6"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 6."]
|
||||
},
|
||||
{
|
||||
"numero": "26",
|
||||
"nome": "GPIO19",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_1"],
|
||||
"funcoes": [
|
||||
"GPIO19",
|
||||
"ADC2_CH7"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino de entrada analógica ADC2 Canal 7."]
|
||||
},
|
||||
{
|
||||
"numero": "27",
|
||||
"nome": "SDIO_DATA0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_SD"],
|
||||
"funcoes": [
|
||||
"SDIO_DATA0",
|
||||
"FSPID"
|
||||
],
|
||||
"categorias": [
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino da interface SDIO de alta velocidade (Dados 0) ou SPI2 MOSI."]
|
||||
},
|
||||
{
|
||||
"numero": "28",
|
||||
"nome": "SDIO_DATA1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_SD"],
|
||||
"funcoes": [
|
||||
"SDIO_DATA1",
|
||||
"FSPIQ"
|
||||
],
|
||||
"categorias": [
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino da interface SDIO de alta velocidade (Dados 1) ou SPI2 MISO."]
|
||||
},
|
||||
{
|
||||
"numero": "29",
|
||||
"nome": "SDIO_DATA2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_SD"],
|
||||
"funcoes": [
|
||||
"SDIO_DATA2",
|
||||
"FSPIWP"
|
||||
],
|
||||
"categorias": [
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino da interface SDIO de alta velocidade (Dados 2) ou SPI2 Write Protect."]
|
||||
},
|
||||
{
|
||||
"numero": "30",
|
||||
"nome": "VDD_PSRAM_1P8_1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação de 1.8V para PSRAM integrada no encapsulamento"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Gerado pelo LDO interno para alimentar a PSRAM integrada. Não conectar a circuitos de potência externa."]
|
||||
},
|
||||
{
|
||||
"numero": "31",
|
||||
"nome": "SDIO_DATA3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_SD"],
|
||||
"funcoes": [
|
||||
"SDIO_DATA3",
|
||||
"FSPIHD"
|
||||
],
|
||||
"categorias": [
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Pino da interface SDIO de alta velocidade (Dados 3) ou SPI2 Hold."]
|
||||
},
|
||||
{
|
||||
"numero": "32",
|
||||
"nome": "SDIO_CLK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_SD"],
|
||||
"funcoes": [
|
||||
"SDIO_CLK",
|
||||
"FSPICLK"
|
||||
],
|
||||
"categorias": [
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Clock da interface SDIO de alta velocidade ou SPI2 Clock."]
|
||||
},
|
||||
{
|
||||
"numero": "33",
|
||||
"nome": "SDIO_CMD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_SD"],
|
||||
"funcoes": [
|
||||
"SDIO_CMD",
|
||||
"FSPICS0"
|
||||
],
|
||||
"categorias": [
|
||||
"SDIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Comando da interface SDIO de alta velocidade ou SPI2 Chip Select 0."]
|
||||
},
|
||||
{
|
||||
"numero": "34",
|
||||
"nome": "VDD_PSRAM_1P8_2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação de 1.8V para PSRAM integrada no encapsulamento"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "35",
|
||||
"nome": "VDD_LDO_1P8",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Pino de entrada/saída LDO de 1.8V"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "36",
|
||||
"nome": "SPICS",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": ["SPICS"],
|
||||
"categorias": ["SPI"],
|
||||
"avisos": ["Chip Select dedicado para a Flash SPI externa ou interna."]
|
||||
},
|
||||
{
|
||||
"numero": "37",
|
||||
"nome": "SPIQ",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": ["SPIQ"],
|
||||
"categorias": ["SPI"],
|
||||
"avisos": ["Dado Q (MISO) dedicado para a Flash SPI externa ou interna."]
|
||||
},
|
||||
{
|
||||
"numero": "38",
|
||||
"nome": "SPIWP",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": ["SPIWP"],
|
||||
"categorias": ["SPI"],
|
||||
"avisos": ["Write Protect dedicado para a Flash SPI externa ou interna."]
|
||||
},
|
||||
{
|
||||
"numero": "39",
|
||||
"nome": "VDD_SPI",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Tensão de alimentação dedicada para a interface Flash SPI"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Tensão típica: 3.3V ou 1.8V gerada internamente."]
|
||||
},
|
||||
{
|
||||
"numero": "40",
|
||||
"nome": "SPIHD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": ["SPIHD"],
|
||||
"categorias": ["SPI"],
|
||||
"avisos": ["Hold dedicado para a Flash SPI externa ou interna."]
|
||||
},
|
||||
{
|
||||
"numero": "41",
|
||||
"nome": "SPICLK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": ["SPICLK"],
|
||||
"categorias": ["SPI"],
|
||||
"avisos": ["Clock dedicado para a Flash SPI externa ou interna."]
|
||||
},
|
||||
{
|
||||
"numero": "42",
|
||||
"nome": "SPID",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SPI"],
|
||||
"funcoes": ["SPID"],
|
||||
"categorias": ["SPI"],
|
||||
"avisos": ["Dado D (MOSI) dedicado para a Flash SPI externa ou interna."]
|
||||
},
|
||||
{
|
||||
"numero": "43",
|
||||
"nome": "VCCA/VDDPST_2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação analógica e digital do domínio 2 (3.3V)"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "44",
|
||||
"nome": "USB_DP",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Pino positivo do transceptor USB Serial/JTAG integrado"],
|
||||
"categorias": ["USB"],
|
||||
"avisos": ["USB D+. Possui pull-up de hardware interno."]
|
||||
},
|
||||
{
|
||||
"numero": "45",
|
||||
"nome": "USB_DM",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Pino negativo do transceptor USB Serial/JTAG integrado"],
|
||||
"categorias": ["USB"],
|
||||
"avisos": ["USB D-."]
|
||||
},
|
||||
{
|
||||
"numero": "46",
|
||||
"nome": "GPIO33",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO33",
|
||||
"ADC2_CH8"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: GPIO33 e ADC2 Canal 8."]
|
||||
},
|
||||
{
|
||||
"numero": "47",
|
||||
"nome": "GPIO34",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO34",
|
||||
"ADC2_CH9"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: GPIO34 e ADC2 Canal 9."]
|
||||
},
|
||||
{
|
||||
"numero": "48",
|
||||
"nome": "GPIO35",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO35",
|
||||
"ADC2_CH10"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "49",
|
||||
"nome": "GPIO36",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO36",
|
||||
"ADC2_CH11"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "50",
|
||||
"nome": "GPIO37",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO37",
|
||||
"ADC2_CH12"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "51",
|
||||
"nome": "GPIO38",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO38",
|
||||
"ADC2_CH13"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "52",
|
||||
"nome": "GPIO39",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO39",
|
||||
"ADC2_CH14"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "53",
|
||||
"nome": "GPIO40",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO40",
|
||||
"ADC2_CH15"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "54",
|
||||
"nome": "VDDPST_3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação de I/O do domínio 3 (3.3V)"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "55",
|
||||
"nome": "GPIO42",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO42",
|
||||
"ADC2_CH16"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "56",
|
||||
"nome": "GPIO43",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO43",
|
||||
"ADC2_CH17"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "57",
|
||||
"nome": "GPIO44",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO44",
|
||||
"ADC2_CH18"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "58",
|
||||
"nome": "GPIO45",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO45",
|
||||
"ADC2_CH19"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "59",
|
||||
"nome": "GPIO46",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO46",
|
||||
"ADC2_CH20"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "60",
|
||||
"nome": "GPIO47",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": [
|
||||
"GPIO47",
|
||||
"ADC2_CH21"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"ADC"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "61",
|
||||
"nome": "GPIO48",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": ["GPIO48"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "62",
|
||||
"nome": "GPIO49",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_3"],
|
||||
"funcoes": ["GPIO49"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "63",
|
||||
"nome": "VREF_ADC",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Tensão de referência estável externa para calibração do ADC"],
|
||||
"categorias": ["Power", "ADC"],
|
||||
"avisos": ["Pino analógico dedicado para calibração precisa do conversor analógico-digital."]
|
||||
},
|
||||
{
|
||||
"numero": "64",
|
||||
"nome": "VDDPST_4",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação de I/O do domínio 4 (3.3V)"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "65",
|
||||
"nome": "GPIO50",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO50"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "66",
|
||||
"nome": "GPIO51",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO51"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "67",
|
||||
"nome": "GPIO52",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO52"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "68",
|
||||
"nome": "GPIO53",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO53"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "69",
|
||||
"nome": "GPIO54",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": [
|
||||
"GPIO54",
|
||||
"MTDO"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTDO."]
|
||||
},
|
||||
{
|
||||
"numero": "70",
|
||||
"nome": "GPIO55",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": [
|
||||
"GPIO55",
|
||||
"MTCK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTCK."]
|
||||
},
|
||||
{
|
||||
"numero": "71",
|
||||
"nome": "GPIO56",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": [
|
||||
"GPIO56",
|
||||
"MTDI"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTDI."]
|
||||
},
|
||||
{
|
||||
"numero": "72",
|
||||
"nome": "GPIO57",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": [
|
||||
"GPIO57",
|
||||
"MTMS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": ["Pino multifuncional: JTAG MTMS."]
|
||||
},
|
||||
{
|
||||
"numero": "73",
|
||||
"nome": "GPIO58",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO58"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "74",
|
||||
"nome": "GPIO59",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO59"],
|
||||
"categorias": ["GPIO"]
|
||||
},
|
||||
{
|
||||
"numero": "75",
|
||||
"nome": "GPIO60",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO60"],
|
||||
"categorias": ["GPIO", "Strapping"],
|
||||
"avisos": [
|
||||
"Pino de Strapping para boot (junto com GPIO61).",
|
||||
"Equipado com pull-up interno ativo por padrão."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "76",
|
||||
"nome": "GPIO61",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDDPST_4"],
|
||||
"funcoes": ["GPIO61"],
|
||||
"categorias": ["GPIO", "Strapping"],
|
||||
"avisos": [
|
||||
"Pino de Strapping principal para seleção de boot.",
|
||||
"Equipado com pull-up interno ativo por padrão. Nível alto (1) no reset ativa SPI Boot. Nível baixo (0) força o modo Download."
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "77",
|
||||
"nome": "VDDA1",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico de 3.3V"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "78",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão externa do cristal oscilador de alta velocidade (Saída N)"],
|
||||
"categorias": ["Clock"]
|
||||
},
|
||||
{
|
||||
"numero": "79",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"funcoes": ["Conexão externa do cristal oscilador de alta velocidade (Entrada P)"],
|
||||
"categorias": ["Clock"]
|
||||
},
|
||||
{
|
||||
"numero": "80",
|
||||
"nome": "VDDA2",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Alimentação do domínio analógico de 3.3V"],
|
||||
"categorias": ["Power"]
|
||||
},
|
||||
{
|
||||
"numero": "81",
|
||||
"nome": "GND",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Pino de aterramento central (Exposed Pad)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": ["Deve ser adequadamente soldado ao plano de terra (GND) da PCB para controle de RF e dissipação térmica estáveis."]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,964 @@
|
||||
[
|
||||
{
|
||||
"numero": "1",
|
||||
"nome": "VDDA",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 2.3V ou 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Para chips com a flash ou PSRAM integrada, a tensão mínima recomendada é 3.0V",
|
||||
"Para chips sem a flash ou PSRAM integrada, a tensão mínima recomendada é 2.3V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "2",
|
||||
"nome": "LNA_IN",
|
||||
"tipo": "analog",
|
||||
"alimentação": ["VDD3P3"],
|
||||
"funcoes": ["Entrada do amplificador de baixo ruído (LNA) para o receptor Wi-Fi e Bluetooth"],
|
||||
"categorias": ["Antena"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "3",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 2.3V ou 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Para chips com a flash ou PSRAM integrada, a tensão mínima recomendada é 3.0V",
|
||||
"Para chips sem a flash ou PSRAM integrada, a tensão mínima recomendada é 2.3V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "4",
|
||||
"nome": "VDD3P3",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 2.3V ou 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Para chips com a flash ou PSRAM integrada, a tensão mínima recomendada é 3.0V",
|
||||
"Para chips sem a flash ou PSRAM integrada, a tensão mínima recomendada é 2.3V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "5",
|
||||
"nome": "SENSOR_VP",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO36",
|
||||
"RTC_GPIO0",
|
||||
"ADC1_CH0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Este pino é de apenas de entrada (input only)"]
|
||||
},
|
||||
{
|
||||
"numero": "6",
|
||||
"nome": "SENSOR_CAPP",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO37",
|
||||
"RTC_GPIO1",
|
||||
"ADC1_CH1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Este pino é de apenas de entrada (input only)"]
|
||||
},
|
||||
{
|
||||
"numero": "7",
|
||||
"nome": "SENSOR_CAPN",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO38",
|
||||
"RTC_GPIO2",
|
||||
"ADC1_CH2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Este pino é de apenas de entrada (input only)"]
|
||||
},
|
||||
{
|
||||
"numero": "8",
|
||||
"nome": "SENSOR_VN",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO39",
|
||||
"RTC_GPIO3",
|
||||
"ADC1_CH3"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Este pino é de apenas de entrada (input only)"]
|
||||
},
|
||||
{
|
||||
"numero": "9",
|
||||
"nome": "CHIP_PU",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": ["Habilitar o chip"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Colocar este pino em nível alto habilitará o funcionamento do chip",
|
||||
"Colocar este pino em nível baixo desabilitará o funcionamento do chip",
|
||||
"Não deixe este pino flutuando, utilize um resistor de pull-up externo",
|
||||
"Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "10",
|
||||
"nome": "VDET_1",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO34",
|
||||
"RTC_GPIO4",
|
||||
"ADC1_CH6"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Este pino é de apenas de entrada (input only)"]
|
||||
},
|
||||
{
|
||||
"numero": "11",
|
||||
"nome": "VDET_2",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO35",
|
||||
"RTC_GPIO5",
|
||||
"ADC1_CH7"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC"
|
||||
],
|
||||
"avisos": ["Este pino é de apenas de entrada (input only)"]
|
||||
},
|
||||
{
|
||||
"numero": "12",
|
||||
"nome": "32K_XP",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO32",
|
||||
"RTC_GPIO9",
|
||||
"ADC1_CH4",
|
||||
"TOUCH9",
|
||||
"XTAL_32K_P"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"Clock"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "13",
|
||||
"nome": "32K_XN",
|
||||
"tipo": "analog",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO33",
|
||||
"RTC_GPIO8",
|
||||
"ADC1_CH5",
|
||||
"TOUCH8",
|
||||
"XTAL_32K_N"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"Clock"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "14",
|
||||
"nome": "GPIO25",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO25",
|
||||
"RTC_GPIO6",
|
||||
"ADC2_CH8",
|
||||
"DAC_1",
|
||||
"EMAC_RXD0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"DAC",
|
||||
"Ethernet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "15",
|
||||
"nome": "GPIO26",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO26",
|
||||
"RTC_GPIO7",
|
||||
"ADC2_CH9",
|
||||
"DAC_2",
|
||||
"EMAC_RXD1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"DAC",
|
||||
"Ethernet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "16",
|
||||
"nome": "GPIO27",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO27",
|
||||
"RTC_GPIO17",
|
||||
"ADC2_CH7",
|
||||
"TOUCH7",
|
||||
"EMAC_RXDV"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"Ethernet"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "17",
|
||||
"nome": "MTMS",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO14",
|
||||
"RTC_GPIO16",
|
||||
"ADC2_CH6",
|
||||
"TOUCH6",
|
||||
"HSPICLK",
|
||||
"HS2_CLK",
|
||||
"SD_CLK",
|
||||
"EMAC_TXD2",
|
||||
"MTMS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"SPI",
|
||||
"SD",
|
||||
"Ethernet",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "18",
|
||||
"nome": "MTDI",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO12",
|
||||
"RTC_GPIO15",
|
||||
"ADC2_CH5",
|
||||
"TOUCH5",
|
||||
"HSPIQ",
|
||||
"HS2_DATA2",
|
||||
"SD_DATA2",
|
||||
"EMAC_TXD3",
|
||||
"MTDI"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"SPI",
|
||||
"SD",
|
||||
"Ethernet",
|
||||
"JTAG",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-down interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-down interno ativado",
|
||||
"Pino utilizado para debugging",
|
||||
"Utilizado para controlar a tensão de VDD_SDIO (LDO interno) (consulte o item 3.2 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "19",
|
||||
"nome": "VDD3P3_RTC",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio de baixo consumo (RTC) e parte do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 2.3V ou 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Para chips com a flash ou PSRAM integrada, a tensão mínima recomendada é 3.0V",
|
||||
"Para chips sem a flash ou PSRAM integrada, a tensão mínima recomendada é 2.3V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "20",
|
||||
"nome": "MTCK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO13",
|
||||
"RTC_GPIO14",
|
||||
"ADC2_CH4",
|
||||
"TOUCH4",
|
||||
"HSPID",
|
||||
"HS2_DATA3",
|
||||
"SD_DATA3",
|
||||
"EMAC_RX_ER",
|
||||
"MTCK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"SPI",
|
||||
"SD",
|
||||
"Ethernet",
|
||||
"JTAG"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-down interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "21",
|
||||
"nome": "MTDO",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO15",
|
||||
"RTC_GPIO13",
|
||||
"ADC2_CH3",
|
||||
"TOUCH3",
|
||||
"HSPICS0",
|
||||
"HS2_CMD",
|
||||
"SD_CMD",
|
||||
"EMAC_RXD3",
|
||||
"MTDO",
|
||||
"I2C_SDA"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"SPI",
|
||||
"SD",
|
||||
"Ethernet",
|
||||
"JTAG",
|
||||
"I2C",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"A função de I2C_SDA está disponível no modo de baixo consumo (RTC)",
|
||||
"Pino utilizado para debugging",
|
||||
"Utilizado para controlar a exibição de mensagens ROM na UART0 (consulte o item 3.3 do datasheet para mais detalhes)",
|
||||
"Utilizado para controlar a temporização do SDIO Slave (consulte o item 3.4 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "22",
|
||||
"nome": "GPIO2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO2",
|
||||
"RTC_GPIO12",
|
||||
"ADC2_CH2",
|
||||
"TOUCH2",
|
||||
"HSPIWP",
|
||||
"HS2_DATA0",
|
||||
"SD_DATA0",
|
||||
"I2C_SCL"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"SPI",
|
||||
"SD",
|
||||
"I2C",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-down interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-down interno ativado",
|
||||
"A função de I2C_SCL está disponível no modo de baixo consumo (RTC)",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "23",
|
||||
"nome": "GPIO0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO0",
|
||||
"RTC_GPIO11",
|
||||
"ADC2_CH1",
|
||||
"TOUCH1",
|
||||
"CLC_OUT1",
|
||||
"EMAC_TX_CLK",
|
||||
"I2C_SDA"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"Clock",
|
||||
"Ethernet",
|
||||
"I2C",
|
||||
"Strapping"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"A função de I2C_SDA está disponível no modo de baixo consumo (RTC)",
|
||||
"Utilizado para controlar o modo de boot do chip (consulte o item 3.1 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "24",
|
||||
"nome": "GPIO4",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_RTC"],
|
||||
"funcoes": [
|
||||
"GPIO4",
|
||||
"RTC_GPIO10",
|
||||
"ADC2_CH0",
|
||||
"TOUCH0",
|
||||
"HSPIHD",
|
||||
"HS2_DATA1",
|
||||
"SD_DATA1",
|
||||
"EMAC_TX_ER",
|
||||
"I2C_SCL"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Low Power",
|
||||
"ADC",
|
||||
"Touch",
|
||||
"SPI",
|
||||
"SD",
|
||||
"Ethernet",
|
||||
"I2C"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-down interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-down interno ativado",
|
||||
"A função de I2C_SCL está disponível no modo de baixo consumo (RTC)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "25",
|
||||
"nome": "GPIO16",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO16",
|
||||
"HS1_DATA4",
|
||||
"U2RXD",
|
||||
"EMAC_CLK_OUT"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"UART",
|
||||
"Ethernet"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "26",
|
||||
"nome": "VDD_SDIO",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada/saída da alimentação das memórias SDIO internas (Flash/PSRAM)"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 2.3V ou 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Este pino é conectado a saída do LDO interno",
|
||||
"Se for conectado diretamente ao VDD3P3_RTC, o LDO interno será desabilitado automaticamente",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "27",
|
||||
"nome": "GPIO17",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO17",
|
||||
"HS1_DATA5",
|
||||
"U2TXD",
|
||||
"EMAC_CLK_OUT_180"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"UART",
|
||||
"Ethernet"
|
||||
],
|
||||
"avisos": [
|
||||
"Após o reset, este pino estará configurado como entrada",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "28",
|
||||
"nome": "SD_DATA_2",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO9",
|
||||
"SPIHD",
|
||||
"HS1_DATA2",
|
||||
"SD_DATA2",
|
||||
"U1RXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "29",
|
||||
"nome": "SD_DATA_3",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO10",
|
||||
"SPIWP",
|
||||
"HS1_DATA3",
|
||||
"SD_DATA3",
|
||||
"U1TXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "30",
|
||||
"nome": "SD_CMD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO11",
|
||||
"SPICS0",
|
||||
"HS1_CMD",
|
||||
"SD_CMD",
|
||||
"U1RTS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "31",
|
||||
"nome": "SD_CLK",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO6",
|
||||
"SPICLK",
|
||||
"HS1_CLK",
|
||||
"SD_CLK",
|
||||
"U1CTS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "32",
|
||||
"nome": "SD_DATA_0",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO7",
|
||||
"SPIQ",
|
||||
"HS1_DATA0",
|
||||
"SD_DATA0",
|
||||
"U2RTS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "33",
|
||||
"nome": "SD_DATA_1",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD_SDIO"],
|
||||
"funcoes": [
|
||||
"GPIO8",
|
||||
"SPID",
|
||||
"HS1_DATA1",
|
||||
"SD_DATA1",
|
||||
"U2CTS"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"SD",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Dedicado a comunicação com a Flash/PSRAM interna, não recomendado para outras funções"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "34",
|
||||
"nome": "GPIO5",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO5",
|
||||
"VSPICS0",
|
||||
"HS1_DATA6",
|
||||
"EMAC_RX_CLK"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"Ethernet"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Utilizado para controlar a temporização do SDIO Slave (consulte o item 3.4 do datasheet para mais detalhes)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "35",
|
||||
"nome": "GPIO18",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO18",
|
||||
"VSPICLK",
|
||||
"HS1_DATA7"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "36",
|
||||
"nome": "GPIO23",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO23",
|
||||
"VSPID",
|
||||
"HS1_STROBE"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "37",
|
||||
"nome": "VDD3P3_CPU",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio digital"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 1.8V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "38",
|
||||
"nome": "GPIO19",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO19",
|
||||
"VSPIQ",
|
||||
"U0CTS",
|
||||
"EMAC_TXD0"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"UART",
|
||||
"Ethernet"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "39",
|
||||
"nome": "GPIO22",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO22",
|
||||
"VSPIWP",
|
||||
"U0RTS",
|
||||
"EMAC_TXD1"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"UART",
|
||||
"Ethernet"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "40",
|
||||
"nome": "U0RXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO3",
|
||||
"CLK_OUT2",
|
||||
"U0RXD"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock",
|
||||
"UART"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "41",
|
||||
"nome": "U0TXD",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO1",
|
||||
"CLK_OUT3",
|
||||
"U0TXD",
|
||||
"EMAC_RXD2"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"Clock",
|
||||
"UART",
|
||||
"Ethernet"
|
||||
],
|
||||
"avisos": [
|
||||
"Durante o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Após o reset, este pino estará configurado como entrada com o pull-up interno ativado",
|
||||
"Pino utilizado para debugging"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "42",
|
||||
"nome": "GPIO21",
|
||||
"tipo": "io",
|
||||
"alimentacao": ["VDD3P3_CPU"],
|
||||
"funcoes": [
|
||||
"GPIO21",
|
||||
"VSPIHD",
|
||||
"EMAC_TX_EN"
|
||||
],
|
||||
"categorias": [
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"Ethernet"
|
||||
],
|
||||
"avisos": ["Após o reset, este pino estará configurado como entrada"]
|
||||
},
|
||||
{
|
||||
"numero": "43",
|
||||
"nome": "VDDA",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 2.3V ou 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Para chips com a flash ou PSRAM integrada, a tensão mínima recomendada é 3.0V",
|
||||
"Para chips sem a flash ou PSRAM integrada, a tensão mínima recomendada é 2.3V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "44",
|
||||
"nome": "XTAL_N",
|
||||
"tipo": "analog",
|
||||
"alimentação": ["VDDA"],
|
||||
"funcoes": ["Entrada/Saída negativa de clock"],
|
||||
"categorias": ["clock"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "45",
|
||||
"nome": "XTAL_P",
|
||||
"tipo": "analog",
|
||||
"alimentação": ["VDDA"],
|
||||
"funcoes": ["Entrada/Saída positiva de clock"],
|
||||
"categorias": ["clock"],
|
||||
"avisos": ["Consulte o item 2.4 do datasheet para mais detalhes sobre pinos analógicos"]
|
||||
},
|
||||
{
|
||||
"numero": "46",
|
||||
"nome": "VDDA",
|
||||
"tipo": "power",
|
||||
"funcoes": ["Entrada de alimentação do domínio analógico"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Tensão Recomendada: 3.3V",
|
||||
"Tensão Mínima Recomendada: 2.3V ou 3.0V",
|
||||
"Tensão Máxima Recomendada: 3.6V",
|
||||
"Para chips com a flash ou PSRAM integrada, a tensão mínima recomendada é 3.0V",
|
||||
"Para chips sem a flash ou PSRAM integrada, a tensão mínima recomendada é 2.3V",
|
||||
"Consulte o item 2.5 do datasheet para mais detalhes sobre a alimentação do chip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "47",
|
||||
"nome": "CAP2",
|
||||
"tipo": "analog",
|
||||
"alimentação": ["VDDA"],
|
||||
"funcoes": ["Capacitor de filtro"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Conecte um capacitor de 3.3nF (10%) e um resistor de 20kΩ em paralelo com o CAP1",
|
||||
"Consulte o item 2.2 do datasheet para mais detalhes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "48",
|
||||
"nome": "CAP1",
|
||||
"tipo": "analog",
|
||||
"alimentação": ["VDDA"],
|
||||
"funcoes": ["Capacitor de filtro"],
|
||||
"categorias": ["Power"],
|
||||
"avisos": [
|
||||
"Conecte um capacitor de 10nF em série com o GND",
|
||||
"Consulte o item 2.2 do datasheet para mais detalhes"
|
||||
]
|
||||
},
|
||||
{
|
||||
"numero": "49",
|
||||
"nome": "GND",
|
||||
"tipo": "ground",
|
||||
"funcoes": ["Referência elétrica do circuito (terra)"],
|
||||
"categorias": ["GND"]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,394 @@
|
||||
{
|
||||
"ESP-IDF": {
|
||||
"nome": "ESP-IDF",
|
||||
"icone": "⚙️",
|
||||
"nome_completo": "Espressif IoT Development Framework",
|
||||
"descricao": "Framework oficial nativo da Espressif para todos os SoCs ESP32. Baseado em FreeRTOS multicore e CMake, oferece controle total do silício, periféricos, rádio e arquitetura de componentes modulares.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Framework Base Oficial",
|
||||
"funcao_principal": "Desenvolvimento industrial e de alta performance com acesso direto aos registradores, RTOS em tempo real e pilha completa de protocolos",
|
||||
"caracteristicas": [
|
||||
"Sistema operacional de tempo real (FreeRTOS SMP multicore)",
|
||||
"Suporte nativo ao ESP Component Registry via idf_component.yml",
|
||||
"Pilha completa de conectividade Wi-Fi 4/6, BLE 5.x, Zigbee e Thread",
|
||||
"Suporte a todos os SoCs (ESP32, S2, S3, C2, C3, C6, H2, P4)",
|
||||
"Gerenciamento avançado de energia e modos Deep Sleep",
|
||||
"Segurança robusta: Secure Boot v2, Flash Encryption e Crypto HW",
|
||||
"Atualizações OTA criptografadas com rollback automático",
|
||||
"Toolchain moderna Clang/GCC, suporte a C++23 e debug via JTAG OpenOCD"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Produtos comerciais e industriais de IoT",
|
||||
"Dispositivos com requisitos rigorosos de bateria e consumo",
|
||||
"Aplicações em tempo real com controle de interrupções",
|
||||
"Sistemas de segurança com criptografia de hardware",
|
||||
"Gateways multiprotocolo de alto desempenho"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-idf.c",
|
||||
"exemplos": "https://github.com/espressif/esp-idf/tree/master/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-idf/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/esp-idf",
|
||||
"cor": "#E74C3C"
|
||||
},
|
||||
"ESP-RainMaker": {
|
||||
"nome": "ESP-RainMaker",
|
||||
"icone": "☁️",
|
||||
"nome_completo": "ESP RainMaker AIoT Cloud Platform",
|
||||
"descricao": "Plataforma completa de nuvem e firmware da Espressif para produtos conectados. Permite criar dispositivos IoT sem precisar desenvolver backend ou aplicativos móveis do zero.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Cloud & AIoT Framework",
|
||||
"funcao_principal": "Construção acelerada de produtos inteligentes com aplicativo móvel (iOS/Android), nuvem AWS Serverless e controle por voz (Alexa/Google Home)",
|
||||
"caracteristicas": [
|
||||
"Provisionamento Wi-Fi e BLE assistido via aplicativo oficial",
|
||||
"Geração dinâmica de interface no app com base nos parâmetros do firmware",
|
||||
"Integração nativa com Amazon Alexa e Google Assistant",
|
||||
"Suporte a controle local (Local Control via mDNS/HTTP) e nuvem simultâneos",
|
||||
"Painel administrativo (RainMaker Dashboard) para gerenciamento de frotas e OTA",
|
||||
"Compatibilidade nativa com nós Matter e Bridge de dispositivos",
|
||||
"Biblioteca integrada via ESP Component Registry (espressif/esp_rainmaker)"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Eletrodomésticos e iluminação inteligente para consumidor final",
|
||||
"Produtos IoT com prazo reduzido de lançamento no mercado (Time-to-Market)",
|
||||
"Dispositivos que exigem controle por app móvel sem custo de infraestrutura própria",
|
||||
"Sistemas de monitoramento remoto com atualização OTA centralizada"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-rainmaker.c",
|
||||
"exemplos": "https://github.com/espressif/esp-rainmaker/tree/master/examples",
|
||||
"documentacao": "https://rainmaker.espressif.com/docs/",
|
||||
"repositorio": "https://github.com/espressif/esp-rainmaker",
|
||||
"cor": "#3B82F6"
|
||||
},
|
||||
"ESP-Matter": {
|
||||
"nome": "ESP-Matter",
|
||||
"icone": "🏠",
|
||||
"nome_completo": "ESP Matter SDK",
|
||||
"descricao": "SDK oficial da Espressif para o padrão universal de casa inteligente Matter (antigo Project CHIP). Permite que seus dispositivos operem de forma interoperável com Apple HomeKit, Google Home, Amazon Alexa e Home Assistant.",
|
||||
"linguagem": "C++",
|
||||
"tipo": "Smart Home Framework",
|
||||
"funcao_principal": "Desenvolvimento de dispositivos e pontes inteligentes compatíveis com o padrão unificado Matter sobre Wi-Fi e Thread",
|
||||
"caracteristicas": [
|
||||
"Implementação completa dos clusters da especificação Matter",
|
||||
"Suporte a transporte sobre Wi-Fi e Thread (802.15.4 em ESP32-H2 e ESP32-C6)",
|
||||
"Comissionamento simplificado via BLE ou On-Network",
|
||||
"Compatibilidade simultânea com Apple Home, Google Home, Alexa e SmartThings",
|
||||
"Segurança baseada em certificados de autenticação de dispositivo (DAC)",
|
||||
"Suporte a Matter Bridge (conectando dispositivos legados Zigbee/BLE ao Matter)",
|
||||
"Integração direta ao ESP-IDF e ESP Component Registry"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Lâmpadas, tomadas, interruptores e dimmers interoperáveis",
|
||||
"Sensores de presença, temperatura, umidade e contato",
|
||||
"Fechaduras eletrônicas e atuadores de cortinas",
|
||||
"Matter Border Routers e Bridges residenciais"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-matter.c",
|
||||
"exemplos": "https://github.com/espressif/esp-matter/tree/main/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-matter/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/esp-matter",
|
||||
"cor": "#F59E0B"
|
||||
},
|
||||
"ESP-ADF": {
|
||||
"nome": "ESP-ADF",
|
||||
"icone": "🎵",
|
||||
"nome_completo": "ESP Audio Development Framework",
|
||||
"descricao": "Framework especializado para processamento, streaming e reprodução de áudio digital de alta qualidade em SoCs ESP32.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Framework de Áudio & Voz",
|
||||
"funcao_principal": "Criação de pipelines de áudio flexíveis com decodificadores, streaming de rede, equalização e efeitos acústicos",
|
||||
"caracteristicas": [
|
||||
"Arquitetura de pipeline de áudio modular (Audio Elements & Audio Stream)",
|
||||
"Suporte a múltiplos codecs: MP3, AAC, FLAC, WAV, OGG, Opus e AMR",
|
||||
"Streaming de áudio via HTTP, HTTPS, HLS, RTSP e WebSockets",
|
||||
"Suporte a Bluetooth A2DP (Sink/Source) e Bluetooth Handsfree (HFP)",
|
||||
"Algoritmos de processamento acústico (AEC, AGC, NS, equalizadores paramétricos)",
|
||||
"Suporte a placas dedicadas como ESP32-LyraT e ESP32-S3-Korvo"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Caixas de som inteligentes e internet radios",
|
||||
"Intercomunicadores, walkie-talkies e sistemas de interfonia VoIP",
|
||||
"Aparelhos de reprodução musical com PSRAM",
|
||||
"Sistemas de som ambiente para automação predial"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-adf.c",
|
||||
"exemplos": "https://github.com/espressif/esp-adf/tree/master/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-adf/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/esp-adf",
|
||||
"cor": "#0284C7"
|
||||
},
|
||||
"ESP-SR": {
|
||||
"nome": "ESP-SR",
|
||||
"icone": "🎙️",
|
||||
"nome_completo": "ESP Speech Recognition Framework",
|
||||
"descricao": "Framework de reconhecimento de fala local e processamento de áudio com IA na borda (Edge AI), permitindo comandos de voz sem depender de conexão à internet.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Framework de Voz & IA",
|
||||
"funcao_principal": "Processamento de voz local, detecção de palavra de ativação (Wake Word) e reconhecimento de comandos de fala em tempo real",
|
||||
"caracteristicas": [
|
||||
"WakeNet: Detecção precisa de Wake Words locais (como 'Hi, ESP' e palavras personalizadas)",
|
||||
"MultiNet: Reconhecimento de até centenas de comandos de voz locais offline em português, inglês e mandarim",
|
||||
"AFE (Audio Front-End): Cancelamento acústico de eco (AEC), supressão de ruído (BSS/NS) e controle automático de ganho (AGC)",
|
||||
"Suporte a múltiplos microfones com formação de feixe direcional (Beamforming)",
|
||||
"Otimizado com aceleração vetorial SIMD para ESP32-S3 e ESP32-P4",
|
||||
"Componente disponível no ESP Component Registry (espressif/esp-sr)"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Eletrodomésticos com controle por voz 100% offline e privativo",
|
||||
"Painéis de automação residencial acionados por fala",
|
||||
"Brinquedos interativos e robótica educacional",
|
||||
"Equipamentos hospitalares e industriais com comando sem as mãos"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-sr.c",
|
||||
"exemplos": "https://github.com/espressif/esp-sr/tree/master/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-sr/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/esp-sr",
|
||||
"cor": "#6366F1"
|
||||
},
|
||||
"ESP-IoT-Solution": {
|
||||
"nome": "ESP-IoT-Solution",
|
||||
"icone": "🧩",
|
||||
"nome_completo": "ESP-IoT-Solution Driver & Peripheral Suite",
|
||||
"descricao": "Coleção oficial da Espressif com dezenas de drivers, componentes de periféricos, telas touch, sensores e protocolos de barramento prontos para produção.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Biblioteca de Periféricos & Drivers",
|
||||
"funcao_principal": "Acelerar a integração de componentes de hardware (telas LCD/OLED, sensores ambientais/IMU, botões inteligentes, barramentos I2C/SPI/Modbus)",
|
||||
"caracteristicas": [
|
||||
"Drivers completos de sensores (temperatura, umidade, pressão, acelerômetros, luz)",
|
||||
"Gerenciamento avançado de botões físicos, matrizes touch e encoders rotativos",
|
||||
"Drivers para displays LCD e OLED (ST7789, ILI9341, SSD1306) e controladores touch (FT6X36, GT911)",
|
||||
"Pilha industrial Modbus (Master e Slave sobre RS-485 ou TCP)",
|
||||
"Controle de motores de passo e drivers de LED endereçável (WS2812/SK6812)",
|
||||
"Totalmente modularizado no ESP Component Registry"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Interfaces homem-máquina (IHM / HMI) com telas e botões capacitivos",
|
||||
"Estações meteorológicas e monitoramento de sensores industriais",
|
||||
"Equipamentos de automação industrial integrados via RS-485 Modbus",
|
||||
"Projetos com fitas e matrizes de LED RGB complexas"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-iot-solution.c",
|
||||
"exemplos": "https://github.com/espressif/esp-iot-solution/tree/master/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-iot-solution/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/esp-iot-solution",
|
||||
"cor": "#10B981"
|
||||
},
|
||||
"ESP-NOW": {
|
||||
"nome": "ESP-NOW & Mesh",
|
||||
"icone": "📡",
|
||||
"nome_completo": "ESP-NOW Protocol & Mesh-Lite",
|
||||
"descricao": "Protocolo de comunicação sem fio de ultra-baixa latência desenvolvido pela Espressif, operando na faixa de 2.4 GHz sem a necessidade de um roteador Wi-Fi tradicional.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Protocolo de Rede & Mesh",
|
||||
"funcao_principal": "Troca de mensagens ponto-a-ponto, broadcast e formação de redes em malha leves entre dezenas de placas ESP32",
|
||||
"caracteristicas": [
|
||||
"Comunicação direta sem roteador ou ponto de acesso (AP)",
|
||||
"Latência de transmissão de milissegundos e conexão instantânea",
|
||||
"Criptografia nativa com chaves de chaveamento AES-128",
|
||||
"Extremamente econômico em energia, ideal para nós alimentados por bateria",
|
||||
"Capacidade de emparelhamento por controle remoto e broadcast para múltiplos nós",
|
||||
"Suporte ao Mesh-Lite para roteamento em malha com salto IP"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Controles remotos sem fio e interruptores de parede a bateria",
|
||||
"Redes de sensores agrícolas distribuídas no campo",
|
||||
"Sincronização em tempo real de iluminação cênica e drones",
|
||||
"Alarmes e botões de pânico residenciais"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-now.c",
|
||||
"exemplos": "https://github.com/espressif/esp-now/tree/master/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_now.html",
|
||||
"repositorio": "https://github.com/espressif/esp-now",
|
||||
"cor": "#8B5CF6"
|
||||
},
|
||||
"ESP-Zigbee-SDK": {
|
||||
"nome": "ESP-Zigbee-SDK",
|
||||
"icone": "🐝",
|
||||
"nome_completo": "ESP Zigbee SDK (ZCL & ZBOSS)",
|
||||
"descricao": "SDK oficial para desenvolvimento de nós, roteadores e coordenadores Zigbee 3.0 nos SoCs ESP32 com suporte ao rádio 802.15.4 (como ESP32-H2 e ESP32-C6).",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Smart Home & Mesh",
|
||||
"funcao_principal": "Construção de redes de automação predial ultraleves e de baixíssimo consumo energético baseadas no padrão Zigbee 3.0",
|
||||
"caracteristicas": [
|
||||
"Implementação certificada Zigbee 3.0 baseada na stack ZBOSS",
|
||||
"Suporte a papéis de Coordenador (ZC), Roteador (ZR) e Dispositivo Final (ZED / Sleepy End Device)",
|
||||
"Biblioteca rica de clusters ZCL (On/Off, Nível, Cor, Temperatura, Medição de Energia)",
|
||||
"Consumo em microampères durante sono profundo para sensores operando por anos a bateria",
|
||||
"Compatibilidade nativa com pontes Zigbee (Home Assistant ZHA/Zigbee2MQTT, Philips Hue)"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Sensores de presença, porta/janela e vazamento operando a pilha botão",
|
||||
"Lâmpadas e tomadas inteligentes na rede Zigbee 3.0",
|
||||
"Gateways e pontes Zigbee-para-Wi-Fi ou Zigbee-para-Ethernet",
|
||||
"Automação predial comercial com alta densidade de nós"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-zigbee.c",
|
||||
"exemplos": "https://github.com/espressif/esp-zigbee-sdk/tree/main/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-zigbee-sdk/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/esp-zigbee-sdk",
|
||||
"cor": "#EC4899"
|
||||
},
|
||||
"ESP-WHO": {
|
||||
"nome": "ESP-WHO",
|
||||
"icone": "📷",
|
||||
"nome_completo": "ESP Image Processing & Vision Framework",
|
||||
"descricao": "Framework da Espressif para processamento de imagens e visão computacional na borda (Edge Vision) com câmeras conectadas ao ESP32.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Visão Computacional & IA",
|
||||
"funcao_principal": "Detecção de rostos, identificação biométrica, detecção de pessoas e processamento de stream de vídeo",
|
||||
"caracteristicas": [
|
||||
"Detecção de faces em tempo real e extração de marcos faciais (Landmarks)",
|
||||
"Reconhecimento facial local com banco de dados de usuários cadastrados",
|
||||
"Detecção de presença humana e contagem de pessoas (Human Detection)",
|
||||
"Otimizado para ESP32-S3 e ESP32-P4 com instruções vetoriais de IA",
|
||||
"Suporte a sensores de câmera DVP e MIPI-CSI (OV2640, OV3660, OV5640, SC030IOT)"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Controle de acesso por biometria facial",
|
||||
"Campainhas e câmeras de segurança inteligentes (Smart Doorbells)",
|
||||
"Sensores inteligentes de ocupação de salas e escritórios",
|
||||
"Robôs seguidores de pessoas e brinquedos interativos"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-who.c",
|
||||
"exemplos": "https://github.com/espressif/esp-who/tree/master/examples",
|
||||
"documentacao": "https://github.com/espressif/esp-who",
|
||||
"repositorio": "https://github.com/espressif/esp-who",
|
||||
"cor": "#F97316"
|
||||
},
|
||||
"ESP-NN": {
|
||||
"nome": "ESP-NN",
|
||||
"icone": "🧠",
|
||||
"nome_completo": "ESP Neural Network Acceleration Library",
|
||||
"descricao": "Biblioteca de kernels e operações de redes neurais altamente otimizada para as arquiteturas Xtensa e RISC-V dos chips ESP32.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Biblioteca Especializada de IA",
|
||||
"funcao_principal": "Aceleração de inferência de redes neurais profundas com quantização INT8 e INT16 aproveitando as instruções SIMD vetoriais",
|
||||
"caracteristicas": [
|
||||
"Operações otimizadas: Convolução 2D, Depthwise Conv, Fully Connected e Pooling",
|
||||
"Backend acelerador oficial integrado ao TensorFlow Lite for Microcontrollers (TFLM)",
|
||||
"Quantização eficiente de 8 e 16 bits para redução drástica de uso de RAM e Flash",
|
||||
"Aceleração extrema no ESP32-S3 e ESP32-P4 usando instruções vetoriais dedicadas",
|
||||
"Execução sem overhead de sistema operacional em tempo real"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Classificação de áudio e sinais de vibração industrial (manutenção preditiva)",
|
||||
"Detecção de anomalias em sensores por modelos TinyML",
|
||||
"Reconhecimento de gestos por IMU",
|
||||
"Visão computacional ultraleve em microcontroladores"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-nn.c",
|
||||
"exemplos": "https://github.com/espressif/esp-nn/tree/master/test_app",
|
||||
"documentacao": "https://github.com/espressif/esp-nn",
|
||||
"repositorio": "https://github.com/espressif/esp-nn",
|
||||
"cor": "#14B8A6"
|
||||
},
|
||||
"ESP-DSP": {
|
||||
"nome": "ESP-DSP",
|
||||
"icone": "📊",
|
||||
"nome_completo": "ESP Digital Signal Processing Library",
|
||||
"descricao": "Biblioteca oficial de processamento digital de sinais para a família ESP32, fornecendo algoritmos matemáticos acelerados em hardware.",
|
||||
"linguagem": "C / C++",
|
||||
"tipo": "Biblioteca Especializada de Sinais",
|
||||
"funcao_principal": "Execução de cálculos matemáticos pesados como FFT, transformadas, filtragem digital e operações matriciais com máxima velocidade",
|
||||
"caracteristicas": [
|
||||
"Transformadas Rápidas de Fourier (FFT real e complexa) otimizadas em Assembly",
|
||||
"Filtros digitais IIR, FIR e estimadores de Kalman",
|
||||
"Operações com matrizes, vetores e produtos escalares",
|
||||
"Suporte a números de ponto flutuante e ponto fixo (Radix-2 e Radix-4)",
|
||||
"Otimizações personalizadas para arquiteturas Xtensa Dual-Core e RISC-V"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Análise espectral de áudio e vibrações em tempo real",
|
||||
"Filtros anti-ruído para sensores biomédicos (ECG/EMG) e industriais",
|
||||
"Controle de motores de alta precisão e algoritmos FOC",
|
||||
"Compressão e codificação de dados na borda"
|
||||
],
|
||||
"exemplo": "/exemplos/esp-dsp.c",
|
||||
"exemplos": "https://github.com/espressif/esp-dsp/tree/master/examples",
|
||||
"documentacao": "https://docs.espressif.com/projects/esp-dsp/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/esp-dsp",
|
||||
"cor": "#A855F7"
|
||||
},
|
||||
"Rust-ESP": {
|
||||
"nome": "Rust on ESP32",
|
||||
"icone": "🦀",
|
||||
"nome_completo": "ESP-RS Rust Ecosystem for ESP32",
|
||||
"descricao": "Ecossistema moderno de desenvolvimento em linguagem Rust para a família ESP32, combinando segurança de memória (Memory Safety), concorrência robusta e alto desempenho.",
|
||||
"linguagem": "Rust",
|
||||
"tipo": "Linguagem & Framework Moderno",
|
||||
"funcao_principal": "Desenvolvimento de firmware seguro e de alta performance tanto em modo bare-metal (no_std via esp-hal) quanto com a pilha completa (std via esp-idf-svc)",
|
||||
"caracteristicas": [
|
||||
"Modo Bare-Metal `no_std` com a biblioteca `esp-hal`: controle total sem RTOS e boot ultrarrápido",
|
||||
"Modo `std` com `esp-idf-svc`: acesso à biblioteca padrão do Rust, Wi-Fi, BLE, HTTP, MQTT e threads",
|
||||
"Prevenção garantida em tempo de compilação contra corrupção de memória e Data Races",
|
||||
"Suporte a targets Xtensa (ESP32, S2, S3) e RISC-V nativo (C2, C3, C6, H2, P4)",
|
||||
"Integração com ecossistema de crates `embedded-hal` e async/await com `embassy`",
|
||||
"Ferramentas oficiais: `espflash` para gravação e monitor serial e `esp-generate` para templates"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Sistemas críticos onde falhas de memória (Null Pointer, Buffer Overflow) são inaceitáveis",
|
||||
"Aplicações IoT modernas com concorrência assíncrona limpa",
|
||||
"Dispositivos industriais que exigem segurança de alto nível",
|
||||
"Projetos modernos de robótica e instrumentação"
|
||||
],
|
||||
"exemplo": "/exemplos/rust-esp.rs",
|
||||
"exemplos": "https://github.com/esp-rs/esp-hal/tree/main/examples",
|
||||
"documentacao": "https://esp-rs.github.io/book/",
|
||||
"repositorio": "https://github.com/esp-rs",
|
||||
"cor": "#E44D26"
|
||||
},
|
||||
"Arduino": {
|
||||
"nome": "Arduino Core",
|
||||
"icone": "🛠️",
|
||||
"nome_completo": "Arduino Core for ESP32",
|
||||
"descricao": "Implementação oficial do framework Arduino sobre o ESP-IDF (versões 3.x+ baseadas em ESP-IDF v5.1+), combinando extrema facilidade com os recursos avançados do ESP32.",
|
||||
"linguagem": "C++",
|
||||
"tipo": "Framework Alternativo Popular",
|
||||
"funcao_principal": "Prototipagem rápida, projetos educacionais e desenvolvimento acelerado aproveitando o vasto ecossistema de bibliotecas Arduino",
|
||||
"caracteristicas": [
|
||||
"Sintaxe clássica `setup()` e `loop()` com centenas de milhares de bibliotecas compatíveis",
|
||||
"Execução como uma tarefa FreeRTOS sobre o ESP-IDF oficial",
|
||||
"Suporte completo a Wi-Fi, Bluetooth Classic/BLE, WebServer e WebSockets",
|
||||
"Compatibilidade com Arduino IDE 2.x, PlatformIO e VS Code",
|
||||
"Suporte atualizado a todos os SoCs populares (ESP32, S2, S3, C3, C6)",
|
||||
"Acesso a funções nativas do ESP-IDF quando necessário"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Prototipagem rápida e validação de conceitos (PoC)",
|
||||
"Projetos educacionais, makers e acadêmicos",
|
||||
"Sistemas IoT simples com dashboards (Blynk, Adafruit IO, ThingSpeak)",
|
||||
"Robótica amadora e automação residencial faça-você-mesmo (DIY)"
|
||||
],
|
||||
"exemplo": "/exemplos/arduino.ino",
|
||||
"exemplos": "https://github.com/espressif/arduino-esp32/tree/master/docs/en/tutorials",
|
||||
"documentacao": "https://docs.espressif.com/projects/arduino-esp32/en/latest/",
|
||||
"repositorio": "https://github.com/espressif/arduino-esp32",
|
||||
"cor": "#00979D"
|
||||
},
|
||||
"MicroPython": {
|
||||
"nome": "MicroPython",
|
||||
"icone": "🐍",
|
||||
"nome_completo": "MicroPython for ESP32",
|
||||
"descricao": "Implementação enxuta e eficiente da linguagem Python 3 otimizada para rodar diretamente na CPU do ESP32 com interpretador em tempo real.",
|
||||
"linguagem": "Python",
|
||||
"tipo": "Linguagem & Interpretador Dinâmico",
|
||||
"funcao_principal": "Desenvolvimento interativo e prototipagem ágil em Python com console REPL interativo e manipulação instantânea de hardware",
|
||||
"caracteristicas": [
|
||||
"Interpretador Python 3 completo com compilação para bytecode em RAM",
|
||||
"Console interativo REPL via porta serial e WebREPL via Wi-Fi",
|
||||
"Sistema de arquivos integrado (LittleFS / FAT) com upload de scripts `.py` sem recompilar",
|
||||
"Módulos nativos `machine`, `network`, `bluetooth`, `espnow` e `asyncio`",
|
||||
"Excelente para ensinar programação e algoritmos com hardware real"
|
||||
],
|
||||
"casos_uso": [
|
||||
"Ensino de computação física e laboratórios universitários",
|
||||
"Prototipagem ágil e testes rápidos de sensores em bancada",
|
||||
"Scripts de automação de testes de bancada",
|
||||
"Aplicações experimentais de coleta de dados IoT"
|
||||
],
|
||||
"exemplo": "/exemplos/micropython.py",
|
||||
"exemplos": "https://github.com/micropython/micropython/tree/master/examples",
|
||||
"documentacao": "https://docs.micropython.org/en/latest/esp32/",
|
||||
"repositorio": "https://github.com/micropython/micropython",
|
||||
"cor": "#2B2B2B"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,732 @@
|
||||
{
|
||||
"ESP32": {
|
||||
"nome_completo": "ESP32 (Clássico)",
|
||||
"icone": "🔷",
|
||||
"descricao": "O modelo original com processador dual-core e ampla gama de periféricos",
|
||||
"arquitetura": "Xtensa® LX6 dual-core de 32 bits",
|
||||
"nucleos": "1 (Single-core) ou 2 (Dual-core)",
|
||||
"frequencia": "Até 240 MHz",
|
||||
"coprocessador_ulp": "Sim",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/192/256",
|
||||
"sha": "SHA-1/256/384/512",
|
||||
"rsa": "Sim (RSA/MPI até 4096 bits)",
|
||||
"ecc": "Não",
|
||||
"ecdsa": "Não",
|
||||
"hmac": "Não",
|
||||
"assinatura_digital": "Não",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "Sim (AES-256, esquema legado)",
|
||||
"secure_boot": "V1 (AES, legado); V2 (RSA-3072, RSA-PSS) a partir da revisão v3.0 (ECO3)",
|
||||
"protecao_dpa": "Não"
|
||||
},
|
||||
"wifi": "IEEE 802.11 b/g/n (2.4 GHz, até 150 Mbps)",
|
||||
"bluetooth": "Bluetooth 4.2 BR/EDR (Clássico) e Bluetooth LE (dual mode)",
|
||||
"ethernet": "Sim (Ethernet MAC integrado)",
|
||||
"memoria_sram": "520 KB",
|
||||
"memoria_sram_rtc": "16 KB (dividida em RTC FAST e RTC SLOW)",
|
||||
"memoria_rom": "448 KB (para boot e funções core)",
|
||||
"flash_externa": "Até 16 MB via QSPI",
|
||||
"psram_externa": "Até 8 MB via QSPI (em módulos específicos como WROVER)",
|
||||
"gpio": "34",
|
||||
"adc": "2x SAR ADC de 12 bits, até 18 canais",
|
||||
"dac": "2x DAC de 8 bits",
|
||||
"touch": "10 canais capacitivos",
|
||||
"uart": "3",
|
||||
"spi": "4 (SPI, HSPI, VSPI - 2 podem ser usados para Flash/PSRAM)",
|
||||
"i2c": "2",
|
||||
"i2s": "2",
|
||||
"pwm": "LED PWM (até 16 canais), Motor PWM",
|
||||
"ethernet_mac": "1 (requer PHY externo)",
|
||||
"can": "1 (CAN 2.0, TWAI®)",
|
||||
"sdio": "1 (SD/SDIO/MMC Host), 1 (SDIO/SPI Slave)",
|
||||
"sensor_hall": "1 (interno)",
|
||||
"sensor_temperatura": "Não (retirado do datasheet em 2018; sem driver no ESP-IDF)",
|
||||
"consumo_energia": {
|
||||
"active_cpu_240mhz": "30-68 mA",
|
||||
"active_wifi_tx": "180-240 mA",
|
||||
"modem_sleep": "20-44 mA",
|
||||
"light_sleep": "0.8 mA",
|
||||
"deep_sleep": "10-150 µA",
|
||||
"hibernation": "5 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 125°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG externo (requer sonda, ex.: ESP-PROG)",
|
||||
"esp_idf_minimo": "Desde o início (v3.x e anteriores)",
|
||||
"arduino_core": "Sim (147 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN48 (6×6 mm) e QFN48 (5×5 mm)",
|
||||
"modulos": "ESP32-MINI-1, ESP32-PICO-MINI-02, ESP32-PICO-V3, ESP32-PICO-V3-02 e mais 11",
|
||||
"datasheet": "https://documentation.espressif.com/esp32_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/index.html",
|
||||
"placa": "/placas/esp32.png",
|
||||
"cor": "#007bff"
|
||||
},
|
||||
"ESP32-S2": {
|
||||
"nome_completo": "ESP32-S2",
|
||||
"icone": "🔒",
|
||||
"descricao": "Foco em segurança e baixo consumo, com USB nativo e o único ADC com saída de 13 bits",
|
||||
"arquitetura": "Xtensa® LX7 single-core de 32 bits",
|
||||
"nucleos": "1 (Single-core)",
|
||||
"frequencia": "Até 240 MHz",
|
||||
"coprocessador_ulp": "Sim (RISC-V)",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/192/256 com GCM",
|
||||
"sha": "SHA-1/224/256/384/512",
|
||||
"rsa": "Sim (RSA/MPI até 4096 bits)",
|
||||
"ecc": "Não",
|
||||
"ecdsa": "Não",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128/256",
|
||||
"secure_boot": "V2 (RSA-3072)",
|
||||
"protecao_dpa": "Não"
|
||||
},
|
||||
"wifi": "IEEE 802.11 b/g/n (2.4 GHz, até 150 Mbps)",
|
||||
"bluetooth": "Não",
|
||||
"memoria_sram": "320 KB",
|
||||
"memoria_sram_rtc": "16 KB",
|
||||
"memoria_rom": "128 KB",
|
||||
"flash_externa": "Até 1 GB via QSPI",
|
||||
"psram_externa": "Até 1 GB via QSPI/Octal SPI",
|
||||
"gpio": "43",
|
||||
"adc": "2x SAR ADC, até 20 canais: saída de 13 bits (0–8191, única da família), resolução efetiva de 12 bits a partir da revisão v1.0 (errata ADC-112)",
|
||||
"dac": "2x DAC de 8 bits",
|
||||
"touch": "14 canais capacitivos",
|
||||
"uart": "2",
|
||||
"spi": "4 (SPI0/1 para Flash, SPI2/3 para uso geral)",
|
||||
"i2c": "2",
|
||||
"i2s": "1",
|
||||
"pwm": "LED PWM (até 8 canais)",
|
||||
"usb": "1 (USB OTG 1.1 Full-Speed)",
|
||||
"lcd": "Interface LCD de 8/16 bits",
|
||||
"camera": "Interface DVP de 8/16 bits",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active_wifi_tx": "160-310 mA",
|
||||
"modem_sleep_cpu_160mhz": "14-24 mA",
|
||||
"light_sleep": "750 µA",
|
||||
"deep_sleep": "20-190 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG externo (requer sonda, ex.: ESP-PROG)",
|
||||
"esp_idf_minimo": "v4.2",
|
||||
"arduino_core": "Sim (26 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN56 (7×7 mm)",
|
||||
"modulos": "ESP32-S2-MINI-1, ESP32-S2-MINI-2, ESP32-S2-SOLO, ESP32-S2-SOLO-2 e mais 4",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-s2_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-s2_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/get-started/index.html",
|
||||
"placa": "/placas/esp32-s2.png",
|
||||
"cor": "#28a745"
|
||||
},
|
||||
"ESP32-S3": {
|
||||
"nome_completo": "ESP32-S3",
|
||||
"icone": "🤖",
|
||||
"descricao": "Processador dual-core com aceleradores para IA e processamento de sinal",
|
||||
"arquitetura": "Xtensa® LX7 dual-core de 32 bits",
|
||||
"nucleos": "2 (Dual-core)",
|
||||
"frequencia": "Até 240 MHz",
|
||||
"coprocessador_ulp": "Sim (RISC-V)",
|
||||
"aceleradores_ia": "Sim (Vector Instructions para IA)",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256",
|
||||
"sha": "SHA-1/224/256/384/512",
|
||||
"rsa": "Sim (RSA/MPI até 4096 bits)",
|
||||
"ecc": "Não",
|
||||
"ecdsa": "Não",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128/256",
|
||||
"secure_boot": "V2 (RSA-3072)",
|
||||
"protecao_dpa": "Não"
|
||||
},
|
||||
"wifi": "IEEE 802.11 b/g/n (2.4 GHz, até 150 Mbps)",
|
||||
"bluetooth": "Bluetooth 5 (LE) e Bluetooth Mesh",
|
||||
"memoria_sram": "512 KB",
|
||||
"memoria_sram_rtc": "16 KB",
|
||||
"memoria_rom": "384 KB",
|
||||
"flash_externa": "Até 1 GB via QSPI/Octal SPI",
|
||||
"psram_externa": "Até 1 GB via QSPI/Octal SPI",
|
||||
"gpio": "45",
|
||||
"adc": "2x SAR ADC de 12 bits, até 20 canais",
|
||||
"dac": "Não",
|
||||
"touch": "14 canais capacitivos",
|
||||
"uart": "3",
|
||||
"spi": "4 (SPI0/1 para Flash, SPI2/3 para uso geral)",
|
||||
"i2c": "2",
|
||||
"i2s": "2",
|
||||
"pwm": "LED PWM (até 8 canais), Motor PWM (6 canais)",
|
||||
"usb": "1 (USB OTG 1.1 Full-Speed) + 1 (USB Serial/JTAG)",
|
||||
"lcd": "Interface LCD RGB de 8/16 bits",
|
||||
"camera": "Interface DVP de 8/16 bits",
|
||||
"sdio": "1 (SD/SDIO/MMC Host)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active": "78 mW (~24 mA @3.3V)",
|
||||
"modem_sleep": "13-42 mA (40-80 MHz, conforme a carga)",
|
||||
"light_sleep": "240 µA (+40 a 200 µA da PSRAM)",
|
||||
"deep_sleep": "7 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 65/85/105°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v4.4",
|
||||
"arduino_core": "Sim (158 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN56 (7×7 mm)",
|
||||
"modulos": "ESP32-S3-MINI-1, ESP32-S3-WROOM-1, ESP32-S3-WROOM-2",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-s3_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-s3_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/get-started/index.html",
|
||||
"placa": "/placas/esp32-s3.png",
|
||||
"cor": "#fd7e14"
|
||||
},
|
||||
"ESP32-S31": {
|
||||
"nome_completo": "ESP32-S31",
|
||||
"icone": "🌀",
|
||||
"descricao": "Processador dual-core RISC-V de alta performance a 320MHz com Wi-Fi 6, Bluetooth 5.4 e Classic, Zigbee/Thread, Matter e aceleração IA",
|
||||
"arquitetura": "RISC-V dual-core de 32 bits (HP) + RISC-V single-core (LP)",
|
||||
"nucleos": "2 (Dual-core HP) + 1 (Single-core LP)",
|
||||
"frequencia": "Até 320 MHz",
|
||||
"coprocessador_ulp": "Sim (RISC-V, LP CPU de 40 MHz)",
|
||||
"aceleradores_ia": "Sim (Custom AI and DSP extension XespV)",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256 com GCM",
|
||||
"sha": "SHA-1/224/256/384/512",
|
||||
"rsa": "Sim (RSA/MPI até 4096 bits)",
|
||||
"ecc": "Sim (P-192, P-256, P-384)",
|
||||
"ecdsa": "Sim (modo determinístico, RFC 6979)",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Sim",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128/256",
|
||||
"secure_boot": "V2 (RSA-3072)",
|
||||
"protecao_dpa": "Sim"
|
||||
},
|
||||
"wifi": "Wi-Fi 6 (802.11ax) 2.4 GHz",
|
||||
"bluetooth": "Bluetooth 5.4 LE e Bluetooth Classic",
|
||||
"zigbee_thread": "IEEE 802.15.4 (Zigbee 3.0, Thread 1.4)",
|
||||
"matter": "Sim",
|
||||
"memoria_sram": "512 KB (HP SRAM)",
|
||||
"memoria_sram_rtc": "32 KB (LP SRAM)",
|
||||
"memoria_rom": "320 KB",
|
||||
"flash_externa": "Até 256 MB via QSPI",
|
||||
"psram_externa": "16 MB ou 32 MB octal DDR, só dentro do encapsulamento (NRV16, NRV32)",
|
||||
"gpio": "60",
|
||||
"adc": "2x SAR ADC de 12 bits, até 16 canais",
|
||||
"dac": "Sim (2x DAC de 10 bits e 2x DAC de 12 bits)",
|
||||
"touch": "14 canais capacitivos",
|
||||
"uart": "5 (4 UART + 1 LP UART)",
|
||||
"spi": "7 (6 SPI + 1 LP SPI)",
|
||||
"i2c": "3 (2 I2C + 1 LP I2C)",
|
||||
"i2s": "2",
|
||||
"pwm": "LED PWM (até 8 canais), Motor PWM (MCPWM)",
|
||||
"usb": "1 (USB 2.0 High-Speed OTG e USB Serial/JTAG)",
|
||||
"can": "Sim (CAN FD Controller)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active": "Consumo otimizado de alta performance configurável",
|
||||
"light_sleep": "0.1-0.8 mA",
|
||||
"deep_sleep": "Baixo consumo com LP CPU ativa"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 85°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v6.1 em preview; suporte oficial a partir da v6.1.1",
|
||||
"arduino_core": "Ainda não suportado pelo core arduino-esp32",
|
||||
"encapsulamento": "QFN80 (8×8 mm)",
|
||||
"modulos": "ESP32-S31-WROOM-1, ESP32-S31-WROOM-3",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-s31_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-s31_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s31/get-started/index.html",
|
||||
"placa": "/placas/esp32-s31.png",
|
||||
"cor": "#ff2a5f",
|
||||
"sdio": "1 (SDIO Host 3.0)"
|
||||
},
|
||||
"ESP32-C2": {
|
||||
"nome_completo": "ESP32-C2 (ESP8684)",
|
||||
"icone": "🌱",
|
||||
"descricao": "Microcontrolador RISC-V ultra econômico e de baixo consumo com Wi-Fi 4 e Bluetooth 5.3 LE",
|
||||
"arquitetura": "RISC-V single-core de 32 bits",
|
||||
"nucleos": "1 (Single-core)",
|
||||
"frequencia": "Até 120 MHz",
|
||||
"seguranca": {
|
||||
"aes": "Não",
|
||||
"sha": "SHA-1/224/256",
|
||||
"rsa": "Não",
|
||||
"ecc": "Sim (P-192, P-256)",
|
||||
"ecdsa": "Não",
|
||||
"hmac": "Não",
|
||||
"assinatura_digital": "Não",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128",
|
||||
"secure_boot": "V2 (ECDSA P-192 ou P-256)",
|
||||
"protecao_dpa": "Não"
|
||||
},
|
||||
"wifi": "IEEE 802.11 b/g/n (2.4 GHz, até 72.2 Mbps)",
|
||||
"bluetooth": "Bluetooth 5.3 LE (certificado)",
|
||||
"memoria_sram": "272 KB (16 KB para cache)",
|
||||
"memoria_sram_rtc": "Não",
|
||||
"memoria_rom": "576 KB",
|
||||
"flash_externa": "Até 16 MB via QSPI, mas indisponível nas variantes vendidas (ESP8684H2X/H4X têm 2 MB ou 4 MB no encapsulamento e não expõem os pinos de flash)",
|
||||
"psram_externa": "Não",
|
||||
"gpio": "14",
|
||||
"adc": "1x SAR ADC de 12 bits, até 5 canais",
|
||||
"dac": "Não",
|
||||
"touch": "Não",
|
||||
"uart": "2",
|
||||
"spi": "3 (SPI0/1 para Flash interna, SPI2 para uso geral)",
|
||||
"i2c": "1 (Master-only)",
|
||||
"i2s": "Não",
|
||||
"pwm": "LED PWM (até 6 canais)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active_cpu_120mhz": "10,7-15,6 mA (modem-sleep)",
|
||||
"light_sleep": "140 µA",
|
||||
"deep_sleep": "5 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG externo (requer sonda, ex.: ESP-PROG)",
|
||||
"esp_idf_minimo": "v5.0",
|
||||
"arduino_core": "Sim (1 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN24 (4×4 mm)",
|
||||
"modulos": "ESP8684-MINI-1, ESP8684-WROOM-01C, ESP8684-WROOM-02C, ESP8684-WROOM-02UC e mais 5",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-c2_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-c2_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/get-started/index.html",
|
||||
"placa": "/placas/esp32-c2.png",
|
||||
"cor": "#8c52ff"
|
||||
},
|
||||
"ESP32-C3": {
|
||||
"nome_completo": "ESP32-C3",
|
||||
"icone": "💎",
|
||||
"descricao": "Processador RISC-V de ultra baixo consumo",
|
||||
"arquitetura": "RISC-V single-core de 32 bits",
|
||||
"nucleos": "1 (Single-core)",
|
||||
"frequencia": "Até 160 MHz",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256",
|
||||
"sha": "SHA-1/224/256",
|
||||
"rsa": "Sim (RSA/MPI até 3072 bits)",
|
||||
"ecc": "Não",
|
||||
"ecdsa": "Não",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128",
|
||||
"secure_boot": "V2 (RSA-3072), a partir da revisão v0.3 (ECO3)",
|
||||
"protecao_dpa": "Não"
|
||||
},
|
||||
"wifi": "IEEE 802.11 b/g/n (2.4 GHz, até 150 Mbps)",
|
||||
"bluetooth": "Bluetooth 5 (LE) e Bluetooth Mesh",
|
||||
"memoria_sram": "400 KB",
|
||||
"memoria_sram_rtc": "8 KB",
|
||||
"memoria_rom": "384 KB",
|
||||
"flash_externa": "Até 16 MB via QSPI",
|
||||
"psram_externa": "Não",
|
||||
"gpio": "22",
|
||||
"adc": "2x SAR ADC de 12 bits, até 6 canais",
|
||||
"dac": "Não",
|
||||
"touch": "Não",
|
||||
"uart": "2",
|
||||
"spi": "3 (SPI0/1 para Flash, SPI2 para uso geral)",
|
||||
"i2c": "1",
|
||||
"i2s": "1",
|
||||
"pwm": "LED PWM (até 6 canais)",
|
||||
"usb": "1 (USB Serial/JTAG)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active_cpu_160mhz": "20 mA",
|
||||
"active_wifi_tx_peak": "335 mA",
|
||||
"modem_sleep_cpu_160mhz": "16-28 mA",
|
||||
"light_sleep": "130 µA",
|
||||
"deep_sleep": "5 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C (85°C no ESP32-C3FN4)",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v4.3",
|
||||
"arduino_core": "Sim (29 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN32 (5×5 mm) e QFN28 (4×4 mm)",
|
||||
"modulos": "ESP32-C3-MINI-1, ESP32-C3-WROOM-02",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-c3_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-c3_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/get-started/index.html",
|
||||
"placa": "/placas/esp32-c3.png",
|
||||
"cor": "#20c997"
|
||||
},
|
||||
"ESP32-C5": {
|
||||
"nome_completo": "ESP32-C5",
|
||||
"icone": "📶",
|
||||
"descricao": "O primeiro com suporte a Wi-Fi 6 dual-band e Bluetooth 6.0, equipado com CPU RISC-V e coprocessador ULP",
|
||||
"arquitetura": "RISC-V single-core de 32 bits (HP) + RISC-V single-core (LP)",
|
||||
"nucleos": "1 (Single-core HP) + 1 (Single-core LP)",
|
||||
"frequencia": "Até 240 MHz",
|
||||
"coprocessador_ulp": "Sim (RISC-V, LP CPU de 48 MHz)",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256",
|
||||
"sha": "SHA-1/224/256/384/512",
|
||||
"rsa": "Sim (RSA/MPI até 3072 bits)",
|
||||
"ecc": "Sim (P-192, P-256, P-384)",
|
||||
"ecdsa": "Sim (modo determinístico, RFC 6979)",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Sim",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128/256",
|
||||
"secure_boot": "V2 (RSA-3072 ou ECDSA P-256/P-384)",
|
||||
"protecao_dpa": "Sim"
|
||||
},
|
||||
"wifi": "Wi-Fi 6 (802.11ax) dual-band 2.4 GHz e 5 GHz",
|
||||
"bluetooth": "Bluetooth 5 (LE) (Bluetooth Core 6.0 certificado)",
|
||||
"zigbee_thread": "IEEE 802.15.4 (Zigbee 3.0, Thread 1.4)",
|
||||
"matter": "Sim",
|
||||
"memoria_sram": "384 KB",
|
||||
"memoria_sram_rtc": "16 KB",
|
||||
"memoria_rom": "320 KB",
|
||||
"flash_externa": "Até 16 MB via QSPI",
|
||||
"psram_externa": "Sim, via SPI (controlador de flash/PSRAM com cache)",
|
||||
"gpio": "29",
|
||||
"adc": "1x SAR ADC de 12 bits, até 6 canais",
|
||||
"dac": "Não",
|
||||
"touch": "Não",
|
||||
"uart": "3 (2 UART + 1 LP UART)",
|
||||
"spi": "3",
|
||||
"i2c": "2 (1 I2C + 1 LP I2C)",
|
||||
"i2s": "1",
|
||||
"pwm": "LED PWM (até 6 canais), Motor PWM",
|
||||
"usb": "1 (USB Serial/JTAG)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active_wifi": "até 377 mA (TX em 5 GHz)",
|
||||
"light_sleep": "60-250 µA",
|
||||
"deep_sleep": "12 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v5.5.2",
|
||||
"arduino_core": "Sim (10 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN48 (6×6 mm)",
|
||||
"modulos": "ESP32-C5-MINI-1, ESP32-C5-WROOM-1",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-c5_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-c5_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c5/get-started/index.html",
|
||||
"placa": "/placas/esp32-c5.png",
|
||||
"cor": "#6f42c1",
|
||||
"sdio": "1 (SDIO Slave, a partir da revisão v1.0)",
|
||||
"can": "2 (CAN FD)"
|
||||
},
|
||||
"ESP32-C6": {
|
||||
"nome_completo": "ESP32-C6",
|
||||
"icone": "🌐",
|
||||
"descricao": "Recursos de segurança avançada, Wi-Fi 6, Bluetooth 6.0, Zigbee e Thread com suporte a Matter",
|
||||
"arquitetura": "RISC-V single-core de 32 bits (HP) + RISC-V single-core (LP)",
|
||||
"nucleos": "1 (Single-core HP) + 1 (Single-core LP)",
|
||||
"frequencia": "Até 160 MHz",
|
||||
"coprocessador_ulp": "Sim (RISC-V, LP CPU de 20 MHz)",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256",
|
||||
"sha": "SHA-1/224/256",
|
||||
"rsa": "Sim (RSA/MPI até 3072 bits)",
|
||||
"ecc": "Sim (P-192, P-256)",
|
||||
"ecdsa": "Não",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128",
|
||||
"secure_boot": "V2 (RSA-3072 ou ECDSA)",
|
||||
"protecao_dpa": "Sim"
|
||||
},
|
||||
"wifi": "Wi-Fi 6 (802.11ax) 2.4 GHz",
|
||||
"bluetooth": "Bluetooth 5 (LE) (Bluetooth 5.3 certificado)",
|
||||
"zigbee_thread": "IEEE 802.15.4 (Zigbee 3.0, Thread 1.3)",
|
||||
"matter": "Sim",
|
||||
"memoria_sram": "512 KB",
|
||||
"memoria_sram_rtc": "16 KB",
|
||||
"memoria_rom": "320 KB",
|
||||
"flash_externa": "Até 16 MB via QSPI",
|
||||
"psram_externa": "Não",
|
||||
"gpio": "30",
|
||||
"adc": "1x SAR ADC de 12 bits, até 7 canais",
|
||||
"dac": "Não",
|
||||
"touch": "Não",
|
||||
"uart": "3 (2 UART + 1 LP UART)",
|
||||
"spi": "3",
|
||||
"i2c": "2 (1 I2C + 1 LP I2C)",
|
||||
"i2s": "1",
|
||||
"pwm": "LED PWM (até 6 canais), Motor PWM",
|
||||
"usb": "1 (USB Serial/JTAG)",
|
||||
"sdio": "1 (SDIO 2.0 Slave)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active_wifi6": "252-354 mA (TX)",
|
||||
"light_sleep": "35-180 µA",
|
||||
"deep_sleep": "7 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v5.1",
|
||||
"arduino_core": "Sim (21 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN40 (5×5 mm) e QFN32 (5×5 mm)",
|
||||
"modulos": "ESP32-C6-MINI-1, ESP32-C6-WROOM-1",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-c6_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-c6_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/get-started/index.html",
|
||||
"placa": "/placas/esp32-c6.png",
|
||||
"cor": "#17a2b8"
|
||||
},
|
||||
"ESP32-C61": {
|
||||
"nome_completo": "ESP32-C61",
|
||||
"icone": "🛰️",
|
||||
"descricao": "Microcontrolador RISC-V econômico de 160MHz com Wi-Fi 6, Bluetooth 6.0 LE e suporte a Flash/PSRAM no encapsulamento",
|
||||
"arquitetura": "RISC-V single-core de 32 bits",
|
||||
"nucleos": "1 (Single-core)",
|
||||
"frequencia": "Até 160 MHz",
|
||||
"seguranca": {
|
||||
"aes": "Não",
|
||||
"sha": "SHA-1/224/256",
|
||||
"rsa": "Não",
|
||||
"ecc": "Sim (P-192, P-256)",
|
||||
"ecdsa": "Sim (modo determinístico, RFC 6979)",
|
||||
"hmac": "Não",
|
||||
"assinatura_digital": "Não",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128",
|
||||
"secure_boot": "V2 (ECDSA)",
|
||||
"protecao_dpa": "Sim"
|
||||
},
|
||||
"wifi": "Wi-Fi 6 (802.11ax) 2.4 GHz",
|
||||
"bluetooth": "Bluetooth 5 (LE) (Bluetooth Core 6.0 certificado)",
|
||||
"zigbee_thread": "Não",
|
||||
"matter": "Sim (via Wi-Fi)",
|
||||
"memoria_sram": "320 KB",
|
||||
"memoria_sram_rtc": "Não",
|
||||
"memoria_rom": "256 KB",
|
||||
"flash_externa": "Até 16 MB via QSPI (modelos com 4 MB ou 8 MB integrados no encapsulamento)",
|
||||
"psram_externa": "Até 16 MB via QSPI (modelos com 2 MB ou 8 MB integrados no encapsulamento)",
|
||||
"gpio": "30",
|
||||
"adc": "1x SAR ADC de 12 bits, até 4 canais",
|
||||
"dac": "Não",
|
||||
"touch": "Não",
|
||||
"uart": "3",
|
||||
"spi": "3 (2 para Flash/PSRAM, 1 para uso geral)",
|
||||
"i2c": "1",
|
||||
"i2s": "1",
|
||||
"pwm": "LED PWM (até 6 canais)",
|
||||
"usb": "1 (USB Serial/JTAG)",
|
||||
"sdio": "1 (SDIO 2.0 Slave)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active": "240-360 mA (TX)",
|
||||
"light_sleep": "50-200 µA",
|
||||
"deep_sleep": "10 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v5.5.2",
|
||||
"arduino_core": "Sim (1 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN40 (5×5 mm) ou LGA40 (5×5 mm)",
|
||||
"modulos": "ESP32-C61-MINI-1, ESP32-C61-WROOM-1",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-c61_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-c61_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c61/get-started/index.html",
|
||||
"placa": "/placas/esp32-c61.png",
|
||||
"cor": "#0dcaf0"
|
||||
},
|
||||
"ESP32-P4": {
|
||||
"nome_completo": "ESP32-P4",
|
||||
"icone": "⚡",
|
||||
"descricao": "Alto desempenho com processador RISC-V dual-core a 400MHz, aceleradores de IA e ricas interfaces de mídia",
|
||||
"arquitetura": "RISC-V de 32 bits dual-core de alto desempenho (HP) + single-core de baixo consumo (LP)",
|
||||
"nucleos": "2 (Dual-core HP) + 1 (Single-core LP)",
|
||||
"frequencia": "Até 400 MHz (HP, revisão v3.x; 360 MHz na v1.x); LP até 40 MHz",
|
||||
"coprocessador_ulp": "Sim (RISC-V, LP CPU de 40 MHz)",
|
||||
"aceleradores_ia": "Sim (Vector Instructions, aceleradores de IA)",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256 com GCM",
|
||||
"sha": "SHA-1/224/256/384/512",
|
||||
"rsa": "Sim (RSA/MPI até 4096 bits)",
|
||||
"ecc": "Sim (P-192, P-256, P-384)",
|
||||
"ecdsa": "Sim (modo determinístico, RFC 6979)",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Sim",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128/256",
|
||||
"secure_boot": "V2 (RSA-3072 ou ECDSA)",
|
||||
"protecao_dpa": "Não"
|
||||
},
|
||||
"wifi": "Não",
|
||||
"bluetooth": "Não",
|
||||
"ethernet": "Sim (Ethernet MAC integrado)",
|
||||
"memoria_sram": "768 KB",
|
||||
"memoria_sram_rtc": "32 KB",
|
||||
"memoria_rom": "128 KB (HP ROM) + 16 KB (LP ROM)",
|
||||
"flash_externa": "Até 128 MB via QSPI/Octal SPI",
|
||||
"psram_externa": "16 MB ou 32 MB integrados no encapsulamento (OPI/HPI, 1,8 V)",
|
||||
"gpio": "55",
|
||||
"adc": "2x SAR ADC de 12 bits, até 14 canais",
|
||||
"dac": "Não",
|
||||
"touch": "Sim (sensor de toque capacitivo)",
|
||||
"uart": "6 (5 UART + 1 LP UART)",
|
||||
"spi": "3",
|
||||
"i2c": "3 (2 I2C + 1 LP I2C)",
|
||||
"i2s": "4 (3 I2S + 1 LP I2S)",
|
||||
"pwm": "LED PWM (até 8 canais), Motor PWM (6 canais)",
|
||||
"usb": "USB 2.0 High-Speed OTG + USB 2.0 Full-Speed OTG + USB Serial/JTAG",
|
||||
"mipi_csi": "Interface MIPI CSI para câmera",
|
||||
"mipi_dsi": "Interface MIPI DSI para display",
|
||||
"lcd": "Interface LCD de 8/16/24 bits",
|
||||
"camera": "Interface DVP de 8/16 bits",
|
||||
"sdio": "1 controlador SD/MMC Host (SDHOST)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active": "15-150 mA (40 a 400 MHz, conforme a carga)",
|
||||
"light_sleep": "75-800 µA",
|
||||
"deep_sleep": "12 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 85°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v5.3",
|
||||
"arduino_core": "Sim (7 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN104 (10×10 mm)",
|
||||
"modulos": "Sem módulo no catálogo oficial (apenas o chip nu)",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-p4-chip-revision-v1.3_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-p4-chip-revision-v1.3_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32p4/get-started/index.html",
|
||||
"placa": "/placas/esp32-p4.png",
|
||||
"cor": "#ffc107"
|
||||
},
|
||||
"ESP32-H2": {
|
||||
"nome_completo": "ESP32-H2",
|
||||
"icone": "🔋",
|
||||
"descricao": "Focado em ultra-baixo consumo com Bluetooth 6.0, Zigbee e Thread. Mas sem suporte a Wi-Fi",
|
||||
"arquitetura": "RISC-V single-core de 32 bits",
|
||||
"nucleos": "1 (Single-core)",
|
||||
"frequencia": "Até 96 MHz",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256",
|
||||
"sha": "SHA-1/224/256",
|
||||
"rsa": "Sim (RSA/MPI até 3072 bits)",
|
||||
"ecc": "Sim (P-192, P-256)",
|
||||
"ecdsa": "Sim (modo determinístico, RFC 6979)",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Sim",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128",
|
||||
"secure_boot": "V2 (RSA-3072 ou ECDSA)",
|
||||
"protecao_dpa": "Sim"
|
||||
},
|
||||
"wifi": "Não",
|
||||
"bluetooth": "Bluetooth 5 (LE) (Bluetooth 5.3 certificado)",
|
||||
"zigbee_thread": "IEEE 802.15.4 (Zigbee 3.0, Thread 1.4)",
|
||||
"matter": "Sim",
|
||||
"memoria_sram": "320 KB",
|
||||
"memoria_sram_rtc": "4 KB (LP Memory)",
|
||||
"memoria_rom": "128 KB",
|
||||
"flash_externa": "Até 16 MB via QSPI",
|
||||
"psram_externa": "Não",
|
||||
"gpio": "19",
|
||||
"adc": "1x SAR ADC de 12 bits, até 5 canais",
|
||||
"dac": "Não",
|
||||
"touch": "Não",
|
||||
"uart": "2",
|
||||
"spi": "3",
|
||||
"i2c": "2",
|
||||
"i2s": "1",
|
||||
"pwm": "LED PWM (até 6 canais)",
|
||||
"usb": "1 (USB Serial/JTAG)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active": "24-140 mA (rádio, de -24 a 20 dBm)",
|
||||
"light_sleep": "25-85 µA",
|
||||
"deep_sleep": "7 µA"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C",
|
||||
"temperatura_armazenamento": "-40°C a 150°C",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v5.1",
|
||||
"arduino_core": "Sim (3 definições de placa no core oficial)",
|
||||
"encapsulamento": "QFN32 (4×4 mm)",
|
||||
"modulos": "ESP32-H2-MINI-1, ESP32-H2-WROOM-02C",
|
||||
"datasheet": "https://documentation.espressif.com/esp32-h2_datasheet_en.html",
|
||||
"manual_tecnico": "https://documentation.espressif.com/esp32-h2_technical_reference_manual_en.html",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32h2/get-started/index.html",
|
||||
"placa": "/placas/esp32-h2.png",
|
||||
"cor": "#6c757d"
|
||||
},
|
||||
"ESP32-H4": {
|
||||
"nome_completo": "ESP32-H4",
|
||||
"icone": "🛡️",
|
||||
"descricao": "SoC dual-core RISC-V de altíssima eficiência energética com Bluetooth 5.4 LE (LE Audio) e IEEE 802.15.4 para Thread, Zigbee e Matter. Sem Wi-Fi",
|
||||
"status_documentacao": "Documentação preliminar: a Espressif ainda não publicou o datasheet nem o manual técnico do ESP32-H4. Os dados abaixo vêm do anúncio oficial do produto e das definições de hardware (soc_caps) do ESP-IDF, e podem mudar até o lançamento.",
|
||||
"arquitetura": "RISC-V dual-core de 32 bits",
|
||||
"nucleos": "2 (Dual-core)",
|
||||
"frequencia": "Até 96 MHz",
|
||||
"seguranca": {
|
||||
"aes": "AES-128/256",
|
||||
"sha": "SHA-1/224/256/384/512",
|
||||
"rsa": "Não",
|
||||
"ecc": "Sim (P-192, P-256, P-384)",
|
||||
"ecdsa": "Sim (modo determinístico, RFC 6979)",
|
||||
"hmac": "Sim",
|
||||
"assinatura_digital": "Não",
|
||||
"key_manager": "Não",
|
||||
"rng": "Sim (TRNG por hardware)",
|
||||
"criptografia_flash": "XTS-AES-128/256",
|
||||
"secure_boot": "Sim no hardware; ainda não habilitado no ESP-IDF",
|
||||
"protecao_dpa": "Não"
|
||||
},
|
||||
"wifi": "Não",
|
||||
"bluetooth": "Bluetooth 5.4 LE (certificado Bluetooth 6.0; LE Audio, canais isócronos BIS/CIS, PAwR, Connection Subrating e Direction Finding AoA/AoD)",
|
||||
"zigbee_thread": "IEEE 802.15.4 (Zigbee 3.0, Thread 1.4)",
|
||||
"matter": "Sim",
|
||||
"memoria_sram": "384 KB",
|
||||
"memoria_sram_rtc": "Sim (LP SRAM)",
|
||||
"memoria_rom": "128 KB",
|
||||
"flash_externa": "Sim, via QSPI (4 MB integrada no encapsulamento no ESP32-H4HF4)",
|
||||
"psram_externa": "Sim (2 MB integrada no encapsulamento no ESP32-H4HR2)",
|
||||
"gpio": "40",
|
||||
"adc": "1x SAR ADC de 12 bits, até 5 canais",
|
||||
"dac": "Não",
|
||||
"touch": "15 canais capacitivos (versão 3, com waterproof e proximidade)",
|
||||
"uart": "2",
|
||||
"spi": "3",
|
||||
"i2c": "2",
|
||||
"i2s": "1",
|
||||
"pwm": "LED PWM (até 8 canais), Motor PWM (MCPWM)",
|
||||
"can": "1 (CAN 2.0, TWAI®)",
|
||||
"usb": "1 (USB OTG 1.1) + 1 (USB Serial/JTAG)",
|
||||
"sensor_temperatura": "1 (interno)",
|
||||
"consumo_energia": {
|
||||
"active": "Não divulgado (documentação preliminar)"
|
||||
},
|
||||
"temperatura_operacao": "-40°C a 105°C",
|
||||
"temperatura_armazenamento": "Não divulgado (documentação preliminar)",
|
||||
"depuracao": "JTAG integrado via USB (não precisa de sonda externa)",
|
||||
"esp_idf_minimo": "v6.0 em preview (sem suporte estável)",
|
||||
"arduino_core": "Ainda não suportado pelo core arduino-esp32",
|
||||
"encapsulamento": "QFN56 (6×6 mm)",
|
||||
"modulos": "ESP32-H4-WROOM-1",
|
||||
"guia_de_programacao": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32h4/get-started/index.html",
|
||||
"cor": "#e83e8c"
|
||||
}
|
||||
}
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* Utilitários de rotas e navegação internacionalizada.
|
||||
* Módulo puro (sem 'use client') seguro para Server e Client Components.
|
||||
*/
|
||||
|
||||
export const LOCALES = [
|
||||
{ code: "pt", label: "Português", short: "PT", lang: "pt-BR" },
|
||||
{ code: "en", label: "English", short: "EN", lang: "en" },
|
||||
{ code: "es", label: "Español", short: "ES", lang: "es-419" },
|
||||
{ code: "fr", label: "Français", short: "FR", lang: "fr" },
|
||||
{ code: "de", label: "Deutsch", short: "DE", lang: "de" },
|
||||
{ code: "zh-CN", label: "简体中文", short: "中", lang: "zh-CN" },
|
||||
];
|
||||
|
||||
export const CANONICAL_ROUTES = [
|
||||
{
|
||||
id: "series_item",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:series|serien)\/([^/]+)/,
|
||||
getSlug: (loc, key) => (loc === "de" ? `/serien/${key}` : `/series/${key}`),
|
||||
},
|
||||
{
|
||||
id: "frameworks_item",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/frameworks\/([^/]+)/,
|
||||
getSlug: (loc, key) => `/frameworks/${key}`,
|
||||
},
|
||||
{
|
||||
id: "series",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:series|serien)(?:\/|$)/,
|
||||
getSlug: (loc) => (loc === "de" ? "/serien" : "/series"),
|
||||
},
|
||||
{
|
||||
id: "catalogo",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:catalogo|catalog|catalogue|katalog)(?:\/|$)/,
|
||||
getSlug: (loc) => {
|
||||
if (loc === "de") return "/katalog";
|
||||
if (loc === "fr") return "/catalogue";
|
||||
if (loc === "en" || loc === "zh-CN") return "/catalog";
|
||||
return "/catalogo";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "comparacao",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:comparacao|compare|comparacion|comparaison|vergleich)(?:\/|$)/,
|
||||
getSlug: (loc) => {
|
||||
if (loc === "en" || loc === "zh-CN") return "/compare";
|
||||
if (loc === "es") return "/comparacion";
|
||||
if (loc === "fr") return "/comparaison";
|
||||
if (loc === "de") return "/vergleich";
|
||||
return "/comparacao";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "componentes",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:componentes|components|composants|komponenten)(?:\/|$)/,
|
||||
getSlug: (loc) => {
|
||||
if (loc === "en" || loc === "zh-CN") return "/components";
|
||||
if (loc === "fr") return "/composants";
|
||||
if (loc === "de") return "/komponenten";
|
||||
return "/componentes";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "diagnostico",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:diagnostico|diagnostics|diagnostic|diagnose)(?:\/|$)/,
|
||||
getSlug: (loc) => {
|
||||
if (loc === "en" || loc === "zh-CN") return "/diagnostics";
|
||||
if (loc === "fr") return "/diagnostic";
|
||||
if (loc === "de") return "/diagnose";
|
||||
return "/diagnostico";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "frameworks",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/frameworks(?:\/|$)/,
|
||||
getSlug: () => "/frameworks",
|
||||
},
|
||||
{
|
||||
id: "glossario",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:glossario|glossary|glosario|glossaire|glossar)(?:\/|$)/,
|
||||
getSlug: (loc) => {
|
||||
if (loc === "en" || loc === "zh-CN") return "/glossary";
|
||||
if (loc === "es") return "/glosario";
|
||||
if (loc === "fr") return "/glossaire";
|
||||
if (loc === "de") return "/glossar";
|
||||
return "/glossario";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "seletor",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:seletor|selector|selecteur|auswahl)(?:\/|$)/,
|
||||
getSlug: (loc) => {
|
||||
if (loc === "en" || loc === "es" || loc === "zh-CN") return "/selector";
|
||||
if (loc === "fr") return "/selecteur";
|
||||
if (loc === "de") return "/auswahl";
|
||||
return "/seletor";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "sobre",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/(?:sobre|about|acerca|a-propos|ueber-uns)(?:\/|$)/,
|
||||
getSlug: (loc) => {
|
||||
if (loc === "en" || loc === "zh-CN") return "/about";
|
||||
if (loc === "es") return "/acerca";
|
||||
if (loc === "fr") return "/a-propos";
|
||||
if (loc === "de") return "/ueber-uns";
|
||||
return "/sobre";
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "livro",
|
||||
match: /^\/(?:pt|en|es|fr|de|zh-CN)\/livro(?:\/|$)/,
|
||||
getSlug: (loc) => (loc === "pt" ? "/livro" : ""),
|
||||
},
|
||||
];
|
||||
|
||||
export function getLocalizedHref(pathname, targetLocale) {
|
||||
if (!pathname || pathname === "/" || pathname === `/${targetLocale}` || pathname === `/${targetLocale}/`) {
|
||||
return `/${targetLocale}/`;
|
||||
}
|
||||
|
||||
for (const route of CANONICAL_ROUTES) {
|
||||
const m = pathname.match(route.match);
|
||||
if (m) {
|
||||
const slug = route.getSlug(targetLocale, m[1]);
|
||||
return slug ? `/${targetLocale}${slug}` : `/${targetLocale}/`;
|
||||
}
|
||||
}
|
||||
return `/${targetLocale}/`;
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { createNavigation } from "next-intl/navigation";
|
||||
import { routing } from "./routing";
|
||||
|
||||
export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);
|
||||
@@ -0,0 +1,26 @@
|
||||
import { getRequestConfig } from "next-intl/server";
|
||||
import { hasLocale } from "next-intl";
|
||||
import { routing } from "./routing";
|
||||
|
||||
export default getRequestConfig(async ({ requestLocale }) => {
|
||||
let locale = await requestLocale;
|
||||
if (!locale || !hasLocale(routing.locales, locale)) {
|
||||
locale = routing.defaultLocale;
|
||||
}
|
||||
|
||||
let messages = {};
|
||||
try {
|
||||
messages = (await import(`../messages/${locale}.json`)).default;
|
||||
} catch {
|
||||
try {
|
||||
messages = (await import("../messages/pt.json")).default;
|
||||
} catch {
|
||||
messages = {};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
locale,
|
||||
messages,
|
||||
};
|
||||
});
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
import { defineRouting } from "next-intl/routing";
|
||||
|
||||
export const routing = defineRouting({
|
||||
locales: ["pt", "en", "es", "fr", "de", "zh-CN"],
|
||||
defaultLocale: "en",
|
||||
localePrefix: "always",
|
||||
pathnames: {
|
||||
"/": "/",
|
||||
"/series": {
|
||||
pt: "/series",
|
||||
en: "/series",
|
||||
es: "/series",
|
||||
fr: "/series",
|
||||
de: "/serien",
|
||||
"zh-CN": "/series",
|
||||
},
|
||||
"/series/[key]": {
|
||||
pt: "/series/[key]",
|
||||
en: "/series/[key]",
|
||||
es: "/series/[key]",
|
||||
fr: "/series/[key]",
|
||||
de: "/serien/[key]",
|
||||
"zh-CN": "/series/[key]",
|
||||
},
|
||||
"/catalogo": {
|
||||
pt: "/catalogo",
|
||||
en: "/catalog",
|
||||
es: "/catalogo",
|
||||
fr: "/catalogue",
|
||||
de: "/katalog",
|
||||
"zh-CN": "/catalog",
|
||||
},
|
||||
"/comparacao": {
|
||||
pt: "/comparacao",
|
||||
en: "/compare",
|
||||
es: "/comparacion",
|
||||
fr: "/comparaison",
|
||||
de: "/vergleich",
|
||||
"zh-CN": "/compare",
|
||||
},
|
||||
"/componentes": {
|
||||
pt: "/componentes",
|
||||
en: "/components",
|
||||
es: "/componentes",
|
||||
fr: "/composants",
|
||||
de: "/komponenten",
|
||||
"zh-CN": "/components",
|
||||
},
|
||||
"/diagnostico": {
|
||||
pt: "/diagnostico",
|
||||
en: "/diagnostics",
|
||||
es: "/diagnostico",
|
||||
fr: "/diagnostic",
|
||||
de: "/diagnose",
|
||||
"zh-CN": "/diagnostics",
|
||||
},
|
||||
"/frameworks": {
|
||||
pt: "/frameworks",
|
||||
en: "/frameworks",
|
||||
es: "/frameworks",
|
||||
fr: "/frameworks",
|
||||
de: "/frameworks",
|
||||
"zh-CN": "/frameworks",
|
||||
},
|
||||
"/frameworks/[key]": {
|
||||
pt: "/frameworks/[key]",
|
||||
en: "/frameworks/[key]",
|
||||
es: "/frameworks/[key]",
|
||||
fr: "/frameworks/[key]",
|
||||
de: "/frameworks/[key]",
|
||||
"zh-CN": "/frameworks/[key]",
|
||||
},
|
||||
"/glossario": {
|
||||
pt: "/glossario",
|
||||
en: "/glossary",
|
||||
es: "/glosario",
|
||||
fr: "/glossaire",
|
||||
de: "/glossar",
|
||||
"zh-CN": "/glossary",
|
||||
},
|
||||
"/seletor": {
|
||||
pt: "/seletor",
|
||||
en: "/selector",
|
||||
es: "/selector",
|
||||
fr: "/selecteur",
|
||||
de: "/auswahl",
|
||||
"zh-CN": "/selector",
|
||||
},
|
||||
"/sobre": {
|
||||
pt: "/sobre",
|
||||
en: "/about",
|
||||
es: "/acerca",
|
||||
fr: "/a-propos",
|
||||
de: "/ueber-uns",
|
||||
"zh-CN": "/about",
|
||||
},
|
||||
"/livro": {
|
||||
pt: "/livro",
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Carregadores de dados organizados por locale (seção 6.2 da spec).
|
||||
* Suporta pt, en, es, fr, de, zh-CN com fallback para pt.
|
||||
*/
|
||||
|
||||
export async function getSeries(locale = "pt") {
|
||||
try {
|
||||
return (await import(`@/data/${locale}/series.json`)).default;
|
||||
} catch {
|
||||
return (await import("@/data/pt/series.json")).default;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getFrameworks(locale = "pt") {
|
||||
try {
|
||||
return (await import(`@/data/${locale}/frameworks.json`)).default;
|
||||
} catch {
|
||||
return (await import("@/data/pt/frameworks.json")).default;
|
||||
}
|
||||
}
|
||||
|
||||
export async function getConexoes(key, locale = "pt") {
|
||||
try {
|
||||
return (await import(`@/data/${locale}/conexoes/${key}.json`)).default;
|
||||
} catch {
|
||||
try {
|
||||
return (await import(`@/data/pt/conexoes/${key}.json`)).default;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function getGlossario(locale = "pt") {
|
||||
try {
|
||||
return await import(`@/lib/data/${locale}/glossario.js`);
|
||||
} catch {
|
||||
return await import("@/lib/data/pt/glossario.js");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getDiagnostico(locale = "pt") {
|
||||
try {
|
||||
return await import(`@/lib/data/${locale}/diagnostico.js`);
|
||||
} catch {
|
||||
return await import("@/lib/data/pt/diagnostico.js");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getComponentes(locale = "pt") {
|
||||
try {
|
||||
return await import(`@/lib/data/${locale}/componentes.js`);
|
||||
} catch {
|
||||
return await import("@/lib/data/pt/componentes.js");
|
||||
}
|
||||
}
|
||||
|
||||
export async function getTopicos(locale = "pt") {
|
||||
try {
|
||||
return await import(`@/lib/data/${locale}/topicos.js`);
|
||||
} catch {
|
||||
return await import("@/lib/data/pt/topicos.js");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,858 @@
|
||||
/**
|
||||
* Base de Dados Oficial Curada: ESP Component Registry & IDF Component Manager
|
||||
*
|
||||
* O ESP Component Registry (https://components.espressif.com) é o ecossistema
|
||||
* central de distribuição de bibliotecas modulares para o ESP-IDF v4.4+ / v5.x+.
|
||||
*/
|
||||
|
||||
export const CATEGORIAS_COMPONENTES = [
|
||||
{
|
||||
id: "todos",
|
||||
nome: "Todos os Componentes",
|
||||
icone: "Layers",
|
||||
descricao: "Explore todo o catálogo curado de bibliotecas e drivers"
|
||||
},
|
||||
{
|
||||
id: "ui_display",
|
||||
nome: "UI, Displays & Gráficos",
|
||||
icone: "Monitor",
|
||||
descricao: "Bibliotecas gráficas (LVGL), drivers de display LCD/OLED, touch e decodificadores"
|
||||
},
|
||||
{
|
||||
id: "cloud_conectividade",
|
||||
nome: "Cloud & Conectividade",
|
||||
icone: "Cloud",
|
||||
descricao: "ESP RainMaker, AWS IoT, MQTT, WebSockets, Mesh-Lite e coprocessamento ESP-Hosted"
|
||||
},
|
||||
{
|
||||
id: "audio_voz_ia",
|
||||
nome: "Áudio, Voz & IA",
|
||||
icone: "Brain",
|
||||
descricao: "Reconhecimento de fala ESP-SR, processamento DSP, codecs, câmeras DVP e TinyML"
|
||||
},
|
||||
{
|
||||
id: "smart_home_mesh",
|
||||
nome: "Smart Home & Mesh",
|
||||
icone: "Home",
|
||||
descricao: "Matter SDK, pilhas Zigbee 3.0 (ZBOSS), Thread e redes ESP-NOW"
|
||||
},
|
||||
{
|
||||
id: "drivers_perifericos",
|
||||
nome: "Drivers & Sensores",
|
||||
icone: "Cpu",
|
||||
descricao: "Botões, encoders, LEDs RGB, Ethernet (W5500/CH390), USB nativo e sensores ambientais/IMU"
|
||||
},
|
||||
{
|
||||
id: "bsp_placas",
|
||||
nome: "BSPs (Board Support Packages)",
|
||||
icone: "CircuitBoard",
|
||||
descricao: "Pacotes de suporte direto para placas oficiais como ESP-BOX-3, Korvo, EYE e M5Stack"
|
||||
},
|
||||
{
|
||||
id: "sistema_utilitarios",
|
||||
nome: "Sistema & Utilitários",
|
||||
icone: "Wrench",
|
||||
descricao: "Sistemas de arquivos LittleFS, wrappers C++ modernos, CBOR e utilitários de rede"
|
||||
}
|
||||
];
|
||||
|
||||
export const COMPONENTES_REGISTRY = [
|
||||
// ==========================================
|
||||
// 1. UI, Displays & Gráficos
|
||||
// ==========================================
|
||||
{
|
||||
id: "espressif-esp_lvgl_port",
|
||||
namespace: "espressif",
|
||||
name: "esp_lvgl_port",
|
||||
versao: "^2.4.0",
|
||||
categoria: "ui_display",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP LVGL Port",
|
||||
descricao: "Port oficial e thread-safe do LVGL (Light and Versatile Graphics Library) para ESP-IDF com aceleração por hardware e suporte multi-display.",
|
||||
tags: ["LVGL", "GUI", "Display", "Touch", "IHM"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-P4", "ESP32-C3", "ESP32-C6"],
|
||||
dependenciasSugeridas: ["lvgl/lvgl^9.1.0"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_lvgl_port",
|
||||
urlRepo: "https://github.com/espressif/esp-bsp/tree/master/components/esp_lvgl_port",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_lvgl_port: "^2.4.0"
|
||||
lvgl/lvgl: "^9.1.0"`
|
||||
},
|
||||
{
|
||||
id: "lvgl-lvgl",
|
||||
namespace: "lvgl",
|
||||
name: "lvgl",
|
||||
versao: "^9.1.0",
|
||||
categoria: "ui_display",
|
||||
oficial: false,
|
||||
popular: true,
|
||||
titulo: "LVGL Graphics Library Core",
|
||||
descricao: "Biblioteca gráfica de código aberto em C mais popular para sistemas embarcados. Fornece widgets ricos, animações fluidas e suporte a layouts modernos.",
|
||||
tags: ["LVGL 9", "Graphics", "Widgets", "GUI", "Embedded UI"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-P4", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/lvgl/lvgl",
|
||||
urlRepo: "https://github.com/lvgl/lvgl",
|
||||
exemploYaml: `dependencies:
|
||||
lvgl/lvgl: "^9.1.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp32_display_panel",
|
||||
namespace: "espressif",
|
||||
name: "esp32_display_panel",
|
||||
versao: "^0.2.0",
|
||||
categoria: "ui_display",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP32 Display Panel Driver",
|
||||
descricao: "Driver unificado de controladores LCD (RGB, SPI, QSPI, MIPI-DSI) e touch capacitivo desenhado especialmente para ESP32-S3 e ESP32-P4.",
|
||||
tags: ["LCD", "MIPI-DSI", "QSPI", "Touch", "ST7789", "ILI9341"],
|
||||
chips: ["ESP32-S3", "ESP32-P4", "ESP32-S2", "ESP32"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp32_display_panel",
|
||||
urlRepo: "https://github.com/esp-arduino-libs/ESP32_Display_Panel",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp32_display_panel: "^0.2.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_lcd_touch",
|
||||
namespace: "espressif",
|
||||
name: "esp_lcd_touch",
|
||||
versao: "^1.1.2",
|
||||
categoria: "ui_display",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP LCD Touch Framework",
|
||||
descricao: "Componente central de abstração de painéis touch para telas LCD. Suporta calibragem de coordenadas, leitura de múltiplos toques e integração direta com LVGL.",
|
||||
tags: ["Touchscreen", "Capacitivo", "Resistivo", "I2C Touch", "Coordenadas"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-P4", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_lcd_touch",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/display/touch_panel/esp_lcd_touch",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_lcd_touch: "^1.1.2"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_lcd_touch_gt911",
|
||||
namespace: "espressif",
|
||||
name: "esp_lcd_touch_gt911",
|
||||
versao: "^1.1.2",
|
||||
categoria: "ui_display",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "Driver Touch Capacitivo GT911",
|
||||
descricao: "Driver I2C especializado para o controlador de touch capacitivo Goodix GT911, amplamente utilizado em displays de 4.3\", 5\" e 7\" para ESP32-S3 e P4.",
|
||||
tags: ["GT911", "Goodix", "Touch Capacitivo", "Multitouch", "I2C"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-P4", "ESP32-S2"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_lcd_touch_gt911",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/display/touch_panel/esp_lcd_touch_gt911",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_lcd_touch_gt911: "^1.1.2"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_lcd_touch_ft5x06",
|
||||
namespace: "espressif",
|
||||
name: "esp_lcd_touch_ft5x06",
|
||||
versao: "^1.1.0",
|
||||
categoria: "ui_display",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "Driver Touch FocalTech FT5x06 / FT6x36",
|
||||
descricao: "Driver de painel touch capacitivo para controladores FocalTech (FT5206, FT5316, FT5436, FT6236, FT6336) com suporte a gestos e interrupções.",
|
||||
tags: ["FT6236", "FT5x06", "FocalTech", "Touch", "I2C"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-P4", "ESP32-S2", "ESP32-C3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_lcd_touch_ft5x06",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/display/touch_panel/esp_lcd_touch_ft5x06",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_lcd_touch_ft5x06: "^1.1.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_jpeg",
|
||||
namespace: "espressif",
|
||||
name: "esp_jpeg",
|
||||
versao: "^1.3.0",
|
||||
categoria: "ui_display",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "ESP JPEG Decoder (TJpgDec)",
|
||||
descricao: "Decodificador e codificador JPEG de alta velocidade com otimizações SIMD em Assembly para exibir imagens e streams de câmeras em displays sem atrasos.",
|
||||
tags: ["JPEG", "TJpgDec", "Câmera", "Imagem", "SIMD"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-P4", "ESP32-C3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_jpeg",
|
||||
urlRepo: "https://github.com/espressif/esp-jpeg",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_jpeg: "^1.3.0"`
|
||||
},
|
||||
|
||||
// ==========================================
|
||||
// 2. Cloud & Conectividade
|
||||
// ==========================================
|
||||
{
|
||||
id: "espressif-esp_rainmaker",
|
||||
namespace: "espressif",
|
||||
name: "esp_rainmaker",
|
||||
versao: "^1.4.0",
|
||||
categoria: "cloud_conectividade",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP RainMaker Agent",
|
||||
descricao: "Agente oficial de firmware para a plataforma de nuvem AIoT ESP RainMaker. Habilita controle por app móvel, Alexa, Google Home e OTA.",
|
||||
tags: ["RainMaker", "AWS Cloud", "App iOS/Android", "Alexa", "Google Home", "OTA"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_rainmaker",
|
||||
urlRepo: "https://github.com/espressif/esp-rainmaker",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_rainmaker: "^1.4.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-mesh_lite",
|
||||
namespace: "espressif",
|
||||
name: "mesh_lite",
|
||||
versao: "^1.2.0",
|
||||
categoria: "cloud_conectividade",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP Mesh-Lite Network Stack",
|
||||
descricao: "Rede em malha Wi-Fi leve onde cada nó possui conectividade IP independente, permitindo comunicação direta na rede local e acesso à nuvem com múltiplos saltos.",
|
||||
tags: ["Mesh", "Wi-Fi Mesh", "Rede em Malha", "IoT Distribuída", "IP Layer"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/mesh_lite",
|
||||
urlRepo: "https://github.com/espressif/esp-mesh-lite",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/mesh_lite: "^1.2.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_modbus",
|
||||
namespace: "espressif",
|
||||
name: "esp_modbus",
|
||||
versao: "^1.0.15",
|
||||
categoria: "cloud_conectividade",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP-Modbus Industrial Stack",
|
||||
descricao: "Implementação completa da pilha industrial Modbus (Master/Slave) suportando interfaces RS-485 (RTU/ASCII) e Ethernet/Wi-Fi (Modbus TCP).",
|
||||
tags: ["Modbus", "RS-485", "Modbus TCP", "Automação Industrial", "PLC"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_modbus",
|
||||
urlRepo: "https://github.com/espressif/esp-modbus",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_modbus: "^1.0.15"`
|
||||
},
|
||||
{
|
||||
id: "espressif-net_connect",
|
||||
namespace: "espressif",
|
||||
name: "net_connect",
|
||||
versao: "^1.0.0",
|
||||
categoria: "cloud_conectividade",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "Unified Network Connect",
|
||||
descricao: "Componente unificado de gerenciamento de conexão de rede, alternando e inicializando de forma transparente Wi-Fi, Ethernet, Thread ou PPP móvel.",
|
||||
tags: ["Network", "Wi-Fi", "Ethernet", "Fallback", "Conexão Automática"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/net_connect",
|
||||
urlRepo: "https://github.com/espressif/esp-idf/tree/master/components",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/net_connect: "^1.0.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_hosted",
|
||||
namespace: "espressif",
|
||||
name: "esp_hosted",
|
||||
versao: "^0.0.10",
|
||||
categoria: "cloud_conectividade",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "ESP-Hosted Coprocessor",
|
||||
descricao: "Transforma o ESP32 em um coprocessador de comunicação sem fio (Wi-Fi + BLE) para hosts Linux (Raspberry Pi, i.MX) ou microcontroladores via SPI/SDIO/UART.",
|
||||
tags: ["Coprocessador", "SDIO", "SPI", "Linux Wi-Fi", "Raspberry Pi"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_hosted",
|
||||
urlRepo: "https://github.com/espressif/esp-hosted",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_hosted: "^0.0.10"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp-now",
|
||||
namespace: "espressif",
|
||||
name: "esp-now",
|
||||
versao: "^2.5.0",
|
||||
categoria: "cloud_conectividade",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP-NOW Enhanced & Provisioning",
|
||||
descricao: "Extensão com recursos avançados de emparelhamento por controle remoto, segurança AES-128 e controle de múltiplos dispositivos com protocolo ESP-NOW.",
|
||||
tags: ["ESP-NOW", "Sem Fio", "Baixa Latência", "Broadcast", "Controle Remoto"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-now",
|
||||
urlRepo: "https://github.com/espressif/esp-now",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-now: "^2.5.0"`
|
||||
},
|
||||
|
||||
// ==========================================
|
||||
// 3. Áudio, Voz & IA
|
||||
// ==========================================
|
||||
{
|
||||
id: "espressif-esp-sr",
|
||||
namespace: "espressif",
|
||||
name: "esp-sr",
|
||||
versao: "^1.5.0",
|
||||
categoria: "audio_voz_ia",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP-SR Speech Recognition",
|
||||
descricao: "Framework de reconhecimento de fala 100% offline com WakeNet (palavra de ativação), MultiNet (comandos locais) e algoritmos acústicos AFE.",
|
||||
tags: ["Voz", "WakeNet", "MultiNet", "Reconhecimento de Fala", "Offline", "AEC"],
|
||||
chips: ["ESP32-S3", "ESP32-P4", "ESP32"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-sr",
|
||||
urlRepo: "https://github.com/espressif/esp-sr",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-sr: "^1.5.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_codec_dev",
|
||||
namespace: "espressif",
|
||||
name: "esp_codec_dev",
|
||||
versao: "^1.3.0",
|
||||
categoria: "audio_voz_ia",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP Audio Codec Device HAL",
|
||||
descricao: "Camada unificada de abstração de codecs de áudio I2S/I2C (ES8311, ES8388, ES7210, ES7243, TAS5805M) para entrada e saída de som estéreo.",
|
||||
tags: ["Audio Codec", "I2S", "ES8311", "ES8388", "Microfone DAC"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-P4", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_codec_dev",
|
||||
urlRepo: "https://github.com/espressif/esp-codec-dev",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_codec_dev: "^1.3.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-es8311",
|
||||
namespace: "espressif",
|
||||
name: "es8311",
|
||||
versao: "^1.0.0",
|
||||
categoria: "audio_voz_ia",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "Driver Codec de Áudio ES8311",
|
||||
descricao: "Driver dedicado de baixo consumo para o codec Everest ES8311 (DAC mono + ADC de microfone) presente no ESP32-S3-BOX e placas de IoT.",
|
||||
tags: ["ES8311", "Áudio", "DAC", "Microfone", "I2S"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-P4", "ESP32-C3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/es8311",
|
||||
urlRepo: "https://github.com/espressif/esp-bsp/tree/master/components/es8311",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/es8311: "^1.0.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp32-camera",
|
||||
namespace: "espressif",
|
||||
name: "esp32-camera",
|
||||
versao: "^2.0.12",
|
||||
categoria: "audio_voz_ia",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP32 Camera Driver",
|
||||
descricao: "Driver oficial de câmeras CMOS (OV2640, OV3660, OV5640, OV7670, GC0308) com suporte a DMA, DMA-2D, captura JPEG e streaming MJPEG por HTTP/RTSP.",
|
||||
tags: ["Câmera", "OV2640", "OV5640", "DVP", "MIPI-CSI", "Vídeo"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-P4", "ESP32-S2"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp32-camera",
|
||||
urlRepo: "https://github.com/espressif/esp32-camera",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp32-camera: "^2.0.12"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp-dsp",
|
||||
namespace: "espressif",
|
||||
name: "esp-dsp",
|
||||
versao: "^1.5.1",
|
||||
categoria: "audio_voz_ia",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP-DSP Signal Processing",
|
||||
descricao: "Biblioteca oficial de processamento digital de sinais para SoCs ESP32 (FFT, filtros digitais FIR/IIR, matrizes e álgebra linear acelerada).",
|
||||
tags: ["DSP", "FFT", "Filtros", "Matemática", "SIMD", "Assembly"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-P4", "ESP32-C3", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-dsp",
|
||||
urlRepo: "https://github.com/espressif/esp-dsp",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-dsp: "^1.5.1"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp-nn",
|
||||
namespace: "espressif",
|
||||
name: "esp-nn",
|
||||
versao: "^1.2.0",
|
||||
categoria: "audio_voz_ia",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP-NN Neural Network Kernels",
|
||||
descricao: "Kernels otimizados em assembly vetorial para aceleração de redes neurais e modelos TensorFlow Lite Micro em chips ESP32.",
|
||||
tags: ["TinyML", "TensorFlow Lite", "Redes Neurais", "Inferência", "Edge AI"],
|
||||
chips: ["ESP32-S3", "ESP32-P4", "ESP32"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-nn",
|
||||
urlRepo: "https://github.com/espressif/esp-nn",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-nn: "^1.2.0"`
|
||||
},
|
||||
|
||||
// ==========================================
|
||||
// 4. Smart Home & Mesh
|
||||
// ==========================================
|
||||
{
|
||||
id: "espressif-esp-matter",
|
||||
namespace: "espressif",
|
||||
name: "esp-matter",
|
||||
versao: "^1.3.0",
|
||||
categoria: "smart_home_mesh",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP Matter SDK",
|
||||
descricao: "SDK oficial para criar dispositivos interoperáveis com Apple Home, Google Home, Amazon Alexa e Home Assistant sobre Wi-Fi e Thread.",
|
||||
tags: ["Matter", "Smart Home", "Apple HomeKit", "Google Home", "Thread", "CHIP"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-H2"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-matter",
|
||||
urlRepo: "https://github.com/espressif/esp-matter",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-matter: "^1.3.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp-zigbee-lib",
|
||||
namespace: "espressif",
|
||||
name: "esp-zigbee-lib",
|
||||
versao: "^1.6.0",
|
||||
categoria: "smart_home_mesh",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP Zigbee 3.0 Library",
|
||||
descricao: "Pilha certificada Zigbee 3.0 (ZBOSS) para criação de nós Coordenadores, Roteadores e Dispositivos Finais de baixo consumo em chips 802.15.4.",
|
||||
tags: ["Zigbee 3.0", "ZBOSS", "802.15.4", "Home Automation", "Bateria"],
|
||||
chips: ["ESP32-H2", "ESP32-C6"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-zigbee-lib",
|
||||
urlRepo: "https://github.com/espressif/esp-zigbee-sdk",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-zigbee-lib: "^1.6.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_rcp_update",
|
||||
namespace: "espressif",
|
||||
name: "esp_rcp_update",
|
||||
versao: "^1.0.0",
|
||||
categoria: "smart_home_mesh",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "ESP RCP Thread/Zigbee Gateway",
|
||||
descricao: "Componente para atualização de coprocessador de rádio (RCP) 802.15.4 para construção de Thread Border Routers e gateways Zigbee multiprotocolo.",
|
||||
tags: ["Thread Border Router", "OpenThread", "RCP", "Zigbee Gateway"],
|
||||
chips: ["ESP32-H2", "ESP32-C6", "ESP32-S3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_rcp_update",
|
||||
urlRepo: "https://github.com/espressif/esp-thread-br",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_rcp_update: "^1.0.0"`
|
||||
},
|
||||
|
||||
// ==========================================
|
||||
// 5. Drivers & Sensores
|
||||
// ==========================================
|
||||
{
|
||||
id: "espressif-led_indicator",
|
||||
namespace: "espressif",
|
||||
name: "led_indicator",
|
||||
versao: "^1.2.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "LED Indicator Driver",
|
||||
descricao: "Driver inteligente para controle de padrões de iluminação de LED (piscar rápido, respiração/fade, códigos de erro e RGB) sem travar o loop principal.",
|
||||
tags: ["LED", "PWM", "RGB", "Blink", "Feedback Visual"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C2", "ESP32-C3", "ESP32-C6", "ESP32-H2", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/led_indicator",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/led/led_indicator",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/led_indicator: "^1.2.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-button",
|
||||
namespace: "espressif",
|
||||
name: "button",
|
||||
versao: "^3.4.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "IoT Button Handler (iot_button)",
|
||||
descricao: "Gerenciador completo de botões com debounce, eventos de clique único, duplo, múltiplo, pressionamento longo e matrizes de teclado.",
|
||||
tags: ["Botão", "Debounce", "Long Press", "Double Click", "GPIO"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-H2", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/button",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/button",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/button: "^3.4.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-led_strip",
|
||||
namespace: "espressif",
|
||||
name: "led_strip",
|
||||
versao: "^2.5.4",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "Addressable LED Strip (WS2812/SK6812)",
|
||||
descricao: "Driver de alto desempenho para fitas e matrizes de LED endereçáveis WS2812, WS2813 e SK6812 usando periféricos RMT ou SPI.",
|
||||
tags: ["WS2812B", "Neopixel", "SK6812", "RMT", "Fita de LED", "RGB"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/led_strip",
|
||||
urlRepo: "https://github.com/espressif/idf-extra-components/tree/master/led_strip",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/led_strip: "^2.5.4"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_tinyusb",
|
||||
namespace: "espressif",
|
||||
name: "esp_tinyusb",
|
||||
versao: "^1.5.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP Native USB Device (TinyUSB)",
|
||||
descricao: "Extensão oficial do TinyUSB para ESP32-S2, ESP32-S3 e ESP32-P4, permitindo emular portas seriais USB CDC, Teclado/Mouse HID, Pen Drive MSC, DFU e WebUSB.",
|
||||
tags: ["USB Nativo", "TinyUSB", "USB CDC", "USB HID", "WebUSB", "MSC"],
|
||||
chips: ["ESP32-S2", "ESP32-S3", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_tinyusb",
|
||||
urlRepo: "https://github.com/espressif/esp-tinyusb",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_tinyusb: "^1.5.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-w5500",
|
||||
namespace: "espressif",
|
||||
name: "w5500",
|
||||
versao: "^1.2.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "WIZnet W5500 SPI Ethernet Driver",
|
||||
descricao: "Driver oficial para o chip Ethernet WIZnet W5500 via barramento SPI, integrando perfeitamente a interface física à pilha TCP/IP (lwIP) nativa do ESP-IDF.",
|
||||
tags: ["W5500", "Ethernet", "SPI Ethernet", "RJ45", "lwIP", "Rede Cabeada"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/w5500",
|
||||
urlRepo: "https://github.com/espressif/esp-eth-drivers/tree/master/w5500",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/w5500: "^1.2.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-ch390",
|
||||
namespace: "espressif",
|
||||
name: "ch390",
|
||||
versao: "^1.0.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "CH390 SPI Ethernet Driver",
|
||||
descricao: "Driver SPI Ethernet 10/100M para o controlador WCH CH390, ideal para adicionar porta de rede RJ45 econômica em placas com ESP32-C3, S3 ou P4.",
|
||||
tags: ["CH390", "Ethernet", "WCH", "SPI Ethernet", "RJ45"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/ch390",
|
||||
urlRepo: "https://github.com/espressif/esp-eth-drivers/tree/master/ch390",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/ch390: "^1.0.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-usb_host_uvc",
|
||||
namespace: "espressif",
|
||||
name: "usb_host_uvc",
|
||||
versao: "^1.0.4",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "USB Host UVC (Webcam Driver)",
|
||||
descricao: "Driver USB Host para conectar webcams USB UVC padrão diretamente na porta USB nativa do ESP32-S2, ESP32-S3 ou ESP32-P4.",
|
||||
tags: ["USB Host", "UVC", "Webcam", "Câmera USB", "Vídeo"],
|
||||
chips: ["ESP32-S2", "ESP32-S3", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/usb_host_uvc",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/usb/usb_host_uvc",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/usb_host_uvc: "^1.0.4"`
|
||||
},
|
||||
{
|
||||
id: "espressif-sensor_hub",
|
||||
namespace: "espressif",
|
||||
name: "sensor_hub",
|
||||
versao: "^1.0.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "ESP Sensor Hub Manager",
|
||||
descricao: "Framework unificado para gerenciamento de sensores heterogêneos (I2C/SPI) com amostragem periódica, fusão de dados e disparo por eventos/interrupções.",
|
||||
tags: ["Sensores", "Sensor Hub", "I2C", "Eventos", "Coleta Periódica"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/sensor_hub",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/sensors/sensor_hub",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/sensor_hub: "^1.0.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-bmi270_sensor",
|
||||
namespace: "espressif",
|
||||
name: "bmi270_sensor",
|
||||
versao: "^1.0.1",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "Driver Sensor IMU Bosch BMI270",
|
||||
descricao: "Driver oficial para o sensor inercial IMU de 6 eixos Bosch BMI270 (Acelerômetro + Giroscópio) com detecção de gestos de movimento e passos.",
|
||||
tags: ["BMI270", "IMU", "Acelerômetro", "Giroscópio", "Bosch", "Gestos"],
|
||||
chips: ["ESP32", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/bmi270_sensor",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/sensors/imu/bmi270",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/bmi270_sensor: "^1.0.1"`
|
||||
},
|
||||
{
|
||||
id: "espressif-ds18b20",
|
||||
namespace: "espressif",
|
||||
name: "ds18b20",
|
||||
versao: "^1.0.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "Driver Sensor de Temperatura DS18B20",
|
||||
descricao: "Driver digital para sensor de temperatura 1-Wire Dallas/Maxim DS18B20 com suporte a múltiplos sensores no mesmo pino GPIO via barramento RMT.",
|
||||
tags: ["DS18B20", "1-Wire", "Temperatura", "Sensor", "Dallas"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/ds18b20",
|
||||
urlRepo: "https://github.com/espressif/esp-iot-solution/tree/master/components/sensors/temperature/ds18b20",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/ds18b20: "^1.0.0"`
|
||||
},
|
||||
{
|
||||
id: "esp-idf-lib-scd4x",
|
||||
namespace: "esp-idf-lib",
|
||||
name: "scd4x",
|
||||
versao: "^1.0.0",
|
||||
categoria: "drivers_perifericos",
|
||||
oficial: false,
|
||||
popular: true,
|
||||
titulo: "Driver Sensor CO2 Sensirion SCD40/SCD41",
|
||||
descricao: "Driver I2C de alta precisão para sensores fotoacústicos de CO2, temperatura e umidade relativa Sensirion SCD40 e SCD41 com auto-calibragem.",
|
||||
tags: ["SCD40", "SCD41", "Sensirion", "CO2", "Qualidade do Ar", "I2C"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-H2", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/esp-idf-lib/scd4x",
|
||||
urlRepo: "https://github.com/UncleRus/esp-idf-lib/tree/master/components/scd4x",
|
||||
exemploYaml: `dependencies:
|
||||
esp-idf-lib/scd4x: "^1.0.0"`
|
||||
},
|
||||
|
||||
// ==========================================
|
||||
// 6. BSPs (Board Support Packages)
|
||||
// ==========================================
|
||||
{
|
||||
id: "espressif-esp-box-3",
|
||||
namespace: "espressif",
|
||||
name: "esp-box-3",
|
||||
versao: "^1.2.0",
|
||||
categoria: "bsp_placas",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "BSP ESP32-S3-BOX-3",
|
||||
descricao: "Pacote de suporte completo para a placa de desenvolvimento de IA ESP32-S3-BOX-3, inicializando tela touch, codec de áudio, microfones duplos, sensor de movimento e LEDs com uma única função.",
|
||||
tags: ["BSP", "ESP-BOX-3", "Display Touch", "Microfone", "Áudio ES8311", "I2C/SPI"],
|
||||
chips: ["ESP32-S3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-box-3",
|
||||
urlRepo: "https://github.com/espressif/esp-bsp/tree/master/bsp/esp-box-3",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-box-3: "^1.2.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp32_s3_korvo_2",
|
||||
namespace: "espressif",
|
||||
name: "esp32_s3_korvo_2",
|
||||
versao: "^1.1.0",
|
||||
categoria: "bsp_placas",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "BSP ESP32-S3-Korvo-2",
|
||||
descricao: "Board Support Package para o kit de desenvolvimento de áudio e reconhecimento de voz ESP32-S3-Korvo-2, com suporte a microfones I2S e botões de toque.",
|
||||
tags: ["BSP", "Korvo", "Áudio", "Array de Microfones", "ESP-SR"],
|
||||
chips: ["ESP32-S3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp32_s3_korvo_2",
|
||||
urlRepo: "https://github.com/espressif/esp-bsp/tree/master/bsp/esp32_s3_korvo_2",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp32_s3_korvo_2: "^1.1.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp32_s3_eye",
|
||||
namespace: "espressif",
|
||||
name: "esp32_s3_eye",
|
||||
versao: "^1.1.0",
|
||||
categoria: "bsp_placas",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "BSP ESP32-S3-EYE",
|
||||
descricao: "Board Support Package para a placa de visão computacional oficial ESP32-S3-EYE, configurando câmera OV2640, display LCD SPI redondo e microfone digital.",
|
||||
tags: ["BSP", "ESP32-S3-EYE", "Câmera", "Visão Computacional", "Display"],
|
||||
chips: ["ESP32-S3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp32_s3_eye",
|
||||
urlRepo: "https://github.com/espressif/esp-bsp/tree/master/bsp/esp32_s3_eye",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp32_s3_eye: "^1.1.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-m5stack_core_s3",
|
||||
namespace: "espressif",
|
||||
name: "m5stack_core_s3",
|
||||
versao: "^1.0.0",
|
||||
categoria: "bsp_placas",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "BSP M5Stack CoreS3",
|
||||
descricao: "Board Support Package oficial para o dispositivo M5Stack CoreS3, inicializando tela sensível ao toque, PMIC AXP2101, câmera GC0308 e alto-falante I2S.",
|
||||
tags: ["BSP", "M5Stack", "CoreS3", "Display ILI9342C", "AXP2101", "Câmera"],
|
||||
chips: ["ESP32-S3"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/m5stack_core_s3",
|
||||
urlRepo: "https://github.com/espressif/esp-bsp/tree/master/bsp/m5stack_core_s3",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/m5stack_core_s3: "^1.0.0"`
|
||||
},
|
||||
{
|
||||
id: "waveshare-esp32_p4_wifi6_touch_lcd_7b",
|
||||
namespace: "waveshare",
|
||||
name: "esp32_p4_wifi6_touch_lcd_7b",
|
||||
versao: "^1.0.0",
|
||||
categoria: "bsp_placas",
|
||||
oficial: false,
|
||||
popular: true,
|
||||
titulo: "BSP Waveshare ESP32-P4 Touch LCD 7\"",
|
||||
descricao: "Pacote de suporte para a placa de alta performance Waveshare ESP32-P4 com tela touch capacitiva de 7 polegadas (MIPI-DSI 1024x600) e coprocessador Wi-Fi 6.",
|
||||
tags: ["BSP", "ESP32-P4", "MIPI-DSI", "Waveshare", "Tela 7 Polegadas", "Touch"],
|
||||
chips: ["ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/waveshare/esp32_p4_wifi6_touch_lcd_7b",
|
||||
urlRepo: "https://github.com/waveshare/ESP32-P4-WiFi6-Touch-LCD-7B",
|
||||
exemploYaml: `dependencies:
|
||||
waveshare/esp32_p4_wifi6_touch_lcd_7b: "^1.0.0"`
|
||||
},
|
||||
|
||||
// ==========================================
|
||||
// 7. Sistema & Utilitários
|
||||
// ==========================================
|
||||
{
|
||||
id: "joltwallet-littlefs",
|
||||
namespace: "joltwallet",
|
||||
name: "littlefs",
|
||||
versao: "^1.14.8",
|
||||
categoria: "sistema_utilitarios",
|
||||
oficial: false,
|
||||
popular: true,
|
||||
titulo: "LittleFS Filesystem for ESP-IDF",
|
||||
descricao: "Port robusto do sistema de arquivos LittleFS para memória Flash SPI com wear-leveling dinâmico e proteção contra corrupção por queda de energia.",
|
||||
tags: ["LittleFS", "Flash", "Filesystem", "Wear Leveling", "NVS"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-H2", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/joltwallet/littlefs",
|
||||
urlRepo: "https://github.com/joltwallet/esp_littlefs",
|
||||
exemploYaml: `dependencies:
|
||||
joltwallet/littlefs: "^1.14.8"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp-idf-cxx",
|
||||
namespace: "espressif",
|
||||
name: "esp-idf-cxx",
|
||||
versao: "^1.2.0",
|
||||
categoria: "sistema_utilitarios",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP-IDF C++ Idiomatic Wrappers",
|
||||
descricao: "Conjunto de classes e wrappers C++ modernos (C++17/C++20/C++23) com semântica RAII para GPIOs, Wi-Fi, timers, filas FreeRTOS e semáforos.",
|
||||
tags: ["C++", "C++20", "RAII", "Modern C++", "Object Oriented", "FreeRTOS"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-H2", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp-idf-cxx",
|
||||
urlRepo: "https://github.com/espressif/esp-idf-cxx",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp-idf-cxx: "^1.2.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-cbor",
|
||||
namespace: "espressif",
|
||||
name: "cbor",
|
||||
versao: "^0.6.0",
|
||||
categoria: "sistema_utilitarios",
|
||||
oficial: true,
|
||||
popular: false,
|
||||
titulo: "TinyCBOR Serialization",
|
||||
descricao: "Biblioteca ultraleve para serialização e deserialização de dados em formato binário CBOR (Concise Binary Object Representation).",
|
||||
tags: ["CBOR", "Serialização", "Binário", "IoT Protocol", "JSON Compacto"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-H2", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/cbor",
|
||||
urlRepo: "https://github.com/espressif/tinycbor",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/cbor: "^0.6.0"`
|
||||
},
|
||||
{
|
||||
id: "espressif-esp_websocket_client",
|
||||
namespace: "espressif",
|
||||
name: "esp_websocket_client",
|
||||
versao: "^1.2.4",
|
||||
categoria: "sistema_utilitarios",
|
||||
oficial: true,
|
||||
popular: true,
|
||||
titulo: "ESP WebSocket Client",
|
||||
descricao: "Cliente WebSocket bidirecional em tempo real com suporte a TLS/SSL (WSS), reconexão automática, sub-protocolos e ping/pong de heartbeat.",
|
||||
tags: ["WebSocket", "WSS", "TLS", "Tempo Real", "Sockets", "JSON"],
|
||||
chips: ["ESP32", "ESP32-S2", "ESP32-S3", "ESP32-C3", "ESP32-C6", "ESP32-P4"],
|
||||
urlRegistry: "https://components.espressif.com/components/espressif/esp_websocket_client",
|
||||
urlRepo: "https://github.com/espressif/esp-protocols/tree/master/components/esp_websocket_client",
|
||||
exemploYaml: `dependencies:
|
||||
espressif/esp_websocket_client: "^1.2.4"`
|
||||
}
|
||||
];
|
||||
|
||||
export const GUIA_COMPONENT_MANAGER = {
|
||||
titulo: "Como Usar o ESP Component Registry no ESP-IDF",
|
||||
resumo: "A partir do ESP-IDF v4.4 e consolidado no v5.x+, a Espressif adotou a arquitetura de pacotes modulares gerenciada pelo IDF Component Manager. Esqueça submódulos git complexos: agora basta declarar as bibliotecas no arquivo de manifesto idf_component.yml do seu projeto.",
|
||||
vantagens: [
|
||||
{
|
||||
titulo: "Instalação Automática e Desacoplada",
|
||||
descricao: "O compilador baixa, compila e gerencia as versões das bibliotecas automaticamente durante o 'idf.py build' ou 'idf.py reconfigure'."
|
||||
},
|
||||
{
|
||||
titulo: "Versionamento Semântico Rigoroso",
|
||||
descricao: "Controle exatamente quando atualizar com operadores de versão (^ para compatibilidade minor, ~ para patches ou versões exatas fixas)."
|
||||
},
|
||||
{
|
||||
titulo: "Projetos mais Leves e Limpos",
|
||||
descricao: "O repositório do seu projeto fica limpo, sem carregar código de terceiros dentro do histórico do Git."
|
||||
},
|
||||
{
|
||||
titulo: "Compartilhamento Corporativo ou Comunitário",
|
||||
descricao: "Publique seus próprios componentes na nuvem pública da Espressif ou em registros privados locais da sua empresa."
|
||||
}
|
||||
],
|
||||
comandosCli: [
|
||||
{
|
||||
comando: 'idf.py add-dependency "namespace/componente^versao"',
|
||||
exemplo: 'idf.py add-dependency "espressif/esp_lvgl_port^2.4.0"',
|
||||
explicacao: "Cria ou atualiza automaticamente o arquivo 'main/idf_component.yml' adicionando a dependência informada."
|
||||
},
|
||||
{
|
||||
comando: "idf.py reconfigure",
|
||||
exemplo: "idf.py reconfigure",
|
||||
explicacao: "Força o CMake e o Component Manager a resolver novamente a árvore de dependências e baixar pacotes pendentes."
|
||||
},
|
||||
{
|
||||
comando: "compote component upload --name <component_name> --namespace <sua_org>",
|
||||
exemplo: "compote component upload --name meu_driver_sensor --namespace minhadiv",
|
||||
explicacao: "Publica seu componente de código aberto ou proprietário no ESP Component Registry usando a ferramenta oficial Compote CLI."
|
||||
}
|
||||
],
|
||||
sintaxeManifesto: `# Estrutura típica do arquivo: main/idf_component.yml
|
||||
dependencies:
|
||||
# Baixa do registro oficial da Espressif
|
||||
espressif/esp_lvgl_port: "^2.4.0"
|
||||
espressif/button: "~3.4.0"
|
||||
|
||||
# Versão exata
|
||||
espressif/led_indicator: "1.2.0"
|
||||
|
||||
# Dependência da comunidade
|
||||
joltwallet/littlefs: "^1.14.8"
|
||||
|
||||
# Dependência local no seu disco (opcional)
|
||||
# meu_driver_local:
|
||||
# path: "../../components/meu_driver"`
|
||||
};
|
||||
@@ -0,0 +1,743 @@
|
||||
/**
|
||||
* Base de dados estruturada para o Guia de Diagnóstico, Erros Comuns e Resolução de Problemas no ESP32.
|
||||
* Abrange 6 categorias técnicas com causas raízes, comparativos de boas práticas vs gambiarras e exemplos de código
|
||||
* em Arduino C++, ESP-IDF (C) e MicroPython.
|
||||
*/
|
||||
|
||||
export const categoriasDiagnostico = [
|
||||
{
|
||||
id: "alimentacao",
|
||||
nome: "Alimentação & Hardware",
|
||||
icone: "Zap",
|
||||
cor: "amber",
|
||||
descricao: "Quedas de tensão por picos de RF Wi-Fi/BLE, strapping pins conflitantes, ruído eletromagnético e problemas de LDO.",
|
||||
},
|
||||
{
|
||||
id: "cpu-panics",
|
||||
nome: "Pânicos de CPU & Guru Meditation",
|
||||
icone: "Cpu",
|
||||
cor: "red",
|
||||
descricao: "Ponteiros nulos, violações de memória (Load/StoreProhibited), instruções ilegais e cache panics em ISR.",
|
||||
},
|
||||
{
|
||||
id: "freertos",
|
||||
nome: "FreeRTOS & Multitarefa",
|
||||
icone: "Layers",
|
||||
cor: "purple",
|
||||
descricao: "Task Watchdog (TWDT), Interrupt Watchdog (IWDT), estouro de pilha (Stack Overflow) e bloqueios de escalonador.",
|
||||
},
|
||||
{
|
||||
id: "memoria",
|
||||
nome: "Memória, Heap & PSRAM",
|
||||
icone: "Activity",
|
||||
cor: "blue",
|
||||
descricao: "Fragmentação de Heap, vazamento de memória (Memory Leaks), alocações para DMA e limitações de PSRAM.",
|
||||
},
|
||||
{
|
||||
id: "boot-flash",
|
||||
nome: "Bootloader & Gravação",
|
||||
icone: "Terminal",
|
||||
cor: "emerald",
|
||||
descricao: "Falha de comunicação serial (DTR/RTS), erros de leitura SPI Flash, incompatibilidade de clock e partições.",
|
||||
},
|
||||
{
|
||||
id: "conectividade",
|
||||
nome: "Conectividade & Protocolos",
|
||||
icone: "Wifi",
|
||||
cor: "cyan",
|
||||
descricao: "Wi-Fi Beacon Timeout, falhas de handshake TLS/HTTPS por falta de relógio SNTP e instabilidade de sinal.",
|
||||
},
|
||||
];
|
||||
|
||||
export const sintomasRapidos = [
|
||||
{ id: "bootloop", rotulo: "🔄 Reiniciando em loop (Bootloop)", categoria: "todos" },
|
||||
{ id: "wifi-crash", rotulo: "📶 Trava ao ligar Wi-Fi/BLE", categoria: "alimentacao" },
|
||||
{ id: "upload-fail", rotulo: "🔌 Falha ao gravar código (Upload)", categoria: "boot-flash" },
|
||||
{ id: "random-freeze", rotulo: "⏱️ Trava após minutos/horas", categoria: "memoria" },
|
||||
{ id: "null-pointer", rotulo: "💥 Guru Meditation (Crash)", categoria: "cpu-panics" },
|
||||
{ id: "wdt-reset", rotulo: "🐕 Watchdog Triggered", categoria: "freertos" },
|
||||
{ id: "tls-fail", rotulo: "🔒 Falha em HTTPS / SSL", categoria: "conectividade" },
|
||||
];
|
||||
|
||||
export const errosCatalogo = [
|
||||
{
|
||||
id: "brownout-reset",
|
||||
titulo: "Brownout Detector Reset (Queda de Tensão)",
|
||||
categoria: "alimentacao",
|
||||
sintomas: ["bootloop", "wifi-crash"],
|
||||
gravidade: "Alta",
|
||||
logSerial: "Brownout detector was triggered\n\nrst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)",
|
||||
resumo: "A tensão de alimentação do ESP32 caiu abaixo do limiar operacional seguro (aproximadamente 2.8V ~ 2.43V).",
|
||||
causaRaiz:
|
||||
"Quando o rádio Wi-Fi ou BLE é ligado, o estágio de potência (PA) consome pulsos de corrente muito rápidos que podem superar 500mA em menos de 1 milissegundo. Se a fonte de alimentação, os cabos USB longos/finos, os trilhos de protoboard ou o regulador LDO não fornecerem corrente instantânea com baixa impedância, a tensão no pino 3V3 do chip afunda momentaneamente, disparando o circuito comparador interno de Brownout para evitar corrupção de memória Flash e estados indeterminados.",
|
||||
gambiarra: {
|
||||
titulo: "Desativar o Brownout por software",
|
||||
descricao: "Chamar WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0) para silenciar o erro no código.",
|
||||
consequencia: "Extremamente perigoso: o ESP32 continuará executando instruções sob subtensão, corrompendo a memória Flash SPI, travando registradores e causando comportamento imprevisível em campo sem aviso.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Dimensionamento correto de hardware e desacoplamento",
|
||||
passos: [
|
||||
"Adicione um capacitor de tântalo ou cerâmico de 10µF a 100µF de baixo ESR (Low-ESR) em paralelo com um cerâmico de 100nF o mais próximo possível dos pinos 3V3 e GND do ESP32.",
|
||||
"Utilize reguladores LDO projetados para picos de no mínimo 600mA a 1A com excelente resposta a transitórios (ex: AP2112K, ME6211, TPS73733 ou XC6206 robusto). Evite clones de baixa qualidade do antigo AMS1117.",
|
||||
"Evite alimentar o ESP32 via trilhos compridos de protoboard com cabos jumper finos quando o Wi-Fi estiver transmitindo em potência máxima.",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// NÃO desative o Brownout! Se precisar reduzir o pico em testes:
|
||||
#include <WiFi.h>
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
// Opcional: Reduzir ligeiramente a potência máxima de transmissão do Wi-Fi
|
||||
// de 20dBm para 17dBm diminui o pico de corrente em ~20%
|
||||
WiFi.setTxPower(WIFI_POWER_17dBm);
|
||||
WiFi.begin("SSID", "SENHA");
|
||||
}`,
|
||||
codigoEspIdf: `// Configuração no ESP-IDF:
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
void app_main(void) {
|
||||
// No menuconfig: Component config -> ESP32-specific -> Hardware Brownout Reset (Mantenha sempre ATIVO)
|
||||
// Para mitigar picos em ambientes com limite de potência:
|
||||
esp_wifi_set_max_tx_power(68); // 68 = 17dBm (unidades de 0.25dBm)
|
||||
}`,
|
||||
codigoMicroPython: `# Conexão Wi-Fi segura no MicroPython com estabilização:
|
||||
import network
|
||||
import time
|
||||
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
|
||||
# Aguarda estabilização da alimentação antes de iniciar transmissão
|
||||
time.sleep_ms(200)
|
||||
wlan.connect("SSID", "SENHA")
|
||||
|
||||
tentativas = 0
|
||||
while not wlan.isconnected() and tentativas < 30:
|
||||
time.sleep_ms(200)
|
||||
tentativas += 1
|
||||
|
||||
if wlan.isconnected():
|
||||
print("Wi-Fi Conectado! IP:", wlan.ifconfig()[0])
|
||||
else:
|
||||
print("[ERRO] Falha ao conectar Wi-Fi")`,
|
||||
dicaPro: "Se estiver projetando sua própria PCB, coloque um plano de terra sólido sob o módulo e trilhas de alimentação com largura mínima de 0.5mm a 1mm para suportar os surtos de corrente sem queda resistiva (IR drop).",
|
||||
},
|
||||
{
|
||||
id: "strapping-pins",
|
||||
titulo: "Conflito de Strapping Pins no Boot",
|
||||
categoria: "alimentacao",
|
||||
sintomas: ["bootloop", "upload-fail"],
|
||||
gravidade: "Crítica",
|
||||
logSerial: "rst:0x1 (POWERON_RESET),boot:0x12 (SPI_FAST_FLASH_BOOT)\nflash read err, 1000\nwaiting for download",
|
||||
resumo: "O ESP32 não inicializa o firmware da Flash ou entra acidentalmente em modo de download porque um pino de strapping foi forçado a um nível lógico incorreto no reset.",
|
||||
causaRaiz:
|
||||
"No momento exato em que o pino EN/CHIP_PU sobe (Power-On Reset), a CPU amostra o estado de pinos específicos (Strapping Pins) para configurar tensão de Flash (1.8V vs 3.3V), modo de boot (Download UART vs SPI Flash) e saída de clock. Se você conectar sensores, relés ou LEDs com pull-up/pull-down nesses pinos, o microcontrolador lerá um nível lógico inválido e travará o boot.",
|
||||
gambiarra: {
|
||||
titulo: "Colocar delays no código ou desconectar na mão toda vez que liga",
|
||||
descricao: "Tentar tratar o problema via software no setup() ou depender de desconectar fios manualmente antes de cada reinicialização.",
|
||||
consequencia: "Inútil: os Strapping Pins são lidos por hardware antes mesmo da CPU carregar qualquer linha do seu código ou do bootloader.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Mapeamento seguro de GPIOs e isolamento no reset",
|
||||
passos: [
|
||||
"ESP32 Clássico: Evite usar GPIO 0 (Boot), GPIO 2 (deve estar LOW ou flutuando no flash), GPIO 12 (define tensão de Flash: se puxado para HIGH no reset, queima/trava a flash de 3.3V) e GPIO 15 (silencia mensagens de log de boot se LOW).",
|
||||
"ESP32-C3: Evite puxar GPIO 8 para LOW ou GPIO 9 para LOW no reset.",
|
||||
"ESP32-S3: Atenção com GPIO 0, GPIO 45 (tensão VDD_SPI) e GPIO 46.",
|
||||
"Se for estritamente necessário usar esses pinos para periféricos, utilize transistores ou buffers para isolá-los até que o sinal EN esteja totalmente estabilizado.",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// RECOMENDAÇÃO DE PINAGEM SEGURA (ESP32 Clássico):
|
||||
// Pinos ideais para I2C / SPI / Sensores gerais:
|
||||
// SDA: GPIO 21 | SCL: GPIO 22
|
||||
// SPI: MOSI 23 | MISO 19 | SCK 18 | CS 5
|
||||
|
||||
// ATENÇÃO: GPIOs 34, 35, 36 (VP), 39 (VN) são APENAS ENTRADA (sem pull-up interno).
|
||||
// Nunca tente usá-los como pinMode(..., OUTPUT); nem para I2C/SPI.`,
|
||||
codigoEspIdf: `// No ESP-IDF, proteja a configuração de tensão de Flash via eFuse (CUIDADO: IRREVERSÍVEL):
|
||||
// Se você usa ESP32 clássico e precisa liberar GPIO12, pode queimar o eFuse de 3.3V:
|
||||
// espefuse.py --port /dev/ttyUSB0 set_flash_voltage 3.3V
|
||||
// Isso desativa a amostragem de hardware no GPIO12 para sempre.`,
|
||||
codigoMicroPython: `# Configuração correta de pinos no MicroPython:
|
||||
from machine import Pin
|
||||
|
||||
# ✅ Pinos seguros para saídas e botões com pull-up interno:
|
||||
led = Pin(2, Pin.OUT) # GPIO 2
|
||||
botao = Pin(4, Pin.IN, Pin.PULL_UP) # GPIO 4 (seguro)
|
||||
|
||||
# ⚠️ Pinos 34, 35, 36, 39 são APENAS ENTRADA e não têm pull-up interno:
|
||||
sensor_analogico = Pin(36, Pin.IN) # Correto (requer resistor externo se for botão)`,
|
||||
dicaPro: "Lembre-se sempre: pinos 'Input-Only' (GPI 34 a 39 no ESP32 clássico) não possuem circuitos de pull-up/pull-down de silício nem transistores de saída. Sensores analógicos ou botões neles exigem resistores de pull-up externos.",
|
||||
},
|
||||
{
|
||||
id: "guru-load-prohibited",
|
||||
titulo: "Guru Meditation: LoadProhibited / StoreProhibited",
|
||||
categoria: "cpu-panics",
|
||||
sintomas: ["bootloop", "null-pointer"],
|
||||
gravidade: "Crítica",
|
||||
logSerial: "Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.\nCore 0 register dump:\nPC : 0x400d14bc PS : 0x00060830 A0 : 0x800d1512 A1 : 0x3ffb1f20 \nEXCVADDR: 0x00000000",
|
||||
resumo: "A CPU tentou ler (Load) ou escrever (Store) em um endereço de memória inacessível ou inválido, tipicamente o endereço nulo 0x00000000.",
|
||||
causaRaiz:
|
||||
"Essa é a clássica desreferência de ponteiro nulo (Null Pointer Dereference) ou uso de ponteiro solto (Dangling Pointer). O registrador EXCVADDR indica o endereço que causou a falha: se EXCVADDR for 0x00000000 ou muito próximo de zero (ex: 0x00000008, que é um offset de struct), significa que você tentou acessar membros de um objeto/ponteiro que não foi inicializado ou cujo malloc/criação falhou.",
|
||||
gambiarra: {
|
||||
titulo: "Adicionar delays aleatórios ou reiniciar no loop sem tratar",
|
||||
descricao: "Achar que é problema de temporização e encher o código de delay() ou mascarar o reinício automático sem investigar a causa.",
|
||||
consequencia: "O sistema continuará quebrando aleatoriamente em produção quando a condição de ponteiro nulo se repetir.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Validação defensiva e Decodificação de Backtrace",
|
||||
passos: [
|
||||
"Verifique sempre se retornos de funções de alocação ou busca (malloc, WiFi.client(), JSON parsing, xQueueReceive) não retornaram NULL antes de acessar seus campos.",
|
||||
"Instale o 'Espressif Exception Decoder' na sua IDE (Arduino IDE / PlatformIO) ou use o comando 'xtensa-esp32-elf-addr2line -pfia -e firmware.elf 0x400d14bc' para descobrir exatamente a linha do seu código .c/.cpp onde o crash aconteceu.",
|
||||
"No ESP-IDF, execute 'idf.py monitor' que decodifica o backtrace de pilha automaticamente em tempo real.",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// PROGRAMAÇÃO DEFENSIVA:
|
||||
struct SensorData {
|
||||
float temperatura;
|
||||
float umidade;
|
||||
};
|
||||
|
||||
void processarSensor(SensorData* sensor) {
|
||||
// Verificação obrigatória contra LoadProhibited:
|
||||
if (sensor == nullptr) {
|
||||
Serial.println("[ERRO] Ponteiro de sensor nulo!");
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.printf("Temp: %.1f C\\n", sensor->temperatura);
|
||||
}`,
|
||||
codigoEspIdf: `// No ESP-IDF, use ESP_ERROR_CHECK ou assertivas explícitas:
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
static const char* TAG = "SENSOR";
|
||||
|
||||
esp_err_t ler_dado(char* buffer, size_t max_len) {
|
||||
ESP_RETURN_ON_FALSE(buffer != NULL, ESP_ERR_INVALID_ARG, TAG, "Buffer nulo fornecido!");
|
||||
// Operação segura...
|
||||
return ESP_OK;
|
||||
}`,
|
||||
codigoMicroPython: `# Prevenção contra NoneType e exceções de objeto no MicroPython:
|
||||
import json
|
||||
|
||||
def processar_sensor(dados_raw):
|
||||
# Proteção defensiva contra payload nulo:
|
||||
if dados_raw is None:
|
||||
print("[ERRO] Dados nulos recebidos!")
|
||||
return None
|
||||
|
||||
try:
|
||||
obj = json.loads(dados_raw)
|
||||
# Uso seguro de .get() com valor padrão para evitar KeyError
|
||||
temperatura = obj.get("temp", 0.0)
|
||||
return temperatura
|
||||
except (ValueError, AttributeError) as e:
|
||||
print("Erro ao processar objeto:", e)
|
||||
return None`,
|
||||
dicaPro: "Se EXCVADDR for algo como 0x3fxxxxxx ou 0x40xxxxxx mas seu código falha, você pode estar acessando um array fora do limite (buffer overflow) que sobrescreveu ponteiros na memória.",
|
||||
},
|
||||
{
|
||||
id: "guru-iram-cache",
|
||||
titulo: "Cache Error / InstructionFetchError em ISRs",
|
||||
categoria: "cpu-panics",
|
||||
sintomas: ["bootloop", "null-pointer"],
|
||||
gravidade: "Alta",
|
||||
logSerial: "Guru Meditation Error: Core 0 panic'ed (Cache disabled but cached memory region accessed)\nGuru Meditation Error: Core 0 panic'ed (InstructionFetchError)",
|
||||
resumo: "Uma rotina de interrupção (ISR) tentou executar código ou ler dados da Flash SPI enquanto a Flash estava desativada para uma operação de escrita/leitura.",
|
||||
causaRaiz:
|
||||
"Por padrão, o código do ESP32 fica armazenado na memória Flash externa e é carregado sob demanda para a CPU através da memória Cache interna. Quando o ESP32 grava dados na Flash (como em gravações NVS, LittleFS, SPIFFS ou atualização OTA), o controlador desativa o Cache de instruções temporariamente. Se uma interrupção de hardware (timer, GPIO, etc.) disparar nesse instante e a função ISR estiver na Flash, a CPU não consegue buscar a próxima instrução e entra em pânico imediato.",
|
||||
gambiarra: {
|
||||
titulo: "Desativar interrupções antes de gravar na Flash",
|
||||
descricao: "Tentar envolver operações de gravação de arquivos em blocos de noInterrupts() indiscriminadamente.",
|
||||
consequencia: "Gera perda de pulsos de sensores de alta velocidade, instabilidade nos timers do sistema e potenciais estouros de Watchdog.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Alocar ISRs e constantes em IRAM / DRAM",
|
||||
passos: [
|
||||
"Decore TODA função de callback de interrupção com o atributo IRAM_ATTR (ou IRAM_ATTR static void...).",
|
||||
"Garanta que variáveis ou strings acessadas dentro da ISR também residam em DRAM (evite usar strings literais diretas dentro da ISR sem a tag DRAM_ATTR no ESP-IDF).",
|
||||
"Nunca chame funções pesadas de bibliotecas externas (como Serial.print ou cálculos de float pesados) dentro de uma ISR.",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// ISR declarada corretamente na IRAM:
|
||||
volatile uint32_t contadorPulsos = 0;
|
||||
|
||||
void IRAM_ATTR tratarInterrupcaoGPIO() {
|
||||
contadorPulsos++;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
pinMode(4, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(4), tratarInterrupcaoGPIO, FALLING);
|
||||
}`,
|
||||
codigoEspIdf: `// No ESP-IDF:
|
||||
#include "esp_attr.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
static volatile uint32_t pulsos = 0;
|
||||
|
||||
// Função colocada explicitamente na memória interna IRAM:
|
||||
static void IRAM_ATTR gpio_isr_handler(void* arg) {
|
||||
pulsos++;
|
||||
}
|
||||
|
||||
void app_main(void) {
|
||||
gpio_install_isr_service(ESP_INTR_FLAG_IRAM);
|
||||
gpio_isr_handler_add(GPIO_NUM_4, gpio_isr_handler, NULL);
|
||||
}`,
|
||||
codigoMicroPython: `# Tratamento seguro de interrupções (ISR) no MicroPython:
|
||||
import micropython
|
||||
from machine import Pin
|
||||
|
||||
# Aloca buffer de emergência para depurar exceções dentro de ISRs:
|
||||
micropython.alloc_emergency_exception_buf(100)
|
||||
|
||||
contador_pulsos = 0
|
||||
|
||||
# Callback de interrupção: NÃO aloque memória (sem strings, sem floats novos)
|
||||
def tratar_pulso(pin):
|
||||
global contador_pulsos
|
||||
contador_pulsos += 1
|
||||
|
||||
sensor = Pin(4, Pin.IN, Pin.PULL_UP)
|
||||
sensor.irq(trigger=Pin.IRQ_FALLING, handler=tratar_pulso)`,
|
||||
dicaPro: "Se você passar ESP_INTR_FLAG_IRAM ao registrar a interrupção no ESP-IDF, qualquer função chamada por essa interrupção (inclusive funções do FreeRTOS) DEVE suportar IRAM (ex: xQueueSendFromISR).",
|
||||
},
|
||||
{
|
||||
id: "freertos-twdt",
|
||||
titulo: "Task Watchdog Timer (TWDT) Timeout",
|
||||
categoria: "freertos",
|
||||
sintomas: ["bootloop", "wdt-reset"],
|
||||
gravidade: "Crítica",
|
||||
logSerial: "E (10532) task_wdt: Task watchdog got triggered. The following tasks/users did not reset the watchdog in time:\nE (10532) task_wdt: - IDLE0 (CPU 0)\nTask watchdog got triggered. System will be reset.",
|
||||
resumo: "Uma tarefa de alta prioridade entrou em um loop bloqueante e não cedeu tempo de CPU, impedindo que a tarefa IDLE alimente o cão de guarda.",
|
||||
causaRaiz:
|
||||
"O FreeRTOS no ESP32 executa uma tarefa essencial de prioridade 0 chamada IDLE em cada núcleo de CPU. O Task Watchdog monitora se a tarefa IDLE consegue rodar periodicamente (por padrão, a cada 5 segundos). Se você criar uma tarefa com prioridade >= 1 que contenha um loop while(1) sem nenhuma chamada bloqueante (vTaskDelay, leitura de fila, semáforo), a CPU fica 100% ocupada e o Watchdog dispara um reset de emergência.",
|
||||
gambiarra: {
|
||||
titulo: "Desabilitar o Task Watchdog no menuconfig ou aumentar para 60s",
|
||||
descricao: "Desligar o TWDT para o código parar de reiniciar.",
|
||||
consequencia: "Se o seu código travar em um loop infinito ou deadlock, o microcontrolador ficará congelado para sempre, exigindo que alguém vá até o local desligar da tomada.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Arquitetura orientada a eventos e concessão de CPU (Yield)",
|
||||
passos: [
|
||||
"Nunca utilize loops de espera ativa vazios while(!condicao); em tarefas FreeRTOS.",
|
||||
"Sempre insira vTaskDelay(pdMS_TO_TICKS(10)) ou espere por um evento através de xQueueReceive(), ulTaskNotifyTake() ou xSemaphoreTake() com timeout.",
|
||||
"Se for necessário executar um processamento matemático contínuo e pesado, alimente o Watchdog explicitamente com esp_task_wdt_reset().",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// FORMA CORRETA NO ARDUINO COM FREERTOS:
|
||||
void minhaTarefa(void *pvParameters) {
|
||||
for (;;) {
|
||||
// Executa a leitura do sensor
|
||||
float valor = analogRead(36);
|
||||
|
||||
// LIBERA a CPU para o FreeRTOS e a tarefa IDLE:
|
||||
vTaskDelay(pdMS_TO_TICKS(100)); // Aguarda 100ms de forma não-bloqueante
|
||||
}
|
||||
}`,
|
||||
codigoEspIdf: `// ESP-IDF com Task Watchdog:
|
||||
#include "esp_task_wdt.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
void tarefa_processamento(void *pvParameters) {
|
||||
// Opcional: Inscrever a própria tarefa no TWDT
|
||||
esp_task_wdt_add(NULL);
|
||||
|
||||
while (1) {
|
||||
// Processamento...
|
||||
|
||||
// Alimenta o Watchdog se o bloco for longo:
|
||||
esp_task_wdt_reset();
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
}`,
|
||||
codigoMicroPython: `# Watchdog e laços não-bloqueantes com uasyncio no MicroPython:
|
||||
from machine import WDT
|
||||
import uasyncio as asyncio
|
||||
|
||||
# Inicializa o Watchdog de hardware com timeout de 5 segundos
|
||||
wdt = WDT(timeout=5000)
|
||||
|
||||
async def tarefa_sensor():
|
||||
while True:
|
||||
# Alimenta o cão de guarda a cada ciclo saudável:
|
||||
wdt.feed()
|
||||
|
||||
# Cede controle para o escalonador cooperativo:
|
||||
await asyncio.sleep_ms(100)
|
||||
|
||||
async def main():
|
||||
asyncio.create_task(tarefa_sensor())
|
||||
while True:
|
||||
await asyncio.sleep(1)
|
||||
|
||||
asyncio.run(main())`,
|
||||
dicaPro: "No Arduino, a função delay(ms) na verdade chama internamente o vTaskDelay do FreeRTOS. Porém, loops que usam delayMicroseconds() ou operações puras de CPU não cedem tempo e podem disparar o TWDT se durarem mais de alguns segundos.",
|
||||
},
|
||||
{
|
||||
id: "freertos-stack-overflow",
|
||||
titulo: "Stack Overflow (Estouro de Pilha da Tarefa)",
|
||||
categoria: "freertos",
|
||||
sintomas: ["bootloop", "null-pointer"],
|
||||
gravidade: "Crítica",
|
||||
logSerial: "Guru Meditation Error: Core 1 panic'ed (Unhandled debug exception).\nDebug exception reason: Stack canary watchpoint triggered (minha_tarefa)",
|
||||
resumo: "A tarefa consumiu mais memória de pilha (Stack) do que a quantidade alocada em sua criação, corrompendo o canário de proteção do RTOS.",
|
||||
causaRaiz:
|
||||
"Cada tarefa no FreeRTOS recebe um bloco fixo de memória contígua para suas variáveis locais, argumentos de funções e endereços de retorno de chamadas. Se você declarar arrays grandes (ex: char buffer[2048];), instanciar buffers JSON pesados (ex: DynamicJsonDocument doc(4096);), ou fizer chamadas recursivas profundas dentro de uma tarefa configurada com stack padrão de 2048 bytes, a pilha ultrapassa o limite e sobrescreve áreas críticas do sistema.",
|
||||
gambiarra: {
|
||||
titulo: "Colocar 64KB de stack em todas as tarefas sem critério",
|
||||
descricao: "Alocar stacks gigantescas para não se preocupar com estouro.",
|
||||
consequencia: "A memória interna SRAM do ESP32 (cerca de 320KB úteis) se esgotará rapidamente, causando falhas de inicialização do Wi-Fi e alocação de heap.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Dimensionamento consciente e monitoramento com HighWaterMark",
|
||||
passos: [
|
||||
"Meça o consumo real da pilha usando a função uxTaskGetStackHighWaterMark(). Ela retorna o menor número de bytes/words livres restantes que a pilha teve desde o boot.",
|
||||
"Mova buffers volumosos da pilha para a Heap dinâmica (usando malloc/free temporário) ou declare-os como static fora do escopo da função se forem reutilizados.",
|
||||
"Tarefas que utilizam conexões seguras TLS/HTTPS ou MQTT com SSL exigem no mínimo 6KB a 8KB de stack devido à complexidade das rotinas criptográficas do MbedTLS.",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// MONITORANDO O STACK NO ARDUINO:
|
||||
void tarefaSensor(void *pvParameters) {
|
||||
for (;;) {
|
||||
// Código da tarefa...
|
||||
|
||||
// Verifica o espaço livre mínimo da pilha (em Words no FreeRTOS clássico / Bytes no ESP32)
|
||||
UBaseType_t espacoLivre = uxTaskGetStackHighWaterMark(NULL);
|
||||
Serial.printf("[STACK] Espaço livre mínimo: %d bytes\\n", (int)espacoLivre);
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||
}
|
||||
}
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
// Aloca 4096 bytes (4KB) de forma equilibrada:
|
||||
xTaskCreatePinnedToCore(tarefaSensor, "tarefaSensor", 4096, NULL, 1, NULL, 1);
|
||||
}`,
|
||||
codigoEspIdf: `// Habilite a checagem dupla de Stack no menuconfig:
|
||||
// Component config -> FreeRTOS -> Set a end of stack check -> Option 2 (Check by Stack Canary)
|
||||
// Isso detecta o estouro ANTES que dados sejam corrompidos em tempo de execução.`,
|
||||
codigoMicroPython: `# Monitoramento de memória e pilha no MicroPython:
|
||||
import gc
|
||||
import micropython
|
||||
|
||||
# Exibe estatísticas de memória RAM e pilha da VM do Python:
|
||||
micropython.mem_info()
|
||||
|
||||
# Executa garbage collector para liberar blocos órfãos:
|
||||
gc.collect()
|
||||
print("Memória Heap Livre:", gc.mem_free(), "bytes")
|
||||
print("Memória Heap Alocada:", gc.mem_alloc(), "bytes")`,
|
||||
dicaPro: "Se a sua função precisa processar um JSON ou pacote HTTP esporadicamente, aloque o buffer no Heap apenas durante o processamento e libere-o logo em seguida, em vez de inflar o Stack permanente da tarefa.",
|
||||
},
|
||||
{
|
||||
id: "memoria-fragmentacao-heap",
|
||||
titulo: "Fragmentação de Heap e Memory Leaks",
|
||||
categoria: "memoria",
|
||||
sintomas: ["random-freeze", "tls-fail"],
|
||||
gravidade: "Alta",
|
||||
logSerial: "E (45892) mbedtls: mbedtls_ssl_setup returned -0x7f00\nE (45892) esp-tls: create_ssl_handle failed\nE (45893) HTTP_CLIENT: Connection failed, out of memory",
|
||||
resumo: "O microcontrolador falha ao alocar memória mesmo reportando uma quantidade total de memória livre aparentemente alta.",
|
||||
causaRaiz:
|
||||
"A memória Heap fica fragmentada quando ocorrem milhares de alocações e desalocações de tamanhos variados ao longo do tempo (muito comum ao usar objetos String do Arduino com concatenação contínua de texto em loops). O heap se divide em pequenos blocos livres separados por blocos ocupados. Quando o driver de Wi-Fi ou a biblioteca TLS precisa de um único bloco contíguo de 40KB para o buffer de criptografia SSL, o malloc falha mesmo que existam 100KB de memória livre total dispersa.",
|
||||
gambiarra: {
|
||||
titulo: "Reiniciar o ESP32 periodicamente com ESP.restart() a cada X horas",
|
||||
descricao: "Agendar um reboot diário para limpar a memória fragmentada.",
|
||||
consequencia: "Apenas camufla o defeito: em condições de pico de requisições o dispositivo cairá muito antes do reboot programado.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Evitar strings dinâmicas e utilizar buffers estáticos pré-alocados",
|
||||
passos: [
|
||||
"No Arduino, evite a classe String. Utilize buffers de caracteres em estilo C (char buffer[128];) com funções seguras como snprintf().",
|
||||
"Monitore a fragmentação acompanhando a relação entre a memória livre total (heap_caps_get_free_size) e o maior bloco contíguo livre (heap_caps_get_largest_free_block).",
|
||||
"Em firmwares complexos no ESP-IDF, ative o Heap Memory Tracing (CONFIG_HEAP_TRACING) para listar exatamente quais arquivos e linhas esqueceram de chamar free().",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// COMPARAÇÃO:
|
||||
// ❌ EVITE (Gera fragmentação severa de Heap):
|
||||
// String json = "{\\"temp\\":";
|
||||
// json += String(temperatura) + "}";
|
||||
|
||||
// ✅ CORRETO (Sem alocação dinâmica no Heap):
|
||||
char payload[64];
|
||||
snprintf(payload, sizeof(payload), "{\\"temp\\":%.2f,\\"umid\\":%.2f}", temperatura, umidade);
|
||||
|
||||
// Monitoramento:
|
||||
Serial.printf("Heap Livre: %u | Maior Bloco: %u\\n",
|
||||
ESP.getFreeHeap(),
|
||||
ESP.getMaxAllocHeap());`,
|
||||
codigoEspIdf: `// Monitoramento de Heap no ESP-IDF:
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
void inspecionar_memoria(void) {
|
||||
size_t livre_total = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t maior_bloco = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
|
||||
|
||||
ESP_LOGI("HEAP", "Total livre: %d bytes | Maior bloco continuo: %d bytes", livre_total, maior_bloco);
|
||||
}`,
|
||||
codigoMicroPython: `# Prevenção de fragmentação de Heap no MicroPython:
|
||||
import gc
|
||||
|
||||
# 1. Habilita coleta automática
|
||||
gc.enable()
|
||||
|
||||
# 2. Pré-aloque bytearrays para reaproveitamento em vez de criar novas strings:
|
||||
buffer_leitura = bytearray(256)
|
||||
|
||||
def ler_sensor_sem_alocacao(stream):
|
||||
# Lê reutilizando o mesmo espaço em memória (Zero-Allocation):
|
||||
bytes_lidos = stream.readinto(buffer_leitura)
|
||||
return buffer_leitura[:bytes_lidos]
|
||||
|
||||
# 3. Dispare o GC antes de abrir conexões pesadas (como HTTPS / TLS):
|
||||
gc.collect()
|
||||
print(f"Heap Livre: {gc.mem_free()} B | Alocado: {gc.mem_alloc()} B")`,
|
||||
dicaPro: "Se o maior bloco contíguo livre for menor que 35KB ~ 40KB, conexões HTTPS/TLS modernas falharão durante o handshake de certificados.",
|
||||
},
|
||||
{
|
||||
id: "memoria-dma-psram",
|
||||
titulo: "Falha de Alocação DMA em Memória Externa (PSRAM)",
|
||||
categoria: "memoria",
|
||||
sintomas: ["bootloop", "random-freeze"],
|
||||
gravidade: "Alta",
|
||||
logSerial: "E (1204) spi_master: spi_bus_initialize: DMA channel not compatible with external RAM buffer\nESP_ERROR_CHECK failed: esp_err_t 0x102 (ESP_ERR_INVALID_ARG)",
|
||||
resumo: "O firmware tentou passar um buffer alocado em PSRAM externa para um periférico com DMA (SPI, I2S, LCD, SDMMC) que só tem acesso à SRAM interna.",
|
||||
causaRaiz:
|
||||
"Nos chips da família ESP32 (especialmente ESP32 clássico, ESP32-S2 e ESP32-S3 com barramento padrão), o controlador de DMA dos periféricos não possui barramento físico com acesso direto à memória PSRAM externa conectada via SPI/QSPI. O DMA exige que os buffers de transmissão e recepção estejam obrigatoriamente localizados na SRAM interna do chip.",
|
||||
gambiarra: {
|
||||
titulo: "Desativar o DMA nos periféricos",
|
||||
descricao: "Configurar o barramento SPI/I2S para operar em modo por polling sem DMA.",
|
||||
consequencia: "A taxa de transferência cai drasticamente e a CPU fica 100% ocupada durante o envio de frames para displays ou streaming de áudio.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Alocação explícita com MALLOC_CAP_DMA e MALLOC_CAP_INTERNAL",
|
||||
passos: [
|
||||
"Sempre aloque buffers dedicados a DMA utilizando a função heap_caps_malloc(tamanho, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL).",
|
||||
"Mantenha dados pesados não-DMA (como imagens decodificadas, modelos de machine learning e áudio em repouso) na PSRAM, e copie blocos menores para buffers de DMA internos sob demanda (ping-pong buffering).",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// Alocando buffer para DMA no Arduino ESP32:
|
||||
#include <esp_heap_caps.h>
|
||||
|
||||
uint8_t* dmaBuffer = nullptr;
|
||||
|
||||
void setup() {
|
||||
size_t tamanho = 4096;
|
||||
// Garante que o buffer reside na SRAM interna compatível com DMA:
|
||||
dmaBuffer = (uint8_t*) heap_caps_malloc(tamanho, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
|
||||
if (dmaBuffer == nullptr) {
|
||||
Serial.println("[ERRO] Falha ao alocar buffer DMA na memória interna!");
|
||||
}
|
||||
}`,
|
||||
codigoEspIdf: `// ESP-IDF:
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
uint8_t* alocar_buffer_spi(size_t len) {
|
||||
return (uint8_t*) heap_caps_aligned_alloc(4, len, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
}`,
|
||||
codigoMicroPython: `# No MicroPython, verifique a memória PSRAM disponível:
|
||||
import gc
|
||||
import esp32
|
||||
|
||||
# Se o firmware foi compilado com suporte a SPIRAM (ex: firmwares com 'SPIRAM'):
|
||||
print("Memória total acessível no MicroPython:", gc.mem_free() + gc.mem_alloc(), "bytes")
|
||||
|
||||
# Para operações rápidas com periféricos, use bytearrays contíguos:
|
||||
buffer_spi = bytearray(1024)`,
|
||||
dicaPro: "No ESP32-P4, a arquitetura avançada de barramento AXI permite DMA em certas regiões externas, mas para toda a linha ESP32/S2/S3/C3 a regra da SRAM interna é estrita.",
|
||||
},
|
||||
{
|
||||
id: "boot-failed-connect",
|
||||
titulo: "Failed to connect to ESP32: Timed out waiting for packet header",
|
||||
categoria: "boot-flash",
|
||||
sintomas: ["upload-fail"],
|
||||
gravidade: "Média",
|
||||
logSerial: "A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header\nesptool.py v4.6\nConnecting...................",
|
||||
resumo: "A ferramenta de gravação (esptool / Arduino IDE / PlatformIO) não conseguiu colocar o microcontrolador no modo de bootloader UART.",
|
||||
causaRaiz:
|
||||
"Para iniciar a gravação do firmware, o chip de conversão USB-Serial (CH340, CP2102, FTDI) utiliza as linhas DTR e RTS para puxar o pino GPIO 0 para LOW enquanto pulsa o pino EN/RST para LOW e depois HIGH. Em muitas placas de desenvolvimento populares, o circuito de temporização RC (resistor-capacitor) do pino EN não possui capacitância suficiente para segurar o reset durante a transição do sinal DTR.",
|
||||
gambiarra: {
|
||||
titulo: "Ficar segurando o botão BOOT com o dedo a cada upload",
|
||||
descricao: "Pressionar o botão físico BOOT/GPIO0 toda vez que o compilador terminar de gerar o binário.",
|
||||
consequencia: "Inconveniente para desenvolvimento ágil e impossível em placas seladas ou embutidas dentro de gabinetes.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Capacitor de 10µF no pino EN ou verificação do cabo de dados",
|
||||
passos: [
|
||||
"Conecte um capacitor eletrolítico ou cerâmico de 10µF (ou 1µF a 10µF) entre o pino EN (RST) e o GND da placa. Isso estabiliza a rampa de reset automático.",
|
||||
"Verifique se o cabo USB possui linhas de dados (D+ e D-) ativas. Muitos cabos de carregador de celular baratos possuem apenas os fios de alimentação VBUS e GND.",
|
||||
"No Linux, certifique-se de que seu usuário pertence ao grupo 'dialout' (sudo usermod -a -G dialout $USER) e que o serviço 'brltty' não está sequestrando a porta serial.",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// Dica de Linha de Comando para testar a comunicação serial com o esptool:
|
||||
// python -m esptool --port /dev/ttyUSB0 chip_id
|
||||
// Se retornar o MAC e o modelo do chip, a comunicação física está perfeita.`,
|
||||
codigoEspIdf: `// No ESP-IDF:
|
||||
// idf.py -p /dev/ttyUSB0 -b 460800 flash
|
||||
// Se o upload falhar em altas velocidades, reduza a taxa de baud rate para 115200:
|
||||
// idf.py -p /dev/ttyUSB0 -b 115200 flash`,
|
||||
codigoMicroPython: `# Gravação do firmware MicroPython oficial no ESP32 via terminal:
|
||||
# 1. Apague a memória Flash:
|
||||
# esptool.py --port /dev/ttyUSB0 erase_flash
|
||||
|
||||
# 2. Grave o binário com taxa de baud segura:
|
||||
# esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 460800 write_flash -z 0x1000 ESP32_GENERIC-*.bin`,
|
||||
dicaPro: "Se estiver usando módulos ESP32-S3 ou C3 com USB nativo (Direct USB-JTAG), certifique-se de que a porta correta selecionada é a porta CDC/JTAG e não a UART legada.",
|
||||
},
|
||||
{
|
||||
id: "tls-sntp-clock-fail",
|
||||
titulo: "Falha de Handshake TLS/HTTPS por Relógio Desincronizado",
|
||||
categoria: "conectividade",
|
||||
sintomas: ["tls-fail", "random-freeze"],
|
||||
gravidade: "Alta",
|
||||
logSerial: "E (15420) esp-tls-mbedtls: mbedtls_ssl_handshake returned -0x2700\nE (15420) esp-tls: Failed to verify peer certificate!\nE (15421) esp-tls: Verification info: The certificate is not yet valid (or has expired)",
|
||||
resumo: "Conexões seguras HTTPS, AWS IoT, MQTT com TLS ou APIs Web falham porque o relógio interno do ESP32 está na data padrão de 01/01/1970.",
|
||||
causaRaiz:
|
||||
"Certificados de segurança digitais (X.509 SSL/TLS) possuem um período estrito de validade (Not Before e Not After). Como o ESP32 não possui uma bateria de RTC externa por padrão, ao ligar seu relógio interno sempre inicia na época Unix zero (1970). Quando o cliente MbedTLS valida a data do certificado do servidor, considera que o certificado 'ainda não é válido' (pois 2026 é no futuro em relação a 1970) e aborta a conexão criptografada imediatamente com o erro -0x2700 (MBEDTLS_ERR_X509_CERT_VERIFY_FAILED).",
|
||||
gambiarra: {
|
||||
titulo: "Desativar a validação de certificados SSL (Insecure / No-Verify)",
|
||||
descricao: "Usar client.setInsecure() no Arduino ou desabilitar checagem de CA no ESP-IDF.",
|
||||
consequencia: "Abre brecha gravíssima de segurança: seu dispositivo fica vulnerável a ataques de Man-in-the-Middle (MitM), permitindo que invasores interceptem senhas e firmwares.",
|
||||
},
|
||||
solucaoEngenharia: {
|
||||
titulo: "Sincronização obrigatória de data e hora via SNTP antes de conexões TLS",
|
||||
passos: [
|
||||
"Logo após obter IP no Wi-Fi, inicie o cliente SNTP apontando para servidores confiáveis (ex: pool.ntp.br, time.google.com).",
|
||||
"Aguarde o status do relógio atingir o estado sincronizado antes de iniciar a primeira conexão HTTPS/MQTT.",
|
||||
"Configure o fuso horário (Timezone) correto para formatar logs com horários precisos.",
|
||||
],
|
||||
},
|
||||
codigoArduino: `// SINCRONIZAÇÃO SNTP ANTES DO HTTPS NO ARDUINO:
|
||||
#include <WiFi.h>
|
||||
#include <time.h>
|
||||
|
||||
void sincronizarRelogio() {
|
||||
// Configura servidores NTP (NTP Brasil e Google)
|
||||
configTime(-3 * 3600, 0, "a.st1.ntp.br", "time.google.com");
|
||||
|
||||
Serial.print("Aguardando sincronizacao de horario");
|
||||
time_t now = time(nullptr);
|
||||
// Ano 2020 em Unix time é 1577836800. Se for menor, ainda está em 1970:
|
||||
while (now < 1577836800) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
now = time(nullptr);
|
||||
}
|
||||
Serial.println("\\n[OK] Horario sincronizado! Conexoes TLS liberadas.");
|
||||
}`,
|
||||
codigoEspIdf: `// SNTP no ESP-IDF:
|
||||
#include "esp_sntp.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
void inicializar_sntp(void) {
|
||||
ESP_LOGI("SNTP", "Iniciando cliente SNTP...");
|
||||
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
esp_sntp_setservername(0, "pool.ntp.br");
|
||||
esp_sntp_init();
|
||||
|
||||
// Aguarda sincronização do relógio...
|
||||
}`,
|
||||
codigoMicroPython: `# Sincronização SNTP e requisições HTTPS no MicroPython:
|
||||
import ntptime
|
||||
import time
|
||||
import urequests
|
||||
|
||||
def sincronizar_e_requisitar():
|
||||
try:
|
||||
print("Sincronizando relógio via NTP...")
|
||||
ntptime.host = "pool.ntp.br"
|
||||
ntptime.settime() # Atualiza o RTC interno do ESP32 via NTP
|
||||
print("Hora sincronizada UTC:", time.localtime())
|
||||
|
||||
# Agora o handshake TLS validará o certificado sem o erro -0x2700:
|
||||
resposta = urequests.get("https://api.github.com")
|
||||
print("Resposta HTTPS:", resposta.status_code)
|
||||
resposta.close()
|
||||
except Exception as e:
|
||||
print("[ERRO TLS/NTP]:", e)`,
|
||||
dicaPro: "Se seu projeto opera em ambientes sem acesso à internet externa (rede local isolada), configure um servidor NTP local no roteador ou adicione um módulo RTC físico como o DS3231 via I2C.",
|
||||
},
|
||||
];
|
||||
|
||||
export const regrasDecodificadorLog = [
|
||||
{
|
||||
padrao: /Brownout detector was triggered/i,
|
||||
titulo: "Brownout Detector (Subtensão Crítica)",
|
||||
tipo: "Alimentação / Hardware",
|
||||
explicacao:
|
||||
"A tensão no pino 3V3 do ESP32 caiu abaixo do nível seguro (geralmente por pico de corrente do rádio Wi-Fi/BLE ou fonte subdimensionada).",
|
||||
acaoRecomendada:
|
||||
"Adicione capacitor de 10µF a 100µF Low-ESR no VCC, use fonte estável e verifique o regulador LDO.",
|
||||
},
|
||||
{
|
||||
padrao: /LoadProhibited|StoreProhibited/i,
|
||||
titulo: "Guru Meditation: Load/StoreProhibited (Ponteiro Nulo ou Inválido)",
|
||||
tipo: "CPU Panic / Exceção",
|
||||
explicacao:
|
||||
"Tentativa de ler ou gravar em um endereço inválido na memória (quase sempre desreferência de ponteiro NULL ou array fora de limite).",
|
||||
acaoRecomendada:
|
||||
"Decodifique o Backtrace com o Exception Decoder ou 'addr2line' para identificar a linha exata. Adicione checagens defensivas `if (ptr != NULL)`.",
|
||||
},
|
||||
{
|
||||
padrao: /Cache disabled but cached memory region accessed|InstructionFetchError/i,
|
||||
titulo: "Cache Error em Interrupção (ISR fora da IRAM)",
|
||||
tipo: "CPU Panic / Flash",
|
||||
explicacao:
|
||||
"Uma rotina de interrupção (ISR) tentou rodar a partir da memória Flash enquanto ela estava ocupada gravando dados (NVS, LittleFS ou OTA).",
|
||||
acaoRecomendada:
|
||||
"Adicione o atributo `IRAM_ATTR` na função de interrupção e garanta que ela não acesse variáveis na Flash sem DRAM_ATTR.",
|
||||
},
|
||||
{
|
||||
padrao: /Task watchdog got triggered/i,
|
||||
titulo: "Task Watchdog Timer (TWDT) Timeout",
|
||||
tipo: "FreeRTOS / Multitarefa",
|
||||
explicacao:
|
||||
"Uma tarefa de prioridade alta monopolizou a CPU sem ceder tempo (sem vTaskDelay ou bloqueio), impedindo o watchdog da tarefa IDLE.",
|
||||
acaoRecomendada:
|
||||
"Adicione `vTaskDelay(pdMS_TO_TICKS(10))` em loops longos ou use filas/semáforos em vez de loops `while(1)` contínuos.",
|
||||
},
|
||||
{
|
||||
padrao: /Stack canary watchpoint triggered/i,
|
||||
titulo: "Stack Overflow (Estouro de Pilha da Tarefa)",
|
||||
tipo: "FreeRTOS / Memória",
|
||||
explicacao:
|
||||
"A tarefa excedeu a quantidade de memória de pilha (Stack) alocada na sua criação, corrompendo o canário de proteção.",
|
||||
acaoRecomendada:
|
||||
"Aumente o tamanho da pilha no `xTaskCreate` (ex: de 2048 para 4096 bytes) e mova arrays grandes para o Heap ou variáveis estáticas.",
|
||||
},
|
||||
{
|
||||
padrao: /Timed out waiting for packet header|Failed to connect to ESP32/i,
|
||||
titulo: "Falha de Conexão UART / Upload",
|
||||
tipo: "Bootloader / Conexão",
|
||||
explicacao:
|
||||
"O computador não conseguiu colocar o ESP32 em modo de gravação via DTR/RTS ou o cabo USB não possui linhas de dados.",
|
||||
acaoRecomendada:
|
||||
"Coloque um capacitor de 10µF entre o pino EN e o GND, troque o cabo USB por um com fios de dados e teste segurar o botão BOOT durante a conexão.",
|
||||
},
|
||||
{
|
||||
padrao: /The certificate is not yet valid|-0x2700/i,
|
||||
titulo: "Falha de Certificado SSL/TLS (Relógio em 1970)",
|
||||
tipo: "Conectividade / TLS",
|
||||
explicacao:
|
||||
"O ESP32 tentou autenticar um certificado HTTPS/TLS com a data zerada na época Unix (01/01/1970).",
|
||||
acaoRecomendada:
|
||||
"Sincronize o horário via SNTP (`configTime` no Arduino ou `ntptime.settime()` no MicroPython) antes de iniciar requisições HTTPS seguras.",
|
||||
},
|
||||
{
|
||||
padrao: /rst:0x1 \(POWERON_RESET\),boot:0x[0-9a-fA-F]+/i,
|
||||
titulo: "Reset por Power-On / Strapping Pins",
|
||||
tipo: "Hardware / Boot",
|
||||
explicacao:
|
||||
"O microcontrolador reiniciou e reportou o registrador de strapping pins. Se travar após isso, um pino de boot pode estar em nível lógico incorreto.",
|
||||
acaoRecomendada:
|
||||
"Verifique se GPIOs como 0, 2, 12, 15 (ESP32) ou 8, 9 (C3) estão conectados a resistores ou periféricos que forçam níveis inadequados no boot.",
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* Base de dados estruturada e abrangente de termos técnicos do Glossário ESP32.
|
||||
* Abrange todas as séries de chips da Espressif (ESP32, S2, S3, S31, C2, C3, C5, C6, C61, H2, H4, P4)
|
||||
* e seus recursos de hardware, periféricos, rádio, segurança e software.
|
||||
*/
|
||||
|
||||
export const categoriasGlossario = [
|
||||
{
|
||||
id: "processamento",
|
||||
nome: "Processamento, CPU & Silício",
|
||||
icone: "Cpu",
|
||||
emoji: "🧠",
|
||||
cor: "blue",
|
||||
descricao: "Arquiteturas Xtensa e RISC-V, núcleos, coprocessadores ULP, aceleradores vetoriais de IA e unidades de ponto flutuante.",
|
||||
termos: [
|
||||
{
|
||||
termo: "Arquitetura Xtensa vs RISC-V",
|
||||
definicao: "Conjunto de instruções base do processador. O ESP32 clássico, S2 e S3 usam núcleos proprietários Tensilica Xtensa (LX6/LX7). As séries modernas C (C2, C3, C5, C6, C61), H (H2, H4) e P (P4) adotam a arquitetura aberta, modular e eficiente RISC-V (32-bit).",
|
||||
exemplo: "ESP32-S3 usa Xtensa LX7 dual-core, enquanto ESP32-C6 usa RISC-V single-core e ESP32-P4 usa RISC-V dual-core a 400 MHz.",
|
||||
},
|
||||
{
|
||||
termo: "Núcleos de CPU (Dual-Core vs Single-Core)",
|
||||
definicao: "Unidades centrais de processamento independentes. Chips dual-core permitem dedicar um núcleo (Core 0) exclusivamente ao rádio Wi-Fi/Bluetooth e escalonamento do FreeRTOS, deixando o segundo núcleo (Core 1) 100% livre para a aplicação e cálculos do usuário.",
|
||||
exemplo: "ESP32, ESP32-S3 e ESP32-P4 são dual-core; ESP32-S2, C2, C3, C6 e H2 são single-core.",
|
||||
},
|
||||
{
|
||||
termo: "Frequência de Clock (MHz)",
|
||||
definicao: "Velocidade de processamento medida em Megahertz (MHz). O ESP-IDF ajusta dinamicamente a frequência (Dynamic Frequency Scaling - DFS) para economizar energia em momentos ociosos.",
|
||||
exemplo: "O ESP32-C2 opera a até 120 MHz; ESP32, S2, S3 e C6 chegam a 160/240 MHz; e o ESP32-P4 atinge 400 MHz.",
|
||||
},
|
||||
{
|
||||
termo: "ULP (Ultra Low Power Coprocessor)",
|
||||
definicao: "Processador secundário independente de consumo ultra baixo que continua rodando instruções, lendo sensores analógicos (ADC), I2C e pinos GPIO enquanto os núcleos principais permanecem desligados em Deep Sleep.",
|
||||
exemplo: "O ESP32 original tem ULP FSM; ESP32-S2, S3 e C6 possuem ULP RISC-V programável em C; ESP32-P4 possui ULP de baixa potência dedicado.",
|
||||
},
|
||||
{
|
||||
termo: "Extensões Vetoriais de IA (Vector Extension / ESP-NN)",
|
||||
definicao: "Instruções especializadas de silício que executam operações matemáticas vetoriais e matriciais com inteiros (int8/int16) em paralelo, acelerando redes neurais convolucionais (CNNs) e processamento de sinal.",
|
||||
exemplo: "ESP32-S3 e ESP32-P4 aceleram inferências de reconhecimento facial, detecção de voz e modelos TensorFlow Lite for Microcontrollers.",
|
||||
},
|
||||
{
|
||||
termo: "FPU (Floating Point Unit)",
|
||||
definicao: "Unidade de processamento de ponto flutuante por hardware que realiza somas, multiplicações e divisões com números decimais (`float`) em um único ciclo de clock, sem sobrecarga de software.",
|
||||
exemplo: "Presente nos núcleos Xtensa do ESP32 e ESP32-S3, e nos núcleos RISC-V de alto desempenho do ESP32-P4.",
|
||||
},
|
||||
{
|
||||
termo: "PPA (Pixel Processing Accelerator)",
|
||||
definicao: "Acelerador gráfico 2D por hardware exclusivo do ESP32-P4 para manipulação acelerada de imagens: rotação de frames, redimensionamento (scaling), mistura de canais alfa (alpha blending) e conversão de cores (RGB565, ARGB8888, YUV420).",
|
||||
exemplo: "Renderização de interfaces gráficas complexas (LVGL) a 60 FPS sem ocupar tempo dos núcleos de CPU principais.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "seguranca",
|
||||
nome: "Segurança, Criptografia & eFuses",
|
||||
icone: "ShieldCheck",
|
||||
emoji: "🔒",
|
||||
cor: "red",
|
||||
descricao: "eFuses invioláveis, Secure Boot V2, Criptografia de Flash XTS-AES, Key Manager, ECC e proteção contra DPA.",
|
||||
termos: [
|
||||
{
|
||||
termo: "eFuse (Electronic Fuses)",
|
||||
definicao: "Conjunto de fusíveis microscópicos de silício de gravação única e irreversível (One-Time Programmable - OTP). Armazenam chaves secretas de criptografia, o endereço MAC de fábrica e bloqueiam interfaces de debug em produtos comerciais.",
|
||||
exemplo: "Usado com a ferramenta `espefuse.py` para gravar chaves de Secure Boot e desativar portas JTAG antes do envio ao consumidor.",
|
||||
},
|
||||
{
|
||||
termo: "Secure Boot (V1 e V2)",
|
||||
definicao: "Protocolo de inicialização segura em que o código da ROM verifica criptograficamente a assinatura RSA-3072 ou ECDSA do bootloader e firmware antes de permitir sua execução, impedindo injeção de código adulterado.",
|
||||
exemplo: "ESP32 clássico usa Secure Boot V1; do ESP32-S2 em diante todos adotam o Secure Boot V2 com múltiplas chaves de assinatura.",
|
||||
},
|
||||
{
|
||||
termo: "Criptografia de Flash (Flash Encryption)",
|
||||
definicao: "Mecanismo de hardware que cifra e decifra em tempo real o conteúdo da memória Flash SPI externa usando o algoritmo XTS-AES. Impede a leitura física do firmware caso a placa seja roubada ou a memória dessoldada.",
|
||||
exemplo: "XTS-AES-128 na maioria dos chips; ESP32-S3, C5, P4 e H4 também suportam XTS-AES-256.",
|
||||
},
|
||||
{
|
||||
termo: "Key Manager",
|
||||
definicao: "Módulo de segurança avançado que provisiona, armazena e opera chaves criptográficas em silício sem nunca expô-las à memória SRAM ou ao firmware, impedindo extração de chaves mesmo sob vulnerabilidades de software.",
|
||||
exemplo: "Presente nas séries de alta segurança como ESP32-S31, ESP32-C5 e ESP32-P4.",
|
||||
},
|
||||
{
|
||||
termo: "ECC & ECDSA em Hardware",
|
||||
definicao: "Aceleradores de curvas elípticas (como P-256 e P-384) e algoritmos de assinatura digital ECDSA em silício, fundamentais para conexão rápida e segura com a nuvem e requisitos de atestação do padrão Matter.",
|
||||
exemplo: "ESP32-S31, C5, C61, P4, H2 e H4 possuem acelerador de hardware para ECDSA.",
|
||||
},
|
||||
{
|
||||
termo: "HMAC & Assinatura Digital (DS)",
|
||||
definicao: "Periféricos de autenticação criptográfica que calculam códigos HMAC e assinam mensagens com chaves secretas gravadas em eFuses de forma invisível para o firmware.",
|
||||
exemplo: "Permite autenticação segura e rápida com AWS IoT Core e Microsoft Azure IoT sem armazenar certificados em texto plano.",
|
||||
},
|
||||
{
|
||||
termo: "TRNG (True Random Number Generator)",
|
||||
definicao: "Gerador de números aleatórios verdadeiros baseado no ruído térmico analógico dos circuitos de rádio e silício, essencial para geração de chaves de sessão em handshakes TLS/HTTPS.",
|
||||
exemplo: "Disponível em todas as séries do ESP32 para garantir entropia segura em conexões HTTPS/MbedTLS.",
|
||||
},
|
||||
{
|
||||
termo: "Proteção contra DPA (Differential Power Analysis)",
|
||||
definicao: "Mecanismo físico de hardware que adiciona ruído e balanceamento no consumo de corrente elétrica do chip para impedir que invasores descubram chaves criptográficas medindo o consumo com osciloscópios.",
|
||||
exemplo: "Presente nas séries ESP32-C5, C6, C61 e H2.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "memoria",
|
||||
nome: "Memória, Barramentos & Armazenamento",
|
||||
icone: "Database",
|
||||
emoji: "💾",
|
||||
cor: "purple",
|
||||
descricao: "SRAM interna, ROM de boot, memórias Flash SPI, PSRAM QSPI/Octal, RTC Memory e alocações de DMA.",
|
||||
termos: [
|
||||
{
|
||||
termo: "SRAM Interna",
|
||||
definicao: "Memória volátil ultrarrápida integrada diretamente no silício da CPU. Utilizada para variáveis do programa, estruturas do FreeRTOS, buffers de drivers e pilha de execução. Perde os dados ao desligar a alimentação.",
|
||||
exemplo: "O ESP32 clássico possui 520 KB de SRAM; ESP32-S3 tem 512 KB; ESP32-C3 tem 400 KB; ESP32-C6 tem 512 KB; ESP32-P4 tem 768 KB.",
|
||||
},
|
||||
{
|
||||
termo: "ROM de Boot",
|
||||
definicao: "Memória somente-leitura gravada permanentemente na fábrica da Espressif contendo o First-Stage Bootloader, tabelas matemáticas e rotinas básicas de inicialização que nunca podem ser alteradas.",
|
||||
exemplo: "Ao ligar, a ROM executa primeiro, verifica os Strapping Pins e carrega o bootloader do usuário da Flash.",
|
||||
},
|
||||
{
|
||||
termo: "Flash SPI (Quad-SPI vs Octal-SPI)",
|
||||
definicao: "Memória não-volátil externa onde reside o firmware da aplicação. Conectada via 4 vias (Quad SPI / QSPI) ou 8 vias de dados (Octal SPI / OPI / OSPI) com o dobro de largura de banda e taxas de transferência.",
|
||||
exemplo: "ESP32-S3 e ESP32-P4 suportam memórias Flash e PSRAM em modo Octal SPI de até 120 MHz para máxima velocidade de carregamento de texturas e código.",
|
||||
},
|
||||
{
|
||||
termo: "PSRAM (Pseudo-Static RAM Externa)",
|
||||
definicao: "Memória RAM externa de alta densidade conectada via SPI/QSPI/OPI que estende a memória do microcontrolador em até dezenas de Megabytes para aplicações que demandam buffers gigantescos.",
|
||||
exemplo: "ESP32-WROVER e ESP32-S3-WROOM-1 com 8 MB de PSRAM externa para decodificação JPEG de câmeras e buffers gráficos de displays TFT.",
|
||||
},
|
||||
{
|
||||
termo: "RTC Fast & Slow SRAM",
|
||||
definicao: "Blocos de memória SRAM dedicados ao domínio de energia do Real-Time Clock (RTC). Permanecem alimentados durante o modo Deep Sleep para armazenar código do ULP e variáveis marcadas com `RTC_DATA_ATTR`.",
|
||||
exemplo: "Manter contadores de leituras ou dados de calibração intactos enquanto o ESP32 dorme em Deep Sleep consumindo 10 µA.",
|
||||
},
|
||||
{
|
||||
termo: "Alocação DMA (MALLOC_CAP_DMA)",
|
||||
definicao: "Memória compatível com Direct Memory Access (DMA), permitindo que periféricos (SPI, I2S, LCD, SDMMC) transfiram dados diretamente para a RAM sem consumir tempo da CPU.",
|
||||
exemplo: "Na maioria dos chips ESP32, o DMA exige alocação exclusiva na SRAM interna através da flag `MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL`.",
|
||||
},
|
||||
{
|
||||
termo: "Fragmentação de Heap",
|
||||
definicao: "Fenômeno em que a memória dinâmica fica dividida em blocos pequenos dispersos após múltiplas alocações e desalocações (muito comum ao usar objetos `String` do Arduino), impedindo alocações contíguas grandes para TLS/Wi-Fi.",
|
||||
exemplo: "Monitorado no ESP-IDF através de `heap_caps_get_largest_free_block()` para prevenir falhas de conexão HTTPS.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "conectividade",
|
||||
nome: "Conectividade Sem Fio & Protocolos",
|
||||
icone: "Wifi",
|
||||
emoji: "📡",
|
||||
cor: "emerald",
|
||||
descricao: "Wi-Fi 4/6, Dual-Band 5 GHz, OFDMA, TWT, Bluetooth Classic, BLE 5.x, LE Audio, Zigbee 3.0, Thread e Matter.",
|
||||
termos: [
|
||||
{
|
||||
termo: "Wi-Fi 6 (802.11ax)",
|
||||
definicao: "Padrão moderno de rede sem fio que traz suporte a OFDMA (comunicação paralela com menor latência), modulação 1024-QAM e o recurso TWT (Target Wake Time) para economizar drasticamente a bateria de sensores IoT.",
|
||||
exemplo: "Presente no ESP32-C6, ESP32-C61 e ESP32-C5.",
|
||||
},
|
||||
{
|
||||
termo: "Wi-Fi Dual-Band (2.4 GHz e 5 GHz)",
|
||||
definicao: "Capacidade de operar tanto na faixa tradicional de 2.4 GHz quanto na faixa de 5 GHz com menor congestionamento eletromagnético, canais de 20 MHz / 40 MHz e maior estabilidade de conexão.",
|
||||
exemplo: "O ESP32-C5 é o primeiro chip da Espressif com rádio Wi-Fi 6 Dual-Band integrado.",
|
||||
},
|
||||
{
|
||||
termo: "OFDMA (Orthogonal Frequency Division Multiple Access)",
|
||||
definicao: "Tecnologia do Wi-Fi 6 que divide um único canal de rádio em dezenas de subportadoras menores (Resource Units), permitindo que o roteador atenda múltiplos dispositivos ESP32 simultaneamente sem colisões.",
|
||||
exemplo: "Reduz a latência de resposta em ambientes residenciais ou industriais densos com dezenas de nós conectados.",
|
||||
},
|
||||
{
|
||||
termo: "TWT (Target Wake Time)",
|
||||
definicao: "Protocolo do Wi-Fi 6 onde o ESP32 e o roteador combinam horários exatos para troca de pacotes, permitindo que o microcontrolador mantenha seu rádio totalmente desligado por longos períodos sem se desconectar da rede.",
|
||||
exemplo: "Sensores alimentados por bateria com ESP32-C6 operando por anos conectados ao Wi-Fi 6 sem perder sincronismo.",
|
||||
},
|
||||
{
|
||||
termo: "Bluetooth Classic (BR/EDR)",
|
||||
definicao: "Protocolo Bluetooth tradicional para transmissão contínua de áudio estéreo (A2DP), portas seriais virtuais (SPP) e dispositivos que exigem alta taxa de transferência sustentada.",
|
||||
exemplo: "Implementação de caixas de som Bluetooth, receptores de áudio e teclados HID no ESP32 clássico.",
|
||||
},
|
||||
{
|
||||
termo: "Bluetooth Low Energy (BLE 5.0 a 5.4)",
|
||||
definicao: "Versão de baixo consumo elétrico do Bluetooth com suporte a taxas de 2 Mbps (2M PHY), longo alcance de centenas de metros (Coded PHY / Long Range), extensões de publicidade e redes mesh Bluetooth.",
|
||||
exemplo: "ESP32-S3 suporta BLE 5.0; ESP32-C6 e ESP32-H2 suportam Bluetooth 5.4 LE.",
|
||||
},
|
||||
{
|
||||
termo: "Bluetooth LE Audio & Auracast",
|
||||
definicao: "Nova geração de áudio Bluetooth de alta fidelidade e baixíssimo consumo com o codec LC3 e suporte a transmissões de áudio para múltiplos ouvintes simultâneos (Broadcast Audio / Auracast).",
|
||||
exemplo: "Disponível na série ESP32-H4 para novos ecossistemas de áudio e fones inteligentes.",
|
||||
},
|
||||
{
|
||||
termo: "IEEE 802.15.4 (Zigbee 3.0 & Thread)",
|
||||
definicao: "Padrão de rádio em 2.4 GHz de baixo consumo e baixa taxa de dados que forma a base física das redes em malha (Mesh) industriais e residenciais Zigbee 3.0 e Thread 1.3.",
|
||||
exemplo: "ESP32-C6, ESP32-H2 e ESP32-H4 possuem transceptor IEEE 802.15.4 integrado no silício.",
|
||||
},
|
||||
{
|
||||
termo: "Matter Protocol",
|
||||
definicao: "Padrão universal e aberto de conectividade para automação residencial mantido pela CSA, funcionando sobre redes Wi-Fi, Ethernet e Thread, compatível nativamente com Apple Home, Google Home, Alexa e Home Assistant.",
|
||||
exemplo: "Lâmpadas e tomadas inteligentes desenvolvidas com ESP-Matter no ESP32-C6 ou ESP32-H2 sem depender de nuvens proprietárias.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "perifericos",
|
||||
nome: "Entradas, Saídas & Periféricos",
|
||||
icone: "Sliders",
|
||||
emoji: "🔌",
|
||||
cor: "amber",
|
||||
descricao: "Pinos GPIO, strapping pins, conversores ADC/DAC, PWM/LEDC, MCPWM, RMT, PCNT, TWAI®/CAN, I2C, SPI e I2S.",
|
||||
termos: [
|
||||
{
|
||||
termo: "GPIO (General Purpose Input/Output)",
|
||||
definicao: "Pinos multifuncionais configuráveis como entradas ou saídas digitais, com resistores de pull-up/pull-down internos selecionáveis e suporte a interrupções externas em qualquer pino.",
|
||||
exemplo: "Leitura de botões, chaveamento de relés e controle de LEDs com `gpio_set_level()` ou `digitalWrite()`.",
|
||||
},
|
||||
{
|
||||
termo: "Strapping Pins",
|
||||
definicao: "Pinos GPIO específicos amostrados por hardware no milissegundo em que o chip sai do reset para determinar o modo de boot (Download UART vs SPI Flash) e níveis de tensão.",
|
||||
exemplo: "GPIO 0 no ESP32 clássico/S3 ou GPIO 9 no ESP32-C3: se puxados para LOW durante o reset, colocam o chip em modo de gravação de firmware.",
|
||||
},
|
||||
{
|
||||
termo: "ADC (Analog-to-Digital Converter)",
|
||||
definicao: "Conversor que transforma níveis contínuos de tensão analógica (0 a 3.3V) em valores numéricos digitais de 12 bits (o ESP32-S2 entrega 13 bits, com 12 efetivos) através de atenuadores configuráveis (0dB, 2.5dB, 6dB, 11dB/12dB).",
|
||||
exemplo: "Leitura de sensores LDR, potenciômetros, termistores e medição do nível de carga de baterias de lítio.",
|
||||
},
|
||||
{
|
||||
termo: "DAC (Digital-to-Analog Converter)",
|
||||
definicao: "Conversor que gera tensões analógicas contínuas proporcionais a valores digitais gerados por software sem necessidade de circuitos externos.",
|
||||
exemplo: "Disponível no ESP32 clássico e ESP32-S2 para sintetizar áudio analógico ou sinais de controle direto.",
|
||||
},
|
||||
{
|
||||
termo: "LEDC (LED PWM Controller)",
|
||||
definicao: "Periférico dedicado a gerar múltiplos canais de modulação por largura de pulso (PWM) com controle de frequência, resolução de até 14-20 bits e transições graduais (fade por hardware) sem ocupar a CPU.",
|
||||
exemplo: "Controle suave de brilho de fitas de LED RGBW e posicionamento de servomotores.",
|
||||
},
|
||||
{
|
||||
termo: "MCPWM (Motor Control PWM)",
|
||||
definicao: "Controlador PWM avançado projetado para acionamento de motores elétricos, inversores de frequência trifásicos, pontes H com tempo morto (dead-time) configurável e captura de encoders em quadratura.",
|
||||
exemplo: "Controle preciso de motores sem escovas (BLDC) e robôs móveis no ESP32 clássico, S3 e P4.",
|
||||
},
|
||||
{
|
||||
termo: "RMT (Remote Control Peripheral)",
|
||||
definicao: "Transceptor e gerador de pulsos de temporização precisa em microssegundos projetado originalmente para controles remotos infravermelhos (NEC, RC5, Sony) e amplamente usado para controlar fitas de LED digitais WS2812B / NeoPixel.",
|
||||
exemplo: "Atualização de centenas de LEDs NeoPixel sem desativar interrupções do sistema.",
|
||||
},
|
||||
{
|
||||
termo: "PCNT (Pulse Counter)",
|
||||
definicao: "Contador de pulsos de hardware que mede a contagem de bordas de subida/descida de sinais externos em alta frequência sem gerar interrupções por software para a CPU.",
|
||||
exemplo: "Leitura de encoders rotativos industriais, tacômetros de velocidade e medidores de vazão de água.",
|
||||
},
|
||||
{
|
||||
termo: "TWAI® (Two-Wire Automotive Interface / CAN Bus)",
|
||||
definicao: "Controlador de barramento veicular e industrial CAN 2.0B compatível com a norma ISO 11898-1 integrado no silício, necessitando apenas de um transceptor físico externo (como SN65HVD230).",
|
||||
exemplo: "Diagnóstico automotivo OBD-II, telemetria de veículos elétricos e automação industrial robusta.",
|
||||
},
|
||||
{
|
||||
termo: "Touch Capacitivo",
|
||||
definicao: "Pinos especializados que medem a variação da capacitância eletrostática quando um dedo se aproxima, permitindo criar botões e sliders sensíveis ao toque através de vidro ou acrílico.",
|
||||
exemplo: "Painéis de comando touch modernos com até 14 canais no ESP32-S2 e S3.",
|
||||
},
|
||||
{
|
||||
termo: "PARLIO (Parallel IO Controller)",
|
||||
definicao: "Barramento paralelo configurável de alta velocidade presente nas séries mais novas (C6, H2, P4) para transferir dados síncronos com clock customizado para displays LCD, câmeras e sensores externos.",
|
||||
exemplo: "Comunicação paralela eficiente com chips periféricos sem recorrer a bit-banging na CPU.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "multimidia",
|
||||
nome: "Multimídia, USB & Interfaces Avançadas",
|
||||
icone: "Sparkles",
|
||||
emoji: "✨",
|
||||
cor: "pink",
|
||||
descricao: "USB OTG nativo, USB Serial/JTAG, USB High-Speed 480Mbps, MIPI CSI/DSI, codificador H.264 e Ethernet MAC.",
|
||||
termos: [
|
||||
{
|
||||
termo: "USB OTG (On-The-Go) Nativo",
|
||||
definicao: "Controlador USB Full-Speed (12 Mbps) embutido no chip que permite ao ESP32 operar como dispositivo periférico (teclado HID, mouse, pendrive Mass Storage) ou como USB Host (lendo pen drives ou periféricos).",
|
||||
exemplo: "Nativamente disponível no ESP32-S2 e ESP32-S3 para criação de teclados customizados e emuladores.",
|
||||
},
|
||||
{
|
||||
termo: "USB Serial/JTAG Nativo",
|
||||
definicao: "Interface USB integrada no silício que fornece simultaneamente uma porta serial de comunicação para o console e uma sonda de depuração JTAG completa sem a necessidade de chips conversores externos (CH340/CP2102).",
|
||||
exemplo: "Permite gravar firmware e debugar com breakpoints no VS Code no ESP32-C3, S3, C6 e H2 apenas com o cabo USB conectado aos pinos D+/D-.",
|
||||
},
|
||||
{
|
||||
termo: "USB 2.0 High-Speed (480 Mbps)",
|
||||
definicao: "Controlador USB 2.0 de alta velocidade capaz de transferir até 480 Mbps com PHY integrado, proporcionando largura de banda 40x superior ao USB Full-Speed.",
|
||||
exemplo: "Exclusivo do ESP32-P4 para streaming de vídeo em alta definição e transferência em massa de dados.",
|
||||
},
|
||||
{
|
||||
termo: "MIPI CSI & MIPI DSI",
|
||||
definicao: "Interfaces seriais diferenciais de alta velocidade padrão da indústria de smartphones: MIPI-CSI (Camera Serial Interface) para sensores de câmera de alta resolução e MIPI-DSI (Display Serial Interface) para telas sensíveis ao toque.",
|
||||
exemplo: "Conexão de telas de 1080p e câmeras de alta taxa de quadros no SoC ESP32-P4.",
|
||||
},
|
||||
{
|
||||
termo: "Codificador de Vídeo H.264 por Hardware",
|
||||
definicao: "Bloco acelerador dedicado que comprime fluxos de vídeo brutos de câmeras no formato padrão H.264 (AVC) em tempo real em resoluções de até 1080p a 30 FPS sem sobrecarregar a CPU.",
|
||||
exemplo: "Câmeras de segurança inteligentes e porteiros eletrônicos com compressão eficiente no ESP32-P4.",
|
||||
},
|
||||
{
|
||||
termo: "Ethernet MAC 10/100 Mbps",
|
||||
definicao: "Controlador de camada de enlace de dados (Media Access Control) de rede cabeada integrado no silício, que exige apenas um chip transceptor físico externo (PHY como LAN8720 ou IP101) via interface RMII.",
|
||||
exemplo: "Conexão Ethernet RJ45 estável imune a ruídos de rádio para automação predial no ESP32 clássico e ESP32-P4.",
|
||||
},
|
||||
{
|
||||
termo: "Interface de Câmera DVP (8-bit / 16-bit)",
|
||||
definicao: "Barramento paralelo com sinais VSYNC, HREF, PCLK e barramento de dados com suporte a DMA para captura direta de frames de módulos de câmera populares (OV2640, OV5640).",
|
||||
exemplo: "Usado em placas ESP32-CAM e ESP32-S3-CAM para captura de fotos e streaming de vídeo MJPEG.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "energia",
|
||||
nome: "Gerenciamento de Energia & Sleep Modes",
|
||||
icone: "BatteryCharging",
|
||||
emoji: "🔋",
|
||||
cor: "teal",
|
||||
descricao: "Active Mode, Modem Sleep, Light Sleep, Deep Sleep, Hibernation, Brownout Detector e fontes de despertar.",
|
||||
termos: [
|
||||
{
|
||||
termo: "Active Mode",
|
||||
definicao: "Modo de operação normal onde a CPU executa instruções na frequência máxima e todos os periféricos e rádios estão prontos para uso, com consumo elétrico variando de 30 mA a ~240 mA (durante transmissões Wi-Fi).",
|
||||
exemplo: "ESP32 processando áudio, atualizando displays ou transmitindo dados de sensores em tempo real.",
|
||||
},
|
||||
{
|
||||
termo: "Modem Sleep",
|
||||
definicao: "Modo em que os circuitos de rádio Wi-Fi e Bluetooth são desligados temporariamente nos intervalos entre transmissões enquanto a CPU continua rodando seu código normalmente, reduzindo o consumo para ~20 a 40 mA.",
|
||||
exemplo: "Modo padrão em aplicações conectadas ao Wi-Fi que aguardam eventos de rede sem perder a associação ao roteador.",
|
||||
},
|
||||
{
|
||||
termo: "Light Sleep",
|
||||
definicao: "Modo de economia intermediário: a CPU tem seu clock pausado e os rádios são desligados, mas a memória SRAM interna, os periféricos e o estado das tarefas são preservados intactos. O chip acorda em menos de 1 ms.",
|
||||
exemplo: "Consumo de ~0.8 mA em dispositivos que precisam acordar rapidamente por interrupção de botão ou timer.",
|
||||
},
|
||||
{
|
||||
termo: "Deep Sleep",
|
||||
definicao: "Modo de sono profundo em que todos os domínios digitais e a CPU são desligados, mantendo alimentado apenas o domínio RTC (e opcionalmente a RTC Memory e o ULP). O consumo cai para 5 a 15 µA e o chip reinicia a execução ao acordar.",
|
||||
exemplo: "Estações meteorológicas remotas alimentadas por bateria e painel solar que realizam leituras a cada hora.",
|
||||
},
|
||||
{
|
||||
termo: "Hibernation Mode",
|
||||
definicao: "O estado de menor consumo elétrico do silício: desliga inclusive o oscilador de cristal do RTC e domínios lentos, mantendo apenas um circuito analógico de recuperação que acorda por botão externo ou reset.",
|
||||
exemplo: "Consumo residual de ~5 µA em dispositivos que operam por anos com bateria botão tipo moeda (CR2032).",
|
||||
},
|
||||
{
|
||||
termo: "Fontes de Despertar (Wakeup Sources)",
|
||||
definicao: "Eventos de hardware configurados para tirar o ESP32 do modo Deep Sleep ou Light Sleep: temporizadores RTC, pinos GPIO externos (EXT0 / EXT1), toque capacitivo ou sinal do coprocessador ULP.",
|
||||
exemplo: "`esp_sleep_enable_timer_wakeup(60 * 1000000)` para acordar exatamente a cada 60 segundos.",
|
||||
},
|
||||
{
|
||||
termo: "Brownout Detector",
|
||||
definicao: "Circuito comparador analógico interno de hardware que monitora a tensão de alimentação no pino 3V3 e força um reset de emergência seguro caso a tensão caia abaixo de ~2.8V para prevenir corrupção da memória Flash.",
|
||||
exemplo: "Protege o microcontrolador contra resets parciais causados por fontes fracas durante picos de transmissão de rádio.",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "desenvolvimento",
|
||||
nome: "Firmware, Boot & Sistema Operacional",
|
||||
icone: "Code2",
|
||||
emoji: "🚀",
|
||||
cor: "rose",
|
||||
descricao: "Bootloader, FreeRTOS, macros IRAM_ATTR, partições da Flash, atualização OTA com Rollback e armazenamento NVS.",
|
||||
termos: [
|
||||
{
|
||||
termo: "Bootloader (First & Second Stage)",
|
||||
definicao: "Código que executa logo após o reset elétrico. O primeiro estágio reside na ROM do chip; o segundo estágio reside na Flash, valida a tabela de partições, checa as assinaturas de segurança e carrega o firmware do usuário.",
|
||||
exemplo: "Controla a alternância entre partições OTA e inicializa a memória PSRAM antes do `app_main`.",
|
||||
},
|
||||
{
|
||||
termo: "FreeRTOS (Sistema Operacional de Tempo Real)",
|
||||
definicao: "Kernel multitarefa preemptivo padrão do ESP-IDF que divide a CPU entre múltiplas tarefas (Tasks), filas de mensagens (Queues), semáforos, mutexes e timers de software com controle de prioridades.",
|
||||
exemplo: "`xTaskCreatePinnedToCore()` para alocar tarefas pesadas em núcleos específicos da CPU.",
|
||||
},
|
||||
{
|
||||
termo: "IRAM_ATTR & DRAM_ATTR",
|
||||
definicao: "Atributos especiais do compilador GCC para o ESP32 que forçam funções e variáveis a residirem na memória interna ultrarrápida IRAM/DRAM em vez da Flash externa, obrigatório para rotinas de interrupção (ISRs).",
|
||||
exemplo: "Evita que uma interrupção cause travamento (*Cache Error*) enquanto a Flash estiver ocupada gravando dados.",
|
||||
},
|
||||
{
|
||||
termo: "Tabela de Partições (partitions.csv)",
|
||||
definicao: "Arquivo de configuração que mapeia o espaço de armazenamento da memória Flash em blocos lógicos dedicados ao bootloader, dados NVS, arquivos LittleFS e múltiplas imagens de firmware (Factory, OTA_0, OTA_1).",
|
||||
exemplo: "Personalizado para acomodar firmwares grandes com bibliotecas de Bluetooth, Wi-Fi e criptografia.",
|
||||
},
|
||||
{
|
||||
termo: "OTA (Over-The-Air Update) com Rollback",
|
||||
definicao: "Atualização sem fio de firmware onde a nova versão é gravada em uma partição secundária. Se o novo firmware falhar ao inicializar, o sistema reverte automaticamente (*Rollback*) para a versão funcional anterior.",
|
||||
exemplo: "`esp_ota_mark_app_valid_cancel_rollback()` confirma que a nova atualização está saudável em campo.",
|
||||
},
|
||||
{
|
||||
termo: "NVS (Non-Volatile Storage) & NVS Encryption",
|
||||
definicao: "Mecanismo estruturado de chave-valor na memória Flash para persistir credenciais de rede, parâmetros de calibração e contadores, com suporte a criptografia em hardware via chave AES nos eFuses.",
|
||||
exemplo: "Salvar nome de rede Wi-Fi e senhas criptografadas para reconexão automática após desligamento.",
|
||||
},
|
||||
{
|
||||
termo: "LittleFS & SPIFFS",
|
||||
definicao: "Sistemas de arquivos desenvolvidos para memórias Flash com nivelamento de desgaste (*wear leveling*), permitindo que a aplicação leia e grave arquivos como páginas HTML, certificados SSL e logs.",
|
||||
exemplo: "Armazenar páginas HTML/CSS do servidor web embutido do ESP32 para configuração de rede via navegador.",
|
||||
},
|
||||
{
|
||||
termo: "JTAG & OpenOCD",
|
||||
definicao: "Padrão de depuração em nível de hardware que permite pausar a CPU, colocar breakpoints e inspecionar registradores e variáveis em tempo real no VS Code ou Eclipse via sondas USB-JTAG.",
|
||||
exemplo: "Depuração de crashes complexos e ponteiros nulos sem depender apenas de comandos `Serial.println()`.",
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Conhecimento de domínio da busca inteligente.
|
||||
*
|
||||
* Sem dependências nem alias de import: roda no servidor (montando o índice),
|
||||
* no navegador (interpretando a consulta) e em scripts de teste no Node.
|
||||
*
|
||||
* Todos os textos de `termos` já estão normalizados (minúsculos, sem acento).
|
||||
*/
|
||||
|
||||
export const normalizar = (s = "") =>
|
||||
String(s)
|
||||
.toLowerCase()
|
||||
.normalize("NFD")
|
||||
.replace(/[\u0300-\u036f]/g, "");
|
||||
|
||||
/**
|
||||
* Reconhece pinos ocupados por flash/PSRAM com base no que o diagrama diz.
|
||||
* "forte": o pino é consumido pela memória (ou é a alimentação dela).
|
||||
* "fraco": só é afetado em certos modos (ex.: SPI de 8 linhas/octal).
|
||||
* Avisos genéricos de tensão mínima ("para chips com flash integrada...") não contam.
|
||||
*/
|
||||
const nivelMemoria = (palavra) => (p) => {
|
||||
const citam = p._avs.filter((a) => a.includes(palavra) && !/^para chips (com|sem)/.test(a));
|
||||
if (citam.some((a) => /(utilizad|dedicad|conectad)/.test(a) && !/a menos que/.test(a))) return "forte";
|
||||
if (p._fn.some((f) => /alimentacao/.test(f) && f.includes(palavra))) return "forte";
|
||||
if (citam.length) return "fraco";
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assuntos que o usuário pode citar. Cada um sabe:
|
||||
* - termos: como as pessoas escrevem (sinônimos, siglas, plurais comuns);
|
||||
* - pinoCats / pinoRe: como reconhecer os pinos relacionados no diagrama;
|
||||
* - pinoRotulo: frase usada no título do resultado de pinos.
|
||||
* Os dados de especificação ligam-se aos assuntos por SPEC_CAMPOS.
|
||||
*/
|
||||
export const TOPICOS = [
|
||||
{ id: "flash", nome: "Flash", termos: ["flash", "memoria flash", "spi flash", "armazenamento", "firmware", "rom externa"], pinoNivel: nivelMemoria("flash"), pinoRotulo: "ligados à memória flash" },
|
||||
{ id: "psram", nome: "PSRAM", termos: ["psram", "ram externa", "spiram"], pinoNivel: nivelMemoria("psram"), pinoRotulo: "ligados à PSRAM" },
|
||||
{ id: "memoria", nome: "Memória", termos: ["memoria", "sram", "heap", "rtc ram", "kb de ram", "memoria interna", "ram"], pinoRotulo: "" },
|
||||
{ id: "wifi", nome: "Wi-Fi", termos: ["wifi", "wi-fi", "wireless", "sem fio", "802.11", "wifi6", "wifi 6", "wi-fi 6"], pinoCats: ["Antena"], pinoRotulo: "de antena e rádio" },
|
||||
{ id: "bluetooth", nome: "Bluetooth", termos: ["bluetooth", "ble", "bt", "bluetooth le", "mesh"], pinoCats: ["Antena"], pinoRotulo: "de antena e rádio" },
|
||||
{ id: "zigbee", nome: "Zigbee/Thread", termos: ["zigbee", "thread", "802.15.4", "ieee 802.15.4"], pinoRotulo: "" },
|
||||
{ id: "matter", nome: "Matter", termos: ["matter", "casa inteligente", "smart home"], pinoRotulo: "" },
|
||||
{ id: "ethernet", nome: "Ethernet", termos: ["ethernet", "rmii", "cabo de rede", "lan"], pinoCats: ["Ethernet"], pinoRotulo: "de Ethernet" },
|
||||
{ id: "can", nome: "CAN / TWAI", termos: ["can", "twai", "can bus", "canbus", "can fd"], pinoRe: /twai|\bcan\b/, pinoRotulo: "de CAN/TWAI" },
|
||||
{ id: "usb", nome: "USB", termos: ["usb", "otg", "usb serial", "usb otg", "hid", "cdc"], pinoCats: ["USB"], pinoRotulo: "de USB" },
|
||||
{ id: "jtag", nome: "JTAG / Depuração", termos: ["jtag", "debug", "depuracao", "depurar", "openocd", "gdb"], pinoCats: ["JTAG"], pinoRotulo: "de JTAG" },
|
||||
{ id: "adc", nome: "ADC", termos: ["adc", "analogico", "entrada analogica", "conversor analogico", "analogread", "saradc"], pinoCats: ["ADC"], pinoRotulo: "com ADC" },
|
||||
{ id: "dac", nome: "DAC", termos: ["dac", "saida analogica", "conversor digital"], pinoCats: ["DAC"], pinoRotulo: "com DAC" },
|
||||
{ id: "touch", nome: "Touch capacitivo", termos: ["touch", "capacitivo", "toque", "touchpad", "sensor de toque"], pinoCats: ["Touch"], pinoRotulo: "de touch capacitivo" },
|
||||
{ id: "uart", nome: "UART", termos: ["uart", "serial", "tx", "rx", "txd", "rxd", "porta serial"], pinoCats: ["UART"], pinoRotulo: "de UART" },
|
||||
{ id: "spi", nome: "SPI", termos: ["spi", "mosi", "miso", "sclk", "barramento spi"], pinoCats: ["SPI"], pinoRotulo: "de SPI" },
|
||||
{ id: "i2c", nome: "I2C", termos: ["i2c", "sda", "scl", "twi", "iic"], pinoCats: ["I2C"], pinoRotulo: "de I2C" },
|
||||
{ id: "i2s", nome: "I2S", termos: ["i2s", "audio", "som", "microfone", "pdm", "codec"], pinoRe: /i2s|\bpdm\b/, pinoRotulo: "de I2S/áudio" },
|
||||
{ id: "pwm", nome: "PWM", termos: ["pwm", "ledc", "mcpwm", "servo", "dimmer"], pinoRe: /ledc|pwm/, pinoRotulo: "de PWM" },
|
||||
{ id: "sd", nome: "Cartão SD / SDIO", termos: ["sd", "sdio", "sd card", "sdcard", "cartao sd", "microsd", "sdmmc", "mmc"], pinoCats: ["SD"], pinoRe: /sdio|sdmmc|\bsd\b/, pinoRotulo: "de cartão SD/SDIO" },
|
||||
{ id: "camera", nome: "Câmera", termos: ["camera", "cam", "dvp", "csi", "mipi csi", "ov2640", "video"], pinoCats: ["CSI"], pinoRe: /\bcam\b|dvp|cam_/, pinoRotulo: "de câmera" },
|
||||
{ id: "lcd", nome: "Display / LCD", termos: ["lcd", "display", "tela", "dsi", "mipi dsi", "oled", "tft", "lvgl", "rgb"], pinoCats: ["DSI"], pinoRe: /lcd/, pinoRotulo: "de display/LCD" },
|
||||
{ id: "strapping", nome: "Boot / Strapping", termos: ["strapping", "boot", "bootstrap", "modo de boot", "download mode", "modo de gravacao", "inicializacao"], pinoCats: ["Strapping"], pinoRotulo: "de strapping (modo de boot)" },
|
||||
{ id: "energia_pinos", nome: "Alimentação", termos: ["alimentacao", "vdd", "3v3", "3.3v", "tensao", "regulador", "ldo", "fonte"], pinoCats: ["Power"], pinoRotulo: "de alimentação" },
|
||||
{ id: "clock", nome: "Clock / Cristal", termos: ["clock", "xtal", "cristal", "oscilador", "32khz", "40mhz"], pinoCats: ["Clock"], pinoRotulo: "de clock/cristal" },
|
||||
{ id: "gpio", nome: "GPIO", termos: ["gpio", "entradas e saidas"], pinoCats: ["GPIO"], pinoRotulo: "de GPIO" },
|
||||
{ id: "baixo_consumo", nome: "Baixo consumo / ULP", termos: ["ulp", "lp core", "lp cpu", "coprocessador", "lp gpio", "low power", "rtc gpio"], pinoCats: ["Low Power"], pinoRotulo: "de baixo consumo (LP/RTC)" },
|
||||
{ id: "antena", nome: "Antena / RF", termos: ["antena", "rf", "radiofrequencia", "ipex"], pinoCats: ["Antena"], pinoRotulo: "de antena/RF" },
|
||||
{ id: "seguranca", nome: "Segurança", termos: ["seguranca", "secure boot", "criptografia", "encriptacao", "aes", "sha", "rsa", "hmac", "ecdsa", "efuse", "tee", "trng", "rng", "hsm", "protecao"], pinoRotulo: "" },
|
||||
{ id: "consumo", nome: "Consumo de energia", termos: ["consumo", "bateria", "deep sleep", "light sleep", "sleep", "modem sleep", "corrente", "miliamperes", "autonomia", "economia de energia", "low power mode"], pinoRotulo: "" },
|
||||
{ id: "temperatura", nome: "Temperatura", termos: ["temperatura", "calor", "graus", "faixa de temperatura", "industrial"], pinoRotulo: "" },
|
||||
{ id: "ia", nome: "IA / Aceleração", termos: ["ia", "ai", "machine learning", "ml", "tinyml", "vetorial", "inteligencia artificial", "rede neural", "esp-nn", "esp-dl"], pinoRotulo: "" },
|
||||
{ id: "processador", nome: "Processador", termos: ["processador", "cpu", "nucleo", "nucleos", "core", "dual core", "single core", "arquitetura", "xtensa", "risc-v", "riscv"], pinoRotulo: "" },
|
||||
{ id: "frequencia", nome: "Frequência", termos: ["frequencia", "mhz", "velocidade", "desempenho", "performance"], pinoRotulo: "" },
|
||||
{ id: "ferramentas", nome: "Ferramentas / SDK", termos: ["esp-idf", "idf", "arduino", "sdk", "toolchain", "versao do idf"], pinoRotulo: "" },
|
||||
{ id: "encapsulamento", nome: "Módulos e encapsulamento", termos: ["modulo", "modulos", "encapsulamento", "package", "qfn", "wroom", "wrover", "mini-1"], pinoRotulo: "" },
|
||||
];
|
||||
|
||||
/**
|
||||
* Campos de public/series.json que respondem a cada assunto.
|
||||
* `campo` aceita caminho com ponto (seguranca.aes). `secao` é o id da âncora
|
||||
* na página /series/[key].
|
||||
*/
|
||||
export const SPEC_CAMPOS = [
|
||||
{ campo: "arquitetura", label: "Arquitetura", secao: "processador", topicos: ["processador"] },
|
||||
{ campo: "nucleos", label: "Núcleos", secao: "processador", topicos: ["processador"] },
|
||||
{ campo: "frequencia", label: "Frequência", secao: "processador", topicos: ["frequencia", "processador"] },
|
||||
{ campo: "coprocessador_ulp", label: "Coprocessador ULP", secao: "processador", topicos: ["baixo_consumo"] },
|
||||
{ campo: "aceleradores_ia", label: "Aceleradores de IA", secao: "processador", topicos: ["ia"] },
|
||||
|
||||
{ campo: "wifi", label: "Wi-Fi", secao: "conectividade", topicos: ["wifi"] },
|
||||
{ campo: "bluetooth", label: "Bluetooth", secao: "conectividade", topicos: ["bluetooth"] },
|
||||
{ campo: "zigbee_thread", label: "Zigbee/Thread", secao: "conectividade", topicos: ["zigbee"] },
|
||||
{ campo: "matter", label: "Matter", secao: "conectividade", topicos: ["matter"] },
|
||||
{ campo: "ethernet", label: "Ethernet", secao: "conectividade", topicos: ["ethernet"] },
|
||||
{ campo: "ethernet_mac", label: "Ethernet MAC", secao: "conectividade", topicos: ["ethernet"] },
|
||||
{ campo: "can", label: "CAN", secao: "conectividade", topicos: ["can"] },
|
||||
|
||||
{ campo: "memoria_sram", label: "SRAM", secao: "memoria", topicos: ["memoria"] },
|
||||
{ campo: "memoria_sram_rtc", label: "SRAM RTC", secao: "memoria", topicos: ["memoria", "baixo_consumo"] },
|
||||
{ campo: "memoria_rom", label: "ROM", secao: "memoria", topicos: ["memoria"] },
|
||||
{ campo: "flash_externa", label: "Flash externa", secao: "memoria", topicos: ["flash", "memoria"] },
|
||||
{ campo: "psram_externa", label: "PSRAM externa", secao: "memoria", topicos: ["psram", "memoria"] },
|
||||
|
||||
{ campo: "gpio", label: "GPIO", secao: "perifericos", topicos: ["gpio"] },
|
||||
{ campo: "adc", label: "ADC", secao: "perifericos", topicos: ["adc"] },
|
||||
{ campo: "dac", label: "DAC", secao: "perifericos", topicos: ["dac"] },
|
||||
{ campo: "touch", label: "Touch", secao: "perifericos", topicos: ["touch"] },
|
||||
{ campo: "uart", label: "UART", secao: "perifericos", topicos: ["uart"] },
|
||||
{ campo: "spi", label: "SPI", secao: "perifericos", topicos: ["spi", "flash"] },
|
||||
{ campo: "i2c", label: "I2C", secao: "perifericos", topicos: ["i2c"] },
|
||||
{ campo: "i2s", label: "I2S", secao: "perifericos", topicos: ["i2s"] },
|
||||
{ campo: "pwm", label: "PWM", secao: "perifericos", topicos: ["pwm"] },
|
||||
{ campo: "usb", label: "USB", secao: "perifericos", topicos: ["usb"] },
|
||||
{ campo: "lcd", label: "LCD", secao: "interfaces", topicos: ["lcd"] },
|
||||
{ campo: "camera", label: "Câmera", secao: "interfaces", topicos: ["camera"] },
|
||||
{ campo: "mipi_csi", label: "MIPI CSI", secao: "interfaces", topicos: ["camera"] },
|
||||
{ campo: "mipi_dsi", label: "MIPI DSI", secao: "interfaces", topicos: ["lcd"] },
|
||||
{ campo: "sdio", label: "SDIO", secao: "interfaces", topicos: ["sd"] },
|
||||
{ campo: "sensor_temperatura", label: "Sensor de temperatura", secao: "interfaces", topicos: ["temperatura"] },
|
||||
|
||||
{ campo: "seguranca.aes", label: "AES", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.sha", label: "SHA", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.rsa", label: "RSA", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.ecc", label: "ECC", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.ecdsa", label: "ECDSA", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.hmac", label: "HMAC", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.assinatura_digital", label: "Assinatura digital", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.rng", label: "Gerador aleatório", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.criptografia_flash", label: "Criptografia de flash", secao: "seguranca", topicos: ["seguranca", "flash"] },
|
||||
{ campo: "seguranca.secure_boot", label: "Secure Boot", secao: "seguranca", topicos: ["seguranca", "strapping"] },
|
||||
|
||||
{ campo: "temperatura_operacao", label: "Temperatura de operação", secao: "temperatura", topicos: ["temperatura"] },
|
||||
{ campo: "temperatura_armazenamento", label: "Temperatura de armazenamento", secao: "temperatura", topicos: ["temperatura"] },
|
||||
|
||||
{ campo: "esp_idf_minimo", label: "ESP-IDF mínimo", secao: "ferramentas", topicos: ["ferramentas"] },
|
||||
{ campo: "arduino_core", label: "Core Arduino", secao: "ferramentas", topicos: ["ferramentas"] },
|
||||
{ campo: "depuracao", label: "Depuração", secao: "ferramentas", topicos: ["jtag", "ferramentas"] },
|
||||
{ campo: "encapsulamento", label: "Encapsulamento", secao: "ferramentas", topicos: ["encapsulamento"] },
|
||||
{ campo: "modulos", label: "Módulos", secao: "ferramentas", topicos: ["encapsulamento"] },
|
||||
];
|
||||
|
||||
const ROTULOS_ENERGIA = {
|
||||
active: "Ativo",
|
||||
modem_sleep: "Modem Sleep",
|
||||
light_sleep: "Light Sleep",
|
||||
deep_sleep: "Deep Sleep",
|
||||
hibernation: "Hibernação",
|
||||
};
|
||||
|
||||
const pegar = (obj, caminho) => caminho.split(".").reduce((o, k) => (o == null ? o : o[k]), obj);
|
||||
|
||||
/**
|
||||
* Monta, para cada série, a lista plana de especificações (com os assuntos a
|
||||
* que respondem) e os pinos do diagrama. É o que o navegador baixa.
|
||||
*
|
||||
* @param {Record<string, object>} series conteúdo de public/series.json
|
||||
* @param {Record<string, object[]>} conexoes pinos por série (public/conexoes)
|
||||
*/
|
||||
export function montarConhecimento(series, conexoes) {
|
||||
const saida = {};
|
||||
for (const [chave, s] of Object.entries(series)) {
|
||||
const specs = [];
|
||||
for (const c of SPEC_CAMPOS) {
|
||||
const valor = pegar(s, c.campo);
|
||||
if (valor == null || valor === "") continue;
|
||||
specs.push({ label: c.label, valor: String(valor), secao: c.secao, topicos: c.topicos });
|
||||
}
|
||||
for (const [modo, valor] of Object.entries(s.consumo_energia ?? {})) {
|
||||
const base = modo.replace(/_cpu.*|_wifi.*/, "");
|
||||
const label = ROTULOS_ENERGIA[modo] ?? ROTULOS_ENERGIA[base] ?? modo.replace(/_/g, " ");
|
||||
specs.push({ label: `Consumo: ${label}`, valor: String(valor), secao: "energia", topicos: ["consumo"] });
|
||||
}
|
||||
saida[chave] = {
|
||||
nome: s.nome_completo ?? chave,
|
||||
specs,
|
||||
pinos: (conexoes[chave] ?? []).map((p) => ({
|
||||
n: String(p.numero),
|
||||
nome: p.nome,
|
||||
f: p.funcoes ?? [],
|
||||
c: p.categorias ?? [],
|
||||
a: p.avisos ?? [],
|
||||
})),
|
||||
};
|
||||
}
|
||||
return saida;
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
import { TOPICOS, normalizar } from "./searchTopics.js";
|
||||
|
||||
/**
|
||||
* Motor da busca inteligente (puro: sem React nem DOM).
|
||||
*
|
||||
* Em vez de só casar texto, ele INTERPRETA a consulta:
|
||||
* "flash s3" → chip = ESP32-S3, assunto = Flash
|
||||
* e então monta respostas diretas: o que a série diz sobre aquele assunto,
|
||||
* quais pinos do diagrama se relacionam a ele (com link já filtrado) e, por
|
||||
* fim, os resultados de texto de sempre (glossário, erros, componentes...).
|
||||
*/
|
||||
|
||||
const STOP = new Set([
|
||||
"de", "do", "da", "dos", "das", "o", "a", "os", "as", "um", "uma", "no", "na", "nos", "nas", "em",
|
||||
"para", "pra", "pro", "com", "sem", "que", "qual", "quais", "como", "e", "ou", "ver", "sobre", "eh",
|
||||
"preciso", "quero", "onde", "fica", "ficam", "esta", "estao", "meu", "minha", "usar", "uso",
|
||||
]);
|
||||
const INTENCAO_PINOS = new Set(["pino", "pinos", "pinagem", "pinout", "pin", "pins", "gpios"]);
|
||||
const INTENCAO_DADOS = new Set([
|
||||
"dados", "especificacao", "especificacoes", "spec", "specs", "informacao", "informacoes", "info",
|
||||
"quanto", "quantos", "quantas", "capacidade", "limite", "limites", "tem", "possui", "suporta",
|
||||
]);
|
||||
|
||||
const EXEMPLOS_TOPICOS = ["flash", "psram", "usb", "adc", "i2c", "deep sleep", "wifi", "strapping"];
|
||||
|
||||
/** Distância de edição com corte: devolve > max assim que passa do limite. */
|
||||
function distancia(a, b, max) {
|
||||
if (Math.abs(a.length - b.length) > max) return max + 1;
|
||||
let anterior = Array.from({ length: b.length + 1 }, (_, i) => i);
|
||||
for (let i = 1; i <= a.length; i++) {
|
||||
const atual = [i];
|
||||
let minimo = i;
|
||||
for (let j = 1; j <= b.length; j++) {
|
||||
const v = Math.min(anterior[j] + 1, atual[j - 1] + 1, anterior[j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
||||
atual[j] = v;
|
||||
if (v < minimo) minimo = v;
|
||||
}
|
||||
if (minimo > max) return max + 1;
|
||||
anterior = atual;
|
||||
}
|
||||
return anterior[b.length];
|
||||
}
|
||||
|
||||
const palavrasDe = (texto) => texto.split(/[^a-z0-9]+/).filter((w) => w.length > 1);
|
||||
|
||||
/** Normaliza o payload do servidor uma única vez, na abertura da busca. */
|
||||
export function preparar(dados) {
|
||||
if (!dados) return { itens: [], series: {}, porFuncao: new Map(), aliases: new Map(), chaves: [] };
|
||||
|
||||
const itensRaw = Array.isArray(dados) ? dados : (dados.itens ?? []);
|
||||
const seriesRaw = Array.isArray(dados) ? {} : (dados.series ?? {});
|
||||
|
||||
const itens = itensRaw.map((d) => {
|
||||
const _t = normalizar(d.titulo ?? "");
|
||||
const _d = normalizar(d.descricao ?? "");
|
||||
const _k = normalizar(d.keywords ?? "");
|
||||
return { ...d, _t, _d, _k, _all: `${_t} ${_k} ${_d}`, _w: new Set(palavrasDe(`${_t} ${_k}`)) };
|
||||
});
|
||||
|
||||
const series = {};
|
||||
const porFuncao = new Map(); // "gpio26" | "mtck" -> [{ chave, pino }]
|
||||
const aliases = new Map();
|
||||
|
||||
for (const [chave, s] of Object.entries(seriesRaw)) {
|
||||
const pinos = (s.pinos ?? []).map((p) => {
|
||||
const fs = (p.f ?? []).map(normalizar);
|
||||
const avs = (p.a ?? []).map(normalizar);
|
||||
return {
|
||||
...p,
|
||||
_fs: fs,
|
||||
_fn: fs,
|
||||
_avs: avs,
|
||||
_nome: normalizar(p.nome ?? ""),
|
||||
_blob: normalizar([p.nome ?? "", ...(p.f ?? []), ...(p.c ?? []), ...(p.a ?? [])].join(" ")),
|
||||
};
|
||||
});
|
||||
series[chave] = { ...s, pinos };
|
||||
|
||||
for (const p of pinos) {
|
||||
for (const f of new Set([p._nome, ...p._fs])) {
|
||||
if (!/^[a-z0-9_]{3,}$/.test(f)) continue;
|
||||
if (!porFuncao.has(f)) porFuncao.set(f, []);
|
||||
porFuncao.get(f).push({ chave, pino: p });
|
||||
}
|
||||
}
|
||||
|
||||
const k = normalizar(chave);
|
||||
aliases.set(k, chave);
|
||||
aliases.set(k.replace("-", ""), chave);
|
||||
if (k.startsWith("esp32-")) aliases.set(k.slice(6), chave);
|
||||
}
|
||||
|
||||
return { itens, series, porFuncao, aliases, chaves: Object.keys(series) };
|
||||
}
|
||||
|
||||
/** Tenta casar um termo do dicionário com os tokens livres. Devolve { idx[], qualidade } ou null. */
|
||||
function casarTermo(termo, livres) {
|
||||
const partes = termo.split(" ");
|
||||
if (partes.length > 1) {
|
||||
for (let i = 0; i + partes.length <= livres.length; i++) {
|
||||
if (partes.every((p, j) => livres[i + j].t === p)) {
|
||||
return { idx: partes.map((_, j) => livres[i + j].i), qualidade: 3 + partes.length };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
for (const { t, i } of livres) {
|
||||
if (t === termo) return { idx: [i], qualidade: 3 };
|
||||
if (t === `${termo}s` || `${t}s` === termo) return { idx: [i], qualidade: 2.5 };
|
||||
if (termo.length >= 5 && t.length >= 5 && distancia(t, termo, 1) <= 1) return { idx: [i], qualidade: 1 };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function interpretar(indice, consulta) {
|
||||
const bruto = normalizar(consulta)
|
||||
.replace(/gpio\s*-?\s*(\d+)/g, "gpio$1")
|
||||
.replace(/[^a-z0-9.+\-_ ]/g, " ");
|
||||
const tokens = bruto.split(/\s+/).filter(Boolean);
|
||||
const usados = new Set();
|
||||
|
||||
// 1) Chips
|
||||
const chips = [];
|
||||
tokens.forEach((t, i) => {
|
||||
const chave = indice.aliases.get(t);
|
||||
if (chave && t !== "esp32") {
|
||||
if (!chips.includes(chave)) chips.push(chave);
|
||||
usados.add(i);
|
||||
}
|
||||
});
|
||||
tokens.forEach((t, i) => {
|
||||
if (t !== "esp32") return;
|
||||
usados.add(i);
|
||||
if (!chips.length && indice.series.ESP32) chips.push("ESP32");
|
||||
});
|
||||
|
||||
// 2) Pinos citados (GPIO26) e palavras de intenção / ligação
|
||||
const gpios = [];
|
||||
let querPinos = false;
|
||||
let querDados = false;
|
||||
tokens.forEach((t, i) => {
|
||||
if (/^gpio\d+$/.test(t)) {
|
||||
gpios.push(t);
|
||||
usados.add(i);
|
||||
} else if (INTENCAO_PINOS.has(t)) {
|
||||
querPinos = true;
|
||||
usados.add(i);
|
||||
} else if (INTENCAO_DADOS.has(t)) {
|
||||
querDados = true;
|
||||
usados.add(i);
|
||||
} else if (STOP.has(t)) {
|
||||
usados.add(i);
|
||||
}
|
||||
});
|
||||
|
||||
// 3) Assuntos: os melhores casamentos, sem reaproveitar token
|
||||
const livres = tokens.map((t, i) => ({ t, i })).filter(({ i }) => !usados.has(i));
|
||||
const candidatos = [];
|
||||
for (const topico of TOPICOS) {
|
||||
let melhor = null;
|
||||
for (const termo of topico.termos) {
|
||||
const m = casarTermo(normalizar(termo), livres);
|
||||
if (m && (!melhor || m.qualidade > melhor.qualidade)) melhor = m;
|
||||
}
|
||||
if (melhor) candidatos.push({ topico, ...melhor });
|
||||
}
|
||||
candidatos.sort((a, b) => b.qualidade - a.qualidade);
|
||||
const topicos = [];
|
||||
for (const c of candidatos) {
|
||||
if (topicos.length >= 3) break;
|
||||
if (c.idx.some((i) => usados.has(i))) continue;
|
||||
c.idx.forEach((i) => usados.add(i));
|
||||
topicos.push(c.topico);
|
||||
}
|
||||
|
||||
// 4) Nome/função de pino exato (ex.: "mtck", "xtal_p")
|
||||
const funcoes = [];
|
||||
tokens.forEach((t, i) => {
|
||||
if (usados.has(i) || t.length < 3) return;
|
||||
if (indice.porFuncao.has(t)) {
|
||||
funcoes.push(t);
|
||||
usados.add(i);
|
||||
}
|
||||
});
|
||||
|
||||
const restantes = tokens.filter((_, i) => !usados.has(i));
|
||||
return { tokens, chips, topicos, gpios, funcoes, restantes, querPinos, querDados };
|
||||
}
|
||||
|
||||
const rotuloPino = (p) => {
|
||||
const gpio = p.f.find((f) => /^GPIO\d+$/i.test(f));
|
||||
return gpio && gpio.toLowerCase() !== p.nome.toLowerCase() ? `${gpio}/${p.nome}` : p.nome;
|
||||
};
|
||||
|
||||
/** Pinos do diagrama ligados ao assunto, já separados por nível de certeza. */
|
||||
function pinosDoTopico(serie, topico) {
|
||||
const forte = [];
|
||||
const fraco = [];
|
||||
for (const p of serie.pinos) {
|
||||
let nivel = null;
|
||||
if (topico.pinoNivel) nivel = topico.pinoNivel(p);
|
||||
else if ((topico.pinoCats && p.c.some((c) => topico.pinoCats.includes(c))) || (topico.pinoRe && topico.pinoRe.test(p._blob))) nivel = "forte";
|
||||
if (nivel === "forte") forte.push(p);
|
||||
else if (nivel === "fraco") fraco.push(p);
|
||||
}
|
||||
return { forte, fraco };
|
||||
}
|
||||
|
||||
const hrefPinos = (chave, pinos, motivo) =>
|
||||
`/series/${chave}?pinos=${pinos.map((p) => p.n).join(",")}&motivo=${encodeURIComponent(motivo)}#connections`;
|
||||
|
||||
function respostas(indice, it) {
|
||||
const saida = [];
|
||||
const alvos = it.chips.slice(0, 2);
|
||||
|
||||
for (const chave of alvos) {
|
||||
const serie = indice.series[chave];
|
||||
if (!serie) continue;
|
||||
|
||||
for (const topico of it.topicos.slice(0, 2)) {
|
||||
const specs = serie.specs.filter((s) => s.topicos.includes(topico.id));
|
||||
const cartaoSpec = specs.length
|
||||
? {
|
||||
tipo: "resposta",
|
||||
titulo: `${topico.nome} no ${serie.nome}`,
|
||||
descricao: "Dados da série",
|
||||
linhas: specs.slice(0, 5).map((s) => ({ k: s.label, v: s.valor })),
|
||||
href: `/series/${chave}#${specs[0].secao}`,
|
||||
}
|
||||
: null;
|
||||
|
||||
const { forte, fraco } = pinosDoTopico(serie, topico);
|
||||
const principais = forte.length ? forte : fraco;
|
||||
const cartaoPinos = principais.length
|
||||
? {
|
||||
tipo: "pino",
|
||||
titulo: `Pinos do ${serie.nome} ${topico.pinoRotulo}`,
|
||||
descricao:
|
||||
forte.length && fraco.length
|
||||
? `${forte.length} ocupados + ${fraco.length} que dependem do modo de uso (ex.: SPI de 8 linhas) · abre o diagrama filtrado`
|
||||
: forte.length
|
||||
? `${forte.length} ${forte.length === 1 ? "pino" : "pinos"} · abre o diagrama já filtrado`
|
||||
: `${fraco.length} pinos que só são afetados em certos modos de uso · abre o diagrama filtrado`,
|
||||
chips: forte
|
||||
.slice(0, 12)
|
||||
.map(rotuloPino)
|
||||
.concat(forte.length > 12 ? [`+${forte.length - 12}`] : [])
|
||||
.concat(fraco.length && forte.length ? [`+${fraco.length} condicionais`] : forte.length ? [] : fraco.slice(0, 10).map(rotuloPino)),
|
||||
href: hrefPinos(chave, [...forte, ...fraco], `${topico.nome}: pinos ${topico.pinoRotulo}`),
|
||||
}
|
||||
: null;
|
||||
|
||||
(it.querPinos ? [cartaoPinos, cartaoSpec] : [cartaoSpec, cartaoPinos]).filter(Boolean).forEach((c) => saida.push(c));
|
||||
}
|
||||
|
||||
if (!it.topicos.length && !it.gpios.length && !it.funcoes.length) {
|
||||
if (it.querPinos && serie.pinos.length) {
|
||||
saida.push({
|
||||
tipo: "pino",
|
||||
titulo: `Diagrama de pinos do ${serie.nome}`,
|
||||
descricao: `${serie.pinos.length} pinos com funções, restrições e avisos`,
|
||||
href: `/series/${chave}#connections`,
|
||||
});
|
||||
}
|
||||
if (it.querDados) {
|
||||
saida.push({ tipo: "resposta", titulo: `Especificações do ${serie.nome}`, descricao: "Processador, memória, conectividade, periféricos e mais", href: `/series/${chave}` });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assunto sem chip: panorama por série ("qual série tem PSRAM?")
|
||||
if (!alvos.length && it.topicos.length) {
|
||||
const topico = it.topicos[0];
|
||||
const linhas = [];
|
||||
for (const chave of indice.chaves) {
|
||||
const serie = indice.series[chave];
|
||||
const spec = serie.specs.find((s) => s.topicos.includes(topico.id));
|
||||
if (spec) linhas.push({ k: serie.nome, v: spec.valor.length > 46 ? `${spec.valor.slice(0, 45)}…` : spec.valor });
|
||||
}
|
||||
if (linhas.length > 1) {
|
||||
saida.push({ tipo: "resposta", titulo: `${topico.nome} em cada série`, descricao: "Comparativo rápido · adicione o chip na busca para detalhar", linhas, href: "/comparacao" });
|
||||
}
|
||||
}
|
||||
|
||||
// GPIO26 e nomes de função: "gpio26 s3", "mtck"
|
||||
const buscas = [...it.gpios, ...it.funcoes];
|
||||
for (const termo of buscas) {
|
||||
const achados = indice.porFuncao.get(termo) ?? [];
|
||||
const filtrados = it.chips.length ? achados.filter((a) => it.chips.includes(a.chave)) : achados;
|
||||
for (const { chave, pino } of filtrados.slice(0, it.chips.length ? 3 : 5)) {
|
||||
const serie = indice.series[chave];
|
||||
saida.push({
|
||||
tipo: "pino",
|
||||
titulo: `${rotuloPino(pino)} no ${serie.nome}`,
|
||||
descricao: [pino.f.join(" · "), pino.a[0]].filter(Boolean).join(" — "),
|
||||
href: hrefPinos(chave, [pino], `Pino ${rotuloPino(pino)}`),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return saida;
|
||||
}
|
||||
|
||||
function pontuarTermo(item, t) {
|
||||
if (item._t === t) return 100;
|
||||
if (item._t.startsWith(t)) return 60;
|
||||
if (item._t.includes(t)) return 40;
|
||||
if (item._k.includes(t)) return 15;
|
||||
if (item._d.includes(t)) return 10;
|
||||
if (t.length >= 4) {
|
||||
const max = t.length >= 8 ? 2 : 1;
|
||||
for (const w of item._w) if (distancia(w, t, max) <= max) return 6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function casaTopico(item, topico) {
|
||||
let melhor = 0;
|
||||
for (const termo of topico.termos) {
|
||||
const n = normalizar(termo);
|
||||
if (n.includes(" ") ? item._all.includes(n) : item._w.has(n)) {
|
||||
melhor = Math.max(melhor, item._t.includes(n) ? 2 : 1);
|
||||
}
|
||||
}
|
||||
return melhor;
|
||||
}
|
||||
|
||||
const topicoCasou = (item, topicos) => topicos.some((t) => casaTopico(item, t));
|
||||
|
||||
export function buscar(indice, consulta) {
|
||||
const it = interpretar(indice, consulta);
|
||||
const interpretacao = {
|
||||
chips: it.chips.map((c) => ({ chave: c, nome: indice.series[c]?.nome ?? c })),
|
||||
topicos: it.topicos.map((t) => ({ id: t.id, nome: t.nome })),
|
||||
};
|
||||
|
||||
const smart = respostas(indice, it).map((r, i) => ({ id: `r${i}`, keywords: "", ...r }));
|
||||
|
||||
const nomesChips = it.chips.map((c) => new RegExp(`(?<![a-z0-9])${normalizar(c).replace(/[-]/g, "\\-")}(?![a-z0-9]|-[a-z0-9])`));
|
||||
const pontuados = [];
|
||||
for (const item of indice.itens) {
|
||||
let s = 0;
|
||||
let ok = true;
|
||||
for (const t of it.restantes) {
|
||||
const p = pontuarTermo(item, t);
|
||||
if (!p) {
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
s += p;
|
||||
}
|
||||
if (!ok) continue;
|
||||
|
||||
let acertos = 0;
|
||||
for (const topico of it.topicos) {
|
||||
const m = casaTopico(item, topico);
|
||||
if (m) {
|
||||
s += m === 2 ? 50 : 20;
|
||||
acertos++;
|
||||
}
|
||||
}
|
||||
nomesChips.forEach((nome, i) => {
|
||||
if (item.tipo === "serie" && item.titulo === it.chips[i]) {
|
||||
s += 300;
|
||||
acertos++;
|
||||
} else if (nome.test(item._all)) {
|
||||
s += 25;
|
||||
acertos++;
|
||||
}
|
||||
});
|
||||
|
||||
const ehSerie = item.tipo === "serie" && it.chips.includes(item.titulo);
|
||||
if (!it.restantes.length && !(it.topicos.length ? acertos > (ehSerie ? 0 : 0) && topicoCasou(item, it.topicos) : ehSerie)) continue;
|
||||
if (s > 0) pontuados.push({ item, s });
|
||||
}
|
||||
pontuados.sort((a, b) => b.s - a.s);
|
||||
|
||||
// Quando já respondemos com cartões, a série que repete a resposta fica no fim.
|
||||
const texto = pontuados.slice(0, 24).map((p) => p.item);
|
||||
|
||||
const sugestoes = [];
|
||||
if (it.topicos.length && !it.chips.length) {
|
||||
for (const c of indice.chaves.slice(0, 12)) sugestoes.push({ rotulo: indice.series[c].nome, anexar: c });
|
||||
} else if (it.chips.length && !it.topicos.length && !it.gpios.length) {
|
||||
for (const nome of EXEMPLOS_TOPICOS) sugestoes.push({ rotulo: nome, anexar: nome });
|
||||
}
|
||||
|
||||
return { resultados: [...smart, ...texto], interpretacao, sugestoes, totalRespostas: smart.length };
|
||||
}
|
||||
|
||||
export const EXEMPLOS_DE_BUSCA = ["flash s3", "pinos usb c6", "deep sleep p4", "gpio0 esp32", "secure boot c3", "psram"];
|
||||
@@ -0,0 +1,104 @@
|
||||
import seriesData from "@/public/series.json";
|
||||
import frameworksData from "@/public/frameworks.json";
|
||||
import { categoriasGlossario } from "@/lib/glossarioData";
|
||||
import { errosCatalogo } from "@/lib/diagnosticoData";
|
||||
import { COMPONENTES_REGISTRY } from "@/lib/componentRegistryData";
|
||||
import { montarConhecimento } from "@/lib/searchTopics";
|
||||
import { readFileSync, existsSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
/**
|
||||
* Índice de busca do site, montado no servidor a partir dos mesmos dados que
|
||||
* alimentam as páginas. Uma série, termo ou erro novo entra sozinho na busca.
|
||||
*
|
||||
* Cada entrada: { id, tipo, titulo, descricao, href, keywords }
|
||||
* `keywords` guarda texto extra pesquisável (não exibido).
|
||||
*/
|
||||
|
||||
const PAGINAS = [
|
||||
{ titulo: "Início", descricao: "Página inicial do ESPDocs", href: "/", keywords: "home inicio" },
|
||||
{ titulo: "Todas as Séries", descricao: "Pinouts, especificações e restrições de cada série ESP32", href: "/series", keywords: "chips pinout especificações" },
|
||||
{ titulo: "Comparador de Séries", descricao: "Compare até 4 modelos lado a lado", href: "/comparacao", keywords: "comparar comparação versus" },
|
||||
{ titulo: "Catálogo de Placas", descricao: "Placas de desenvolvimento, conectores e compras", href: "/catalogo", keywords: "placas dev boards comprar devkit" },
|
||||
{ titulo: "Seletor Inteligente", descricao: "Descubra o chip ideal para o seu projeto", href: "/seletor", keywords: "quiz escolher recomendar" },
|
||||
{ titulo: "Diagnóstico de Erros", descricao: "Solucione brownout, bootloop, WDT e falhas", href: "/diagnostico", keywords: "erro problema bug falha" },
|
||||
{ titulo: "Frameworks & SDKs", descricao: "ESP-IDF, Arduino, Rust, RainMaker e mais", href: "/frameworks", keywords: "sdk" },
|
||||
{ titulo: "Component Registry", descricao: "Catálogo de drivers e gerador de idf_component.yml", href: "/componentes", keywords: "bibliotecas drivers yml" },
|
||||
{ titulo: "Glossário Técnico", descricao: "Conceitos essenciais de hardware e software", href: "/glossario", keywords: "termos dicionário significado" },
|
||||
{ titulo: "O Livro", descricao: "Microcontroladores ESP32: conectividade, eficiência e desempenho", href: "/livro", keywords: "livro book capa comprar" },
|
||||
{ titulo: "Sobre o Projeto", descricao: "História, autor e Ciência Embarcada", href: "/sobre", keywords: "autor contato" },
|
||||
];
|
||||
|
||||
const cortar = (texto = "", max = 140) => (texto.length > max ? `${texto.slice(0, max - 1).trimEnd()}…` : texto);
|
||||
|
||||
export function construirIndiceBusca() {
|
||||
const itens = [];
|
||||
|
||||
for (const p of PAGINAS) {
|
||||
itens.push({ tipo: "pagina", ...p, keywords: p.keywords });
|
||||
}
|
||||
|
||||
for (const [chave, s] of Object.entries(seriesData)) {
|
||||
itens.push({
|
||||
tipo: "serie",
|
||||
titulo: chave,
|
||||
descricao: cortar(`${s.nome_completo ?? ""} — ${s.descricao ?? ""}`),
|
||||
href: `/series/${chave}`,
|
||||
keywords: [s.arquitetura, s.wifi, s.bluetooth, s.frequencia, s.nucleos].filter(Boolean).join(" "),
|
||||
});
|
||||
}
|
||||
|
||||
for (const [chave, f] of Object.entries(frameworksData)) {
|
||||
itens.push({
|
||||
tipo: "framework",
|
||||
titulo: f.nome ?? chave,
|
||||
descricao: cortar(`${f.nome_completo ?? ""} — ${f.descricao ?? ""}`),
|
||||
href: `/frameworks/${encodeURIComponent(chave)}`,
|
||||
keywords: [f.linguagem, f.tipo, f.funcao_principal].filter(Boolean).join(" "),
|
||||
});
|
||||
}
|
||||
|
||||
for (const cat of categoriasGlossario) {
|
||||
for (const t of cat.termos) {
|
||||
const slug = t.termo.toLowerCase().replace(/[\s()/²]+/g, "-");
|
||||
itens.push({
|
||||
tipo: "glossario",
|
||||
titulo: t.termo,
|
||||
descricao: cortar(t.definicao),
|
||||
href: `/glossario#${slug}`,
|
||||
keywords: [cat.nome, t.exemplo].filter(Boolean).join(" "),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const e of errosCatalogo) {
|
||||
itens.push({
|
||||
tipo: "erro",
|
||||
titulo: e.titulo,
|
||||
descricao: cortar(e.resumo),
|
||||
href: `/diagnostico#${e.id}`,
|
||||
keywords: [e.logSerial, ...(e.sintomas ?? [])].filter(Boolean).join(" "),
|
||||
});
|
||||
}
|
||||
|
||||
for (const c of COMPONENTES_REGISTRY) {
|
||||
itens.push({
|
||||
tipo: "componente",
|
||||
titulo: c.titulo,
|
||||
descricao: cortar(c.descricao),
|
||||
href: "/componentes",
|
||||
keywords: [c.name, c.namespace, ...(c.tags ?? [])].filter(Boolean).join(" "),
|
||||
});
|
||||
}
|
||||
|
||||
const conexoes = {};
|
||||
for (const chave of Object.keys(seriesData)) {
|
||||
const arquivo = path.join(process.cwd(), "public", "conexoes", `${chave}.json`);
|
||||
if (existsSync(arquivo)) conexoes[chave] = JSON.parse(readFileSync(arquivo, "utf8"));
|
||||
}
|
||||
|
||||
return {
|
||||
itens: itens.map((item, i) => ({ id: i, ...item })),
|
||||
series: montarConhecimento(seriesData, conexoes),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* Conhecimento de domínio da busca inteligente.
|
||||
*
|
||||
* Sem dependências nem alias de import: roda no servidor (montando o índice),
|
||||
* no navegador (interpretando a consulta) e em scripts de teste no Node.
|
||||
*
|
||||
* Todos os textos de `termos` já estão normalizados (minúsculos, sem acento).
|
||||
*/
|
||||
|
||||
export const normalizar = (s = "") =>
|
||||
String(s)
|
||||
.toLowerCase()
|
||||
.normalize("NFD")
|
||||
.replace(/[\u0300-\u036f]/g, "");
|
||||
|
||||
/**
|
||||
* Reconhece pinos ocupados por flash/PSRAM com base no que o diagrama diz.
|
||||
* "forte": o pino é consumido pela memória (ou é a alimentação dela).
|
||||
* "fraco": só é afetado em certos modos (ex.: SPI de 8 linhas/octal).
|
||||
* Avisos genéricos de tensão mínima ("para chips com flash integrada...") não contam.
|
||||
*/
|
||||
const nivelMemoria = (palavra) => (p) => {
|
||||
const citam = p._avs.filter((a) => a.includes(palavra) && !/^para chips (com|sem)/.test(a));
|
||||
if (citam.some((a) => /(utilizad|dedicad|conectad)/.test(a) && !/a menos que/.test(a))) return "forte";
|
||||
if (p._fn.some((f) => /alimentacao/.test(f) && f.includes(palavra))) return "forte";
|
||||
if (citam.length) return "fraco";
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assuntos que o usuário pode citar. Cada um sabe:
|
||||
* - termos: como as pessoas escrevem (sinônimos, siglas, plurais comuns);
|
||||
* - pinoCats / pinoRe: como reconhecer os pinos relacionados no diagrama;
|
||||
* - pinoRotulo: frase usada no título do resultado de pinos.
|
||||
* Os dados de especificação ligam-se aos assuntos por SPEC_CAMPOS.
|
||||
*/
|
||||
export const TOPICOS = [
|
||||
{ id: "flash", nome: "Flash", termos: ["flash", "memoria flash", "spi flash", "armazenamento", "firmware", "rom externa"], pinoNivel: nivelMemoria("flash"), pinoRotulo: "ligados à memória flash" },
|
||||
{ id: "psram", nome: "PSRAM", termos: ["psram", "ram externa", "spiram"], pinoNivel: nivelMemoria("psram"), pinoRotulo: "ligados à PSRAM" },
|
||||
{ id: "memoria", nome: "Memória", termos: ["memoria", "sram", "heap", "rtc ram", "kb de ram", "memoria interna", "ram"], pinoRotulo: "" },
|
||||
{ id: "wifi", nome: "Wi-Fi", termos: ["wifi", "wi-fi", "wireless", "sem fio", "802.11", "wifi6", "wifi 6", "wi-fi 6"], pinoCats: ["Antena"], pinoRotulo: "de antena e rádio" },
|
||||
{ id: "bluetooth", nome: "Bluetooth", termos: ["bluetooth", "ble", "bt", "bluetooth le", "mesh"], pinoCats: ["Antena"], pinoRotulo: "de antena e rádio" },
|
||||
{ id: "zigbee", nome: "Zigbee/Thread", termos: ["zigbee", "thread", "802.15.4", "ieee 802.15.4"], pinoRotulo: "" },
|
||||
{ id: "matter", nome: "Matter", termos: ["matter", "casa inteligente", "smart home"], pinoRotulo: "" },
|
||||
{ id: "ethernet", nome: "Ethernet", termos: ["ethernet", "rmii", "cabo de rede", "lan"], pinoCats: ["Ethernet"], pinoRotulo: "de Ethernet" },
|
||||
{ id: "can", nome: "CAN / TWAI", termos: ["can", "twai", "can bus", "canbus", "can fd"], pinoRe: /twai|\bcan\b/, pinoRotulo: "de CAN/TWAI" },
|
||||
{ id: "usb", nome: "USB", termos: ["usb", "otg", "usb serial", "usb otg", "hid", "cdc"], pinoCats: ["USB"], pinoRotulo: "de USB" },
|
||||
{ id: "jtag", nome: "JTAG / Depuração", termos: ["jtag", "debug", "depuracao", "depurar", "openocd", "gdb"], pinoCats: ["JTAG"], pinoRotulo: "de JTAG" },
|
||||
{ id: "adc", nome: "ADC", termos: ["adc", "analogico", "entrada analogica", "conversor analogico", "analogread", "saradc"], pinoCats: ["ADC"], pinoRotulo: "com ADC" },
|
||||
{ id: "dac", nome: "DAC", termos: ["dac", "saida analogica", "conversor digital"], pinoCats: ["DAC"], pinoRotulo: "com DAC" },
|
||||
{ id: "touch", nome: "Touch capacitivo", termos: ["touch", "capacitivo", "toque", "touchpad", "sensor de toque"], pinoCats: ["Touch"], pinoRotulo: "de touch capacitivo" },
|
||||
{ id: "uart", nome: "UART", termos: ["uart", "serial", "tx", "rx", "txd", "rxd", "porta serial"], pinoCats: ["UART"], pinoRotulo: "de UART" },
|
||||
{ id: "spi", nome: "SPI", termos: ["spi", "mosi", "miso", "sclk", "barramento spi"], pinoCats: ["SPI"], pinoRotulo: "de SPI" },
|
||||
{ id: "i2c", nome: "I2C", termos: ["i2c", "sda", "scl", "twi", "iic"], pinoCats: ["I2C"], pinoRotulo: "de I2C" },
|
||||
{ id: "i2s", nome: "I2S", termos: ["i2s", "audio", "som", "microfone", "pdm", "codec"], pinoRe: /i2s|\bpdm\b/, pinoRotulo: "de I2S/áudio" },
|
||||
{ id: "pwm", nome: "PWM", termos: ["pwm", "ledc", "mcpwm", "servo", "dimmer"], pinoRe: /ledc|pwm/, pinoRotulo: "de PWM" },
|
||||
{ id: "sd", nome: "Cartão SD / SDIO", termos: ["sd", "sdio", "sd card", "sdcard", "cartao sd", "microsd", "sdmmc", "mmc"], pinoCats: ["SD"], pinoRe: /sdio|sdmmc|\bsd\b/, pinoRotulo: "de cartão SD/SDIO" },
|
||||
{ id: "camera", nome: "Câmera", termos: ["camera", "cam", "dvp", "csi", "mipi csi", "ov2640", "video"], pinoCats: ["CSI"], pinoRe: /\bcam\b|dvp|cam_/, pinoRotulo: "de câmera" },
|
||||
{ id: "lcd", nome: "Display / LCD", termos: ["lcd", "display", "tela", "dsi", "mipi dsi", "oled", "tft", "lvgl", "rgb"], pinoCats: ["DSI"], pinoRe: /lcd/, pinoRotulo: "de display/LCD" },
|
||||
{ id: "strapping", nome: "Boot / Strapping", termos: ["strapping", "boot", "bootstrap", "modo de boot", "download mode", "modo de gravacao", "inicializacao"], pinoCats: ["Strapping"], pinoRotulo: "de strapping (modo de boot)" },
|
||||
{ id: "energia_pinos", nome: "Alimentação", termos: ["alimentacao", "vdd", "3v3", "3.3v", "tensao", "regulador", "ldo", "fonte"], pinoCats: ["Power"], pinoRotulo: "de alimentação" },
|
||||
{ id: "clock", nome: "Clock / Cristal", termos: ["clock", "xtal", "cristal", "oscilador", "32khz", "40mhz"], pinoCats: ["Clock"], pinoRotulo: "de clock/cristal" },
|
||||
{ id: "gpio", nome: "GPIO", termos: ["gpio", "entradas e saidas"], pinoCats: ["GPIO"], pinoRotulo: "de GPIO" },
|
||||
{ id: "baixo_consumo", nome: "Baixo consumo / ULP", termos: ["ulp", "lp core", "lp cpu", "coprocessador", "lp gpio", "low power", "rtc gpio"], pinoCats: ["Low Power"], pinoRotulo: "de baixo consumo (LP/RTC)" },
|
||||
{ id: "antena", nome: "Antena / RF", termos: ["antena", "rf", "radiofrequencia", "ipex"], pinoCats: ["Antena"], pinoRotulo: "de antena/RF" },
|
||||
{ id: "seguranca", nome: "Segurança", termos: ["seguranca", "secure boot", "criptografia", "encriptacao", "aes", "sha", "rsa", "hmac", "ecdsa", "efuse", "tee", "trng", "rng", "hsm", "protecao"], pinoRotulo: "" },
|
||||
{ id: "consumo", nome: "Consumo de energia", termos: ["consumo", "bateria", "deep sleep", "light sleep", "sleep", "modem sleep", "corrente", "miliamperes", "autonomia", "economia de energia", "low power mode"], pinoRotulo: "" },
|
||||
{ id: "temperatura", nome: "Temperatura", termos: ["temperatura", "calor", "graus", "faixa de temperatura", "industrial"], pinoRotulo: "" },
|
||||
{ id: "ia", nome: "IA / Aceleração", termos: ["ia", "ai", "machine learning", "ml", "tinyml", "vetorial", "inteligencia artificial", "rede neural", "esp-nn", "esp-dl"], pinoRotulo: "" },
|
||||
{ id: "processador", nome: "Processador", termos: ["processador", "cpu", "nucleo", "nucleos", "core", "dual core", "single core", "arquitetura", "xtensa", "risc-v", "riscv"], pinoRotulo: "" },
|
||||
{ id: "frequencia", nome: "Frequência", termos: ["frequencia", "mhz", "velocidade", "desempenho", "performance"], pinoRotulo: "" },
|
||||
{ id: "ferramentas", nome: "Ferramentas / SDK", termos: ["esp-idf", "idf", "arduino", "sdk", "toolchain", "versao do idf"], pinoRotulo: "" },
|
||||
{ id: "encapsulamento", nome: "Módulos e encapsulamento", termos: ["modulo", "modulos", "encapsulamento", "package", "qfn", "wroom", "wrover", "mini-1"], pinoRotulo: "" },
|
||||
];
|
||||
|
||||
/**
|
||||
* Campos de public/series.json que respondem a cada assunto.
|
||||
* `campo` aceita caminho com ponto (seguranca.aes). `secao` é o id da âncora
|
||||
* na página /series/[key].
|
||||
*/
|
||||
export const SPEC_CAMPOS = [
|
||||
{ campo: "arquitetura", label: "Arquitetura", secao: "processador", topicos: ["processador"] },
|
||||
{ campo: "nucleos", label: "Núcleos", secao: "processador", topicos: ["processador"] },
|
||||
{ campo: "frequencia", label: "Frequência", secao: "processador", topicos: ["frequencia", "processador"] },
|
||||
{ campo: "coprocessador_ulp", label: "Coprocessador ULP", secao: "processador", topicos: ["baixo_consumo"] },
|
||||
{ campo: "aceleradores_ia", label: "Aceleradores de IA", secao: "processador", topicos: ["ia"] },
|
||||
|
||||
{ campo: "wifi", label: "Wi-Fi", secao: "conectividade", topicos: ["wifi"] },
|
||||
{ campo: "bluetooth", label: "Bluetooth", secao: "conectividade", topicos: ["bluetooth"] },
|
||||
{ campo: "zigbee_thread", label: "Zigbee/Thread", secao: "conectividade", topicos: ["zigbee"] },
|
||||
{ campo: "matter", label: "Matter", secao: "conectividade", topicos: ["matter"] },
|
||||
{ campo: "ethernet", label: "Ethernet", secao: "conectividade", topicos: ["ethernet"] },
|
||||
{ campo: "ethernet_mac", label: "Ethernet MAC", secao: "conectividade", topicos: ["ethernet"] },
|
||||
{ campo: "can", label: "CAN", secao: "conectividade", topicos: ["can"] },
|
||||
|
||||
{ campo: "memoria_sram", label: "SRAM", secao: "memoria", topicos: ["memoria"] },
|
||||
{ campo: "memoria_sram_rtc", label: "SRAM RTC", secao: "memoria", topicos: ["memoria", "baixo_consumo"] },
|
||||
{ campo: "memoria_rom", label: "ROM", secao: "memoria", topicos: ["memoria"] },
|
||||
{ campo: "flash_externa", label: "Flash externa", secao: "memoria", topicos: ["flash", "memoria"] },
|
||||
{ campo: "psram_externa", label: "PSRAM externa", secao: "memoria", topicos: ["psram", "memoria"] },
|
||||
|
||||
{ campo: "gpio", label: "GPIO", secao: "perifericos", topicos: ["gpio"] },
|
||||
{ campo: "adc", label: "ADC", secao: "perifericos", topicos: ["adc"] },
|
||||
{ campo: "dac", label: "DAC", secao: "perifericos", topicos: ["dac"] },
|
||||
{ campo: "touch", label: "Touch", secao: "perifericos", topicos: ["touch"] },
|
||||
{ campo: "uart", label: "UART", secao: "perifericos", topicos: ["uart"] },
|
||||
{ campo: "spi", label: "SPI", secao: "perifericos", topicos: ["spi", "flash"] },
|
||||
{ campo: "i2c", label: "I2C", secao: "perifericos", topicos: ["i2c"] },
|
||||
{ campo: "i2s", label: "I2S", secao: "perifericos", topicos: ["i2s"] },
|
||||
{ campo: "pwm", label: "PWM", secao: "perifericos", topicos: ["pwm"] },
|
||||
{ campo: "usb", label: "USB", secao: "perifericos", topicos: ["usb"] },
|
||||
{ campo: "lcd", label: "LCD", secao: "interfaces", topicos: ["lcd"] },
|
||||
{ campo: "camera", label: "Câmera", secao: "interfaces", topicos: ["camera"] },
|
||||
{ campo: "mipi_csi", label: "MIPI CSI", secao: "interfaces", topicos: ["camera"] },
|
||||
{ campo: "mipi_dsi", label: "MIPI DSI", secao: "interfaces", topicos: ["lcd"] },
|
||||
{ campo: "sdio", label: "SDIO", secao: "interfaces", topicos: ["sd"] },
|
||||
{ campo: "sensor_temperatura", label: "Sensor de temperatura", secao: "interfaces", topicos: ["temperatura"] },
|
||||
|
||||
{ campo: "seguranca.aes", label: "AES", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.sha", label: "SHA", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.rsa", label: "RSA", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.ecc", label: "ECC", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.ecdsa", label: "ECDSA", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.hmac", label: "HMAC", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.assinatura_digital", label: "Assinatura digital", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.rng", label: "Gerador aleatório", secao: "seguranca", topicos: ["seguranca"] },
|
||||
{ campo: "seguranca.criptografia_flash", label: "Criptografia de flash", secao: "seguranca", topicos: ["seguranca", "flash"] },
|
||||
{ campo: "seguranca.secure_boot", label: "Secure Boot", secao: "seguranca", topicos: ["seguranca", "strapping"] },
|
||||
|
||||
{ campo: "temperatura_operacao", label: "Temperatura de operação", secao: "temperatura", topicos: ["temperatura"] },
|
||||
{ campo: "temperatura_armazenamento", label: "Temperatura de armazenamento", secao: "temperatura", topicos: ["temperatura"] },
|
||||
|
||||
{ campo: "esp_idf_minimo", label: "ESP-IDF mínimo", secao: "ferramentas", topicos: ["ferramentas"] },
|
||||
{ campo: "arduino_core", label: "Core Arduino", secao: "ferramentas", topicos: ["ferramentas"] },
|
||||
{ campo: "depuracao", label: "Depuração", secao: "ferramentas", topicos: ["jtag", "ferramentas"] },
|
||||
{ campo: "encapsulamento", label: "Encapsulamento", secao: "ferramentas", topicos: ["encapsulamento"] },
|
||||
{ campo: "modulos", label: "Módulos", secao: "ferramentas", topicos: ["encapsulamento"] },
|
||||
];
|
||||
|
||||
const ROTULOS_ENERGIA = {
|
||||
active: "Ativo",
|
||||
modem_sleep: "Modem Sleep",
|
||||
light_sleep: "Light Sleep",
|
||||
deep_sleep: "Deep Sleep",
|
||||
hibernation: "Hibernação",
|
||||
};
|
||||
|
||||
const pegar = (obj, caminho) => caminho.split(".").reduce((o, k) => (o == null ? o : o[k]), obj);
|
||||
|
||||
/**
|
||||
* Monta, para cada série, a lista plana de especificações (com os assuntos a
|
||||
* que respondem) e os pinos do diagrama. É o que o navegador baixa.
|
||||
*
|
||||
* @param {Record<string, object>} series conteúdo de public/series.json
|
||||
* @param {Record<string, object[]>} conexoes pinos por série (public/conexoes)
|
||||
*/
|
||||
export function montarConhecimento(series, conexoes) {
|
||||
const saida = {};
|
||||
for (const [chave, s] of Object.entries(series)) {
|
||||
const specs = [];
|
||||
for (const c of SPEC_CAMPOS) {
|
||||
const valor = pegar(s, c.campo);
|
||||
if (valor == null || valor === "") continue;
|
||||
specs.push({ label: c.label, valor: String(valor), secao: c.secao, topicos: c.topicos });
|
||||
}
|
||||
for (const [modo, valor] of Object.entries(s.consumo_energia ?? {})) {
|
||||
const base = modo.replace(/_cpu.*|_wifi.*/, "");
|
||||
const label = ROTULOS_ENERGIA[modo] ?? ROTULOS_ENERGIA[base] ?? modo.replace(/_/g, " ");
|
||||
specs.push({ label: `Consumo: ${label}`, valor: String(valor), secao: "energia", topicos: ["consumo"] });
|
||||
}
|
||||
saida[chave] = {
|
||||
nome: s.nome_completo ?? chave,
|
||||
specs,
|
||||
pinos: (conexoes[chave] ?? []).map((p) => ({
|
||||
n: String(p.numero),
|
||||
nome: p.nome,
|
||||
f: p.funcoes ?? [],
|
||||
c: p.categorias ?? [],
|
||||
a: p.avisos ?? [],
|
||||
})),
|
||||
};
|
||||
}
|
||||
return saida;
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ export const SITE = {
|
||||
autorUrl: "https://lucasrguerra.dev.br",
|
||||
autorLinkedin: "https://linkedin.com/in/lucasrguerra",
|
||||
autorEmail: "contato@lucasrguerra.dev.br",
|
||||
repositorio: "https://github.com/lucasrguerra/ESPDocs",
|
||||
repositorio: "https://git.lucasrguerra.dev.br/lucasrguerra/ESPDocs",
|
||||
blog: "https://cienciaembarcada.com.br",
|
||||
livroTitulo: "Microcontroladores ESP32",
|
||||
livroSubtitulo: "Conectividade, Eficiência e Desempenho",
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
{
|
||||
"Common": {
|
||||
"siteName": "ESPDocs",
|
||||
"author": "Lucas Rayan Guerra",
|
||||
"organization": "Ciência Embarcada",
|
||||
"skipToContent": "Pular para o conteúdo",
|
||||
"allRightsReserved": "Conteúdo sob licença MIT. Feito para a comunidade de sistemas embarcados.",
|
||||
"backToHome": "Voltar ao início",
|
||||
"explore": "Explorar",
|
||||
"tools": "Ferramentas",
|
||||
"project": "Projeto",
|
||||
"loading": "Carregando...",
|
||||
"search": "Buscar...",
|
||||
"officialDocumentation": "Documentação oficial",
|
||||
"community": "Comunidade",
|
||||
"mitLicense": "Licença MIT"
|
||||
},
|
||||
"Header": {
|
||||
"brand": "ESPDocs",
|
||||
"homeAria": "ESPDocs, página inicial",
|
||||
"navAria": "Navegação principal",
|
||||
"mobileNavAria": "Navegação móvel",
|
||||
"openMenu": "Abrir menu de navegação",
|
||||
"closeMenu": "Fechar menu",
|
||||
"navigationTitle": "Navegação",
|
||||
"whereToGo": "Para onde ir",
|
||||
"selectChip": "Selecionar chip",
|
||||
"selectMyChip": "Selecionar meu chip",
|
||||
"hardware": "Hardware",
|
||||
"hardwareDesc": "12 chips, pinagem e especificações",
|
||||
"series": "Séries ESP32",
|
||||
"seriesDesc": "12 chips, pinagem e especificações",
|
||||
"comparator": "Comparador",
|
||||
"comparatorDesc": "Até quatro séries lado a lado",
|
||||
"catalog": "Catálogo de placas",
|
||||
"catalogDesc": "DevKits, pinos e onde comprar",
|
||||
"tools": "Ferramentas",
|
||||
"selector": "Seletor inteligente",
|
||||
"selectorDesc": "O chip certo para o seu projeto",
|
||||
"diagnostics": "Diagnóstico",
|
||||
"diagnosticsDesc": "Brownout, bootloop, WDT e mais",
|
||||
"components": "Component Registry",
|
||||
"componentsDesc": "Drivers e manifests idf_component.yml",
|
||||
"library": "Biblioteca",
|
||||
"frameworks": "Frameworks e SDKs",
|
||||
"frameworksDesc": "ESP-IDF, Arduino, Rust e Matter",
|
||||
"glossary": "Glossário técnico",
|
||||
"glossaryDesc": "Os termos que aparecem nos datasheets",
|
||||
"about": "Sobre o projeto",
|
||||
"aboutDesc": "Autoria, método e abertura",
|
||||
"book": "Livro",
|
||||
"bookNew": "Livro novo",
|
||||
"bookTitle": "Microcontroladores ESP32",
|
||||
"bookSubtitle": "Conectividade, eficiência e desempenho"
|
||||
},
|
||||
"Footer": {
|
||||
"ariaLabel": "Rodapé do ESPDocs",
|
||||
"description": "Documentação independente do ecossistema ESP32, escrita em português brasileiro. Dados públicos, curadoria editorial e links para as fontes oficiais.",
|
||||
"exploreTitle": "Explorar",
|
||||
"toolsTitle": "Ferramentas",
|
||||
"projectTitle": "Projeto",
|
||||
"authorTitle": "Autor",
|
||||
"reportIssue": "Reportar um problema",
|
||||
"repository": "Repositório",
|
||||
"personalSite": "Site pessoal",
|
||||
"linkedin": "LinkedIn",
|
||||
"bookNew": "Livro novo",
|
||||
"bookTitle": "Microcontroladores ESP32",
|
||||
"bookSubtitle": "Conectividade, eficiência e desempenho",
|
||||
"amazon": "Amazon",
|
||||
"uiclap": "UICLAP"
|
||||
},
|
||||
"Home": {
|
||||
"badge": "Documentação aberta do ESP32",
|
||||
"titleLine1": "O ESP32,",
|
||||
"titleLine2": " sem ruído.",
|
||||
"lede": "Especificações, pinagem, comparações e diagnóstico em uma leitura só. Menos tradução de datasheet, mais tempo com o protótipo na bancada.",
|
||||
"chooseMyChip": "Escolher meu chip",
|
||||
"exploreSeries": "Explorar as {count} séries",
|
||||
"seriesCount": "{count} séries",
|
||||
"frameworkCount": "{count} frameworks",
|
||||
"bookChapters": "78 capítulos no livro",
|
||||
"portugueseFlag": "100% em português",
|
||||
"featuredSeries": "Séries em destaque",
|
||||
"featuredDesc": "O essencial de cada família, antes de abrir o datasheet.",
|
||||
"fullIndex": "Índice completo",
|
||||
"toolsTitle": "Comece pelo problema.",
|
||||
"toolsEyebrow": "Ferramentas",
|
||||
"toolsDesc": "Ferramentas para selecionar o chip certo, diagnosticar erros de hardware e acelerar seu desenvolvimento.",
|
||||
"bookTitle": "Microcontroladores ESP32",
|
||||
"bookSubtitle": "Conectividade, Eficiência e Desempenho",
|
||||
"bookNewBadge": "Livro novo",
|
||||
"bookDescription": "Um percurso completo pelo hardware e pelo firmware do ESP32: da arquitetura do chip à implantação de produtos conectados. São 12 partes e 78 capítulos sobre Arduino, ESP-IDF, FreeRTOS, Wi-Fi, BLE, Thread e Matter, periféricos, depuração, baixo consumo e segurança.",
|
||||
"bookParts": "12 partes",
|
||||
"bookChaptersCount": "78 capítulos",
|
||||
"buyDigital": "Comprar digital",
|
||||
"buyPrint": "Comprar impresso",
|
||||
"fullRecord": "Ficha completa"
|
||||
},
|
||||
"NotFound": {
|
||||
"eyebrow": "Erro 404",
|
||||
"title": "Essa página não existe.",
|
||||
"lede": "O endereço pode ter mudado ou estar digitado errado. Escolha um destes caminhos para continuar.",
|
||||
"backToHome": "Voltar ao início",
|
||||
"seriesTitle": "Séries ESP32",
|
||||
"seriesDesc": "As 12 famílias, com pinagem e especificações.",
|
||||
"selectorTitle": "Seletor de chip",
|
||||
"selectorDesc": "Responda a oito perguntas e receba os modelos indicados.",
|
||||
"comparatorTitle": "Comparador",
|
||||
"comparatorDesc": "Até quatro séries lado a lado.",
|
||||
"glossaryTitle": "Glossário",
|
||||
"glossaryDesc": "Termos de hardware explicados em português."
|
||||
},
|
||||
"Sobre": {
|
||||
"label": "Projeto independente",
|
||||
"title": "Sobre o ESPDocs",
|
||||
"lede": "Uma plataforma não oficial, em português, que organiza as informações técnicas do ESP32 e leva você à documentação oficial da Espressif. Feita para a comunidade de hardware livre.",
|
||||
"viewRepository": "Ver o repositório",
|
||||
"features": {
|
||||
"portugueseTitle": "Em português",
|
||||
"portugueseDesc": "Dados técnicos organizados e apresentados em português do Brasil.",
|
||||
"visualCompareTitle": "Comparações visuais",
|
||||
"visualCompareDesc": "Tabelas e diagramas para escolher a série certa sem abrir dez datasheets.",
|
||||
"centralizedAccessTitle": "Acesso centralizado",
|
||||
"centralizedAccessDesc": "Links diretos para a documentação oficial, repositórios e exemplos.",
|
||||
"openSourceTitle": "Código aberto",
|
||||
"openSourceDesc": "Contribuições são bem-vindas no Gitea."
|
||||
}
|
||||
},
|
||||
"Series": {
|
||||
"title": "Séries ESP32",
|
||||
"description": "As 12 séries de ESP32 lado a lado: ESP32, S2, S3, S31, C2, C3, C5, C6, C61, P4, H2 e H4. Arquitetura, memória, rádio, periféricos e pinagem de cada uma, em português.",
|
||||
"pinout": "Pinagem",
|
||||
"specifications": "Especificações",
|
||||
"peripherals": "Periféricos",
|
||||
"architecture": "Arquitetura",
|
||||
"memory": "Memória",
|
||||
"radio": "Rádio",
|
||||
"security": "Segurança em hardware"
|
||||
},
|
||||
"Catalogo": {
|
||||
"title": "Catálogo de Placas de Desenvolvimento",
|
||||
"description": "DevKits oficiais e de terceiros com pinagem, interfaces e links para compra.",
|
||||
"filterBySeries": "Filtrar por série",
|
||||
"searchBoards": "Buscar placas..."
|
||||
},
|
||||
"Comparacao": {
|
||||
"title": "Comparador de Séries ESP32",
|
||||
"description": "Compare até 4 séries lado a lado com especificações completas de processamento, rádio, memória e pinagem."
|
||||
},
|
||||
"Componentes": {
|
||||
"title": "ESP Component Registry",
|
||||
"description": "Drivers, bibliotecas e manifests idf_component.yml prontos para uso no ESP-IDF."
|
||||
},
|
||||
"Diagnostico": {
|
||||
"title": "Diagnóstico & Resolução de Problemas",
|
||||
"description": "Brownout, bootloops, pânicos de CPU, FreeRTOS e boas práticas de hardware."
|
||||
},
|
||||
"Frameworks": {
|
||||
"title": "Frameworks e SDKs",
|
||||
"description": "Guias e visão geral dos principais ambientes de desenvolvimento: ESP-IDF, Arduino, MicroPython, Rust e ESP-Matter."
|
||||
},
|
||||
"Glossario": {
|
||||
"title": "Glossário Técnico",
|
||||
"description": "Explicações práticas em português de conceitos de hardware, periféricos, rádio e arquitetura que aparecem nos datasheets."
|
||||
},
|
||||
"Seletor": {
|
||||
"title": "Seletor Inteligente de ESP32",
|
||||
"description": "Responda a perguntas objetivas sobre o seu projeto e descubra a série ideal com base técnica."
|
||||
},
|
||||
"Livro": {
|
||||
"title": "Microcontroladores ESP32, o livro",
|
||||
"subtitle": "Conectividade, eficiência e desempenho",
|
||||
"badge": "Livro novo · 1ª edição",
|
||||
"description": "12 partes e 78 capítulos em português cobrindo o ecossistema ESP32 do hardware ao firmware.",
|
||||
"buyDigital": "Comprar digital",
|
||||
"buyPrint": "Comprar impresso",
|
||||
"chaptersTitle": "Conteúdo e Capítulos"
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
import createMiddleware from "next-intl/middleware";
|
||||
import { NextResponse } from "next/server";
|
||||
import { routing } from "./i18n/routing";
|
||||
|
||||
const intlMiddleware = createMiddleware(routing);
|
||||
|
||||
const SUPPORTED_LOCALES = routing.locales;
|
||||
|
||||
function parseAcceptLanguage(header) {
|
||||
if (!header) return [];
|
||||
return header
|
||||
.split(",")
|
||||
.map((part) => {
|
||||
const [langRange, qPart] = part.trim().split(";");
|
||||
let q = 1.0;
|
||||
if (qPart) {
|
||||
const match = qPart.match(/q=([\d.]+)/);
|
||||
if (match) {
|
||||
const parsed = parseFloat(match[1]);
|
||||
if (!isNaN(parsed)) q = parsed;
|
||||
}
|
||||
}
|
||||
return { lang: langRange.trim().toLowerCase(), q };
|
||||
})
|
||||
.sort((a, b) => b.q - a.q);
|
||||
}
|
||||
|
||||
function matchLocale(lang) {
|
||||
if (lang.startsWith("pt")) return "pt";
|
||||
if (lang.startsWith("es")) return "es";
|
||||
if (lang.startsWith("fr")) return "fr";
|
||||
if (lang.startsWith("de")) return "de";
|
||||
if (lang.startsWith("zh")) return "zh-CN";
|
||||
if (lang.startsWith("en")) return "en";
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolveRootLocale(request) {
|
||||
const cookieValue = request.cookies.get("NEXT_LOCALE")?.value;
|
||||
if (cookieValue && SUPPORTED_LOCALES.includes(cookieValue)) {
|
||||
return cookieValue;
|
||||
}
|
||||
const acceptLang = request.headers.get("accept-language");
|
||||
const parsed = parseAcceptLanguage(acceptLang);
|
||||
for (const { lang } of parsed) {
|
||||
const matched = matchLocale(lang);
|
||||
if (matched) return matched;
|
||||
}
|
||||
return "en";
|
||||
}
|
||||
|
||||
export default function middleware(request) {
|
||||
const { pathname, search } = request.nextUrl;
|
||||
|
||||
// Exclusões de caminhos e arquivos estáticos
|
||||
if (
|
||||
pathname.startsWith("/api") ||
|
||||
pathname.startsWith("/_next") ||
|
||||
pathname === "/robots.txt" ||
|
||||
pathname === "/sitemap.xml" ||
|
||||
pathname === "/google21a790a2c23c0ec5.html" ||
|
||||
/\.[a-zA-Z0-9]+$/.test(pathname)
|
||||
) {
|
||||
return NextResponse.next();
|
||||
}
|
||||
|
||||
// 1. Raiz: negociação de idioma (307)
|
||||
if (pathname === "/") {
|
||||
const targetLocale = resolveRootLocale(request);
|
||||
const url = new URL(`/${targetLocale}`, request.url);
|
||||
url.search = search;
|
||||
const response = NextResponse.redirect(url, 307);
|
||||
response.headers.set("Vary", "Accept-Language, Cookie");
|
||||
response.headers.set("Cache-Control", "private, no-store");
|
||||
return response;
|
||||
}
|
||||
|
||||
// 2. Livro fora do português: 404
|
||||
if (/^\/(en|es|fr|de|zh-CN)\/livro(\/.*)?$/.test(pathname)) {
|
||||
return new NextResponse(null, { status: 404 });
|
||||
}
|
||||
|
||||
// 3. URLs antigas sem prefixo reconhecido: redirecionamento 308 para /pt/<caminho>
|
||||
const hasLocalePrefix = SUPPORTED_LOCALES.some(
|
||||
(loc) => pathname === `/${loc}` || pathname.startsWith(`/${loc}/`)
|
||||
);
|
||||
|
||||
if (!hasLocalePrefix) {
|
||||
const url = new URL(`/pt${pathname}`, request.url);
|
||||
url.search = search;
|
||||
return NextResponse.redirect(url, 308);
|
||||
}
|
||||
|
||||
// 4. Delegação para o roteamento do next-intl
|
||||
return intlMiddleware(request);
|
||||
}
|
||||
|
||||
export const config = {
|
||||
matcher: [
|
||||
"/((?!api|_next|_vercel|.*\\..*|robots\\.txt|sitemap\\.xml|google21a790a2c23c0ec5\\.html).*)",
|
||||
],
|
||||
};
|
||||
+10
-1
@@ -1,8 +1,16 @@
|
||||
import createNextIntlPlugin from "next-intl/plugin";
|
||||
|
||||
const withNextIntl = createNextIntlPlugin("./i18n/request.js");
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
// A imagem Docker liga isto (NEXT_OUTPUT=standalone) para empacotar só o que
|
||||
// o servidor usa. Fora dela o build continua igual: `next start`/pm2.
|
||||
output: process.env.NEXT_OUTPUT === "standalone" ? "standalone" : undefined,
|
||||
// Metadata (title, canonical, hreflang, Open Graph) sempre no <head> do HTML
|
||||
// inicial, para qualquer cliente. Sem isso o Next 15.5 a transmite no <body>
|
||||
// para navegadores e Googlebot, e só os robôs de preview a recebem no <head>.
|
||||
htmlLimitedBots: /.*/,
|
||||
experimental: {
|
||||
optimizePackageImports: [
|
||||
"lucide-react",
|
||||
@@ -13,4 +21,5 @@ const nextConfig = {
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
export default withNextIntl(nextConfig);
|
||||
|
||||
Generated
+754
-3
@@ -11,6 +11,7 @@
|
||||
"googleapis": "^165.0.0",
|
||||
"lucide-react": "^1.16.0",
|
||||
"next": "^15.5.28",
|
||||
"next-intl": "^4.14.9",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
@@ -37,6 +38,31 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/@eloqnt/config": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@eloqnt/config/-/config-0.1.1.tgz",
|
||||
"integrity": "sha512-YRDigSaiJEzKDfzTth5kG+L/PKfB3mo8h7yNzpXExPfvQmcD05WoZT57PdhJE0jI+Vva6eb0OCU8hnHHgdME3g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@eloqnt/format-json": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@eloqnt/format-json/-/format-json-0.1.0.tgz",
|
||||
"integrity": "sha512-4Pkb+HyzgWNJXoU48aJhUyNZSjZvMGooPCNG1ZFmBm55xTiNNPQCNXH66Ob6sXS6RvbWZrRpCf+Uo/Jz9K9g+A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eloqnt/config": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@eloqnt/format-po": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@eloqnt/format-po/-/format-po-0.1.1.tgz",
|
||||
"integrity": "sha512-aLtmIoqXGEaeTT0RcsLN8sZ3aIrsT/c/dVs28zrLhDjO3+vA3KNP+r98N0xq8w/k36+/GIUt4uZNbqcA71GVWw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eloqnt/config": "^0.1.1",
|
||||
"po-parser": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@emnapi/core": {
|
||||
"version": "1.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
|
||||
@@ -214,6 +240,36 @@
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/fast-memoize": {
|
||||
"version": "3.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.7.tgz",
|
||||
"integrity": "sha512-zXfhLpvA6T7+efdt9JLbBwZ00tT7NsBMDVnDu8rpHeNNv8KfRZAMo2gkG0k9lK/Nzc//3kJ9pImsfuJxk3KhUA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/icu-messageformat-parser": {
|
||||
"version": "3.5.22",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.22.tgz",
|
||||
"integrity": "sha512-YuwN+dDKgssfuYwtOyGQD0CSn7K46g9cv1Fp0VgKpjZDDFvv8b8crzP990IcJhRPWHhKzCGsbUSJVIguyyFA5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-skeleton-parser": "2.1.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/icu-skeleton-parser": {
|
||||
"version": "2.1.12",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.12.tgz",
|
||||
"integrity": "sha512-ca7tZMLpfHX3sUD7hP6gE/qr6Iq89EDd3ZLeRhbsB7r0UD55DGJq+tmFLzrGrnx5StahUevQmQQVtbDRHsfDHA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/intl-localematcher": {
|
||||
"version": "0.8.14",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.14.tgz",
|
||||
"integrity": "sha512-8O7V38QmbB11+ryJ3KM/znrzXtiqgpXzqNoqDsndHZZ5/zDKTTL+cf5F0mzXkQEwhx8IlWnqYvEovf2S5EwLTw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "3.1.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@humanfs/core": {
|
||||
"version": "0.19.2",
|
||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
|
||||
@@ -1108,6 +1164,292 @@
|
||||
"node": ">=12.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz",
|
||||
"integrity": "sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.3",
|
||||
"is-glob": "^4.0.3",
|
||||
"node-addon-api": "^7.0.0",
|
||||
"picomatch": "^4.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@parcel/watcher-android-arm64": "2.6.0",
|
||||
"@parcel/watcher-darwin-arm64": "2.6.0",
|
||||
"@parcel/watcher-darwin-x64": "2.6.0",
|
||||
"@parcel/watcher-freebsd-x64": "2.6.0",
|
||||
"@parcel/watcher-linux-arm-glibc": "2.6.0",
|
||||
"@parcel/watcher-linux-arm-musl": "2.6.0",
|
||||
"@parcel/watcher-linux-arm64-glibc": "2.6.0",
|
||||
"@parcel/watcher-linux-arm64-musl": "2.6.0",
|
||||
"@parcel/watcher-linux-x64-glibc": "2.6.0",
|
||||
"@parcel/watcher-linux-x64-musl": "2.6.0",
|
||||
"@parcel/watcher-win32-arm64": "2.6.0",
|
||||
"@parcel/watcher-win32-x64": "2.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-android-arm64": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz",
|
||||
"integrity": "sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-arm64": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz",
|
||||
"integrity": "sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-darwin-x64": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz",
|
||||
"integrity": "sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-freebsd-x64": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz",
|
||||
"integrity": "sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-glibc": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz",
|
||||
"integrity": "sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm-musl": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz",
|
||||
"integrity": "sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-glibc": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz",
|
||||
"integrity": "sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-arm64-musl": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz",
|
||||
"integrity": "sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-glibc": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz",
|
||||
"integrity": "sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-linux-x64-musl": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz",
|
||||
"integrity": "sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-arm64": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz",
|
||||
"integrity": "sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher-win32-x64": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz",
|
||||
"integrity": "sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 10.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/@parcel/watcher/node_modules/picomatch": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz",
|
||||
"integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgjs/parseargs": {
|
||||
"version": "0.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
@@ -1161,6 +1503,210 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@schummar/icu-type-parser": {
|
||||
"version": "1.21.5",
|
||||
"resolved": "https://registry.npmjs.org/@schummar/icu-type-parser/-/icu-type-parser-1.21.5.tgz",
|
||||
"integrity": "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.16.21.tgz",
|
||||
"integrity": "sha512-VRreJpbRygpSD1hj3HBEOIA1xjXYnhB+IfcKsxZRhCIBGRP4UkqxZH4/ipFh/heIRp7EKQ56E8ygwEftLNCWXw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.16.21.tgz",
|
||||
"integrity": "sha512-KqCJ04pMYDBUYpAOFGUFR8TEjqo4h0Vtwe/za9xNRDKsxSDnjgM7HVhfO0uNNpMMlM2ao2E6d0iLpApIRvNGnA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.16.21.tgz",
|
||||
"integrity": "sha512-tLkw3uWxQj69qBRX5Xm8vbq+5iX5e/ktoPXhrDeFFa2jNMc+AWcxa0bqwatvVGK40v5mcmz6Ulu5Nk9jF8ciMA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.16.21.tgz",
|
||||
"integrity": "sha512-lFHVlHB0B5C7FwyprWJQp7b2iF/ohj2RqnMiv8uCnFJc+rYP0Py2I7ftZ+rOX4Zu7Ra9eMk7GnmuxAywCZYUJQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.16.21.tgz",
|
||||
"integrity": "sha512-gXDgrMMDsWT7r5gZsml10snBS9yaoVYwU9vGffa+DAts4ctEMrMHv+G8AH+ZxCV9gr5MfdgtGGQKjXjLay4mXQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-ppc64-gnu": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.16.21.tgz",
|
||||
"integrity": "sha512-hZF7J2YzXiADZ4eQxTFOWJcSSy3fbUR8/DcCXqiBHh0bVyLl2Y+O5pVWxk/r/XV5tA9n7DnnLlvkPPsHoajE9w==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-s390x-gnu": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.16.21.tgz",
|
||||
"integrity": "sha512-rmtGwkAlbl+fQMGrGUMklUmByueOmt1ju9sKsE5YWVA0KfFYM0W87WVx4lFYQXt+E4P3zkLjeqo/AUa5mFbF1A==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.16.21.tgz",
|
||||
"integrity": "sha512-EUJsyrFw3aNE64iQzk3bDqjADgl4l0vpxfwVMjMuZIooNg35yKqvkw3bYNEhQyrBDY0+5kKoiirGLpth3Wf3lA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.16.21.tgz",
|
||||
"integrity": "sha512-ZXUnLjxTHxvNhVmQmYlb8XNKArfi/MiGoW5DmfuME8ttCLH9OJTqJVFy7g1yYxUCgw3tU6dF1uU59N8P/Yr5Pw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.16.21.tgz",
|
||||
"integrity": "sha512-jnnQpAHiWZgEobVfOPvJJzm1Jh4ZEIKh2IqcDqHv6zJcjvaEkHdkt+qdRsJ9AqvK7g18WBRHTnvKm5IxdbkagA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.16.21.tgz",
|
||||
"integrity": "sha512-TaVTnNm9c1I+VG3hJUt11uspwbTrTQ9+fUPzODlvx4tj/ChYqUm4cKTIHw3O97hILxpmhBR0hbvLEs9seOV59A==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.16.21.tgz",
|
||||
"integrity": "sha512-aPv58Clf6SdAQtouzDYKbEtcCETY2hOXlrHgSFnFIJQOlMWINHSGazaM1Iv63/9wOUDPq6+0ZFytMqnPtER9OQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "Apache-2.0 AND MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/counter": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
|
||||
"integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@swc/helpers": {
|
||||
"version": "0.5.15",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
|
||||
@@ -1170,6 +1716,15 @@
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/types": {
|
||||
"version": "0.1.28",
|
||||
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.28.tgz",
|
||||
"integrity": "sha512-V6Mnml8v09QALx6K0elJ7o9K/MkVDtW3t6L+7Ou/JcWtb3xwId2AH4FeOceySd2JaO87IMw4+6vSZxLm34LPbw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@tailwindcss/node": {
|
||||
"version": "4.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz",
|
||||
@@ -2699,6 +3254,19 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/content-type": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-2.1.0.tgz",
|
||||
"integrity": "sha512-mj7UPXE0jaqaOsukNZRUEfEi2AcL7C/vwmwcHV0O97eO1E1pxBZuyjlZrx5seTaNBg1U6+o35wpa35Qfcc+7ag==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/cross-spawn": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||
@@ -2847,7 +3415,6 @@
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
|
||||
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@@ -4233,6 +4800,21 @@
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/icu-minify": {
|
||||
"version": "4.14.9",
|
||||
"resolved": "https://registry.npmjs.org/icu-minify/-/icu-minify-4.14.9.tgz",
|
||||
"integrity": "sha512-PmO+fNnC3K3mfPKTnm3RrPERrhQZnjm1AlpyZQ0ShbXi8Y/kYZ3YOde8TEjCLz9k3P2DmzkBn8lykGrCAi1Ajw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/amannn"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-messageformat-parser": "^3.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
|
||||
@@ -4285,6 +4867,31 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat": {
|
||||
"version": "11.2.15",
|
||||
"resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-11.2.15.tgz",
|
||||
"integrity": "sha512-W4VNytsXyWgW5lvVchmsb9xgA5rSKqoflu3/IQ9UCtB0z4R+Bx9MoEkwFT/+30RCl/KzUoH0QGGe9lppF5SuvQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "3.1.7",
|
||||
"@formatjs/icu-messageformat-parser": "3.5.18"
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat/node_modules/@formatjs/icu-messageformat-parser": {
|
||||
"version": "3.5.18",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-3.5.18.tgz",
|
||||
"integrity": "sha512-wX1efcL8d7K5QapOTRsP/OLTA/kpwe4LwqWyNxDNg5iRs8i9jJbCyxB5P8jc4KOW5oiLzz2DJr+BRY5xMV9+bA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/icu-skeleton-parser": "2.1.11"
|
||||
}
|
||||
},
|
||||
"node_modules/intl-messageformat/node_modules/@formatjs/icu-skeleton-parser": {
|
||||
"version": "2.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-2.1.11.tgz",
|
||||
"integrity": "sha512-j8cUmOJzVgkHuS0QiQ6ga76UIoLOFSAMWhs7aZJztH3aAdCOAE6vpC8KVvFB4cU10ON0y2/5oOVmPJ43s2lTwA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-array-buffer": {
|
||||
"version": "3.0.5",
|
||||
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
|
||||
@@ -4450,7 +5057,6 @@
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
@@ -4505,7 +5111,6 @@
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
@@ -5386,6 +5991,22 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.1.0.tgz",
|
||||
"integrity": "sha512-NMPBRMJgiQHjbd8phG3Vebdx4kZ1H121rbl5IkMqeOsahptB9BKo/d7oJ3zTXqTgagn2bWlNSXkh0QUGM31RYg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"content-type": "^2.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/next": {
|
||||
"version": "15.5.28",
|
||||
"resolved": "https://registry.npmjs.org/next/-/next-15.5.28.tgz",
|
||||
@@ -5438,6 +6059,97 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl": {
|
||||
"version": "4.14.9",
|
||||
"resolved": "https://registry.npmjs.org/next-intl/-/next-intl-4.14.9.tgz",
|
||||
"integrity": "sha512-uauRtUC+TrYNA1OL/QcwL9irndLrI9jK3Wdaa9W0B5AeKh9cqVdNeT0IWgLnhBqBRrVwppVdI0M+C1+JdGPQ3w==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/amannn"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eloqnt/config": "^0.1.1",
|
||||
"@eloqnt/format-json": "^0.1.0",
|
||||
"@eloqnt/format-po": "^0.1.1",
|
||||
"@formatjs/intl-localematcher": "^0.8.1",
|
||||
"@parcel/watcher": "^2.4.1",
|
||||
"@swc/core": "~1.16.0",
|
||||
"icu-minify": "^4.14.9",
|
||||
"negotiator": "^1.0.0",
|
||||
"next-intl-swc-plugin-extractor": "4.14.9",
|
||||
"use-intl": "^4.14.9"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl-swc-plugin-extractor": {
|
||||
"version": "4.14.9",
|
||||
"resolved": "https://registry.npmjs.org/next-intl-swc-plugin-extractor/-/next-intl-swc-plugin-extractor-4.14.9.tgz",
|
||||
"integrity": "sha512-8jAkmDwQJo6RDavBHm9QRl1YTn2WXf+rI4SVhMaZxZcxopnwZic6fKTXOoNIo3kzC+a6vJySkOkXmHTVFLAYtg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/next-intl/node_modules/@swc/core": {
|
||||
"version": "1.16.21",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.16.21.tgz",
|
||||
"integrity": "sha512-sE2asan0US6gcp11oBDFJb5+s+ltaAPBcagVQGub1+qo+8TsQET2TmXfJCw/Oy0w1eEPp1rV1wsR/Umx2KXGcw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@swc/counter": "^0.1.3",
|
||||
"@swc/types": "^0.1.28"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.16.21",
|
||||
"@swc/core-darwin-x64": "1.16.21",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.16.21",
|
||||
"@swc/core-linux-arm64-gnu": "1.16.21",
|
||||
"@swc/core-linux-arm64-musl": "1.16.21",
|
||||
"@swc/core-linux-ppc64-gnu": "1.16.21",
|
||||
"@swc/core-linux-s390x-gnu": "1.16.21",
|
||||
"@swc/core-linux-x64-gnu": "1.16.21",
|
||||
"@swc/core-linux-x64-musl": "1.16.21",
|
||||
"@swc/core-win32-arm64-msvc": "1.16.21",
|
||||
"@swc/core-win32-ia32-msvc": "1.16.21",
|
||||
"@swc/core-win32-x64-msvc": "1.16.21"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": ">=0.5.17"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/helpers": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/next-intl/node_modules/@swc/helpers": {
|
||||
"version": "0.5.23",
|
||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz",
|
||||
"integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==",
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/next-themes": {
|
||||
"version": "0.4.6",
|
||||
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.4.6.tgz",
|
||||
@@ -5448,6 +6160,12 @@
|
||||
"react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc"
|
||||
}
|
||||
},
|
||||
"node_modules/node-addon-api": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-domexception": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||
@@ -5786,6 +6504,12 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/po-parser": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/po-parser/-/po-parser-2.2.0.tgz",
|
||||
"integrity": "sha512-NdTrKgh0oO7+y+RFX8KKhOB438x/j94UGXEFzl/7pHH0JjWSn42iJ9tgmPksIO6n1JKDHmNDcejPJfKspljB9g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/possible-typed-array-names": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||
@@ -7009,6 +7733,33 @@
|
||||
"integrity": "sha512-XdVKMF4SJ0nP/O7XIPB0JwAEuT9lDIYnNsK8yGVe43y0AWoKeJNdv3ZNWh7ksJ6KqQFjOO6ox/VEitLnaVNufw==",
|
||||
"license": "BSD"
|
||||
},
|
||||
"node_modules/use-intl": {
|
||||
"version": "4.14.9",
|
||||
"resolved": "https://registry.npmjs.org/use-intl/-/use-intl-4.14.9.tgz",
|
||||
"integrity": "sha512-37ktvdCCz+6JY2VFPl/GV69Ds4ahiUT2c2xEZZRZYxdgGLxFsUbdxzjQVRm3YMIOUU0VPs6zvlifb4Yjk4IxIg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
"url": "https://github.com/sponsors/amannn"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "^3.1.0",
|
||||
"@schummar/icu-type-parser": "1.21.5",
|
||||
"icu-minify": "^4.14.9",
|
||||
"intl-messageformat": "^11.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/web-streams-polyfill": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
|
||||
|
||||
+3
-1
@@ -8,7 +8,8 @@
|
||||
"start": "next start",
|
||||
"lint": "eslint",
|
||||
"audit": "node scripts/auditar-paginas.mjs",
|
||||
"check": "npm run lint && npm run auditar-temas && npm run audit",
|
||||
"check:i18n": "node scripts/check-i18n.mjs",
|
||||
"check": "npm run lint && npm run auditar-temas && npm run audit && npm run check:i18n",
|
||||
"favicons": "node scripts/generate-favicons.mjs",
|
||||
"auditar-temas": "node scripts/auditar-temas.mjs",
|
||||
"slides-pdf": "node scripts/slides-pdf.mjs"
|
||||
@@ -17,6 +18,7 @@
|
||||
"googleapis": "^165.0.0",
|
||||
"lucide-react": "^1.16.0",
|
||||
"next": "^15.5.28",
|
||||
"next-intl": "^4.14.9",
|
||||
"next-themes": "^0.4.6",
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
|
||||
@@ -92,6 +92,7 @@ function obterRotasExistentes() {
|
||||
if (arq.endsWith("page.jsx") || arq.endsWith("page.js")) {
|
||||
let rota = arq
|
||||
.replace(/^app/, "")
|
||||
.replace(/\/\[locale\]/, "")
|
||||
.replace(/\/page\.(jsx|js)$/, "");
|
||||
if (rota === "") rota = "/";
|
||||
rotas.add(rota);
|
||||
@@ -132,7 +133,12 @@ function auditarPerformanceConfigs() {
|
||||
|
||||
// Checar globals.css e layout.jsx para transições no body
|
||||
const globalsCss = existsSync("app/globals.css") ? readFileSync("app/globals.css", "utf8") : "";
|
||||
const layoutJsx = existsSync("app/layout.jsx") ? readFileSync("app/layout.jsx", "utf8") : "";
|
||||
const layoutPath = existsSync("app/[locale]/layout.jsx")
|
||||
? "app/[locale]/layout.jsx"
|
||||
: existsSync("app/layout.jsx")
|
||||
? "app/layout.jsx"
|
||||
: null;
|
||||
const layoutJsx = layoutPath ? readFileSync(layoutPath, "utf8") : "";
|
||||
|
||||
if (globalsCss.includes("body {\n\t\t@apply bg-slate-50 text-slate-900 transition-colors")) {
|
||||
falha("globals.css tem transition-colors global no body (provoca animações não compostas no load).");
|
||||
@@ -299,7 +305,8 @@ function auditarRotasInternas() {
|
||||
if (caminho.startsWith("/api") || caminho.startsWith("/favicon") || caminho.startsWith("/icon") || caminho.startsWith("/logo") || caminho.startsWith("/site.webmanifest")) {
|
||||
continue;
|
||||
}
|
||||
const existe = rotasValidas.has(caminho) || rotasDinamicas.some((rx) => rx.test(caminho));
|
||||
const caminhoSemLocale = caminho.replace(/^\/(?:pt|en|es|fr|de|zh-CN)(?=\/|$)/, "") || "/";
|
||||
const existe = rotasValidas.has(caminho) || rotasValidas.has(caminhoSemLocale) || rotasDinamicas.some((rx) => rx.test(caminho) || rx.test(caminhoSemLocale));
|
||||
if (!existe) {
|
||||
falha(`${arq} -> Link interno aponta para rota inexistente: '${caminho}'`);
|
||||
rotasQuebradas++;
|
||||
|
||||
@@ -0,0 +1,327 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* ESPDocs - Script de Verificação Automatizada de Internacionalização (check:i18n)
|
||||
*
|
||||
* Implementa os critérios de aceite da seção 10 (itens 1 e 2) da spec docs/specs/i18n.md:
|
||||
* 1. Consistência estrutural de catálogos e dados (chaves idênticas ao pt).
|
||||
* 2. Ausência de valores vazios.
|
||||
* 3. Detecção de strings idênticas ao pt sem estarem na allowlist técnica.
|
||||
* 4. Verificação estrita de ausência de referências ao livro fora do pt (seção 7).
|
||||
*
|
||||
* Uso: npm run check:i18n
|
||||
*/
|
||||
|
||||
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
const CORES = {
|
||||
reset: "\x1b[0m",
|
||||
verde: "\x1b[32m",
|
||||
vermelho: "\x1b[31m",
|
||||
amarelo: "\x1b[33m",
|
||||
azul: "\x1b[34m",
|
||||
ciano: "\x1b[36m",
|
||||
negrito: "\x1b[1m",
|
||||
cinza: "\x1b[90m",
|
||||
};
|
||||
|
||||
const LOCALES = ["pt", "en", "es", "fr", "de", "zh-CN"];
|
||||
const FORBIDDEN_BOOK_TERMS = /\b(livro|libro|livre|buch|书|book|isbn|amazon|uiclap|capítulo|capitulo|chapter|chapitre|kapitel|章节)\b/i;
|
||||
|
||||
// Termos técnicos e nomes próprios permitidos permanecerem iguais ao pt
|
||||
const TECHNICAL_ALLOWLIST = new Set([
|
||||
"ESPDocs",
|
||||
"Lucas Rayan Guerra",
|
||||
"Ciência Embarcada",
|
||||
"ESP32",
|
||||
"ESP32-S2",
|
||||
"ESP32-S3",
|
||||
"ESP32-S31",
|
||||
"ESP32-C2",
|
||||
"ESP32-C3",
|
||||
"ESP32-C5",
|
||||
"ESP32-C6",
|
||||
"ESP32-C61",
|
||||
"ESP32-P4",
|
||||
"ESP32-H2",
|
||||
"ESP32-H4",
|
||||
"ESP-IDF",
|
||||
"Arduino",
|
||||
"MicroPython",
|
||||
"FreeRTOS",
|
||||
"Rust",
|
||||
"Matter",
|
||||
"ESP-RainMaker",
|
||||
"ESP-Matter",
|
||||
"Xtensa",
|
||||
"RISC-V",
|
||||
"Wi-Fi",
|
||||
"Bluetooth",
|
||||
"BLE",
|
||||
"Zigbee",
|
||||
"Thread",
|
||||
"USB",
|
||||
"GPIO",
|
||||
"SPI",
|
||||
"I2C",
|
||||
"I2S",
|
||||
"UART",
|
||||
"CAN",
|
||||
"TWAI",
|
||||
"ADC",
|
||||
"DAC",
|
||||
"PWM",
|
||||
"JTAG",
|
||||
"Gitea",
|
||||
"GitHub",
|
||||
"MIT",
|
||||
"DevKit",
|
||||
"SoC",
|
||||
"PSRAM",
|
||||
"SRAM",
|
||||
"Flash",
|
||||
"OTA",
|
||||
"DMA",
|
||||
"WDT",
|
||||
"TWDT",
|
||||
"IWDT",
|
||||
"LDO",
|
||||
"DCDC",
|
||||
"LVGL",
|
||||
"IDF",
|
||||
"12",
|
||||
"78",
|
||||
"100%",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
]);
|
||||
|
||||
let totalErros = 0;
|
||||
let totalAvisos = 0;
|
||||
|
||||
function sucesso(msg) {
|
||||
console.log(` ${CORES.verde}✔${CORES.reset} ${msg}`);
|
||||
}
|
||||
|
||||
function falha(msg) {
|
||||
console.log(` ${CORES.vermelho}✖${CORES.reset} ${msg}`);
|
||||
totalErros++;
|
||||
}
|
||||
|
||||
function aviso(msg) {
|
||||
console.log(` ${CORES.amarelo}⚠${CORES.reset} ${msg}`);
|
||||
totalAvisos++;
|
||||
}
|
||||
|
||||
/** Achata um objeto aninhado em chaves dot-notation */
|
||||
function achatarObjeto(obj, prefixo = "") {
|
||||
const resultado = {};
|
||||
for (const [k, v] of Object.entries(obj)) {
|
||||
const chave = prefixo ? `${prefixo}.${k}` : k;
|
||||
if (v !== null && typeof v === "object" && !Array.isArray(v)) {
|
||||
Object.assign(resultado, achatarObjeto(v, chave));
|
||||
} else {
|
||||
resultado[chave] = v;
|
||||
}
|
||||
}
|
||||
return resultado;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 1. Verificação da Base Canônica em Português (pt)
|
||||
// ---------------------------------------------------------------------------
|
||||
function verificarBasePt() {
|
||||
console.log(`\n${CORES.negrito}${CORES.ciano}[1/3] Verificação da Fonte Canônica (pt)${CORES.reset}`);
|
||||
|
||||
// messages/pt.json
|
||||
const messagesPtPath = "messages/pt.json";
|
||||
if (!existsSync(messagesPtPath)) {
|
||||
falha(`Arquivo de mensagens '${messagesPtPath}' não encontrado.`);
|
||||
return null;
|
||||
}
|
||||
|
||||
let ptMessages;
|
||||
try {
|
||||
ptMessages = JSON.parse(readFileSync(messagesPtPath, "utf8"));
|
||||
sucesso(`Catálogo '${messagesPtPath}' carregado com sucesso (${Object.keys(ptMessages).length} namespaces).`);
|
||||
} catch (e) {
|
||||
falha(`Erro ao processar JSON em '${messagesPtPath}': ${e.message}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
// data/pt/
|
||||
const dataFiles = ["series.json", "frameworks.json"];
|
||||
for (const f of dataFiles) {
|
||||
const p = join("data/pt", f);
|
||||
if (existsSync(p)) {
|
||||
try {
|
||||
JSON.parse(readFileSync(p, "utf8"));
|
||||
sucesso(`Arquivo de dados '${p}' validado com sucesso.`);
|
||||
} catch (e) {
|
||||
falha(`Erro em '${p}': ${e.message}`);
|
||||
}
|
||||
} else {
|
||||
falha(`Arquivo esperado '${p}' não encontrado.`);
|
||||
}
|
||||
}
|
||||
|
||||
// data/pt/conexoes
|
||||
const conexoesDir = "data/pt/conexoes";
|
||||
if (existsSync(conexoesDir)) {
|
||||
const arquivos = readdirSync(conexoesDir).filter((f) => f.endsWith(".json"));
|
||||
if (arquivos.length >= 11) {
|
||||
sucesso(`Diretório '${conexoesDir}' contém ${arquivos.length} arquivos de conexões validados.`);
|
||||
} else {
|
||||
aviso(`Diretório '${conexoesDir}' contém apenas ${arquivos.length} arquivos.`);
|
||||
}
|
||||
} else {
|
||||
falha(`Diretório '${conexoesDir}' não encontrado.`);
|
||||
}
|
||||
|
||||
// lib/data/pt/
|
||||
const libDataFiles = ["glossario.js", "diagnostico.js", "componentes.js", "topicos.js"];
|
||||
for (const f of libDataFiles) {
|
||||
const p = join("lib/data/pt", f);
|
||||
if (existsSync(p)) {
|
||||
sucesso(`Módulo de dados '${p}' verificado.`);
|
||||
} else {
|
||||
falha(`Módulo esperado '${p}' não encontrado.`);
|
||||
}
|
||||
}
|
||||
|
||||
return ptMessages;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 2. Verificação de Catálogos e Dados de Outros Idiomas (quando presentes)
|
||||
// ---------------------------------------------------------------------------
|
||||
function verificarOutrosIdiomas(ptMessages) {
|
||||
console.log(`\n${CORES.negrito}${CORES.ciano}[2/3] Verificação de Catálogos & Chaves por Idioma${CORES.reset}`);
|
||||
|
||||
if (!ptMessages) return;
|
||||
const chavesPt = achatarObjeto(ptMessages);
|
||||
const totalChavesPt = Object.keys(chavesPt).length;
|
||||
sucesso(`Catálogo 'pt' contém ${totalChavesPt} chaves de tradução ativas.`);
|
||||
|
||||
for (const loc of LOCALES) {
|
||||
if (loc === "pt") continue;
|
||||
|
||||
const pathMessages = `messages/${loc}.json`;
|
||||
if (!existsSync(pathMessages)) {
|
||||
aviso(`Catálogo '${loc}' (${pathMessages}) ainda não criado (esperado para sua fase de tradução).`);
|
||||
continue;
|
||||
}
|
||||
|
||||
let locMessages;
|
||||
try {
|
||||
locMessages = JSON.parse(readFileSync(pathMessages, "utf8"));
|
||||
} catch (e) {
|
||||
falha(`Erro de parsing em '${pathMessages}': ${e.message}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const chavesLoc = achatarObjeto(locMessages);
|
||||
let faltando = 0;
|
||||
let extras = 0;
|
||||
let vazios = 0;
|
||||
let iguaisSemAllowlist = 0;
|
||||
|
||||
for (const [k, vPt] of Object.entries(chavesPt)) {
|
||||
if (!(k in chavesLoc)) {
|
||||
faltando++;
|
||||
} else {
|
||||
const vLoc = chavesLoc[k];
|
||||
if (typeof vLoc === "string" && vLoc.trim() === "") {
|
||||
vazios++;
|
||||
} else if (vLoc === vPt && typeof vPt === "string") {
|
||||
const limpo = vPt.trim();
|
||||
if (!TECHNICAL_ALLOWLIST.has(limpo) && !/^\d+$/.test(limpo)) {
|
||||
iguaisSemAllowlist++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const k of Object.keys(chavesLoc)) {
|
||||
if (!(k in chavesPt)) extras++;
|
||||
}
|
||||
|
||||
if (faltando > 0) falha(`'${loc}': ${faltando} chave(s) ausente(s) em relação ao pt.`);
|
||||
if (extras > 0) aviso(`'${loc}': ${extras} chave(s) excedente(s) em relação ao pt.`);
|
||||
if (vazios > 0) falha(`'${loc}': ${vazios} valor(es) vazio(s).`);
|
||||
if (iguaisSemAllowlist > 0) {
|
||||
aviso(`'${loc}': ${iguaisSemAllowlist} valor(es) idêntico(s) ao pt sem allowlist.`);
|
||||
}
|
||||
|
||||
if (faltando === 0 && vazios === 0) {
|
||||
sucesso(`Catálogo '${loc}' possui paridade estrutural completa com 'pt'.`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 3. Verificação de Regras do Livro (§7 da spec: ausência fora do pt)
|
||||
// ---------------------------------------------------------------------------
|
||||
function verificarRegrasLivro() {
|
||||
console.log(`\n${CORES.negrito}${CORES.ciano}[3/3] Verificação Estrita de Referências ao Livro (Seção 7)${CORES.reset}`);
|
||||
|
||||
let violacoes = 0;
|
||||
|
||||
for (const loc of LOCALES) {
|
||||
if (loc === "pt") continue;
|
||||
|
||||
// Checar messages/<loc>.json
|
||||
const pathMsg = `messages/${loc}.json`;
|
||||
if (existsSync(pathMsg)) {
|
||||
const conteudo = readFileSync(pathMsg, "utf8");
|
||||
const m = conteudo.match(FORBIDDEN_BOOK_TERMS);
|
||||
if (m) {
|
||||
falha(`Termo proibido do livro '${m[0]}' encontrado em '${pathMsg}'.`);
|
||||
violacoes++;
|
||||
}
|
||||
}
|
||||
|
||||
// Checar data/<loc>/
|
||||
const dirData = `data/${loc}`;
|
||||
if (existsSync(dirData)) {
|
||||
const arquivos = readdirSync(dirData).filter((f) => f.endsWith(".json"));
|
||||
for (const arq of arquivos) {
|
||||
const conteudo = readFileSync(join(dirData, arq), "utf8");
|
||||
const m = conteudo.match(FORBIDDEN_BOOK_TERMS);
|
||||
if (m) {
|
||||
falha(`Termo proibido do livro '${m[0]}' encontrado em '${dirData}/${arq}'.`);
|
||||
violacoes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (violacoes === 0) {
|
||||
sucesso("Nenhuma menção ao livro encontrada em catálogos ou dados fora do português.");
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
console.log(`${CORES.negrito}${CORES.azul}======================================================${CORES.reset}`);
|
||||
console.log(`${CORES.negrito}${CORES.azul} ESPDocs · Verificação de Internacionalização (i18n) ${CORES.reset}`);
|
||||
console.log(`${CORES.negrito}${CORES.azul}======================================================${CORES.reset}`);
|
||||
|
||||
const ptMessages = verificarBasePt();
|
||||
verificarOutrosIdiomas(ptMessages);
|
||||
verificarRegrasLivro();
|
||||
|
||||
console.log(`\n${CORES.negrito}------------------------------------------------------${CORES.reset}`);
|
||||
if (totalErros === 0) {
|
||||
console.log(`${CORES.verde}${CORES.negrito}🎉 TODAS AS VERIFICAÇÕES DE I18N PASSARAM! (0 erros)${CORES.reset}\n`);
|
||||
return 0;
|
||||
} else {
|
||||
console.log(`${CORES.vermelho}${CORES.negrito}✖ Foram encontrados ${totalErros} erro(s) de i18n que bloqueiam o aceite.${CORES.reset}\n`);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
process.exitCode = main();
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
# Uso: scripts/plano-imagem.sh <registro> <repositório>
|
||||
# Imprime inputs=, image= e reuse= (para $GITHUB_OUTPUT). O hash cobre só os
|
||||
# arquivos que entram no build da imagem, não a documentação nem a configuração
|
||||
# de ferramentas. reuse=true quando o registro já tem inputs-<hash>.
|
||||
set -euo pipefail
|
||||
registry=$1; ns=${2,,}
|
||||
|
||||
inputs=$(git ls-tree -r HEAD \
|
||||
| awk -F'\t' '$2 !~ /^(\.gitea|\.github|\.claude|\.superset|docs)\// && $2 !~ /^(README.*|CLAUDE\.md|DESIGN\.md|LICENSE|\.gitignore|CHANGELOG\.md|scripts\/release-notes\.sh)$/' \
|
||||
| sha256sum | cut -c1-16)
|
||||
token=$(curl -fsS "https://$registry/v2/token?service=container_registry&scope=repository:$ns:pull" | jq -r .token)
|
||||
code=$(curl -s -o /dev/null -w '%{http_code}' -I \
|
||||
-H "Authorization: Bearer $token" \
|
||||
-H 'Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.manifest.v1+json' \
|
||||
"https://$registry/v2/$ns/manifests/inputs-$inputs")
|
||||
echo "inputs-$inputs -> HTTP $code" >&2
|
||||
reuse=false; [ "$code" = 200 ] && reuse=true
|
||||
echo "inputs=$inputs"
|
||||
echo "image=$registry/$ns"
|
||||
echo "reuse=$reuse"
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/env bash
|
||||
# Teste de fumaça do servidor: rotas por idioma, redirects e regras do livro.
|
||||
#
|
||||
# scripts/smoke-imagem.sh http://127.0.0.1:3999
|
||||
#
|
||||
# Cada falha é impressa e o script sai com 1 no fim, para mostrar tudo de uma vez.
|
||||
set -uo pipefail
|
||||
|
||||
base=${1:?uso: smoke-imagem.sh <url-base>}
|
||||
falhas=0
|
||||
|
||||
# status <esperado> <caminho> [cabeçalho]
|
||||
status() {
|
||||
local got
|
||||
got=$(curl -s -o /dev/null -w '%{http_code}' ${3:+-H "$3"} "$base$2")
|
||||
[ "$got" = "$1" ] || { echo "FALHOU $2 ${3:-}: esperado $1, veio $got"; falhas=$((falhas + 1)); }
|
||||
}
|
||||
|
||||
# destino <status> <caminho> <redirecionamento esperado> [cabeçalho]
|
||||
destino() {
|
||||
local out
|
||||
out=$(curl -s -o /dev/null -w '%{http_code} %{redirect_url}' ${4:+-H "$4"} "$base$2")
|
||||
[ "$out" = "$1 $base$3" ] || { echo "FALHOU $2 ${4:-}: esperado '$1 $3', veio '${out#* }'" ; falhas=$((falhas + 1)); }
|
||||
}
|
||||
|
||||
# O servidor leva alguns segundos para subir.
|
||||
for _ in $(seq 1 30); do curl -fsS -o /dev/null "$base/pt" && break; sleep 2; done
|
||||
|
||||
# Páginas que existem em todos os idiomas ativos (a home é a que mais depende do render no servidor).
|
||||
for l in pt en es fr de zh-CN; do status 200 "/$l"; done
|
||||
for p in /series /sobre /livro; do status 200 "/pt$p"; done
|
||||
|
||||
# Negociação de idioma na raiz.
|
||||
destino 307 / /pt 'Accept-Language: pt-BR,pt;q=0.9'
|
||||
destino 307 / /es 'Accept-Language: es-MX,es;q=0.9,en;q=0.5'
|
||||
destino 307 / /fr 'Accept-Language: fr-CA,fr;q=0.9'
|
||||
destino 307 / /de 'Accept-Language: de-AT,de;q=0.8'
|
||||
destino 307 / /zh-CN 'Accept-Language: zh-CN,zh;q=0.9'
|
||||
destino 307 / /en 'Accept-Language: it-IT'
|
||||
destino 307 / /pt 'Accept-Language: en;q=0.5,pt;q=0.9'
|
||||
destino 307 / /es 'Cookie: NEXT_LOCALE=es'
|
||||
|
||||
# URLs antigas (sem prefixo) eram em português.
|
||||
destino 308 /series/ESP32-S3 /pt/series/ESP32-S3 'Accept-Language: en-US'
|
||||
destino 308 /livro /pt/livro 'Accept-Language: en-US'
|
||||
|
||||
# O livro existe só em português.
|
||||
for l in en es fr de zh-CN; do status 404 "/$l/livro"; done
|
||||
|
||||
# Metadata no <head> inicial (title, canonical, hreflang), para qualquer cliente.
|
||||
html=$(curl -s -A 'Mozilla/5.0 Chrome/130' "$base/pt/sobre")
|
||||
head=${html%%</head>*}
|
||||
for marca in '<title>' 'rel="canonical"'; do
|
||||
case "$head" in *"$marca"*) ;; *) echo "FALHOU /pt/sobre: $marca fora do <head>"; falhas=$((falhas + 1));; esac
|
||||
done
|
||||
|
||||
exit $((falhas > 0))
|
||||
Reference in new issue
Block a user