Fast AVR ATmega328 based scan controller with velocity dynamic scanning for FATAR TP8/(H)O and PULSE 6105W keybeds or non-dynamic scanning of single-contact keybeds with MOS 4014 shift registers. Comes with velocity slope control and menu system (if equipped with KeyboardPartner MenuPanel). Achieves net 4.5 kHz scan rate, scanning of 2 keybeds (upper and lower manual) takes max. 205 µs plus 80 µs for 25-note bass pedal. Scan rate slowed down to 2 kHz per timer 1 ISR semaphore to yield time for button and menu processing. Design is not critical; cable lengths of up to 1m in total between controller and keybed(s) are allowed.
Designed for KeyboardPartner Scan61, FatarScan2 or new FatarScan1-61 and PulseScan keybed interface boards or DIY equivalents, see schematics in /docs and on KeyboardPartner Update Server.
If not needed, comment out these defines in main.cpp and set defaults in menu_items.h accordingly:
#define LCD_I2C
#define ANLG_MPX
#define PANEL16Just download the ZIP (dropdown menu in green <> Code button above) and unpack on your harddisk (or clone project if you installed Git). Open this folder in VScode/PlatformIO. There are some environments provided for different MCU speeds and to flash an OptiBoot bootloader with USBasp stick. With bootloader installed, use the [env:ATmega328P_20MHz] environment to upload the firmware to your ATmega328(P).
Download the ZIP (dropdown menu in green <> Code button above) and unpack on your harddisk. Copy include and lib directory contects into your sketch directory. Rename main.cpp to .ino. Arduino IDE has no provision to select MCU speed. To use the 20 MHz version, install MiniCore in the Arduino IDE (Board Manager), then select "ATmega328P (MiniCore)" as board and "20 MHz external" as clock speed.
Then burn the bootloader to set the fuses for 20 MHz operation. After that you can upload the sketch with the regular Arduino bootloader method -- no special programmer needed. Anyway, we highly recommend using PlatformIO with VSCode for development!
Version Info:
- New approach for velocity table with variable slope:
void CreateDynTable(uint8_t mindyn, uint8_t slope) {
// Create lookup table, converts key timer value -> MIDI dynamic
// Table index: key velocity timer 0..255 (255 = extremely fast key press)
// mindyn: minimal MIDI dynamic value, 1..40
// slope: 1 = nearly linear, 20 = strong 1/t chracteristic
if (slope < 1) slope = 1;
float inv_slope = 1.0f / (float)slope;
for (uint16_t t = 0; t <= 255; t++) {
float norm = (float)t / 255.0f; // normalisierter Zeitwert 0..1
norm = (inv_slope * norm) / ((1 + inv_slope) - norm);
norm *= (float)(127 - mindyn);
TimeToDyn[t] = (uint8_t)norm + mindyn;
}
}- Added support for analog inputs with KeyboardPartner MPX boards (SR-based multiplexer)
- Faster bit manipulation on ports by inline assembler macros
- Menu Strings moved to progmem, editable CC numbers
- Improved support for Panel16 LED Button board, some examples in main.cpp
- Added scan routine for two PULSE 6105W keybeds
- Simplified state machines and speed-up of scanning to 155µs (FatarScan2 interface), 176µs (FatarScan1-61) or 205µs (Pulse 6105W)
C. Meyer 2/2026