commit 41cf57e7d31b0e06eaef9a700e60a2ebd8de02f0 Author: Jonathan Roth Date: Mon Mar 9 15:08:40 2026 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fa36f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +MPLABXLog.xml diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bb631d5 --- /dev/null +++ b/Makefile @@ -0,0 +1,57 @@ +# ───────────────────────────────────────────── +# Makefile — fdr1-modbus-slave +# Cible : PIC18F4431 +# Compilateur : XC8 +# ───────────────────────────────────────────── + +# Projet +PROJECT = fdr1-modbus-slave +MCU = 18F4431 + +# Outils +CC = xc8-cc +IPECMD = java -jar /opt/microchip/mplabx/v6.20/mplab_platform/mplab_ipe/ipecmd.jar +# -OK + +# Répertoires +SRC_DIR = src +INC_DIR = includes +BUILD_DIR = build + +# Flags +DFP = /opt/microchip/mplabx/v6.20/packs/Microchip/PIC18Fxxxx_DFP/1.6.159/xc8 + +CFLAGS = -mcpu=$(MCU) +CFLAGS += -mdfp=$(DFP) +CFLAGS += -I$(INC_DIR) +CFLAGS += -O2 +CFLAGS += -maddrqual=ignore +CFLAGS += -Wl,-Map=$(BUILD_DIR)/$(PROJECT).map + +# Sources +SRCS = $(wildcard $(SRC_DIR)/*.c) + +# Cible principale +HEX = $(BUILD_DIR)/$(PROJECT).hex + +# ───────────────────────────────────────────── + +.PHONY: all clean flash + +all: $(BUILD_DIR) $(HEX) + +# Création du répertoire build si absent +$(BUILD_DIR): + mkdir -p $(BUILD_DIR) + +# Compilation + link en une seule passe XC8 +$(HEX): $(SRCS) + $(CC) $(CFLAGS) $(SRCS) -o $(HEX) + +# Flash via PICkit3 +flash: $(HEX) + $(IPECMD) -TPPK3 -P$(MCU) -F$(HEX) -M -OL + +# Nettoyage +clean: + rm -rf $(BUILD_DIR) diff --git a/README.md b/README.md new file mode 100644 index 0000000..f5529b8 --- /dev/null +++ b/README.md @@ -0,0 +1,76 @@ +# fdr1-modbus-slave + +Firmware Modbus RTU esclave pour encodeur incrémental, conçu pour tourner sur la carte **FDR1 v1.00**. + +Le PIC lit la position du codeur QEI et la met à disposition d'un maître Modbus RTU (OpenPLC ou autre) via liaison série RS232/RS485. + +--- + +## Matériel requis + +- Carte **FDR1 v1.00** +- Microcontrôleur **PIC18F4431** +- Quartz **8 MHz** (HSPLL x4 → Fosc = 32 MHz) +- Encodeur incrémental raccordé au périphérique QEI +- Liaison série RS232 (RS485 à venir) + +--- + +## Configuration Modbus RTU + +| Paramètre | Valeur | +|------------------|------------| +| Adresse esclave | 183 | +| Vitesse | 115200 bps | +| Format | 8N1 | +| Function code | FC03 | + +### Registres + +| Adresse | Nom | Type | Accès | Description | +|----------|-----------|--------|-------|-----------------| +| `0x1700` | HR0 | UINT16 | R | Position QEI | + +--- + +## Build & Flash + +### Prérequis + +- XC8 (dans le PATH) +- MPLABX v6.20 avec DFP PIC18Fxxxx installé +- PICkit3 + +### Compilation + +```bash +make +``` + +### Flashage + +```bash +make flash +``` + +### Nettoyage + +```bash +make clean +``` + +--- + +## Licence + +Copyright (c) 2026, FDR1 Project +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software must display the following acknowledgement: *This product includes software developed by the FDR1 Project.* +4. Neither the name of the FDR1 Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. diff --git a/includes/config.h b/includes/config.h new file mode 100644 index 0000000..9da4a02 --- /dev/null +++ b/includes/config.h @@ -0,0 +1,70 @@ +/* + * File: config.h + * Author: JR + * + * Created on May 6, 2024, 2:50 PM + * + * All configurable parameters are defined here + * + */ + +#ifndef CONFIG_H +#define CONFIG_H + +// MCU frequency +#define FOSC 32000000 // 8MHz crystal *4 (PLL) = 32MHz +#define _XTAL_FREQ FOSC + +#endif + +#include "sysconfig.h" + +/* Pin Mapping: + * + * Port #4 #2 Func Wire to + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * RA0 2 2 RLD Red LED (limits out of range) + * RA1 3 3 BLD Blue LED (activity) + * RA2 3 4 GLD Green LED (speed) + * RA3 5 5 QEA QEA + * RA4 6 6 QEB QEB + * RA5 7 XX Qenable (reserved/unused) + * RA6 14 10 O Rotation out + * RA7 13 XX + * RB0 33 21 Carriage Step + * RB1 34 22 O Motor Step + * RB2 35 23 Carriage Dir + * RB3 36 24 O Motor Dir + * RB4 37 25 O Motor Enable + * RB5 38 26 P PGM + * RB6 39 27 P PGC + * RB7 40 28 P PGD + * RC0 15 11 Carriage Enable + * RC1 16 12 O DialReq + * RC2 17 13 I DialData + * RC3 18 14 INT0 DialClk + * RC4 23 15 INT1 Btn_Reset_Dist + * RC5 24 16 INT2 Btn_Reset_Limits + * RC6 25 17 TX RS232 TX + * RC7 26 18 RX RS232 RX + * RD0 19 XX + * RD1 20 XX + * RD2 21 XX + * RD3 22 XX + * RD4 27 XX + * RD5 28 XX + * RD6 29 XX + * RD7 30 XX + * RE0 8 XX + * RE1 9 XX + * RE2 10 XX + * RE3 1 1 P VPP + * + * + * Peripherals: + * QEI: 16 bit Motion Feedback (IC+QEI) + * Timer0: 16 bit + * Timer1: 16 bit + * Timer2: 8 bit RTC ? + * Timer5: 16 bit Motor rotation control / Next: Reserved: Velocity measure + */ diff --git a/includes/macros.h b/includes/macros.h new file mode 100644 index 0000000..1c07f40 --- /dev/null +++ b/includes/macros.h @@ -0,0 +1,13 @@ +#include + +#ifndef __MACROS_H__ +#define __MACROS_H__ + +#define RED(STATE) {LATDbits.LD0 = STATE;} +#define GREEN(STATE) {LATDbits.LD2 = STATE;} +#define BLUE(STATE) {LATDbits.LD1 = STATE;} +#define RED_TGL() {LATDbits.LD0 = !LATDbits.LD0;} +#define GREEN_TGL() {LATDbits.LD2 = !LATDbits.LD2;} +#define BLUE_TGL() {LATDbits.LD1 = !LATDbits.LD1;} + +#endif //__MACROS_H__ diff --git a/includes/qei.h b/includes/qei.h new file mode 100644 index 0000000..212c923 --- /dev/null +++ b/includes/qei.h @@ -0,0 +1,9 @@ +#include + +#ifndef __FDR1_QEI__ +#define __FDR1_QEI__ + +void QEI_Init(void); +uint16_t QEI_ReadPosition(void); + +#endif //__FDR1_QEI__ diff --git a/includes/rtu.h b/includes/rtu.h new file mode 100644 index 0000000..1e7ffe8 --- /dev/null +++ b/includes/rtu.h @@ -0,0 +1,40 @@ +#ifndef RTU_H +#define RTU_H + +#include +#include + +// ───────────────────────────────────────────── +// Configuration Modbus RTU +// ───────────────────────────────────────────── + +#define RTU_SLAVE_ADDR 0xB7 +#define RTU_FC03 0x03 + +#define RTU_HR0_ADDR 0x1700 // Position QEI + +// ───────────────────────────────────────────── +// Timer2 — timeout inter-caractère 3.5× +// ≈ 304 µs @ 115200 bps +// prescaler 1:16, PR2 = 151 +// ───────────────────────────────────────────── + +#define RTU_TIMER_PRESCALER 16 +#define RTU_TIMER_PR2 151 + +// ───────────────────────────────────────────── +// Buffer +// ───────────────────────────────────────────── + +#define RTU_BUF_SIZE 32 + +// ───────────────────────────────────────────── +// API publique +// ───────────────────────────────────────────── + +void RTU_Init(void); +void RTU_RxISR(void); // ISR UART RX haute priorité +void RTU_TimerISR(void); // ISR Timer2 basse priorité +void RTU_Task(void); // boucle principale + +#endif // RTU_H \ No newline at end of file diff --git a/includes/setup.h b/includes/setup.h new file mode 100644 index 0000000..77ea81a --- /dev/null +++ b/includes/setup.h @@ -0,0 +1,9 @@ +#include + +#ifndef __FDR1_SETUP__ +#define __FDR1_SETUP__ + +void setup(void); +void setup_gpio(void); + +#endif //__FDR1_SETUP__ diff --git a/includes/sysconfig.h b/includes/sysconfig.h new file mode 100644 index 0000000..5e49b8b --- /dev/null +++ b/includes/sysconfig.h @@ -0,0 +1,68 @@ +/* + * File: sysconfig.h + * Author: JR + * + * Created on May 6, 2024, 2:50 PM + */ + +// CONFIG1H +#pragma config OSC = HSPLL +#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled) +#pragma config IESO = ON // Internal External Oscillator Switchover bit (Internal External Switchover mode enabled) + +// CONFIG2L +#pragma config PWRTEN = OFF // Power-up Timer Enable bit (PWRT disabled) +#pragma config BOREN = OFF // Brown-out Reset Enable bits (Brown-out Reset enabled) +#pragma config BORV = 42 // Brown Out Reset Voltage bits (VBOR set to 4.2V) + +// CONFIG2H +#pragma config WDTEN = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit)) +#pragma config WDPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) +#pragma config WINEN = OFF // Watchdog Timer Window Enable bit (WDT window disabled) + +// CONFIG3L +#pragma config PWMPIN = OFF // PWM output pins Reset state control (PWM outputs disabled upon Reset (default)) +#pragma config LPOL = HIGH // Low-Side Transistors Polarity (PWM0, 2, 4 and 6 are active-high) +#pragma config HPOL = HIGH // High-Side Transistors Polarity (PWM1, 3, 5 and 7 are active-high) +#pragma config T1OSCMX = ON // Timer1 Oscillator MUX (Low-power Timer1 operation when microcontroller is in Sleep mode) + +// CONFIG3H +#pragma config FLTAMX = RC1 // FLTA MUX bit (FLTA input is multiplexed with RC1) +#pragma config SSPMX = RC7 // SSP I/O MUX bit (SCK/SCL clocks and SDA/SDI data are multiplexed with RC5 and RC4, respectively. SDO output is multiplexed with RC7.) +#pragma config PWM4MX = RB5 // PWM4 MUX bit (PWM4 output is multiplexed with RB5) +#pragma config EXCLKMX = RC3 // TMR0/T5CKI External clock MUX bit (TMR0/T5CKI external clock input is multiplexed with RC3) +#pragma config MCLRE = ON // MCLR Pin Enable bit (Enabled) + +// CONFIG4L +#pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) +#pragma config LVP = ON // Low-Voltage ICSP Enable bit (Low-voltage ICSP enabled) + +// CONFIG5L +#pragma config CP0 = OFF // Code Protection bit (Block 0 (000200-000FFFh) not code-protected) +#pragma config CP1 = OFF // Code Protection bit (Block 1 (001000-001FFF) not code-protected) +#pragma config CP2 = OFF // Code Protection bit (Block 2 (002000-002FFFh) not code-protected) +#pragma config CP3 = OFF // Code Protection bit (Block 3 (003000-003FFFh) not code-protected) + +// CONFIG5H +#pragma config CPB = OFF // Boot Block Code Protection bit (Boot Block (000000-0001FFh) not code-protected) +#pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) + +// CONFIG6L +#pragma config WRT0 = OFF // Write Protection bit (Block 0 (000200-000FFFh) not write-protected) +#pragma config WRT1 = OFF // Write Protection bit (Block 1 (001000-001FFF) not write-protected) +#pragma config WRT2 = OFF // Write Protection bit (Block 2 (002000-002FFFh) not write-protected) +#pragma config WRT3 = OFF // Write Protection bit (Block 3 (003000-003FFFh) not write-protected) + +// CONFIG6H +#pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected) +#pragma config WRTB = OFF // Boot Block Write Protection bit (Boot Block (000000-0001FFh) not write-protected) +#pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) + +// CONFIG7L +#pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000200-000FFFh) not protected from table reads executed in other blocks) +#pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (001000-001FFF) not protected from table reads executed in other blocks) +#pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (002000-002FFFh) not protected from table reads executed in other blocks) +#pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (003000-003FFFh) not protected from table reads executed in other blocks) + +// CONFIG7H +#pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot Block (000000-0001FFh) not protected from table reads executed in other blocks) diff --git a/includes/uart.h b/includes/uart.h new file mode 100644 index 0000000..91dabb0 --- /dev/null +++ b/includes/uart.h @@ -0,0 +1,8 @@ +#include + +#ifndef __FDR1_UART__ +#define __FDR1_UART__ + +void UART_Init(void); + +#endif //__FDR1_UART__ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5fd3667 --- /dev/null +++ b/src/main.c @@ -0,0 +1,30 @@ +#include + +#include +#include +#include +#include +#include + +void main(void) { + setup(); + + while(1) { + RTU_Task(); + } +} + +void __interrupt(low_priority) LOWprio_interrupt(void) { + if( PIR1bits.TMR2IF ) + RTU_TimerISR(); + return; +} + +void __interrupt(high_priority) HIGHprio_interrupt(void) { + if( PIR1bits.RCIF ) + RTU_RxISR(); + + return; +} + + diff --git a/src/qei.c b/src/qei.c new file mode 100644 index 0000000..d7d98f5 --- /dev/null +++ b/src/qei.c @@ -0,0 +1,35 @@ +#include + +void QEI_Init(void) { + QEICONbits.QEIM = 0; // Disable QEI Module + QEICONbits.QERR = 0; // Clear any count errors + QEICONbits.PDEC = 0; // Continue operation during sleep + QEICONbits.nVELM = 1; // Disable velocity mode + + DFLTCONbits.FLTCK = 1; // filter 1:2, on QEA, QEB, and IDX + DFLTCONbits.FLT1EN = 1; + DFLTCONbits.FLT2EN = 1; + DFLTCONbits.FLT3EN = 1; + DFLTCONbits.FLT4EN = 0; + + MAXCNTH = 0xFF; // MAXCNT = 65535, to maximize range + MAXCNTL = 0xFF; + + POSCNTH = 0; // Reset position counter + POSCNTL = 0; + + QEICONbits.QEIM = 5; // X4 mode with position counter reset by MAXCNT + // QEICONbits.QEIM = 2; // X2 mode with position counter reset by MAXCNT +} + +uint16_t QEI_ReadPosition(void) { + uint8_t hi1, hi2, lo; + + do { + hi1 = POSCNTH; + lo = POSCNTL; + hi2 = POSCNTH; + } while (hi1 != hi2); + + return ((uint16_t)hi1 << 8) | lo; +} \ No newline at end of file diff --git a/src/rtu.c b/src/rtu.c new file mode 100644 index 0000000..15aa48a --- /dev/null +++ b/src/rtu.c @@ -0,0 +1,180 @@ +#include "rtu.h" +#include "qei.h" +#include + +// ───────────────────────────────────────────── +// Buffers & état interne +// ───────────────────────────────────────────── + +static uint8_t rx_buf[RTU_BUF_SIZE]; +static uint8_t rx_len; +static uint8_t frame_ready; + +// ───────────────────────────────────────────── +// CRC16 Modbus +// ───────────────────────────────────────────── + +static uint16_t RTU_CRC16(uint8_t *buf, uint8_t len) +{ + uint16_t crc = 0xFFFF; + uint8_t i, bit; + + for (i = 0; i < len; i++) { + crc ^= buf[i]; + for (bit = 0; bit < 8; bit++) { + if (crc & 0x0001) + crc = (crc >> 1) ^ 0xA001; + else + crc >>= 1; + } + } + return crc; +} + +// ───────────────────────────────────────────── +// Envoi d'un octet (attente TXIF) +// ───────────────────────────────────────────── + +static void RTU_SendByte(uint8_t byte) +{ + while (!PIR1bits.TXIF); + TXREG = byte; +} + +// ───────────────────────────────────────────── +// Réponse FC03 — 1 registre +// ───────────────────────────────────────────── + +static void RTU_SendFC03(uint16_t value) +{ + uint8_t resp[5]; + uint16_t crc; + + resp[0] = RTU_SLAVE_ADDR; + resp[1] = RTU_FC03; + resp[2] = 0x02; // byte count = 2 + resp[3] = (value >> 8); // high byte + resp[4] = (value & 0xFF); // low byte + + crc = RTU_CRC16(resp, 5); + + RTU_SendByte(resp[0]); + RTU_SendByte(resp[1]); + RTU_SendByte(resp[2]); + RTU_SendByte(resp[3]); + RTU_SendByte(resp[4]); + RTU_SendByte(crc & 0xFF); // CRC low + RTU_SendByte(crc >> 8); // CRC high +} + +// ───────────────────────────────────────────── +// Init +// ───────────────────────────────────────────── + +void RTU_Init(void) +{ + rx_len = 0; + frame_ready = 0; + + // Timer2 — timeout inter-caractère 3.5× + PR2 = RTU_TIMER_PR2; + T2CON = 0b00000110; // prescaler 1:16, Timer2 OFF + PIR1bits.TMR2IF = 0; + IPR1bits.TMR2IP = 0; // basse priorité + PIE1bits.TMR2IE = 1; + + // UART RX interrupt + IPR1bits.RCIP = 1; // haute priorité + PIE1bits.RCIE = 1; +} + +// ───────────────────────────────────────────── +// ISR UART RX — haute priorité +// ───────────────────────────────────────────── + +void RTU_RxISR(void) +{ + uint8_t byte; + + BLUE(1); + + // Gestion erreur overrun + if (RCSTAbits.OERR) { + RCSTAbits.CREN = 0; + RCSTAbits.CREN = 1; + } + + byte = RCREG; + + if (rx_len < RTU_BUF_SIZE) + rx_buf[rx_len++] = byte; + + // Redémarre le timer à chaque octet reçu + TMR2 = 0; + PIR1bits.TMR2IF = 0; + T2CONbits.TMR2ON = 1; +} + +// ───────────────────────────────────────────── +// ISR Timer2 — basse priorité +// Silence de 3.5× détecté → trame complète +// ───────────────────────────────────────────── + +void RTU_TimerISR(void) +{ + T2CONbits.TMR2ON = 0; + PIR1bits.TMR2IF = 0; + BLUE(0); + + if (rx_len > 0) + frame_ready = 1; +} + +// ───────────────────────────────────────────── +// Tâche principale — traitement de la trame +// ───────────────────────────────────────────── + +void RTU_Task(void) +{ + uint16_t crc_rx, crc_calc; + uint16_t reg_addr, reg_count; + + if (!frame_ready) + return; + + frame_ready = 0; + + // Trame FC03 minimum : 8 octets + if (rx_len < 8) + goto done; + + // Adresse esclave + if (rx_buf[0] != RTU_SLAVE_ADDR) + goto done; + + // Function code + if (rx_buf[1] != RTU_FC03) + goto done; + + // Vérification CRC + crc_rx = (uint16_t)rx_buf[rx_len - 1] << 8 | rx_buf[rx_len - 2]; + crc_calc = RTU_CRC16(rx_buf, rx_len - 2); + + if (crc_rx != crc_calc) + goto done; + + // Adresse et nombre de registres + reg_addr = (uint16_t)rx_buf[2] << 8 | rx_buf[3]; + reg_count = (uint16_t)rx_buf[4] << 8 | rx_buf[5]; + + // On ne supporte que HR0, 1 registre + if (reg_addr != RTU_HR0_ADDR || reg_count != 1) + goto done; + + GREEN(1); + RTU_SendFC03(QEI_ReadPosition()); + GREEN(0); + +done: + rx_len = 0; +} \ No newline at end of file diff --git a/src/setup.c b/src/setup.c new file mode 100644 index 0000000..9652950 --- /dev/null +++ b/src/setup.c @@ -0,0 +1,53 @@ +#include + +#include +#include +#include +#include +#include +#include + +void setup(void) { + setup_gpio(); + + RED(1); + + QEI_Init(); + UART_Init(); + RTU_Init(); + + INTCON = 0b01010000; // GIE disabled for now, PEIE enable, INT0 enable (always highprio), not int on portB, TMR0 + INTCON2 = 0b00000101; // port B pull-up enabled, INT0/1/2 on falling edge + INTCON3 = 0b11011000; // INT1 interrupt high prio, enabled , wired on DialCLK // INT2 interrupt high prio, enabled , wired on DialCLK + + RCONbits.IPEN = 1; + INTCONbits.GIEH = 1; // haute priorité + INTCONbits.GIEL = 1; // basse priorité + + __delay_ms(3000); + + RED(0); +} + +void setup_gpio() { + + ANSEL0 = 0; // All analog select disable (=digital I/O) + ANSEL0bits.ANS2 = 1; // set RA2/QEI_IDX as analog to disable acting as QEI input + ANSEL1 = 0; + + LATA = 0; + TRISA = 0b10111011; // XO / QEx / RA0+RA1+RA2 + + LATB = 0; + TRISB = 0b00000000; // PGx / Motor driver outputs / SDA+SCL + + LATC = 0; + TRISC = 0b10111111; // all inputs: TX/RX/ buttons / RC0+RC1 + + LATD = 0; + TRISD = 0b11111000; // Red, Blue, Green LEDs as output + + LATE = 0; + TRISE = 0b11111000; // (xxxxIOOO) MCLR / Arm + +} \ No newline at end of file diff --git a/src/uart.c b/src/uart.c new file mode 100644 index 0000000..c28b591 --- /dev/null +++ b/src/uart.c @@ -0,0 +1,17 @@ +#include + +void UART_Init() { + TRISC |= 0b11000000; + RCSTA = 0xB0; // SPEN | SREN | CREN + TXSTA = 0x24; // TXEN | BRGH + // SPBRG = 1; // 250000bps at 8MHz + // SPBRG = 7; // 250000bps at 32MHz + // SPBRG = 3; // 500000bps at 32MHz + // SPBRG = 1; // 1000000bps at 32MHz + // SPBRG = 17; // 115200 bps à 32MHz, erreur -1.36% + SPBRG = 16; // 115200 bps à 32MHz, erreur +2.12% + + // EUSART interrupts as low prio, enable + IPR1bits.RCIP = 0; + PIE1bits.RCIE = 1; +} diff --git a/unused/echo.c b/unused/echo.c new file mode 100644 index 0000000..2df5c02 --- /dev/null +++ b/unused/echo.c @@ -0,0 +1,80 @@ +#include +#include + +#include + +void echo(char* str) { + for(int i=0; str[i]!=0;i++) + echo_c(str[i]); +} +void echo_c(char c) { + while(!TXIF); + TXREG = c; +} + +// void echo_float(float v) { +// char buf[CHAR_BUFF_SIZE]; +// sprintf(buf, "%0.3f", v); +// echo(buf); +// } + +// void echo_float1(float v) { +// char buf[CHAR_BUFF_SIZE]; +// sprintf(buf, "%0.1f", v); +// echo(buf); +// } +// void echo_float2(float v) { +// char buf[CHAR_BUFF_SIZE]; +// sprintf(buf, "%0.2f", v); +// echo(buf); +// } +// void echo_float4(float v) { +// char buf[CHAR_BUFF_SIZE]; +// sprintf(buf, "%0.4f", v); +// echo(buf); +// } + +// void echo_float6(float v) { +// char buf[CHAR_BUFF_SIZE]; +// sprintf(buf, "%0.6f", v); +// echo(buf); +// } + +// void echo_float8(float v) { +// char buf[CHAR_BUFF_SIZE]; +// sprintf(buf, "%0.8f", v); +// echo(buf); +// } + +const char h[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +void echo_hex(uint8_t v) { + echo_c(h[(v&0xf0)>>4]); + echo_c(h[(v&0x0f)]); +} + +void echo_hex16(uint16_t v) { + echo_hex((v&0xff00)>>8); + echo_hex((v&0x00ff)); +} + +void echo_uint16(uint16_t v) { + char buf[CHAR_BUFF_SIZE]; + sprintf(buf, "%hu", v); + echo(buf); +} + +void echo_int32(int32_t v) { + char buf[CHAR_BUFF_SIZE]; + sprintf(buf, "%ld", v); + echo(buf); +} + + +// void echo_bool_label(char* label, uint8_t b) { +// echo(label); +// if(b) +// echo("ON"); +// else +// echo("off"); +// } \ No newline at end of file diff --git a/unused/echo.h b/unused/echo.h new file mode 100644 index 0000000..1af6272 --- /dev/null +++ b/unused/echo.h @@ -0,0 +1,28 @@ +#ifndef __ECHO_H__ +#define __ECHO_H__ + +#define NL "\r\n" + +#define CHAR_BUFF_SIZE 16 + +void echo(char*); +void echo_c(char); + +// void echo_int(int); +void echo_hex(uint8_t); +void echo_hex16(uint16_t); + +void echo_float(float); // def 3 digits +void echo_float1(float); // 6 digits +void echo_float2(float); // 6 digits +void echo_float4(float); // 6 digits +void echo_float6(float); // 6 digits +void echo_float8(float); // 8 digits + +void echo_uint16(uint16_t); +void echo_int32(int32_t); + +void echo_bool_label(char*, uint8_t); + + +#endif //__ECHO_H__ \ No newline at end of file