diff --git a/keyboards/annepro2/annepro2.c b/keyboards/annepro2/annepro2.c
new file mode 100644
index 0000000000..37489defff
--- /dev/null
+++ b/keyboards/annepro2/annepro2.c
@@ -0,0 +1,202 @@
+/* Copyright 2021 OpenAnnePro community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "hal.h"
+#include "annepro2.h"
+#include "annepro2_ble.h"
+#include "spi_master.h"
+#include "ap2_led.h"
+#include "protocol.h"
+
+#define RAM_MAGIC_LOCATION 0x20001ffc
+#define IAP_MAGIC_VALUE 0x0000fab2
+
+static const SerialConfig ledUartInitConfig = {
+    .speed = 115200,
+};
+
+#ifndef LED_UART_BAUD_RATE
+#    define LED_UART_BAUD_RATE 115200
+#endif  // LED_UART_BAUD_RATE
+
+static const SerialConfig ledUartRuntimeConfig = {
+    .speed = LED_UART_BAUD_RATE,
+};
+
+static const SerialConfig bleUartConfig = {
+    .speed = 115200,
+};
+
+static uint8_t ledMcuWakeup[11] = {0x7b, 0x10, 0x43, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x02};
+
+ble_capslock_t BLECapsLock = {._dummy = {0}, .caps_lock = false};
+
+void bootloader_jump(void) {
+    // Send msg to shine to boot into IAP
+    annepro2SetIAP();
+
+    // wait for shine to boot into IAP
+    wait_ms(15);
+
+    // Load ble into IAP
+    annepro2_ble_bootload();
+    wait_ms(15);
+
+    // Magic key to set keyboard to IAP
+    // It’s from reversing original boot loader
+    // If value is that it stays in boot loader aka IAP
+    *((uint32_t *)RAM_MAGIC_LOCATION) = IAP_MAGIC_VALUE;
+
+    // Load the main MCU into IAP
+    __disable_irq();
+    NVIC_SystemReset();
+}
+
+void keyboard_pre_init_kb(void) {
+    // Start LED UART
+    sdStart(&SD0, &ledUartInitConfig);
+    /* Let the LED chip settle a bit before switching the mode.
+     * That helped at least one person. */
+    wait_ms(15);
+    sdWrite(&SD0, ledMcuWakeup, sizeof(ledMcuWakeup));
+
+    // wait to receive response from wakeup
+    wait_ms(15);
+
+    protoInit(&proto, ledCommandCallback);
+
+    // loop to clear out receive buffer from shine wakeup
+    while (!sdGetWouldBlock(&SD0)) sdGet(&SD0);
+
+    sdStart(&SD0, &ledUartRuntimeConfig);
+    keyboard_pre_init_user();
+}
+
+void keyboard_post_init_kb(void) {
+    // Start BLE UART
+    sdStart(&SD1, &bleUartConfig);
+    annepro2_ble_startup();
+
+    // Give the send uart thread some time to
+    // send out the queue before we read back
+    wait_ms(100);
+
+    // loop to clear out receive buffer from ble wakeup
+    while (!sdGetWouldBlock(&SD1)) sdGet(&SD1);
+
+    annepro2LedGetStatus();
+
+    keyboard_post_init_user();
+}
+
+void matrix_scan_kb() {
+    // if there's stuff on the ble serial buffer
+    // read it into the capslock struct
+    while (!sdGetWouldBlock(&SD1)) {
+        sdReadTimeout(&SD1, (uint8_t *)&BLECapsLock, sizeof(ble_capslock_t), 10);
+    }
+
+    /* While there's data from LED keyboard sent - read it. */
+    while (!sdGetWouldBlock(&SD0)) {
+        uint8_t byte = sdGet(&SD0);
+        protoConsume(&proto, byte);
+    }
+
+    matrix_scan_user();
+}
+
+bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+    if (record->event.pressed) {
+        if (annepro2LedStatus.matrixEnabled && annepro2LedStatus.isReactive) {
+            annepro2LedForwardKeypress(record->event.key.row, record->event.key.col);
+        }
+
+        const annepro2Led_t blue = {
+            .p.blue  = 0xff,
+            .p.red   = 0x00,
+            .p.green = 0x00,
+            .p.alpha = 0xff,
+        };
+
+        switch (keycode) {
+            case KC_AP2_BT1:
+                annepro2_ble_broadcast(0);
+                /* FIXME: This hardcodes col/row position */
+                annepro2LedBlink(0, 1, blue, 8, 50);
+                return false;
+
+            case KC_AP2_BT2:
+                annepro2_ble_broadcast(1);
+                annepro2LedBlink(0, 2, blue, 8, 50);
+                return false;
+
+            case KC_AP2_BT3:
+                annepro2_ble_broadcast(2);
+                annepro2LedBlink(0, 3, blue, 8, 50);
+                return false;
+
+            case KC_AP2_BT4:
+                annepro2_ble_broadcast(3);
+                annepro2LedBlink(0, 4, blue, 8, 50);
+                return false;
+
+            case KC_AP2_USB:
+                annepro2_ble_disconnect();
+                return false;
+
+            case KC_AP2_BT_UNPAIR:
+                annepro2_ble_unpair();
+                return false;
+
+            case KC_AP_LED_OFF:
+                annepro2LedDisable();
+                break;
+
+            case KC_AP_LED_ON:
+                if (annepro2LedStatus.matrixEnabled) {
+                    annepro2LedNextProfile();
+                } else {
+                    annepro2LedEnable();
+                }
+                annepro2LedResetForegroundColor();
+                break;
+
+            case KC_AP_LED_NEXT_PROFILE:
+                annepro2LedNextProfile();
+                annepro2LedResetForegroundColor();
+                break;
+
+            case KC_AP_LED_PREV_PROFILE:
+                annepro2LedPrevProfile();
+                annepro2LedResetForegroundColor();
+                break;
+
+            case KC_AP_LED_NEXT_INTENSITY:
+                annepro2LedNextIntensity();
+                annepro2LedResetForegroundColor();
+                return false;
+
+            case KC_AP_LED_SPEED:
+                annepro2LedNextAnimationSpeed();
+                annepro2LedResetForegroundColor();
+                return false;
+
+            default:
+                break;
+        }
+    }
+    return process_record_user(keycode, record);
+}
diff --git a/keyboards/annepro2/annepro2.h b/keyboards/annepro2/annepro2.h
new file mode 100644
index 0000000000..b08f8c5352
--- /dev/null
+++ b/keyboards/annepro2/annepro2.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018 Yaotian Feng
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+#include "quantum.h"
+#include <stdint.h>
+#include "ap2_led.h"
+
+typedef struct __attribute__((__packed__)) {
+    uint8_t _dummy[10];
+    bool    caps_lock;
+} ble_capslock_t;
+extern ble_capslock_t BLECapsLock;
+
+// Matrix keymap
+// clang-format off
+#define LAYOUT( \
+    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
+    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
+    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C,      \
+    K30,      K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C,      \
+    K40, K42, K43,                K46,           K49,  K4A,   K4B,   K4C  \
+) { \
+    /*            COL1   COL2   COL3   COL4   COL5   COL6   COL7   COL8   COL9   COL10  COL11  COL12  COL13  COL14*/ \
+    /* ROW1  */ { K00,   K01,   K02,   K03,   K04,   K05,   K06,   K07,   K08,   K09,   K0A,   K0B,   K0C,   K0D  }, \
+    /* ROW2  */ { K10,   K11,   K12,   K13,   K14,   K15,   K16,   K17,   K18,   K19,   K1A,   K1B,   K1C,   K1D  }, \
+    /* ROW3  */ { K20,   K21,   K22,   K23,   K24,   K25,   K26,   K27,   K28,   K29,   K2A,   K2B,   K2C,   KC_NO}, \
+    /* ROW4  */ { K30,   KC_NO, K32,   K33,   K34,   K35,   K36,   K37,   K38,   K39,   K3A,   K3B,   K3C,   KC_NO}, \
+    /* ROW5  */ { K40,   KC_NO, K42,   K43,   KC_NO, KC_NO, K46,   KC_NO, KC_NO, K49,   K4A,   K4B,   K4C,   KC_NO}, \
+}
+// clang-format on
+
+enum AP2KeyCodes {
+    KC_AP2_BT1 = SAFE_RANGE,
+    KC_AP2_BT2,
+    KC_AP2_BT3,
+    KC_AP2_BT4,
+    KC_AP2_BT_UNPAIR,
+    KC_AP2_USB,
+    KC_AP_LED_ON,
+    KC_AP_LED_OFF,
+    KC_AP_LED_NEXT_PROFILE,
+    KC_AP_LED_PREV_PROFILE,
+    KC_AP_LED_NEXT_INTENSITY,
+    KC_AP_LED_SPEED,
+    AP2_SAFE_RANGE,
+};
+
+#undef SAFE_RANGE
+#define SAFE_RANGE AP2_SAFE_RANGE
+
diff --git a/keyboards/annepro2/annepro2_ble.c b/keyboards/annepro2/annepro2_ble.c
new file mode 100644
index 0000000000..72cbb68016
--- /dev/null
+++ b/keyboards/annepro2/annepro2_ble.c
@@ -0,0 +1,170 @@
+/*
+    Copyright (C) 2020 Yaotian Feng, Codetector<codetector@codetector.cn>
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+#include "annepro2_ble.h"
+#include "ch.h"
+#include "hal.h"
+#include "host.h"
+#include "host_driver.h"
+#include "report.h"
+
+/* -------------------- Static Function Prototypes -------------------------- */
+static uint8_t ap2_ble_leds(void);
+static void    ap2_ble_mouse(report_mouse_t *report);
+static void    ap2_ble_system(uint16_t data);
+static void    ap2_ble_consumer(uint16_t data);
+static void    ap2_ble_keyboard(report_keyboard_t *report);
+
+static void ap2_ble_swtich_ble_driver(void);
+
+/* -------------------- Static Local Variables ------------------------------ */
+static host_driver_t ap2_ble_driver = {
+    ap2_ble_leds, ap2_ble_keyboard, ap2_ble_mouse, ap2_ble_system, ap2_ble_consumer,
+};
+
+static uint8_t bleMcuWakeup[11] = {0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x01, 0x7d, 0x02, 0x01, 0x02};
+
+static uint8_t bleMcuStartBroadcast[11] = {
+    0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x00, 0x7d, 0x40, 0x01, 0x00  // Broadcast ID[0-3]
+};
+
+static uint8_t bleMcuConnect[11] = {
+    0x7b, 0x12, 0x53, 0x00, 0x03, 0x00, 0x00, 0x7d, 0x40, 0x04, 0x00  // Connect ID [0-3]
+};
+
+static uint8_t bleMcuSendReport[10] = {
+    0x7b, 0x12, 0x53, 0x00, 0x0A, 0x00, 0x00, 0x7d, 0x10, 0x04,
+};
+
+static uint8_t bleMcuSendConsumerReport[10] = {
+    0x7b, 0x12, 0x53, 0x00, 0x06, 0x00, 0x00, 0x7d, 0x10, 0x08,
+};
+
+static uint8_t bleMcuUnpair[10] = {
+    0x7b, 0x12, 0x53, 0x00, 0x02, 0x00, 0x00, 0x7d, 0x40, 0x05,
+};
+
+static uint8_t bleMcuBootload[11] = {0x7b, 0x10, 0x51, 0x10, 0x03, 0x00, 0x00, 0x7d, 0x02, 0x01, 0x01};
+
+static host_driver_t *lastHostDriver = NULL;
+#ifdef NKRO_ENABLE
+static bool lastNkroStatus = false;
+#endif  // NKRO_ENABLE
+
+/* -------------------- Public Function Implementation ---------------------- */
+
+void annepro2_ble_bootload(void) { sdWrite(&SD1, bleMcuBootload, sizeof(bleMcuBootload)); }
+
+void annepro2_ble_startup(void) { sdWrite(&SD1, bleMcuWakeup, sizeof(bleMcuWakeup)); }
+
+void annepro2_ble_broadcast(uint8_t port) {
+    if (port > 3) {
+        port = 3;
+    }
+    // sdPut(&SD1, 0x00);
+    sdWrite(&SD1, bleMcuStartBroadcast, sizeof(bleMcuStartBroadcast));
+    sdPut(&SD1, port);
+    static int lastBroadcast = -1;
+    if (lastBroadcast == port) {
+        annepro2_ble_connect(port);
+    }
+    lastBroadcast = port;
+}
+
+void annepro2_ble_connect(uint8_t port) {
+    if (port > 3) {
+        port = 3;
+    }
+    sdWrite(&SD1, bleMcuConnect, sizeof(bleMcuConnect));
+    sdPut(&SD1, port);
+    ap2_ble_swtich_ble_driver();
+}
+
+void annepro2_ble_disconnect(void) {
+    /* Skip if the driver is already enabled */
+    if (host_get_driver() != &ap2_ble_driver) {
+        return;
+    }
+
+    clear_keyboard();
+#ifdef NKRO_ENABLE
+    keymap_config.nkro = lastNkroStatus;
+#endif
+    host_set_driver(lastHostDriver);
+}
+
+void annepro2_ble_unpair(void) {
+    // sdPut(&SD1, 0x0);
+    sdWrite(&SD1, bleMcuUnpair, sizeof(bleMcuUnpair));
+}
+
+/* ------------------- Static Function Implementation ----------------------- */
+static void ap2_ble_swtich_ble_driver(void) {
+    if (host_get_driver() == &ap2_ble_driver) {
+        return;
+    }
+    clear_keyboard();
+    lastHostDriver = host_get_driver();
+#ifdef NKRO_ENABLE
+    lastNkroStatus = keymap_config.nkro;
+#endif
+    keymap_config.nkro = false;
+    host_set_driver(&ap2_ble_driver);
+}
+
+static uint8_t ap2_ble_leds(void) {
+    return 0;  // TODO: Figure out how to obtain LED status
+}
+
+static void ap2_ble_mouse(report_mouse_t *report) {}
+
+static void ap2_ble_system(uint16_t data) {}
+
+static inline uint16_t CONSUMER2AP2(uint16_t usage) {
+    switch (usage) {
+        case AUDIO_VOL_DOWN:
+            return 0x04;
+        case AUDIO_VOL_UP:
+            return 0x02;
+        case AUDIO_MUTE:
+            return 0x01;
+        case TRANSPORT_PLAY_PAUSE:
+            return 0x08;
+        case TRANSPORT_NEXT_TRACK:
+            return 0x10;
+        case TRANSPORT_PREV_TRACK:
+            return 0x20;
+        default:
+            return 0x00;
+    }
+}
+
+static void ap2_ble_consumer(uint16_t data) {
+    sdPut(&SD1, 0x0);
+    sdWrite(&SD1, bleMcuSendConsumerReport, sizeof(bleMcuSendConsumerReport));
+    sdPut(&SD1, CONSUMER2AP2(data));
+    static const uint8_t dummy[3] = {0};
+    sdWrite(&SD1, dummy, sizeof(dummy));
+}
+
+/*!
+ * @brief  Send keyboard HID report for Bluetooth driver
+ */
+static void ap2_ble_keyboard(report_keyboard_t *report) {
+    sdPut(&SD1, 0x0);
+    sdWrite(&SD1, bleMcuSendReport, sizeof(bleMcuSendReport));
+    sdWrite(&SD1, &report->raw[0], KEYBOARD_REPORT_SIZE);
+}
diff --git a/keyboards/annepro2/annepro2_ble.h b/keyboards/annepro2/annepro2_ble.h
new file mode 100644
index 0000000000..0cfb68e071
--- /dev/null
+++ b/keyboards/annepro2/annepro2_ble.h
@@ -0,0 +1,27 @@
+/*
+    Copyright (C) 2020 Yaotian Feng, Codetector<codetector@codetector.cn>
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+#pragma once
+
+#include "annepro2.h"
+#include "quantum.h"
+
+void annepro2_ble_bootload(void);
+void annepro2_ble_startup(void);
+void annepro2_ble_broadcast(uint8_t port);
+void annepro2_ble_connect(uint8_t port);
+void annepro2_ble_disconnect(void);
+void annepro2_ble_unpair(void);
diff --git a/keyboards/annepro2/ap2_led.c b/keyboards/annepro2/ap2_led.c
new file mode 100644
index 0000000000..9969fcd02a
--- /dev/null
+++ b/keyboards/annepro2/ap2_led.c
@@ -0,0 +1,134 @@
+/* Copyright 2021 OpenAnnePro community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include "hal.h"
+#include "annepro2.h"
+#include "ap2_led.h"
+#include "protocol.h"
+
+annepro2Led_t       ledMask[KEY_COUNT];
+annepro2LedStatus_t annepro2LedStatus;
+
+void ledCommandCallback(const message_t *msg) {
+    switch (msg->command) {
+        case CMD_LED_STATUS:
+            annepro2LedStatus.amountOfProfiles = msg->payload[0];
+            annepro2LedStatus.currentProfile   = msg->payload[1];
+            annepro2LedStatus.matrixEnabled    = msg->payload[2];
+            annepro2LedStatus.isReactive       = msg->payload[3];
+            annepro2LedStatus.ledIntensity     = msg->payload[4];
+            annepro2LedStatus.errors           = msg->payload[5];
+            break;
+
+#ifdef CONSOLE_ENABLE
+        case CMD_LED_DEBUG:
+            /* TODO: Don't use printf. */
+            printf("LED:");
+            for (int i = 0; i < msg->payloadSize; i++) {
+                printf("%02x ", msg->payload[i]);
+            }
+            for (int i = 0; i < msg->payloadSize; i++) {
+                printf("%c", msg->payload[i]);
+            }
+            printf("\n");
+            break;
+#endif
+    }
+}
+
+void annepro2SetIAP(void) { protoTx(CMD_LED_IAP, NULL, 0, 3); }
+
+void annepro2LedDisable(void) { protoTx(CMD_LED_OFF, NULL, 0, 3); }
+
+void annepro2LedEnable(void) { protoTx(CMD_LED_ON, NULL, 0, 3); }
+
+void annepro2LedSetProfile(uint8_t prof) { protoTx(CMD_LED_SET_PROFILE, &prof, sizeof(prof), 3); }
+
+void annepro2LedGetStatus() { protoTx(CMD_LED_GET_STATUS, NULL, 0, 3); }
+
+void annepro2LedNextProfile() { protoTx(CMD_LED_NEXT_PROFILE, NULL, 0, 3); }
+
+void annepro2LedNextIntensity() { protoTx(CMD_LED_NEXT_INTENSITY, NULL, 0, 3); }
+
+void annepro2LedNextAnimationSpeed() { protoTx(CMD_LED_NEXT_ANIMATION_SPEED, NULL, 0, 3); }
+
+void annepro2LedPrevProfile() { protoTx(CMD_LED_PREV_PROFILE, NULL, 0, 3); }
+
+void annepro2LedMaskSetKey(uint8_t row, uint8_t col, annepro2Led_t color) {
+    uint8_t payload[] = {row, col, color.p.blue, color.p.green, color.p.red, color.p.alpha};
+    protoTx(CMD_LED_MASK_SET_KEY, payload, sizeof(payload), 1);
+}
+
+/* Push a whole local row to the shine */
+void annepro2LedMaskSetRow(uint8_t row) {
+    uint8_t payload[NUM_COLUMN * sizeof(annepro2Led_t) + 1];
+    payload[0] = row;
+    memcpy(payload + 1, &ledMask[ROWCOL2IDX(row, 0)], sizeof(*ledMask) * NUM_COLUMN);
+    protoTx(CMD_LED_MASK_SET_ROW, payload, sizeof(payload), 1);
+}
+
+/* Synchronize all rows */
+void annepro2LedMaskSetAll(void) {
+    for (int row = 0; row < 5; row++) annepro2LedMaskSetRow(row);
+}
+
+/* Set all keys to a given color */
+void annepro2LedMaskSetMono(const annepro2Led_t color) { protoTx(CMD_LED_MASK_SET_MONO, (uint8_t *)&color, sizeof(color), 1); }
+
+void annepro2LedBlink(uint8_t row, uint8_t col, annepro2Led_t color, uint8_t count, uint8_t hundredths) {
+    uint8_t payload[] = {row, col, color.p.blue, color.p.green, color.p.red, color.p.alpha, count, hundredths};
+    protoTx(CMD_LED_KEY_BLINK, payload, sizeof(payload), 1);
+}
+
+void annepro2LedSetForegroundColor(uint8_t red, uint8_t green, uint8_t blue) {
+    annepro2Led_t color = {.p.red = red, .p.green = green, .p.blue = blue, .p.alpha = 0xff};
+    annepro2LedMaskSetMono(color);
+}
+
+void annepro2LedResetForegroundColor() {
+    annepro2Led_t color = {
+        .p.red   = 0,
+        .p.green = 0,
+        .p.blue  = 0,
+        .p.alpha = 0,
+    };
+    annepro2LedMaskSetMono(color);
+}
+
+/*
+ * Currently keypresses are unified with other messages, still with single 1
+ * byte payload. Transfer is normally fast enough for that to not be a problem -
+ * especially with asynchronous message reading.
+ *
+ *
+ * Previous description:
+ * If enabled, this data is sent to LED MCU on every keypress.
+ * In order to improve performance, both row and column values
+ * are packed into a single byte.
+ * Row range is [0, 4] and requires only 3 bits.
+ * Column range is [0, 13] and requires 4 bits.
+ *
+ * In order to differentiate this command from regular commands,
+ * the leftmost bit is set to 1 (0b10000000).
+ * Following it are 3 bits of row and 4 bits of col.
+ * 1 + 3 + 4 = 8 bits - only a single byte is sent for every keypress.
+ */
+void annepro2LedForwardKeypress(uint8_t row, uint8_t col) {
+    const uint8_t payload = row << 4 | col;
+    protoTx(CMD_LED_KEY_DOWN, &payload, 1, 1);
+}
diff --git a/keyboards/annepro2/ap2_led.h b/keyboards/annepro2/ap2_led.h
new file mode 100644
index 0000000000..23712a2555
--- /dev/null
+++ b/keyboards/annepro2/ap2_led.h
@@ -0,0 +1,84 @@
+ /* Copyright 2021 OpenAnnePro community
+  * 
+  * This program is free software: you can redistribute it and/or modify 
+  * it under the terms of the GNU General Public License as published by 
+  * the Free Software Foundation, either version 2 of the License, or 
+  * (at your option) any later version. 
+  * 
+  * This program is distributed in the hope that it will be useful, 
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+  * GNU General Public License for more details. 
+  * 
+  * You should have received a copy of the GNU General Public License 
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+  */ 
+
+#pragma once
+
+#include "protocol.h"
+
+// Struct defining an LED and its RGB color components
+// Compatible with Shine firmware.
+typedef union {
+    struct {
+        /* Little endian ordering to match uint32_t */
+        uint8_t blue, green, red;
+        /* Used in mask; nonzero means - use color from mask. */
+        uint8_t alpha;
+    } p; /* parts */
+    /* Parts vector access: 0 - blue, 1 - green, 2 - red */
+    uint8_t pv[4];
+    /* 0xrgb in mem is b g r a */
+    uint32_t rgb;
+} annepro2Led_t;
+
+#define ROWCOL2IDX(row, col) (NUM_COLUMN * (row) + (col))
+#define NUM_COLUMN 14
+#define NUM_ROW 5
+#define KEY_COUNT 70
+
+/* Local copy of ledMask, used to override colors on the board */
+extern annepro2Led_t ledMask[KEY_COUNT];
+
+/* Handle incoming messages */
+extern void ledCommandCallback(const message_t *msg);
+
+void annepro2SetIAP(void);
+void annepro2LedDisable(void);
+void annepro2LedEnable(void);
+void annepro2LedSetProfile(uint8_t prof);
+void annepro2LedGetStatus(void);
+void annepro2LedNextProfile(void);
+void annepro2LedPrevProfile(void);
+void annepro2LedNextIntensity(void);
+void annepro2LedNextAnimationSpeed(void);
+void annepro2LedForwardKeypress(uint8_t row, uint8_t col);
+
+/* Set single key to a given color; alpha controls which is displayed */
+void annepro2LedMaskSetKey(uint8_t row, uint8_t col, annepro2Led_t color);
+/* Push a whole local row to the shine */
+void annepro2LedMaskSetRow(uint8_t row);
+/* Synchronize all rows */
+void annepro2LedMaskSetAll(void);
+
+/* Set all keys to a given color */
+void annepro2LedMaskSetMono(annepro2Led_t color);
+
+/* Blink given key `count` times by masking it with a `color`. Blink takes `hundredths` of a second */
+void annepro2LedBlink(uint8_t row, uint8_t col, annepro2Led_t color, uint8_t count, uint8_t hundredths);
+
+/* Kept for compatibility, but implemented using masks */
+void annepro2LedSetForegroundColor(uint8_t red, uint8_t green, uint8_t blue);
+void annepro2LedResetForegroundColor(void);
+
+typedef struct {
+    uint8_t amountOfProfiles;
+    uint8_t currentProfile;
+    uint8_t matrixEnabled;
+    uint8_t isReactive;
+    uint8_t ledIntensity;
+    uint8_t errors;
+} annepro2LedStatus_t;
+
+extern annepro2LedStatus_t annepro2LedStatus;
diff --git a/keyboards/annepro2/boards/ANNEPRO2_C15/board.c b/keyboards/annepro2/boards/ANNEPRO2_C15/board.c
new file mode 100644
index 0000000000..60c1826155
--- /dev/null
+++ b/keyboards/annepro2/boards/ANNEPRO2_C15/board.c
@@ -0,0 +1,103 @@
+/*
+    Copyright (C) 2020 Yaotian Feng, Codetector<codetector@codetector.cn>
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+#include "hal.h"
+
+/* ============ Private Defines ===================== */
+
+/* ============ Function Prototypes ================== */
+
+#define PBIT(PORT, LINE) ((PAL_PORT(LINE) == PORT) ? (1 << PAL_PAD(LINE)) : 0)
+#define PAFIO_L(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) < 8)) ? (AF << (PAL_PAD(LINE) << 2)) : 0)
+#define PAFIO_H(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) >= 8)) ? (AF << ((PAL_PAD(LINE) - 8) << 2)) : 0)
+#define PAFIO(PORT, N, LINE, AF) ((N) ? PAFIO_H(PORT, LINE, AF) : PAFIO_L(PORT, LINE, AF))
+
+#define OUT_BITS(PORT) (PBIT(PORT, C2) | PBIT(PORT, C1) | PBIT(PORT, B5) | PBIT(PORT, B4) | PBIT(PORT, C3) | 0)
+
+#define IN_BITS(PORT) (PBIT(PORT, C4) | PBIT(PORT, C5) | PBIT(PORT, B10) | PBIT(PORT, B11) | PBIT(PORT, C0) | PBIT(PORT, A15) | PBIT(PORT, A8) | PBIT(PORT, A10) | PBIT(PORT, A11) | PBIT(PORT, A12) | PBIT(PORT, A13) | PBIT(PORT, A14) | PBIT(PORT, B2) | PBIT(PORT, B3) | 0)
+
+// Alternate Functions
+#define AF_BITS(PORT, N) (PAFIO(PORT, N, LINE_UART_RX, AFIO_USART) | PAFIO(PORT, N, LINE_UART_TX, AFIO_USART) | PAFIO(PORT, N, LINE_BT_UART_TX, AFIO_USART) | PAFIO(PORT, N, LINE_BT_UART_RX, AFIO_USART) | PAFIO(PORT, N, C2, AFIO_GPIO) | PAFIO(PORT, N, C1, AFIO_GPIO) | PAFIO(PORT, N, B5, AFIO_GPIO) | PAFIO(PORT, N, B4, AFIO_GPIO) | PAFIO(PORT, N, C3, AFIO_GPIO) | PAFIO(PORT, N, C4, AFIO_GPIO) | PAFIO(PORT, N, C5, AFIO_GPIO) | PAFIO(PORT, N, B10, AFIO_GPIO) | PAFIO(PORT, N, B11, AFIO_GPIO) | PAFIO(PORT, N, C0, AFIO_GPIO) | PAFIO(PORT, N, A15, AFIO_GPIO) | PAFIO(PORT, N, A8, AFIO_GPIO) | PAFIO(PORT, N, A10, AFIO_GPIO) | PAFIO(PORT, N, A11, AFIO_GPIO) | PAFIO(PORT, N, A12, AFIO_GPIO) | PAFIO(PORT, N, A13, AFIO_GPIO) | PAFIO(PORT, N, A14, AFIO_GPIO) | PAFIO(PORT, N, B2, AFIO_GPIO) | PAFIO(PORT, N, B3, AFIO_GPIO) | 0)
+
+/**
+ * @brief   PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ *          This variable is used by the HAL when initializing the PAL driver.
+ */
+const PALConfig pal_default_config = {
+    // GPIO A
+    .setup[0] =
+        {
+            .DIR    = OUT_BITS(IOPORTA),
+            .INE    = IN_BITS(IOPORTA),
+            .PU     = IN_BITS(IOPORTA),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTA, 0),
+            .CFG[1] = AF_BITS(IOPORTA, 1),
+        },
+    // GPIO B
+    .setup[1] =
+        {
+            .DIR    = OUT_BITS(IOPORTB),
+            .INE    = IN_BITS(IOPORTB),
+            .PU     = IN_BITS(IOPORTB),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTB, 0),
+            .CFG[1] = AF_BITS(IOPORTB, 1),
+        },
+    // GPIO C
+    .setup[2] =
+        {
+            .DIR    = OUT_BITS(IOPORTC),
+            .INE    = IN_BITS(IOPORTC),
+            .PU     = IN_BITS(IOPORTC),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTC, 0),
+            .CFG[1] = AF_BITS(IOPORTC, 1),
+        },
+    // GPIO D
+    .setup[3] =
+        {
+            .DIR    = OUT_BITS(IOPORTD),
+            .INE    = IN_BITS(IOPORTD),
+            .PU     = IN_BITS(IOPORTD),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTD, 0),
+            .CFG[1] = AF_BITS(IOPORTD, 1),
+        },
+    .ESSR[0] = 0x00000000,
+    .ESSR[1] = 0x00000000,
+};
+
+void __early_init(void) { ht32_clock_init(); }
+
+void boardInit(void) {}
diff --git a/keyboards/annepro2/boards/ANNEPRO2_C15/board.h b/keyboards/annepro2/boards/ANNEPRO2_C15/board.h
new file mode 100644
index 0000000000..0a044ea181
--- /dev/null
+++ b/keyboards/annepro2/boards/ANNEPRO2_C15/board.h
@@ -0,0 +1,39 @@
+/*
+    ChibiOS - Copyright (C) 2020 Codetector <codetector@codetector.cn>
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+#pragma once
+/*
+ * Setup for Anne Pro 2 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_NAME "Anne Pro 2"
+
+#define HT32F52342
+
+#define FLASH_SIZE (0x10000 - 0x4000)  // 64kB - 16kB
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
\ No newline at end of file
diff --git a/keyboards/annepro2/boards/ANNEPRO2_C15/board.mk b/keyboards/annepro2/boards/ANNEPRO2_C15/board.mk
new file mode 100644
index 0000000000..f308892e7c
--- /dev/null
+++ b/keyboards/annepro2/boards/ANNEPRO2_C15/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = $(BOARD_PATH)/boards/ANNEPRO2_C15/board.c
+
+# Required include directories
+BOARDINC = $(BOARD_PATH)/boards/ANNEPRO2_C15
diff --git a/keyboards/annepro2/boards/ANNEPRO2_C18/board.c b/keyboards/annepro2/boards/ANNEPRO2_C18/board.c
new file mode 100644
index 0000000000..42c03d3d00
--- /dev/null
+++ b/keyboards/annepro2/boards/ANNEPRO2_C18/board.c
@@ -0,0 +1,103 @@
+/*
+    Copyright (C) 2020 Yaotian Feng, Codetector<codetector@codetector.cn>
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+#include "hal.h"
+
+/* ============ Private Defines ===================== */
+
+/* ============ Function Prototypes ================== */
+
+#define PBIT(PORT, LINE) ((PAL_PORT(LINE) == PORT) ? (1 << PAL_PAD(LINE)) : 0)
+#define PAFIO_L(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) < 8)) ? (AF << (PAL_PAD(LINE) << 2)) : 0)
+#define PAFIO_H(PORT, LINE, AF) (((PAL_PORT(LINE) == PORT) && (PAL_PAD(LINE) >= 8)) ? (AF << ((PAL_PAD(LINE) - 8) << 2)) : 0)
+#define PAFIO(PORT, N, LINE, AF) ((N) ? PAFIO_H(PORT, LINE, AF) : PAFIO_L(PORT, LINE, AF))
+
+#define OUT_BITS(PORT) (PBIT(PORT, B5) | PBIT(PORT, B4) | PBIT(PORT, B3) | PBIT(PORT, B2) | PBIT(PORT, D1) | 0)
+
+#define IN_BITS(PORT) (PBIT(PORT, C4) | PBIT(PORT, C5) | PBIT(PORT, D0) | PBIT(PORT, B15) | PBIT(PORT, C11) | PBIT(PORT, A15) | PBIT(PORT, C12) | PBIT(PORT, C13) | PBIT(PORT, A8) | PBIT(PORT, A10) | PBIT(PORT, A11) | PBIT(PORT, A14) | PBIT(PORT, D2) | PBIT(PORT, D3) | 0)
+
+// Alternate Functions
+#define AF_BITS(PORT, N) (PAFIO(PORT, N, LINE_UART_RX, AFIO_USART) | PAFIO(PORT, N, LINE_UART_TX, AFIO_USART) | PAFIO(PORT, N, LINE_BT_UART_TX, AFIO_USART) | PAFIO(PORT, N, LINE_BT_UART_RX, AFIO_USART) | PAFIO(PORT, N, B5, AFIO_GPIO) | PAFIO(PORT, N, B4, AFIO_GPIO) | PAFIO(PORT, N, B3, AFIO_GPIO) | PAFIO(PORT, N, B2, AFIO_GPIO) | PAFIO(PORT, N, D1, AFIO_GPIO) | PAFIO(PORT, N, C4, AFIO_GPIO) | PAFIO(PORT, N, C5, AFIO_GPIO) | PAFIO(PORT, N, D0, AFIO_GPIO) | PAFIO(PORT, N, B15, AFIO_GPIO) | PAFIO(PORT, N, C11, AFIO_GPIO) | PAFIO(PORT, N, A15, AFIO_GPIO) | PAFIO(PORT, N, C12, AFIO_GPIO) | PAFIO(PORT, N, C13, AFIO_GPIO) | PAFIO(PORT, N, A8, AFIO_GPIO) | PAFIO(PORT, N, A10, AFIO_GPIO) | PAFIO(PORT, N, A11, AFIO_GPIO) | PAFIO(PORT, N, A14, AFIO_GPIO) | PAFIO(PORT, N, D2, AFIO_GPIO) | PAFIO(PORT, N, D3, AFIO_GPIO) | 0)
+
+/**
+ * @brief   PAL setup.
+ * @details Digital I/O ports static configuration as defined in @p board.h.
+ *          This variable is used by the HAL when initializing the PAL driver.
+ */
+const PALConfig pal_default_config = {
+    // GPIO A
+    .setup[0] =
+        {
+            .DIR    = OUT_BITS(IOPORTA),
+            .INE    = IN_BITS(IOPORTA),
+            .PU     = IN_BITS(IOPORTA),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTA, 0),
+            .CFG[1] = AF_BITS(IOPORTA, 1),
+        },
+    // GPIO B
+    .setup[1] =
+        {
+            .DIR    = OUT_BITS(IOPORTB),
+            .INE    = IN_BITS(IOPORTB),
+            .PU     = IN_BITS(IOPORTB),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTB, 0),
+            .CFG[1] = AF_BITS(IOPORTB, 1),
+        },
+    // GPIO C
+    .setup[2] =
+        {
+            .DIR    = OUT_BITS(IOPORTC),
+            .INE    = IN_BITS(IOPORTC),
+            .PU     = IN_BITS(IOPORTC),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTC, 0),
+            .CFG[1] = AF_BITS(IOPORTC, 1),
+        },
+    // GPIO D
+    .setup[3] =
+        {
+            .DIR    = OUT_BITS(IOPORTD),
+            .INE    = IN_BITS(IOPORTD),
+            .PU     = IN_BITS(IOPORTD),
+            .PD     = 0x0000,
+            .OD     = 0x0000,
+            .DRV    = 0x0000,
+            .LOCK   = 0x0000,
+            .OUT    = 0x0000,
+            .CFG[0] = AF_BITS(IOPORTD, 0),
+            .CFG[1] = AF_BITS(IOPORTD, 1),
+        },
+    .ESSR[0] = 0x00000000,
+    .ESSR[1] = 0x00000000,
+};
+
+void __early_init(void) { ht32_clock_init(); }
+
+void boardInit(void) {}
diff --git a/keyboards/annepro2/boards/ANNEPRO2_C18/board.h b/keyboards/annepro2/boards/ANNEPRO2_C18/board.h
new file mode 100644
index 0000000000..7345b24231
--- /dev/null
+++ b/keyboards/annepro2/boards/ANNEPRO2_C18/board.h
@@ -0,0 +1,39 @@
+/*
+    ChibiOS - Copyright (C) 2020 Codetector <codetector@codetector.cn>
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+#pragma once
+/*
+ * Setup for Anne Pro 2 board.
+ */
+
+/*
+ * Board identifier.
+ */
+#define BOARD_NAME "Anne Pro 2"
+
+#define HT32F52342
+
+#define FLASH_SIZE (0x10000 - 0x4000)  // 64kB - 16kB
+
+#if !defined(_FROM_ASM_)
+#ifdef __cplusplus
+extern "C" {
+#endif
+void boardInit(void);
+#ifdef __cplusplus
+}
+#endif
+#endif /* _FROM_ASM_ */
diff --git a/keyboards/annepro2/boards/ANNEPRO2_C18/board.mk b/keyboards/annepro2/boards/ANNEPRO2_C18/board.mk
new file mode 100644
index 0000000000..1b41dede85
--- /dev/null
+++ b/keyboards/annepro2/boards/ANNEPRO2_C18/board.mk
@@ -0,0 +1,5 @@
+# List of all the board related files.
+BOARDSRC = $(BOARD_PATH)/boards/ANNEPRO2_C18/board.c
+
+# Required include directories
+BOARDINC = $(BOARD_PATH)/boards/ANNEPRO2_C18
diff --git a/keyboards/annepro2/c15/config.h b/keyboards/annepro2/c15/config.h
new file mode 100644
index 0000000000..f28a6a1b53
--- /dev/null
+++ b/keyboards/annepro2/c15/config.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018 Charlie Waters
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "pin_defs.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xfeed
+#define PRODUCT_ID 0xac15
+#define DEVICE_VER 0x1337
+#define MANUFACTURER Obins
+#define PRODUCT Anne Pro 2 QMK
+// key matrix size
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 14
+// layer size: MATRIX_ROWS * MATRIX_COLS * sizeof(uint16_t) = 140 bytes
+
+#define LINE_UART_TX B0  // Master TX, LED RX
+#define LINE_UART_RX B1  // Master RX, LED TX
+
+#define LINE_BT_UART_TX A4  // Master TX, BLE RX
+#define LINE_BT_UART_RX A5  // Master RX, BLE TX
+
+// outputs (rows are pulled low)
+#define MATRIX_ROW_PINS \
+    { C2, C1, B5, B4, C3 }
+
+// inputs (columns are sampled)
+// PORTA 12,13 conflict with SWD
+
+#define MATRIX_COL_PINS \
+    { C4, C5, B10, B11, C0, A15, A8, A10, A11, A12, A13, A14, B2, B3 }
diff --git a/keyboards/annepro2/c15/readme.md b/keyboards/annepro2/c15/readme.md
new file mode 100644
index 0000000000..5fadb73909
--- /dev/null
+++ b/keyboards/annepro2/c15/readme.md
@@ -0,0 +1 @@
+AnnePro2, ANSI C15 version.
diff --git a/keyboards/annepro2/c15/rules.mk b/keyboards/annepro2/c15/rules.mk
new file mode 100644
index 0000000000..554ddc28ce
--- /dev/null
+++ b/keyboards/annepro2/c15/rules.mk
@@ -0,0 +1,37 @@
+# Anne Pro 2
+SRC = \
+	matrix.c \
+	annepro2_ble.c \
+	ap2_led.c \
+	protocol.c
+
+# MCU
+MCU = cortex-m0plus
+ARMV = 6
+USE_FPU = no
+MCU_FAMILY = HT32
+MCU_SERIES = HT32F523xx
+MCU_LDSCRIPT = HT32F52342_ANNEPRO2
+MCU_STARTUP = ht32f523xx
+
+BOARD = ANNEPRO2_C15
+
+# Options
+
+# Keys
+CUSTOM_MATRIX = lite
+NKRO_ENABLE = no
+MOUSEKEY_ENABLE = no
+EXTRAKEY_ENABLE = yes
+KEY_LOCK_ENABLE = no
+
+# Other featues
+BOOTMAGIC_ENABLE = no
+CONSOLE_ENABLE = no
+COMMAND_ENABLE = no
+RAW_ENABLE = no
+MIDI_ENABLE = no
+VIRTSER_ENABLE = no
+COMBO_ENABLE = no
+BOOTLOADER = custom
+PROGRAM_CMD = annepro2_tools --boot $(BUILD_DIR)/$(TARGET).bin
diff --git a/keyboards/annepro2/c18/config.h b/keyboards/annepro2/c18/config.h
new file mode 100644
index 0000000000..f610ef76e4
--- /dev/null
+++ b/keyboards/annepro2/c18/config.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018 Charlie Waters
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "pin_defs.h"
+
+/* USB Device descriptor parameter */
+#define VENDOR_ID 0xfeed
+#define PRODUCT_ID 0xac18
+#define DEVICE_VER 0x1337
+#define MANUFACTURER Obins
+#define PRODUCT Anne Pro 2(c18)QMK
+// key matrix size
+#define MATRIX_ROWS 5
+#define MATRIX_COLS 14
+// layer size: MATRIX_ROWS * MATRIX_COLS * sizeof(uint16_t) = 140 bytes
+
+#define LINE_UART_TX B0
+#define LINE_UART_RX B1
+
+#define LINE_BT_UART_TX A4  // Master TX, BLE RX
+#define LINE_BT_UART_RX A5  // Master RX, BLE TX
+
+// outputs (rows are pulled low)
+#define MATRIX_ROW_PINS \
+    { B5, B4, B3, B2, D1 }
+
+// inputs (columns are sampled)
+#define MATRIX_COL_PINS \
+    { C4, C5, D0, B15, C11, A15, C12, C13, A8, A10, A11, A14, D2, D3 }
diff --git a/keyboards/annepro2/c18/readme.md b/keyboards/annepro2/c18/readme.md
new file mode 100644
index 0000000000..f2e2fc45b8
--- /dev/null
+++ b/keyboards/annepro2/c18/readme.md
@@ -0,0 +1 @@
+AnnePro2, ANSI C18 version.
diff --git a/keyboards/annepro2/c18/rules.mk b/keyboards/annepro2/c18/rules.mk
new file mode 100644
index 0000000000..b2e16cc35f
--- /dev/null
+++ b/keyboards/annepro2/c18/rules.mk
@@ -0,0 +1,37 @@
+# Anne Pro 2
+SRC = \
+	matrix.c \
+	annepro2_ble.c \
+	ap2_led.c \
+	protocol.c
+
+# MCU
+MCU = cortex-m0plus
+ARMV = 6
+USE_FPU = no
+MCU_FAMILY = HT32
+MCU_SERIES = HT32F523xx
+MCU_LDSCRIPT = HT32F52342_ANNEPRO2
+MCU_STARTUP = ht32f523xx
+
+BOARD = ANNEPRO2_C18
+
+# Options
+
+# Keys
+CUSTOM_MATRIX = lite
+NKRO_ENABLE = no
+MOUSEKEY_ENABLE = no
+EXTRAKEY_ENABLE = yes
+KEY_LOCK_ENABLE = no
+
+# Other featues
+BOOTMAGIC_ENABLE = yes
+CONSOLE_ENABLE = no
+COMMAND_ENABLE = no
+RAW_ENABLE = no
+MIDI_ENABLE = no
+VIRTSER_ENABLE = no
+COMBO_ENABLE = no
+BOOTLOADER = custom
+PROGRAM_CMD = annepro2_tools --boot $(BUILD_DIR)/$(TARGET).bin
diff --git a/keyboards/annepro2/chconf.h b/keyboards/annepro2/chconf.h
new file mode 100644
index 0000000000..51fe38cf27
--- /dev/null
+++ b/keyboards/annepro2/chconf.h
@@ -0,0 +1,31 @@
+/* Copyright 2020 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This file was auto-generated by:
+ *    `qmk chibios-confmigrate -i keyboards/annepro2/chconf.h -r platforms/chibios/common/configs/chconf.h`
+ */
+
+#pragma once
+
+#define CH_CFG_ST_FREQUENCY 1000
+
+#define CH_CFG_ST_TIMEDELTA 0
+
+#define CH_CFG_TIME_QUANTUM 20
+
+
+#include_next <chconf.h>
\ No newline at end of file
diff --git a/keyboards/annepro2/halconf.h b/keyboards/annepro2/halconf.h
new file mode 100644
index 0000000000..686b91a7fb
--- /dev/null
+++ b/keyboards/annepro2/halconf.h
@@ -0,0 +1,28 @@
+/* Copyright 2020 QMK
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * This file was auto-generated by:
+ *    `qmk chibios-confmigrate -i keyboards/annepro2/halconf.h -r platforms/chibios/common/configs/halconf.h`
+ */
+
+#pragma once
+
+#define HAL_USE_SERIAL TRUE
+
+#define SERIAL_USB_BUFFERS_SIZE 256
+
+#include_next <halconf.h>
diff --git a/keyboards/annepro2/info.json b/keyboards/annepro2/info.json
new file mode 100644
index 0000000000..8fd515bd10
--- /dev/null
+++ b/keyboards/annepro2/info.json
@@ -0,0 +1,330 @@
+{
+    "keyboard_name": "Anne Pro 2",
+    "url": "https://openannepro.github.io/",
+    "maintainer": "community",
+    "layouts": {
+        "LAYOUT": {
+            "layout": [
+                {
+                    "label": "~",
+                    "x": 0,
+                    "y": 0
+                },
+                {
+                    "label": "!",
+                    "x": 1,
+                    "y": 0
+                },
+                {
+                    "label": "@",
+                    "x": 2,
+                    "y": 0
+                },
+                {
+                    "label": "#",
+                    "x": 3,
+                    "y": 0
+                },
+                {
+                    "label": "$",
+                    "x": 4,
+                    "y": 0
+                },
+                {
+                    "label": "%",
+                    "x": 5,
+                    "y": 0
+                },
+                {
+                    "label": "^",
+                    "x": 6,
+                    "y": 0
+                },
+                {
+                    "label": "&",
+                    "x": 7,
+                    "y": 0
+                },
+                {
+                    "label": "*",
+                    "x": 8,
+                    "y": 0
+                },
+                {
+                    "label": "(",
+                    "x": 9,
+                    "y": 0
+                },
+                {
+                    "label": ")",
+                    "x": 10,
+                    "y": 0
+                },
+                {
+                    "label": "_",
+                    "x": 11,
+                    "y": 0
+                },
+                {
+                    "label": "+",
+                    "x": 12,
+                    "y": 0
+                },
+                {
+                    "label": "Backspace",
+                    "x": 13,
+                    "y": 0,
+                    "w": 2
+                },
+                {
+                    "label": "Tab",
+                    "x": 0,
+                    "y": 1,
+                    "w": 1.5
+                },
+                {
+                    "label": "Q",
+                    "x": 1.5,
+                    "y": 1
+                },
+                {
+                    "label": "W",
+                    "x": 2.5,
+                    "y": 1
+                },
+                {
+                    "label": "E",
+                    "x": 3.5,
+                    "y": 1
+                },
+                {
+                    "label": "R",
+                    "x": 4.5,
+                    "y": 1
+                },
+                {
+                    "label": "T",
+                    "x": 5.5,
+                    "y": 1
+                },
+                {
+                    "label": "Y",
+                    "x": 6.5,
+                    "y": 1
+                },
+                {
+                    "label": "U",
+                    "x": 7.5,
+                    "y": 1
+                },
+                {
+                    "label": "I",
+                    "x": 8.5,
+                    "y": 1
+                },
+                {
+                    "label": "O",
+                    "x": 9.5,
+                    "y": 1
+                },
+                {
+                    "label": "P",
+                    "x": 10.5,
+                    "y": 1
+                },
+                {
+                    "label": "{",
+                    "x": 11.5,
+                    "y": 1
+                },
+                {
+                    "label": "}",
+                    "x": 12.5,
+                    "y": 1
+                },
+                {
+                    "label": "|",
+                    "x": 13.5,
+                    "y": 1,
+                    "w": 1.5
+                },
+                {
+                    "label": "Caps Lock",
+                    "x": 0,
+                    "y": 2,
+                    "w": 1.75
+                },
+                {
+                    "label": "A",
+                    "x": 1.75,
+                    "y": 2
+                },
+                {
+                    "label": "S",
+                    "x": 2.75,
+                    "y": 2
+                },
+                {
+                    "label": "D",
+                    "x": 3.75,
+                    "y": 2
+                },
+                {
+                    "label": "F",
+                    "x": 4.75,
+                    "y": 2
+                },
+                {
+                    "label": "G",
+                    "x": 5.75,
+                    "y": 2
+                },
+                {
+                    "label": "H",
+                    "x": 6.75,
+                    "y": 2
+                },
+                {
+                    "label": "J",
+                    "x": 7.75,
+                    "y": 2
+                },
+                {
+                    "label": "K",
+                    "x": 8.75,
+                    "y": 2
+                },
+                {
+                    "label": "L",
+                    "x": 9.75,
+                    "y": 2
+                },
+                {
+                    "label": ":",
+                    "x": 10.75,
+                    "y": 2
+                },
+                {
+                    "label": "\"",
+                    "x": 11.75,
+                    "y": 2
+                },
+                {
+                    "label": "Enter",
+                    "x": 12.75,
+                    "y": 2,
+                    "w": 2.25
+                },
+                {
+                    "label": "Shift",
+                    "x": 0,
+                    "y": 3,
+                    "w": 2.25
+                },
+                {
+                    "label": "Z",
+                    "x": 2.25,
+                    "y": 3
+                },
+                {
+                    "label": "X",
+                    "x": 3.25,
+                    "y": 3
+                },
+                {
+                    "label": "C",
+                    "x": 4.25,
+                    "y": 3
+                },
+                {
+                    "label": "V",
+                    "x": 5.25,
+                    "y": 3
+                },
+                {
+                    "label": "B",
+                    "x": 6.25,
+                    "y": 3
+                },
+                {
+                    "label": "N",
+                    "x": 7.25,
+                    "y": 3
+                },
+                {
+                    "label": "M",
+                    "x": 8.25,
+                    "y": 3
+                },
+                {
+                    "label": "<",
+                    "x": 9.25,
+                    "y": 3
+                },
+                {
+                    "label": ">",
+                    "x": 10.25,
+                    "y": 3
+                },
+                {
+                    "label": "?",
+                    "x": 11.25,
+                    "y": 3
+                },
+                {
+                    "label": "Shift",
+                    "x": 12.25,
+                    "y": 3,
+                    "w": 2.75
+                },
+                {
+                    "label": "Ctrl",
+                    "x": 0,
+                    "y": 4,
+                    "w": 1.25
+                },
+                {
+                    "label": "Win",
+                    "x": 1.25,
+                    "y": 4,
+                    "w": 1.25
+                },
+                {
+                    "label": "Alt",
+                    "x": 2.5,
+                    "y": 4,
+                    "w": 1.25
+                },
+                {
+                    "x": 3.75,
+                    "y": 4,
+                    "w": 6.25
+                },
+                {
+                    "label": "Alt",
+                    "x": 10,
+                    "y": 4,
+                    "w": 1.25
+                },
+                {
+                    "label": "Win",
+                    "x": 11.25,
+                    "y": 4,
+                    "w": 1.25
+                },
+                {
+                    "label": "Menu",
+                    "x": 12.5,
+                    "y": 4,
+                    "w": 1.25
+                },
+                {
+                    "label": "Ctrl",
+                    "x": 13.75,
+                    "y": 4,
+                    "w": 1.25
+                }
+            ]
+        }
+    }
+}
diff --git a/keyboards/annepro2/keymaps/default-full-caps/config.h b/keyboards/annepro2/keymaps/default-full-caps/config.h
new file mode 100644
index 0000000000..413c5d8dc5
--- /dev/null
+++ b/keyboards/annepro2/keymaps/default-full-caps/config.h
@@ -0,0 +1,20 @@
+ /* Copyright 2021 OpenAnnePro community
+  * 
+  * This program is free software: you can redistribute it and/or modify 
+  * it under the terms of the GNU General Public License as published by 
+  * the Free Software Foundation, either version 2 of the License, or 
+  * (at your option) any later version. 
+  * 
+  * This program is distributed in the hope that it will be useful, 
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+  * GNU General Public License for more details. 
+  * 
+  * You should have received a copy of the GNU General Public License 
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+  */ 
+  
+#pragma once
+
+// Obins stock firmware has something similar to this already enabled, but disabled by default in QMK
+#define PERMISSIVE_HOLD
diff --git a/keyboards/annepro2/keymaps/default-full-caps/keymap.c b/keyboards/annepro2/keymaps/default-full-caps/keymap.c
new file mode 100644
index 0000000000..8ac9211ac4
--- /dev/null
+++ b/keyboards/annepro2/keymaps/default-full-caps/keymap.c
@@ -0,0 +1,120 @@
+ /* Copyright 2021 OpenAnnePro community
+  * 
+  * This program is free software: you can redistribute it and/or modify 
+  * it under the terms of the GNU General Public License as published by 
+  * the Free Software Foundation, either version 2 of the License, or 
+  * (at your option) any later version. 
+  * 
+  * This program is distributed in the hope that it will be useful, 
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+  * GNU General Public License for more details. 
+  * 
+  * You should have received a copy of the GNU General Public License 
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+  */ 
+
+#include QMK_KEYBOARD_H
+
+enum anne_pro_layers {
+    _BASE_LAYER,
+    _FN1_LAYER,
+    _FN2_LAYER,
+};
+
+// clang-format off
+
+// Key symbols are based on QMK. Use them to remap your keyboard
+/*
+* Layer _BASE_LAYER
+* ,-----------------------------------------------------------------------------------------.
+* | esc |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  0  |  -  |  =  |    Bksp   |
+* |-----------------------------------------------------------------------------------------+
+* | Tab    |  q  |  w  |  e  |  r  |  t  |  y  |  u  |  i  |  o  |  p  |  [  |  ]  |   \    |
+* |-----------------------------------------------------------------------------------------+
+* | Caps    |  a  |  s  |  d  |  f  |  g  |  h  |  j  |  k  |  l  |  ;  |  '  |    Enter    |
+* |-----------------------------------------------------------------------------------------+
+* | Shift      |  z  |  x  |  c  |  v  |  b  |  n  |  m  |  ,  |  .  |  /  |    Shift       |
+* |-----------------------------------------------------------------------------------------+
+* | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+* \-----------------------------------------------------------------------------------------/
+* Layer TAP in _BASE_LAYER
+* ,-----------------------------------------------------------------------------------------.
+* |     |     |     |     |     |     |     |     |     |     |     |     |     |           |
+* |-----------------------------------------------------------------------------------------+
+* |        |     |     |     |     |     |     |     |     |     |     |     |     |        |
+* |-----------------------------------------------------------------------------------------+
+* |         |     |     |     |     |     |     |     |     |     |     |     |             |
+* |-----------------------------------------------------------------------------------------+
+* |            |     |     |     |     |     |     |     |     |     |     |       UP       |
+* |-----------------------------------------------------------------------------------------+
+* |       |       |       |                                 |       |  LEFT | DOWN  | RIGHT |
+* \-----------------------------------------------------------------------------------------/
+*/
+ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_BASE_LAYER] = LAYOUT( /* Base */
+    KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
+    KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
+    LT(_FN1_LAYER,KC_CAPS), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
+    KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, RSFT_T(KC_UP),
+    KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, LT(_FN1_LAYER,KC_LEFT), LT(_FN2_LAYER,KC_DOWN), RCTL_T(KC_RGHT)
+),
+  /*
+  * Layer _FN1_LAYER
+  * ,-----------------------------------------------------------------------------------------.
+  * |  `  |  F1 |  F2 |  F3 |  F4 |  F5 |  F6 |  F7 |  F8 |  F9 | F10 | F11 | F12 |  DELETE   |
+  * |-----------------------------------------------------------------------------------------+
+  * | Tab    |  q  | UP  |  e  |  r  |  t  |  y  |  u  |  i  |  o  | PS | HOME | END |   \    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Esc     |LEFT |DOWN |RIGHT|  f  |  g  |  h  |  j  |  k  |  l  | PGUP|PGDN |    Enter    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Shift      |V-UP |V-DWN|MUTE |  v  |  b  |  n  |  m  |  ,  |INSRT| DEL |    Shift       |
+  * |-----------------------------------------------------------------------------------------+
+  * | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+  * \-----------------------------------------------------------------------------------------/
+  *
+  */
+ [_FN1_LAYER] = LAYOUT( /* Base */
+    KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL,
+    KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
+    KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
+    KC_TRNS, KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN2_LAYER), KC_TRNS
+),
+  /*
+  * Layer _FN2_LAYER
+  * ,-----------------------------------------------------------------------------------------.
+  * |  ~  | BT1 | BT2 | BT3 | BT4 |  F5 |  F6 |  F7 |LEDOF|LEDON| F10 | F11 | F12 |    Bksp   |
+  * |-----------------------------------------------------------------------------------------+
+  * | Tab    |  q  | UP  |  e  |  r  |  t  |  y  |  u  |  i  |  o  | PS | HOME | END |   \    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Esc     |LEFT |DOWN |RIGHT|  f  |  g  |  h  |  j  |  k  |  l  | PGUP|PGDN |    Enter    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Shift      |  z  |  x  |  c  |  v  |  b  |  n  |  m  |  ,  |INSRT| DEL |    Shift       |
+  * |-----------------------------------------------------------------------------------------+
+  * | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+  * \-----------------------------------------------------------------------------------------/
+  *
+  */
+ [_FN2_LAYER] = LAYOUT( /* Base */
+    KC_TRNS, KC_AP2_BT1, KC_AP2_BT2, KC_AP2_BT3, KC_AP2_BT4, KC_TRNS, KC_TRNS, KC_TRNS, KC_AP_LED_OFF, KC_AP_LED_ON, KC_AP_LED_NEXT_INTENSITY, KC_AP_LED_SPEED, KC_TRNS, KC_TRNS,
+    MO(_FN2_LAYER), KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
+    KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN1_LAYER), MO(_FN2_LAYER), KC_TRNS
+ ),
+};
+
+// clang-format on
+
+// The function to handle the caps lock logic
+bool led_update_user(led_t leds) {
+    if (leds.caps_lock) {
+        // Set the leds to red
+        annepro2LedSetForegroundColor(0xFF, 0x00, 0x00);
+    } else {
+        annepro2LedResetForegroundColor();
+    }
+
+    return true;
+}
diff --git a/keyboards/annepro2/keymaps/default-layer-indicators/config.h b/keyboards/annepro2/keymaps/default-layer-indicators/config.h
new file mode 100644
index 0000000000..413c5d8dc5
--- /dev/null
+++ b/keyboards/annepro2/keymaps/default-layer-indicators/config.h
@@ -0,0 +1,20 @@
+ /* Copyright 2021 OpenAnnePro community
+  * 
+  * This program is free software: you can redistribute it and/or modify 
+  * it under the terms of the GNU General Public License as published by 
+  * the Free Software Foundation, either version 2 of the License, or 
+  * (at your option) any later version. 
+  * 
+  * This program is distributed in the hope that it will be useful, 
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+  * GNU General Public License for more details. 
+  * 
+  * You should have received a copy of the GNU General Public License 
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+  */ 
+  
+#pragma once
+
+// Obins stock firmware has something similar to this already enabled, but disabled by default in QMK
+#define PERMISSIVE_HOLD
diff --git a/keyboards/annepro2/keymaps/default-layer-indicators/keymap.c b/keyboards/annepro2/keymaps/default-layer-indicators/keymap.c
new file mode 100644
index 0000000000..ac2b421d06
--- /dev/null
+++ b/keyboards/annepro2/keymaps/default-layer-indicators/keymap.c
@@ -0,0 +1,147 @@
+ /* Copyright 2021 OpenAnnePro community
+  * 
+  * This program is free software: you can redistribute it and/or modify 
+  * it under the terms of the GNU General Public License as published by 
+  * the Free Software Foundation, either version 2 of the License, or 
+  * (at your option) any later version. 
+  * 
+  * This program is distributed in the hope that it will be useful, 
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+  * GNU General Public License for more details. 
+  * 
+  * You should have received a copy of the GNU General Public License 
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+  */ 
+
+#include QMK_KEYBOARD_H
+
+enum anne_pro_layers {
+    _BASE_LAYER,
+    _FN1_LAYER,
+    _FN2_LAYER,
+};
+
+// clang-format off
+
+// Key symbols are based on QMK. Use them to remap your keyboard
+/*
+* Layer _BASE_LAYER
+* ,-----------------------------------------------------------------------------------------.
+* | esc |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  0  |  -  |  =  |    Bksp   |
+* |-----------------------------------------------------------------------------------------+
+* | Tab    |  q  |  w  |  e  |  r  |  t  |  y  |  u  |  i  |  o  |  p  |  [  |  ]  |   \    |
+* |-----------------------------------------------------------------------------------------+
+* | Caps    |  a  |  s  |  d  |  f  |  g  |  h  |  j  |  k  |  l  |  ;  |  '  |    Enter    |
+* |-----------------------------------------------------------------------------------------+
+* | Shift      |  z  |  x  |  c  |  v  |  b  |  n  |  m  |  ,  |  .  |  /  |    Shift       |
+* |-----------------------------------------------------------------------------------------+
+* | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+* \-----------------------------------------------------------------------------------------/
+* Layer TAP in _BASE_LAYER
+* ,-----------------------------------------------------------------------------------------.
+* |     |     |     |     |     |     |     |     |     |     |     |     |     |           |
+* |-----------------------------------------------------------------------------------------+
+* |        |     |     |     |     |     |     |     |     |     |     |     |     |        |
+* |-----------------------------------------------------------------------------------------+
+* |         |     |     |     |     |     |     |     |     |     |     |     |             |
+* |-----------------------------------------------------------------------------------------+
+* |            |     |     |     |     |     |     |     |     |     |     |       UP       |
+* |-----------------------------------------------------------------------------------------+
+* |       |       |       |                                 |       |  LEFT | DOWN  | RIGHT |
+* \-----------------------------------------------------------------------------------------/
+*/
+ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_BASE_LAYER] = LAYOUT( /* Base */
+    KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
+    KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
+    LT(_FN1_LAYER,KC_CAPS), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
+    KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, RSFT_T(KC_UP),
+    KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, LT(_FN1_LAYER,KC_LEFT), LT(_FN2_LAYER,KC_DOWN), RCTL_T(KC_RGHT)
+),
+  /*
+  * Layer _FN1_LAYER
+  * ,-----------------------------------------------------------------------------------------.
+  * |  `  |  F1 |  F2 |  F3 |  F4 |  F5 |  F6 |  F7 |  F8 |  F9 | F10 | F11 | F12 |  DELETE   |
+  * |-----------------------------------------------------------------------------------------+
+  * | Tab    |  q  | UP  |  e  |  r  |  t  |  y  |  u  |  i  |  o  | PS | HOME | END |   \    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Esc     |LEFT |DOWN |RIGHT|  f  |  g  |  h  |  j  |  k  |  l  | PGUP|PGDN |    Enter    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Shift      |V-UP |V-DWN|MUTE |  v  |  b  |  n  |  m  |  ,  |INSRT| DEL |    Shift       |
+  * |-----------------------------------------------------------------------------------------+
+  * | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+  * \-----------------------------------------------------------------------------------------/
+  *
+  */
+ [_FN1_LAYER] = LAYOUT( /* Base */
+    KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL,
+    KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
+    KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
+    KC_TRNS, KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN2_LAYER), KC_TRNS
+),
+  /*
+  * Layer _FN2_LAYER
+  * ,-----------------------------------------------------------------------------------------.
+  * |  ~  | BT1 | BT2 | BT3 | BT4 |  F5 |  F6 |  F7 |LEDOF|LEDON| F10 | F11 | F12 |    Bksp   |
+  * |-----------------------------------------------------------------------------------------+
+  * | Tab    |  q  | UP  |  e  |  r  |  t  |  y  |  u  |  i  |  o  | PS | HOME | END |   \    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Esc     |LEFT |DOWN |RIGHT|  f  |  g  |  h  |  j  |  k  |  l  | PGUP|PGDN |    Enter    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Shift      |  z  |  x  |  c  |  v  |  b  |  n  |  m  |  ,  |INSRT| DEL |    Shift       |
+  * |-----------------------------------------------------------------------------------------+
+  * | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+  * \-----------------------------------------------------------------------------------------/
+  *
+  */
+ [_FN2_LAYER] = LAYOUT( /* Base */
+    KC_TRNS, KC_AP2_BT1, KC_AP2_BT2, KC_AP2_BT3, KC_AP2_BT4, KC_TRNS, KC_TRNS, KC_TRNS, KC_AP_LED_OFF, KC_AP_LED_ON, KC_AP_LED_NEXT_INTENSITY, KC_AP_LED_SPEED, KC_TRNS, KC_TRNS,
+    MO(_FN2_LAYER), KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
+    KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN1_LAYER), MO(_FN2_LAYER), KC_TRNS
+ ),
+};
+
+// clang-format on
+
+layer_state_t layer_state_set_user(layer_state_t state) {
+    switch (get_highest_layer(state)) {
+        case _FN1_LAYER:
+            // Set the leds to green
+            annepro2LedSetForegroundColor(0x00, 0xFF, 0x00);
+            break;
+        case _FN2_LAYER:
+            // Set the leds to blue
+            annepro2LedSetForegroundColor(0x00, 0x00, 0xFF);
+            break;
+        default:
+            // Reset back to the current profile
+            annepro2LedResetForegroundColor();
+            break;
+    }
+    return state;
+}
+
+// The function to handle the caps lock logic
+// It's called after the capslock changes state or after entering layers 1 and 2.
+bool led_update_user(led_t leds) {
+    if (leds.caps_lock) {
+        // Set the caps-lock to red
+        const annepro2Led_t color = {.p.red = 0xff, .p.green = 0x00, .p.blue = 0x00, .p.alpha = 0xff};
+
+        annepro2LedMaskSetKey(2, 0, color);
+        /* NOTE: Instead of colouring the capslock only, you can change the whole
+           keyboard with annepro2LedSetForegroundColor */
+    } else {
+        // Reset the capslock if there is no layer active
+        if (!layer_state_is(_FN1_LAYER) && !layer_state_is(_FN2_LAYER)) {
+            const annepro2Led_t color = {.p.red = 0xff, .p.green = 0x00, .p.blue = 0x00, .p.alpha = 0x00};
+            annepro2LedMaskSetKey(2, 0, color);
+        }
+    }
+
+    return true;
+}
diff --git a/keyboards/annepro2/keymaps/default/config.h b/keyboards/annepro2/keymaps/default/config.h
new file mode 100644
index 0000000000..413c5d8dc5
--- /dev/null
+++ b/keyboards/annepro2/keymaps/default/config.h
@@ -0,0 +1,20 @@
+ /* Copyright 2021 OpenAnnePro community
+  * 
+  * This program is free software: you can redistribute it and/or modify 
+  * it under the terms of the GNU General Public License as published by 
+  * the Free Software Foundation, either version 2 of the License, or 
+  * (at your option) any later version. 
+  * 
+  * This program is distributed in the hope that it will be useful, 
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+  * GNU General Public License for more details. 
+  * 
+  * You should have received a copy of the GNU General Public License 
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+  */ 
+  
+#pragma once
+
+// Obins stock firmware has something similar to this already enabled, but disabled by default in QMK
+#define PERMISSIVE_HOLD
diff --git a/keyboards/annepro2/keymaps/default/keymap.c b/keyboards/annepro2/keymaps/default/keymap.c
new file mode 100644
index 0000000000..a984b05830
--- /dev/null
+++ b/keyboards/annepro2/keymaps/default/keymap.c
@@ -0,0 +1,106 @@
+ /* Copyright 2021 OpenAnnePro community
+  * 
+  * This program is free software: you can redistribute it and/or modify 
+  * it under the terms of the GNU General Public License as published by 
+  * the Free Software Foundation, either version 2 of the License, or 
+  * (at your option) any later version. 
+  * 
+  * This program is distributed in the hope that it will be useful, 
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+  * GNU General Public License for more details. 
+  * 
+  * You should have received a copy of the GNU General Public License 
+  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
+  */ 
+
+#include QMK_KEYBOARD_H
+
+enum anne_pro_layers {
+    _BASE_LAYER,
+    _FN1_LAYER,
+    _FN2_LAYER,
+};
+
+// clang-format off
+// Key symbols are based on QMK. Use them to remap your keyboard
+/*
+* Layer _BASE_LAYER
+* ,-----------------------------------------------------------------------------------------.
+* | esc |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |  0  |  -  |  =  |    Bksp   |
+* |-----------------------------------------------------------------------------------------+
+* | Tab    |  q  |  w  |  e  |  r  |  t  |  y  |  u  |  i  |  o  |  p  |  [  |  ]  |   \    |
+* |-----------------------------------------------------------------------------------------+
+* | Caps    |  a  |  s  |  d  |  f  |  g  |  h  |  j  |  k  |  l  |  ;  |  '  |    Enter    |
+* |-----------------------------------------------------------------------------------------+
+* | Shift      |  z  |  x  |  c  |  v  |  b  |  n  |  m  |  ,  |  .  |  /  |    Shift       |
+* |-----------------------------------------------------------------------------------------+
+* | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+* \-----------------------------------------------------------------------------------------/
+* Layer TAP in _BASE_LAYER
+* ,-----------------------------------------------------------------------------------------.
+* |     |     |     |     |     |     |     |     |     |     |     |     |     |           |
+* |-----------------------------------------------------------------------------------------+
+* |        |     |     |     |     |     |     |     |     |     |     |     |     |        |
+* |-----------------------------------------------------------------------------------------+
+* |         |     |     |     |     |     |     |     |     |     |     |     |             |
+* |-----------------------------------------------------------------------------------------+
+* |            |     |     |     |     |     |     |     |     |     |     |       UP       |
+* |-----------------------------------------------------------------------------------------+
+* |       |       |       |                                 |       |  LEFT | DOWN  | RIGHT |
+* \-----------------------------------------------------------------------------------------/
+*/
+ const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+ [_BASE_LAYER] = LAYOUT( /* Base */
+    KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
+    KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
+    LT(_FN1_LAYER,KC_CAPS), KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
+    KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, RSFT_T(KC_UP),
+    KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, LT(_FN1_LAYER,KC_LEFT), LT(_FN2_LAYER,KC_DOWN), RCTL_T(KC_RGHT)
+),
+  /*
+  * Layer _FN1_LAYER
+  * ,-----------------------------------------------------------------------------------------.
+  * |  `  |  F1 |  F2 |  F3 |  F4 |  F5 |  F6 |  F7 |  F8 |  F9 | F10 | F11 | F12 |  DELETE   |
+  * |-----------------------------------------------------------------------------------------+
+  * | Tab    |  q  | UP  |  e  |  r  |  t  |  y  |  u  |  i  |  o  | PS | HOME | END |   \    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Esc     |LEFT |DOWN |RIGHT|  f  |  g  |  h  |  j  |  k  |  l  | PGUP|PGDN |    Enter    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Shift      |V-UP |V-DWN|MUTE |  v  |  b  |  n  |  m  |  ,  |INSRT| DEL |    Shift       |
+  * |-----------------------------------------------------------------------------------------+
+  * | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+  * \-----------------------------------------------------------------------------------------/
+  *
+  */
+ [_FN1_LAYER] = LAYOUT( /* Base */
+    KC_GRV, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL,
+    KC_TRNS, KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
+    KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
+    KC_TRNS, KC_VOLU, KC_VOLD, KC_MUTE, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN2_LAYER), KC_TRNS
+),
+  /*
+  * Layer _FN2_LAYER
+  * ,-----------------------------------------------------------------------------------------.
+  * |  ~  | BT1 | BT2 | BT3 | BT4 |  F5 |  F6 |  F7 |LEDOF|LEDON| F10 | F11 | F12 |    Bksp   |
+  * |-----------------------------------------------------------------------------------------+
+  * | Tab    |  q  | UP  |  e  |  r  |  t  |  y  |  u  |  i  |  o  | PS | HOME | END |   \    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Esc     |LEFT |DOWN |RIGHT|  f  |  g  |  h  |  j  |  k  |  l  | PGUP|PGDN |    Enter    |
+  * |-----------------------------------------------------------------------------------------+
+  * | Shift      |  z  |  x  |  c  |  v  |  b  |  n  |  m  |  ,  |INSRT| DEL |    Shift       |
+  * |-----------------------------------------------------------------------------------------+
+  * | Ctrl  |  L1   |  Alt  |               space             |  Alt  |  FN1  |  FN2  | Ctrl  |
+  * \-----------------------------------------------------------------------------------------/
+  *
+  */
+ [_FN2_LAYER] = LAYOUT( /* Base */
+    KC_TRNS, KC_AP2_BT1, KC_AP2_BT2, KC_AP2_BT3, KC_AP2_BT4, KC_TRNS, KC_TRNS, KC_TRNS, KC_AP_LED_OFF, KC_AP_LED_ON, KC_AP_LED_NEXT_INTENSITY, KC_AP_LED_SPEED, KC_TRNS, KC_TRNS,
+    MO(_FN2_LAYER), KC_TRNS, KC_UP, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PSCR, KC_HOME, KC_END, KC_TRNS,
+    KC_TRNS, KC_LEFT, KC_DOWN, KC_RGHT, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_PGUP, KC_PGDN, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_INS, KC_DEL, KC_TRNS,
+    KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, MO(_FN1_LAYER), MO(_FN2_LAYER), KC_TRNS
+ ),
+};
+// clang-format on
diff --git a/keyboards/annepro2/ld/HT32F52342_ANNEPRO2.ld b/keyboards/annepro2/ld/HT32F52342_ANNEPRO2.ld
new file mode 100644
index 0000000000..544400b948
--- /dev/null
+++ b/keyboards/annepro2/ld/HT32F52342_ANNEPRO2.ld
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013-2016 Fabio UJonathan A. Kollaschtzig, http://fabioutzig.com
+ *           (c) 2020 Yaotian Feng (Codetector) <codetector@codetector.cn>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * HT32F52342 w/ Anne Pro 2 bootloader memory setup.
+ */
+MEMORY {
+    flash0   : org = 0x00004000, len = 64k - 16k       /* firmware */
+    flash1   : org = 0x00000000, len = 0
+    flash2   : org = 0x00000000, len = 0
+    flash3   : org = 0x00000000, len = 0
+    flash4   : org = 0x00000000, len = 0
+    flash5   : org = 0x00000000, len = 0
+    flash6   : org = 0x00000000, len = 0
+    flash7   : org = 0x00000000, len = 0
+    ram0     : org = 0x20000000, len = 8k - 4          /* RAM */
+    ram1     : org = 0x00000000, len = 0
+    ram2     : org = 0x00000000, len = 0
+    ram3     : org = 0x00000000, len = 0
+    ram4     : org = 0x00000000, len = 0
+    ram5     : org = 0x00000000, len = 0
+    ram6     : org = 0x00000000, len = 0
+    ram7     : org = 0x00000000, len = 0
+}
+
+/* For each data/text section two region are defined, a virtual region
+   and a load region (_LMA suffix).*/
+
+/* Flash region to be used for exception vectors.*/
+REGION_ALIAS("VECTORS_FLASH", flash0);
+REGION_ALIAS("VECTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for constructors and destructors.*/
+REGION_ALIAS("XTORS_FLASH", flash0);
+REGION_ALIAS("XTORS_FLASH_LMA", flash0);
+
+/* Flash region to be used for code text.*/
+REGION_ALIAS("TEXT_FLASH", flash0);
+REGION_ALIAS("TEXT_FLASH_LMA", flash0);
+
+/* Flash region to be used for read only data.*/
+REGION_ALIAS("RODATA_FLASH", flash0);
+REGION_ALIAS("RODATA_FLASH_LMA", flash0);
+
+/* Flash region to be used for various.*/
+REGION_ALIAS("VARIOUS_FLASH", flash0);
+REGION_ALIAS("VARIOUS_FLASH_LMA", flash0);
+
+/* Flash region to be used for RAM(n) initialization data.*/
+REGION_ALIAS("RAM_INIT_FLASH_LMA", flash0);
+
+/* RAM region to be used for Main stack. This stack accommodates the processing
+   of all exceptions and interrupts.*/
+REGION_ALIAS("MAIN_STACK_RAM", ram0);
+
+/* RAM region to be used for the process stack. This is the stack used by
+   the main() function.*/
+REGION_ALIAS("PROCESS_STACK_RAM", ram0);
+
+/* RAM region to be used for data segment.*/
+REGION_ALIAS("DATA_RAM", ram0);
+REGION_ALIAS("DATA_RAM_LMA", flash0);
+
+/* RAM region to be used for BSS segment.*/
+REGION_ALIAS("BSS_RAM", ram0);
+
+/* RAM region to be used for the default heap.*/
+REGION_ALIAS("HEAP_RAM", ram0);
+
+/* Generic rules inclusion.*/
+INCLUDE rules.ld
diff --git a/keyboards/annepro2/matrix.c b/keyboards/annepro2/matrix.c
new file mode 100644
index 0000000000..a1585e4ddf
--- /dev/null
+++ b/keyboards/annepro2/matrix.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018 Charlie Waters
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <hal.h>
+#include "timer.h"
+#include "wait.h"
+#include "print.h"
+#include "matrix.h"
+#include "annepro2.h"
+
+pin_t row_list[MATRIX_ROWS] = MATRIX_ROW_PINS;
+pin_t col_list[MATRIX_COLS] = MATRIX_COL_PINS;
+
+bool matrix_scan_custom(matrix_row_t current_matrix[]) {
+    bool matrix_has_changed = false;
+    // cache of input ports for columns
+    static uint16_t port_cache[4];
+    // scan each row
+    for (int row = 0; row < MATRIX_ROWS; row++) {
+        palClearLine(row_list[row]);
+        __NOP();
+        __NOP();
+        __NOP();
+        __NOP();
+        // read i/o ports
+        port_cache[0] = palReadPort(IOPORTA);
+        port_cache[1] = palReadPort(IOPORTB);
+        port_cache[2] = palReadPort(IOPORTC);
+        port_cache[3] = palReadPort(IOPORTD);
+        palSetLine(row_list[row]);
+
+        // get columns from ports
+        matrix_row_t data = 0;
+        for (int col = 0; col < MATRIX_COLS; ++col) {
+            pin_t line = col_list[col];
+            uint16_t port = port_cache[HT32_PAL_IDX(PAL_PORT(line))];
+            data |= (((port & (1 << PAL_PAD(line))) ? 0 : 1) << col);
+        }
+
+        if (current_matrix[row] != data) {
+            current_matrix[row] = data;
+            matrix_has_changed  = true;
+        }
+    }
+    return matrix_has_changed;
+}
\ No newline at end of file
diff --git a/keyboards/annepro2/mcuconf.h b/keyboards/annepro2/mcuconf.h
new file mode 100644
index 0000000000..8265fe6eb9
--- /dev/null
+++ b/keyboards/annepro2/mcuconf.h
@@ -0,0 +1,62 @@
+/*
+    ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+#pragma once
+
+#include "nvic.h"
+
+#define HT32F52342_MCUCONF
+
+/*
+ * HAL driver system settings.
+ */
+
+/*
+ * Clock configuration.
+ */
+
+// This configuration:
+// 8 MHz HSE crystal
+// PLL multiplies HSE to 48 MHz core and peripheral clock
+// 48 MHz to UART
+// 48 MHz to USB
+
+#define HT32_CK_HSE_FREQUENCY 8000000UL  // 8 MHz
+#define HT32_CKCU_SW CKCU_GCCR_SW_PLL
+#define HT32_PLL_USE_HSE TRUE
+#define HT32_PLL_FBDIV 6  // 8 MHz -> 48 MHz
+#define HT32_PLL_OTDIV 0
+#define HT32_AHB_PRESCALER 1    // 48 MHz -> 48 MHz
+#define HT32_USART_PRESCALER 1  // 48 MHz
+#define HT32_USB_PRESCALER 1    // 48 MHz -> 48 MHz
+// SysTick uses processor clock at 48MHz
+#define HT32_ST_USE_HCLK TRUE
+
+/*
+ * Peripheral driver settings
+ */
+
+#define HT32_SERIAL_USE_USART0 TRUE
+#define HT32_USART0_IRQ_PRIORITY 6
+
+#define HT32_SERIAL_USE_USART1 TRUE
+#define HT32_USART1_IRQ_PRIORITY 7
+
+/*
+ * USB driver settings
+ */
+
+#define HT32_USB_USE_USB0 TRUE
+#define HT32_USB_USB0_IRQ_PRIORITY 5
diff --git a/keyboards/annepro2/protocol.c b/keyboards/annepro2/protocol.c
new file mode 100644
index 0000000000..171ac5c239
--- /dev/null
+++ b/keyboards/annepro2/protocol.c
@@ -0,0 +1,116 @@
+/*
+ * (c) 2021 by Tomasz bla Fortuna
+ * License: GPLv2
+ *
+ * This file is shared with the Shine firmware. Keep it in sync (and in the
+ * shine's clang formatting).
+ *
+ * Implementation of a robust serial protocol which can handle single dropped
+ * characters during transit without locking.
+ *
+ * At 115200, transmitting the shortest message takes 0.043ms, at 9600 - 0.52ms.
+ *
+ */
+
+#include "protocol.h"
+#include "board.h"
+#include "ch.h"
+#include "hal.h"
+
+/* UART communication protocol state */
+protocol_t proto;
+
+void protoInit(protocol_t *proto, void (*callback)(const message_t *)) {
+    proto->previousId = 0;
+    proto->callback   = callback;
+    proto->state      = STATE_SYNC_1;
+    proto->errors     = 0;
+}
+
+static uint8_t msgId = 0;
+void           protoTx(uint8_t cmd, const unsigned char *buf, int payloadSize, int retries) {
+    chDbgCheck(payloadSize <= MAX_PAYLOAD_SIZE);
+
+    const uint8_t header[5] = {
+        0x7A, 0x1D, cmd, ++msgId, payloadSize,
+    };
+
+    /* We don't implement ACKs, yet some messages should not be lost. */
+    for (int i = 0; i < retries; i++) {
+        sdWrite(&PROTOCOL_SD, header, sizeof(header));
+        if (payloadSize) sdWrite(&PROTOCOL_SD, buf, payloadSize);
+    }
+}
+
+static inline void messageReceived(protocol_t *proto) {
+    if (proto->buffer.msgId != proto->previousId) {
+        /* It's not a resend / duplicate */
+        proto->callback(&proto->buffer);
+        proto->previousId = proto->buffer.msgId;
+    }
+    proto->state = STATE_SYNC_1;
+}
+
+void protoConsume(protocol_t *proto, uint8_t byte) {
+    switch (proto->state) {
+        case STATE_SYNC_1:
+            if (byte == 0x7A) {
+                proto->state = STATE_SYNC_2;
+            } else {
+                proto->errors++;
+            }
+            return;
+
+        case STATE_SYNC_2:
+            if (byte == 0x1D) {
+                proto->state = STATE_CMD;
+            } else {
+                proto->state = STATE_SYNC_1;
+                proto->errors++;
+            }
+            return;
+
+        case STATE_CMD:
+            proto->buffer.command = byte;
+            proto->state          = STATE_ID;
+            return;
+
+        case STATE_ID:
+            proto->buffer.msgId = byte;
+            proto->state        = STATE_PAYLOAD_SIZE;
+            return;
+
+        case STATE_PAYLOAD_SIZE:
+            proto->buffer.payloadSize = byte;
+            if (proto->buffer.payloadSize > MAX_PAYLOAD_SIZE) {
+                proto->buffer.payloadSize = MAX_PAYLOAD_SIZE;
+                proto->errors++;
+            }
+            proto->payloadPosition = 0;
+            if (proto->buffer.payloadSize == 0) {
+                /* No payload - whole message received */
+                messageReceived(proto);
+            } else {
+                proto->state = STATE_PAYLOAD;
+            }
+            return;
+
+        case STATE_PAYLOAD:
+            /* NOTE: This could be read with sdReadTimeout probably, but that breaks
+             * abstraction */
+            proto->buffer.payload[proto->payloadPosition] = byte;
+            proto->payloadPosition++;
+            if (proto->payloadPosition == proto->buffer.payloadSize) {
+                /* Payload read - message received */
+                messageReceived(proto);
+            }
+            return;
+    }
+}
+
+void protoSilence(protocol_t *proto) {
+    if (proto->state != STATE_SYNC_1) {
+        proto->state = STATE_SYNC_1;
+        proto->errors++;
+    }
+}
diff --git a/keyboards/annepro2/protocol.h b/keyboards/annepro2/protocol.h
new file mode 100644
index 0000000000..d1a05683c8
--- /dev/null
+++ b/keyboards/annepro2/protocol.h
@@ -0,0 +1,111 @@
+/*
+ * (c) 2021 by Tomasz bla Fortuna
+ * License: GPLv2
+ *
+ * This file is shared with the Shine firmware. Keep it in sync (and in the
+ * shine's clang formatting).
+ */
+
+#pragma once
+#include <stdint.h>
+
+#define PROTOCOL_SD SD0
+
+enum {
+    /*
+     * Main -> LED
+     */
+    /* Basic config */
+    CMD_LED_ON  = 0x01,
+    CMD_LED_OFF = 0x02,
+
+    CMD_LED_SET_PROFILE  = 0x03,
+    CMD_LED_NEXT_PROFILE = 0x04,
+    CMD_LED_PREV_PROFILE = 0x05,
+
+    CMD_LED_NEXT_INTENSITY       = 0x06,
+    CMD_LED_NEXT_ANIMATION_SPEED = 0x07,
+
+    /* Masks */
+    /* Override a key color, eg. capslock */
+    CMD_LED_MASK_SET_KEY = 0x10,
+    /* Override all keys in a row with configurable colors */
+    CMD_LED_MASK_SET_ROW = 0x11,
+
+    /* Override all keys with single color (eg. foreground color) */
+    CMD_LED_MASK_SET_MONO = 0x12,
+
+    /* Reactive / status */
+    CMD_LED_GET_STATUS = 0x20,
+    CMD_LED_KEY_BLINK  = 0x21,
+    CMD_LED_KEY_DOWN   = 0x22,
+    CMD_LED_KEY_UP     = 0x23, /* TODO */
+    CMD_LED_IAP        = 0x24,
+
+    /* LED -> Main */
+    /* Payload with data to send over HID */
+    CMD_LED_DEBUG = 0x40,
+
+    /* Number of profiles, current profile, on/off state,
+       reactive flag, brightness, errors */
+    CMD_LED_STATUS = 0x41,
+};
+
+/* 1 ROW * 14 COLS * 4B (RGBX) = 56 + header prefix. */
+#define MAX_PAYLOAD_SIZE 64
+
+/** Enum of the states used for the serial protocol finite-state automaton */
+enum protoState {
+    /* 2-byte initial start-of-message sync */
+    STATE_SYNC_1,
+    STATE_SYNC_2,
+    /* Waiting for command byte */
+    STATE_CMD,
+    /* Waiting for ID byte */
+    STATE_ID,
+    /* Waiting for payload size */
+    STATE_PAYLOAD_SIZE,
+    /* Reading payload until payloadPosition == payloadSize */
+    STATE_PAYLOAD,
+};
+
+/* Buffer holding a single message */
+typedef struct {
+    uint8_t command;
+    uint8_t msgId;
+    uint8_t payloadSize;
+    uint8_t payload[MAX_PAYLOAD_SIZE];
+} message_t;
+
+/* Internal protocol state */
+typedef struct {
+    /* Callback to call upon receiving a valid message */
+    void (*callback)(const message_t *);
+
+    /* Number of read payload bytes */
+    uint8_t payloadPosition;
+
+    /* Current finite-state-automata state */
+    enum protoState state;
+
+    uint8_t previousId;
+    uint8_t errors;
+
+    /* Currently received message */
+    message_t buffer;
+} protocol_t;
+
+/* NOTE: This didn't work when defined on stack */
+extern protocol_t proto;
+
+/* Init state */
+extern void protoInit(protocol_t *proto, void (*callback)(const message_t *));
+
+/* Consume one byte and push state forward - might call the callback */
+extern void protoConsume(protocol_t *proto, uint8_t byte);
+
+/* Prolonged silence - reset state */
+extern void protoSilence(protocol_t *proto);
+
+/* Transmit message */
+extern void protoTx(uint8_t cmd, const unsigned char *buf, int payloadSize, int retries);
diff --git a/keyboards/annepro2/readme.md b/keyboards/annepro2/readme.md
new file mode 100644
index 0000000000..e3e0b95be4
--- /dev/null
+++ b/keyboards/annepro2/readme.md
@@ -0,0 +1,50 @@
+# Anne Pro 2 rev. C15 and C18 QMK firmware
+
+## Introduction
+
+This is the QMK firmware repository for the Anne Pro 2 rev. C15 and C18 keyboard.
+
+## Layouts
+
+Keyboard has 60% ANSI standard layout.
+
+## How to compile
+
+After setting up your build environment, you can compile the Anne Pro 2 C18 default keymap by using:
+
+    make annepro2/c18:default
+
+If you want to compile the Anne Pro 2 C15 default keymap use:
+
+    make annepro2/c15:default
+
+## Installing
+
+### Get AnnePro2 Tools
+
+If you want the executable instead of compiling it yourself, [download it here](https://ci.codetector.org/job/OpenAnnePro/job/AnnePro2-Tools/job/master/).
+Windows and Linux versions are available. Otherwise, follow the steps below:
+
+0. Install the latest stable `rust` toolchain using [rustup](https://rustup.rs/)
+0. Also install [Visual Studio Community edition](https://visualstudio.microsoft.com/downloads/)
+including the C/C++ module to prevent errors while compiling
+0. Download or Clone the [AnnePro2-Tools](https://github.com/OpenAnnePro/AnnePro2-Tools) project.
+0. Compile the tool using
+```bash
+cargo build --release
+```
+0. The compiled tool should be in `./target/release/annepro2_tools` (In later I will refer to this as `annepro2_tools`)
+
+### Flashing the firmware
+0. Put the keyboard into DFU/IAP mode by unplugging the keyboard, then holding ESC while plugging it back in.
+0. Run annepro2_tools with the firmware you just built.
+
+**Please substitute with the correct paths and correct bin file if you chose another keymap profile**
+```bash
+annepro2_tools annepro2_c15_default.bin
+```
+
+If the tool can't find the keyboard please double check you have the keyboard in IAP mode.
+
+
+See the [build environment setup](https://docs.qmk.fm/#/getting_started_build_tools) and the [make instructions](https://docs.qmk.fm/#/getting_started_make_guide) for more information. Brand new to QMK? Start with our [Complete Newbs Guide](https://docs.qmk.fm/#/newbs).
\ No newline at end of file