Skip to content

2026-02

2026-02-25 🌐 🎬 💾 📚 📑 🔬

Method for Converting a PWM Output to an Analog Output When Using Hall Effect Sensor ICs

🌐PWM to Analog


Pico CDC Host use TinyUSB

#include "Adafruit_TinyUSB.h"
#define USE_TINYUSB_HOST 1

// Language ID: English
#define LANGUAGE_ID 0x0409

typedef struct {
  tusb_desc_device_t desc_device;
  uint16_t manufacturer[32];
  uint16_t product[48];
  uint16_t serial[16];
  bool mounted;
} dev_info_t;

// CFG_TUH_DEVICE_MAX is defined by tusb_config header
dev_info_t dev_info[CFG_TUH_DEVICE_MAX] = { 0 };

Adafruit_USBH_Host USBHost;
// CDC Host object
Adafruit_USBH_CDC SerialHost;

// forward Seral <-> SerialHost
void forward_serial(void) {
  char d;
  uint8_t buf[64];

  // Serial -> SerialHost
  if (Serial1.available()) {
    d = Serial1.read();
    if (SerialHost && SerialHost.connected()) {
      SerialHost.write(d);
      SerialHost.flush();
    }
  }

  // SerialHost -> Serial
  if (SerialHost.connected() && SerialHost.available()) {
    size_t count = SerialHost.read(buf, sizeof(buf));
    Serial1.write(buf, count);
    Serial1.flush();
  }
}

//--------------------------------------------------------------------+
// setup() & loop()
//--------------------------------------------------------------------+
void setup() {
  Serial1.begin(115200);
  Serial1.println("TinyUSB Host: Device Info Example");

  // Init USB Host on native controller roothub port0
  USBHost.begin(0);
  SerialHost.begin(115200);
}

void loop() {
  USBHost.task();
  Serial1.flush();
  forward_serial();
}

//--------------------------------------------------------------------+
// TinyUSB Host callbacks
//--------------------------------------------------------------------+
void print_device_descriptor(tuh_xfer_t *xfer);

void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len);

void print_lsusb(void) {
  bool no_device = true;
  for (uint8_t daddr = 1; daddr < CFG_TUH_DEVICE_MAX + 1; daddr++) {
    // TODO can use tuh_mounted(daddr), but tinyusb has an bug
    // use local connected flag instead
    dev_info_t *dev = &dev_info[daddr - 1];
    if (dev->mounted) {
      Serial1.printf("Device %u: ID %04x:%04x %s %s\r\n", daddr,
                    dev->desc_device.idVendor, dev->desc_device.idProduct,
                    (char *) dev->manufacturer, (char *) dev->product);

      no_device = false;
    }
  }

  if (no_device) {
    Serial1.println("No device connected (except hub)");
  }
}

// Invoked when device is mounted (configured)
void tuh_mount_cb(uint8_t daddr) {
  Serial1.printf("Device attached, address = %d\r\n", daddr);

  dev_info_t *dev = &dev_info[daddr - 1];
  dev->mounted = true;

  // Get Device Descriptor
  tuh_descriptor_get_device(daddr, &dev->desc_device, 18, print_device_descriptor, 0);
}

/// Invoked when device is unmounted (bus reset/unplugged)
void tuh_umount_cb(uint8_t daddr) {
  Serial1.printf("Device removed, address = %d\r\n", daddr);
  dev_info_t *dev = &dev_info[daddr - 1];
  dev->mounted = false;

  // print device summary
  print_lsusb();
}

void print_device_descriptor(tuh_xfer_t *xfer) {
  if (XFER_RESULT_SUCCESS != xfer->result) {
    Serial1.printf("Failed to get device descriptor\r\n");
    return;
  }

  uint8_t const daddr = xfer->daddr;
  dev_info_t *dev = &dev_info[daddr - 1];
  tusb_desc_device_t *desc = &dev->desc_device;

  Serial1.printf("Device %u: ID %04x:%04x\r\n", daddr, desc->idVendor, desc->idProduct);
  Serial1.printf("Device Descriptor:\r\n");
  Serial1.printf("  bLength             %u\r\n"     , desc->bLength);
  Serial1.printf("  bDescriptorType     %u\r\n"     , desc->bDescriptorType);
  Serial1.printf("  bcdUSB              %04x\r\n"   , desc->bcdUSB);
  Serial1.printf("  bDeviceClass        %u\r\n"     , desc->bDeviceClass);
  Serial1.printf("  bDeviceSubClass     %u\r\n"     , desc->bDeviceSubClass);
  Serial1.printf("  bDeviceProtocol     %u\r\n"     , desc->bDeviceProtocol);
  Serial1.printf("  bMaxPacketSize0     %u\r\n"     , desc->bMaxPacketSize0);
  Serial1.printf("  idVendor            0x%04x\r\n" , desc->idVendor);
  Serial1.printf("  idProduct           0x%04x\r\n" , desc->idProduct);
  Serial1.printf("  bcdDevice           %04x\r\n"   , desc->bcdDevice);

  // Get String descriptor using Sync API
  Serial1.printf("  iManufacturer       %u     ", desc->iManufacturer);
  if (XFER_RESULT_SUCCESS ==
      tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, dev->manufacturer, sizeof(dev->manufacturer))) {
    utf16_to_utf8(dev->manufacturer, sizeof(dev->manufacturer));
    Serial1.printf((char *) dev->manufacturer);
  }
  Serial1.printf("\r\n");

  Serial1.printf("  iProduct            %u     ", desc->iProduct);
  if (XFER_RESULT_SUCCESS ==
      tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, dev->product, sizeof(dev->product))) {
    utf16_to_utf8(dev->product, sizeof(dev->product));
    Serial1.printf((char *) dev->product);
  }
  Serial1.printf("\r\n");

  Serial1.printf("  iSerialNumber       %u     ", desc->iSerialNumber);
  if (XFER_RESULT_SUCCESS ==
      tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, dev->serial, sizeof(dev->serial))) {
    utf16_to_utf8(dev->serial, sizeof(dev->serial));
    Serial1.printf((char *) dev->serial);
  }
  Serial1.printf("\r\n");

  Serial1.printf("  bNumConfigurations  %u\r\n", desc->bNumConfigurations);

  // print device summary
  print_lsusb();
}

//--------------------------------------------------------------------+
// String Descriptor Helper
//--------------------------------------------------------------------+

static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
  // TODO: Check for runover.
  (void) utf8_len;
  // Get the UTF-16 length out of the data itself.

  for (size_t i = 0; i < utf16_len; i++) {
    uint16_t chr = utf16[i];
    if (chr < 0x80) {
      *utf8++ = chr & 0xff;
    } else if (chr < 0x800) {
      *utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
      *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
    } else {
      // TODO: Verify surrogate.
      *utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
      *utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
      *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
    }
    // TODO: Handle UTF-16 code points that take two entries.
  }
}

// Count how many bytes a utf-16-le encoded string will take in utf-8.
static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
  size_t total_bytes = 0;
  for (size_t i = 0; i < len; i++) {
    uint16_t chr = buf[i];
    if (chr < 0x80) {
      total_bytes += 1;
    } else if (chr < 0x800) {
      total_bytes += 2;
    } else {
      total_bytes += 3;
    }
    // TODO: Handle UTF-16 code points that take two entries.
  }
  return total_bytes;
}

void utf16_to_utf8(uint16_t *temp_buf, size_t buf_len) {
  size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
  size_t utf8_len = _count_utf8_bytes(temp_buf + 1, utf16_len);

  _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, buf_len);
  ((uint8_t *) temp_buf)[utf8_len] = '\0';
}

Computer's primitive operation is Boolean logic. (And, Or, Not)

What's Nuron's primitive operaion ?

Self Modification is the key to Concious


PICO as USB Host

🎬PICO as USB Host

💾PICO as USB Host

STM32F405 also can function as USB Host


2026-02-26 🌐 🎬 💾 📚 📑 🔬

Protothreads for Arduino

💾Protothreads for Arduino


YoWASP (Yosys nextpnr use WebAssembly)

🌐YoWASP

Unofficial WebAssembly-based packages for Yosys, nextpnr, and more

🌐YoWASP Toolchain for VSCode

Run Python, Yosys, nextpnr, openFPGALoader, ... in VS Code without installation.

This extension runs the open source FPGA toolchain anywhere you can run VS Code. Windows, Linux, macOS, Chromebooks, corporate networks, even vscode.dev! Add it to VS Code, wait a few minutes, and get a bitstream; simple as that.


WebUSB_API

🌐WebUSB_API

The WebUSB API provides a way to expose non-standard Universal Serial Bus (USB) compatible devices services to the web, to make USB safer and easier to use.


WebAssembly Compiler use LLVM

🌐Emscripten

Emscripten is a complete compiler toolchain to WebAssembly, using LLVM, with a special focus on speed, size, and the Web platform.


Firing squad synchronization problem

Firing squad synchronization problem

The firing squad synchronization problem is a problem in computer science and cellular automata in which the goal is to design a cellular automaton that, starting with a single active cell, eventually reaches a state in which all cells are simultaneously active. It was first proposed by John Myhill in 1957 and published (with a solution by John McCarthy and Marvin Minsky) in 1962 by Edward F. Moore.


2026-02-24 🌐 🎬 💾 📚 📑 🔬

ZTurn Board CDROM file

Zturn Board CDROM


Linux Utilities

  • Krusader

  • Tree

Linux 核心設計 (Linux Kernel Internals) by 黃敬群

Linux 核心設計 (Linux Kernel Internals)

你所不知道的 C 語言


Lattice Semiconductor FPGA System Design CrossLink-NX


Mental Models for Critical Thining

2026-012


The Idea Factory

2026-011

沒有 Bell Lab 我大概在台東種田


2026-02-23 🌐 🎬 💾 📚 📑 🔬🦠

How to Access ALVIUM 1800 U-050m Python480 USB 3 Camera

  • Download Vimba X SDK

    Vimba X SDK

  • Install TransporterLayer

    Extract the sdk and in cti folder run Install_GenTL_Path.sh use sudo

    Reboot

  • Install Python Library vmbpy

    pip install vmbpy

vmbpy sample code

Scan Camera

import vmbpy

def main():
    with vmbpy.VmbSystem.get_instance() as vmb:
        cams = vmb.get_all_cameras()
        print('Cameras found: {}'.format(len(cams)))
        for cam in cams:
            print('Camera Name : {}'.format(cam.get_name()))
            print('Model Name  : {}'.format(cam.get_model()))
            print('Camera ID   : {}'.format(cam.get_id()))

if __name__ == '__main__':
    main()

Continus Capture

import vmbpy
import cv2
import queue

frame_queue = queue.SimpleQueue()

def frame_handler(cam: vmbpy.Camera, stream: vmbpy.Stream, frame: vmbpy.Frame):
    if frame.get_status() == vmbpy.FrameStatus.Complete:
        frame_queue.put(frame.as_numpy_ndarray())
    cam.queue_frame(frame) # Re-queue for next frame

def main():
    CAMERA_ID = 'YOUR_CAMERA_ID'
    with vmbpy.VmbSystem.get_instance() as vmb:
        with vmb.get_camera_by_id(CAMERA_ID) as cam:
            cam.get_feature_by_name('AcquisitionMode').set('Continuous')
            cam.start_streaming(handler=frame_handler)
            while True:
                frame = frame_queue.get()
                cv2.imshow('Alvium Live Stream', frame)
                if cv2.waitKey(1) & 0xFF == ord('q'):
                    break
            cam.stop_streaming()
            cv2.destroyAllWindows()

if __name__ == '__main__':
    main()

PicoCalc Update

🎬PicoCalc Gets a BIG 2026 Update with LVGL, SSH Terminal, and more!

💾PicoWare


「成為美國的敵人或許很危險,但做美國的朋友卻是致命」("It may be dangerous to be America's enemy, but to be America's friend is fatal")據說是 季辛吉說的(有爭議)


確信是寬容的死敵 from Movie Convlave

🌐Convlave


2026-02-13 🌐 🎬 💾 📚 📑 🔬🦠

Chinese New Year Vacation from 02-14 to 02-23

AXI-Stream

💾AXI Stream SystemVerilog Modules for High-Performance On-Chip Communication

🌐Creating a custom AXI-Streaming IP in Vivado

🌐MicroZed Chronicles: AXI Stream FIFO IP Core


2026-02-12 🌐 🎬 💾 📚 📑 🔬🦠🧪

Numba Python JIT Compiler

Numba

Numba is an open source JIT compiler that translates a subset of Python and NumPy code into fast machine code.


Boxcar Integrator

Boxcar Integrator

Similar to Lock In Amp


Pioreactor: An automated Raspberry Pi bioreactor

🌐Pioreactor: An automated Raspberry Pi bioreactor

A bioreactor is a vessel that provides an optimised environment for growing cells, microorganisms, and microbial cultures. In its simplest form, it could just be a jar, but the term ‘bioreactor’ commonly describes more complex setups in which the environment can be controlled and automated. Bioreactors are typically used in the development of pharmaceuticals, as well as in the food sciences, medical sciences, and many other chemistry- and biology-adjacent sectors.


Lightweight dataflow embedded programming in C++

💾Ramen

Lightweight dataflow embedded programming in C++

RAMEN is a very compact, unopinionated, single-header C++20+ dependency-free library that implements message-passing/flow-based programming for hard real-time mission-critical embedded systems, as well as general-purpose applications. It is designed to be very low-overhead, efficient, and easy to use.


2026-02-11 🌐 🎬 💾 📚 📑 🔬🦠🧪

PICO FFT

💾Pico FFT


Yellow Tooth

Yellow Tooth

  • 小蘇答粉 加 活性碳 刷牙

  • 用椰子油素口 20 分鐘


AD5934 as Lock In Amp

📚Silicon Photomultiplier-based Low-light in vivo Fiber Photometry


AD630 as Lock In Amp

🌐AD630 as Lock In Amp

🎬How a Lock in amplifier works

🎬Lock-in Amplifier Technique for Noise Rejection

🌐AD630 as Lock In Amp


2026-02-10 🌐 🎬 💾 📚 📑 🔬🦠🧪

ThunderScope Github Projects

💾ThunderScope Github Projects


Avnet HDL Sample Code

💾Avnet HDL Sample Code


FPGA HDMI display controller

🎬FPGA HDMI display controller


🌐FPGA纯verilog代码解码CameraLink视频,附带工程源码和技术支持

🌐Hello-FPGA Camera link Full Receiver FMC Card User Manual

🌐Python1300 use Zynq


2026-02-09 🌐 🎬 💾 📚 📑 🔬🦠🧪

Faust (Functional Audio Stream)

🌐Faust (Functional Audio Stream)

Faust (Functional Audio Stream) is a functional programming language for sound synthesis and audio processing with a strong focus on the design of synthesizers, musical instruments, audio effects, etc. created at the GRAME-CNCM Research Department.

📑FAUST_an_Efficient_Functional_Approach_to_DSP_Prog


How I turned my iPad into an ideal e-reader

How I turned my iPad into an ideal e-reader


How to show webcam in TkInter Window - Python

🌐How to show webcam in TkInter Window - Python


Camera in Commutator


2026-02-06 🌐 🎬 💾 📚 📑 🔬🦠🧪

Camera In Commutator


CEBRA Consistent EmBeddings of high-dimensional Recordings using Auxiliary variables

🌐CEBRA


2026-02-05 🌐 🎬 💾 📚 📑 🔬🦠🧪

High Level Sythesis Make Easy

2026-010


Master Embedded Linux Development

2026-009


C++23 Coroutines

2026-008


The MicroZed Chronicles

2026-007


2026-02-04 🌐 🎬 💾 📚 📑 🔬🦠🧪

SiPM Specification


Python Precision Delay

start_time_ns = time.perf_counter_ns()
time_elapsed_ns = time.perf_counter_ns() - start_time_ns
while(time_elapsed_ns < gap_us*1000):
    time_elapsed_ns = time.perf_counter_ns() - start_time_ns

UVC camera exposure timing in OpenCV

ExpoTime_ms = 5

fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
#camera.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25) On
camera.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.75)

camera.set(cv2.CAP_PROP_FOURCC, fourcc)
camera.set(cv2.CAP_PROP_FRAME_WIDTH, 800)
camera.set(cv2.CAP_PROP_FRAME_HEIGHT,600)
camera.set(cv2.CAP_PROP_FPS, 120) # Must after CAP_PROP_FOURCC
camera.set(cv2.CAP_PROP_EXPOSURE, ExpoTime_ms*10)

OpenCV Camera Caputer and Display

ret, frame = camera.read()

ret = camera.grab()
ret, frame = camera.retrieve()

cv2.imshow("image1", frame)

if cv2.waitKey(1) & 0xff == ord('q'):
    print("exit")
    break

2026-02-03 🌐 🎬 💾 📚 📑 🔬🦠🧪

HLS Libs

🌐HLS Libs


我是X世代

X世代是指1960年代中期至1980年代出生的人。


Bonsai

📑Bonsai Event Based Framework


📑Miniscope Review 2019

📑NINScope 2019

📑Head Mounted Microcope 2023


TVS vs ESD Diode (via AI)

TVS 二極體(瞬態電壓抑制器)是一個廣義類別,而 ESD 二極體則是該類別中專門針對靜電放電保護而優化的子集。 兩者的主要區別在於它們應對的能量等級與反應速度。

核心規格對比

ESD 二極體 (ESD Diode)

  • 主要用途 保護電路免受人體或設備接觸產生的靜電傷害。

  • 能量處理能力 較低。設計用於應對極短(<1ns)但高壓的脈衝。

  • 電容值 (Capacitance) 極低(通常 <1pF)。適用於 USB 3.0、HDMI 等高頻信號線。

  • 封裝尺寸 體積極小,適合嵌入式設備或移動裝置。

  • 突波電流 (Ipp) 德州儀器 (TI) 將其定義為通常 <12A。


TVS 二極體 (TVS Diode)

  • 主要用途 保護電路免受電源浪湧、雷擊或開關突波影響

  • 能量處理能力 較高。需吸收持續時間較長(微秒至毫秒級)的大能量脈衝。

  • 電容值 (Capacitance) 較高。通常用於電源輸入端,對高頻信號可能造成失真。

  • 封裝尺寸 體積較大,以散發浪湧產生的熱能。

  • 突波電流 (Ipp) 德州儀器將其定義為通常 >12A。


2026-02-02 🌐 🎬 💾 📚 📑 🔬🦠🧪

PyFTDI

📑PyFTDI ReadMe

💾PyFTDI

USB Rules

# /etc/udev/rules.d/11-ftdi.rules

# FT232AM/FT232BM/FT232R
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6001", GROUP="plugdev", MODE="0664"
# FT2232C/FT2232D/FT2232H
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6010", GROUP="plugdev", MODE="0664"
# FT4232/FT4232H
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6011", GROUP="plugdev", MODE="0664"
# FT232H
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6014", GROUP="plugdev", MODE="0664"
# FT230X/FT231X/FT234X
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6015", GROUP="plugdev", MODE="0664"
# FT4232HA
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", ATTR{idProduct}=="6048", GROUP="plugdev", MODE="0664"

Fiber Photometry in Commutator

Mv series camera appnotes 4 rpi

📚Mv series camera appnotes 4 rpi

Camera Module : MV-MIPI-GMAX4002

轉接板 : adp-mv1-v2


LVDS Input/Output Protection