AaronHM 2 месяцев назад
Родитель
Сommit
3762863a9d

+ 378 - 345
AD7124_ATY.c

@@ -1,7 +1,7 @@
 /**
 * @file AD7124_ATY.c
 *
-* @param Project DEVICE_GENERAL_ATY_LIB
+* @param Project DEVICE_DRIVER_ATY_LIB
 *
 * @author ATY
 *
@@ -18,6 +18,8 @@
 *
 * @brief functions of AD7124 for C platform
 *
+* @note SPI_POLARITY_LOW + SPI_PHASE_1EDGE = CPOL=0, CPHA=0 = SPI Mode 1
+*
 * @version
 *       - 1_01_230828 > ATY
 *           -# Preliminary version, first Release
@@ -27,6 +29,8 @@
 *           -# add lock
 *       - 1_04_251124 > ATY
 *           -# change log and test basely
+*       - 1_05_251225 > ATY
+*           -# change dev position and add initFlag to auto init
 ********************************************************************************
 */
 
@@ -48,13 +52,14 @@
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_WriteRead(uint8_t* data, uint8_t len, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_WriteRead(struct AD7124_ATY_Dev* dev, uint8_t* data, uint8_t len){
     uint8_t errCode = 0;
+
     __ATY_LOCK(dev);
     dev->nssSet(__ATY_HL_L);
     printf_ATY_D("%sRW_W: ", AD7124_ATY_TAG);
     for(int i = 0; i < len; i++) printf_ATY_D("%02X ", data[i]);
-    errCode = dev->spiProcess(data, len, __ATY_RW_RW);
+    errCode = dev->spiProcess(data, len);
     printf_ATY_D("%sRW_R: ", AD7124_ATY_TAG);
     for(int i = 0; i < len; i++) printf_ATY_D("%02X ", data[i]);
     dev->nssSet(__ATY_HL_H);
@@ -80,7 +85,7 @@ uint8_t AD7124_Reset(struct AD7124_ATY_Dev* dev){
     __ATY_UNLOCK(dev);
 
     // write more than 64 bits to reset AD7124
-    errCode = AD7124_WriteRead(resetBuf, 9, dev);
+    errCode = AD7124_WriteRead(dev, resetBuf, 9);
     return errCode;
 }
 
@@ -91,12 +96,12 @@ uint8_t AD7124_Reset(struct AD7124_ATY_Dev* dev){
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_ReadId(uint8_t* id, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_ReadId(struct AD7124_ATY_Dev* dev, uint8_t* id){
     uint8_t errCode = 0, groupTrans[2] = {0};
     printf_ATY_D("%s--ReadId", AD7124_ATY_TAG);
     groupTrans[0] = 0x45;
     groupTrans[1] = 0;
-    errCode = AD7124_WriteRead(groupTrans, 2, dev);
+    errCode = AD7124_WriteRead(dev, groupTrans, 2);
     dev->id = groupTrans[1];
     *id = dev->id;
     printf_ATY_D("%sAD7124_ID: %02X\r\n", AD7124_ATY_TAG, dev->id);
@@ -113,7 +118,7 @@ uint8_t AD7124_ReadId(uint8_t* id, struct AD7124_ATY_Dev* dev){
  * @return  uint8_t
  * @note    AD7124_ERR_REG_SPI_IGNORE_ERR only for crc trans
  */
-uint8_t AD7124_WriteReg(uint8_t regAddr, uint32_t data, uint8_t len, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_WriteReg(struct AD7124_ATY_Dev* dev, uint8_t regAddr, uint32_t data, uint8_t len){
     uint8_t errCode = 0, i = 0, groupTrans[4] = {0};
     printf_ATY_D("%s--WriteReg", AD7124_ATY_TAG);
     groupTrans[0] = AD7124_COMM_REG_WA(regAddr);
@@ -124,7 +129,7 @@ uint8_t AD7124_WriteReg(uint8_t regAddr, uint32_t data, uint8_t len, struct AD71
     printf_ATY_D("%sWriteReg: ", AD7124_ATY_TAG);
     for(i = 0; i < len + 1; i++)
         printf_ATY_D("%02X ", groupTrans[i]);
-    errCode = AD7124_WriteRead(groupTrans, len + 1, dev);
+    errCode = AD7124_WriteRead(dev, groupTrans, len + 1);
     return errCode;
 }
 
@@ -137,11 +142,11 @@ uint8_t AD7124_WriteReg(uint8_t regAddr, uint32_t data, uint8_t len, struct AD71
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_ReadReg(uint8_t regAddr, uint32_t* data, uint8_t len, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_ReadReg(struct AD7124_ATY_Dev* dev, uint8_t regAddr, uint32_t* data, uint8_t len){
     uint8_t errCode = 0, i = 0, groupTrans[4] = {0};
     printf_ATY_D("%s--ReadReg", AD7124_ATY_TAG);
     groupTrans[0] = AD7124_COMM_REG_RA(regAddr);
-    errCode = AD7124_WriteRead(groupTrans, len + 1, dev);
+    errCode = AD7124_WriteRead(dev, groupTrans, len + 1);
     if(len == 1)
         *data = groupTrans[1];
     else if(len == 2)
@@ -161,11 +166,14 @@ uint8_t AD7124_ReadReg(uint8_t regAddr, uint32_t* data, uint8_t len, struct AD71
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_ReadData(uint8_t* data, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_ReadData(struct AD7124_ATY_Dev* dev, uint8_t* data){
+    AD7124_Init(dev, dev->cfg);
+
     printf_ATY_D("%s--ReadData", AD7124_ATY_TAG);
     uint8_t errCode = 0, i = 0;
     data[0] = AD7124_COMM_REG_RA(AD7124_DATA_REG);
-    errCode = AD7124_WriteRead(data, 5, dev);
+    errCode = AD7124_WriteRead(dev, data, 5);
+
     printf_ATY_D("%sReadData: 0x ", AD7124_ATY_TAG);
     for(i = 0; i < 5; i++)
         printf_ATY_D("%02X ", data[i]);
@@ -179,9 +187,9 @@ uint8_t AD7124_ReadData(uint8_t* data, struct AD7124_ATY_Dev* dev){
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_ReadStatus(uint8_t* status, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_ReadStatus(struct AD7124_ATY_Dev* dev, uint8_t* status){
     printf_ATY_D("%s--ReadStatus", AD7124_ATY_TAG);
-    if(AD7124_ReadReg(AD7124_STATUS_REG, (uint32_t*)status, 1, dev)){
+    if(AD7124_ReadReg(dev, AD7124_STATUS_REG, (uint32_t*)status, 1)){
         printf_ATY_D("%sAD7124_ERR: STATE %02X %02X\r\n",
             AD7124_ATY_TAG, status[0], status[1]);
         return 1;
@@ -224,24 +232,29 @@ float AD7124_DataToResDefault(uint32_t data){
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_Init(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev){
-    uint8_t id = 0, status[2] = {0};
-    dev->enSet(__ATY_HL_H);
-    if(AD7124_Reset(dev)){
-        printf_ATY_D("%sAD7124_ERR: RST\r\n", AD7124_ATY_TAG);
-        return 1;
-    }
-    if(AD7124_ReadId(&id, dev)){
-        printf_ATY_D("%sAD7124_ERR: ID\r\n", AD7124_ATY_TAG);
-        return 2;
-    }
-    if(AD7124_ReadStatus(status, dev)){
-        printf_ATY_D("%sAD7124_ERR: Status\r\n", AD7124_ATY_TAG);
-        return 3;
-    }
-    if(AD7124_Config(cfg, dev)){
-        printf_ATY_D("%sAD7124_ERR: CFG\r\n", AD7124_ATY_TAG);
-        return 4;
+uint8_t AD7124_Init(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg){
+    if(dev->initFlag == 0){
+        uint8_t id = 0, status[2] = {0};
+        printf_ATY_D("%sAD7124_Init", AD7124_ATY_TAG);
+        dev->enSet(__ATY_HL_H);
+        if(AD7124_Reset(dev)){
+            printf_ATY_D("%sAD7124_ERR: RST", AD7124_ATY_TAG);
+            return 1;
+        }
+        if(AD7124_ReadId(dev, &id)){
+            printf_ATY_D("%sAD7124_ERR: ID", AD7124_ATY_TAG);
+            return 2;
+        }
+        if(AD7124_ReadStatus(dev, status)){
+            printf_ATY_D("%sAD7124_ERR: Status", AD7124_ATY_TAG);
+            return 3;
+        }
+        if(AD7124_Config(dev, cfg)){
+            printf_ATY_D("%sAD7124_ERR: CFG", AD7124_ATY_TAG);
+            return 4;
+        }
+        dev->initFlag = 1;
+        return 0;
     }
     return 0;
 }
@@ -253,65 +266,65 @@ uint8_t AD7124_Init(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev){
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_Config(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_Config(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg){
     printf_ATY_D("%s--Config", AD7124_ATY_TAG);
-    if(cfg->AD7124_ADC_CTRL_REG_t) AD7124_WriteReg(AD7124_ADC_CTRL_REG, cfg->AD7124_ADC_CTRL_REG_t, 2, dev);
-    if(cfg->AD7124_IO_CTRL1_REG_t) AD7124_WriteReg(AD7124_IO_CTRL1_REG, cfg->AD7124_IO_CTRL1_REG_t, 3, dev);
-    if(cfg->AD7124_IO_CTRL2_REG_t) AD7124_WriteReg(AD7124_IO_CTRL2_REG, cfg->AD7124_IO_CTRL2_REG_t, 2, dev);
-    if(cfg->AD7124_ERREN_REG_t) AD7124_WriteReg(AD7124_ERREN_REG, cfg->AD7124_ERREN_REG_t, 3, dev);
-
-    if(cfg->AD7124_CH0_MAP_REG_t) AD7124_WriteReg(AD7124_CH0_MAP_REG, cfg->AD7124_CH0_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH1_MAP_REG_t) AD7124_WriteReg(AD7124_CH1_MAP_REG, cfg->AD7124_CH1_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH2_MAP_REG_t) AD7124_WriteReg(AD7124_CH2_MAP_REG, cfg->AD7124_CH2_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH3_MAP_REG_t) AD7124_WriteReg(AD7124_CH3_MAP_REG, cfg->AD7124_CH3_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH4_MAP_REG_t) AD7124_WriteReg(AD7124_CH4_MAP_REG, cfg->AD7124_CH4_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH5_MAP_REG_t) AD7124_WriteReg(AD7124_CH5_MAP_REG, cfg->AD7124_CH5_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH6_MAP_REG_t) AD7124_WriteReg(AD7124_CH6_MAP_REG, cfg->AD7124_CH6_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH7_MAP_REG_t) AD7124_WriteReg(AD7124_CH7_MAP_REG, cfg->AD7124_CH7_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH8_MAP_REG_t) AD7124_WriteReg(AD7124_CH8_MAP_REG, cfg->AD7124_CH8_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH9_MAP_REG_t) AD7124_WriteReg(AD7124_CH9_MAP_REG, cfg->AD7124_CH9_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH10_MAP_REG_t) AD7124_WriteReg(AD7124_CH10_MAP_REG, cfg->AD7124_CH10_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH11_MAP_REG_t) AD7124_WriteReg(AD7124_CH11_MAP_REG, cfg->AD7124_CH11_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH12_MAP_REG_t) AD7124_WriteReg(AD7124_CH12_MAP_REG, cfg->AD7124_CH12_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH13_MAP_REG_t) AD7124_WriteReg(AD7124_CH13_MAP_REG, cfg->AD7124_CH13_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH14_MAP_REG_t) AD7124_WriteReg(AD7124_CH14_MAP_REG, cfg->AD7124_CH14_MAP_REG_t, 2, dev);
-    if(cfg->AD7124_CH15_MAP_REG_t) AD7124_WriteReg(AD7124_CH15_MAP_REG, cfg->AD7124_CH15_MAP_REG_t, 2, dev);
-
-    if(cfg->AD7124_CFG0_REG_t) AD7124_WriteReg(AD7124_CFG0_REG, cfg->AD7124_CFG0_REG_t, 2, dev);
-    if(cfg->AD7124_CFG1_REG_t) AD7124_WriteReg(AD7124_CFG1_REG, cfg->AD7124_CFG1_REG_t, 2, dev);
-    if(cfg->AD7124_CFG2_REG_t) AD7124_WriteReg(AD7124_CFG2_REG, cfg->AD7124_CFG2_REG_t, 2, dev);
-    if(cfg->AD7124_CFG3_REG_t) AD7124_WriteReg(AD7124_CFG3_REG, cfg->AD7124_CFG3_REG_t, 2, dev);
-    if(cfg->AD7124_CFG4_REG_t) AD7124_WriteReg(AD7124_CFG4_REG, cfg->AD7124_CFG4_REG_t, 2, dev);
-    if(cfg->AD7124_CFG5_REG_t) AD7124_WriteReg(AD7124_CFG5_REG, cfg->AD7124_CFG5_REG_t, 2, dev);
-    if(cfg->AD7124_CFG6_REG_t) AD7124_WriteReg(AD7124_CFG6_REG, cfg->AD7124_CFG6_REG_t, 2, dev);
-    if(cfg->AD7124_CFG7_REG_t) AD7124_WriteReg(AD7124_CFG7_REG, cfg->AD7124_CFG7_REG_t, 2, dev);
-
-    if(cfg->AD7124_FILT0_REG_t) AD7124_WriteReg(AD7124_FILT0_REG, cfg->AD7124_FILT0_REG_t, 3, dev);
-    if(cfg->AD7124_FILT1_REG_t) AD7124_WriteReg(AD7124_FILT1_REG, cfg->AD7124_FILT1_REG_t, 3, dev);
-    if(cfg->AD7124_FILT2_REG_t) AD7124_WriteReg(AD7124_FILT2_REG, cfg->AD7124_FILT2_REG_t, 3, dev);
-    if(cfg->AD7124_FILT3_REG_t) AD7124_WriteReg(AD7124_FILT3_REG, cfg->AD7124_FILT3_REG_t, 3, dev);
-    if(cfg->AD7124_FILT4_REG_t) AD7124_WriteReg(AD7124_FILT4_REG, cfg->AD7124_FILT4_REG_t, 3, dev);
-    if(cfg->AD7124_FILT5_REG_t) AD7124_WriteReg(AD7124_FILT5_REG, cfg->AD7124_FILT5_REG_t, 3, dev);
-    if(cfg->AD7124_FILT6_REG_t) AD7124_WriteReg(AD7124_FILT6_REG, cfg->AD7124_FILT6_REG_t, 3, dev);
-    if(cfg->AD7124_FILT7_REG_t) AD7124_WriteReg(AD7124_FILT7_REG, cfg->AD7124_FILT7_REG_t, 3, dev);
-
-    if(cfg->AD7124_OFFS0_REG_t) AD7124_WriteReg(AD7124_OFFS0_REG, cfg->AD7124_OFFS0_REG_t, 3, dev);
-    if(cfg->AD7124_OFFS1_REG_t) AD7124_WriteReg(AD7124_OFFS1_REG, cfg->AD7124_OFFS1_REG_t, 3, dev);
-    if(cfg->AD7124_OFFS2_REG_t) AD7124_WriteReg(AD7124_OFFS2_REG, cfg->AD7124_OFFS2_REG_t, 3, dev);
-    if(cfg->AD7124_OFFS3_REG_t) AD7124_WriteReg(AD7124_OFFS3_REG, cfg->AD7124_OFFS3_REG_t, 3, dev);
-    if(cfg->AD7124_OFFS4_REG_t) AD7124_WriteReg(AD7124_OFFS4_REG, cfg->AD7124_OFFS4_REG_t, 3, dev);
-    if(cfg->AD7124_OFFS5_REG_t) AD7124_WriteReg(AD7124_OFFS5_REG, cfg->AD7124_OFFS5_REG_t, 3, dev);
-    if(cfg->AD7124_OFFS6_REG_t) AD7124_WriteReg(AD7124_OFFS6_REG, cfg->AD7124_OFFS6_REG_t, 3, dev);
-    if(cfg->AD7124_OFFS7_REG_t) AD7124_WriteReg(AD7124_OFFS7_REG, cfg->AD7124_OFFS7_REG_t, 3, dev);
-
-    if(cfg->AD7124_GAIN0_REG_t) AD7124_WriteReg(AD7124_GAIN0_REG, cfg->AD7124_GAIN0_REG_t, 3, dev);
-    if(cfg->AD7124_GAIN1_REG_t) AD7124_WriteReg(AD7124_GAIN1_REG, cfg->AD7124_GAIN1_REG_t, 3, dev);
-    if(cfg->AD7124_GAIN2_REG_t) AD7124_WriteReg(AD7124_GAIN2_REG, cfg->AD7124_GAIN2_REG_t, 3, dev);
-    if(cfg->AD7124_GAIN3_REG_t) AD7124_WriteReg(AD7124_GAIN3_REG, cfg->AD7124_GAIN3_REG_t, 3, dev);
-    if(cfg->AD7124_GAIN4_REG_t) AD7124_WriteReg(AD7124_GAIN4_REG, cfg->AD7124_GAIN4_REG_t, 3, dev);
-    if(cfg->AD7124_GAIN5_REG_t) AD7124_WriteReg(AD7124_GAIN5_REG, cfg->AD7124_GAIN5_REG_t, 3, dev);
-    if(cfg->AD7124_GAIN6_REG_t) AD7124_WriteReg(AD7124_GAIN6_REG, cfg->AD7124_GAIN6_REG_t, 3, dev);
-    if(cfg->AD7124_GAIN7_REG_t) AD7124_WriteReg(AD7124_GAIN7_REG, cfg->AD7124_GAIN7_REG_t, 3, dev);
+    if(cfg->AD7124_ADC_CTRL_REG_t) AD7124_WriteReg(dev, AD7124_ADC_CTRL_REG, cfg->AD7124_ADC_CTRL_REG_t, 2);
+    if(cfg->AD7124_IO_CTRL1_REG_t) AD7124_WriteReg(dev, AD7124_IO_CTRL1_REG, cfg->AD7124_IO_CTRL1_REG_t, 3);
+    if(cfg->AD7124_IO_CTRL2_REG_t) AD7124_WriteReg(dev, AD7124_IO_CTRL2_REG, cfg->AD7124_IO_CTRL2_REG_t, 2);
+    if(cfg->AD7124_ERREN_REG_t) AD7124_WriteReg(dev, AD7124_ERREN_REG, cfg->AD7124_ERREN_REG_t, 3);
+
+    if(cfg->AD7124_CH0_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH0_MAP_REG, cfg->AD7124_CH0_MAP_REG_t, 2);
+    if(cfg->AD7124_CH1_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH1_MAP_REG, cfg->AD7124_CH1_MAP_REG_t, 2);
+    if(cfg->AD7124_CH2_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH2_MAP_REG, cfg->AD7124_CH2_MAP_REG_t, 2);
+    if(cfg->AD7124_CH3_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH3_MAP_REG, cfg->AD7124_CH3_MAP_REG_t, 2);
+    if(cfg->AD7124_CH4_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH4_MAP_REG, cfg->AD7124_CH4_MAP_REG_t, 2);
+    if(cfg->AD7124_CH5_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH5_MAP_REG, cfg->AD7124_CH5_MAP_REG_t, 2);
+    if(cfg->AD7124_CH6_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH6_MAP_REG, cfg->AD7124_CH6_MAP_REG_t, 2);
+    if(cfg->AD7124_CH7_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH7_MAP_REG, cfg->AD7124_CH7_MAP_REG_t, 2);
+    if(cfg->AD7124_CH8_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH8_MAP_REG, cfg->AD7124_CH8_MAP_REG_t, 2);
+    if(cfg->AD7124_CH9_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH9_MAP_REG, cfg->AD7124_CH9_MAP_REG_t, 2);
+    if(cfg->AD7124_CH10_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH10_MAP_REG, cfg->AD7124_CH10_MAP_REG_t, 2);
+    if(cfg->AD7124_CH11_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH11_MAP_REG, cfg->AD7124_CH11_MAP_REG_t, 2);
+    if(cfg->AD7124_CH12_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH12_MAP_REG, cfg->AD7124_CH12_MAP_REG_t, 2);
+    if(cfg->AD7124_CH13_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH13_MAP_REG, cfg->AD7124_CH13_MAP_REG_t, 2);
+    if(cfg->AD7124_CH14_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH14_MAP_REG, cfg->AD7124_CH14_MAP_REG_t, 2);
+    if(cfg->AD7124_CH15_MAP_REG_t) AD7124_WriteReg(dev, AD7124_CH15_MAP_REG, cfg->AD7124_CH15_MAP_REG_t, 2);
+
+    if(cfg->AD7124_CFG0_REG_t) AD7124_WriteReg(dev, AD7124_CFG0_REG, cfg->AD7124_CFG0_REG_t, 2);
+    if(cfg->AD7124_CFG1_REG_t) AD7124_WriteReg(dev, AD7124_CFG1_REG, cfg->AD7124_CFG1_REG_t, 2);
+    if(cfg->AD7124_CFG2_REG_t) AD7124_WriteReg(dev, AD7124_CFG2_REG, cfg->AD7124_CFG2_REG_t, 2);
+    if(cfg->AD7124_CFG3_REG_t) AD7124_WriteReg(dev, AD7124_CFG3_REG, cfg->AD7124_CFG3_REG_t, 2);
+    if(cfg->AD7124_CFG4_REG_t) AD7124_WriteReg(dev, AD7124_CFG4_REG, cfg->AD7124_CFG4_REG_t, 2);
+    if(cfg->AD7124_CFG5_REG_t) AD7124_WriteReg(dev, AD7124_CFG5_REG, cfg->AD7124_CFG5_REG_t, 2);
+    if(cfg->AD7124_CFG6_REG_t) AD7124_WriteReg(dev, AD7124_CFG6_REG, cfg->AD7124_CFG6_REG_t, 2);
+    if(cfg->AD7124_CFG7_REG_t) AD7124_WriteReg(dev, AD7124_CFG7_REG, cfg->AD7124_CFG7_REG_t, 2);
+
+    if(cfg->AD7124_FILT0_REG_t) AD7124_WriteReg(dev, AD7124_FILT0_REG, cfg->AD7124_FILT0_REG_t, 3);
+    if(cfg->AD7124_FILT1_REG_t) AD7124_WriteReg(dev, AD7124_FILT1_REG, cfg->AD7124_FILT1_REG_t, 3);
+    if(cfg->AD7124_FILT2_REG_t) AD7124_WriteReg(dev, AD7124_FILT2_REG, cfg->AD7124_FILT2_REG_t, 3);
+    if(cfg->AD7124_FILT3_REG_t) AD7124_WriteReg(dev, AD7124_FILT3_REG, cfg->AD7124_FILT3_REG_t, 3);
+    if(cfg->AD7124_FILT4_REG_t) AD7124_WriteReg(dev, AD7124_FILT4_REG, cfg->AD7124_FILT4_REG_t, 3);
+    if(cfg->AD7124_FILT5_REG_t) AD7124_WriteReg(dev, AD7124_FILT5_REG, cfg->AD7124_FILT5_REG_t, 3);
+    if(cfg->AD7124_FILT6_REG_t) AD7124_WriteReg(dev, AD7124_FILT6_REG, cfg->AD7124_FILT6_REG_t, 3);
+    if(cfg->AD7124_FILT7_REG_t) AD7124_WriteReg(dev, AD7124_FILT7_REG, cfg->AD7124_FILT7_REG_t, 3);
+
+    if(cfg->AD7124_OFFS0_REG_t) AD7124_WriteReg(dev, AD7124_OFFS0_REG, cfg->AD7124_OFFS0_REG_t, 3);
+    if(cfg->AD7124_OFFS1_REG_t) AD7124_WriteReg(dev, AD7124_OFFS1_REG, cfg->AD7124_OFFS1_REG_t, 3);
+    if(cfg->AD7124_OFFS2_REG_t) AD7124_WriteReg(dev, AD7124_OFFS2_REG, cfg->AD7124_OFFS2_REG_t, 3);
+    if(cfg->AD7124_OFFS3_REG_t) AD7124_WriteReg(dev, AD7124_OFFS3_REG, cfg->AD7124_OFFS3_REG_t, 3);
+    if(cfg->AD7124_OFFS4_REG_t) AD7124_WriteReg(dev, AD7124_OFFS4_REG, cfg->AD7124_OFFS4_REG_t, 3);
+    if(cfg->AD7124_OFFS5_REG_t) AD7124_WriteReg(dev, AD7124_OFFS5_REG, cfg->AD7124_OFFS5_REG_t, 3);
+    if(cfg->AD7124_OFFS6_REG_t) AD7124_WriteReg(dev, AD7124_OFFS6_REG, cfg->AD7124_OFFS6_REG_t, 3);
+    if(cfg->AD7124_OFFS7_REG_t) AD7124_WriteReg(dev, AD7124_OFFS7_REG, cfg->AD7124_OFFS7_REG_t, 3);
+
+    if(cfg->AD7124_GAIN0_REG_t) AD7124_WriteReg(dev, AD7124_GAIN0_REG, cfg->AD7124_GAIN0_REG_t, 3);
+    if(cfg->AD7124_GAIN1_REG_t) AD7124_WriteReg(dev, AD7124_GAIN1_REG, cfg->AD7124_GAIN1_REG_t, 3);
+    if(cfg->AD7124_GAIN2_REG_t) AD7124_WriteReg(dev, AD7124_GAIN2_REG, cfg->AD7124_GAIN2_REG_t, 3);
+    if(cfg->AD7124_GAIN3_REG_t) AD7124_WriteReg(dev, AD7124_GAIN3_REG, cfg->AD7124_GAIN3_REG_t, 3);
+    if(cfg->AD7124_GAIN4_REG_t) AD7124_WriteReg(dev, AD7124_GAIN4_REG, cfg->AD7124_GAIN4_REG_t, 3);
+    if(cfg->AD7124_GAIN5_REG_t) AD7124_WriteReg(dev, AD7124_GAIN5_REG, cfg->AD7124_GAIN5_REG_t, 3);
+    if(cfg->AD7124_GAIN6_REG_t) AD7124_WriteReg(dev, AD7124_GAIN6_REG, cfg->AD7124_GAIN6_REG_t, 3);
+    if(cfg->AD7124_GAIN7_REG_t) AD7124_WriteReg(dev, AD7124_GAIN7_REG, cfg->AD7124_GAIN7_REG_t, 3);
 
     printf_ATY_D("\r\n");
     return 0;
@@ -329,44 +342,46 @@ uint8_t AD7124_Config(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev){
             0100 sys full cal
             1000 sys zero cal
  */
-uint8_t AD7124_Calibrate(uint8_t calibrateType, struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_Calibrate(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg, uint8_t calibrateType){
     uint32_t regTrans = 0;
+    AD7124_Init(dev, dev->cfg);
+
     printf_ATY_D("%s--Calibrate: %02X", AD7124_ATY_TAG, calibrateType);
-    AD7124_WriteReg(AD7124_OFFS0_REG, 0x800000, 3, dev);
-    AD7124_WriteReg(AD7124_OFFS1_REG, 0x800000, 3, dev);
-    AD7124_WriteReg(AD7124_OFFS2_REG, 0x800000, 3, dev);
-    AD7124_WriteReg(AD7124_OFFS3_REG, 0x800000, 3, dev);
-    AD7124_WriteReg(AD7124_OFFS4_REG, 0x800000, 3, dev);
-    AD7124_WriteReg(AD7124_OFFS5_REG, 0x800000, 3, dev);
-    AD7124_WriteReg(AD7124_OFFS6_REG, 0x800000, 3, dev);
-    AD7124_WriteReg(AD7124_OFFS7_REG, 0x800000, 3, dev);
+    AD7124_WriteReg(dev, AD7124_OFFS0_REG, 0x800000, 3);
+    AD7124_WriteReg(dev, AD7124_OFFS1_REG, 0x800000, 3);
+    AD7124_WriteReg(dev, AD7124_OFFS2_REG, 0x800000, 3);
+    AD7124_WriteReg(dev, AD7124_OFFS3_REG, 0x800000, 3);
+    AD7124_WriteReg(dev, AD7124_OFFS4_REG, 0x800000, 3);
+    AD7124_WriteReg(dev, AD7124_OFFS5_REG, 0x800000, 3);
+    AD7124_WriteReg(dev, AD7124_OFFS6_REG, 0x800000, 3);
+    AD7124_WriteReg(dev, AD7124_OFFS7_REG, 0x800000, 3);
 
     if(calibrateType & AD7124_CALIBRATE_INT_FULL){
-        AD7124_WriteReg(AD7124_ADC_CTRL_REG, 0x0058, 2, dev);                   // int full cal at mid power
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_WriteReg(dev, AD7124_ADC_CTRL_REG, 0x0058, 2);                   // int full cal at mid power
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
         dev->delay(1500);    // 1300ms min
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
     }
     if(calibrateType & AD7124_CALIBRATE_INT_ZERO){
-        AD7124_WriteReg(AD7124_ADC_CTRL_REG, 0x0094, 2, dev);                   // int zero cal at full power
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_WriteReg(dev, AD7124_ADC_CTRL_REG, 0x0094, 2);                   // int zero cal at full power
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
         dev->delay(100);     // 80ms min
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
     }
     if(calibrateType & AD7124_CALIBRATE_SYS_FULL){
-        AD7124_WriteReg(AD7124_ADC_CTRL_REG, 0x00A0, 2, dev);                   // sys full cal
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_WriteReg(dev, AD7124_ADC_CTRL_REG, 0x00A0, 2);                   // sys full cal
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
         dev->delay(100);     // 80ms min
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
     }
     if(calibrateType & AD7124_CALIBRATE_SYS_ZERO){
-        AD7124_WriteReg(AD7124_ADC_CTRL_REG, 0x009C, 2, dev);                   // sys zero cal
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_WriteReg(dev, AD7124_ADC_CTRL_REG, 0x009C, 2);                   // sys zero cal
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
         dev->delay(100);     // 80ms min
-        AD7124_ReadReg(AD7124_ADC_CTRL_REG, &regTrans, 2, dev);
+        AD7124_ReadReg(dev, AD7124_ADC_CTRL_REG, &regTrans, 2);
     }
 
-    AD7124_WriteReg(AD7124_ADC_CTRL_REG, cfg->AD7124_ADC_CTRL_REG_t, 2, dev);   // detect mode
+    AD7124_WriteReg(dev, AD7124_ADC_CTRL_REG, cfg->AD7124_ADC_CTRL_REG_t, 2);   // detect mode
     printf_ATY_D("\r\n");
     dev->delay(1);
     return 0;
@@ -378,13 +393,13 @@ uint8_t AD7124_Calibrate(uint8_t calibrateType, struct AD7124_ATY_Cfg* cfg, stru
  * @param   dev
  * @return  uint8_t
  */
-uint8_t AD7124_ReadAllReg(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev){
+uint8_t AD7124_ReadAllReg(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg){
     uint8_t i = 0;
     uint32_t* p = (uint32_t*)cfg;
     printf_ATY_D("%s--AllRegs %d", AD7124_ATY_TAG, (sizeof(struct AD7124_ATY_Cfg) / sizeof(uint32_t)));
     for(i = 0; i < (sizeof(struct AD7124_ATY_Cfg) / sizeof(uint32_t)); i++){    // 0x00~0x38
         printf_ATY_D("\r\nReg 0x%02X: ", i);
-        AD7124_ReadReg(i, (p + i), 3, dev);
+        AD7124_ReadReg(dev, i, (p + i), 3);
     }
     // AD7124_ReadReg(AD7124_ADC_CTRL_REG, groupTrans, 2, dev);
     printf_ATY_D("\r\n");
@@ -394,238 +409,256 @@ uint8_t AD7124_ReadAllReg(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev
 #endif /* __AD7124_ATY_C */
 
 /************************************ etc *************************************/
-/* init */
-// #include "AD7124_ATY.h"
-// void AD7124_1_NSS_SET(uint8_t level){
-//     if(level == __ATY_HL_L)
-//         GPIO_SET_L(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin);
-//     else if(level == __ATY_HL_H)
-//         GPIO_SET_H(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin);
-// }
-// void AD7124_1_EN_SET(uint8_t level){ }
-// void AD7124_1_SYNC_SET(uint8_t level){ }
-// uint8_t AD7124_1_SPI(uint8_t* data_t, uint16_t len, uint8_t rw){
-//     if(rw == _ATY_RW_RW)
-//         return HAL_SPI_TransmitReceive(&hspi2, (uint8_t*)data_t, (uint8_t*)data_t, len, 1000);
-//     return 0;
-// }
-// struct AD7124_ATY_Dev AD7124_ATY_Dev_1 = {
-//     .id = 0,
-//     .nssSet = AD7124_1_NSS_SET,
-//     .enSet = AD7124_1_EN_SET,
-//     .syncSet = AD7124_1_SYNC_SET,
-//     .spiProcess = AD7124_1_SPI,
-//     .delay = HAL_Delay,
-//     .lock = __ATY_UNLOCKED,
-//     .debugEnable = 0,
-// };
-
-
-/* config template */
-// struct AD7124_ATY_Cfg AD7124_ATY_Cfg_CHIP_T = {
-//     .AD7124_ADC_CTRL_REG_t = 0x0580,
-//
-//     .AD7124_CFG0_REG_t = 0x09F0,
-//
-//     .AD7124_CH0_MAP_REG_t = 0x8211, // IC Temp, int vref
-// };
-// struct AD7124_ATY_Cfg AD7124_ATY_Cfg_NTC10_O1 = {
-//     .AD7124_ADC_CTRL_REG_t = 0x0580,
-//
-//     .AD7124_CFG1_REG_t = 0x09F0,
-//     .AD7124_FILT1_REG_t = 0x0060180,
-//     .AD7124_GAIN1_REG_t = 0x5558CC,
-//
-//     .AD7124_CH0_MAP_REG_t = 0x918D,
-// };
-// struct AD7124_ATY_Cfg AD7124_ATY_Cfg_RTD4_1 = {
-//     .AD7124_ADC_CTRL_REG_t = 0x0480,
-//     .AD7124_IO_CTRL1_REG_t = 0x000400,
-//     // .AD7124_ERREN_REG_t = 0x06FFFF,
-//
-//     .AD7124_CFG0_REG_t = 0x09E4,
-//     .AD7124_FILT0_REG_t = 0x0060180,
-//     .AD7124_GAIN0_REG_t = 0x5558CC,
-//     .AD7124_CH0_MAP_REG_t = 0x9211, //IC Temp
-//
-//     .AD7124_CFG1_REG_t = 0x09E4,
-//     .AD7124_FILT1_REG_t = 0x0060180,
-//     .AD7124_GAIN1_REG_t = 0x05558CC,
-//     .AD7124_CH1_MAP_REG_t = 0x9022,
-// };
-// struct AD7124_ATY_Cfg AD7124_ATY_Cfg_NTC1_1 = {
-//     .AD7124_ADC_CTRL_REG_t = 0x0480,
-//     .AD7124_IO_CTRL1_REG_t = 0x002040,
-//
-//     .AD7124_CFG1_REG_t = 0x09E1,
-//     .AD7124_FILT1_REG_t = 0x0060180,
-//     .AD7124_GAIN1_REG_t = 0x05558CC,
-//      // 500uA * 5.11K = 2.5Vref, 1K gain 2 max
-//     .AD7124_CH2_MAP_REG_t = 0x90A6,
-// };
-// struct AD7124_ATY_Cfg AD7124_ATY_Cfg_NTC10_1 = {
-//     .AD7124_ADC_CTRL_REG_t = 0x0580,
-//
-//     .AD7124_CFG1_REG_t = 0x09F0,
-//     .AD7124_FILT1_REG_t = 0x0060180,
-//     .AD7124_GAIN1_REG_t = 0x5558CC,
-//
-//     .AD7124_CH3_MAP_REG_t = 0x918D,
-//     .AD7124_CH4_MAP_REG_t = 0x91CF,
-// };
-// struct AD7124_ATY_Cfg AD7124_ATY_Cfg_TC_1 = {
-//     .AD7124_ADC_CTRL_REG_t = 0x0580,
-//     .AD7124_IO_CTRL2_REG_t = 0x0500,
-//
-//     .AD7124_CFG1_REG_t = 0x09F7,
-//     .AD7124_FILT1_REG_t = 0x0060180,
-//     .AD7124_GAIN1_REG_t = 0x5558CC,
-//
-//     .AD7124_CH5_MAP_REG_t = 0x9109,
-//     .AD7124_CH6_MAP_REG_t = 0x914B,
-// };
-
-
-/* use */
-// tested 20ms fastest at stm32f103cbt6, spi 18MBit/s, line 50mm
-
-// uint8_t group_AD7124_Data[5] = {0};
-
-// uint8_t adDetectType = 0;   // 0: IC temp / user channel, 1: RTD, 2: NTC1K, 34: NTC10K, 56: TC
-// uint8_t adInitFlag = 0;
-
-// uint32_t ad7124Code = 0;
-// uint8_t ad7124End = 0;
-// uint8_t ad7124State = 0;
-
-// #define AD_INIT_MAX_COUNT 8
-// void AD7124_Calc(uint8_t* codeGroup){
-//     if((codeGroup[4] & 0x80) != 0){
-//         adInitFlag++;
-//         if(adInitFlag > AD_INIT_MAX_COUNT){
-//             adInitFlag = 0;
-//         }
-//         return;
-//     }
-//
-//     if((codeGroup[4] & 0x0F) != adDetectType){
-//         adInitFlag++;
-//         if(adInitFlag > AD_INIT_MAX_COUNT)
-//             adInitFlag = 0;
-//         return;
-//     }
-//
-//     ad7124State = codeGroup[4];
-//     ad7124End = codeGroup[0];
-//     ad7124Code = (codeGroup[3] + (codeGroup[2] << 8) + (codeGroup[1] << 16));
-//
-//     float calcVol = 0, calcRes = 0, fastTempCalc = 0, aboveTempCalc = 0, belowTempCalc = 0;
-//     if((codeGroup[4] & 0x0F) == 0){                                             // IC Temp
-//         fastTempCalc = ((float)(ad7124Code - 0x800000) / 13584.0) - 272.5;
-//     }
-//     if((codeGroup[4] & 0x0F) == 1){                                             // RTD4
-//         calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 16);
-//     }
-//     if((codeGroup[4] & 0x0F) == 2){                                             // NTC1K
-//         calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 2);
-//     }
-//     if(((codeGroup[4] & 0x0F) == 3) || ((codeGroup[4] & 0x0F) == 4)){           // NTC10K
-//         calcRes = 10.0 * 1000.0 * ((double)((double)(ad7124Code - 0x800000) / (double)(0x1000000 - ad7124Code)));
-//     }
-//     if(((codeGroup[4] & 0x0F) == 5) || ((codeGroup[4] & 0x0F) == 6)){           // TC
-//         calcVol = (((float)ad7124Code - 8388608.0) * 2500.0 / (128.0 * 8388608.0));
-//     }
-// }
-
-// void AD7124_Detect(void){
-//     static uint8_t lastChannel = 0;
-//     if(lastChannel != adDetectType){
-//         lastChannel = adDetectType;
-//         adInitFlag = 0;
-//     }
-//     switch(adDetectType){
-//         case 0:
-//         case 1:
-//             if(adInitFlag == 0){
-//                 adInitFlag = 1;
-//                 // AD7124_Init(&AD7124_ATY_Cfg_CHIP_T, &AD7124_ATY_Dev_1);
-//                 AD7124_Init(&AD7124_ATY_Cfg_RTD4_1, &AD7124_ATY_Dev_1);
-//                 // AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
-//                 //     &AD7124_ATY_Cfg_RTD4_1, &AD7124_ATY_Dev_1);
-//             }
-//             AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
-//             AD7124_Calc(group_AD7124_Data);
-//             AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
-//             AD7124_Calc(group_AD7124_Data);
-//             break;
-//         case 2:
-//             if(adInitFlag == 0){
-//                 adInitFlag = 1;
-//                 AD7124_Init(&AD7124_ATY_Cfg_NTC1_1, &AD7124_ATY_Dev_1);
-//                 AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
-//                     &AD7124_ATY_Cfg_NTC1_1, &AD7124_ATY_Dev_1);
-//             }
-//             AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
-//             AD7124_Calc(group_AD7124_Data);
-//             break;
-//         case 3:
-//         case 4:
-//             if(adInitFlag == 0){
-//                 adInitFlag = 1;
-//                 AD7124_Init(&AD7124_ATY_Cfg_NTC10_1, &AD7124_ATY_Dev_1);
-//                 AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
-//                     &AD7124_ATY_Cfg_NTC10_1, &AD7124_ATY_Dev_1);
-//             }
-//             AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
-//             AD7124_Calc(group_AD7124_Data);
-//             AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
-//             AD7124_Calc(group_AD7124_Data);
-//             break;
-//         case 5:
-//         case 6:
-//             if(adInitFlag == 0){
-//                 adInitFlag = 1;
-//                 AD7124_Init(&AD7124_ATY_Cfg_TC_1, &AD7124_ATY_Dev_1);
-//                 AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
-//                     &AD7124_ATY_Cfg_TC_1, &AD7124_ATY_Dev_1);
-//             }
-//             AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
-//             AD7124_Calc(group_AD7124_Data);
-//             AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
-//             AD7124_Calc(group_AD7124_Data);
-//             break;
-//         default:
-//             break;
-//     }
-// }
-
-/* calc */
-// // IC Temp
-// fastTempCalc = ((float)(ad7124Code - 0x800000) / 13584.0) - 272.5;
-
-// // RTD4
-// calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 16);
-// fastTempCalc = ALGO_Temp_RTD_Res_Fast(calcRes);
-// aboveTempCalc = ALGO_Temp_RTD_Res_Above(calcRes);
-// belowTempCalc = ALGO_Temp_RTD_Res_Below(calcRes);
-
-// // NTC1K
-// calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 2);
-// fastTempCalc = ALGO_ResToKelvinTemp((calcRes / 1000.0), 1.0, 3950);
-// // NTC10K
-// calcVol = (((float)ad7124Code - 8388608.0) * 2500.0 / (1.0 * 8388608.0));
-// calcRes = ((calcVol * 10.0) / (2500.0 - calcVol));
-// fastTempCalc = ALGO_ResToKelvinTemp(calcRes, 10.0, 3380);
-
-// // TC
-// calcVol = (((float)ad7124Code - 8388608.0) * 2500.0 / (128.0 * 8388608.0));
-// float coldTemp = 25.0;
-// float calcVolCold = ALGO_Temp_TC_TempToVol('T', coldTemp);
-// calcVol += calcVolCold;
-// aboveTempCalc = ALGO_Temp_TC_VolToTemp('T', calcVol);
-// belowTempCalc = ALGO_Temp_TC_VolToTemp('T', calcVol);
-// fastTempCalc = aboveTempCalc;
+/* init
+// AD7124 ----------------------------------------------------------------------
+#include "AD7124_ATY.h"
+uint8_t group_AD7124_Data[5] = {0};
+void AD7124_1_NSS_SET(uint8_t level){
+    if(level == __ATY_HL_L)
+        HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_RESET);
+    else if(level == __ATY_HL_H)
+        HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_SET);
+}
+void AD7124_1_EN_SET(uint8_t level){}
+void AD7124_1_SYNC_SET(uint8_t level){}
+uint8_t AD7124_1_SPI(uint8_t* data_t, uint16_t len){
+    return HAL_SPI_TransmitReceive(&hspi2, (uint8_t*)data_t, (uint8_t*)data_t, len, 1000);
+}
+
+// config template
+struct AD7124_ATY_Cfg AD7124_ATY_Cfg_CHIP_T = {
+    .AD7124_ADC_CTRL_REG_t = 0x0580,
+
+    .AD7124_CFG0_REG_t = 0x09F0,
+
+    .AD7124_CH0_MAP_REG_t = 0x8211, // IC Temp, int vref
+};
+struct AD7124_ATY_Cfg AD7124_ATY_Cfg_NTC10_O1 = {
+    .AD7124_ADC_CTRL_REG_t = 0x0580,
+
+    .AD7124_CFG1_REG_t = 0x09F0,
+    .AD7124_FILT1_REG_t = 0x0060180,
+    .AD7124_GAIN1_REG_t = 0x5558CC,
+
+    .AD7124_CH0_MAP_REG_t = 0x918D,
+};
+
+struct AD7124_ATY_Cfg AD7124_ATY_Cfg_RTD4_1 = {
+    .AD7124_ADC_CTRL_REG_t = 0x0480,
+    .AD7124_IO_CTRL1_REG_t = 0x000400,
+    // .AD7124_ERREN_REG_t = 0x06FFFF,
+
+    .AD7124_CFG0_REG_t = 0x09E4,
+    .AD7124_FILT0_REG_t = 0x0060180,
+    .AD7124_GAIN0_REG_t = 0x5558CC,
+    .AD7124_CH0_MAP_REG_t = 0x9211, //IC Temp
+
+    .AD7124_CFG1_REG_t = 0x09E4,
+    .AD7124_FILT1_REG_t = 0x0060180,
+    .AD7124_GAIN1_REG_t = 0x05558CC,
+    .AD7124_CH1_MAP_REG_t = 0x9022,
+};
+struct AD7124_ATY_Cfg AD7124_ATY_Cfg_NTC1_1 = {
+    .AD7124_ADC_CTRL_REG_t = 0x0480,
+    .AD7124_IO_CTRL1_REG_t = 0x002040,
+
+    .AD7124_CFG1_REG_t = 0x09E1,
+    .AD7124_FILT1_REG_t = 0x0060180,
+    .AD7124_GAIN1_REG_t = 0x05558CC,
+     // 500uA * 5.11K = 2.5Vref, 1K gain 2 max
+    .AD7124_CH2_MAP_REG_t = 0x90A6,
+};
+struct AD7124_ATY_Cfg AD7124_ATY_Cfg_NTC10_1 = {
+    .AD7124_ADC_CTRL_REG_t = 0x0580,
+
+    .AD7124_CFG1_REG_t = 0x09F0,
+    .AD7124_FILT1_REG_t = 0x0060180,
+    .AD7124_GAIN1_REG_t = 0x5558CC,
+
+    .AD7124_CH3_MAP_REG_t = 0x918D,
+    .AD7124_CH4_MAP_REG_t = 0x91CF,
+};
+struct AD7124_ATY_Cfg AD7124_ATY_Cfg_TC_1 = {
+    .AD7124_ADC_CTRL_REG_t = 0x0580,
+    .AD7124_IO_CTRL2_REG_t = 0x0500,
+
+    .AD7124_CFG1_REG_t = 0x09F7,
+    .AD7124_FILT1_REG_t = 0x0060180,
+    .AD7124_GAIN1_REG_t = 0x5558CC,
+
+    .AD7124_CH5_MAP_REG_t = 0x9109,
+    .AD7124_CH6_MAP_REG_t = 0x914B,
+};
+
+struct AD7124_ATY_Dev AD7124_ATY_Dev_1 = {
+    .enSet = AD7124_1_EN_SET,
+    .syncSet = AD7124_1_SYNC_SET,
+    .nssSet = AD7124_1_NSS_SET,
+    .spiProcess = AD7124_1_SPI,
+    .initFlag = 0,
+
+    .addr = 0,
+    .id = 0,
+    .data = group_AD7124_Data,
+    // .cfg = &AD7124_ATY_Cfg_NTC10_O1,
+    .cfg = &AD7124_ATY_Cfg_CHIP_T,
+
+    .delay = HAL_Delay,
+
+    .lock = __ATY_UNLOCKED
+};
+*/
+
+/* use
+// tested 18ms fastest at stm32f103cbt6 72MHz, spi 18MBit/s, line 50mm, signal channel IC T
+#define AD_INIT_MAX_COUNT 8
+uint8_t adDetectType = 0;   // 0: IC Temp / user channel, 1: RTD, 2: NTC1K, 34: NTC10K, 56: TC
+uint32_t ad7124Code = 0;
+
+void AD7124_Calc(uint8_t* codeGroup){
+    if((codeGroup[4] & 0x80) != 0){
+        AD7124_ATY_Dev_1.initFlag++;
+        if(AD7124_ATY_Dev_1.initFlag > AD_INIT_MAX_COUNT){
+            AD7124_ATY_Dev_1.initFlag = 0;
+        }
+        return;
+    }
+
+    if((codeGroup[4] & 0x0F) != adDetectType){
+        AD7124_ATY_Dev_1.initFlag++;
+        if(AD7124_ATY_Dev_1.initFlag > AD_INIT_MAX_COUNT)
+            AD7124_ATY_Dev_1.initFlag = 0;
+        return;
+    }
+
+    ad7124Code = (codeGroup[3] + (codeGroup[2] << 8) + (codeGroup[1] << 16));
 
+    printf_ATY("\r\nChip: %f", (((float)(ad7124Code - 0x800000) / 13584.0) - 272.5));
+
+    // Type Calc
+    float calcVol = 0, calcRes = 0, fastTempCalc = 0, aboveTempCalc = 0, belowTempCalc = 0;
+    if((codeGroup[4] & 0x0F) == 0){                                             // IC Temp
+        fastTempCalc = ((float)(ad7124Code - 0x800000) / 13584.0) - 272.5;
+    }
+    if((codeGroup[4] & 0x0F) == 1){                                             // RTD4
+        calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 16);
+    }
+    if((codeGroup[4] & 0x0F) == 2){                                             // NTC1K
+        calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 2);
+    }
+    if(((codeGroup[4] & 0x0F) == 3) || ((codeGroup[4] & 0x0F) == 4)){           // NTC10K
+        calcRes = 10.0 * 1000.0 * ((double)((double)(ad7124Code - 0x800000) / (double)(0x1000000 - ad7124Code)));
+    }
+    if(((codeGroup[4] & 0x0F) == 5) || ((codeGroup[4] & 0x0F) == 6)){           // TC
+        calcVol = (((float)ad7124Code - 8388608.0) * 2500.0 / (128.0 * 8388608.0));
+    }
+
+    // Type Table, put table out of function!!
+    const uint16_t RT_table_N30toP50_1_T_size = 81;
+    const double RT_table_N30toP50_1_T[81] = {-30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50};
+    const double RT_table_PT1000_N30toP50_1_R[81] = {882.21656767, 886.1604620248771, 890.1030863723519, 894.0444460833969, 897.984546428592, 901.9233925781249, 905.8609896017921, 909.797342468997, 913.7324560487519, 917.666335109677, 921.5989843200001, 925.530408247557, 929.460611359792, 933.389598023757, 937.317372506112, 941.243938973125, 945.1693014906721, 949.0934640242369, 953.0164304389119, 956.938204499397, 960.85878987, 964.7781901146369, 968.696408696832, 972.613448979717, 976.529314226032, 980.444007598125, 984.3575321579519, 988.2698908670769, 992.1810865866721, 996.091122077517, 1000, 1003.9077225, 1007.81429, 1011.7197025, 1015.6239599999999, 1019.5270625000002, 1023.4290100000001, 1027.3298025, 1031.2294399999998, 1035.1279225, 1039.02525, 1042.9214224999998, 1046.81644, 1050.7103025, 1054.60301, 1058.4945625000003, 1062.38496, 1066.2742025, 1070.16229, 1074.0492225, 1077.935, 1081.8196225, 1085.70309, 1089.5854024999999, 1093.46656, 1097.3465625000001, 1101.22541, 1105.1031025, 1108.97964, 1112.8550225, 1116.7292499999999, 1120.6023225, 1124.47424, 1128.3450025000002, 1132.2146100000002, 1136.0830625, 1139.95036, 1143.8165025, 1147.68149, 1151.5453224999999, 1155.408, 1159.2695224999998, 1163.12989, 1166.9891025000002, 1170.84716, 1174.7040625, 1178.5598100000002, 1182.4144025, 1186.26784, 1190.1201225, 1193.97125};
+    const double RT_table_NTC10K_B3950_N30toP50_1_R[81] = {200203.9024466842, 187316.35371436414, 175353.56517945265, 164242.815037761, 153917.57353446394, 144316.93726809666, 135385.11855020453, 127070.98414555467, 119327.63833441163, 112112.04578468086, 105384.690206038, 99109.26518793346, 93252.3940049376, 87783.37551199133, 82673.95355365716, 77898.10757980836, 73431.86239916032, 69253.11521500889, 65341.47827746307, 61678.13565594302, 58245.71278707882, 55028.15758840015, 52010.63204917008, 49179.41331794596, 46521.80340337541, 44026.046691571566, 41681.25456127495, 39477.33644786429, 37404.936769989145, 35455.37718893085, 33620.60372143574, 31893.138272305434, 30266.034194017953, 28732.835517560583, 27287.53953191174, 25924.56241959352, 24638.70768276219, 23425.137118719744, 22279.344125776763, 21197.12914032421, 20174.57702398485, 19208.036236013788, 18294.09964087108, 17429.586814247774, 16611.527722935953, 15837.147664908136, 15103.853365929419, 14409.220138062792, 13750.980013633698, 13127.010775676536, 12535.32581266281, 11974.064731474306, 11441.484668193882, 10935.952241391826, 10455.936097237052, 10000, 9566.796425378521, 9155.060617602236, 8763.605074487228, 8391.314427550227, 8037.140686973136, 7700.09882366077, 7379.2626628761145, 7073.761065987096, 6782.774378735532, 6505.531126156567, 6241.304935849771, 5989.411672745506, 5749.206769831047, 5520.082740513648, 5301.466859409668, 5092.818999369683, 4893.62961348718, 4703.417851699504, 4521.7298023814565, 4348.136850059472, 4182.234141043995, 4023.6391493935307, 3871.990336190894, 3726.945895634597, 3588.1825819290834};
+    const double RT_table_NTC10K_B3380_N30toP50_1_R[81] = {129916.73842576398, 122726.45506217859, 115987.98389609528, 109669.80710548842, 103742.81092588141, 98180.08736222527, 92956.75343550005, 88049.78631286524, 83437.87283482423, 79101.27210022854, 75021.689901878, 71182.16392373295, 67566.95871677202, 64161.46956567978, 60952.13444397613, 57926.35333195929, 55072.41424084727, 52379.42534858893, 49837.25270871057, 47436.46304390781, 45168.27118147633, 43024.49172859917, 40997.49462244794, 39080.16422340271, 37265.86164983361, 35548.39008012747, 33921.96277228722, 32381.173573736873, 30920.9697141643, 29536.62669253702, 28223.725086022154, 26978.129123593826, 25795.96688077618, 24673.61196437721, 23607.66656734277, 22594.945784110834, 21632.463086167136, 20717.41686598908, 19847.177965288593, 19019.278110503867, 18231.399184902846, 17481.363272511575, 16767.123414418118, 16086.755022872807, 15438.44790305672, 14820.498836453826, 14231.304683479702, 13669.355966418227, 13133.230896827301, 12621.589814422336, 12133.170007053395, 11666.78088378108, 11221.299475246835, 10795.666237541593, 10388.881137620136, 10000, 9628.131096037672, 9272.431958502, 8932.106405476528, 8606.401758829414, 8294.606243598528, 7996.046555661133, 7710.085585997876, 7436.120290726329, 7173.579696877923, 6921.923034627457, 6680.637987362497, 6449.239051606348, 6227.265999385221, 6014.2824361639205, 5809.8744479667575, 5613.649331755301, 5425.234403555528, 5244.275879215621, 5070.437823035709, 4903.401159843523, 4742.862746398391, 4588.534498291319, 4440.142568773257, 4297.426576188887, 4160.138876920097};
+    if(ntcType == 0){
+        fastTempCalc = ALGO_RT_Table_R2T(calcRes * 1.0,
+            RT_table_N30toP50_1_T,
+            RT_table_Custom3950_N30toP50_1_R,
+            RT_table_N30toP50_1_T_size);
+    }
+    else if(ntcType == 1){
+        fastTempCalc = ALGO_RT_Table_R2T(calcRes * 1.0,
+            RT_table_N30toP50_1_T,
+            RT_table_NTC10K_B3380_N30toP50_1_R,
+            RT_table_N30toP50_1_T_size);
+    }
+    else if(ntcType == 2){
+        fastTempCalc = ALGO_RT_Table_R2T(calcRes * 1.0,
+            RT_table_N30toP50_1_T,
+            RT_table_NTC10K_B3950_N30toP50_1_R,
+            RT_table_N30toP50_1_T_size);
+    }
+    // offset
+    fastTempCalc = (fastTempCalc * 1000.0) + 180.0;
+}
+
+void AD7124_Detect(void){
+    static uint8_t lastChannel = 0;
+    if(lastChannel != adDetectType){
+        lastChannel = adDetectType;
+        AD7124_ATY_Dev_1.initFlag++;
+        if(AD7124_ATY_Dev_1.initFlag > AD_INIT_MAX_COUNT)
+            AD7124_ATY_Dev_1.initFlag = 0;
+        return;
+    }
+    switch(adDetectType){
+        case 0:
+        case 1:
+            // AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
+            //     &AD7124_ATY_Cfg_RTD4_1, &AD7124_ATY_Dev_1);
+            AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
+            AD7124_Calc(group_AD7124_Data);
+            AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
+            AD7124_Calc(group_AD7124_Data);
+            break;
+        case 2:
+            AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
+                &AD7124_ATY_Cfg_NTC1_1, &AD7124_ATY_Dev_1);
+            AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
+            AD7124_Calc(group_AD7124_Data);
+            break;
+        case 3:
+        case 4:
+            AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
+                &AD7124_ATY_Cfg_NTC10_1, &AD7124_ATY_Dev_1);
+            AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
+            AD7124_Calc(group_AD7124_Data);
+            AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
+            AD7124_Calc(group_AD7124_Data);
+            break;
+        case 5:
+        case 6:
+            AD7124_Calibrate(AD7124_CALIBRATE_INT_FULL | AD7124_CALIBRATE_INT_ZERO,
+                &AD7124_ATY_Cfg_TC_1, &AD7124_ATY_Dev_1);
+            AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
+            AD7124_Calc(group_AD7124_Data);
+            AD7124_ReadData(group_AD7124_Data, &AD7124_ATY_Dev_1);
+            AD7124_Calc(group_AD7124_Data);
+            break;
+        default:
+            break;
+    }
+}
+*/
+
+
+/* calc
+// IC Temp
+fastTempCalc = ((float)(ad7124Code - 0x800000) / 13584.0) - 272.5;
+
+// RTD4
+calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 16);
+fastTempCalc = ALGO_Temp_RTD_Res_Fast(calcRes);
+aboveTempCalc = ALGO_Temp_RTD_Res_Above(calcRes);
+belowTempCalc = ALGO_Temp_RTD_Res_Below(calcRes);
+
+// NTC1K
+calcRes = AD7124_DataToRes(ad7124Code, 24, 5110.0, 2);
+fastTempCalc = ALGO_ResToKelvinTemp((calcRes / 1000.0), 1.0, 3950);
+
+// NTC10K
+calcVol = (((float)ad7124Code - 8388608.0) * 2500.0 / (1.0 * 8388608.0));
+calcRes = ((calcVol * 10.0) / (2500.0 - calcVol));
+fastTempCalc = ALGO_ResToKelvinTemp(calcRes, 10.0, 3380);
+
+// TC
+calcVol = (((float)ad7124Code - 8388608.0) * 2500.0 / (128.0 * 8388608.0));
+float coldTemp = 25.0;
+float calcVolCold = ALGO_Temp_TC_TempToVol('T', coldTemp);
+calcVol += calcVolCold;
+aboveTempCalc = ALGO_Temp_TC_VolToTemp('T', calcVol);
+belowTempCalc = ALGO_Temp_TC_VolToTemp('T', calcVol);
+fastTempCalc = aboveTempCalc;
+*/
 
 /******************************************************************************/
 

+ 20 - 20
AD7124_ATY.h

@@ -1,7 +1,7 @@
 /**
 * @file AD7124_ATY.h
 *
-* @param Project DEVICE_GENERAL_ATY_LIB
+* @param Project DEVICE_DRIVER_ATY_LIB
 *
 * @author ATY
 *
@@ -40,8 +40,7 @@
 /******************************************************************************/
 
 
-struct AD7124_ATY_Cfg
-{
+struct AD7124_ATY_Cfg{
     uint32_t AD7124_STATUS_REG_t;           // r
     uint32_t AD7124_ADC_CTRL_REG_t;
     uint32_t AD7124_DATA_REG_t;             // r
@@ -106,36 +105,37 @@ struct AD7124_ATY_Cfg
     uint32_t AD7124_GAIN7_REG_t;
 };
 
-struct AD7124_ATY_Dev
-{
-    uint8_t addr;
-    uint8_t id;
-
-    void (*nssSet)(uint8_t level);
+struct AD7124_ATY_Dev{
     void (*enSet)(uint8_t level);
     void (*syncSet)(uint8_t level);
+    void (*nssSet)(uint8_t level);
+    uint8_t(*spiProcess)(uint8_t* data_t, uint16_t len);
+    uint8_t initFlag;
 
-    uint8_t(*spiProcess)(uint8_t* data_t, uint16_t len, uint8_t rw);
+    uint8_t addr;
+    uint8_t id;
+    uint8_t* data;
+    struct AD7124_ATY_Cfg* cfg;
 
     void (*delay)(uint32_t t);
 
     uint8_t lock;
 };
 
-uint8_t AD7124_WriteRead(uint8_t* data, uint8_t len, struct AD7124_ATY_Dev* dev);
+uint8_t AD7124_WriteRead(struct AD7124_ATY_Dev* dev, uint8_t* data, uint8_t len);
 uint8_t AD7124_Reset(struct AD7124_ATY_Dev* dev);
-uint8_t AD7124_ReadId(uint8_t* id, struct AD7124_ATY_Dev* dev);
-uint8_t AD7124_WriteReg(uint8_t regAddr, uint32_t data, uint8_t len, struct AD7124_ATY_Dev* dev);
-uint8_t AD7124_ReadReg(uint8_t regAddr, uint32_t* data, uint8_t len, struct AD7124_ATY_Dev* dev);
-uint8_t AD7124_ReadData(uint8_t* data, struct AD7124_ATY_Dev* dev);
-uint8_t AD7124_ReadStatus(uint8_t* status, struct AD7124_ATY_Dev* dev);
+uint8_t AD7124_ReadId(struct AD7124_ATY_Dev* dev, uint8_t* id);
+uint8_t AD7124_WriteReg(struct AD7124_ATY_Dev* dev, uint8_t regAddr, uint32_t data, uint8_t len);
+uint8_t AD7124_ReadReg(struct AD7124_ATY_Dev* dev, uint8_t regAddr, uint32_t* data, uint8_t len);
+uint8_t AD7124_ReadData(struct AD7124_ATY_Dev* dev, uint8_t* data);
+uint8_t AD7124_ReadStatus(struct AD7124_ATY_Dev* dev, uint8_t* status);
 float AD7124_DataToRes(uint32_t data, uint8_t resolution, float refRes, uint8_t gain);
 float AD7124_DataToResDefault(uint32_t data);
-uint8_t AD7124_Init(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev);
-uint8_t AD7124_Config(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev);
-uint8_t AD7124_ReadAllReg(struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev);
+uint8_t AD7124_Init(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg);
+uint8_t AD7124_Config(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg);
+uint8_t AD7124_ReadAllReg(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg);
 
-uint8_t AD7124_Calibrate(uint8_t calibrateType, struct AD7124_ATY_Cfg* cfg, struct AD7124_ATY_Dev* dev);
+uint8_t AD7124_Calibrate(struct AD7124_ATY_Dev* dev, struct AD7124_ATY_Cfg* cfg, uint8_t calibrateType);
 #define AD7124_CALIBRATE_INT_FULL 0x01
 #define AD7124_CALIBRATE_INT_ZERO 0x02
 #define AD7124_CALIBRATE_SYS_FULL 0x04

+ 1 - 0
ALGO_Bat_ATY.c

@@ -21,6 +21,7 @@
 * @version
 *       - 1_01_230107 > ATY
 *           -# Preliminary version, first Release
+* @todo not real test
 ********************************************************************************
 */
 

+ 86 - 83
ALGO_Kalman_ATY.c

@@ -18,14 +18,16 @@
 *
 * @brief functions of Kalman
 *
+* @note
+*       https://www.kalmanfilter.net/
+*       https://github.com/xiahouzuoxin/kalman_filter
+*       https://blog.csdn.net/whereismatrix/article/details/79920748
+*
 * @version
 *       - 1_01_220605 > ATY
 *           -# Preliminary version, first Release
 *       - 1_02_230108 > ATY
 *           -# Finish and test 2D
-* @see https://www.kalmanfilter.net/
-* @see https://github.com/xiahouzuoxin/kalman_filter
-* @see https://blog.csdn.net/whereismatrix/article/details/79920748
 ********************************************************************************
 */
 
@@ -264,88 +266,89 @@ void ALGO_Kalman_Test(void){
     }
 }
 
+/*
 // debug output data format: $y1a y1b;$y2a y2b;...------------------------------
+$0.732202 0.732166;$1.107485 0.923521;$0.832648 0.891278;$0.997930 0.921472;
+$0.743661 0.878040;$0.928340 0.889176;$0.546396 0.818120;$0.510484 0.757106;
+$0.114057 0.633303;$0.181101 0.547962;$-0.103150 0.426716;$-0.561716 0.244303;
+$-0.307147 0.143145;$-0.921523 -0.051368;$-0.626582 -0.156174;$-0.817900 -0.276524;
+$-0.899243 -0.389642;$-1.011869 -0.502578;$-0.948660 -0.583498;$-1.024685 -0.663502;
+$-1.078591 -0.738754;$-0.854667 -0.759765;$-0.905492 -0.786177;$-0.548572 -0.743116;
+$-0.737286 -0.742059;$-0.450227 -0.689175;$-1.032790 -0.751442;$-0.293712 -0.668498;
+$-0.159926 -0.576342;$-0.117551 -0.493208;$0.363302 -0.338006;$0.637550 -0.161233;
+$0.284187 -0.080522;$0.737519 0.067708;$0.521005 0.149846;$0.893311 0.284563;
+$1.054081 0.424001;$0.525526 0.442397;$0.782144 0.503960;$1.009261 0.595521;
+$0.967746 0.662969;$1.229197 0.765570;$1.179795 0.840628;$0.998553 0.869244;
+$0.806697 0.857911;$0.615047 0.813903;$0.003506 0.667058;$0.023320 0.550412;
+$0.510523 0.543184;$0.020320 0.448441;$-0.168222 0.336701;$-0.358753 0.210684;
+$-0.424160 0.095649;$-0.492052 -0.010843;$-0.425293 -0.085942;$-0.460660 -0.153841;
+$-0.712114 -0.255001;$-1.311701 -0.446476;$-0.815038 -0.513260;$-0.827395 -0.570182;
+$-0.946493 -0.638370;$-0.962119 -0.697033;$-0.849309 -0.724626;$-0.733573 -0.726247;
+$-0.680960 -0.718041;$-0.742870 -0.722540;$-0.529109 -0.687490;$-0.567446 -0.665738;
+$-0.136456 -0.569832;$-0.199753 -0.502773;$0.169624 -0.380934;$0.231133 -0.270027;
+$0.686898 -0.096631;$0.284297 -0.027606;$0.491547 0.066465;$0.766148 0.193248;
+$0.808002 0.304642;$1.106872 0.450007;$1.134952 0.574120;$0.806723 0.616268;
+$1.119804 0.707509;$0.931759 0.748143;$1.326805 0.852998;$0.890237 0.859745;
+$0.653111 0.822303;$0.973650 0.849727;$0.903934 0.859550;$0.350950 0.767391;
+$0.088230 0.644326;$0.208081 0.565278;$-0.084471 0.447543;$-0.272629 0.317047;
+$-0.352162 0.195785;$-0.748851 0.024616;$-0.887943 -0.140741;$-0.736057 -0.248613;
+$-0.939653 -0.373830;$-1.119212 -0.508894;$-0.944213 -0.587774;$-0.761944 -0.619334;
+$-0.988381 -0.686206;$-0.681791 -0.685406;$-0.900586 -0.724397;$-1.064615 -0.786045;
+$-0.843333 -0.796425;$-0.718142 -0.782240;$-0.138929 -0.665672;$-0.583088 -0.650707;
+$-0.460869 -0.616308;$-0.050059 -0.513703;$0.101613 -0.402207;$0.150226 -0.302106;
+$0.593740 -0.139777;$0.454790 -0.032041;$0.612092 0.084677;$0.829426 0.219626;
+$0.899205 0.342766;$1.024959 0.466381;$1.159378 0.591953;$0.977459 0.661807;
 
-// $0.732202 0.732166;$1.107485 0.923521;$0.832648 0.891278;$0.997930 0.921472;
-// $0.743661 0.878040;$0.928340 0.889176;$0.546396 0.818120;$0.510484 0.757106;
-// $0.114057 0.633303;$0.181101 0.547962;$-0.103150 0.426716;$-0.561716 0.244303;
-// $-0.307147 0.143145;$-0.921523 -0.051368;$-0.626582 -0.156174;$-0.817900 -0.276524;
-// $-0.899243 -0.389642;$-1.011869 -0.502578;$-0.948660 -0.583498;$-1.024685 -0.663502;
-// $-1.078591 -0.738754;$-0.854667 -0.759765;$-0.905492 -0.786177;$-0.548572 -0.743116;
-// $-0.737286 -0.742059;$-0.450227 -0.689175;$-1.032790 -0.751442;$-0.293712 -0.668498;
-// $-0.159926 -0.576342;$-0.117551 -0.493208;$0.363302 -0.338006;$0.637550 -0.161233;
-// $0.284187 -0.080522;$0.737519 0.067708;$0.521005 0.149846;$0.893311 0.284563;
-// $1.054081 0.424001;$0.525526 0.442397;$0.782144 0.503960;$1.009261 0.595521;
-// $0.967746 0.662969;$1.229197 0.765570;$1.179795 0.840628;$0.998553 0.869244;
-// $0.806697 0.857911;$0.615047 0.813903;$0.003506 0.667058;$0.023320 0.550412;
-// $0.510523 0.543184;$0.020320 0.448441;$-0.168222 0.336701;$-0.358753 0.210684;
-// $-0.424160 0.095649;$-0.492052 -0.010843;$-0.425293 -0.085942;$-0.460660 -0.153841;
-// $-0.712114 -0.255001;$-1.311701 -0.446476;$-0.815038 -0.513260;$-0.827395 -0.570182;
-// $-0.946493 -0.638370;$-0.962119 -0.697033;$-0.849309 -0.724626;$-0.733573 -0.726247;
-// $-0.680960 -0.718041;$-0.742870 -0.722540;$-0.529109 -0.687490;$-0.567446 -0.665738;
-// $-0.136456 -0.569832;$-0.199753 -0.502773;$0.169624 -0.380934;$0.231133 -0.270027;
-// $0.686898 -0.096631;$0.284297 -0.027606;$0.491547 0.066465;$0.766148 0.193248;
-// $0.808002 0.304642;$1.106872 0.450007;$1.134952 0.574120;$0.806723 0.616268;
-// $1.119804 0.707509;$0.931759 0.748143;$1.326805 0.852998;$0.890237 0.859745;
-// $0.653111 0.822303;$0.973650 0.849727;$0.903934 0.859550;$0.350950 0.767391;
-// $0.088230 0.644326;$0.208081 0.565278;$-0.084471 0.447543;$-0.272629 0.317047;
-// $-0.352162 0.195785;$-0.748851 0.024616;$-0.887943 -0.140741;$-0.736057 -0.248613;
-// $-0.939653 -0.373830;$-1.119212 -0.508894;$-0.944213 -0.587774;$-0.761944 -0.619334;
-// $-0.988381 -0.686206;$-0.681791 -0.685406;$-0.900586 -0.724397;$-1.064615 -0.786045;
-// $-0.843333 -0.796425;$-0.718142 -0.782240;$-0.138929 -0.665672;$-0.583088 -0.650707;
-// $-0.460869 -0.616308;$-0.050059 -0.513703;$0.101613 -0.402207;$0.150226 -0.302106;
-// $0.593740 -0.139777;$0.454790 -0.032041;$0.612092 0.084677;$0.829426 0.219626;
-// $0.899205 0.342766;$1.024959 0.466381;$1.159378 0.591953;$0.977459 0.661807;
-
-// <!DOCTYPE html>
-// <html>
-// <head><title>Line</title></head>
-// <body>
-// <textarea id="dataInput" style="width: 795px;" placeholder="$y1a y1b;$y2a y2b;..."
-// onchange="plotGraph()"></textarea><br>
-// <canvas id="graphCanvas" width="800" height="400"></canvas>
-// <script>
-// function parseData(input) {
-//     const records = input.trim().split(';').filter(r => r.trim() !== '');
-//     const s1 = [], s2 = [];
-//     for (let r of records) {
-//         if (!r.startsWith('$')) continue;
-//         const vals = r.substring(1).trim().split(/\s+/);
-//         if (vals.length !== 2) continue;
-//         const y1 = parseFloat(vals[0]), y2 = parseFloat(vals[1]);
-//         if (isNaN(y1) || isNaN(y2)) continue;
-//         s1.push(y1); s2.push(y2);
-//     }
-//     return { s1, s2 };
-// }
-// function plotGraph() {
-//     const { s1, s2 } = parseData(document.getElementById('dataInput').value);
-//     if (s1.length === 0 || s2.length === 0) { alert('No valid data'); return; }
-//     const canvas = document.getElementById('graphCanvas');
-//     const ctx = canvas.getContext('2d');
-//     ctx.clearRect(0, 0, canvas.width, canvas.height);
-//     const allY = [...s1, ...s2];
-//     let minY = Math.min(...allY), maxY = Math.max(...allY);
-//     const margin = (maxY - minY) * 0.05 || 0.1;
-//     minY -= margin; maxY += margin;
-//     const n = s1.length, w = canvas.width, h = canvas.height;
-//     function mapY(y) { return h - ((y - minY) / (maxY - minY)) * h; }
-//     ctx.strokeStyle = '#1f77b4'; ctx.beginPath();
-//     for (let i = 0; i < n; i++) {
-//         const x = (i / (n - 1)) * w, y = mapY(s1[i]);
-//         if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
-//     }
-//     ctx.stroke();
-//     ctx.strokeStyle = '#ff7f0e'; ctx.beginPath();
-//     for (let i = 0; i < n; i++) {
-//         const x = (i / (n - 1)) * w, y = mapY(s2[i]);
-//         if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
-//     }
-//     ctx.stroke();
-// }
-// </script>
-// </body>
-// </html>
+<!DOCTYPE html>
+<html>
+<head><title>Line</title></head>
+<body>
+<textarea id="dataInput" style="width: 795px;" placeholder="$y1a y1b;$y2a y2b;..."
+onchange="plotGraph()"></textarea><br>
+<canvas id="graphCanvas" width="800" height="400"></canvas>
+<script>
+function parseData(input) {
+    const records = input.trim().split(';').filter(r => r.trim() !== '');
+    const s1 = [], s2 = [];
+    for (let r of records) {
+        if (!r.startsWith('$')) continue;
+        const vals = r.substring(1).trim().split(/\s+/);
+        if (vals.length !== 2) continue;
+        const y1 = parseFloat(vals[0]), y2 = parseFloat(vals[1]);
+        if (isNaN(y1) || isNaN(y2)) continue;
+        s1.push(y1); s2.push(y2);
+    }
+    return { s1, s2 };
+}
+function plotGraph() {
+    const { s1, s2 } = parseData(document.getElementById('dataInput').value);
+    if (s1.length === 0 || s2.length === 0) { alert('No valid data'); return; }
+    const canvas = document.getElementById('graphCanvas');
+    const ctx = canvas.getContext('2d');
+    ctx.clearRect(0, 0, canvas.width, canvas.height);
+    const allY = [...s1, ...s2];
+    let minY = Math.min(...allY), maxY = Math.max(...allY);
+    const margin = (maxY - minY) * 0.05 || 0.1;
+    minY -= margin; maxY += margin;
+    const n = s1.length, w = canvas.width, h = canvas.height;
+    function mapY(y) { return h - ((y - minY) / (maxY - minY)) * h; }
+    ctx.strokeStyle = '#1f77b4'; ctx.beginPath();
+    for (let i = 0; i < n; i++) {
+        const x = (i / (n - 1)) * w, y = mapY(s1[i]);
+        if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
+    }
+    ctx.stroke();
+    ctx.strokeStyle = '#ff7f0e'; ctx.beginPath();
+    for (let i = 0; i < n; i++) {
+        const x = (i / (n - 1)) * w, y = mapY(s2[i]);
+        if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);
+    }
+    ctx.stroke();
+}
+</script>
+</body>
+</html>
+*/
 #endif /* ALGO_Kalman_ATY_Test_ATY */
 
 

+ 10 - 8
ALGO_Temperature_ATY.c

@@ -652,15 +652,17 @@ uint32_t ALGO_Temperature_ATY_Test(void){
 
 
 /************************************ etc *************************************/
+/*
 // T ---------------------------------------------------------------------------
-// #include "ALGO_Temperature_ATY.h"
-// void TempGet(void){
-//     float MCU_BASE_VOL_D = 1200;//VREFINT_MCU_ATY;
-//     float BOARD_TEMP = ALGO_VolToKelvinTemp((1000.0 *
-//         ADC_Get(&hadc1, ADC_CHANNEL_5) / MCU_BASE_VOL_D),
-//         3300.0, 10.0, 10.0, 3950, 1);
-//     printf_ATY_D("\r\nT: %f\r\n", BOARD_TEMP);
-// }
+#include "ALGO_Temperature_ATY.h"
+void TempGet(void){
+    float MCU_BASE_VOL_D = 1200; //VREFINT_MCU_ATY;
+    float BOARD_TEMP = ALGO_VolToKelvinTemp((1000.0 *
+        ADC_Get(&hadc1, ADC_CHANNEL_5) / MCU_BASE_VOL_D),
+        3300.0, 10.0, 10.0, 3950, 1);
+    printf_ATY_D("\r\nT: %f\r\n", BOARD_TEMP);
+}
+*/
 
 #endif /* __ALGO_Temperature_ATY_C */
 

+ 254 - 0
CAN_ATY.c

@@ -0,0 +1,254 @@
+/**
+* @file CAN_ATY.c
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of can process for C platform
+*
+* @version
+*       - 1_00_260116 > ATY
+*           -# Preliminary version
+********************************************************************************
+*/
+
+#ifndef __CAN_ATY_C
+#define __CAN_ATY_C
+
+#include "CAN_ATY.h"
+#include "string.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+void CAN_RegRW(struct CAN_ATY_Dev* dev,
+    uint32_t frameId, uint8_t cmd, uint8_t regAddr, float value){
+    uint8_t txData[8] = {0};
+
+    txData[0] = cmd;
+    txData[1] = regAddr;
+    memcpy(&txData[2], &value, 4);
+    txData[6] = 0;
+    txData[7] = 0;
+
+    dev->addTxMessage(frameId, txData, 8);
+}
+
+void CAN_Response(struct CAN_ATY_Dev* dev,
+    uint8_t cmd, uint8_t regAddr, float value, uint8_t error){
+    uint8_t txData[8] = {0};
+
+    txData[0] = cmd;
+    txData[1] = regAddr;
+    memcpy(&txData[2], &value, 4);
+    txData[6] = 0;
+    txData[7] = error;
+
+    dev->addTxMessage(CAN_STD_ID_RESPONSE + dev->addr, txData, 8);
+}
+
+
+void CAN_FaultReport(struct CAN_ATY_Dev* dev,
+    uint8_t faultCode, uint8_t severity, float faultValue){
+    uint8_t txData[8] = {0};
+
+    txData[0] = faultCode;
+    txData[1] = severity;
+    memcpy(&txData[2], &faultValue, 4);
+    txData[6] = 0;
+    txData[7] = 0;
+
+    dev->addTxMessage(CAN_STD_ID_FAULT + dev->addr, txData, 8);
+}
+
+
+void CAN_RX_Callback(struct CAN_ATY_Dev* dev, uint32_t stdId, float* data, uint8_t* rxData){
+    uint8_t cmd = rxData[0];
+    uint8_t regAddr = rxData[1];
+
+    if(stdId == CAN_STD_ID_BROADCAST
+        || stdId == (CAN_STD_ID_MULTICAST + dev->groupId)){
+        memcpy(&data[regAddr], &rxData[2], 4);
+    }
+    else if(stdId == (CAN_STD_ID_P2P + dev->addr)){
+        switch(cmd){
+            case CAN_CMD_READ:
+                CAN_Response(dev, cmd, regAddr, data[regAddr], CAN_ERR_NONE);
+                break;
+
+            case CAN_CMD_WRITE:
+                memcpy(&data[regAddr], &rxData[2], 4);
+                CAN_Response(dev, cmd, regAddr, data[regAddr], CAN_ERR_NONE);
+                break;
+            default:
+                CAN_Response(dev, cmd, regAddr, data[regAddr], CAN_ERR_CMD);
+                break;
+        }
+    }
+    else if(stdId == (CAN_STD_ID_RESPONSE + dev->addr)){
+
+    }
+    else if(stdId == CAN_STD_ID_FAULT + dev->addr){
+
+    }
+}
+
+
+#endif /* __CAN_ATY_C */
+
+/************************************ etc *************************************/
+/* init
+// CAN -------------------------------------------------------------------------
+#include "CAN_ATY.h"
+uint8_t CAN1_FilterConfig(uint8_t bankId){
+    CAN_FilterTypeDef sFilterConfig;
+
+    if(bankId > 14){
+        sFilterConfig.FilterBank = CAN_FILTER_BROADCAST;
+        sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
+        sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
+        sFilterConfig.FilterIdHigh = 0x0000;
+        sFilterConfig.FilterIdLow = 0x0000;
+        sFilterConfig.FilterMaskIdHigh = 0x0000;
+        sFilterConfig.FilterMaskIdLow = 0x0000;
+        sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
+        sFilterConfig.FilterActivation = ENABLE;
+        sFilterConfig.SlaveStartFilterBank = 0;
+        if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
+            return 9;
+    }
+    if(bankId == 0 || bankId == CAN_FILTER_BROADCAST){
+        sFilterConfig.FilterBank = CAN_FILTER_BROADCAST;
+        sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
+        sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
+        sFilterConfig.FilterIdHigh = ((CAN_STD_ID_BROADCAST << 21) >> 16);
+        sFilterConfig.FilterIdLow = (CAN_STD_ID_BROADCAST << 21) & 0xFFFF;
+        sFilterConfig.FilterMaskIdHigh = 0xFFFF;
+        sFilterConfig.FilterMaskIdLow = 0xFFFF;
+        sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO1;
+        sFilterConfig.FilterActivation = ENABLE;
+        sFilterConfig.SlaveStartFilterBank = 0;
+        if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
+            return 1;
+    }
+
+    if(bankId == 0 || bankId == CAN_FILTER_MULTICAST){
+        sFilterConfig.FilterBank = CAN_FILTER_MULTICAST;
+        sFilterConfig.FilterIdHigh = (((CAN_STD_ID_MULTICAST + (uint8_t)RGF_SYS_GROUP_ID) << 21) >> 16);
+        sFilterConfig.FilterIdLow = ((CAN_STD_ID_MULTICAST + (uint8_t)RGF_SYS_GROUP_ID) << 21) & 0xFFFF;
+        sFilterConfig.FilterMaskIdHigh = 0xFFFF;
+        sFilterConfig.FilterMaskIdLow = 0xFFFF;
+        sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO1;
+        sFilterConfig.FilterActivation = ENABLE;
+        if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
+            return 2;
+    }
+
+    if(bankId == 0 || bankId == CAN_FILTER_P2P){
+        sFilterConfig.FilterBank = CAN_FILTER_P2P;
+        sFilterConfig.FilterIdHigh = (((CAN_STD_ID_P2P + (uint8_t)RGF_SYS_ADDR) << 21) >> 16);
+        sFilterConfig.FilterIdLow = ((CAN_STD_ID_P2P + (uint8_t)RGF_SYS_ADDR) << 21) & 0xFFFF;
+        sFilterConfig.FilterMaskIdHigh = 0xFFFF;
+        sFilterConfig.FilterMaskIdLow = 0xFFFF;
+        sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO1;
+        sFilterConfig.FilterActivation = ENABLE;
+        if(HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK)
+            return 3;
+    }
+    return 0;
+}
+uint8_t CAN1_InitConfigStart(void){
+    uint8_t err = 0;
+
+    err = CAN1_FilterConfig(0);
+    if(err != 0) return err;
+
+    if(HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK)
+        err = 10;
+    if(HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO1_MSG_PENDING) != HAL_OK)
+        err = 11;
+
+    if(HAL_CAN_Start(&hcan) != HAL_OK)
+        err = 12;
+
+    return err;
+}
+uint8_t CAN1_AddTxMessage(uint32_t stdId, uint8_t* data, uint8_t len){
+    CAN_TxHeaderTypeDef txHeader;
+    uint32_t mailBox;
+
+    txHeader.StdId = stdId;
+    txHeader.IDE = CAN_ID_STD;
+    txHeader.RTR = CAN_RTR_DATA;
+    txHeader.DLC = len;
+    txHeader.TransmitGlobalTime = DISABLE;
+
+    HAL_CAN_AddTxMessage(&hcan, &txHeader, data, &mailBox);
+    return 0;
+}
+struct CAN_ATY_Dev CAN_ATY_Dev_1 = {
+    .addTxMessage = CAN1_AddTxMessage,
+
+    .addr = 0,
+    .groupId = 0,
+
+    .lock = __ATY_UNLOCKED
+};
+void CAN1_UpdateFilter(uint8_t addr, uint8_t groupId){
+    if(CAN_ATY_Dev_1.addr != addr){
+        CAN_ATY_Dev_1.addr = addr;
+        CAN1_FilterConfig(0);
+    }
+    if(CAN_ATY_Dev_1.groupId != groupId){
+        CAN_ATY_Dev_1.groupId = groupId;
+        CAN1_FilterConfig(CAN_FILTER_MULTICAST);
+    }
+}
+void CAN1_RxProcess(CAN_HandleTypeDef* hcan_t, uint32_t RxFifo){
+    CAN_RxHeaderTypeDef rxHeader;
+    uint8_t rxData[8] = {0};
+
+    if(HAL_CAN_GetRxMessage(hcan_t, RxFifo, &rxHeader, rxData) != HAL_OK){
+        return;
+    }
+    if(rxHeader.IDE != CAN_ID_STD || rxHeader.DLC < 2 || rxHeader.DLC < 6){
+        return;
+    }
+    CAN_RX_Callback(&CAN_ATY_Dev_1, rxHeader.StdId, rgf, rxData);
+}
+void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef* hcan_t){
+    if(hcan_t == &hcan){
+        CAN1_RxProcess(hcan_t, CAN_RX_FIFO0);
+    }
+}
+void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef* hcan_t){
+    if(hcan_t == &hcan){
+        CAN1_RxProcess(hcan_t, CAN_RX_FIFO1);
+    }
+}
+*/
+
+/* use
+// init
+CAN1_InitConfigStart();
+
+// cycles
+CAN1_UpdateFilter((uint8_t)RGF_SYS_ADDR, (uint8_t)RGF_SYS_GROUP_ID);
+*/
+
+/******************************************************************************/
+
+/******************************** End Of File *********************************/

+ 118 - 0
CAN_ATY.h

@@ -0,0 +1,118 @@
+/**
+* @file CAN_ATY.h
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of can process for C platform
+*
+* @version
+*       - 1_00_260116 > ATY
+*           -# Preliminary version
+********************************************************************************
+*/
+
+/**
+ * =============================================================================
+ * CAN Protocol Frame Definitions (Classic CAN, 11-bit Standard ID)
+ * =============================================================================
+ *
+ * -------------------
+ * │ Frame Type      │ CAN ID         │ Data Field Layout                      │
+ * -------------------
+ * │ Broadcast       │ 0x00FF         │ [0]: CMD                               │
+ * │ (Host -> Slave) │                │ [1]: REG_ADDR                          │
+ * │                 │                │ [2-5]: VALUE (float)                   │
+ * │                 │                │ [6-7]: -                               │
+ * -------------------
+ * │ Multicast       │ 0x100 + N      │ [0]: CMD                               │
+ * │ (Host -> Slave) │ (N = Group Id) │ [1]: REG_ADDR                          │
+ * │                 │                │ [2-5]: VALUE (float)                   │
+ * │                 │                │ [6-7]: -                               │
+ * -------------------
+ * │ P2P             │ 0x200 + N      │ [0]: CMD                               │
+ * │ (Host -> Slave) │ (N = ADDR)     │ [1]: REG_ADDR                          │
+ * │                 │                │ [2-5]: VALUE                           │
+ * │                 │                │ [6-7]: -                               │
+ * -------------------
+ * │ Slave Response  │ 0x300 + N      │ [0]: CMD_ECHO                          │
+ * │ (Slave -> Host) │ (N = ADDR)     │ [1]: REG_ADDR                          │
+ * │                 │                │ [2-5]: VALUE (float)                   │
+ * │                 │                │ [6]: ERR                               │
+ * │                 │                │ [7]: -                                 │
+ * -------------------
+ * │ Fault Report    │ 0x0010 + N     │ [0]: FAULT_CODE                        │
+ * │ (High Priority) │ (N = ADDR)     │ [1]: SEVERITY                          │
+ * │                 │                │ [2-5]: ERROR_VALUE (float)             │
+ * │                 │                │ [6-7]: -                               │
+ * -------------------
+ * =============================================================================
+ */
+
+#ifndef __CAN_ATY_H
+#define __CAN_ATY_H
+
+#include "INCLUDE_ATY.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+struct CAN_ATY_Dev{
+    uint8_t (*addTxMessage)(uint32_t addr, uint8_t* data, uint8_t len);
+
+    uint8_t addr;
+    uint8_t groupId;
+
+    uint8_t lock;
+};
+
+
+void CAN_RegRW(struct CAN_ATY_Dev* dev,
+    uint32_t frameId, uint8_t cmd, uint8_t regAddr, float value);
+void CAN_Response(struct CAN_ATY_Dev* dev,
+    uint8_t cmd, uint8_t regAddr, float value, uint8_t error);
+void CAN_FaultReport(struct CAN_ATY_Dev* dev,
+    uint8_t faultCode, uint8_t severity, float faultValue);
+void CAN_RX_Callback(struct CAN_ATY_Dev* dev, uint32_t stdId, float* data, uint8_t* rxData);
+
+#define CAN_FILTER_BROADCAST         1
+#define CAN_FILTER_MULTICAST         2
+#define CAN_FILTER_P2P               3
+#define CAN_FILTER_RESPONSE          4
+#define CAN_FILTER_FAULT             5
+
+#define CAN_STD_ID_BROADCAST         0x00FF
+#define CAN_STD_ID_MULTICAST         0x0100
+#define CAN_STD_ID_P2P               0x0200
+#define CAN_STD_ID_RESPONSE          0x0300
+#define CAN_STD_ID_FAULT             0x0010
+
+#define CAN_CMD_READ                 0x01
+#define CAN_CMD_WRITE                0x02
+
+#define CAN_ERR_NONE                 0x00
+#define CAN_ERR_CMD                  0x01
+#define CAN_ERR_PARAM                0x02
+
+#define CAN_FAULT_SEVERITY_WARN      0x00
+#define CAN_FAULT_SEVERITY_CRITICAL  0x01
+
+#define CAN_FAULT_CODE_NONE          0x00
+
+
+#endif /* __CAN_ATY_H */
+
+/******************************** End Of File *********************************/

+ 1 - 2
Doing/HW_SPI_ATY.c

@@ -26,8 +26,7 @@
 *           -# add lock
 *       - 1_03_251114 > ATY
 *           -# remove delay
-* @todo
-*       - all test
+* @todo all test
 ********************************************************************************
 */
 

+ 1 - 1
Doing/MOTOR_DC_ATY.c

@@ -126,7 +126,7 @@ void MOTOR_DC_StateMachine_PWM(struct MOTOR_DC_ATY_Dev* dev)
         //             - (dev->lineProParam * (float)((float)dev->motorSoftSteps / 2) * (float)((float)dev->motorSoftSteps / 2) / 2))
         //             / ((float)((float)dev->motorSoftSteps / 2) * (float)((float)dev->motorSoftSteps / 2)
         //                 * (float)((float)dev->motorSoftSteps / 2) * (float)((float)dev->motorSoftSteps / 2)) * 4;
-        //         // mbG[27] = S_param_A * 10000000;
+        //         // rgf[27] = S_param_A * 10000000;
         //         if(dev->motorStepCounter < (dev->motorSoftSteps / 2))
         //             dev->speedIncreaseStep =
         //             ((float)(S_param_A * dev->motorStepCounter * dev->motorStepCounter * dev->motorStepCounter * dev->motorStepCounter) / 4)

+ 2 - 2
Doing/MOTOR_STEP_ATY.c

@@ -280,7 +280,7 @@ void MotorStateMachine_Step_PWM(void)
                     - (motorStep_t_Group[i].S_paramC * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2) * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2) / 2))
                     / ((float)((float)motorStep_t_Group[i].motorSoftSteps / 2) * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2)
                         * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2) * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2)) * 4;
-                // mbG[27] = motorStep_t_Group[i].S_paramA * 10000000;
+                // rgf[27] = motorStep_t_Group[i].S_paramA * 10000000;
                 if(motorStep_t_Group[i].motorStepCounter < (motorStep_t_Group[i].motorSoftSteps / 2))
                     motorStep_t_Group[i].speedIncreaseStep =
                     ((float)(motorStep_t_Group[i].S_paramA * motorStep_t_Group[i].motorStepCounter * motorStep_t_Group[i].motorStepCounter * motorStep_t_Group[i].motorStepCounter * motorStep_t_Group[i].motorStepCounter) / 4)
@@ -410,7 +410,7 @@ void MotorStateMachine_Step(void)
 //                     - (motorStep_t_Group[i].S_paramC * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2) * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2) / 2))
 //                     / ((float)((float)motorStep_t_Group[i].motorSoftSteps / 2) * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2)
 //                         * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2) * (float)((float)motorStep_t_Group[i].motorSoftSteps / 2)) * 4;
-//                 // mbG[27] = motorStep_t_Group[i].S_paramA * 10000000;
+//                 // rgf[27] = motorStep_t_Group[i].S_paramA * 10000000;
 //                 if(motorStep_t_Group[i].motorSpeedCounter < (motorStep_t_Group[i].motorSoftSteps / 2))
 //                     motorStep_t_Group[i].speedIncreaseStep =
 //                     ((float)(motorStep_t_Group[i].S_paramA * motorStep_t_Group[i].motorSpeedCounter * motorStep_t_Group[i].motorSpeedCounter * motorStep_t_Group[i].motorSpeedCounter * motorStep_t_Group[i].motorSpeedCounter) / 4)

+ 1 - 1
Doing/TMC2209_ATY.c

@@ -189,7 +189,7 @@ void TMC2209_StateMachine_PWM(struct TMC2209_ATY_Dev* dev)
                     - (dev->lineProParam * (float)((float)dev->motorSoftSteps / 2) * (float)((float)dev->motorSoftSteps / 2) / 2))
                     / ((float)((float)dev->motorSoftSteps / 2) * (float)((float)dev->motorSoftSteps / 2)
                         * (float)((float)dev->motorSoftSteps / 2) * (float)((float)dev->motorSoftSteps / 2)) * 4;
-                // mbG[27] = S_param_A * 10000000;
+                // rgf[27] = S_param_A * 10000000;
                 if(dev->motorStepCounter < (dev->motorSoftSteps / 2))
                     dev->speedIncreaseStep =
                     ((float)(S_param_A * dev->motorStepCounter * dev->motorStepCounter * dev->motorStepCounter * dev->motorStepCounter) / 4)

+ 0 - 598
Doing/VL6180X_ATY.c

@@ -1,598 +0,0 @@
-/**
-* @file VL6180X_ATY.c
-*
-* @param Project DEVICE_GENERAL_ATY_LIB
-*
-* @author ATY
-*
-* @copyright
-*       - Copyright 2017 - 2026 MZ-ATY
-*       - This code follows:
-*           - MZ-ATY Various Contents Joint Statement -
-*               <a href="https://mengze.top/MZ-ATY_VCJS">
-*                        https://mengze.top/MZ-ATY_VCJS</a>
-*           - CC 4.0 BY-NC-SA -
-*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
-*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
-*       - Your use will be deemed to have accepted the terms of this statement.
-*
-* @brief functions of VL6180 for C platform
-*
-* @version
-*       - 1_01_231228 > ATY
-*           -# Preliminary version, first Release
-*       - 1_01_240104 > ATY
-*           -# base tested VL6180
-*       - 1_01_240111 > ATY
-*           -# add lock
-********************************************************************************
-*/
-
-#ifndef __VL6180X_ATY_C
-#define __VL6180X_ATY_C
-
-#include "VL6180X_ATY.h"
-
-/******************************* For user *************************************/
-
-/******************************************************************************/
-
-/**
- * @brief
- *
- * @param   reg
- * @param   data
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_WriteByte(uint16_t reg, uint8_t data, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t groupRegData[3], errCode = 0;
-    __ATY_LOCK(dev);
-    groupRegData[0] = (reg >> 8) & 0xFF;    // MSB of register address
-    groupRegData[1] = reg & 0xFF;           // LSB of register address
-    groupRegData[2] = data & 0xFF;
-    errCode = dev->i2cProcess(dev->addr, groupRegData, 3, __ATY_RW_W);
-    __ATY_UNLOCK(dev);
-    return errCode;
-}
-
-/**
- * @brief
- *
- * @param   reg
- * @param   data
- * @param   bytes num to write
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_WriteBytes(uint16_t reg, uint8_t* data, uint8_t bytes, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t groupRegData[3], i = 0, errCode = 0;
-    __ATY_LOCK(dev);
-    groupRegData[0] = (reg >> 8) & 0xFF;    // MSB of register address
-    groupRegData[1] = reg & 0xFF;           // LSB of register address
-    for(i = 0; i < bytes; i++)
-        groupRegData[2 + i] = data[i] & 0xFF;
-    errCode = dev->i2cProcess(dev->addr, groupRegData, 2 + bytes, __ATY_RW_W);
-    __ATY_UNLOCK(dev);
-    return errCode;
-}
-
-/**
- * @brief
- *
- * @param   reg
- * @param   data
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_ReadByte(uint16_t reg, uint8_t* data, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t groupReg[2], errCode = 0;
-    __ATY_LOCK(dev);
-    groupReg[0] = (reg >> 8) & 0xFF;            // MSB of register address
-    groupReg[1] = reg & 0xFF;                   // LSB of register address
-    errCode = dev->i2cProcess(dev->addr, groupReg, 2, __ATY_RW_W);
-    if(errCode){ __ATY_UNLOCK(dev); return errCode; }
-    errCode = dev->i2cProcess(dev->addr, data, 1, __ATY_RW_R);
-    __ATY_UNLOCK(dev);
-    return errCode;
-}
-
-/**
- * @brief
- *
- * @param   reg
- * @param   data
- * @param   bytes num to read
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_ReadBytes(uint16_t reg, uint8_t* data, uint8_t bytes, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t groupReg[2], errCode = 0;
-    __ATY_LOCK(dev);
-    groupReg[0] = (reg >> 8) & 0xFF;        // MSB of register address
-    groupReg[1] = reg & 0xFF;               // LSB of register address
-    errCode = dev->i2cProcess(dev->addr, groupReg, 2, __ATY_RW_W);
-    if(errCode){ __ATY_UNLOCK(dev); return errCode; }
-    errCode = dev->i2cProcess(dev->addr, data, bytes, __ATY_RW_R);
-    __ATY_UNLOCK(dev);
-    return errCode;
-}
-
-/**
- * @brief   get ids
- *
- * @param   id need 9 size array
- * @param   dev device
- * @return  uint8_t
- */
-uint8_t VL6180X_GetId(uint8_t* id, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t errCode = 0;
-    errCode = 0x00 & VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODEL_ID, &id[0], dev);
-    errCode = 0x10 & VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODEL_REV_MAJOR, &id[1], dev);
-    errCode = 0x20 & VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODEL_REV_MINOR, &id[2], dev);
-    errCode = 0x30 & VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODULE_REV_MAJOR, &id[3], dev);
-    errCode = 0x40 & VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_MODULE_REV_MINOR, &id[4], dev);
-    errCode = 0x50 & VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_DATE_HI, &id[5], dev);
-    errCode = 0x60 & VL6180X_ReadByte(VL6180X_REG_IDENTIFICATION_DATE_LO, &id[6], dev);
-    errCode = 0x70 & VL6180X_ReadBytes(VL6180X_REG_IDENTIFICATION_TIME, &id[7], 2, dev);
-
-    if(dev->debugEnable == 1){
-        uint8_t i = 0;
-        for(i = 0; i < 9; i++)
-            dev->LOG("%02X ", id[i]);
-        dev->LOG("\r\n");
-    }
-    if(id[0] != 0x84){ return 0x81; }
-    return errCode;
-}
-
-/**
- * @brief   set offset
- *
- * @param   offset
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_SetOffset(uint8_t offset, struct VL6180X_ATY_Dev* dev)
-{
-    return VL6180X_WriteByte(VL6180X_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET, offset, dev);
-}
-
-/**
- * @brief   write new addr
- *
- * @param   newAddr
- * @param   dev
- * @note    not real tested
- * @return  uint8_t
- */
-uint8_t VL6180X_SetAddress(uint8_t newAddr, struct VL6180X_ATY_Dev* dev)
-{
-    if(VL6180X_WriteByte(VL6180X_REG_SLAVE_DEVICE_ADDRESS, newAddr & 0x7F, dev) == 1)
-        return 1;
-    dev->addr = newAddr;
-    return 0;
-}
-
-/**
- * @brief
- *
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_ClearInterrupts(struct VL6180X_ATY_Dev* dev)
-{
-    if(VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR, 0x07, dev) == 1)
-        return 1;
-    return 0;
-}
-
-/**
- * @brief
- *
- * @return  uint8_t 1 for ready
- */
-uint8_t VL6180X_IsDeviceReady(struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t byte = 0;
-    if(VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO, &byte, dev) == 1)
-        return 2;
-    if((byte & 0x01))
-        return 1;
-    return 0;
-}
-
-/**
- * @brief
- *
- * @return  uint8_t 1 for ready
- */
-uint8_t VL6180X_WaitDeviceReady(struct VL6180X_ATY_Dev* dev)
-{
-    uint16_t errCount = 0;
-    while(VL6180X_IsDeviceReady(dev) != 1){
-        errCount++;
-        if(errCount > 100) return 2;
-    }
-    return 1;
-}
-
-/**
- * @brief
- *
- * @return  uint8_t 1 for complete
- */
-uint8_t VL6180X_IsRangeComplete(struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t status = 0;
-    if(VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO, &status, dev) == 1)
-        return 2;
-    status &= 0x07;
-    if((status & 0x04))
-        return 1;
-    return 0;
-}
-
-/**
- * @brief
- *
- * @return  uint8_t 1 for complete
- */
-uint8_t VL6180X_WaitRangeComplete(struct VL6180X_ATY_Dev* dev)
-{
-    uint16_t errCount = 0;
-    while(VL6180X_IsRangeComplete(dev) != 1){
-        errCount++;
-        if(errCount > 100) return 2;
-    }
-    return 1;
-}
-
-/**
- * @brief   request ranging success/error message (retreive after ranging)
- *
- * @param   value
- * @param   dev
- * @return  uint8_t one of possible VL6180X_ERROR_* values
- */
-uint8_t VL6180X_ReadRangeStatus(uint8_t* status, struct VL6180X_ATY_Dev* dev)
-{
-    if(VL6180X_ReadByte(VL6180X_REG_RESULT_RANGE_STATUS, status, dev) == 1)
-        return 1;
-    return 0;
-}
-
-/**
- * @brief
- *
- * @param   dev
- * @return  uint8_t
- * @note    Return results of read reqyest also clears out the interrupt
-            Be sure to check the return of {@link readRangeStatus} to before using
-            the return value!
- */
-uint8_t VL6180X_ReadRangeResult(uint8_t* range, struct VL6180X_ATY_Dev* dev)
-{
-    if(VL6180X_ReadByte(VL6180X_REG_RESULT_RANGE_VAL, range, dev) == 1)
-        return 1;
-    if(dev->debugEnable == 1)
-        dev->LOG("%d\r\n", *range);
-    return 0;
-}
-
-/**
- * @brief
- *
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_StartRange(struct VL6180X_ATY_Dev* dev)
-{
-    if(VL6180X_WriteByte(VL6180X_REG_SYSRANGE_START, 0x01, dev) == 1)
-        return 1;
-    return 0;
-}
-
-/**
- * @brief   start continuous ranging
- *
- * @param   period_msOptional Period between ranges in ms.
-            Values will be rounded down to 10ms units with minimum of 10ms.
-            Default is 50
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_StartRangeContinuous(uint16_t period_ms, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t period_reg = 0;
-    if(period_ms > 10) {
-        if(period_ms < 2550)
-            period_reg = (period_ms / 10) - 1;
-        else
-            period_reg = 254;
-    }
-    // Set ranging inter-measurement
-    if(VL6180X_WriteByte(SYSRANGE__INTERMEASUREMENT_PERIOD, period_reg, dev) == 1)
-        return 1;
-    // Start a continuous range measurement
-    if(VL6180X_WriteByte(VL6180X_REG_SYSRANGE_START, 0x03, dev) == 1)
-        return 1;
-    return 0;
-}
-
-/**
- * @brief   stop continuous range operation
- *
- * @param   dev
- * @return  uint8_t
- * @note    stop the continuous range operation, by setting the range register
-            back to 1, Page 7 of appication notes
- */
-uint8_t VL6180X_StopRangeContinuous(struct VL6180X_ATY_Dev* dev)
-{
-    if(VL6180X_WriteByte(VL6180X_REG_SYSRANGE_START, 0x01, dev) == 1)
-        return 1;
-    return 0;
-}
-
-
-/**
- * @brief   initializes I2C interface, checks that VL6180X is found and resets chip
- *
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_Init(struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t reset;
-    if(VL6180X_ReadByte(VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET, &reset, dev) == 1)
-        return 1;
-    // check to see has it be Initialised already
-    if(reset == 1){
-        if(VL6180X_Config(dev))
-            return 3;
-        //change fresh out of set status to 0
-        if(VL6180X_WriteByte(VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00, dev) == 1)
-            return 2;
-    }
-    return 0;
-}
-
-
-/**
- * @brief
- *
- * @param   range
- * @param   dev
- * @return  uint8_t distance in millimeters if valid
- */
-uint8_t VL6180X_MeasureRangeOnce(uint8_t* range, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t errCode = 0;
-    errCode = 0x00 & VL6180X_WaitDeviceReady(dev);  // slower
-    errCode = 0x10 & VL6180X_StartRange(dev);
-    errCode = 0x20 & VL6180X_WaitRangeComplete(dev);
-    errCode = 0x30 & VL6180X_ReadRangeResult(range, dev);
-    errCode = 0x40 & VL6180X_ClearInterrupts(dev);
-    return errCode;
-}
-
-/**
- * @brief
- *
- * @param   range
- * @param   dev
- * @return  uint8_t distance in millimeters if valid(100ms cycle tested)
- */
-uint8_t VL6180X_MeasureRangeOnceFast(uint8_t* range, struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t errCode = 0;
-    // errCode = 0x00 & VL6180X_WaitDeviceReady(dev);
-    errCode = 0x10 & VL6180X_StartRange(dev);
-    // errCode = 0x10 & VL6180X_StartRangeContinuous(10, dev);
-    errCode = 0x20 & VL6180X_WaitRangeComplete(dev);
-    errCode = 0x30 & VL6180X_ReadRangeResult(range, dev);
-    errCode = 0x40 & VL6180X_ClearInterrupts(dev);
-    return errCode;
-}
-
-
-/**
- * @brief   single shot lux measurement
- *
- * @param   gain gain setting, one of VL6180X_ALS_GAIN_*
- * @param   lux
- * @param   dev
- * @return  uint8_t
- * @note    only for VL6180X
- */
-uint8_t VL6180X_ReadLux(uint8_t gain, float* lux, struct VL6180X_ATY_Dev* dev)
-{
-    uint16_t errCount = 0;
-    uint8_t byte = 0;
-
-    if(VL6180X_ReadByte(VL6180X_REG_SYSTEM_INTERRUPT_CONFIG, &byte, dev) == 1)
-        return 1;
-    byte &= ~0x38;
-    byte |= (0x4 << 3); // IRQ on ALS ready
-    if(VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CONFIG, byte, dev) == 1)
-        return 2;
-
-    // 100 ms integration period
-    if(VL6180X_WriteByte(VL6180X_REG_SYSALS_INTEGRATION_PERIOD_HI, 0, dev) == 1)
-        return 3;
-    if(VL6180X_WriteByte(VL6180X_REG_SYSALS_INTEGRATION_PERIOD_LO, 100, dev) == 1)
-        return 4;
-
-    // analog gain
-    if(gain > VL6180X_ALS_GAIN_40) {
-        gain = VL6180X_ALS_GAIN_40;
-    }
-    if(VL6180X_WriteByte(VL6180X_REG_SYSALS_ANALOGUE_GAIN, 0x40 | gain, dev) == 1)
-        return 5;
-
-    // start ALS
-    if(VL6180X_WriteByte(VL6180X_REG_SYSALS_START, 0x01, dev) == 1)
-        return 6;
-    if(VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO, &byte, dev) == 1)
-        return 7;
-    // Poll until "New Sample Ready threshold event" is set
-    while(4 != ((byte >> 3) & 0x7)){
-        if(VL6180X_ReadByte(VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO, &byte, dev) == 1)
-            return 8;
-        errCount++;
-        if(errCount > 1000) return 9;
-    }
-
-    // read lux!
-    uint8_t luxBytes[2] = {0};
-    if(VL6180X_ReadBytes(VL6180X_REG_RESULT_ALS_VAL, luxBytes, 2, dev) == 1)
-        return 10;
-    *lux = ((luxBytes[0] << 8) | luxBytes[1]);
-
-    // clear interrupt
-    if(VL6180X_WriteByte(VL6180X_REG_SYSTEM_INTERRUPT_CLEAR, 0x07, dev) == 1)
-        return 11;
-
-    *lux *= 0.32; // calibrated count/lux
-    switch(gain) {
-        case VL6180X_ALS_GAIN_1:
-            break;
-        case VL6180X_ALS_GAIN_1_25:
-            *lux /= 1.25;
-            break;
-        case VL6180X_ALS_GAIN_1_67:
-            *lux /= 1.67;
-            break;
-        case VL6180X_ALS_GAIN_2_5:
-            *lux /= 2.5;
-            break;
-        case VL6180X_ALS_GAIN_5:
-            *lux /= 5;
-            break;
-        case VL6180X_ALS_GAIN_10:
-            *lux /= 10;
-            break;
-        case VL6180X_ALS_GAIN_20:
-            *lux /= 20;
-            break;
-        case VL6180X_ALS_GAIN_40:
-            *lux /= 40;
-            break;
-    }
-    *lux *= 100;
-    *lux /= 100; // integration time in ms
-
-    return 0;
-}
-
-
-/**
- * @brief
- *
- * @param   dev
- * @return  uint8_t
- */
-uint8_t VL6180X_Config(struct VL6180X_ATY_Dev* dev)
-{
-    uint8_t errCode = 0;
-    // Mandatory : private registers
-    errCode = 0x10 & VL6180X_WriteByte(0x0207, 0x01, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x0208, 0x01, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x0096, 0x00, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x0097, 0xfd, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00e3, 0x01, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00e4, 0x03, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00e5, 0x02, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00e6, 0x01, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00e7, 0x03, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00f5, 0x02, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00d9, 0x05, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00db, 0xce, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00dc, 0x03, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00dd, 0xf8, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x009f, 0x00, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00a3, 0x3c, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00b7, 0x00, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00bb, 0x3c, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00b2, 0x09, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00ca, 0x09, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x0198, 0x01, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x01b0, 0x17, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x01ad, 0x00, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x00ff, 0x05, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x0100, 0x05, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x0199, 0x05, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x01a6, 0x1b, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x01ac, 0x3e, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x01a7, 0x1f, dev);
-    errCode = 0x10 & VL6180X_WriteByte(0x0030, 0x00, dev);
-
-    // Recommended : Public registers - See data sheet for more detail
-    errCode = 0x20 & VL6180X_WriteByte(0x0011, 0x10, dev); // Enables polling for "New Sample ready" when measurement completes
-    errCode = 0x20 & VL6180X_WriteByte(0x010a, 0x30, dev); // Set the averaging sample period (compromise between lower noise and increased execution time)
-    errCode = 0x20 & VL6180X_WriteByte(0x003f, 0x46, dev); // Sets the light and dark gain (upper nibble). Dark gain should not be changed.
-    errCode = 0x20 & VL6180X_WriteByte(0x0031, 0xFF, dev); // sets the # of range measurements after which auto calibration of system is performed
-    errCode = 0x20 & VL6180X_WriteByte(0x0041, 0x63, dev); // Set ALS integration time to 100ms
-    errCode = 0x20 & VL6180X_WriteByte(0x002e, 0x01, dev); // perform a single temperature calibration of the ranging sensor
-
-    // Optional: Public registers - See data sheet for more detail
-    errCode = 0x30 & VL6180X_WriteByte(0x001b, 0x09, dev); // Set default ranging inter-measurement period to 100ms
-    errCode = 0x30 & VL6180X_WriteByte(0x003e, 0x31, dev); // Set default ALS inter-measurement period to 500ms
-    errCode = 0x30 & VL6180X_WriteByte(0x0014, 0x24, dev); // Configures interrupt on "New Sample Ready threshold event"
-    return errCode;
-}
-
-#endif /* __VL6180X_ATY_C */
-
-/************************************ etc *************************************/
-/* init */
-// uint8_t VL6180X_1_I2C(uint8_t addr, uint8_t* data_t, uint8_t len, uint8_t rw){
-//     if(rw == __ATY_RW_W)
-//         return I2C_Write(addr, data_t, len, &HW_I2C_ATY_Dev_1);
-//     else if(rw == __ATY_RW_R)
-//         return I2C_Read(addr, data_t, len, &HW_I2C_ATY_Dev_1);
-// }
-
-// uint8_t VL6180X_1_I2C(uint8_t addr, uint8_t* data_t, uint8_t len, uint8_t rw){
-//     if(rw == __ATY_RW_W)
-//         return (uint8_t)HAL_I2C_Master_Transmit(&hi2c1, (addr << 1 | 0), data_t, len, 1000);
-//     else if(rw == __ATY_RW_R)
-//         return (uint8_t)HAL_I2C_Master_Receive(&hi2c1, (addr << 1 | 1), data_t, len, 1000);
-// }
-
-// struct VL6180X_ATY_Dev VL6180X_ATY_t_1 = {
-//     .addr = VL6180X_ADDRESS,
-//     .i2cProcess = VL6180X_1_I2C,
-//     .lock = __ATY_UNLOCKED,
-//     .debugEnable = 0,
-// };
-
-// VL6180X_Init(&VL6180X_ATY_t_1);
-
-/* use */
-// VL6180X_ATY_t_1.debugEnable = 1;
-
-// uint8_t idGroup[9] = {0};
-// VL6180X_GetId(idGroup, &VL6180X_ATY_t_1);
-
-// VL6180X_SetOffset(10, &VL6180X_ATY_t_1);
-
-// VL6180X_SetAddress(0x10, &VL6180X_ATY_t_1);
-
-// VL6180X_MeasureRangeOnce(&range, &VL6180X_ATY_t_1);
-// VL6180X_MeasureRangeOnceFast(&range, &VL6180X_ATY_t_1);
-// only for VL6180X
-// VL6180X_ReadLux(VL6180X_ALS_GAIN_40, &lux, &VL6180X_ATY_t_1);
-
-// rcPara_t rcParam_VL6180 = {0.028, 0};
-// rcLpFilter(&rcParam_VL6180, value);
-
-/******************************************************************************/
-
-/******************************** End Of File *********************************/

+ 0 - 170
Doing/VL6180X_ATY.h

@@ -1,170 +0,0 @@
-/**
-* @file VL6180X_ATY.h
-*
-* @param Project DEVICE_GENERAL_ATY_LIB
-*
-* @author ATY
-*
-* @copyright
-*       - Copyright 2017 - 2026 MZ-ATY
-*       - This code follows:
-*           - MZ-ATY Various Contents Joint Statement -
-*               <a href="https://mengze.top/MZ-ATY_VCJS">
-*                        https://mengze.top/MZ-ATY_VCJS</a>
-*           - CC 4.0 BY-NC-SA -
-*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
-*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
-*       - Your use will be deemed to have accepted the terms of this statement.
-*
-* @brief functions of VL6180 for C platform
-*
-* @version
-*       - 1_01_230828 > ATY
-*           -# Preliminary version, first Release
-*       - 1_01_240104 > ATY
-*           -# base tested VL6180
-*       - 1_01_240111 > ATY
-*           -# add lock
-********************************************************************************
-*/
-
-#ifndef __VL6180X_ATY_H
-#define __VL6180X_ATY_H
-
-#include "INCLUDE_ATY.h"
-
-/******************************* For user *************************************/
-// 0 1 0 1 0 0 1 R/W    // can edit by program
-#define VL6180X_ADDRESS (0x29)
-
-/******************************************************************************/
-
-struct VL6180X_ATY_Dev
-{
-    uint8_t addr;
-
-    uint8_t(*i2cProcess)(uint8_t addr, uint8_t* data_t, uint8_t len, uint8_t rw);
-
-    uint8_t lock;
-    uint8_t debugEnable;
-    int (*LOG)();
-};
-
-
-uint8_t VL6180X_WriteByte(uint16_t reg, uint8_t data, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_WriteBytes(uint16_t reg, uint8_t* data, uint8_t bytes, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_ReadByte(uint16_t reg, uint8_t* data, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_ReadBytes(uint16_t reg, uint8_t* data, uint8_t bytes, struct VL6180X_ATY_Dev* dev);
-
-uint8_t VL6180X_GetId(uint8_t* id, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_SetOffset(uint8_t offset, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_SetAddress(uint8_t newAddr, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_Clear_Interrupts(struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_IsDeviceReady(struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_WaitDeviceReady(struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_IsRangeComplete(struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_WaitRangeComplete(struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_ReadRangeStatus(uint8_t* status, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_ReadRangeResult(uint8_t* range, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_StartRange(struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_StartRangeContinuous(uint16_t period_ms, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_StopRangeContinuous(struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_Init(struct VL6180X_ATY_Dev* dev);
-
-uint8_t VL6180X_MeasureRangeOnce(uint8_t* range, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_MeasureRangeOnceFast(uint8_t* range, struct VL6180X_ATY_Dev* dev);
-uint8_t VL6180X_ReadLux(uint8_t gain, float* lux, struct VL6180X_ATY_Dev* dev);
-
-uint8_t VL6180X_Config(struct VL6180X_ATY_Dev* dev);
-
-// device model identification number
-#define VL6180X_REG_IDENTIFICATION_MODEL_ID                 0x000
-#define VL6180X_REG_IDENTIFICATION_MODEL_REV_MAJOR          0x001
-#define VL6180X_REG_IDENTIFICATION_MODEL_REV_MINOR          0x002
-#define VL6180X_REG_IDENTIFICATION_MODULE_REV_MAJOR         0x003
-#define VL6180X_REG_IDENTIFICATION_MODULE_REV_MINOR         0x004
-#define VL6180X_REG_IDENTIFICATION_DATE_HI                  0x006
-#define VL6180X_REG_IDENTIFICATION_DATE_LO                  0x007
-#define VL6180X_REG_IDENTIFICATION_TIME                     0x008 // 8~9
-#define VL6180X_REG_SYSTEM_MODE_GPIO0                       0x010
-#define VL6180X_REG_SYSTEM_MODE_GPIO1                       0x011
-#define VL6180X_REG_SYSTEM_HISTORY_CTRL                     0x012
-#define VL6180X_REG_SYSTEM_INTERRUPT_CONFIG                 0x014
-#define VL6180X_REG_SYSTEM_INTERRUPT_CLEAR                  0x015
-#define VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET               0x016
-#define VL6180X_REG_SYSTEM_GROUPED_PARAMETER_HOLD           0x017
-#define VL6180X_REG_SYSRANGE_START                          0x018
-#define VL6180X_REG_SYSRANGE_THRESH_HIGH                    0x019
-#define VL6180X_REG_SYSRANGE_THRESH_LOW                     0x01A
-#define VL6180X_REG_SYSRANGE_INTERMEASUREMENT_PERIOD        0x01B
-#define VL6180X_REG_SYSRANGE_MAX_CONVERGENCE_TIME           0x01C
-#define VL6180X_REG_SYSRANGE_CROSSTALK_COMPENSATION_RATE    0x01E
-#define VL6180X_REG_SYSRANGE_CROSSTALK_VALID_HEIGHT         0x021
-#define VL6180X_REG_SYSRANGE_EARLY_CONVERGENCE_ESTIMATE     0x022
-#define VL6180X_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET      0x024
-#define VL6180X_REG_SYSRANGE_RANGE_IGNORE_VALID_HEIGHT      0x025
-#define VL6180X_REG_SYSRANGE_RANGE_IGNORE_THRESHOLD         0x026
-#define VL6180X_REG_SYSRANGE_MAX_AMBIENT_LEVEL_MULT         0x02C
-#define VL6180X_REG_SYSRANGE_RANGE_CHECK_ENABLES            0x02D
-#define VL6180X_REG_SYSRANGE_VHV_RECALIBRATE                0x02E
-#define VL6180X_REG_SYSRANGE_VHV_REPEAT_RATE                0x031
-#define VL6180X_REG_RESULT_RANGE_STATUS                     0x04D
-#define VL6180X_REG_RESULT_ALS_STATUS                       0x04E
-#define VL6180X_REG_RESULT_INTERRUPT_STATUS_GPIO            0x04F
-#define VL6180X_REG_RESULT_HISTORY_BUFFER_x                 0x052 // 52~60
-#define VL6180X_REG_RESULT_RANGE_VAL                        0x062
-#define VL6180X_REG_RESULT_RANGE_RAW                        0x064
-#define VL6180X_REG_RESULT_RANGE_RETURN_RATE                0x066
-#define VL6180X_REG_RESULT_RANGE_REFERENCE_RATE             0x068
-#define VL6180X_REG_RESULT_RANGE_RETURN_SIGNAL_COUNT        0x06C
-#define VL6180X_REG_RESULT_RANGE_REFERENCE_SIGNAL_COUNT     0x070
-#define VL6180X_REG_RESULT_RANGE_RETURN_AMB_COUNT           0x074
-#define VL6180X_REG_RESULT_RANGE_REFERENCE_AMB_COUNT        0x078
-#define VL6180X_REG_RESULT_RANGE_RETURN_CONV_TIME           0x07C
-#define VL6180X_REG_RESULT_RANGE_REFERENCE_CONV_TIME        0x080
-#define VL6180X_REG_READOUT_AVERAGING_SAMPLE_PERIOD         0x10A
-#define VL6180X_REG_FIRMWARE_BOOTUP                         0x119
-#define VL6180X_REG_SLAVE_DEVICE_ADDRESS                    0x212
-
-// only for VL6180X below reg
-#define VL6180X_REG_SYSALS_START                            0x038
-#define VL6180X_REG_SYSALS_THRESH_HIGH                      0x03A
-#define VL6180X_REG_SYSALS_THRESH_LOW                       0x03C
-#define VL6180X_REG_SYSALS_INTERMEASUREMENT_PERIOD          0x03E
-#define VL6180X_REG_SYSALS_ANALOGUE_GAIN                    0x03F
-#define VL6180X_REG_SYSALS_INTEGRATION_PERIOD_HI            0x040
-#define VL6180X_REG_SYSALS_INTEGRATION_PERIOD_LO            0x041
-#define VL6180X_REG_RESULT_ALS_VAL                          0x050
-#define VL6180X_REG_FIRMWARE_RESULT_SCALER                  0x120
-#define VL6180X_REG_INTERLEAVED_MODE_ENABLE                 0x2A3
-
-
-
-#define VL6180X_ALS_GAIN_1          0x06
-#define VL6180X_ALS_GAIN_1_25       0x05
-#define VL6180X_ALS_GAIN_1_67       0x04
-#define VL6180X_ALS_GAIN_2_5        0x03
-#define VL6180X_ALS_GAIN_5          0x02
-#define VL6180X_ALS_GAIN_10         0x01
-#define VL6180X_ALS_GAIN_20         0x00
-#define VL6180X_ALS_GAIN_40         0x07
-
-#define VL6180X_ERROR_NONE          0   // Success!
-#define VL6180X_ERROR_SYSERR_1      1   // System error
-#define VL6180X_ERROR_SYSERR_5      5   // Sysem error
-#define VL6180X_ERROR_ECEFAIL       6   // Early convergence estimate fail
-#define VL6180X_ERROR_NOCONVERGE    7   // No target detected
-#define VL6180X_ERROR_RANGEIGNORE   8   // Ignore threshold check failed
-#define VL6180X_ERROR_SNR           11  // Ambient conditions too high
-#define VL6180X_ERROR_RAWUFLOW      12  // Raw range algo underflow
-#define VL6180X_ERROR_RAWOFLOW      13  // Raw range algo overflow
-#define VL6180X_ERROR_RANGEUFLOW    14  // Raw range algo underflow
-#define VL6180X_ERROR_RANGEOFLOW    15  // Raw range algo overflow
-
-// Define some additional registers mentioned in application notes and we use
-// period between each measurement when in continuous mode
-#define SYSRANGE__INTERMEASUREMENT_PERIOD 0x001b // P19 application notes
-
-#endif /* __VL6180X_ATY_H */
-
-/******************************** End Of File *********************************/

+ 0 - 77
Doing/WS2812_ATY.c

@@ -1,77 +0,0 @@
-/**
-* @file WS2812_ATY.c
-*
-* @param Project DEVICE_GENERAL_ATY_LIB
-*
-* @author ATY
-*
-* @copyright
-*       - Copyright 2017 - 2026 MZ-ATY
-*       - This code follows:
-*           - MZ-ATY Various Contents Joint Statement -
-*               <a href="https://mengze.top/MZ-ATY_VCJS">
-*                        https://mengze.top/MZ-ATY_VCJS</a>
-*           - CC 4.0 BY-NC-SA -
-*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
-*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
-*       - Your use will be deemed to have accepted the terms of this statement.
-*
-* @brief functions of WS2812 for C platform (Dev-style)
-*
-* @version
-*       - 1_01_251112 > ATY
-*           -# Refactor to Dev-style; remove legacy global interfaces
-********************************************************************************
-*/
-
- #ifndef __WS2812_ATY_C
- #define __WS2812_ATY_C
-
- #include "WS2812_ATY.h"
-
- static void _ws2812_send_byte(struct WS2812_ATY_Dev* dev, uint8_t byte)
- {
-     for (int i = 7; i >= 0; --i) {
-         uint8_t bit = (byte >> i) & 0x01;
-         dev->sendBit(bit);
-     }
- }
-
- uint8_t WS2812_InitDev(struct WS2812_ATY_Dev* dev)
- {
-     if (!dev || !dev->sendBit) return 1;
-     if (dev->debugEnable == 1 && dev->LOG) dev->LOG("\r\nWS2812 init done.");
-     return 0;
- }
-
- void WS2812_SendColorDev(struct WS2812_ATY_Dev* dev, uint8_t R, uint8_t G, uint8_t B)
- {
-     __ATY_LOCK(dev);
-     _ws2812_send_byte(dev, G);
-     _ws2812_send_byte(dev, R);
-     _ws2812_send_byte(dev, B);
-     if (dev->reset_us) dev->reset_us(60);
-     if (dev->debugEnable == 1 && dev->LOG) dev->LOG("\r\nWS2812 send color.");
-     __ATY_UNLOCK(dev);
- }
-
- void WS2812_SendBufferDev(struct WS2812_ATY_Dev* dev, const uint8_t* rgb, uint16_t count)
- {
-     __ATY_LOCK(dev);
-     if (!dev || !dev->sendBit || !rgb) { __ATY_UNLOCK(dev); return; }
-     for (uint16_t i = 0; i < count; ++i) {
-         uint8_t R = rgb[i*3 + 0];
-         uint8_t G = rgb[i*3 + 1];
-         uint8_t B = rgb[i*3 + 2];
-         _ws2812_send_byte(dev, G);
-         _ws2812_send_byte(dev, R);
-         _ws2812_send_byte(dev, B);
-     }
-     if (dev->reset_us) dev->reset_us(60);
-     if (dev->debugEnable == 1 && dev->LOG) dev->LOG("\r\nWS2812 send buffer.");
-     __ATY_UNLOCK(dev);
- }
-
- #endif /* __WS2812_ATY_C */
-
-/******************************** End Of File *********************************/

+ 0 - 45
Doing/WS2812_ATY.h

@@ -1,45 +0,0 @@
-/**
-* @file WS2812_ATY.h
-*
-* @param Project DEVICE_GENERAL_ATY_LIB
-*
-* @author ATY
-*
-* @copyright
-*       - Copyright 2017 - 2026 MZ-ATY
-*       - This code follows:
-*           - MZ-ATY Various Contents Joint Statement -
-*               <a href="https://mengze.top/MZ-ATY_VCJS">
-*                        https://mengze.top/MZ-ATY_VCJS</a>
-*           - CC 4.0 BY-NC-SA -
-*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
-*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
-*       - Your use will be deemed to have accepted the terms of this statement.
-*
-* @brief functions of WS2812 for C platform (Dev-style)
-*
-* @version
-*       - 1_01_251112 > ATY
-*           -# Refactor to Dev-style; remove legacy global interfaces
-********************************************************************************
-*/
-
-#ifndef __WS2812_ATY_H
-#define __WS2812_ATY_H
-
-#include "INCLUDE_ATY.h"
-
-struct WS2812_ATY_Dev
-{
-    void (*sendBit)(uint8_t bit);
-    void (*reset_us)(uint16_t us);
-    uint8_t lock;
-};
-
-uint8_t WS2812_InitDev(struct WS2812_ATY_Dev* dev);
-void WS2812_SendColorDev(struct WS2812_ATY_Dev* dev, uint8_t R, uint8_t G, uint8_t B);
-void WS2812_SendBufferDev(struct WS2812_ATY_Dev* dev, const uint8_t* rgb, uint16_t count);
-
-#endif /* __WS2812_ATY_H */
-
-/******************************** End Of File *********************************/

+ 22 - 18
HW_ADC_ATY.c

@@ -110,26 +110,30 @@ uint16_t ADC_Get(ADC_HandleTypeDef* adc, uint32_t channel){
 
 #endif /* PLATFORM */
 
+#endif /* __HW_ADC_ATY_C */
+
+/************************************ etc *************************************/
+/*
 // ADC -------------------------------------------------------------------------
-// #include "HW_ADC_ATY.h"
-// void MCU_CoreAdcGet(void){
-//     // F405/F407(mV)
-//     // float VOL_PER_AD_ATY = 1210.0 / ((float)(*(__IO uint16_t*)(0x1FFF7A2A)));
-//     // float VREFINT_MCU_ATY = ADC_Get(&hadc1, ADC_CHANNEL_VREFINT) * VOL_PER_AD_ATY;
-//     // float TEMPERATURE_MCU_ATY =
-//     //     (((ADC_Get(&hadc1, ADC_CHANNEL_TEMPSENSOR) * VOL_PER_AD_ATY) - 760.0) / 2.5) + 25.0;
-//     // F103(mV)
-//     float VOL_PER_AD_ATY = 1200.0 / ADC_Get(&hadc1, ADC_CHANNEL_VREFINT);
-//     float VREFINT_MCU_ATY = ADC_Get(&hadc1, ADC_CHANNEL_VREFINT) * VOL_PER_AD_ATY;
-//     float TEMPERATURE_MCU_ATY = ((1430.0 -
-//         (ADC_Get(&hadc1, ADC_CHANNEL_TEMPSENSOR) * VOL_PER_AD_ATY)) / 4.3) + 25.0;
+#include "HW_ADC_ATY.h"
+void MCU_CoreAdcGet(void){
+    // F405/F407(mV)
+    // float VOL_PER_AD_ATY = 1210.0 / ((float)(*(__IO uint16_t*)(0x1FFF7A2A)));
+    // float VREFINT_MCU_ATY = ADC_Get(&hadc1, ADC_CHANNEL_VREFINT) * VOL_PER_AD_ATY;
+    // float TEMPERATURE_MCU_ATY =
+    //     (((ADC_Get(&hadc1, ADC_CHANNEL_TEMPSENSOR) * VOL_PER_AD_ATY) - 760.0) / 2.5) + 25.0;
+    // F103(mV)
+    float VOL_PER_AD_ATY = 1200.0 / ADC_Get(&hadc1, ADC_CHANNEL_VREFINT);
+    float VREFINT_MCU_ATY = ADC_Get(&hadc1, ADC_CHANNEL_VREFINT) * VOL_PER_AD_ATY;
+    float TEMPERATURE_MCU_ATY = ((1430.0 -
+        (ADC_Get(&hadc1, ADC_CHANNEL_TEMPSENSOR) * VOL_PER_AD_ATY)) / 4.3) + 25.0;
 
-//     float MCU_BASE_VOL_D = 1200;//VREFINT_MCU_ATY;
-//     float MCU_BASE_VOL = VREFINT_MCU_ATY;
-//     float MCU_TEMP = TEMPERATURE_MCU_ATY;
-//     printf_ATY_D("\r\nCAD: %f, CV: %f, CT: %f\r\n", VOL_PER_AD_ATY, MCU_BASE_VOL, MCU_TEMP);
-// }
+    float MCU_BASE_VOL_D = 1200;//VREFINT_MCU_ATY;
+    float MCU_BASE_VOL = VREFINT_MCU_ATY;
+    float MCU_TEMP = TEMPERATURE_MCU_ATY;
+    printf_ATY_D("\r\nCAD: %f, CV: %f, CT: %f\r\n", VOL_PER_AD_ATY, MCU_BASE_VOL, MCU_TEMP);
+}
+*/
 
-#endif /* __HW_ADC_ATY_C */
 
 /******************************** End Of File *********************************/

+ 49 - 48
HW_TIMER_ATY.c

@@ -101,55 +101,56 @@ void UserTimerLoop_Cycle1ms(struct HW_TIMER_ATY_Dev* dev){
 #endif /* __HW_TIMER_ATY_C */
 
 /************************************ etc *************************************/
-/* init */
+/* init
 // Timer loop ------------------------------------------------------------------
-// #include "HW_TIMER_ATY.h"
-// void TimerLoopProcess_User_4(void);
-// void TimerInit_4(){
-//     HAL_TIM_Base_Start_IT(&htim4);
-// }
-// struct HW_TIMER_ATY_Dev HW_TIMER_ATY_Dev_4 = {
-//     .msN = 0,
-//     .ms10 = 0,
-//     .ms100 = 0,
-//     .s1 = 0,
-//
-//     .ms1_f = 0,
-//     .ms10_f = 0,
-//     .ms100_f = 0,
-//     .s1_f = 0,
-//
-//     .timerInitFlag = 0,
-//     .timerInit = TimerInit_4,
-//
-//     .timerLoopProcess_User = TimerLoopProcess_User_4,
-//
-//     .lock = __ATY_UNLOCKED
-// };
-// void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){
-//     if(htim == &htim4){
-//         UserTimerLoop_Cycle1ms(&HW_TIMER_ATY_Dev_4);
-//     }
-// }
-
-/* use */
-/* ATY Machine ****************************************************************/
-// void TimerLoopProcess_User_4(void){
-//     if(HW_TIMER_ATY_Dev_4.ms1_f == 1){
-//         HW_TIMER_ATY_Dev_4.ms1_f = 0;
-//     }
-//     if(HW_TIMER_ATY_Dev_4.ms100_f == 1){
-//         HW_TIMER_ATY_Dev_4.ms100_f = 0;
-//         SysLedBlink(&LED_ATY_t_1);
-//         PWR_BTN_Status_withIT(&PWR_BTN_ATY_t_1);
-//
-//         UpdateMbRegsFromFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1);
-//     }
-//     if(HW_TIMER_ATY_Dev_4.s1_f == 1){
-//         HW_TIMER_ATY_Dev_4.s1_f = 0;
-//
-//     }
-// }
+#include "HW_TIMER_ATY.h"
+void TimerLoopProcess_User_4(void);
+void TimerInit_4(){
+    HAL_TIM_Base_Start_IT(&htim4);
+}
+struct HW_TIMER_ATY_Dev HW_TIMER_ATY_Dev_4 = {
+    .msN = 0,
+    .ms10 = 0,
+    .ms100 = 0,
+    .s1 = 0,
+
+    .ms1_f = 0,
+    .ms10_f = 0,
+    .ms100_f = 0,
+    .s1_f = 0,
+
+    .timerInitFlag = 0,
+    .timerInit = TimerInit_4,
+
+    .timerLoopProcess_User = TimerLoopProcess_User_4,
+
+    .lock = __ATY_UNLOCKED
+};
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){
+    if(htim == &htim4){
+        UserTimerLoop_Cycle1ms(&HW_TIMER_ATY_Dev_4);
+    }
+}
+*/
+
+/* use
+void TimerLoopProcess_User_4(void){
+    if(HW_TIMER_ATY_Dev_4.ms1_f == 1){
+        HW_TIMER_ATY_Dev_4.ms1_f = 0;
+    }
+    if(HW_TIMER_ATY_Dev_4.ms100_f == 1){
+        HW_TIMER_ATY_Dev_4.ms100_f = 0;
+        SysLedBlink(&LED_ATY_t_1);
+        PWR_BTN_Status_withIT(&PWR_BTN_ATY_t_1);
+
+        UpdateMbRegsFromFloat(rgf, &MODBUS_S_LOW_ATY_Dev_1);
+    }
+    if(HW_TIMER_ATY_Dev_4.s1_f == 1){
+        HW_TIMER_ATY_Dev_4.s1_f = 0;
+
+    }
+}
+*/
 
 /******************************************************************************/
 

+ 99 - 91
HW_UART_ATY.c

@@ -453,99 +453,107 @@ void UartPrintf_Test_Quick(struct HW_UART_ATY_Dev* dev){
 #endif /* __HW_UART_ATY_C */
 
 /************************************ etc *************************************/
-/* init */
-/* STM32 (Open uart global IT, open rx DMA(Mode Normal, Width Byte) and default DMA IT) */
+/* init
+// STM32 (Open uart global IT, open rx DMA(Mode Normal, Width Byte) and default DMA IT)
 // Uart ------------------------------------------------------------------------
-// #include "HW_UART_ATY.h"
-// extern DMA_HandleTypeDef hdma_usart1_rx;
-// void UartReceiveProcess_User_1(void);
-// void UartInit_1(uint8_t* rx){
-//     HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx, UART_RX_MAX_LEN);
-//     __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
-// }
-// void UartSendByte_1(uint8_t byte){
-//     HAL_UART_Transmit(&huart1, (uint8_t*)&byte, 1, 0xFFFF);
-// }
-// struct HW_UART_ATY_Dev HW_UART_ATY_Dev_1 = {
-//     // .rx = uartRx1,
-//     .rx = {0},
-//     .rxCount = 0,
-//     .txCount = 0,
-//     .rcvOverTimeOutCountNum = 1,
-//     .rcvOverTimeOutCount = 0,
-//     .rcvOverFlag = 0,
-
-//     .uartInitFlag = 0,
-//     .uartInit = UartInit_1,
-//     .uartSendByte = UartSendByte_1,
-
-//     .uartReceiveProcess_User = UartReceiveProcess_User_1,
-
-//     .lock = __ATY_UNLOCKED
-// };
-// void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size){
-//     if(huart == &huart1){
-//         HAL_UART_DMAStop(&huart1);
-//         HW_UART_ATY_Dev_1.rcvOverTimeOutCount = 0;
-//         HW_UART_ATY_Dev_1.rxCount = UART_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
-//         HW_UART_ATY_Dev_1.rcvOverFlag = 0;
-
-//         HAL_UARTEx_ReceiveToIdle_DMA(&huart1, HW_UART_ATY_Dev_1.rx, UART_RX_MAX_LEN);
-//         __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
-//     }
-// }
-
-/* 51 */
-
-
-
-/* use */
-// void main()
-// {
-//     UartPrintf(&HW_UART_ATY_Dev_1, "\r\nHello word!\r\n",);
-//     while (1)
-//     {
-//         UartReceiveProcess(&HW_UART_ATY_Dev_1);
-//     }
-// }
-
-// /**
-//  * @brief   uart receive data analysis in user define self
-//  */
-// void UartReceiveProcess_User_1(void){
-//     if(HW_UART_ATY_Dev_1.rx[0] == 'O'
-//         && HW_UART_ATY_Dev_1.rx[1] == 'K'
-//         && HW_UART_ATY_Dev_1.rx[2] == '?')
-//         printf_ATY("OK!");
-
-//     if(HW_UART_ATY_Dev_1.rx[0] == 'P'
-//         && HW_UART_ATY_Dev_1.rx[1] == 'W'
-//         && HW_UART_ATY_Dev_1.rx[2] == 'R'
-//         && HW_UART_ATY_Dev_1.rx[3] == 'O'
-//         && HW_UART_ATY_Dev_1.rx[4] == 'F'
-//         && HW_UART_ATY_Dev_1.rx[5] == 'F'
-//         )
-//         PWR_BTN_Off(&PWR_BTN_ATY_t_1);
-//
-//     // echo back, both type has tested
-//     UartSendBytes(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &HW_UART_ATY_Dev_1);
-//     UartPrintf(&HW_UART_ATY_Dev_1, "\r\n%s\r\n", HW_UART_ATY_Dev_1.rx);
-//
-//     if(HW_UART_ATY_Dev_1.rxCount != 0){
-//         Modbus_Process(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
-
-//         if(MODBUS_S_LOW_ATY_Dev_1.setFlag == 1){
-//             MODBUS_S_LOW_ATY_Dev_1.setFlag = 0;
-//             TransMbRegsToFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1);
-//         }
-
-// //        memcpy((char*)cdcStr, ((const char*)(HW_UART_ATY_Dev_3.rx)), HW_UART_ATY_Dev_3.rxCount);
-// //        CDC_Transmit_FS(cdcStr, HW_UART_ATY_Dev_3.rxCount);
-// //        memset(cdcStr, 0, HW_UART_ATY_Dev_3.rxCount);
-// //        HW_UART_ATY_Dev_3.rxCount = 0;
-//     }
-// }
+#include "HW_UART_ATY.h"
+extern DMA_HandleTypeDef hdma_usart1_rx;
+void UartReceiveProcess_User_1(void);
+void UartInit_1(uint8_t* rx){
+    HAL_UARTEx_ReceiveToIdle_DMA(&huart1, rx, UART_RX_MAX_LEN);
+    __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
+}
+void UartSendByte_1(uint8_t byte){
+    HAL_UART_Transmit(&huart1, (uint8_t*)&byte, 1, 0xFFFF);
+}
+struct HW_UART_ATY_Dev HW_UART_ATY_Dev_1 = {
+    // .rx = uartRx1,
+    .rx = {0},
+    .rxCount = 0,
+    .txCount = 0,
+    .rcvOverTimeOutCountNum = 1,
+    .rcvOverTimeOutCount = 0,
+    .rcvOverFlag = 0,
+
+    .uartInitFlag = 0,
+    .uartInit = UartInit_1,
+    .uartSendByte = UartSendByte_1,
+
+    .uartReceiveProcess_User = UartReceiveProcess_User_1,
+
+    .lock = __ATY_UNLOCKED
+};
+void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef* huart, uint16_t Size){
+    if(huart == &huart1){
+        HAL_UART_DMAStop(&huart1);
+        HW_UART_ATY_Dev_1.rcvOverTimeOutCount = 0;
+        HW_UART_ATY_Dev_1.rxCount = UART_RX_MAX_LEN - __HAL_DMA_GET_COUNTER(&hdma_usart1_rx);
+        HW_UART_ATY_Dev_1.rcvOverFlag = 0;
+
+        HAL_UARTEx_ReceiveToIdle_DMA(&huart1, HW_UART_ATY_Dev_1.rx, UART_RX_MAX_LEN);
+        __HAL_DMA_DISABLE_IT(&hdma_usart1_rx, DMA_IT_HT);
+    }
+}
+*/
+
+// 51
+
+
 
+/* use
+void main()
+{
+    UartPrintf(&HW_UART_ATY_Dev_1, "\r\nHello word!\r\n",);
+    while (1)
+    {
+        UartReceiveProcess(&HW_UART_ATY_Dev_1);
+    }
+}
+
+void UartReceiveProcess_User_1(void){
+    if(HW_UART_ATY_Dev_1.rx[0] == 'O'
+        && HW_UART_ATY_Dev_1.rx[1] == 'K'
+        && HW_UART_ATY_Dev_1.rx[2] == '?')
+        printf_ATY("OK!");
+
+    if(HW_UART_ATY_Dev_1.rx[0] == 'P'
+        && HW_UART_ATY_Dev_1.rx[1] == 'W'
+        && HW_UART_ATY_Dev_1.rx[2] == 'R'
+        && HW_UART_ATY_Dev_1.rx[3] == 'O'
+        && HW_UART_ATY_Dev_1.rx[4] == 'F'
+        && HW_UART_ATY_Dev_1.rx[5] == 'F'
+        )
+        PWR_BTN_Off(&PWR_BTN_ATY_t_1);
+
+    // echo back, both type has tested
+    // UartSendBytes(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &HW_UART_ATY_Dev_1);
+    // UartPrintf(&HW_UART_ATY_Dev_1, "\r\n%s\r\n", HW_UART_ATY_Dev_1.rx);
+
+    if(HW_UART_ATY_Dev_1.rxCount != 0){
+        Modbus_Process(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
+
+        if(MODBUS_S_LOW_ATY_Dev_1.setFlag == 1){
+            MODBUS_S_LOW_ATY_Dev_1.setFlag = 0;
+            TransMbRegsToFloat(rgf, &MODBUS_S_LOW_ATY_Dev_1);
+        }
+
+        // simulate data change
+        // for(uint8_t i = 0; i < MODBUS_REG_HOLDING_SIZE / 2; i++){
+        //     if(rgf[i] < 100.0)
+        //         rgf[i] += (0.01 * (float)(i + 1));
+        //     else if(rgf[i] >= 100.0 && rgf[i] < 200.0)
+        //         rgf[i] = i;
+        //     // else test write save if rgf[i] > 200.0, data stop auto change
+        // }
+
+        // trans uart to usb cdc
+        // memcpy((char*)cdcStr, ((const char*)(HW_UART_ATY_Dev_3.rx)), HW_UART_ATY_Dev_3.rxCount);
+        // CDC_Transmit_FS(cdcStr, HW_UART_ATY_Dev_3.rxCount);
+        // memset(cdcStr, 0, HW_UART_ATY_Dev_3.rxCount);
+        // HW_UART_ATY_Dev_3.rxCount = 0;
+    }
+}
+*/
 
 /******************************************************************************/
 

+ 47 - 11
IAP_YMODEM_STM32F1_ATY.c

@@ -166,7 +166,7 @@ HAL_StatusTypeDef Interface_Transmit(uint8_t* bytes, uint16_t size, uint32_t tim
 /**
   * @brief  Display the Main Menu on HyperTerminal
   */
-void Main_Menu(void){
+void Main_Menu(uint8_t transKey){
     uint8_t key = 0;
     uint16_t errTimes = 0;
     uint32_t FlashProtection = 0;
@@ -194,11 +194,16 @@ void Main_Menu(void){
         /* Clean the input path */
         Interface_Clean();
 
-        /* Receive key */
-        Interface_Receive(&key, 1, IAP_3_TIME);
-        /* Auto jump to app */
-        if(key == 0)
-            key = 51;
+        if(transKey != 0){
+            key = transKey;
+        }
+        else{
+            /* Receive key */
+            Interface_Receive(&key, 1, IAP_3_TIME);
+            /* Auto jump to app */
+            if(key == 0)
+                key = '3';
+        }
 
         switch(key){
             case '*':
@@ -211,6 +216,7 @@ void Main_Menu(void){
                 break;
             case '1':
                 /* Download user application in the Flash */
+                // HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_SET);
                 if(Interface_Download() != COM_OK)
                     break;
             case '3':
@@ -255,12 +261,33 @@ void Main_Menu(void){
     }
 }
 
+// do not init usb if not use and connect to others with d+ dan d- pins
 #include "rtc.h"
+#include "usart.h"
 void Main_Cycle(void){
     uint8_t sKey[2] = {0};
     HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, IAP_VerA);
     HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, IAP_VerB);
     HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, IAP_VerC);
+
+    HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_RESET);
+    Interface_PutString("\r\n\r\nS to start\r\n\r\n");
+    if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR6) == __ATY_BL_APP){
+        HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR6, 0);
+        JumpToAppWithReset();
+    }
+    else if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR6) == __ATY_BL_UPDATE){
+        HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR6, 0);
+        MX_USART3_UART_Init();
+        Main_Menu('1');
+    }
+    else{
+    #ifndef IAP_YMODEM_STM32F1_ATY_USB
+        HAL_Delay(6000);    // for android sereen start
+        MX_USART3_UART_Init();
+    #endif
+    }
+
     Interface_PutString("\r\n\r\nS to start\r\n\r\n");
     while(1){
     #ifdef IAP_YMODEM_STM32F1_ATY_USB
@@ -270,7 +297,7 @@ void Main_Cycle(void){
             Interface_PutByte(0x00);
             Interface_Receive(t, 1, 10);
             continue;
-        }
+    }
     #endif
         if(1){
             if(Interface_Receive(sKey, 2, IAP_S_TIME) == HAL_OK){
@@ -290,7 +317,7 @@ void Main_Cycle(void){
                     }
                     else{
                         Interface_Clean();
-                        Main_Menu();
+                        Main_Menu(0);
                     }
                 }
                 else{
@@ -299,14 +326,14 @@ void Main_Cycle(void){
             }
             else{
                 Interface_Clean();
-                Main_Menu();
+                Main_Menu(0);
             }
         }
         /* Keep the user application running */
         else{
             JumpToAppWithReset();
         }
-    }
+}
 }
 
 /* ****************************************************************************/
@@ -896,6 +923,7 @@ COM_StatusTypeDef Ymodem_Receive(uint32_t* p_size){
     uint8_t* file_ptr;
     uint8_t file_size[FILE_SIZE_LENGTH], tmp;
     COM_StatusTypeDef result = COM_OK;
+    uint8_t tryTimes = 0;
 
     /* Initialize flashdestination variable */
     flashdestination = APPLICATION_ADDRESS;
@@ -907,13 +935,14 @@ COM_StatusTypeDef Ymodem_Receive(uint32_t* p_size){
             statA = ReceivePacket(aPacketData, &packet_length, DOWNLOAD_TIMEOUT);
             switch(statA){
                 case HAL_OK:
+                    HAL_GPIO_TogglePin(SYSLED_GPIO_Port, SYSLED_Pin);
                     errors = 0;
                     switch(packet_length){
                         case 2:
                             /* Abort by sender */
                             Interface_PutByte(ACK);
                             result = COM_ABORT;
-                            break;
+                            return result;
                         case 0:
                             /* End of transmission */
                             Interface_PutByte(ACK);
@@ -1007,8 +1036,15 @@ COM_StatusTypeDef Ymodem_Receive(uint32_t* p_size){
                         Interface_PutByte(CA);
                     }
                     else{
+                        tryTimes++;
+                        if(tryTimes > 10){
+                            Interface_PutByte(ACK);
+                            result = COM_ABORT;
+                            return result;
+                        }
                         /* Ask for a packet */
                         Interface_PutByte(CRC16);
+                        HAL_GPIO_TogglePin(SYSLED_GPIO_Port, SYSLED_Pin);
                     }
                     break;
             }

+ 5 - 5
IAP_YMODEM_STM32F1_ATY.h

@@ -43,14 +43,14 @@
 #endif
 
 #define IAP_VerA 102
-#define IAP_VerB 251
-#define IAP_VerC 202
+#define IAP_VerB 260
+#define IAP_VerC 104
 
 #define Interface_UART huart3
 extern UART_HandleTypeDef Interface_UART;
 
 #ifndef IAP_YMODEM_STM32F1_ATY_USB
-#if 0
+#if 0 // define in keil project C/C++ target define
 #define IAP_YMODEM_STM32F1_ATY_USB
 #endif
 #endif
@@ -60,7 +60,7 @@ extern UART_HandleTypeDef Interface_UART;
 #define IAP_S_TIME RX_TIMEOUT
 #else
 // #define IAP_S_TIME RX_TIMEOUT
-#define IAP_S_TIME 1000
+#define IAP_S_TIME 2000
 #endif
 #endif
 #ifndef IAP_3_TIME
@@ -75,7 +75,7 @@ extern USBD_HandleTypeDef hUsbDeviceFS;
 void PUT_IN_CDC_Receive_FS(uint8_t* Buf, uint32_t* Len);
 #endif
 
-void Main_Menu(void);
+void Main_Menu(uint8_t transKey);
 void Main_Cycle(void);
 /******************************************************************************/
 

+ 10 - 2
INCLUDE_ATY.h

@@ -362,11 +362,19 @@ typedef signed long int int64_t;        // 64 = 32, not 64 bit platform
 #define __ATY_RW_W 0
 #define __ATY_RW_R 1
 #define __ATY_RW_RW 2
+#define __ATY_PN_P 0    // + CW
+#define __ATY_PN_N 1    // - CCW
+
+#define __ATY_OK 0
+#define __ATY_ERROR 1
 
 #define __ATY_BUSY 99
 #define __ATY_LOCKED 101
 #define __ATY_UNLOCKED 102
 
+#define __ATY_BL_APP 0xA503
+#define __ATY_BL_UPDATE 0xA501
+
 #if (USE_RTOS == 1U)
 #define __ATY_LOCK(__HANDLE__)
 #define __ATY_UNLOCK(__HANDLE__)
@@ -463,8 +471,8 @@ typedef char* va_list;
 #endif /* __stdarg_h */
 #endif /* __ATY_USE_STDARG_LIB */
 
-#define __ATY_PRINT_ENABLE 1
-#define __ATY_DEBUG_ENABLE 1
+#define __ATY_PRINT_ENABLE 0
+#define __ATY_DEBUG_ENABLE 0
 #if __ATY_PRINT_ENABLE
 #include "HW_UART_ATY.h"
 extern struct HW_UART_ATY_Dev HW_UART_ATY_Dev_1;

+ 20 - 18
LED_ATY.c

@@ -210,26 +210,28 @@ uint8_t SysLedBlink(struct LED_ATY_Dev* dev){
 #endif /* __LED_ATY_C */
 
 /************************************ etc *************************************/
-/* init */
+/* init
 // Sysled ----------------------------------------------------------------------
-// #include "LED_ATY.h"
-// void SysLed_1_IO_SET(uint8_t level){
-//     if(level)
-//         HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_SET);
-//     else
-//         HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_RESET);
-// }
-// struct LED_ATY_Dev LED_ATY_t_1 = {
-//     .ledBlinkStep = 0,
-//     .ledBlinkType = 0x20,
-//     .ioSet = SysLed_1_IO_SET,
-//     .longSteps = 20,
-//     .lock = __ATY_UNLOCKED
-// };
+#include "LED_ATY.h"
+void SysLed_1_IO_SET(uint8_t level){
+    if(level)
+        HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_SET);
+    else
+        HAL_GPIO_WritePin(SYSLED_GPIO_Port, SYSLED_Pin, GPIO_PIN_RESET);
+}
+struct LED_ATY_Dev LED_ATY_t_1 = {
+    .ledBlinkStep = 0,
+    .ledBlinkType = 0x20,
+    .ioSet = SysLed_1_IO_SET,
+    .longSteps = 20,
+    .lock = __ATY_UNLOCKED
+};
+*/
 
-/* use */
-// SysLedBlink(&LED_ATY_t_1); // put at 1ms cycle
-// LED_ATY_t_1.ledBlinkType = 0x02;
+/* use
+LED_ATY_t_1.ledBlinkType = 0x02;
+SysLedBlink(&LED_ATY_t_1); // put at 1ms cycle
+*/
 
 /******************************************************************************/
 

+ 78 - 71
MAX31865_ATY.c

@@ -1,7 +1,7 @@
 /**
 * @file MAX31865_ATY.c
 *
-* @param Project DEVICE_GENERAL_ATY_LIB
+* @param Project DEVICE_DRIVER_ATY_LIB
 *
 * @author ATY
 *
@@ -18,13 +18,12 @@
 *
 * @brief functions of MAX31865 platinum resistance temperature detector for C platform
 *
+* @note SPI_POLARITY_HIGH + SPI_PHASE_2EDGE = CPOL=1, CPHA=1 = SPI Mode 3
+*
 * @version
 *       - 1_01_251216 > ATY
 *           -# Preliminary version, first Release
-*
 * @todo MAX31865_CONFIG_FAULTCTR and MAX31865_REG_H/LFAULT_M/LSB
-*
-* @note SPI_POLARITY_HIGH + SPI_PHASE_2EDGE = CPOL=1, CPHA=1 = SPI Mode 3
 ********************************************************************************
 */
 
@@ -121,6 +120,8 @@ uint8_t MAX31865_ReadConfig(struct MAX31865_ATY_Dev* dev){
  * @return  uint8_t Execution result
  */
 uint8_t MAX31865_ReadRTD(struct MAX31865_ATY_Dev* dev){
+    MAX31865_Init(dev);
+
     __ATY_LOCK(dev);
 
     wrData[0] = MAX31865_REG_RTD_MSB;
@@ -225,6 +226,8 @@ uint8_t MAX31865_ClearFaults(struct MAX31865_ATY_Dev* dev){
  * @return  uint8_t Execution result
  */
 uint8_t MAX31865_OneShot(struct MAX31865_ATY_Dev* dev){
+    MAX31865_Init(dev);
+
     __ATY_LOCK(dev);
 
     wrData[0] = MAX31865_REG_CONFIG;
@@ -278,74 +281,78 @@ float MAX31865_CalculateTemperature(struct MAX31865_ATY_Dev* dev, uint16_t rtd){
 #endif /* __MAX31865_ATY_C */
 
 /************************************ etc *************************************/
-/* init */
+/* init
 // MAX31865 --------------------------------------------------------------------
-// #include "MAX31865_ATY.h"
-// void MAX31865_1_NSS_SET(uint8_t level){
-//     if(level == __ATY_HL_L)
-//         HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_RESET);
-//     else if(level == __ATY_HL_H)
-//         HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_SET);
-// }
-// uint8_t MAX31865_1_SPI(uint8_t* data_t, uint16_t len, uint8_t rw){
-//     if(rw == __ATY_RW_R){
-//         return HAL_SPI_Receive(&hspi2, (uint8_t*)data_t, len, 1000);
-//     }
-//     else{
-//         return HAL_SPI_Transmit(&hspi2, (uint8_t*)data_t, len, 1000);
-//     }
-// }
-// struct MAX31865_ATY_Dev MAX31865_ATY_Dev_1 = {
-//     .nssSet = MAX31865_1_NSS_SET,
-//     .spiProcess = MAX31865_1_SPI,
-
-//     .rtdWires = 3,
-//     .filter50Hz = 1,
-//     .autoConvert = 1,
-//     .bias = 1,
-//     .faultControl = 0,
-
-//     .rtdNominal = 100.0,
-//     .refResistor = 424.0,
-
-//     .lock = __ATY_UNLOCKED
-// };
-
-
-/* use */
-// uint8_t Max31865_errCount = 0;
-// void MAX31865_Test(void){
-//     MAX31865_Init(&MAX31865_ATY_Dev_1);
-//     MAX31865_ReadRTD(&MAX31865_ATY_Dev_1);
-//     MAX31865_ReadFault(&MAX31865_ATY_Dev_1);
-
-//     // (9584640.0 / MAX31865_ATY_Dev_1.refResistor) -> 500C
-//     // (2015232.0 / MAX31865_ATY_Dev_1.refResistor) -> -100C
-//     if(MAX31865_ATY_Dev_1.faultStatus != 0
-//         || MAX31865_ATY_Dev_1.rtdValue == 32767
-//         || MAX31865_ATY_Dev_1.rtdValue == 0
-//         || MAX31865_ATY_Dev_1.rtdValue > (9584640.0 / MAX31865_ATY_Dev_1.refResistor)
-//         || MAX31865_ATY_Dev_1.rtdValue < (2015232.0 / MAX31865_ATY_Dev_1.refResistor)){
-//         Max31865_errCount++;
-//         // if cycle is long like 1s, this errCount can be lower
-//         if(Max31865_errCount > 6){
-//             Max31865_errCount = 0;
-//             MAX31865_ATY_Dev_1.initFlag = 0;
-//             // Notice: ClearFaults might make next rtd value wrong,
-//             // so wait a cycle to read value after clear fault
-//             if(MAX31865_ATY_Dev_1.faultStatus != 0) MAX31865_ClearFaults(&MAX31865_ATY_Dev_1);
-//             printf_ATY("\r\nRTD Value Abnormal - Reinitializing...");
-//         }
-//     }
-//     // else
-//     {
-//         printf_ATY("\r\nRTD: 0x%04X, Resistance: %.2f ohm, Temperature: %.2f C",
-//             MAX31865_ATY_Dev_1.rtdValue,
-//             MAX31865_CalculateResistance(&MAX31865_ATY_Dev_1, 0),
-//             MAX31865_CalculateTemperature(&MAX31865_ATY_Dev_1, 0));
-//         // MAX31865_ReadConfig(&MAX31865_ATY_Dev_1);
-//     }
-// }
+#include "MAX31865_ATY.h"
+void MAX31865_1_NSS_SET(uint8_t level){
+    if(level == __ATY_HL_L)
+        HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_RESET);
+    else if(level == __ATY_HL_H)
+        HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_SET);
+}
+uint8_t MAX31865_1_SPI(uint8_t* data_t, uint16_t len, uint8_t rw){
+    if(rw == __ATY_RW_R){
+        return HAL_SPI_Receive(&hspi2, (uint8_t*)data_t, len, 1000);
+    }
+    else{
+        return HAL_SPI_Transmit(&hspi2, (uint8_t*)data_t, len, 1000);
+    }
+}
+struct MAX31865_ATY_Dev MAX31865_ATY_Dev_1 = {
+    .nssSet = MAX31865_1_NSS_SET,
+    .spiProcess = MAX31865_1_SPI,
+    .initFlag = 0,
+
+    .bias = 1,
+    .autoConvert = 1,
+    .rtdWires = 3,
+    .faultControl = 0,
+    .filter50Hz = 1,
+
+    .rtdNominal = 100.0,
+    .refResistor = 424.0,
+
+    .rtdValue = 0,
+    .faultStatus = 0,
+
+    .lock = __ATY_UNLOCKED
+};
+*/
+
+/* use
+uint8_t Max31865_errCount = 0;
+void MAX31865_Test(void){
+    MAX31865_ReadRTD(&MAX31865_ATY_Dev_1);
+    MAX31865_ReadFault(&MAX31865_ATY_Dev_1);
+
+    // (9584640.0 / MAX31865_ATY_Dev_1.refResistor) -> 500C
+    // (2015232.0 / MAX31865_ATY_Dev_1.refResistor) -> -100C
+    if(MAX31865_ATY_Dev_1.faultStatus != 0
+        || MAX31865_ATY_Dev_1.rtdValue == 32767
+        || MAX31865_ATY_Dev_1.rtdValue == 0
+        || MAX31865_ATY_Dev_1.rtdValue > (9584640.0 / MAX31865_ATY_Dev_1.refResistor)
+        || MAX31865_ATY_Dev_1.rtdValue < (2015232.0 / MAX31865_ATY_Dev_1.refResistor)){
+        Max31865_errCount++;
+        // if cycle is long like 1s, this errCount can be lower
+        if(Max31865_errCount > 6){
+            Max31865_errCount = 0;
+            MAX31865_ATY_Dev_1.initFlag = 0;
+            // Notice: ClearFaults might make next rtd value wrong,
+            // so wait a cycle to read value after clear fault
+            if(MAX31865_ATY_Dev_1.faultStatus != 0) MAX31865_ClearFaults(&MAX31865_ATY_Dev_1);
+            printf_ATY("\r\nRTD Value Abnormal - Reinitializing...");
+        }
+    }
+    // else
+    {
+        printf_ATY("\r\nRTD: 0x%04X, Resistance: %.2f ohm, Temperature: %.2f C",
+            MAX31865_ATY_Dev_1.rtdValue,
+            MAX31865_CalculateResistance(&MAX31865_ATY_Dev_1, 0),
+            MAX31865_CalculateTemperature(&MAX31865_ATY_Dev_1, 0));
+        // MAX31865_ReadConfig(&MAX31865_ATY_Dev_1);
+    }
+}
+*/
 
 /******************************************************************************/
 

+ 21 - 21
MAX31865_ATY.h

@@ -1,7 +1,7 @@
 /**
 * @file MAX31865_ATY.h
 *
-* @param Project DEVICE_GENERAL_ATY_LIB
+* @param Project DEVICE_DRIVER_ATY_LIB
 *
 * @author ATY
 *
@@ -33,6 +33,26 @@
 
 /******************************************************************************/
 
+struct MAX31865_ATY_Dev{
+    void (*nssSet)(uint8_t level);
+    uint8_t (*spiProcess)(uint8_t* data_t, uint16_t len, uint8_t rw);
+    uint8_t initFlag;
+
+    uint8_t bias;                   // Bias on (1) or off (0)
+    uint8_t autoConvert;            // Auto conversion enabled (1) or disabled (0)
+    uint8_t rtdWires;               // RTD wire count (2, 3, 4)
+    uint8_t faultControl;
+    uint8_t filter50Hz;             // Filter 50Hz (1) or 60Hz (0)
+
+    float rtdNominal;               // RTD nominal resistance (typically 100.0 ohm for PT100)
+    float refResistor;              // Reference resistor value (typically 430.0 ohm for PT100)
+
+    uint16_t rtdValue;
+    uint8_t faultStatus;
+
+    uint8_t lock;
+};
+
 // MAX31865 Register Addresses
 #define MAX31865_REG_CONFIG         0x00
 #define MAX31865_REG_RTD_MSB        0x01
@@ -60,26 +80,6 @@
 #define MAX31865_FAULT_RTDIN_LOW    0x08
 #define MAX31865_FAULT_OVUV         0x04
 
-struct MAX31865_ATY_Dev{
-    void (*nssSet)(uint8_t level);
-    uint8_t (*spiProcess)(uint8_t* data_t, uint16_t len, uint8_t rw);
-
-    uint8_t rtdWires;               // RTD wire count (2, 3, 4)
-    uint8_t filter50Hz;             // Filter 50Hz (1) or 60Hz (0)
-    uint8_t bias;                   // Bias on (1) or off (0)
-    uint8_t autoConvert;            // Auto conversion enabled (1) or disabled (0)
-    uint8_t faultControl;
-
-    float rtdNominal;               // RTD nominal resistance (typically 100.0 ohm for PT100)
-    float refResistor;              // Reference resistor value (typically 430.0 ohm for PT100)
-
-    uint8_t initFlag;
-    uint16_t rtdValue;
-    uint8_t faultStatus;
-
-    uint8_t lock;
-};
-
 uint8_t MAX31865_Init(struct MAX31865_ATY_Dev* dev);
 uint8_t MAX31865_ReadConfig(struct MAX31865_ATY_Dev* dev);
 uint8_t MAX31865_ReadRTD(struct MAX31865_ATY_Dev* dev);

+ 44 - 41
MODBUS_S_LOW_ATY.c

@@ -16,7 +16,7 @@
 *                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
 *       - Your use will be deemed to have accepted the terms of this statement.
 *
-* @brief functions of modbus for all device
+* @brief functions of modbus slaver for all device
 *
 * @note 4 byte per reg, save float or uint32
 *
@@ -225,52 +225,55 @@ void TransMbRegsToFloat(float* floatBuf, struct MODBUS_S_LOW_ATY_Dev* dev){
 #endif /* __MODBUS_S_LOW_ATY_C */
 
 /************************************ etc *************************************/
-/* init */
+/* init
 // Modbus ----------------------------------------------------------------------
-// #include "MODBUS_S_LOW_ATY.h"
-// float mbG[MODBUS_REG_HOLDING_SIZE / 2] = {0};
-// uint8_t MODBUS1_UART(uint8_t* buf, uint8_t len){
-//     UartSendBytes(buf, len, &HW_UART_ATY_Dev_1);
-//     return 0;
-// }
-// struct MODBUS_S_LOW_ATY_Dev MODBUS_S_LOW_ATY_Dev_1 = {
-//     .addr = 0x01,
-//     .mbRegs = {0},
-//     .uartSendBytes = MODBUS1_UART,
-//     .bigEndian = 0,
-//     .lock = __ATY_UNLOCKED
-// };
+#include "MODBUS_S_LOW_ATY.h"
+float rgf[MODBUS_REG_HOLDING_SIZE / 2] = {0};
+uint8_t MODBUS1_UART(uint8_t* buf, uint8_t len){
+    UartSendBytes(buf, len, &HW_UART_ATY_Dev_1);
+    return 0;
+}
+struct MODBUS_S_LOW_ATY_Dev MODBUS_S_LOW_ATY_Dev_1 = {
+    .addr = 0x01,
+    .mbRegs = {0},
+    .uartSendBytes = MODBUS1_UART,
+    .bigEndian = 0,
 
-/* use */
-// void UartReceiveProcess_User_1(void){
-//     if(HW_UART_ATY_Dev_1.rx[0] == 'O'
-//         && HW_UART_ATY_Dev_1.rx[1] == 'K'
-//         && HW_UART_ATY_Dev_1.rx[2] == '?')
-//         printf_ATY("OK!");
+    .lock = __ATY_UNLOCKED
+};
+*/
 
-//     if(HW_UART_ATY_Dev_1.rxCount != 0){
-//         Modbus_Process(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
+/* use
+void UartReceiveProcess_User_1(void){
+    if(HW_UART_ATY_Dev_1.rx[0] == 'O'
+        && HW_UART_ATY_Dev_1.rx[1] == 'K'
+        && HW_UART_ATY_Dev_1.rx[2] == '?')
+        printf_ATY("OK!");
 
-//         if(MODBUS_S_LOW_ATY_Dev_1.setFlag == 1){
-//             MODBUS_S_LOW_ATY_Dev_1.setFlag = 0;
-//             TransMbRegsToFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1);
-//         }
+    if(HW_UART_ATY_Dev_1.rxCount != 0){
+        Modbus_Process(HW_UART_ATY_Dev_1.rx, HW_UART_ATY_Dev_1.rxCount, &MODBUS_S_LOW_ATY_Dev_1);
 
-//         // simulate data change
-//         for(uint8_t i = 0; i < MODBUS_REG_HOLDING_SIZE / 2; i++){
-//             if(mbG[i] < 100.0)
-//                 mbG[i] += (0.01 * (float)(i + 1));
-//             else if(mbG[i] >= 100.0 && mbG[i] < 200.0)
-//                 mbG[i] = i;
-//             // else test write save if mbG[i] > 200.0, data stop auto change
-//         }
-//     }
-// }
+        if(MODBUS_S_LOW_ATY_Dev_1.setFlag == 1){
+            MODBUS_S_LOW_ATY_Dev_1.setFlag = 0;
+            TransMbRegsToFloat(rgf, &MODBUS_S_LOW_ATY_Dev_1);
+        }
 
-// // 100ms cycle
-// {
-//     UpdateMbRegsFromFloat(mbG, &MODBUS_S_LOW_ATY_Dev_1);
-// }
+        // simulate data change
+        for(uint8_t i = 0; i < MODBUS_REG_HOLDING_SIZE / 2; i++){
+            if(rgf[i] < 100.0)
+                rgf[i] += (0.01 * (float)(i + 1));
+            else if(rgf[i] >= 100.0 && rgf[i] < 200.0)
+                rgf[i] = i;
+            // else test write save if rgf[i] > 200.0, data stop auto change
+        }
+    }
+}
+
+// 100ms cycle
+{
+    UpdateMbRegsFromFloat(rgf, &MODBUS_S_LOW_ATY_Dev_1);
+}
+*/
 
 /******************************************************************************/
 

+ 1 - 1
MODBUS_S_LOW_ATY.h

@@ -16,7 +16,7 @@
 *                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
 *       - Your use will be deemed to have accepted the terms of this statement.
 *
-* @brief functions of modbus for all device
+* @brief functions of modbus slaver for all device
 *
 * @version
 *       - 1_01_221029 > ATY

+ 349 - 0
MOTOR_STEP_C_ATY.c

@@ -0,0 +1,349 @@
+/**
+* @file MOTOR_STEP_C_ATY.c
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of closed loop stepper motor control for C platform
+*
+* @note Slave Mode: Disable
+*       Trigger Source: Disable
+*       Clock Source: Internal Clock
+*       Channel2: PWM Generation CH2
+*       Prescaler: 71
+*       Counter Mode: Up
+*       Counter Period: 999
+*       Internal Clock Division: No Division
+*       auto-reload preload: Disable
+*       Master/Slave Mode (MSM bit): Disable
+*       Trigger Event Selection: Update Event
+*       PWM Generation Channel 2 Mode: PWM mode 2
+*       Pulse: 499
+*       Output compare preload: Enable
+*       Fast Mode: Disable
+*       CH Polarity: High
+*       CH Idle State: Reset
+*
+*       htim1.Init.Prescaler = 71;
+*       htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
+*       htim1.Init.Period = 999;
+*       htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+*       htim1.Init.RepetitionCounter = 0;
+*       htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+*       sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
+*       sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
+*       sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+*       sConfigOC.OCMode = TIM_OCMODE_PWM2;
+*       sConfigOC.Pulse = 499;
+*       sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
+*       sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
+*       sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
+*       sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
+*       sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+*       htim2.Init.Prescaler = 0;
+*       htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
+*       htim2.Init.Period = 65535;
+*       htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+*       htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+*       sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
+*       sSlaveConfig.InputTrigger = TIM_TS_ITR0;
+*       sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
+*       sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+*
+*       import angle to use COMPENSATE
+*
+* @version
+*       - 1_00_260109 > ATY
+*           -# Preliminary version
+********************************************************************************
+*/
+
+#ifndef __MOTOR_STEP_C_ATY_C
+#define __MOTOR_STEP_C_ATY_C
+
+#include "MOTOR_STEP_C_ATY.h"
+#define MOTOR_STEP_C_ATY_TAG "\r\n[MOTOR_STEP_C_ATY] "
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+uint8_t MSC_MoveToAngleSteps(struct MOTOR_STEP_C_ATY_Dev* dev,
+    float targetAngle, float currentAngle){
+    uint8_t dir = __ATY_PN_P;
+    float angleSpace = (360.0 / dev->fullSteps / dev->microstepping);
+    if(currentAngle > targetAngle + angleSpace){
+        if(currentAngle - targetAngle > 180.0){
+            dev->stepCount = (targetAngle + 360.0 - currentAngle) / angleSpace;
+        }
+        else{
+            dir = __ATY_PN_N;
+            dev->stepCount = (currentAngle - targetAngle) / angleSpace;
+        }
+        dev->dirSet(dir);
+        dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
+        return 1;
+    }
+    else if(targetAngle > currentAngle + angleSpace){
+        if(targetAngle - currentAngle > 180.0){
+            dir = __ATY_PN_N;
+            dev->stepCount = (currentAngle + 360.0 - targetAngle) / angleSpace;
+        }
+        else{
+            dev->stepCount = (targetAngle - currentAngle) / angleSpace;
+        }
+        dev->dirSet(dir);
+        dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
+        return 1;
+    }
+    else{
+        return 0;
+    }
+}
+
+uint8_t MSC_Cycle(struct MOTOR_STEP_C_ATY_Dev* dev,
+    uint8_t mode, uint8_t enable, uint8_t direction,
+    uint16_t stepCount,
+    float frequency, float dutyCycle, float speed,
+    float currentAngle, float targetAngle){
+    float angleSpace = (360.0 / dev->fullSteps / dev->microstepping);
+    uint8_t regUpdateFlag = 0;
+
+    if(mode != dev->mode){
+        dev->mode = mode;
+        regUpdateFlag = 1;
+    }
+    if(enable != dev->enable){
+        dev->enable = enable;
+        if(dev->autoPower == 0) dev->enSet(dev->enable);
+    }
+    if(direction != dev->direction){
+        dev->direction = direction;
+        dev->dirSet(dev->direction);
+    }
+    if(targetAngle != dev->targetAngle){
+        while(targetAngle >= 360.0) targetAngle -= 360.0;
+        dev->targetAngle = targetAngle;
+        if(regUpdateFlag != 1) regUpdateFlag = 2;
+    }
+
+    if(stepCount != dev->stepCount){
+        dev->stepCount = stepCount;
+        if(dev->mode == MOTOR_STEP_C_MODE_POST_MOTION)
+            regUpdateFlag = 1;
+    }
+
+    if(speed != dev->speed){
+        dev->speed = speed;
+        dev->frequency = (dev->speed * (dev->fullSteps
+            * dev->microstepping) / 60.0);
+        dev->dutyCycle = 50.0;
+
+        if(dev->mode == MOTOR_STEP_C_MODE_NOCOUNT){
+            regUpdateFlag = 1;
+        }
+        else{
+            if(regUpdateFlag != 1) regUpdateFlag = 2;
+        }
+    }
+    else if(frequency != dev->frequency
+        || dutyCycle != dev->dutyCycle){
+        dev->frequency = frequency;
+        dev->dutyCycle = dutyCycle;
+        if(dev->dutyCycle < 0) dev->dutyCycle = 0;
+        else if(dev->dutyCycle > 100) dev->dutyCycle = 100;
+        dev->speed = (dev->frequency * 60.0
+            / (dev->fullSteps * dev->microstepping));
+
+        if(dev->mode == MOTOR_STEP_C_MODE_NOCOUNT){
+            regUpdateFlag = 1;
+        }
+        else{
+            if(regUpdateFlag != 1) regUpdateFlag = 2;
+        }
+    }
+
+    if(dev->mode == MOTOR_STEP_C_MODE_POST_MOTION
+        && dev->stepCount == 0){
+        if(dev->angleLock == 1){
+            dev->positionFixFlag++;
+        }
+        if(dev->positionFixFlag != 0){
+            if(MSC_MoveToAngleSteps(dev, dev->targetAngle, currentAngle) == 0){
+                dev->positionFixFlag = 0;
+                // dev->startAngle = 0.0;
+                // dev->targetAngle = 0.0;
+            }
+            else{
+                dev->positionFixFlag++;
+            }
+        }
+    }
+
+    if(dev->autoPower == 1){
+        if(regUpdateFlag == 0
+            && dev->stepCount == 0
+            && dev->positionFixFlag == 0
+            && dev->mode != MOTOR_STEP_C_MODE_NOCOUNT){
+            dev->enSet(0);
+        }
+        else{
+            dev->enSet(1);
+        }
+    }
+    else{
+        dev->enSet(dev->enable);
+    }
+    if(regUpdateFlag == 1 && dev->mode == MOTOR_STEP_C_MODE_POST_MOTION
+        && dev->positionFixFlag == 0){
+        dev->startAngle = currentAngle;
+        dev->targetAngle = ((dev->stepCount % (dev->fullSteps * dev->microstepping)) * 360.0)
+            / (dev->fullSteps * dev->microstepping) + dev->startAngle;
+        while(dev->targetAngle >= 360.0) dev->targetAngle -= 360.0;
+
+        dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
+        dev->positionFixFlag++;
+    }
+    else if(regUpdateFlag == 1 && dev->mode == MOTOR_STEP_C_MODE_NOCOUNT){
+        dev->pwmSet(dev->frequency, dev->dutyCycle);
+    }
+    return regUpdateFlag;
+}
+
+#endif /* __MOTOR_STEP_C_ATY_C */
+
+
+/************************************ etc *************************************/
+/* init
+// MOTOR Close -----------------------------------------------------------------
+#include "MOTOR_STEP_C_ATY.h"
+uint8_t MOTOR_STEP_C_1_EnSet(uint8_t en){
+    HAL_GPIO_WritePin(MS_EN_GPIO_Port, MS_EN_Pin,
+        (en == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
+    return __ATY_OK;
+}
+uint8_t MOTOR_STEP_C_1_DirSet(uint8_t dir){
+    HAL_GPIO_WritePin(MS_DIR_GPIO_Port, MS_DIR_Pin,
+        (dir == __ATY_PN_P) ? GPIO_PIN_SET : GPIO_PIN_RESET);
+    return __ATY_OK;
+}
+void MOTOR_STEP_C_1_PWM_NoCount(float freq, float dutycycle){
+    uint32_t ticksPeriod = 1000000U / freq;
+    uint32_t ticksPulse = ticksPeriod * dutycycle / 100.0;
+    HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
+    __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
+    __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
+    __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
+    HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
+}
+void MOTOR_STEP_C_1_PWM_Count(float freq, float dutycycle, uint16_t step){
+    uint32_t ticksPeriod = 1000000U / freq;
+    uint32_t ticksPulse = ticksPeriod * dutycycle / 100.0;
+    HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
+    HAL_TIM_Base_Stop_IT(&htim2);
+    if(step != 0){
+        __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
+        // Set 1 to make sure the system can generate one pulse
+        __HAL_TIM_SET_COUNTER(&htim2, 1);
+        // init counter 1, then do not need -1
+        __HAL_TIM_SET_AUTORELOAD(&htim2, step);
+        __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
+        __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
+        HAL_TIM_Base_Start_IT(&htim2);
+        HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
+    }
+}
+struct MOTOR_STEP_C_ATY_Dev MOTOR_STEP_C_ATY_Dev_1 = {
+    .enSet = MOTOR_STEP_C_1_EnSet,
+    .dirSet = MOTOR_STEP_C_1_DirSet,
+
+    .pwmSet = MOTOR_STEP_C_1_PWM_NoCount,
+    .pwmSetCount = MOTOR_STEP_C_1_PWM_Count,
+
+    .mode = 0xFF,
+    .enable = 0xFF,
+    .direction = 0xFF,
+    .stepCount = 0xFFFF,
+    .frequency = -1.0,
+    .dutyCycle = -1.0,
+    .speed = -1.0,
+
+    .autoPower = 0,
+    .positionFixFlag = 0,
+    .startAngle = 0.0,
+    .targetAngle = 0.0,
+    .forbidReverseCorrection = 0,
+    .angleLock = 0,
+
+    .fullSteps = 200,
+    .microstepping = 8,
+
+    .lock = __ATY_UNLOCKED
+};
+void MOTOR_STEP_C_1_ValueUpdateBack(struct MOTOR_STEP_C_ATY_Dev* dev){
+    RGF_MOTOR_STEP_COUNT = dev->stepCount;
+    RGF_MOTOR_FREQUENCY = dev->frequency;
+    RGF_MOTOR_DUTY_CYCLE = dev->dutyCycle;
+    RGF_MOTOR_SPEED = dev->speed;
+    RGF_MOTOR_ANGLE_LOCK_TARGET = dev->targetAngle;
+}
+void MOTOR_STEP_C_1_Init(void){
+    RGF_MOTOR_MODE = MOTOR_STEP_C_MODE_POST_MOTION;
+    RGF_MOTOR_ENABLE = 0;
+    RGF_MOTOR_DIRECTION = __ATY_PN_P;
+    RGF_MOTOR_STEP_COUNT = 6;
+    RGF_MOTOR_FREQUENCY = (1600.0 / 60.0);
+    RGF_MOTOR_DUTY_CYCLE = 50.0;
+    RGF_MOTOR_SPEED = 60.0;
+    RGF_MOTOR_ANGLE_LOCK_TARGET = 0;
+    // Prevent from getting into an interruption from the very beginning
+    __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
+}
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){
+    if(htim == &htim4){
+        UserTimerLoop_Cycle1ms(&HW_TIMER_ATY_Dev_4);
+    }
+    if((uint8_t)RGF_MOTOR_MODE == 0 && htim == &htim2){
+        // HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
+        // HAL_TIM_Base_Stop_IT(&htim2);
+        // RGF_MOTOR_STEP_COUNT = 0;
+        // MOTOR_STEP_C_ATY_Dev_1.stepCount = 0;
+        // MOTOR_STEP_C_ATY_Dev_1.dirSet(MOTOR_STEP_C_ATY_Dev_1.direction);
+    }
+}
+*/
+
+/* use
+MOTOR_STEP_C_1_Init();
+
+if(MSC_Cycle(&MOTOR_STEP_C_ATY_Dev_1,
+    (uint8_t)RGF_MOTOR_MODE,
+    (uint8_t)RGF_MOTOR_ENABLE,
+    (uint8_t)RGF_MOTOR_DIRECTION,
+    (uint16_t)RGF_MOTOR_STEP_COUNT,
+    RGF_MOTOR_FREQUENCY,
+    RGF_MOTOR_DUTY_CYCLE,
+    RGF_MOTOR_SPEED,
+    RGF_MOTOR_ANGLE,
+    RGF_MOTOR_ANGLE_LOCK,
+    RGF_MOTOR_ANGLE_LOCK_TARGET) != 0){
+    MOTOR_STEP_C_1_ValueUpdateBack(&MOTOR_STEP_C_ATY_Dev_1);
+}
+*/
+
+/******************************************************************************/
+
+/******************************** End Of File *********************************/
+

+ 83 - 0
MOTOR_STEP_C_ATY.h

@@ -0,0 +1,83 @@
+/**
+* @file MOTOR_STEP_C_ATY.h
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of close loop stepper motor control for C platform
+*        Based on position feedback from encoder (e.g. MT6816)
+*
+* @version
+*       - 1_00_260109 > ATY
+*           -# Preliminary version
+********************************************************************************
+*/
+
+#ifndef __MOTOR_STEP_C_ATY_H
+#define __MOTOR_STEP_C_ATY_H
+
+#include "INCLUDE_ATY.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+struct MOTOR_STEP_C_ATY_Dev{
+    uint8_t (*enSet)(uint8_t en);
+    uint8_t (*dirSet)(uint8_t dir);
+
+    void (*pwmSet)(float frequency, float dutycycle);
+    void (*pwmSetCount)(float frequency, float dutycycle, uint16_t step);
+
+    uint8_t mode;
+    uint8_t enable;
+    uint8_t direction;
+    uint16_t stepCount;
+    float frequency;        // Hz
+    float dutyCycle;        // 0-100f
+    float speed;            // rpm
+
+    uint8_t autoPower;
+    uint8_t forbidReverseCorrection;
+                            /* if used for flow control, fix over steps may lead
+                             no effect or bad effect, set this to 1 to forbid motor
+                             reverse */
+    uint8_t positionFixFlag;
+    float startAngle;
+    float targetAngle;
+    uint8_t angleLock;
+
+    uint16_t cycleSpace;    // in ms
+
+    uint16_t fullSteps;     // steps per revolution, 360 / 1.8 degree = 200 steps
+    uint8_t microstepping;  // 1/8 = 8, 1/16, 1/32, 1/64, 1/128, 1/256
+
+    uint8_t lock;
+};
+
+#define MOTOR_STEP_C_MODE_POST_MOTION 0x00   // post-Motion Correction
+#define MOTOR_STEP_C_MODE_NOCOUNT 0x01       // continuous mode - run continuously
+#define MOTOR_STEP_C_MODE_POSITION_CC 0x02   // position Closed-Loop Control
+#define MOTOR_STEP_C_MODE_ANGLE_LOCK 0x03    // angle lock
+
+uint8_t MSC_Cycle(struct MOTOR_STEP_C_ATY_Dev* dev,
+    uint8_t mode, uint8_t enable, uint8_t direction,
+    uint16_t stepCount,
+    float frequency, float dutyCycle, float speed,
+    float currentAngle, float targetAngle);
+
+#endif /* __MOTOR_STEP_C_ATY_H */
+
+/******************************** End Of File *********************************/

+ 281 - 0
MOTOR_STEP_O_ATY.c

@@ -0,0 +1,281 @@
+/**
+* @file MOTOR_STEP_O_ATY.c
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of open loop stepper motor control for C platform
+*
+* @note Slave Mode: Disable
+*       Trigger Source: Disable
+*       Clock Source: Internal Clock
+*       Channel2: PWM Generation CH2
+*       Prescaler: 71
+*       Counter Mode: Up
+*       Counter Period: 999
+*       Internal Clock Division: No Division
+*       auto-reload preload: Disable
+*       Master/Slave Mode (MSM bit): Disable
+*       Trigger Event Selection: Update Event
+*       PWM Generation Channel 2 Mode: PWM mode 2
+*       Pulse: 499
+*       Output compare preload: Enable
+*       Fast Mode: Disable
+*       CH Polarity: High
+*       CH Idle State: Reset
+*
+*       htim1.Init.Prescaler = 71;
+*       htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
+*       htim1.Init.Period = 999;
+*       htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+*       htim1.Init.RepetitionCounter = 0;
+*       htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+*       sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
+*       sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
+*       sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+*       sConfigOC.OCMode = TIM_OCMODE_PWM2;
+*       sConfigOC.Pulse = 499;
+*       sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
+*       sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
+*       sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
+*       sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
+*       sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
+*       htim2.Init.Prescaler = 0;
+*       htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
+*       htim2.Init.Period = 65535;
+*       htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
+*       htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
+*       sSlaveConfig.SlaveMode = TIM_SLAVEMODE_GATED;
+*       sSlaveConfig.InputTrigger = TIM_TS_ITR0;
+*       sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
+*       sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
+*
+* @version
+*       - 1_00_260109 > ATY
+*           -# Preliminary version
+********************************************************************************
+*/
+
+#ifndef __MOTOR_STEP_O_ATY_C
+#define __MOTOR_STEP_O_ATY_C
+
+#include "MOTOR_STEP_O_ATY.h"
+#define MOTOR_STEP_O_ATY_TAG "\r\n[MOTOR_STEP_O_ATY] "
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+/**
+ * @brief open loop stepper motor control
+ *
+ * @param dev
+ * @param mode
+ * @param enable
+ * @param direction
+ * @param stepCount
+ * @param frequency
+ * @param dutyCycle
+ * @param speed
+ * @return uint8_t 0: no update, 1: update, only for register update, en and dir is hardware
+ * @note - Frequency and speed are mutually exclusive set, when set one, another
+ *       is auto calculate and update, speed has higher priority.
+ *       - When use speed, dutyCycle will set to 50% automatically.
+ *       - This function based on diff input and dev registers, so do not forget
+ *       update input registers back after update, like MSO_1_ValueUpdateBack().
+ */
+uint8_t MSO_Cycle(struct MOTOR_STEP_O_ATY_Dev* dev,
+    uint8_t mode, uint8_t enable, uint8_t direction,
+    uint16_t stepCount,
+    float frequency, float dutyCycle, float speed){
+    uint8_t regUpdateFlag = 0;
+
+    if(mode != dev->mode){
+        dev->mode = mode;
+        regUpdateFlag = 1;
+    }
+
+    if(enable != dev->enable){
+        dev->enable = enable;
+        dev->enSet(dev->enable);
+        if(regUpdateFlag == 0) regUpdateFlag = 2;
+    }
+    if(direction != dev->direction){
+        dev->direction = direction;
+        dev->dirSet(dev->direction);
+        if(regUpdateFlag == 0) regUpdateFlag = 2;
+    }
+
+    if(stepCount != dev->stepCount){
+        dev->stepCount = stepCount;
+        if(regUpdateFlag == 0) regUpdateFlag = 2;
+        if(dev->mode == MOTOR_OPEN_MODE_COUNT)
+            regUpdateFlag = 1;
+    }
+
+    if(speed != dev->speed){
+        dev->speed = speed;
+        dev->frequency = (dev->speed * (dev->fullSteps
+            * dev->microstepping) / 60.0);
+        dev->dutyCycle = 50.0;
+        if(regUpdateFlag == 0) regUpdateFlag = 2;
+
+        if(dev->mode == MOTOR_OPEN_MODE_NOCOUNT
+            || (dev->mode == MOTOR_OPEN_MODE_COUNT && dev->stepCount == 1))
+            regUpdateFlag = 1;
+    }
+    else if(frequency != dev->frequency
+        || dutyCycle != dev->dutyCycle){
+        dev->frequency = frequency;
+        dev->dutyCycle = dutyCycle;
+        if(dev->dutyCycle < 0) dev->dutyCycle = 0;
+        else if(dev->dutyCycle > 100) dev->dutyCycle = 100;
+        dev->speed = (dev->frequency * 60.0
+            / (dev->fullSteps * dev->microstepping));
+        if(regUpdateFlag == 0) regUpdateFlag = 2;
+
+        if(dev->mode == MOTOR_OPEN_MODE_NOCOUNT
+            || (dev->mode == MOTOR_OPEN_MODE_COUNT && dev->stepCount == 1))
+            regUpdateFlag = 1;
+    }
+
+    if(regUpdateFlag == 1 && dev->mode == MOTOR_OPEN_MODE_COUNT){
+        dev->pwmSetCount(dev->frequency, dev->dutyCycle, dev->stepCount);
+    }
+    else if(regUpdateFlag == 1 && dev->mode == MOTOR_OPEN_MODE_NOCOUNT){
+        dev->pwmSet(dev->frequency, dev->dutyCycle);
+    }
+    return regUpdateFlag;
+}
+
+#endif /* __MOTOR_STEP_O_ATY_C */
+
+
+/************************************ etc *************************************/
+/* init
+#define MS_1_TIM htim1
+#define MS_1_TIM_CHANNEL TIM_CHANNEL_2
+#define MS_1_TIM_IT_CC TIM_IT_CC2
+#define MS_1_COUNT_TIM htim2
+// MOTOR Open ------------------------------------------------------------------
+#include "MOTOR_STEP_O_ATY.h"
+uint8_t MSO_1_EnSet(uint8_t en){
+    HAL_GPIO_WritePin(MS_EN_GPIO_Port, MS_EN_Pin,
+        (en == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
+    return __ATY_OK;
+}
+uint8_t MSO_1_DirSet(uint8_t dir){
+    HAL_GPIO_WritePin(MS_DIRO_GPIO_Port, MS_DIRO_Pin,
+        (dir == __ATY_PN_P) ? GPIO_PIN_SET : GPIO_PIN_RESET);
+    return __ATY_OK;
+}
+void MSO_1_PWM_NoCount(float freq, float dutycycle){
+    uint32_t ticksPeriod = 1000000U / freq;
+    uint32_t ticksPulse = ticksPeriod * (100.0 - dutycycle) / 100.0;
+    HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
+    __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
+    __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
+    __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
+    HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
+}
+void MSO_1_PWM_Count(float freq, float dutycycle, uint16_t step){
+    uint32_t ticksPeriod = 1000000U / freq;
+    uint32_t ticksPulse = ticksPeriod * (100.0 - dutycycle) / 100.0;
+    HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
+    HAL_TIM_Base_Stop_IT(&MS_1_COUNT_TIM);
+    __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
+    // Set 1 to make sure the system can generate one pulse
+    __HAL_TIM_SET_COUNTER(&MS_1_COUNT_TIM, 1);
+    if(step != 0){
+        // init counter 1, then do not need -1
+        __HAL_TIM_SET_AUTORELOAD(&MS_1_COUNT_TIM, step);
+        __HAL_TIM_SET_AUTORELOAD(&MS_1_TIM, ticksPeriod - 1);
+        __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, ticksPulse - 1);
+        HAL_TIM_Base_Start_IT(&MS_1_COUNT_TIM);
+        HAL_TIM_PWM_Start(&MS_1_TIM, MS_1_TIM_CHANNEL);
+    }
+}
+struct MOTOR_STEP_O_ATY_Dev MOTOR_STEP_O_ATY_Dev_1 = {
+    .enSet = MSO_1_EnSet,
+    .dirSet = MSO_1_DirSet,
+
+    .pwmSet = MSO_1_PWM_NoCount,
+    .pwmSetCount = MSO_1_PWM_Count,
+
+    .mode = 0xFF,
+    .enable = 0xFF,
+    .direction = 0xFF,
+    .stepCount = 0xFFFF,
+    .frequency = -1.0,
+    .dutyCycle = -1.0,
+    .speed = -1.0,
+
+    .fullSteps = 200,
+    .microstepping = 8,
+
+    .lock = __ATY_UNLOCKED
+};
+void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim){
+    if(htim == &htim4){
+        UserTimerLoop_Cycle1ms(&HW_TIMER_ATY_Dev_4);
+    }
+    if((uint8_t)RGF_MOTOR_MODE == 0 && htim == &MS_1_COUNT_TIM){
+        HAL_TIM_PWM_Stop(&MS_1_TIM, MS_1_TIM_CHANNEL);
+        HAL_TIM_Base_Stop_IT(&MS_1_COUNT_TIM);
+        RGF_MOTOR_STEP_COUNT = 0;
+        MOTOR_STEP_O_ATY_Dev_1.stepCount = 0;
+    }
+}
+void MSO_1_ValueUpdateBack(struct MOTOR_STEP_O_ATY_Dev* dev){
+    RGF_MOTOR_MODE = dev->mode;
+    RGF_MOTOR_ENABLE = dev->enable;
+    RGF_MOTOR_DIRECTION = dev->direction;
+    // RGF_MOTOR_STEP_COUNT = dev->stepCount;
+    RGF_MOTOR_FREQUENCY = dev->frequency;
+    RGF_MOTOR_DUTY_CYCLE = dev->dutyCycle;
+    RGF_MOTOR_SPEED = dev->speed;
+}
+void MSO_1_Init(void){
+    RGF_MOTOR_MODE = MOTOR_OPEN_MODE_COUNT;
+    RGF_MOTOR_ENABLE = 1;
+    RGF_MOTOR_DIRECTION = __ATY_PN_P;
+    RGF_MOTOR_STEP_COUNT = 10000;
+    RGF_MOTOR_FREQUENCY = (1600.0 / 60.0);
+    RGF_MOTOR_DUTY_CYCLE = 50.0;
+    RGF_MOTOR_SPEED = 200.0;
+    // Prevent from getting into an interruption from the very beginning
+    __HAL_TIM_CLEAR_FLAG(&MS_1_COUNT_TIM, TIM_FLAG_UPDATE);
+}
+*/
+
+/* use
+MSO_1_Init();
+
+// 100ms cycle
+if(MSO_Cycle(&MOTOR_STEP_O_ATY_Dev_1,
+    (uint8_t)RGF_MOTOR_MODE,
+    (uint8_t)RGF_MOTOR_ENABLE,
+    (uint8_t)RGF_MOTOR_DIRECTION,
+    (uint16_t)RGF_MOTOR_STEP_COUNT,
+    RGF_MOTOR_FREQUENCY,
+    RGF_MOTOR_DUTY_CYCLE,
+    RGF_MOTOR_SPEED) != 0){
+    MSO_1_ValueUpdateBack(&MOTOR_STEP_O_ATY_Dev_1);
+}
+*/
+
+/******************************************************************************/
+
+/******************************** End Of File *********************************/

+ 67 - 0
MOTOR_STEP_O_ATY.h

@@ -0,0 +1,67 @@
+/**
+* @file MOTOR_STEP_O_ATY.h
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of open loop stepper motor control for C platform
+*
+* @version
+*       - 1_00_260109 > ATY
+*           -# Preliminary version
+********************************************************************************
+*/
+
+#ifndef __MOTOR_STEP_O_ATY_H
+#define __MOTOR_STEP_O_ATY_H
+
+#include "INCLUDE_ATY.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+struct MOTOR_STEP_O_ATY_Dev{
+    uint8_t (*enSet)(uint8_t en);
+    uint8_t (*dirSet)(uint8_t dir);
+
+    void (*pwmSet)(float frequency, float dutycycle);
+    void (*pwmSetCount)(float frequency, float dutycycle, uint16_t step);
+
+    uint8_t mode;
+    uint8_t enable;
+    uint8_t direction;
+    uint16_t stepCount;
+    float frequency;        // Hz
+    float dutyCycle;        // 0-100f
+    float speed;            // rpm
+
+    uint16_t fullSteps;     // steps per revolution, 360 / 1.8 degree = 200 steps
+    uint8_t microstepping;  // 1/8 = 8, 1/16, 1/32, 1/64, 1/128, 1/256
+
+    uint8_t lock;
+};
+
+#define MOTOR_OPEN_MODE_COUNT     0x00  // Count mode - run for specified steps, step set 1 to continuous
+#define MOTOR_OPEN_MODE_NOCOUNT   0x01  // Continuous mode - run continuously
+
+uint8_t MSO_Cycle(struct MOTOR_STEP_O_ATY_Dev* dev,
+    uint8_t mode, uint8_t enable, uint8_t direction,
+    uint16_t stepCount,
+    float frequency, float dutyCycle, float speed);
+
+#endif /* __MOTOR_STEP_O_ATY_H */
+
+/******************************** End Of File *********************************/

+ 706 - 0
MOTOR_STEP_SPEED_T_C_ATY.c

@@ -0,0 +1,706 @@
+/**
+* @file MOTOR_STEP_SPEED_T_C_ATY.c
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief Trapezoidal acceleration and deceleration control implementation for stepper motor
+*
+* @note  import angle to use COMPENSATE
+*
+* @version
+*       - 1_00_260119 > ATY
+*           -# Initial version
+********************************************************************************
+*/
+
+#ifndef __MOTOR_STEP_SPEED_T_C_ATY_C
+#define __MOTOR_STEP_SPEED_T_C_ATY_C
+
+#include "MOTOR_STEP_SPEED_T_C_ATY.h"
+#include <math.h>
+
+#define MOTOR_STEP_SPEED_T_C_ATY_TAG "\r\n[MOTOR_STEP_SPEED_T_C_ATY] "
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+
+uint8_t MSSTC_PulseToggle = 0;          // pulse toggle counter (for complete pulse)
+int32_t MSSTC_CelCount = 0;             // ac/deceleration step counter
+uint32_t MSSTC_FastStepDelay = 0;       // minimum delay at fullSpeed
+int32_t MSSTC_StepDelay = 0;            // current step delay (timer ticks)
+uint32_t MSSTC_NewStepDelay = 0;    // calculated step delay for next step from last step
+int32_t MSSTC_Rest = 0;                 // Remainder for precision
+int32_t MSSTC_LastDelay = 0;            // Last acceleration delay
+
+// for angle compensation ------------------------------------------------------
+float MSSTC_StartAngle = 0;
+uint32_t MSSTC_CurrentTurn = 0;
+float MSSTC_CurrentAngle = 0;
+uint32_t MSSTC_TargetTurn = 0;
+float MSSTC_TargetAngle = 0;
+float MSSTC_AnglePerStep = 0;
+float MSSTC_TargetAngleL = 0;
+float MSSTC_TargetAngleH = 0;
+float MSSTC_AngleDiff = 0;
+int32_t MSSTC_StepDiff = 0;
+uint8_t MSSTC_CelCountErrCount = 0;
+
+
+float K = 0.676;
+/**
+ * @brief Move motor with trapezoidal dev->fullSpeed profile
+ * @param dev Pointer to motor device structure
+ * @param steps Number of steps to move (positive=CW, negative=CCW)
+ * @return 0=success, 1=busy, 2=invalid parameters
+ */
+uint8_t MSSTC_Move(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev,
+    uint32_t steps, float startAngle){
+
+    if(MSSTC_IsRunning(dev) == 1){
+        return 1;
+    }
+
+    if(steps == 0 || dev->fullSpeed == 0){
+        dev->stop();
+        return 0;
+    }
+    if(dev->unitDivision == 0)
+        dev->unitDivision = 1;
+
+    if(dev->powerOnlyRun == 1){
+        dev->enable = 1;
+    }
+    dev->enSet(dev->enable);
+    dev->dirSet(dev->direction);
+
+    /* Handle single step */
+    if(steps == 1){
+        dev->runState = MSSTC_STATE_DECEL;
+        MSSTC_CelCount = -1;
+        MSSTC_StepDelay = 1000;
+        dev->start();
+        return 0;
+    }
+
+    /* Calculate motor parameters */
+    // alpha = 2 * PI / stepsPerRevolution [rad/step]
+    float alpha = 2.0 * 3.14159265359 / (dev->fullSteps * dev->microstepping);
+    /* Calculate minimum delay (maximum dev->fullSpeed) */
+    // wmax = fullSpeed [rad/sec]
+    // tmin = alpha / wmax [sec/step] (t = distance / velocity)
+    // fastStepDelay = cmin = tmin * timerFreq = alpha * timerFreq / fullSpeed
+    MSSTC_FastStepDelay = (uint32_t)(alpha * dev->timerFreq * dev->unitDivision / dev->fullSpeed);
+    if(MSSTC_FastStepDelay <= 1){
+        MSSTC_FastStepDelay = 2;
+    }
+
+    /* Calculate initial step delay (first step) */
+    // t0 = sqrt(2 * alpha / (acceleration / unit)) = sqrt(2 * alpha * unit / acceleration)
+    // stepDelay = K * timerFreq * t0
+    if(dev->acceleration != 0){
+        MSSTC_StepDelay = (uint32_t)(K * dev->timerFreq
+            * sqrt(2.0 * alpha * dev->unitDivision / dev->acceleration));
+    }
+    if(dev->acceleration == 0){
+        // no acceleration and no deceleration
+        MSSTC_StepDelay = MSSTC_FastStepDelay;
+    }
+
+    /* Calculate steps to reach fullSpeed */
+    // accelSteps = (fullSpeed / unit)^2 / (2 * alpha * (acceleration / unit))
+    // accelSteps = fullSpeed^2 / (2 * alpha * acceleration * unit)
+    dev->accelSteps = 1;
+    if(dev->acceleration != 0){
+        dev->accelSteps = (uint32_t)((double)dev->fullSpeed
+            / (2.0 * alpha * dev->acceleration * dev->unitDivision)
+            * dev->fullSpeed);
+    }
+    if(dev->accelSteps == 0 || dev->acceleration == 0){
+        dev->accelSteps = 1;
+    }
+
+    /* Calculate steps before deceleration */
+    dev->accelLimit = 1;
+    if(dev->acceleration != 0 && dev->deceleration != 0){
+        dev->accelLimit = (uint32_t)(steps * dev->deceleration
+            / (dev->acceleration + dev->deceleration));
+    }
+    else if(dev->deceleration == 0){
+        dev->accelLimit = steps - 1;
+    }
+    if(dev->accelLimit == 0 || dev->acceleration == 0){
+        dev->accelLimit = 1;
+    }
+
+    /* Calculate steps deceleration */
+    dev->decelSteps = 1;
+    if(dev->acceleration != 0 && dev->deceleration != 0){
+        if(dev->accelLimit <= dev->accelSteps){
+            // not to fullSpeed
+            dev->decelSteps = steps - dev->accelLimit;
+            dev->accelSteps = dev->accelLimit;
+        }
+        else{
+            // accelerate to fullSpeed
+            dev->decelSteps = (uint32_t)(dev->accelSteps
+                * dev->acceleration / dev->deceleration);
+        }
+    }
+    else if(dev->acceleration == 0 && dev->deceleration != 0){
+        dev->decelSteps = (uint32_t)((double)dev->fullSpeed
+            / (2.0 * alpha * dev->deceleration * dev->unitDivision)
+            * dev->fullSpeed);
+        if(dev->decelSteps >= steps - 1){
+            dev->decelSteps = steps - 1;
+        }
+    }
+    if(dev->decelSteps == 0 || dev->deceleration == 0){
+        dev->decelSteps = 1;
+    }
+    /* Calculate deceleration start position */
+    dev->decelStart = steps - dev->decelSteps;
+    if(dev->mode == MSSTC_MODE_SPEED_OPEN){
+        dev->decelSteps = (uint32_t)((double)dev->fullSpeed
+            / (2.0 * alpha * dev->deceleration * dev->unitDivision)
+            * dev->fullSpeed);
+    }
+
+    /* Set initial state */
+    if(MSSTC_StepDelay <= MSSTC_FastStepDelay){
+        // fullSpeed is very low, no acceleration
+        MSSTC_StepDelay = MSSTC_FastStepDelay;
+        dev->runState = MSSTC_STATE_FULL;
+    }
+    else{
+        dev->runState = MSSTC_STATE_ACCEL;
+    }
+
+    /* Reset counters */
+    dev->stepCountCurrent = 0;
+    MSSTC_PulseToggle = 0;
+    MSSTC_CelCount = 0;
+    MSSTC_NewStepDelay = 0;
+    MSSTC_Rest = 0;
+    MSSTC_LastDelay = MSSTC_StepDelay;
+    MSSTC_CelCountErrCount = 0;
+
+    MSSTC_StartAngle = startAngle;
+    MSSTC_CurrentTurn = 0;
+    MSSTC_CurrentAngle = startAngle;
+    MSSTC_TargetTurn = steps / (dev->fullSteps * dev->microstepping);
+    MSSTC_TargetAngle = ((steps % (dev->fullSteps * dev->microstepping)) * 360.0)
+        / (dev->fullSteps * dev->microstepping) + startAngle;
+    while(MSSTC_TargetAngle >= 360.0){
+        MSSTC_TargetAngle -= 360.0;
+        MSSTC_TargetTurn++;
+    }
+    MSSTC_AnglePerStep = 360.0 / (dev->fullSteps * dev->microstepping);
+    MSSTC_TargetAngleL = MSSTC_TargetAngle - MSSTC_AnglePerStep;
+    MSSTC_TargetAngleH = MSSTC_TargetAngle + MSSTC_AnglePerStep;
+    MSSTC_AngleDiff = 0;
+    MSSTC_StepDiff = 0;
+
+    /* Start PWM and timer */
+    dev->setTimerCompare(MSSTC_StepDelay);
+    dev->start();
+
+    return 0;
+}
+
+/**
+ * @brief Timer interrupt handler - dev->fullSpeed decision algorithm
+ * @param dev Pointer to motor device structure
+ * @note Call this function in timer compare interrupt
+ */
+void MSSTC_IRQHandler(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev){
+    /* Update timer compare value */
+    dev->setTimerCompare(MSSTC_StepDelay);
+
+    /* Toggle counter for complete pulse generation */
+    MSSTC_PulseToggle++;
+    if(MSSTC_PulseToggle >= 2){
+        MSSTC_PulseToggle = 0;
+
+        /* State machine for dev->fullSpeed control */
+        switch(dev->runState){
+            case MSSTC_STATE_STOP:
+            {
+                dev->stop();
+                if(dev->mode == MSSTC_MODE_DISTANCE_CLOSE){
+                    dev->runState = MSSTC_STATE_COMPENSATE;
+                }
+                else{
+                    dev->runState = MSSTC_STATE_STANDBY;
+                    if(dev->powerOnlyRun == 1){
+                        dev->enable = 0;
+                        dev->enSet(dev->enable);
+                    }
+                }
+                break;
+            }
+            case MSSTC_STATE_ACCEL:
+            {
+                dev->stepCountCurrent++;
+                MSSTC_CelCount++;
+
+                /* Calculate new step delay */
+                MSSTC_NewStepDelay = MSSTC_StepDelay -
+                    ((2 * MSSTC_StepDelay + MSSTC_Rest) /
+                        (4 * MSSTC_CelCount + 1));
+                MSSTC_Rest = ((2 * MSSTC_StepDelay + MSSTC_Rest) %
+                    (4 * MSSTC_CelCount + 1));
+
+                /* Check if should start deceleration */
+                if(dev->mode != MSSTC_MODE_SPEED_OPEN
+                    && dev->stepCountCurrent >= dev->decelStart){
+                    MSSTC_PulseToggle = 1;
+                    MSSTC_CelCount = -1 * (int32_t)dev->decelSteps;
+                    dev->runState = MSSTC_STATE_DECEL;
+                }
+                /* Check if reached maximum dev->fullSpeed */
+                else if(MSSTC_NewStepDelay <= MSSTC_FastStepDelay){
+                    MSSTC_LastDelay = MSSTC_NewStepDelay;
+                    MSSTC_CelCount = -1 * (int32_t)dev->decelSteps;
+                    dev->runState = MSSTC_STATE_FULL;
+                }
+                break;
+            }
+            case MSSTC_STATE_FULL:
+            {
+                if(dev->mode == MSSTC_MODE_SPEED_OPEN){
+                    dev->stepCountCurrent = 0;
+                }
+                else{
+                    dev->stepCountCurrent++;
+                }
+                MSSTC_NewStepDelay = MSSTC_FastStepDelay;
+                // MSSTC_LastDelay = MSSTC_NewStepDelay;
+
+                /* Check if should start deceleration */
+                if(dev->stepCountCurrent >= dev->decelStart){
+                    MSSTC_PulseToggle = 1;
+                    MSSTC_Rest = 0;
+                    MSSTC_CelCount = -1 * (int32_t)dev->decelSteps;
+                    MSSTC_NewStepDelay = MSSTC_LastDelay;
+                    dev->runState = MSSTC_STATE_DECEL;
+                }
+                break;
+            }
+            case MSSTC_STATE_DECEL:
+            {
+                dev->stepCountCurrent++;
+                MSSTC_CelCount++;
+
+                /* Check if this is the last step */
+                if(MSSTC_CelCount >= 0){
+                    dev->runState = MSSTC_STATE_STOP;
+                    break;
+                }
+
+                if(MSSTC_StepDiff == 0){
+                    MSSTC_NewStepDelay = MSSTC_StepDelay -
+                        ((2 * MSSTC_StepDelay + MSSTC_Rest) /
+                            (4 * MSSTC_CelCount + 1));
+                    MSSTC_Rest = ((2 * MSSTC_StepDelay + MSSTC_Rest) %
+                        (4 * MSSTC_CelCount + 1));
+                    MSSTC_LastDelay = MSSTC_NewStepDelay;
+                }
+                break;
+            }
+            default:
+            {
+                if(dev->powerOnlyRun == 1){
+                    dev->enable = 0;
+                    dev->enSet(dev->enable);
+                }
+                break;
+            }
+        }
+        if(MSSTC_NewStepDelay <= 1){
+            MSSTC_NewStepDelay = 2;
+        }
+        MSSTC_StepDelay = MSSTC_NewStepDelay;
+    }
+}
+
+/**
+ * @brief Stop motor immediately but not clear params data
+ * @param dev Pointer to motor device structure
+ */
+void MSSTC_Scram(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev){
+    dev->runState = MSSTC_STATE_STANDBY;
+    if(dev->powerOnlyRun == 1){
+        dev->enable = 0;
+        dev->enSet(dev->enable);
+    }
+    dev->stop();
+}
+
+void MSSTC_Stop(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev){
+    MSSTC_CelCount = -1 * (int32_t)dev->decelSteps;
+    dev->runState = MSSTC_STATE_DECEL;
+    dev->start();
+    MSSTC_IRQHandler(dev);
+}
+
+void MSSTC_UpdateFullSpeed(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev){
+    float alpha = 2.0 * 3.14159265359 / (dev->fullSteps * dev->microstepping);
+    MSSTC_FastStepDelay = (uint32_t)(alpha * dev->timerFreq * dev->unitDivision / dev->fullSpeed);
+    dev->setTimerCompare(MSSTC_FastStepDelay);
+}
+
+/**
+ * @brief Check if motor is running
+ * @param dev Pointer to motor device structure
+ * @return 1=running, 0=stopped
+ */
+uint8_t MSSTC_IsRunning(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev){
+    return (dev->runState == MSSTC_STATE_STANDBY) ? 0 : 1;
+}
+
+/**
+ * @brief MSSTC_Compensate
+ *
+ * @param dev
+ */
+void MSSTC_Compensate(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev){
+    if(dev->runState != MSSTC_STATE_COMPENSATE){
+        return;
+    }
+
+    uint32_t publicTurns = ((MSSTC_TargetTurn < MSSTC_CurrentTurn) ? MSSTC_TargetTurn : MSSTC_CurrentTurn);
+    float targetAngleTotal = 360.0 * (MSSTC_TargetTurn - publicTurns) + MSSTC_TargetAngle;
+    float currentAngleTotal = 360.0 * (MSSTC_CurrentTurn - publicTurns) + MSSTC_CurrentAngle;
+    MSSTC_StepDiff = (int32_t)((targetAngleTotal - currentAngleTotal) / MSSTC_AnglePerStep);
+    if(MSSTC_StepDiff > 1 || MSSTC_StepDiff < -1){
+        if(MSSTC_StepDiff < 0){
+            if(dev->turnBackAllowed == 1){
+                MSSTC_CelCount = MSSTC_StepDiff;
+                dev->dirSet(dev->direction ^ 0x01);
+            }
+            else{
+                dev->runState = MSSTC_STATE_STANDBY;
+                if(dev->powerOnlyRun == 1){
+                    dev->enable = 0;
+                    dev->enSet(dev->enable);
+                }
+            }
+        }
+        else{
+            dev->dirSet(dev->direction);
+            MSSTC_CelCount = -1 * MSSTC_StepDiff;
+        }
+        dev->runState = MSSTC_STATE_DECEL;
+
+        MSSTC_CelCountErrCount++;
+        if(MSSTC_CelCountErrCount > 5){
+            dev->runState = MSSTC_STATE_STANDBY;
+            if(dev->powerOnlyRun == 1){
+                dev->enable = 0;
+                dev->enSet(dev->enable);
+            }
+        }
+        else{
+            dev->start();
+        }
+    }
+    else{
+        dev->runState = MSSTC_STATE_STANDBY;
+        if(dev->powerOnlyRun == 1){
+            dev->enable = 0;
+            dev->enSet(dev->enable);
+        }
+    }
+}
+
+/**
+ * @brief Update current angle
+ * @param dev Pointer to motor device structure
+ * @param turn Turn count
+ * @param angle Current angle
+ */
+void MSSTC_UpdateAngle(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev,
+    uint32_t turn, float angle){
+    MSSTC_CurrentTurn = turn;
+    MSSTC_CurrentAngle = angle;
+    MSSTC_Compensate(dev);
+}
+
+#endif /* __MOTOR_STEP_SPEED_T_C_ATY_C */
+
+/************************************ etc *************************************/
+/* init
+#define MS_1_TIM htim1
+#define MS_1_TIM_CHANNEL TIM_CHANNEL_1
+#define MS_1_TIM_IT_CC TIM_IT_CC1
+// MSSTC -----------------------------------------------------------------------
+#include "MOTOR_STEP_SPEED_T_C_ATY.h"
+uint8_t MSSTC_1_EnSet(uint8_t en){
+    HAL_GPIO_WritePin(MS_EN_GPIO_Port, MS_EN_Pin,
+        (en == 0) ? GPIO_PIN_SET : GPIO_PIN_RESET);
+    return 0;
+}
+uint8_t MSSTC_1_DirSet(uint8_t dir){
+    HAL_GPIO_WritePin(MS_DIR_GPIO_Port, MS_DIR_Pin,
+        (dir == __ATY_PN_P) ? GPIO_PIN_SET : GPIO_PIN_RESET);
+    return 0;
+}
+void MSSTC_1_SetTimerCompare(uint32_t value){
+    __HAL_TIM_SET_COMPARE(&MS_1_TIM, MS_1_TIM_CHANNEL, value);
+    __HAL_TIM_SET_COUNTER(&MS_1_TIM, 0);
+}
+void MSSTC_1_Start(void){
+    HAL_TIM_OC_Start_IT(&MS_1_TIM, MS_1_TIM_CHANNEL);
+}
+void MSSTC_1_Stop(void){
+    HAL_TIM_OC_Stop_IT(&MS_1_TIM, MS_1_TIM_CHANNEL);
+}
+struct MOTOR_STEP_SPEED_T_C_ATY_Dev MSSTC_Dev_1 = {
+    .enSet = MSSTC_1_EnSet,
+    .dirSet = MSSTC_1_DirSet,
+    .start = MSSTC_1_Start,
+    .stop = MSSTC_1_Stop,
+    .setTimerCompare = MSSTC_1_SetTimerCompare,
+
+    .timerFreq = 1000000,
+    .fullSteps = 200,
+    .microstepping = 8,
+
+    .enable = 0,
+    .direction = __ATY_PN_P,
+    .fullSpeed = 20,
+    .unitDivision = 1,
+    .acceleration = 100,
+    .deceleration = 200,
+
+    .mode = 0,
+    .angleLock = 0,
+    .powerOnlyRun = 1,
+    .runState = MSSTC_STATE_STANDBY,
+
+    .lock = __ATY_UNLOCKED
+};
+void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef* htim){
+    if(htim->Instance == TIM1 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1){
+        if(__HAL_TIM_GET_IT_SOURCE(&MS_1_TIM, MS_1_TIM_IT_CC) != RESET){
+            __HAL_TIM_CLEAR_IT(&MS_1_TIM, MS_1_TIM_IT_CC);
+            MSSTC_IRQHandler(&MSSTC_Dev_1);
+        }
+    }
+}
+void MSSTC_1_Init(void){
+    HAL_GPIO_WritePin(MS_SP_GPIO_Port, MS_SP_Pin, GPIO_PIN_SET);
+    HAL_GPIO_WritePin(MS_MS1_GPIO_Port, MS_MS1_Pin, GPIO_PIN_RESET);
+    HAL_GPIO_WritePin(MS_MS2_GPIO_Port, MS_MS2_Pin, GPIO_PIN_RESET);
+    HAL_GPIO_WritePin(MS_EN_GPIO_Port, MS_EN_Pin, GPIO_PIN_SET);
+
+    RGF_MOTOR_FREQUENCY = (1600.0 / 60.0);
+    RGF_MOTOR_DUTY_CYCLE = 50.0;
+
+    RGF_MOTOR_FULL_STEPS = MSSTC_Dev_1.fullSteps;
+    RGF_MOTOR_MICROSTEPPING = MSSTC_Dev_1.microstepping;
+
+    RGF_MOTOR_ENABLE = MSSTC_Dev_1.enable;
+    RGF_MOTOR_DIRECTION = MSSTC_Dev_1.direction;
+    RGF_MOTOR_SPEED = MSSTC_Dev_1.fullSpeed;
+    RGF_MOTOR_UNIT_DIVISION = MSSTC_Dev_1.unitDivision;
+    RGF_MOTOR_ACCELERATION = MSSTC_Dev_1.acceleration;
+    RGF_MOTOR_DECELERATION = MSSTC_Dev_1.deceleration;
+
+    RGF_MOTOR_MODE = MSSTC_Dev_1.mode;
+    RGF_MOTOR_ANGLE_LOCK_TARGET = MSSTC_Dev_1.angleLock;
+    RGF_MOTOR_AUTO_POWER = MSSTC_Dev_1.powerOnlyRun;
+    RGF_MOTOR_RUN_STATE = MSSTC_Dev_1.runState;
+    RGF_MOTOR_RUN = 1;
+    RGF_MOTOR_STEP_COUNT = 1600;
+}
+void MSSTC_1_Cycle(void){
+    if(MSSTC_IsRunning(&MSSTC_Dev_1) != 1){
+        MSSTC_Dev_1.fullSteps = (uint16_t)RGF_MOTOR_FULL_STEPS;
+        if(MSSTC_Dev_1.microstepping != (uint16_t)RGF_MOTOR_MICROSTEPPING){
+            MSSTC_Dev_1.microstepping = (uint16_t)RGF_MOTOR_MICROSTEPPING;
+            MSSTC_Dev_1.enSet(0);
+            if(MSSTC_Dev_1.microstepping == 8){
+                HAL_GPIO_WritePin(MS_MS1_GPIO_Port, MS_MS1_Pin, GPIO_PIN_RESET);
+                HAL_GPIO_WritePin(MS_MS2_GPIO_Port, MS_MS2_Pin, GPIO_PIN_RESET);
+            }
+            else if(MSSTC_Dev_1.microstepping == 16){
+                HAL_GPIO_WritePin(MS_MS1_GPIO_Port, MS_MS1_Pin, GPIO_PIN_SET);
+                HAL_GPIO_WritePin(MS_MS2_GPIO_Port, MS_MS2_Pin, GPIO_PIN_SET);
+            }
+            else if(MSSTC_Dev_1.microstepping == 32){
+                HAL_GPIO_WritePin(MS_MS1_GPIO_Port, MS_MS1_Pin, GPIO_PIN_RESET);
+                HAL_GPIO_WritePin(MS_MS2_GPIO_Port, MS_MS2_Pin, GPIO_PIN_SET);
+            }
+            else if(MSSTC_Dev_1.microstepping == 64){
+                HAL_GPIO_WritePin(MS_MS1_GPIO_Port, MS_MS1_Pin, GPIO_PIN_SET);
+                HAL_GPIO_WritePin(MS_MS2_GPIO_Port, MS_MS2_Pin, GPIO_PIN_RESET);
+            }
+            if(MSSTC_Dev_1.powerOnlyRun == 0){
+                MSSTC_Dev_1.enSet(MSSTC_Dev_1.enable);
+            }
+        }
+
+        if(MSSTC_Dev_1.enable != (uint8_t)RGF_MOTOR_ENABLE){
+            MSSTC_Dev_1.enable = (uint8_t)RGF_MOTOR_ENABLE;
+            if(MSSTC_Dev_1.powerOnlyRun == 0){
+                MSSTC_Dev_1.enSet(MSSTC_Dev_1.enable);
+            }
+        }
+        if(MSSTC_Dev_1.direction != (uint8_t)RGF_MOTOR_DIRECTION){
+            MSSTC_Dev_1.direction = (uint8_t)RGF_MOTOR_DIRECTION;
+            MSSTC_Dev_1.dirSet(MSSTC_Dev_1.direction);
+        }
+        MSSTC_Dev_1.fullSpeed = (uint16_t)RGF_MOTOR_SPEED;
+        MSSTC_Dev_1.unitDivision = (uint8_t)RGF_MOTOR_UNIT_DIVISION;
+        MSSTC_Dev_1.acceleration = (uint16_t)RGF_MOTOR_ACCELERATION;
+        MSSTC_Dev_1.deceleration = (uint16_t)RGF_MOTOR_DECELERATION;
+
+        MSSTC_Dev_1.mode = (uint8_t)RGF_MOTOR_MODE;
+        if(MSSTC_Dev_1.angleLock != (uint8_t)RGF_MOTOR_ANGLE_LOCK_TARGET){
+            MSSTC_Dev_1.angleLock = (uint8_t)RGF_MOTOR_ANGLE_LOCK_TARGET;
+            if(MSSTC_Dev_1.mode == 1){
+
+            }
+        }
+        if(MSSTC_Dev_1.powerOnlyRun != (uint8_t)RGF_MOTOR_AUTO_POWER){
+            MSSTC_Dev_1.powerOnlyRun = (uint8_t)RGF_MOTOR_AUTO_POWER;
+            if(MSSTC_Dev_1.powerOnlyRun == 0){
+                MSSTC_Dev_1.enSet(MSSTC_Dev_1.enable);
+            }
+            else{
+                MSSTC_Dev_1.enSet(0);
+            }
+        }
+    }
+
+
+    MT6816_1_UpdateCycle();
+    MSSTC_UpdateAngle(&MSSTC_Dev_1,
+        MT6816_ATY_Dev_1.turnCount,
+        MT6816_ATY_Dev_1.angleTotal + MT6816_ATY_Dev_1.angleStart);
+    if((uint8_t)RGF_MOTOR_RUN == 1){
+        MT6816_TurnCountOffsetStart(&MT6816_ATY_Dev_1, MSSTC_Dev_1.direction);
+        MSSTC_Move(&MSSTC_Dev_1, RGF_MOTOR_STEP_COUNT, MT6816_ATY_Dev_1.angleStart);
+    }
+    else if((uint8_t)RGF_MOTOR_RUN == 2){
+        MSSTC_Scram(&MSSTC_Dev_1);
+    }
+    RGF_MOTOR_RUN = 0;
+
+    if(MSSTC_Dev_1.runState == MSSTC_STATE_STANDBY
+        && MT6816_ATY_Dev_1.start == 1){
+        MT6816_TurnCountOffsetStop(&MT6816_ATY_Dev_1);
+    }
+
+
+    RGF_MOTOR_ENABLE = MSSTC_Dev_1.enable;
+    RGF_MOTOR_DIRECTION = MSSTC_Dev_1.direction;
+
+    RGF_MOTOR_RUN_STATE = MSSTC_Dev_1.runState;
+
+    RGF_MOTOR_CURRENT_STEPS = MSSTC_Dev_1.stepCountCurrent;
+    RGF_MOTOR_ACCEL_STEPS = MSSTC_Dev_1.accelSteps;
+    RGF_MOTOR_ACCEL_LIMIT = MSSTC_Dev_1.accelLimit;
+    RGF_MOTOR_DECEL_STEPS = MSSTC_Dev_1.decelSteps;
+    RGF_MOTOR_DECEL_START = MSSTC_Dev_1.decelStart;
+}
+*/
+
+/* use
+MSSTC_1_Init();
+MSSTC_1_Cycle();
+
+
+// Reg -------------------------------------------------------------------------
+// motor fan
+#define RGF_MOTOR_FAN_EN rgf[20]
+#define RGF_MOTOR_FAN_BASE rgf[21]
+#define RGF_MOTOR_FAN_LOW_T rgf[22]
+#define RGF_MOTOR_FAN_HIGH_T rgf[23]
+#define RGF_MOTOR_FAN_T_SPACE rgf[24]
+// motor angle base
+#define RGF_MOTOR_ANGLE_SET_ZERO rgf[25]
+#define RGF_MOTOR_ANGLE_ZERO rgf[26]
+#define RGF_MOTOR_ANGLE rgf[27]
+#define RGF_MOTOR_ANGLE_ERR rgf[28]
+// motor angle correction
+#define RGF_MOTOR_ANGLE_ANGLE_START rgf[30]
+#define RGF_MOTOR_ANGLE_TURN_COUNT rgf[31]
+#define RGF_MOTOR_ANGLE_ANGLE_TOTAL rgf[32]
+#define RGF_MOTOR_ANGLE_START rgf[33]
+
+// useless motor params
+#define RGF_MOTOR_FREQUENCY rgf[35]
+#define RGF_MOTOR_DUTY_CYCLE rgf[36]
+
+#define RGF_MOTOR_FULL_STEPS rgf[38]
+#define RGF_MOTOR_MICROSTEPPING rgf[39]
+
+// motor base
+#define RGF_MOTOR_ENABLE rgf[40]
+#define RGF_MOTOR_DIRECTION rgf[41]
+#define RGF_MOTOR_SPEED rgf[42]
+#define RGF_MOTOR_UNIT_DIVISION rgf[43]
+#define RGF_MOTOR_ACCELERATION rgf[44]
+#define RGF_MOTOR_DECELERATION rgf[45]
+
+#define RGF_MOTOR_MODE rgf[46]
+#define RGF_MOTOR_ANGLE_LOCK_TARGET rgf[47]
+#define RGF_MOTOR_AUTO_POWER rgf[48]
+#define RGF_MOTOR_RUN_STATE rgf[49]
+#define RGF_MOTOR_RUN rgf[50]
+#define RGF_MOTOR_STEP_COUNT rgf[51]
+
+#define RGF_MOTOR_CURRENT_STEPS rgf[52]
+#define RGF_MOTOR_ACCEL_STEPS rgf[53]
+#define RGF_MOTOR_ACCEL_LIMIT rgf[54]
+#define RGF_MOTOR_DECEL_STEPS rgf[55]
+#define RGF_MOTOR_DECEL_START rgf[56]
+
+// FAN -------------------------------------------------------------------------
+uint8_t fanLastLevel = 0;
+void FAN_ControlCycle(void){
+    if((uint8_t)RGF_MOTOR_FAN_EN == 1 && RGF_BOARD_TEMP > RGF_MOTOR_FAN_LOW_T){
+        if((uint8_t)((RGF_BOARD_TEMP - RGF_MOTOR_FAN_LOW_T) / RGF_MOTOR_FAN_T_SPACE) + 1 != fanLastLevel){
+            fanLastLevel = (uint8_t)((RGF_BOARD_TEMP - RGF_MOTOR_FAN_LOW_T) / RGF_MOTOR_FAN_T_SPACE) + 1;
+            HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
+            __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,
+                RGF_MOTOR_FAN_BASE + ((1000 - RGF_MOTOR_FAN_BASE) * fanLastLevel
+                    / ((RGF_MOTOR_FAN_HIGH_T - RGF_MOTOR_FAN_LOW_T) / RGF_MOTOR_FAN_T_SPACE)));
+            HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
+        }
+    }
+    else{
+        __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1, 0);
+        HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
+        fanLastLevel = 0;
+    }
+}
+void FAN_Init(void){
+    RGF_MOTOR_FAN_EN = 1;
+    RGF_MOTOR_FAN_BASE = 200;
+    RGF_MOTOR_FAN_LOW_T = 50;
+    RGF_MOTOR_FAN_HIGH_T = 80;
+    RGF_MOTOR_FAN_T_SPACE = 5;
+}
+*/
+
+/******************************************************************************/
+
+/******************************** End Of File *********************************/

+ 104 - 0
MOTOR_STEP_SPEED_T_C_ATY.h

@@ -0,0 +1,104 @@
+/**
+* @file MOTOR_STEP_SPEED_T_C_ATY.h
+*
+* @param Project DEVICE_GENERAL_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief Trapezoidal acceleration and deceleration control implementation for stepper motor
+*
+* @note  import angle to use COMPENSATE
+*
+* @version
+*       - 1_00_260119 > ATY
+*           -# Initial version based on trapezoidal acceleration algorithm
+********************************************************************************
+*/
+
+#ifndef __MOTOR_STEP_SPEED_T_C_ATY_H
+#define __MOTOR_STEP_SPEED_T_C_ATY_H
+
+#include "INCLUDE_ATY.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+/* Motion states */
+#define MSSTC_STATE_STANDBY     0   // Standby
+#define MSSTC_STATE_STOP        1   // Stopped
+#define MSSTC_STATE_ACCEL       2   // Accelerating
+#define MSSTC_STATE_DECEL       3   // Decelerating
+#define MSSTC_STATE_FULL        4   // Full speed
+#define MSSTC_STATE_COMPENSATE  5   // COMPENSATE
+
+#define MSSTC_MODE_DISTANCE_CLOSE   0
+#define MSSTC_MODE_DISTANCE_OPEN    1
+#define MSSTC_MODE_SPEED_OPEN       2
+
+/* Motor control device structure */
+struct MOTOR_STEP_SPEED_T_C_ATY_Dev{
+    /* Hardware control functions */
+    uint8_t (*enSet)(uint8_t en);
+    uint8_t (*dirSet)(uint8_t dir);
+    void (*start)(void);
+    void (*stop)(void);
+    void (*setTimerCompare)(uint32_t value);
+
+    // MCU params
+    uint32_t timerFreq;         // Timer frequency in Hz
+    // motor params
+    uint32_t fullSteps;         // steps per revolution, 360 / 1.8 degree = 200 steps
+    uint32_t microstepping;     // 1/8 = 8, 1/16, 1/32, 1/64, 1/128, 1/256
+
+    uint8_t enable;
+    uint8_t direction;
+
+    uint32_t fullSpeed;         // rad/sec / unitDiv
+    uint32_t unitDivision;      // 10 -> 0.1 rad, set 1 to ignore
+    uint32_t acceleration;      // rad/sec^2 / unitDiv, set 0 to disable acceleration
+    uint32_t deceleration;      // rad/sec^2 / unitDiv, set 0 to disable deceleration
+
+    uint8_t mode;
+    float angleLock;
+    uint8_t powerOnlyRun;
+    uint8_t turnBackAllowed;
+    uint8_t runState;
+
+    uint32_t stepCountCurrent;  // current total step counter
+    uint32_t accelSteps;        // accelerate to fullSpeed steps
+    uint32_t accelLimit;        // max acceleration steps before deceleration
+    uint32_t decelSteps;        // decelerate to stop steps
+    uint32_t decelStart;        // Step position to start deceleration
+
+    uint8_t lock;
+};
+
+
+uint8_t MSSTC_Move(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev,
+    uint32_t steps, float startAngle);
+
+void MSSTC_IRQHandler(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev);
+
+void MSSTC_Scram(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev);
+void MSSTC_Stop(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev);
+uint8_t MSSTC_IsRunning(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev);
+void MSSTC_UpdateFullSpeed(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev);
+
+void MSSTC_UpdateAngle(struct MOTOR_STEP_SPEED_T_C_ATY_Dev* dev,
+    uint32_t turn, float angle);
+
+#endif /* __MOTOR_STEP_SPEED_T_C_ATY_H */
+
+/******************************** End Of File *********************************/

+ 377 - 0
MT6816_ATY.c

@@ -0,0 +1,377 @@
+/**
+* @file MT6816_ATY.c
+*
+* @param Project DEVICE_DRIVER_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of MT6816 magnetic encoder for C platform
+*
+* @note SPI_POLARITY_HIGH + SPI_PHASE_2EDGE = CPOL=1, CPHA=1 = SPI Mode 3
+*
+* @version
+*       - 1_01_251222 > ATY
+*           -# Preliminary version, first Release
+********************************************************************************
+*/
+
+#ifndef __MT6816_ATY_C
+#define __MT6816_ATY_C
+
+#include "MT6816_ATY.h"
+#define MT6816_ATY_TAG "\r\n[MT6816_ATY] "
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+uint8_t wrData[3] = {0};
+
+/**
+ * @brief   Parity check
+ *
+ * @param   dev Device structure pointer
+ * @param   data Data
+ * @return  uint8_t Execution result
+ */
+uint8_t MT6816_ParityCheck(struct MT6816_ATY_Dev* dev, uint16_t data){
+    uint8_t parityCheck = 0;
+    if(data == 0) data = dev->angleValue;
+    dev->error &= ~(uint8_t)MT6816_PARITY_CHECK_MASK;
+
+    for(int i = 0; i < 15; i++){
+        data >>= 1;
+        if(data & 0x01){
+            parityCheck ^= 1;
+        }
+    }
+    // Check if parity bit matches (parity bit is bit 7 of angle_lsb)
+    if((dev->angleValue & 0x01) != parityCheck){
+        dev->error |= MT6816_PARITY_CHECK_MASK;
+        printf_ATY_D("%sParity check failed", MT6816_ATY_TAG);
+    }
+    return dev->error;
+}
+
+/**
+ * @brief   Error check
+ *
+ * @param   dev Device structure pointer
+ * @param   data Data
+ * @return  uint8_t Execution result
+ */
+uint8_t MT6816_ErrorCheck(struct MT6816_ATY_Dev* dev, uint8_t* data){
+    dev->error = 0;
+    MT6816_ParityCheck(dev, (data[0] << 8) | data[1]);
+    if(data[1] & MT6816_NO_MAG_WARNING_MASK){
+        dev->error |= MT6816_NO_MAG_WARNING_MASK;
+        printf_ATY_D("%sNo magnetic field warning", MT6816_ATY_TAG);
+    }
+    if(data[2] & MT6816_OVER_SPEED_MASK){
+        dev->error |= MT6816_OVER_SPEED_MASK;
+        printf_ATY_D("%sOver speed warning", MT6816_ATY_TAG);
+    }
+    return dev->error;
+}
+
+/**
+ * @brief   Read angle value from MT6816 for only angle value
+ *
+ * @param   dev Device structure pointer
+ * @return  uint8_t Execution result
+ */
+uint8_t MT6816_ReadAngleBase(struct MT6816_ATY_Dev* dev){
+    __ATY_LOCK(dev);
+
+    // Reading MSB (ANGLE_MSB register)
+    wrData[0] = MT6816_REG_ANGLE_13_6 | 0x80;
+
+    dev->nssSet(__ATY_HL_L);
+    dev->spiProcess(wrData, 1, __ATY_RW_W);
+    dev->spiProcess(wrData, 1, __ATY_RW_R);
+    dev->nssSet(__ATY_HL_H);
+    dev->angleValue = ((uint16_t)wrData[0] << 8);
+
+    // Reading LSB (ANGLE_LSB register)
+    wrData[0] = MT6816_REG_ANGLE_5_0 | 0x80;
+
+    dev->nssSet(__ATY_HL_L);
+    dev->spiProcess(wrData, 1, __ATY_RW_W);
+    dev->spiProcess(wrData, 1, __ATY_RW_R);
+    dev->nssSet(__ATY_HL_H);
+    dev->angleValue |= (wrData[0]);
+
+    MT6816_ParityCheck(dev, 0);
+
+    // dev->angleValue >>= 2;
+    MT6816_CalculateAngleReal(dev, 0);
+
+    __ATY_UNLOCK(dev);
+    return 0;
+}
+
+
+/**
+ * @brief   Read angle value from MT6816 for all 3 regs
+ *
+ * @param   dev Device structure pointer
+ * @return  uint8_t Execution result
+ */
+uint8_t MT6816_ReadAngleFull(struct MT6816_ATY_Dev* dev){
+    __ATY_LOCK(dev);
+
+    wrData[0] = MT6816_REG_ANGLE_13_6 | 0x80;
+
+    dev->nssSet(__ATY_HL_L);
+    dev->spiProcess(wrData, 1, __ATY_RW_W);
+    dev->spiProcess(wrData, 3, __ATY_RW_R);
+    dev->nssSet(__ATY_HL_H);
+
+    // Combine MSB and LSB to form 14-bit angle value
+    dev->angleValue = ((uint16_t)wrData[0] << 8 | wrData[1]);
+
+    MT6816_ErrorCheck(dev, wrData);
+
+    // dev->angleValue >>= 2;
+    MT6816_CalculateAngleReal(dev, 0);
+
+    __ATY_UNLOCK(dev);
+    return 0;
+}
+
+/**
+ * @brief   Set zero point
+ *
+ * @param   dev Device structure pointer
+ * @return  uint8_t Zero point value
+ */
+uint16_t MT6816_SetZeroPoint(struct MT6816_ATY_Dev* dev){
+    MT6816_ReadAngleFull(dev);
+    dev->zeroPoint = dev->angleValue >> 2;
+    return dev->zeroPoint;
+}
+
+
+/**
+ * @brief   Calculate angle in degrees from raw value
+ *
+ * @param   dev Device structure pointer
+ * @param   angle Raw angle value, if 0, use internal angle value
+ * @return  float Angle in degrees
+ */
+float MT6816_CalculateAngle(struct MT6816_ATY_Dev* dev, uint16_t angle){
+    if(angle == 0) angle = dev->angleValue >> 2;
+    dev->angle = (float)angle * 360.0 / 16384.0;
+    if(dev->angleReverseDir == 1){ dev->angle = 360.0 - dev->angle; }
+    return dev->angle;
+}
+
+/**
+ * @brief   Calculate angle in degrees from raw value and remove zero diff
+ *
+ * @param   dev Device structure pointer
+ * @param   angle Raw angle value, if 0, use internal angle value
+ * @return  float Angle in degrees
+ */
+float MT6816_CalculateAngleReal(struct MT6816_ATY_Dev* dev, uint16_t angle){
+    if(angle == 0) angle = dev->angleValue >> 2;
+
+    if(angle == dev->zeroPoint) return 0.0;
+    angle = 16384 + angle - dev->zeroPoint;
+    if(angle > 16384) angle -= 16384;
+    return MT6816_CalculateAngle(dev, angle);
+}
+
+/**
+ * @brief   Update turn count
+ *
+ * @param   dev Device structure pointer
+ * @return  uint8_t Execution result
+ * @note    motor fast rpm = 1 / tCycle(sec) / 2 * 60(1min),
+ *              be sure angle can read back every 180 degree.
+ *          only use for increased angle value.
+ */
+uint32_t MT6816_TurnCount(struct MT6816_ATY_Dev* dev){
+    // jump zero
+    if(dev->angle - dev->angleLast < -180.0){
+        dev->turnCount++;
+    }
+    dev->angleLast = dev->angle;
+    return dev->turnCount;
+}
+
+uint32_t MT6816_TurnCountOffset(struct MT6816_ATY_Dev* dev){
+    // jump zero
+    if(dev->angle - dev->angleLast < -180.0){
+        dev->angleTotal += dev->angle + 360.0 - dev->angleLast;
+    }
+    else{
+        dev->angleTotal += dev->angle - dev->angleLast;
+    }
+
+    if(dev->angleTotal >= 720.0){
+        dev->turnCount++;
+        dev->angleTotal -= 360.0;
+    }
+    dev->angleLast = dev->angle;
+
+    if(dev->start == 0){
+        if(dev->angleTotal >= 360.0){
+            dev->turnCount++;
+            dev->angleTotal -= 360.0;
+        }
+    }
+    return dev->turnCount;
+}
+void MT6816_TurnCountOffsetStart(struct  MT6816_ATY_Dev* dev, uint8_t dir){
+    dev->start = 1;
+    dev->turnCount = 0;
+    dev->angleStart = dev->angle;
+    dev->angleLast = dev->angle;
+    dev->angleTotal = 0;
+    /* call once TurnCountOffsetStart and TurnCountOffsetStop after change dir,
+        like:
+        if(MSSTC_Dev_1.direction != (uint8_t)RGF_MOTOR_DIRECTION){
+            MSSTC_Dev_1.direction = (uint8_t)RGF_MOTOR_DIRECTION;
+            MSSTC_Dev_1.dirSet(MSSTC_Dev_1.direction);
+            MT6816_TurnCountOffsetStart(&MT6816_ATY_Dev_1, MSSTC_Dev_1.direction);
+            MT6816_TurnCountOffsetStop(&MT6816_ATY_Dev_1);
+        }
+    */
+    dev->angleReverseDir = dir ^ 0x01;
+
+    MT6816_TurnCountOffset(dev);
+}
+
+void MT6816_TurnCountOffsetStop(struct  MT6816_ATY_Dev* dev){
+    dev->start = 0;
+
+    MT6816_TurnCountOffset(dev);
+}
+
+#endif /* __MT6816_ATY_C */
+
+/************************************ etc *************************************/
+/* init
+// MT6816 ---------------------------------------------------------------------
+#include "MT6816_ATY.h"
+void MT6816_1_NSS_SET(uint8_t level){
+    if(level == __ATY_HL_L)
+        HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_RESET);
+    else if(level == __ATY_HL_H)
+        HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);
+}
+uint8_t MT6816_1_SPI(uint8_t* data_t, uint16_t len, uint8_t rw){
+    if(rw == __ATY_RW_R){
+        return HAL_SPI_Receive(&hspi1, (uint8_t*)data_t, len, 1000);
+    }
+    else{
+        return HAL_SPI_Transmit(&hspi1, (uint8_t*)data_t, len, 1000);
+    }
+}
+struct MT6816_ATY_Dev MT6816_ATY_Dev_1 = {
+    .nssSet = MT6816_1_NSS_SET,
+    .spiProcess = MT6816_1_SPI,
+
+    .angleValue = 0,
+    .angle = 0,
+    .angleLast = 0,
+    .angleStart = 0,
+    .angleTotal = 0,
+    .turnCount = 0,
+    .start = 0,
+
+    .error = 0,
+    .zeroPoint = 0,
+    .angleReverseDir = 1,
+
+    .lock = __ATY_UNLOCKED
+};
+void MT6816_1_Init(void){
+    MT6816_ReadAngleFull(&MT6816_ATY_Dev_1);
+    HAL_Delay(100);
+    MT6816_ReadAngleFull(&MT6816_ATY_Dev_1);
+
+    RGF_MOTOR_ANGLE_SET_ZERO = 0;
+    RGF_MOTOR_ANGLE_ZERO = MT6816_ATY_Dev_1.zeroPoint;
+    RGF_MOTOR_ANGLE = MT6816_ATY_Dev_1.angle;
+    RGF_MOTOR_ANGLE_ERR = MT6816_ATY_Dev_1.error;
+
+    RGF_MOTOR_ANGLE_ANGLE_START = MT6816_ATY_Dev_1.angleStart;
+    RGF_MOTOR_ANGLE_TURN_COUNT = MT6816_ATY_Dev_1.turnCount;
+    RGF_MOTOR_ANGLE_ANGLE_TOTAL = MT6816_ATY_Dev_1.angleTotal;
+    RGF_MOTOR_ANGLE_START = MT6816_ATY_Dev_1.start;
+}
+void MT6816_1_UpdateCycle(void){
+    MT6816_ReadAngleFull(&MT6816_ATY_Dev_1);
+    MT6816_TurnCountOffset(&MT6816_ATY_Dev_1);
+    if((uint8_t)RGF_MOTOR_ANGLE_SET_ZERO == 1){
+        RGF_MOTOR_ANGLE_SET_ZERO = 0;
+        MT6816_SetZeroPoint(&MT6816_ATY_Dev_1);
+    }
+    RGF_MOTOR_ANGLE_ZERO = MT6816_ATY_Dev_1.zeroPoint;
+    RGF_MOTOR_ANGLE = MT6816_ATY_Dev_1.angle;
+    RGF_MOTOR_ANGLE_ERR = MT6816_ATY_Dev_1.error;
+    RGF_MOTOR_ANGLE_ANGLE_START = MT6816_ATY_Dev_1.angleStart;
+    RGF_MOTOR_ANGLE_TURN_COUNT = MT6816_ATY_Dev_1.turnCount;
+    RGF_MOTOR_ANGLE_ANGLE_TOTAL = MT6816_ATY_Dev_1.angleTotal;
+    RGF_MOTOR_ANGLE_START = MT6816_ATY_Dev_1.start;
+}
+*/
+
+/* use
+MT6816_1_Init();
+
+// read first value and abort
+MT6816_ReadAngleFull(&MT6816_ATY_Dev_1);
+HAL_Delay(100);
+MT6816_ReadAngleFull(&MT6816_ATY_Dev_1);
+
+// if need to set zero point, read angle value first
+MT6816_SetZeroPoint(&MT6816_ATY_Dev_1);
+
+// calculate turn count for motor
+MT6816_TurnCountOffset(&MT6816_ATY_Dev_1);
+
+printf_ATY("\r\nAngle: 0x%04X, Degrees: %.2f",
+    MT6816_ATY_Dev_1.angleValue,
+    MT6816_ATY_Dev_1.angle);
+
+void MSSTC_1_Cycle(void){
+    ...
+    MT6816_1_UpdateCycle();
+    MSSTC_UpdateAngle(&MSSTC_Dev_1,
+        MT6816_ATY_Dev_1.turnCount,
+        MT6816_ATY_Dev_1.angleTotal + MT6816_ATY_Dev_1.angleStart);
+    if((uint8_t)RGF_MOTOR_RUN == 1){
+        MT6816_TurnCountOffsetStart(&MT6816_ATY_Dev_1, MSSTC_Dev_1.direction);
+        MSSTC_Move(&MSSTC_Dev_1, RGF_MOTOR_STEP_COUNT, MT6816_ATY_Dev_1.angleStart);
+    }
+    else if((uint8_t)RGF_MOTOR_RUN == 2){
+        MSSTC_Scram(&MSSTC_Dev_1);
+    }
+    RGF_MOTOR_RUN = 0;
+
+    if(MSSTC_Dev_1.runState == MSSTC_STATE_STANDBY
+        && MT6816_ATY_Dev_1.start == 1){
+        MT6816_TurnCountOffsetStop(&MT6816_ATY_Dev_1);
+    }
+    ...
+}
+*/
+
+/******************************************************************************/
+
+
+/******************************** End Of File *********************************/

+ 81 - 0
MT6816_ATY.h

@@ -0,0 +1,81 @@
+/**
+* @file MT6816_ATY.h
+*
+* @param Project DEVICE_DRIVER_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of MT6816 magnetic encoder for C platform
+*
+* @version
+*       - 1_01_251222 > ATY
+*           -# Preliminary version, first Release
+********************************************************************************
+*/
+
+#ifndef __MT6816_ATY_H
+#define __MT6816_ATY_H
+
+#include "INCLUDE_ATY.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+struct MT6816_ATY_Dev{
+    void (*nssSet)(uint8_t level);
+    uint8_t (*spiProcess)(uint8_t* data_t, uint16_t len, uint8_t rw);
+
+    uint16_t angleValue;
+    float angle;
+    float angleLast;
+    float angleStart;
+    float angleTotal;
+    uint32_t turnCount;
+    uint8_t start;
+
+    uint8_t error;
+    uint16_t zeroPoint;
+    uint8_t angleReverseDir;
+
+    uint8_t lock;
+};
+
+// MT6816 Register Addresses
+#define MT6816_REG_ANGLE_13_6           0x03
+#define MT6816_REG_ANGLE_5_0            0x04
+#define MT6816_REG_ANGLE_OVER_SPEED     0x05
+
+#define MT6816_PARITY_CHECK_MASK        0x01
+#define MT6816_NO_MAG_WARNING_MASK      0x02
+#define MT6816_OVER_SPEED_MASK          0x08
+
+uint8_t MT6816_ParityCheck(struct MT6816_ATY_Dev* dev, uint16_t data);
+uint8_t MT6816_ErrorCheck(struct MT6816_ATY_Dev* dev, uint8_t* data);
+
+uint8_t MT6816_ReadAngleBase(struct MT6816_ATY_Dev* dev);
+uint8_t MT6816_ReadAngleFull(struct MT6816_ATY_Dev* dev);
+uint16_t MT6816_SetZeroPoint(struct MT6816_ATY_Dev* dev);
+
+float MT6816_CalculateAngle(struct MT6816_ATY_Dev* dev, uint16_t angle);
+float MT6816_CalculateAngleReal(struct MT6816_ATY_Dev* dev, uint16_t angle);
+
+uint32_t MT6816_TurnCount(struct MT6816_ATY_Dev* dev);
+uint32_t MT6816_TurnCountOffset(struct MT6816_ATY_Dev* dev);
+void MT6816_TurnCountOffsetStart(struct  MT6816_ATY_Dev* dev, uint8_t dir);
+void MT6816_TurnCountOffsetStop(struct  MT6816_ATY_Dev* dev);
+
+#endif /* __MT6816_ATY_H */
+
+/******************************** End Of File *********************************/

+ 43 - 41
PWR_BTN_ATY.c

@@ -136,48 +136,50 @@ uint8_t PWR_BTN_Status_withCycle(struct PWR_BTN_ATY_Dev* dev){
 #endif /* __PWR_BTN_ATY_C */
 
 /************************************ etc *************************************/
-/* init */
+/* init
 // Power Button ----------------------------------------------------------------
-// #include "PWR_BTN_ATY.h"
-// void PWR_BTN_1_IO_SET(uint8_t level){
-//     if(level)
-//         HAL_GPIO_WritePin(SYS_PWR_GPIO_Port, SYS_PWR_Pin, GPIO_PIN_SET);
-//     else
-//         HAL_GPIO_WritePin(SYS_PWR_GPIO_Port, SYS_PWR_Pin, GPIO_PIN_RESET);
-// }
-// uint8_t PWR_BTN_1_IO_GET(void){
-//     if(HAL_GPIO_ReadPin(SYS_OFF_GPIO_Port, SYS_OFF_Pin) == GPIO_PIN_SET)
-//         return 1;
-//     else
-//         return 0;
-// }
-// void PWR_BTN_1_powerOffCallback(void){
-//     // turn off board
-//     LED_ATY_t_1.ledBlinkType = 0x00;
-// }
-// struct PWR_BTN_ATY_Dev PWR_BTN_ATY_t_1 = {
-//     .PWR_BTN_LongPressCountMax = 20,
-//     .PWR_BTN_LongPressCount = 0,
-//     .ioSet = PWR_BTN_1_IO_SET,
-//     .ioGet = PWR_BTN_1_IO_GET,
-//     .powerOffCallback = PWR_BTN_1_powerOffCallback,
-//     .lock = __ATY_UNLOCKED
-// };
-// // if use IT type
-// void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
-//     if(GPIO_Pin == SYS_OFF_Pin){
-//         // raise and fall
-//         if(HAL_GPIO_ReadPin(SYS_OFF_GPIO_Port, SYS_OFF_Pin) == GPIO_PIN_SET)
-//             PWR_BTN_ATY_t_1.PWR_BTN_LongPressCount = 0;
-//         else
-//             PWR_BTN_ATY_t_1.PWR_BTN_LongPressCount = 1;
-//     }
-// }
-
-/* use */
-// PWR_BTN_Status_withIT(&PWR_BTN_ATY_t_1); // put at 1ms cycle
-// // or
-// PWR_BTN_Status_withCycle(&PWR_BTN_ATY_t_1); // put at 1ms cycle
+#include "PWR_BTN_ATY.h"
+void PWR_BTN_1_IO_SET(uint8_t level){
+    if(level)
+        HAL_GPIO_WritePin(SYS_PWR_GPIO_Port, SYS_PWR_Pin, GPIO_PIN_SET);
+    else
+        HAL_GPIO_WritePin(SYS_PWR_GPIO_Port, SYS_PWR_Pin, GPIO_PIN_RESET);
+}
+uint8_t PWR_BTN_1_IO_GET(void){
+    if(HAL_GPIO_ReadPin(SYS_OFF_GPIO_Port, SYS_OFF_Pin) == GPIO_PIN_SET)
+        return 1;
+    else
+        return 0;
+}
+void PWR_BTN_1_powerOffCallback(void){
+    // turn off board
+    LED_ATY_t_1.ledBlinkType = 0x00;
+}
+struct PWR_BTN_ATY_Dev PWR_BTN_ATY_t_1 = {
+    .PWR_BTN_LongPressCountMax = 20,
+    .PWR_BTN_LongPressCount = 0,
+    .ioSet = PWR_BTN_1_IO_SET,
+    .ioGet = PWR_BTN_1_IO_GET,
+    .powerOffCallback = PWR_BTN_1_powerOffCallback,
+    .lock = __ATY_UNLOCKED
+};
+// if use IT type
+void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
+    if(GPIO_Pin == SYS_OFF_Pin){
+        // raise and fall
+        if(HAL_GPIO_ReadPin(SYS_OFF_GPIO_Port, SYS_OFF_Pin) == GPIO_PIN_SET)
+            PWR_BTN_ATY_t_1.PWR_BTN_LongPressCount = 0;
+        else
+            PWR_BTN_ATY_t_1.PWR_BTN_LongPressCount = 1;
+    }
+}
+*/
+
+/* use
+PWR_BTN_Status_withIT(&PWR_BTN_ATY_t_1); // put at 1ms cycle
+// or
+PWR_BTN_Status_withCycle(&PWR_BTN_ATY_t_1); // put at 1ms cycle
+*/
 
 /******************************************************************************/
 

+ 1 - 1
RM/MODBUS_LOW_ATY.h

@@ -39,7 +39,7 @@
 // #include "HW_UART_ATY.h"
 // #define MODBUS_REG_HOLDING_SIZE                    60   // set --model-large at 51
 // #include "MODBUS_LOW_ATY.h"
-// #define mbG mbRegHoding
+// #define rgf mbRegHoding
 
 #include "main.h"
 #ifndef MODBUS_REG_HOLDING_SIZE

+ 0 - 0
Doing/VL6180_ATY.c → RM/VL6180_ATY.c


+ 0 - 0
Doing/VL6180_ATY.h → RM/VL6180_ATY.h


+ 583 - 0
VL6180x_ATY.c

@@ -0,0 +1,583 @@
+/**
+* @file VL6180x_ATY.c
+*
+* @param Project DEVICE_DRIVER_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of VL6180 for C platform
+*
+* @version
+*       - 1_01_231228 > ATY
+*           -# Preliminary version, first Release
+*       - 1_01_240104 > ATY
+*           -# base tested VL6180
+*       - 1_01_240111 > ATY
+*           -# add lock
+********************************************************************************
+*/
+
+#ifndef __VL6180x_ATY_C
+#define __VL6180x_ATY_C
+
+#include "VL6180x_ATY.h"
+#define VL6180x_ATY_TAG "\r\n[VL6180x_ATY] "
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+/**
+ * @brief
+ *
+ * @param   reg
+ * @param   data
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_WriteByte(uint16_t reg, uint8_t data, struct VL6180x_ATY_Dev* dev){
+    uint8_t groupRegData[3], errCode = 0;
+    __ATY_LOCK(dev);
+    groupRegData[0] = (reg >> 8) & 0xFF;    // MSB of register address
+    groupRegData[1] = reg & 0xFF;           // LSB of register address
+    groupRegData[2] = data & 0xFF;
+    errCode = dev->i2cProcess(dev->addr, groupRegData, 3, __ATY_RW_W);
+    __ATY_UNLOCK(dev);
+    return errCode;
+}
+
+/**
+ * @brief
+ *
+ * @param   reg
+ * @param   data
+ * @param   bytes num to write
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_WriteBytes(uint16_t reg, uint8_t* data, uint8_t bytes, struct VL6180x_ATY_Dev* dev){
+    uint8_t groupRegData[3], i = 0, errCode = 0;
+    __ATY_LOCK(dev);
+    groupRegData[0] = (reg >> 8) & 0xFF;    // MSB of register address
+    groupRegData[1] = reg & 0xFF;           // LSB of register address
+    for(i = 0; i < bytes; i++)
+        groupRegData[2 + i] = data[i] & 0xFF;
+    errCode = dev->i2cProcess(dev->addr, groupRegData, 2 + bytes, __ATY_RW_W);
+    __ATY_UNLOCK(dev);
+    return errCode;
+}
+
+/**
+ * @brief
+ *
+ * @param   reg
+ * @param   data
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_ReadByte(uint16_t reg, uint8_t* data, struct VL6180x_ATY_Dev* dev){
+    uint8_t groupReg[2], errCode = 0;
+    __ATY_LOCK(dev);
+    groupReg[0] = (reg >> 8) & 0xFF;    // MSB of register address
+    groupReg[1] = reg & 0xFF;           // LSB of register address
+    errCode = dev->i2cProcess(dev->addr, groupReg, 2, __ATY_RW_W);
+    if(errCode){ __ATY_UNLOCK(dev); return errCode; }
+    errCode = dev->i2cProcess(dev->addr, data, 1, __ATY_RW_R);
+    __ATY_UNLOCK(dev);
+    return errCode;
+}
+
+/**
+ * @brief
+ *
+ * @param   reg
+ * @param   data
+ * @param   bytes num to read
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_ReadBytes(uint16_t reg, uint8_t* data, uint8_t bytes, struct VL6180x_ATY_Dev* dev){
+    uint8_t groupReg[2], errCode = 0;
+    __ATY_LOCK(dev);
+    groupReg[0] = (reg >> 8) & 0xFF;    // MSB of register address
+    groupReg[1] = reg & 0xFF;           // LSB of register address
+    errCode = dev->i2cProcess(dev->addr, groupReg, 2, __ATY_RW_W);
+    if(errCode){ __ATY_UNLOCK(dev); return errCode; }
+    errCode = dev->i2cProcess(dev->addr, data, bytes, __ATY_RW_R);
+    __ATY_UNLOCK(dev);
+    return errCode;
+}
+
+/**
+ * @brief   get ids
+ *
+ * @param   id need 9 size array
+ * @param   dev device
+ * @return  uint8_t
+ * @note    B4 01 03 ......
+ */
+uint8_t VL6180x_GetId(uint8_t* id, struct VL6180x_ATY_Dev* dev){
+    uint8_t errCode = 0;
+    errCode = 0x00 & VL6180x_ReadByte(VL6180x_REG_IDENTIFICATION_MODEL_ID, &id[0], dev);
+    errCode = 0x10 & VL6180x_ReadByte(VL6180x_REG_IDENTIFICATION_MODEL_REV_MAJOR, &id[1], dev);
+    errCode = 0x20 & VL6180x_ReadByte(VL6180x_REG_IDENTIFICATION_MODEL_REV_MINOR, &id[2], dev);
+    errCode = 0x30 & VL6180x_ReadByte(VL6180x_REG_IDENTIFICATION_MODULE_REV_MAJOR, &id[3], dev);
+    errCode = 0x40 & VL6180x_ReadByte(VL6180x_REG_IDENTIFICATION_MODULE_REV_MINOR, &id[4], dev);
+    errCode = 0x50 & VL6180x_ReadByte(VL6180x_REG_IDENTIFICATION_DATE_HI, &id[5], dev);
+    errCode = 0x60 & VL6180x_ReadByte(VL6180x_REG_IDENTIFICATION_DATE_LO, &id[6], dev);
+    errCode = 0x70 & VL6180x_ReadBytes(VL6180x_REG_IDENTIFICATION_TIME, &id[7], 2, dev);
+
+    printf_ATY_D("%sID: %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n",
+        VL6180x_ATY_TAG, id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8]);
+
+    if(id[0] != 0xB4){ return 0x81; }
+    return errCode;
+}
+/**
+ * @brief   write new addr
+ *
+ * @param   newAddr
+ * @param   dev
+ * @note    not real tested
+ * @return  uint8_t
+ */
+uint8_t VL6180x_SetAddress(uint8_t newAddr, struct VL6180x_ATY_Dev* dev){
+    if(VL6180x_WriteByte(VL6180x_REG_SLAVE_DEVICE_ADDRESS, newAddr & 0x7F, dev) == 1)
+        return 1;
+    dev->addr = newAddr;
+    return 0;
+}
+
+/**
+ * @brief   get offset
+ *
+ * @param   offset
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_GetOffset(uint8_t* offset, struct VL6180x_ATY_Dev* dev){
+    return VL6180x_ReadByte(VL6180x_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET, offset, dev);
+}
+
+/**
+ * @brief   set offset
+ *
+ * @param   offset
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_SetOffset(uint8_t offset, struct VL6180x_ATY_Dev* dev){
+    return VL6180x_WriteByte(VL6180x_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET, offset, dev);
+}
+
+
+
+/**
+ * @brief
+ *
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_Config(struct VL6180x_ATY_Dev* dev){
+    uint8_t errCode = 0;
+    // Mandatory : private registers
+    errCode = 0x10 & VL6180x_WriteByte(0x0207, 0x01, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x0208, 0x01, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x0096, 0x00, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x0097, 0xfd, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00e3, 0x01, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00e4, 0x03, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00e5, 0x02, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00e6, 0x01, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00e7, 0x03, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00f5, 0x02, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00d9, 0x05, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00db, 0xce, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00dc, 0x03, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00dd, 0xf8, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x009f, 0x00, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00a3, 0x3c, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00b7, 0x00, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00bb, 0x3c, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00b2, 0x09, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00ca, 0x09, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x0198, 0x01, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x01b0, 0x17, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x01ad, 0x00, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x00ff, 0x05, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x0100, 0x05, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x0199, 0x05, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x01a6, 0x1b, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x01ac, 0x3e, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x01a7, 0x1f, dev);
+    errCode = 0x10 & VL6180x_WriteByte(0x0030, 0x00, dev);
+
+    // Recommended : Public registers - See data sheet for more detail
+    errCode = 0x20 & VL6180x_WriteByte(0x0011, 0x10, dev); // Enables polling for "New Sample ready" when measurement completes
+    errCode = 0x20 & VL6180x_WriteByte(0x010a, 0x30, dev); // Set the averaging sample period (compromise between lower noise and increased execution time)
+    errCode = 0x20 & VL6180x_WriteByte(0x003f, 0x46, dev); // Sets the light and dark gain (upper nibble). Dark gain should not be changed.
+    errCode = 0x20 & VL6180x_WriteByte(0x0031, 0xFF, dev); // sets the # of range measurements after which auto calibration of system is performed
+    errCode = 0x20 & VL6180x_WriteByte(0x0041, 0x63, dev); // Set ALS integration time to 100ms
+    errCode = 0x20 & VL6180x_WriteByte(0x002e, 0x01, dev); // perform a single temperature calibration of the ranging sensor
+
+    // Optional: Public registers - See data sheet for more detail
+    errCode = 0x30 & VL6180x_WriteByte(0x001b, 0x09, dev); // Set default ranging inter-measurement period to 100ms
+    errCode = 0x30 & VL6180x_WriteByte(0x003e, 0x31, dev); // Set default ALS inter-measurement period to 500ms
+    errCode = 0x30 & VL6180x_WriteByte(0x0014, 0x24, dev); // Configures interrupt on "New Sample Ready threshold event"
+    return errCode;
+}
+
+/**
+ * @brief   initializes I2C interface, checks that VL6180x is found and resets chip
+ *
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_Init(struct VL6180x_ATY_Dev* dev){
+    uint8_t reset;
+    if(VL6180x_ReadByte(VL6180x_REG_SYSTEM_FRESH_OUT_OF_RESET, &reset, dev) == 1)
+        return 1;
+    // check to see has it be Initialised already
+    if(reset == 1){
+        if(VL6180x_Config(dev))
+            return 3;
+        //change fresh out of set status to 0
+        if(VL6180x_WriteByte(VL6180x_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00, dev) == 1)
+            return 2;
+    }
+    VL6180x_GetId(dev->id, dev);
+    return 0;
+}
+
+
+
+/**
+ * @brief
+ *
+ * @return  uint8_t 1 for ready
+ */
+uint8_t VL6180x_IsDeviceReady(struct VL6180x_ATY_Dev* dev){
+    uint8_t byte = 0;
+    if(VL6180x_ReadByte(VL6180x_REG_RESULT_INTERRUPT_STATUS_GPIO, &byte, dev) == 1)
+        return 1;
+    if((byte & 0x01))
+        return 0;
+    return 2;
+}
+
+/**
+ * @brief
+ *
+ * @return  uint8_t 1 for ready
+ */
+uint8_t VL6180x_WaitDeviceReady(struct VL6180x_ATY_Dev* dev){
+    uint16_t errCount = 0;
+    while(VL6180x_IsDeviceReady(dev) != 0){
+        errCount++;
+        if(errCount > 100) return 2;
+    }
+    return 1;
+}
+
+/**
+ * @brief
+ *
+ * @return  uint8_t 1 for complete
+ */
+uint8_t VL6180x_IsRangeComplete(struct VL6180x_ATY_Dev* dev){
+    uint8_t status = 0;
+    if(VL6180x_ReadByte(VL6180x_REG_RESULT_INTERRUPT_STATUS_GPIO, &status, dev) == 1)
+        return 1;
+    status &= 0x07;
+    if((status & 0x04))
+        return 1;
+    return 2;
+}
+
+/**
+ * @brief
+ *
+ * @return  uint8_t 1 for complete
+ */
+uint8_t VL6180x_WaitRangeComplete(struct VL6180x_ATY_Dev* dev){
+    uint16_t errCount = 0;
+    while(VL6180x_IsRangeComplete(dev) != 0){
+        errCount++;
+        if(errCount > 100) return 2;
+    }
+    return 1;
+}
+
+/**
+ * @brief
+ *
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_StartRange(struct VL6180x_ATY_Dev* dev){
+    return VL6180x_WriteByte(VL6180x_REG_SYSRANGE_START, 0x01, dev);
+}
+
+/**
+ * @brief
+ *
+ * @param   dev
+ * @return  uint8_t
+ * @note    Return results of read reqyest also clears out the interrupt
+            Be sure to check the return of {@link readRangeStatus} to before using
+            the return value!
+ */
+uint8_t VL6180x_ReadRangeResult(uint8_t* range, struct VL6180x_ATY_Dev* dev){
+    if(VL6180x_ReadByte(VL6180x_REG_RESULT_RANGE_VAL, range, dev) == 1)
+        return 1;
+    printf_ATY_D("%sRange: %d\r\n", VL6180x_ATY_TAG, *range);
+    return 0;
+}
+
+/**
+ * @brief
+ *
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_ClearInterrupts(struct VL6180x_ATY_Dev* dev){
+    return VL6180x_WriteByte(VL6180x_REG_SYSTEM_INTERRUPT_CLEAR, 0x07, dev);
+}
+
+/**
+ * @brief
+ *
+ * @param   range
+ * @param   dev
+ * @return  uint8_t distance in millimeters if valid
+ * @note    tested in 100ms cycle with uart printf in stm32f103c8t6 72MHz(limited by uart)
+ */
+uint8_t VL6180x_MeasureRangeOnce(uint8_t* range, struct VL6180x_ATY_Dev* dev){
+    uint8_t errCode = 0;
+    errCode = 0x00 & VL6180x_WaitDeviceReady(dev);  // slower
+    errCode = 0x10 & VL6180x_StartRange(dev);
+    errCode = 0x20 & VL6180x_WaitRangeComplete(dev);
+    errCode = 0x30 & VL6180x_ReadRangeResult(range, dev);
+    errCode = 0x40 & VL6180x_ClearInterrupts(dev);
+    return errCode;
+}
+
+/**
+ * @brief
+ *
+ * @param   range
+ * @param   dev
+ * @return  uint8_t distance in millimeters if valid
+ * @note    tested in 50ms cycle with uart printf in stm32f103c8t6 72MHz(limited by uart)
+ */
+uint8_t VL6180x_MeasureRangeOnceFast(uint8_t* range, struct VL6180x_ATY_Dev* dev){
+    uint8_t errCode = 0;
+    // errCode = 0x00 & VL6180x_WaitDeviceReady(dev);
+    errCode = 0x10 & VL6180x_StartRange(dev);
+    // errCode = 0x10 & VL6180x_StartRangeContinuous(10, dev);
+    errCode = 0x20 & VL6180x_WaitRangeComplete(dev);
+    errCode = 0x30 & VL6180x_ReadRangeResult(range, dev);
+    errCode = 0x40 & VL6180x_ClearInterrupts(dev);
+    return errCode;
+}
+
+
+
+
+/**
+ * @brief   request ranging success/error message (retreive after ranging)
+ *
+ * @param   value
+ * @param   dev
+ * @return  uint8_t one of possible VL6180x_ERROR_* values
+ */
+uint8_t VL6180x_ReadRangeStatus(uint8_t* status, struct VL6180x_ATY_Dev* dev){
+    if(VL6180x_ReadByte(VL6180x_REG_RESULT_RANGE_STATUS, status, dev) == 1)
+        return 1;
+    return 0;
+}
+
+/**
+ * @brief   start continuous ranging
+ *
+ * @param   period_msOptional Period between ranges in ms.
+            Values will be rounded down to 10ms units with minimum of 10ms.
+            Default is 50
+ * @param   dev
+ * @return  uint8_t
+ */
+uint8_t VL6180x_StartRangeContinuous(uint16_t period_ms, struct VL6180x_ATY_Dev* dev){
+    uint8_t period_reg = 0;
+    if(period_ms > 10){
+        if(period_ms < 2550)
+            period_reg = (period_ms / 10) - 1;
+        else
+            period_reg = 254;
+    }
+    // Set ranging inter-measurement
+    if(VL6180x_WriteByte(SYSRANGE__INTERMEASUREMENT_PERIOD, period_reg, dev) == 1)
+        return 1;
+    // Start a continuous range measurement
+    if(VL6180x_WriteByte(VL6180x_REG_SYSRANGE_START, 0x03, dev) == 1)
+        return 1;
+    return 0;
+}
+
+/**
+ * @brief   stop continuous range operation
+ *
+ * @param   dev
+ * @return  uint8_t
+ * @note    stop the continuous range operation, by setting the range register
+            back to 1, Page 7 of appication notes
+ */
+uint8_t VL6180x_StopRangeContinuous(struct VL6180x_ATY_Dev* dev){
+    return VL6180x_WriteByte(VL6180x_REG_SYSRANGE_START, 0x01, dev);
+}
+
+
+
+/**
+ * @brief   single shot lux measurement
+ *
+ * @param   gain gain setting, one of VL6180x_ALS_GAIN_*
+ * @param   lux
+ * @param   dev
+ * @return  uint8_t
+ * @note    only for VL6180X
+ */
+uint8_t VL6180x_ReadLux(uint8_t gain, float* lux, struct VL6180x_ATY_Dev* dev){
+    uint16_t errCount = 0;
+    uint8_t byte = 0;
+
+    if(VL6180x_ReadByte(VL6180x_REG_SYSTEM_INTERRUPT_CONFIG, &byte, dev) == 1)
+        return 1;
+    byte &= ~0x38;
+    byte |= (0x4 << 3); // IRQ on ALS ready
+    if(VL6180x_WriteByte(VL6180x_REG_SYSTEM_INTERRUPT_CONFIG, byte, dev) == 1)
+        return 2;
+
+    // 100 ms integration period
+    if(VL6180x_WriteByte(VL6180x_REG_SYSALS_INTEGRATION_PERIOD_HI, 0, dev) == 1)
+        return 3;
+    if(VL6180x_WriteByte(VL6180x_REG_SYSALS_INTEGRATION_PERIOD_LO, 100, dev) == 1)
+        return 4;
+
+    // analog gain
+    if(gain > VL6180x_ALS_GAIN_40){
+        gain = VL6180x_ALS_GAIN_40;
+    }
+    if(VL6180x_WriteByte(VL6180x_REG_SYSALS_ANALOGUE_GAIN, 0x40 | gain, dev) == 1)
+        return 5;
+
+    // start ALS
+    if(VL6180x_WriteByte(VL6180x_REG_SYSALS_START, 0x01, dev) == 1)
+        return 6;
+    if(VL6180x_ReadByte(VL6180x_REG_RESULT_INTERRUPT_STATUS_GPIO, &byte, dev) == 1)
+        return 7;
+    // Poll until "New Sample Ready threshold event" is set
+    while(4 != ((byte >> 3) & 0x7)){
+        if(VL6180x_ReadByte(VL6180x_REG_RESULT_INTERRUPT_STATUS_GPIO, &byte, dev) == 1)
+            return 8;
+        errCount++;
+        if(errCount > 1000) return 9;
+    }
+
+    // read lux!
+    uint8_t luxBytes[2] = {0};
+    if(VL6180x_ReadBytes(VL6180x_REG_RESULT_ALS_VAL, luxBytes, 2, dev) == 1)
+        return 10;
+    *lux = ((luxBytes[0] << 8) | luxBytes[1]);
+
+    // clear interrupt
+    if(VL6180x_WriteByte(VL6180x_REG_SYSTEM_INTERRUPT_CLEAR, 0x07, dev) == 1)
+        return 11;
+
+    *lux *= 0.32; // calibrated count/lux
+    switch(gain){
+        case VL6180x_ALS_GAIN_1:
+            break;
+        case VL6180x_ALS_GAIN_1_25:
+            *lux /= 1.25;
+            break;
+        case VL6180x_ALS_GAIN_1_67:
+            *lux /= 1.67;
+            break;
+        case VL6180x_ALS_GAIN_2_5:
+            *lux /= 2.5;
+            break;
+        case VL6180x_ALS_GAIN_5:
+            *lux /= 5;
+            break;
+        case VL6180x_ALS_GAIN_10:
+            *lux /= 10;
+            break;
+        case VL6180x_ALS_GAIN_20:
+            *lux /= 20;
+            break;
+        case VL6180x_ALS_GAIN_40:
+            *lux /= 40;
+            break;
+    }
+    *lux *= 100;
+    *lux /= 100; // integration time in ms
+
+    return 0;
+}
+
+#endif /* __VL6180x_ATY_C */
+
+/************************************ etc *************************************/
+/* init
+// VL6180x ---------------------------------------------------------------------
+#include "VL6180x_ATY.h"
+uint8_t VL6180x_1_I2C_Soft(uint8_t addr, uint8_t* data_t, uint8_t len, uint8_t rw){
+    if(rw == __ATY_RW_W)
+        return I2C_Write(addr, data_t, len, &HW_I2C_ATY_Dev_1);
+    else if(rw == __ATY_RW_R)
+        return I2C_Read(addr, data_t, len, &HW_I2C_ATY_Dev_1);
+}
+uint8_t VL6180x_1_I2C(uint8_t addr, uint8_t* data_t, uint8_t len, uint8_t rw){
+    if(rw == __ATY_RW_W)
+        return (uint8_t)HAL_I2C_Master_Transmit(&hi2c1, (addr << 1 | 0), data_t, len, 1000);
+    else if(rw == __ATY_RW_R)
+        return (uint8_t)HAL_I2C_Master_Receive(&hi2c1, (addr << 1 | 1), data_t, len, 1000);
+    return 1;
+}
+uint8_t VL6180x_1_ATY_id[9] = {0};
+struct VL6180x_ATY_Dev VL6180x_ATY_t_1 = {
+    .addr = VL6180x_ADDRESS,
+    .id = VL6180x_1_ATY_id,
+    .i2cProcess = VL6180x_1_I2C,
+    .lock = __ATY_UNLOCKED
+};
+*/
+
+/* use
+VL6180x_Init(&VL6180x_ATY_t_1);
+VL6180x_GetId(idGroup, &VL6180x_ATY_t_1);
+VL6180x_SetAddress(0x29, &VL6180x_ATY_t_1);
+VL6180x_GetOffset(&offset, &VL6180x_ATY_t_1);
+VL6180x_SetOffset(0x0D, &VL6180x_ATY_t_1);
+
+VL6180x_MeasureRangeOnce(&range, &VL6180x_ATY_t_1);
+VL6180x_MeasureRangeOnceFast(&range, &VL6180x_ATY_t_1);
+
+// only for VL6180X
+VL6180x_ReadLux(VL6180x_ALS_GAIN_40, &lux, &VL6180x_ATY_t_1);
+*/
+
+/******************************************************************************/
+
+/******************************** End Of File *********************************/

+ 171 - 0
VL6180x_ATY.h

@@ -0,0 +1,171 @@
+/**
+* @file VL6180x_ATY.h
+*
+* @param Project DEVICE_DRIVER_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of VL6180 for C platform
+*
+* @version
+*       - 1_01_230828 > ATY
+*           -# Preliminary version, first Release
+*       - 1_01_240104 > ATY
+*           -# base tested VL6180
+*       - 1_01_240111 > ATY
+*           -# add lock
+********************************************************************************
+*/
+
+#ifndef __VL6180x_ATY_H
+#define __VL6180x_ATY_H
+
+#include "INCLUDE_ATY.h"
+
+/******************************* For user *************************************/
+// 0 1 0 1 0 0 1 R/W    // can be editted by program
+#define VL6180x_ADDRESS (0x29)
+
+/******************************************************************************/
+
+struct VL6180x_ATY_Dev
+{
+    uint8_t addr;
+    uint8_t* id;
+
+    uint8_t (*i2cProcess)(uint8_t addr, uint8_t* data_t, uint8_t len, uint8_t rw);
+
+    uint8_t lock;
+};
+
+
+
+uint8_t VL6180x_GetId(uint8_t* id, struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_SetAddress(uint8_t newAddr, struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_GetOffset(uint8_t *offset, struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_SetOffset(uint8_t offset, struct VL6180x_ATY_Dev* dev);
+
+uint8_t VL6180x_Init(struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_Config(struct VL6180x_ATY_Dev* dev);
+
+uint8_t VL6180x_MeasureRangeOnce(uint8_t* range, struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_MeasureRangeOnceFast(uint8_t* range, struct VL6180x_ATY_Dev* dev);
+
+uint8_t VL6180x_IsDeviceReady(struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_WaitDeviceReady(struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_IsRangeComplete(struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_WaitRangeComplete(struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_StartRange(struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_ReadRangeResult(uint8_t* range, struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_ClearInterrupts(struct VL6180x_ATY_Dev* dev);
+
+// not tested below
+uint8_t VL6180x_ReadRangeStatus(uint8_t* status, struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_StartRangeContinuous(uint16_t period_ms, struct VL6180x_ATY_Dev* dev);
+uint8_t VL6180x_StopRangeContinuous(struct VL6180x_ATY_Dev* dev);
+
+uint8_t VL6180x_ReadLux(uint8_t gain, float* lux, struct VL6180x_ATY_Dev* dev);
+
+
+// device model identification number
+#define VL6180x_REG_IDENTIFICATION_MODEL_ID                 0x000
+#define VL6180x_REG_IDENTIFICATION_MODEL_REV_MAJOR          0x001
+#define VL6180x_REG_IDENTIFICATION_MODEL_REV_MINOR          0x002
+#define VL6180x_REG_IDENTIFICATION_MODULE_REV_MAJOR         0x003
+#define VL6180x_REG_IDENTIFICATION_MODULE_REV_MINOR         0x004
+#define VL6180x_REG_IDENTIFICATION_DATE_HI                  0x006
+#define VL6180x_REG_IDENTIFICATION_DATE_LO                  0x007
+#define VL6180x_REG_IDENTIFICATION_TIME                     0x008 // 8~9
+#define VL6180x_REG_SYSTEM_MODE_GPIO0                       0x010
+#define VL6180x_REG_SYSTEM_MODE_GPIO1                       0x011
+#define VL6180x_REG_SYSTEM_HISTORY_CTRL                     0x012
+#define VL6180x_REG_SYSTEM_INTERRUPT_CONFIG                 0x014
+#define VL6180x_REG_SYSTEM_INTERRUPT_CLEAR                  0x015
+#define VL6180x_REG_SYSTEM_FRESH_OUT_OF_RESET               0x016
+#define VL6180x_REG_SYSTEM_GROUPED_PARAMETER_HOLD           0x017
+#define VL6180x_REG_SYSRANGE_START                          0x018
+#define VL6180x_REG_SYSRANGE_THRESH_HIGH                    0x019
+#define VL6180x_REG_SYSRANGE_THRESH_LOW                     0x01A
+#define VL6180x_REG_SYSRANGE_INTERMEASUREMENT_PERIOD        0x01B
+#define VL6180x_REG_SYSRANGE_MAX_CONVERGENCE_TIME           0x01C
+#define VL6180x_REG_SYSRANGE_CROSSTALK_COMPENSATION_RATE    0x01E
+#define VL6180x_REG_SYSRANGE_CROSSTALK_VALID_HEIGHT         0x021
+#define VL6180x_REG_SYSRANGE_EARLY_CONVERGENCE_ESTIMATE     0x022
+#define VL6180x_REG_SYSRANGE_PART_TO_PART_RANGE_OFFSET      0x024
+#define VL6180x_REG_SYSRANGE_RANGE_IGNORE_VALID_HEIGHT      0x025
+#define VL6180x_REG_SYSRANGE_RANGE_IGNORE_THRESHOLD         0x026
+#define VL6180x_REG_SYSRANGE_MAX_AMBIENT_LEVEL_MULT         0x02C
+#define VL6180x_REG_SYSRANGE_RANGE_CHECK_ENABLES            0x02D
+#define VL6180x_REG_SYSRANGE_VHV_RECALIBRATE                0x02E
+#define VL6180x_REG_SYSRANGE_VHV_REPEAT_RATE                0x031
+#define VL6180x_REG_RESULT_RANGE_STATUS                     0x04D
+#define VL6180x_REG_RESULT_ALS_STATUS                       0x04E
+#define VL6180x_REG_RESULT_INTERRUPT_STATUS_GPIO            0x04F
+#define VL6180x_REG_RESULT_HISTORY_BUFFER_x                 0x052 // 52~60
+#define VL6180x_REG_RESULT_RANGE_VAL                        0x062
+#define VL6180x_REG_RESULT_RANGE_RAW                        0x064
+#define VL6180x_REG_RESULT_RANGE_RETURN_RATE                0x066
+#define VL6180x_REG_RESULT_RANGE_REFERENCE_RATE             0x068
+#define VL6180x_REG_RESULT_RANGE_RETURN_SIGNAL_COUNT        0x06C
+#define VL6180x_REG_RESULT_RANGE_REFERENCE_SIGNAL_COUNT     0x070
+#define VL6180x_REG_RESULT_RANGE_RETURN_AMB_COUNT           0x074
+#define VL6180x_REG_RESULT_RANGE_REFERENCE_AMB_COUNT        0x078
+#define VL6180x_REG_RESULT_RANGE_RETURN_CONV_TIME           0x07C
+#define VL6180x_REG_RESULT_RANGE_REFERENCE_CONV_TIME        0x080
+#define VL6180x_REG_READOUT_AVERAGING_SAMPLE_PERIOD         0x10A
+#define VL6180x_REG_FIRMWARE_BOOTUP                         0x119
+#define VL6180x_REG_SLAVE_DEVICE_ADDRESS                    0x212
+
+// only for VL6180x below reg
+#define VL6180x_REG_SYSALS_START                            0x038
+#define VL6180x_REG_SYSALS_THRESH_HIGH                      0x03A
+#define VL6180x_REG_SYSALS_THRESH_LOW                       0x03C
+#define VL6180x_REG_SYSALS_INTERMEASUREMENT_PERIOD          0x03E
+#define VL6180x_REG_SYSALS_ANALOGUE_GAIN                    0x03F
+#define VL6180x_REG_SYSALS_INTEGRATION_PERIOD_HI            0x040
+#define VL6180x_REG_SYSALS_INTEGRATION_PERIOD_LO            0x041
+#define VL6180x_REG_RESULT_ALS_VAL                          0x050
+#define VL6180x_REG_FIRMWARE_RESULT_SCALER                  0x120
+#define VL6180x_REG_INTERLEAVED_MODE_ENABLE                 0x2A3
+
+
+
+#define VL6180x_ALS_GAIN_1          0x06
+#define VL6180x_ALS_GAIN_1_25       0x05
+#define VL6180x_ALS_GAIN_1_67       0x04
+#define VL6180x_ALS_GAIN_2_5        0x03
+#define VL6180x_ALS_GAIN_5          0x02
+#define VL6180x_ALS_GAIN_10         0x01
+#define VL6180x_ALS_GAIN_20         0x00
+#define VL6180x_ALS_GAIN_40         0x07
+
+#define VL6180x_ERROR_NONE          0   // Success!
+#define VL6180x_ERROR_SYSERR_1      1   // System error
+#define VL6180x_ERROR_SYSERR_5      5   // Sysem error
+#define VL6180x_ERROR_ECEFAIL       6   // Early convergence estimate fail
+#define VL6180x_ERROR_NOCONVERGE    7   // No target detected
+#define VL6180x_ERROR_RANGEIGNORE   8   // Ignore threshold check failed
+#define VL6180x_ERROR_SNR           11  // Ambient conditions too high
+#define VL6180x_ERROR_RAWUFLOW      12  // Raw range algo underflow
+#define VL6180x_ERROR_RAWOFLOW      13  // Raw range algo overflow
+#define VL6180x_ERROR_RANGEUFLOW    14  // Raw range algo underflow
+#define VL6180x_ERROR_RANGEOFLOW    15  // Raw range algo overflow
+
+// Define some additional registers mentioned in application notes and we use
+// period between each measurement when in continuous mode
+#define SYSRANGE__INTERMEASUREMENT_PERIOD 0x001b // P19 application notes
+
+#endif /* __VL6180x_ATY_H */
+
+/******************************** End Of File *********************************/

+ 255 - 0
WS2812_ATY.c

@@ -0,0 +1,255 @@
+/**
+* @file WS2812_ATY.c
+*
+* @param Project DEVICE_DRIVER_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of WS2812 for C platform
+*
+* @version
+*       - 1_01_251112 > ATY
+*           -# Refactor to Dev-style; remove legacy global interfaces
+*       - 1_02_251218 > ATY
+*           -# Refactor all
+********************************************************************************
+*/
+
+#ifndef __WS2812_ATY_C
+#define __WS2812_ATY_C
+
+#include "WS2812_ATY.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+/**
+ * @brief Auto flush
+ *
+ * @param dev
+ * @param buffer
+ * @param count
+ * @return uint8_t
+ */
+uint8_t WS2812_AutoFlush(struct WS2812_ATY_Dev* dev, uint8_t* buffer, uint16_t count){
+    uint8_t errCode = 0;
+    __ATY_LOCK(dev);
+    if(dev->autoUpdate != 0){
+        errCode = dev->set(buffer, count);
+    }
+    __ATY_UNLOCK(dev);
+    return errCode;
+}
+
+/**
+ * @brief Flush buffer
+ *
+ * @param dev
+ * @return uint8_t
+ * @note if use SetPixel, disable dev->autoUpdate and flush light by hands
+ */
+uint8_t WS2812_Flush(struct WS2812_ATY_Dev* dev){
+    uint8_t errCode = 0;
+    __ATY_LOCK(dev);
+    errCode = dev->set(dev->buffer, dev->count);
+
+    __ATY_UNLOCK(dev);
+    return errCode;
+}
+
+/**
+ * @brief Set RGB
+ *
+ * @param dev
+ * @param index
+ * @param R
+ * @param G
+ * @param B
+ */
+uint8_t WS2812_SetRGB(struct WS2812_ATY_Dev* dev, uint16_t index, uint8_t R, uint8_t G, uint8_t B){
+    __ATY_LOCK(dev);
+    if(index < dev->count){
+        uint8_t i = 0;
+        uint8_t colors[3] = {G * dev->brightness, R * dev->brightness, B * dev->brightness};
+        for(i = 0; i < 24; i++){
+            if(colors[i / 8] & (1 << (7 - (i % 8)))){
+                dev->buffer[index * 24 + i] = dev->code1;
+            }
+            else{
+                dev->buffer[index * 24 + i] = dev->code0;
+            }
+        }
+    }
+    __ATY_UNLOCK(dev);
+    return 0;
+}
+
+/**
+ * @brief Get RGB
+ *
+ * @param dev
+ * @param index
+ * @param R
+ * @param G
+ * @param B
+ */
+void WS2812_GetRGB(struct WS2812_ATY_Dev* dev, uint16_t index, uint8_t* R, uint8_t* G, uint8_t* B){
+    if(index < dev->count){
+        uint8_t i = 0;
+        uint8_t colors[3] = {0};
+        for(i = 0; i < 24; i++){
+            if(dev->buffer[index * 24 + i] == dev->code1){
+                colors[i / 8] |= (1 << (7 - (i % 8)));
+            }
+            *G = colors[0] / dev->brightness;
+            *R = colors[1] / dev->brightness;
+            *B = colors[2] / dev->brightness;
+        }
+    }
+}
+
+/**
+ * @brief Fill
+ *
+ * @param dev
+ * @param R
+ * @param G
+ * @param B
+ * @return uint8_t
+ */
+uint8_t WS2812_Fill(struct WS2812_ATY_Dev* dev, uint8_t R, uint8_t G, uint8_t B){
+    for(uint16_t i = 0; i < dev->count; i++){
+        WS2812_SetRGB(dev, i, R, G, B);
+    }
+    WS2812_AutoFlush(dev, dev->buffer, dev->count);
+    return 0;
+}
+
+/**
+ * @brief Set pixel
+ *
+ * @param dev
+ * @param index
+ * @param R
+ * @param G
+ * @param B
+ * @return uint8_t
+ */
+uint8_t WS2812_SetPixel(struct WS2812_ATY_Dev* dev, uint16_t index, uint8_t R, uint8_t G, uint8_t B){
+    if(index < dev->count){
+        WS2812_SetRGB(dev, index, R, G, B);
+    }
+    WS2812_AutoFlush(dev, dev->buffer, dev->count);
+    return 0;
+}
+
+/**
+ * @brief Get pixel
+ *
+ * @param dev
+ * @param index
+ * @param R
+ * @param G
+ * @param B
+ * @return uint8_t
+ */
+uint8_t WS2812_GetPixel(struct WS2812_ATY_Dev* dev, uint16_t index, uint8_t* R, uint8_t* G, uint8_t* B){
+    if(index < dev->count){
+        WS2812_GetRGB(dev, index, R, G, B);
+    }
+    return 0;
+}
+
+/**
+ * @brief Clear
+ *
+ * @param dev
+ * @return uint8_t
+ */
+uint8_t WS2812_Clear(struct WS2812_ATY_Dev* dev){
+    for(uint16_t i = 0; i < dev->count; ++i){
+        WS2812_SetRGB(dev, i, 0, 0, 0);
+    }
+    WS2812_AutoFlush(dev, dev->buffer, dev->count);
+    return 0;
+}
+
+
+#endif /* __WS2812_ATY_C */
+
+/************************************ etc *************************************/
+/* init
+// WS2812 ----------------------------------------------------------------------
+#include "WS2812_ATY.h"
+#define WS2812_1_COUNT 8
+uint8_t WS2812_1_Buffer[WS2812_1_COUNT * 24 + 1] = {0};
+uint8_t WS2812_1_Set(uint8_t* buffer, uint8_t count){
+    return HAL_SPI_Transmit_DMA(&hspi1, buffer, count * 24 + 1);
+}
+struct WS2812_ATY_Dev WS2812_ATY_Dev_1 = {
+    .set = WS2812_1_Set,
+
+    .count = WS2812_1_COUNT,
+    .buffer = WS2812_1_Buffer,
+    .brightness = 0.1,
+
+    .code0 = 0XE0,
+    .code1 = 0XF8,
+    .autoUpdate = 1,
+
+    .lock = __ATY_UNLOCKED
+};
+*/
+
+/* use
+uint8_t WS2812_index = 0;
+void WS2812_Test(void){
+    WS2812_index++;
+    if(WS2812_index > 8) WS2812_index = 0;
+    if(WS2812_index == 0)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0xFF, 0x00, 0x00);
+    else if(WS2812_index == 1)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0x00, 0xFF, 0x00);
+    else if(WS2812_index == 2)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0x00, 0x00, 0xFF);
+    else if(WS2812_index == 3)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0xFF, 0xFF, 0x00);
+    else if(WS2812_index == 4)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0xFF, 0x00, 0xFF);
+    else if(WS2812_index == 5)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0x00, 0xFF, 0xFF);
+    else if(WS2812_index == 6)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0xFF, 0xFF, 0xFF);
+    else if(WS2812_index == 7)
+        WS2812_Fill(&WS2812_ATY_Dev_1, 0x00, 0x00, 0x00);
+    else if(WS2812_index == 8){
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 0, 0xFF, 0x00, 0x00);
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 1, 0x00, 0xFF, 0x00);
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 2, 0x00, 0x00, 0xFF);
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 3, 0x00, 0x00, 0x00);
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 4, 0xFF, 0xFF, 0x00);
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 5, 0xFF, 0x00, 0xFF);
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 6, 0x00, 0xFF, 0xFF);
+        WS2812_SetPixel(&WS2812_ATY_Dev_1, 7, 0xFF, 0xFF, 0xFF);
+    }
+    WS2812_Flush(&WS2812_ATY_Dev_1);
+//        WS2812_Clear(&WS2812_ATY_Dev_1);
+//        WS2812_Fill(&WS2812_ATY_Dev_1, 0xFF, 0x00, 0x00);
+}
+*/
+
+/******************************************************************************/
+
+/******************************** End Of File *********************************/

+ 61 - 0
WS2812_ATY.h

@@ -0,0 +1,61 @@
+/**
+* @file WS2812_ATY.h
+*
+* @param Project DEVICE_DRIVER_ATY_LIB
+*
+* @author ATY
+*
+* @copyright
+*       - Copyright 2017 - 2026 MZ-ATY
+*       - This code follows:
+*           - MZ-ATY Various Contents Joint Statement -
+*               <a href="https://mengze.top/MZ-ATY_VCJS">
+*                        https://mengze.top/MZ-ATY_VCJS</a>
+*           - CC 4.0 BY-NC-SA -
+*               <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/">
+*                        https://creativecommons.org/licenses/by-nc-sa/4.0/</a>
+*       - Your use will be deemed to have accepted the terms of this statement.
+*
+* @brief functions of WS2812 for C platform
+*
+* @version
+*       - 1_01_251112 > ATY
+*           -# Refactor to Dev-style; remove legacy global interfaces
+*       - 1_02_251218 > ATY
+*           -# Refactor all
+********************************************************************************
+*/
+
+#ifndef __WS2812_ATY_H
+#define __WS2812_ATY_H
+
+#include "INCLUDE_ATY.h"
+
+/******************************* For user *************************************/
+
+/******************************************************************************/
+
+struct WS2812_ATY_Dev{
+    uint8_t (*set)(uint8_t* buffer, uint8_t count);
+
+    uint8_t count;
+    uint8_t* buffer;
+    float brightness;   // 0.0 - 1.0
+
+    uint8_t code0;
+    uint8_t code1;
+    uint8_t autoUpdate;
+
+    uint8_t lock;
+};
+
+uint8_t WS2812_Flush(struct WS2812_ATY_Dev* dev);
+void WS2812_GetRGB(struct WS2812_ATY_Dev* dev, uint16_t index, uint8_t* R, uint8_t* G, uint8_t* B);
+uint8_t WS2812_Fill(struct WS2812_ATY_Dev* dev, uint8_t R, uint8_t G, uint8_t B);
+uint8_t WS2812_SetPixel(struct WS2812_ATY_Dev* dev, uint16_t index, uint8_t R, uint8_t G, uint8_t B);
+uint8_t WS2812_GetPixel(struct WS2812_ATY_Dev* dev, uint16_t index, uint8_t* R, uint8_t* G, uint8_t* B);
+uint8_t WS2812_Clear(struct WS2812_ATY_Dev* dev);
+
+#endif /* __WS2812_ATY_H */
+
+/******************************** End Of File *********************************/