Skip to content

Instantly share code, notes, and snippets.

@arcostasi
Last active March 29, 2022 22:23
Show Gist options
  • Save arcostasi/135623c04efe86cda1db84fe36f4b08b to your computer and use it in GitHub Desktop.
Save arcostasi/135623c04efe86cda1db84fe36f4b08b to your computer and use it in GitHub Desktop.
Wokwi Custom Chips C API

Este documento descreve a C API em andamento para escrever chips personalizados para o simulador Wokwi.

Usando a API

Primeiro, certifique-se de incluir wokwi-api.h. Cada método externo que você declara deve ser encapsulado com a macro EXPORT (por exemplo, void EXPORT(my_method_name) (uint32_t arg) { ... }). O chip deve declarar um método chip_init. Este método será chamado para cada nova instância do chip. Se o chip possui algum estado interno, o chip_init deve alocar memória para o estado interno e retornar um ponteiro para esta memória. Este ponteiro será passado no primeiro argumento para qualquer ouvinte que você declarar (por exemplo, chip_pin_change). Para chip sem nenhum estado interno, basta retornar NULL.

Aqui está um exemplo de um arquivo de chip mínimo:

#include "wokwi-api.h"

void* EXPORT(chip_init)(void) {
  /* Este método é executado quando a simulação é iniciada. É chamado uma vez para cada instância do chip. */
  /* Deve retornar um ponteiro para uma estrutura com dados específicos da instância do chip, ou NULL se o chip não tiver estado interno. */
  return NULL;
}

API de pinos GPIO

Chips interage com a simulação usando pinos digitais. Use a macro DECLARE_PIN para definir seus pinos, por exemplo:

DECLARE_PIN(VCC);
DECLARE_PIN(GND);
DECLARE_PIN(SCL);
DECLARE_PIN(SDA);
DECLARE_PIN(INT);

Em seguida, use os pinos no código chamando a macro PIN. Por exemplo, o código a seguir irá configurar o pino INT como um pino de saída digital:

pin_mode(PIN(INT), OUTPUT);

Os seguintes métodos da API interagem com os pinos GPIO:

void pin_mode(uint32_t pin, int mode)

Configura o pin dado como entrada ou saída digital. Os valores válidos para mode são: INPUT, OUTPUT, INPUT_PULLUP e INPUT_PULLDOWN.

void digital_write(uint32_t pin, int value)

Defina o valor de saída para um pino digital. Use as constantes LOW e HIGH para value.

uint32_t digital_read(uint32_t pin)

Lê o valor digital atual do pino, retorna LOW ou HIGH.

void digital_watch(uint32_t pin, uint32_t edge)

Escuta as alterações no valor digital do pino fornecido. Os valores válidos para edge são:

  • BOTH - Ouça qualquer alteração de valor
  • FALLING - Ouça as mudanças de ALTO para BAIXO
  • RISING - Ouça as mudanças de BAIXO a alto
  • NONE - Pare de ouvir as alterações

Você também precisa declarar um listener com a seguinte assinatura:

void EXPORT(chip_pin_change)(void *chip, uint32_t pin, uint32_t value) {
  // ...
}

Este listener será chamado para alterações em qualquer pino que você assistiu com digital_watch(). O argumento chip é um ponteiro para o estado do chip, conforme retornado de chip_init(). O parâmetro pin é o índice do pino, e value é o novo valor digital do pino, LOW ou HIGH.

Tempo de simulação

uint64_t get_sim_nanos(void)

Retorna o tempo atual do simulador (virtual) em nanossegundos.

I2C Device

Para criar um dispositivo I2C, você precisa declarar quatro retornos de chamada: chip_i2c_connect, chip_i2c_read, chip_i2c_write e chip_i2c_disconnect. Os dois primeiros argumentos para todos esses retornos de chamada são um ponteiro para o estado do chip e o índice da interface i2c.

i2c_init(uint32_t address, uint32_t pin_scl, uint32_t pin_sda)

Inicializa um dispositivo I2C. O dispositivo se conectará ao barramento I2C nos pinos pin_scl e pin_sda, e ouvirá as solicitações correspondentes ao endereço fornecido.

bool EXPORT(chip_i2c_connect)(chip_state_t *chip, uint32_t i2c_index, uint32_t address)

Chamado sempre que seu chip é endereçado no barramento I2C. O parâmetro address contém o endereço do seu dispositivo. Retorne true para reconhecer a conexão ou false para descartá-la.

uint8_t EXPORT(chip_i2c_read)(chip_state_t *chip, uint32_t i2c_index)

Chamado quando o microcontrolador quer ler um byte de dados do seu chip.

bool EXPORT(chip_i2c_write)(chip_state_t *chip, uint32_t i2c_index, uint8_t data)

Chamado quando o microcontrolador grava um byte em seu chip. data conterá o byte de entrada. Retorne true para confirmar a transação ou false para encerrar a conexão.

void EXPORT(chip_i2c_disconnect)(chip_state_t *chip, uint32_t i2c_index)

Chamado quando o microcontrolador se desconecta do seu chip.

Credits

Uri Shaked - wokwi-custom-chips-c-api.md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment