Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions FIRMWARE_GPIO_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
Use este arquivo para documentar os GPIOs do microcontrolador em projetos de firmware.

## Microcontrolador
- Modelo: `<preencher>`
- Família: `<preencher>`
- Modelo: `ESP32-C3 (Seeed XIAO ESP32C3)`
- Família: `Espressif ESP32`

## Tabela de GPIOs

| GPIO | Direção | Função | Módulo/Periférico | Observações |
|---|---|---|---|---|
| `<ex: PA0>` | `<Entrada/Saída>` | `<ex: Botão usuário>` | `<ex: GPIO/EXTI>` | `<pull-up, nível ativo, etc.>` |
| `D4` | Bidirecional | SDA do barramento de sensores | `I2C/Wire` | Barramento compartilhado entre VL53L0X e QMC6500 |
| `D5` | Saída | SCL do barramento de sensores | `I2C/Wire` | Clock do barramento I2C |
| `D3` | Entrada | Interrupção de vibração do QMC6500 | `GPIO/EXTI` | Configurado com `INPUT_PULLUP`, borda de descida (`FALLING`) |

## Regras

Expand Down
15 changes: 13 additions & 2 deletions architecture/DIAGRAM.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ flowchart LR

subgraph Driver[Camada de Driver]
IR[driver/ir.cpp\nsetup_ir + read_ir]
IMU[driver/imu.cpp\nsetup_imu + imu_has_vibration_event]
end

subgraph HAL[Camada HAL]
Expand All @@ -43,27 +44,37 @@ flowchart LR
subgraph Host[Execução Host]
HMAIN[src/host/main.cpp]
MIR[host/mocks/mock_ir.cpp]
MIMU[host/mocks/mock_imu.cpp]
MLOG[host/mocks/mock_log.cpp]
TESTS[tests/host/unit/*]
end

subgraph Target[Execução Hardware]
TMAIN[src/main.cpp]
SENSOR[VL53L0X]
IRSENSOR[VL53L0X]
IMUSENSOR[QMC6500]
UART[Serial]
I2C[Wire]
EXTI[GPIO Interrupt]
end

APP --> FILTER
APP --> IR
APP --> IMU
APP --> LOG

IR --> SENSOR
IR --> IRSENSOR
IMU --> IMUSENSOR
IR --> I2C
IMU --> I2C
IMU --> EXTI
LOG --> UART

HMAIN --> APP
TESTS --> APP
TESTS --> FILTER
TESTS -. substitui .-> MIR
TESTS -. substitui .-> MIMU
TESTS -. substitui .-> MLOG

TMAIN --> APP
Expand Down
7 changes: 5 additions & 2 deletions architecture/TECHNICAL_BASELINE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ mudanças sem conflitar com o fluxo de governança.

- `src/app/`
- Orquestra o ciclo da aplicação (`setup_app`, `loop_app`).
- Aplica regras de negócio (`half_value`).
- Aplica regras de negócio (`half_value`) e reage a evento de vibração.
- `src/driver/`
- Integração com sensor IR (VL53L0X).
- Integração com IMU QMC6500 e interrupção por vibração.
- `src/hal/`
- Inicialização e saída de logs.
- `src/host/`
Expand All @@ -25,6 +26,7 @@ mudanças sem conflitar com o fluxo de governança.

- Entrada principal: `src/main.cpp`.
- Usa `driver/ir.cpp` real com dependência de biblioteca de sensor.
- Usa `driver/imu.cpp` real com `Wire` e GPIO de interrupção.
- Usa `hal/log.cpp` para observabilidade em runtime.

### Host (native)
Expand All @@ -37,7 +39,8 @@ mudanças sem conflitar com o fluxo de governança.

Para preservar testabilidade e baixo acoplamento:

- `driver/ir.h` define contrato de leitura e setup do sensor.
- `driver/ir.h` define contrato de leitura e setup do sensor IR.
- `driver/imu.h` define contrato de setup e consulta de evento de vibração.
- `hal/log.h` define contrato de logging.
- `app/` depende dos contratos e não de detalhes concretos de hardware.

Expand Down
12 changes: 11 additions & 1 deletion src/app/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ void setup_app() {
if (!setup_ir()) {
log_info("IR Setup failed");
while(1);
};
}

if (!setup_imu()) {
log_info("QMC6500 setup failed");
while(1);
}
}


void loop_app() {
if (imu_has_vibration_event()) {
log_info("Vibration event interrupt detected");
return;
}

uint16_t measure = read_ir();
int half_measure = half_value(measure);
log_info("Measure: %d | %d", measure, half_measure);
Expand Down
1 change: 1 addition & 0 deletions src/app/app.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "filter/filter.h"
#include "driver/ir.h"
#include "driver/imu.h"

void setup_app();
void loop_app();
74 changes: 74 additions & 0 deletions src/driver/imu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#include "imu.h"

#include <Arduino.h>
#include <Wire.h>

namespace {
constexpr uint8_t QMC6500_I2C_ADDR = 0x0D;
constexpr uint8_t REG_CTRL1 = 0x09;
constexpr uint8_t REG_CTRL2 = 0x0A;
constexpr uint8_t REG_INT_STATUS = 0x0D;
constexpr uint8_t REG_THRESHOLD = 0x0E;
constexpr uint8_t REG_RESET = 0x0B;
constexpr uint8_t CTRL1_CONTINUOUS_200HZ_2G = 0x1D;
constexpr uint8_t CTRL2_INT_ENABLE = 0x01;
constexpr uint8_t INT_STATUS_VIBRATION = 0x01;
constexpr uint8_t DEFAULT_VIBRATION_THRESHOLD = 0x12;
constexpr uint8_t QMC6500_INT_PIN = D3;

volatile bool g_vibration_irq = false;

void write_register(uint8_t reg, uint8_t value) {
Wire.beginTransmission(QMC6500_I2C_ADDR);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}

uint8_t read_register(uint8_t reg) {
Wire.beginTransmission(QMC6500_I2C_ADDR);
Wire.write(reg);
if (Wire.endTransmission(false) != 0) {
return 0;
}

if (Wire.requestFrom(QMC6500_I2C_ADDR, static_cast<uint8_t>(1)) != 1) {
return 0;
}

return Wire.read();
}

void IRAM_ATTR on_vibration_interrupt() {
g_vibration_irq = true;
}
} // namespace

bool setup_imu() {
Wire.begin();

write_register(REG_RESET, 0x01);
delay(2);

write_register(REG_THRESHOLD, DEFAULT_VIBRATION_THRESHOLD);
write_register(REG_CTRL1, CTRL1_CONTINUOUS_200HZ_2G);
write_register(REG_CTRL2, CTRL2_INT_ENABLE);

pinMode(QMC6500_INT_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(QMC6500_INT_PIN), on_vibration_interrupt, FALLING);

return true;
}

bool imu_has_vibration_event() {
if (!g_vibration_irq) {
return false;
}

noInterrupts();
g_vibration_irq = false;
interrupts();

const uint8_t status = read_register(REG_INT_STATUS);
return (status & INT_STATUS_VIBRATION) != 0;
}
4 changes: 4 additions & 0 deletions src/driver/imu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

bool setup_imu();
bool imu_has_vibration_event();
22 changes: 22 additions & 0 deletions src/host/mocks/mock_imu.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "driver/imu.h"

static bool mock_setup_imu_output = true;
static bool mock_imu_event = false;

void set_mock_setup_imu_output(bool output) {
mock_setup_imu_output = output;
}

void set_mock_imu_event(bool event_raised) {
mock_imu_event = event_raised;
}

bool setup_imu() {
return mock_setup_imu_output;
}

bool imu_has_vibration_event() {
bool has_event = mock_imu_event;
mock_imu_event = false;
return has_event;
}
4 changes: 4 additions & 0 deletions src/host/mocks/mock_imu.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#pragma once

void set_mock_setup_imu_output(bool output);
void set_mock_imu_event(bool event_raised);
23 changes: 16 additions & 7 deletions tests/host/unit/test_loop_app/test_loop_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,33 @@
#include "app/app.h"
#include "host/mocks/mock_log.h"
#include "host/mocks/mock_ir.h"

#include "host/mocks/mock_imu.h"

void setUp(void) {}

void tearDown(void) {}

void test_loop_app(void) {
uint16_t read_value = 10;
const char* expected = "Measure: 10 | 5";
set_mock_read_ir_output(read_value);
void test_loop_app_logs_measure_when_no_vibration_event(void) {
set_mock_read_ir_output(10);
set_mock_imu_event(false);

loop_app();

TEST_ASSERT_EQUAL_STRING("Measure: 10 | 5", get_last_log());
}

void test_loop_app_logs_vibration_interrupt_when_event_is_raised(void) {
set_mock_read_ir_output(10);
set_mock_imu_event(true);

loop_app();

TEST_ASSERT_EQUAL_STRING(expected, get_last_log());
TEST_ASSERT_EQUAL_STRING("Vibration event interrupt detected", get_last_log());
}

int main(void) {
UNITY_BEGIN();
RUN_TEST(test_loop_app);
RUN_TEST(test_loop_app_logs_measure_when_no_vibration_event);
RUN_TEST(test_loop_app_logs_vibration_interrupt_when_event_is_raised);
return UNITY_END();
}