diff --git a/Software/examples/WS2812/Makefile b/Software/examples/WS2812/Makefile new file mode 100644 index 0000000..a256f61 --- /dev/null +++ b/Software/examples/WS2812/Makefile @@ -0,0 +1,88 @@ +# =================================================================================== +# Project: Examples for CH55x +# Author: CésarBautista +# Year: 2023 +# =================================================================================== +# Type "make help" in the command line. +# =================================================================================== +# File Names +SKETCH = main.c +TARGET = $(basename $(SKETCH)) +INCLUDE = src + +# Microcontroller Settings +FREQ_SYS = 16000000 +XRAM_LOC = 0x0100 +XRAM_SIZE = 0x0300 +CODE_SIZE = 0x3800 + +# Toolchain +CC = sdcc +OBJCOPY = objcopy +PACK_HEX = packihx + +# if linux use python3, if windows use python +WCHISP ?= python prog/uploader.py + +# Compiler Flags +CFLAGS = -mmcs51 --model-small --no-xinit-opt +CFLAGS += --xram-size $(XRAM_SIZE) --xram-loc $(XRAM_LOC) --code-size $(CODE_SIZE) +CFLAGS += -I$(INCLUDE) -DF_CPU=$(FREQ_SYS) +CFILES = $(SKETCH) $(wildcard $(INCLUDE)/*.c) +RFILES = $(CFILES:.c=.rel) +CLEAN = rm -f *.ihx *.lk *.map *.mem *.lst *.rel *.rst *.sym *.asm *.adb + +# Symbolic Targets +help: + @echo "Use the following commands:" + @echo "make all compile, build, and keep all files" + @echo "make hex compile and build $(TARGET).hex" + @echo "make bin compile and build $(TARGET).bin" + @echo "make flash compile, build, and upload $(TARGET).bin to the device" + @echo "make clean remove all build files" + +%.rel : %.c + @echo "Compiling $< ..." + @$(CC) -c $(CFLAGS) $< + +$(TARGET).ihx: $(RFILES) + @echo "Building $(TARGET).ihx ..." + @$(CC) $(notdir $(RFILES)) $(CFLAGS) -o $(TARGET).ihx + +$(TARGET).hex: $(TARGET).ihx + @echo "Building $(TARGET).hex ..." + @$(PACK_HEX) $(TARGET).ihx > $(TARGET).hex + +$(TARGET).bin: $(TARGET).ihx + @echo "Building $(TARGET).bin ..." + @$(OBJCOPY) -I ihex -O binary $(TARGET).ihx $(TARGET).bin + +flash: $(TARGET).bin size removetemp + @echo "Uploading to CH55x ..." + @$(WCHISP) $(TARGET).bin + +all: $(TARGET).bin $(TARGET).hex size + +hex: $(TARGET).hex size removetemp + +bin: $(TARGET).bin size removetemp + +bin-hex: $(TARGET).bin $(TARGET).hex size removetemp + +install: flash + +size: + @echo "------------------" + @echo "FLASH: $(shell awk '$$1 == "ROM/EPROM/FLASH" {print $$4}' $(TARGET).mem) bytes" + @echo "IRAM: $(shell awk '$$1 == "Stack" {print 248-$$10}' $(TARGET).mem) bytes" + @echo "XRAM: $(shell awk '$$1 == "EXTERNAL" {print $(XRAM_LOC)+$$5}' $(TARGET).mem) bytes" + @echo "------------------" + +removetemp: + @echo "Removing temporary files ..." + @$(CLEAN) + +clean: removetemp + @echo "Cleaning all up ..." + @$(CLEAN) + @rm -f $(TARGET).hex $(TARGET).bin diff --git a/Software/examples/WS2812/main.c b/Software/examples/WS2812/main.c new file mode 100644 index 0000000..317e7e3 --- /dev/null +++ b/Software/examples/WS2812/main.c @@ -0,0 +1,92 @@ +// =================================================================================== +// Libraries, Definitions and Macros +// =================================================================================== +// Code Rewrite by Master +// ------- CH552 +// +--\/--+ +// ---------------- P32 1|° |16 V33 ------------- +// ---------------- P14 2| |15 Vcc ------------- +// ---------------- P15 3| |14 GND ------------- +// ---------------- P16 4| |13 P37 UDM --- USB D- +// ---------------- P17 5| |12 P36 UDP --- USB D+ +// ---------------- RST 6| |11 P34 ------------- +// ---------------- P31 7| |10 P33 ---------DOUT +// ---------------- P30 8| |9 P11 ------------- +// +------+ + +// Libraries + + +#include "src/system.h" // system functions +#include "src/delay.h" // delay functions +#include "src/neo.h" // NeoPixel functions +#include // for random number generation + +// =================================================================================== +// NeoPixel Functions +// =================================================================================== + +// Pin definitions +#define PIN_NEO P33 // pin connected to NeoPixel +// + + + +#define delay 100 +#define NeoPixel 16 // Number Neopixel conect +#define level 100 // Ilumination level 0 to 255 + +void randomColorSequence(void) { + + for(int j=0;j self.code_flash_size: + raise Exception('Not enough memory') + if self.chipversion == 1: + self.__writev1(data, MODE_WRITE_V1) + else: + self.__writev2(data, MODE_WRITE_V2) + + print('Flashed successfully') + + def verify_data(self, data): + if len(data) > self.code_flash_size: + raise Exception('Not enough memory') + if self.chipversion == 1: + self.__writev1(data, MODE_VERIFY_V1) + else: + self.__writev2(data, MODE_VERIFY_V2) + + print('Verified successfully') + + def exit(self): + if self.chipversion == 1: + self.__exitv1() + else: + self.__exitv2() + + print('Exited successfully') + + def __sendcmd(self, cmd): + self.epout.write(cmd) + b = self.epin.read(64) + if len(b) == 2: + return struct.unpack('> 4) + '.' + str(cfganswer[0] & 0xf) + else: + raise Exception('Wrong bootloader ID') + + print('Chip ID:', self.chipid) + print('Bootloader version:', self.bootloader) + + def __identchipv2(self): + identanswer = self.__sendcmd(DETECT_CHIP_CMD_V2) + if len(identanswer) == 6: + self.chipid = identanswer[4] + else: + raise Exception('Wrong chip ID') + + cfganswer = self.__sendcmd((0xa7, 0x02, 0x00, 0x1f, 0x00)) + if len(cfganswer) == 30: + self.bootloader = str(cfganswer[19]) + '.' + str(cfganswer[20]) + str(cfganswer[21]) + outbuffer = bytearray(64) + outbuffer[0] = 0xa3 + outbuffer[1] = 0x30 + outbuffer[2] = 0x00 + checksum = cfganswer[22] + checksum += cfganswer[23] + checksum += cfganswer[24] + checksum += cfganswer[25] + for x in range(0x30): + outbuffer[x + 3] = checksum & 0xff + self.__sendcmd(outbuffer) + else: + raise Exception('Wrong bootloader ID') + + print('Chip ID:', self.chipid) + print('Bootloader version:', self.bootloader) + + def __erasev1(self): + self.__sendcmd((0xa6, 0x04, 0x00, 0x00, 0x00, 0x00)) + for x in range(self.device_flash_size): + buffer = self.__sendcmd((0xa9, 0x02, 0x00, x * 4)) + if buffer[0] != 0x00: + raise Exception('Erase failed') + + def __erasev2(self): + buffer = self.__sendcmd((0xa4, 0x01, 0x00, self.device_erase_size)) + if buffer[4] != 0x00: + raise Exception('Erase failed') + + def __exitv1(self): + self.epout.write((0xa5, 0x02, 0x01, 0x00)) + + def __exitv2(self): + self.epout.write((0xa2, 0x01, 0x00, 0x01)) + + def __writev1(self, data, mode): + rest = len(data) + curr_addr = 0 + pkt_length = 0 + outbuffer = bytearray(64) + outbuffer[0] = mode + while curr_addr < len(data): + if rest >= 0x3c: + pkt_length = 0x3c + else: + pkt_length = rest + outbuffer[1] = pkt_length + outbuffer[2] = (curr_addr & 0xff) + outbuffer[3] = ((curr_addr >> 8) & 0xff) + for x in range(pkt_length): + outbuffer[x + 4] = data[curr_addr + x] + buffer = self.__sendcmd(outbuffer) + curr_addr += pkt_length + rest -= pkt_length + if buffer is not None: + if buffer[0] != 0x00: + if mode == MODE_WRITE_V1: + raise Exception('Write failed') + elif mode == MODE_VERIFY_V1: + raise Exception('Verify failed') + return len(data) + + def __writev2(self, data, mode): + rest = len(data) + curr_addr = 0 + pkt_length = 0 + outbuffer = bytearray(64) + outbuffer[0] = mode + outbuffer[2] = 0x00 + outbuffer[5] = 0x00 + outbuffer[6] = 0x00 + while curr_addr < len(data): + if rest >= 0x38: + pkt_length = 0x38 + else: + pkt_length = rest + outbuffer[1] = (pkt_length + 5) + outbuffer[3] = (curr_addr & 0xff) + outbuffer[4] = ((curr_addr >> 8) & 0xff) + outbuffer[7] = rest & 0xff + for x in range(pkt_length): + outbuffer[x + 8] = data[curr_addr + x] + for x in range(pkt_length + 8): + if x % 8 == 7: + outbuffer[x] ^= self.chipid + buffer = self.__sendcmd(outbuffer) + curr_addr += pkt_length + rest -= pkt_length + if buffer is not None: + if buffer[4] != 0x00 and buffer[4] != 0xfe and buffer[4] != 0xf5: + if mode == MODE_WRITE_V2: + raise Exception('Write failed') + elif mode == MODE_VERIFY_V2: + raise Exception('Verify failed') + + # Rest of the Programmer class code ... + +# Rest of the code ... + +CH_VID = 0x4348 +CH_PID = 0x55e0 + +MODE_WRITE_V1 = 0xa8 +MODE_VERIFY_V1 = 0xa7 +MODE_WRITE_V2 = 0xa5 +MODE_VERIFY_V2 = 0xa6 + +DETECT_CHIP_CMD_V1 = (0xa2, 0x13, 0x55, 0x53, 0x42, 0x20, 0x44, 0x42, 0x47, 0x20, 0x43, 0x48, 0x35, 0x35, 0x39, 0x20, 0x26, 0x20, 0x49, 0x53, 0x50, 0x00) +DETECT_CHIP_CMD_V2 = (0xa1, 0x12, 0x00, 0x52, 0x11, 0x4d, 0x43, 0x55, 0x20, 0x49, 0x53, 0x50, 0x20, 0x26, 0x20, 0x57, 0x43, 0x48, 0x2e, 0x43, 0x4e) \ No newline at end of file diff --git a/Software/examples/WS2812/src/ch554.h b/Software/examples/WS2812/src/ch554.h new file mode 100644 index 0000000..8157295 --- /dev/null +++ b/Software/examples/WS2812/src/ch554.h @@ -0,0 +1,758 @@ +/*-------------------------------------------------------------------------- +CH554.H +Header file for CH554 microcontrollers. +**************************************** +** Copyright (C) W.ch 1999-2014 ** +** Web: http://wch.cn ** +**************************************** +--------------------------------------------------------------------------*/ + +#ifndef __CH554_H__ +#define __CH554_H__ + +#define SBIT(name, addr, bit) __sbit __at(addr+bit) name +#define SFR(name, addr) __sfr __at(addr) name +#define SFRX(name, addr) __xdata volatile unsigned char __at(addr) name +#define SFR16(name, addr) __sfr16 __at(((addr+1U)<<8) | addr) name +#define SFR16E(name, fulladdr) __sfr16 __at(fulladdr) name +#define SFR32(name, addr) __sfr32 __at(((addr+3UL)<<24) | ((addr+2UL)<<16) | ((addr+1UL)<<8) | addr) name +#define SFR32E(name, fulladdr) __sfr32 __at(fulladdr) name + +/*----- SFR --------------------------------------------------------------*/ +/* sbit are bit addressable, others are byte addressable */ + +/* System Registers */ +SFR(PSW, 0xD0); // program status word + SBIT(CY, 0xD0, 7); // carry flag + SBIT(AC, 0xD0, 6); // auxiliary carry flag + SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0 + SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit + SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit +#define MASK_PSW_RS 0x18 // bit mask of register R0-R7 bank selection +// RS1 & RS0: register R0-R7 bank selection +// 00 - bank 0, R0-R7 @ address 0x00-0x07 +// 01 - bank 1, R0-R7 @ address 0x08-0x0F +// 10 - bank 2, R0-R7 @ address 0x10-0x17 +// 11 - bank 3, R0-R7 @ address 0x18-0x1F + SBIT(OV, 0xD0, 2); // overflow flag + SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1 + SBIT(P, 0xD0, 0); // ReadOnly: parity flag +SFR(ACC, 0xE0); // accumulator +SFR(B, 0xF0); // general purpose register B +SFR(SP, 0x81); // stack pointer +//sfr16 DPTR = 0x82; // DPTR pointer, little-endian +SFR(DPL, 0x82); // data pointer low +SFR(DPH, 0x83); // data pointer high +SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode +//sfr CHIP_ID = 0xA1; // ReadOnly: reading chip ID +#define CHIP_ID SAFE_MOD +SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode +#define bBOOT_LOAD 0x20 // ReadOnly: boot loader status for discriminating BootLoader or Application: set 1 by power on reset, clear 0 by software reset +#define bSW_RESET 0x10 // software reset bit, auto clear by hardware +#define bCODE_WE 0x08 // enable flash-ROM (include code & Data-Flash) being program or erasing: 0=writing protect, 1=enable program and erase +#define bDATA_WE 0x04 // enable Data-Flash (flash-ROM data area) being program or erasing: 0=writing protect, 1=enable program and erase +#define bLDO3V3_OFF 0x02 // disable 5V->3.3V LDO: 0=enable LDO for USB and internal oscillator under 5V power, 1=disable LDO, V33 pin input external 3.3V power +#define bWDOG_EN 0x01 // enable watch-dog reset if watch-dog timer overflow: 0=as timer only, 1=enable reset if timer overflow + +/* Clock and Sleep and Power Registers */ +SFR(PCON, 0x87); // power control and reset flag +#define SMOD 0x80 // baud rate selection for UART0 mode 1/2/3: 0=slow(Fsys/128 @mode2, TF1/32 @mode1/3, no effect for TF2), + // 1=fast(Fsys/32 @mode2, TF1/16 @mode1/3, no effect for TF2) +#define bRST_FLAG1 0x20 // ReadOnly: recent reset flag high bit +#define bRST_FLAG0 0x10 // ReadOnly: recent reset flag low bit +#define MASK_RST_FLAG 0x30 // ReadOnly: bit mask of recent reset flag +#define RST_FLAG_SW 0x00 +#define RST_FLAG_POR 0x10 +#define RST_FLAG_WDOG 0x20 +#define RST_FLAG_PIN 0x30 +// bPC_RST_FLAG1 & bPC_RST_FLAG0: recent reset flag +// 00 - software reset, by bSW_RESET=1 @(bBOOT_LOAD=0 or bWDOG_EN=1) +// 01 - power on reset +// 10 - watch-dog timer overflow reset +// 11 - external input manual reset by RST pin +#define GF1 0x08 // general purpose flag bit 1 +#define GF0 0x04 // general purpose flag bit 0 +#define PD 0x02 // power-down enable bit, auto clear by wake-up hardware +SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode +#define bOSC_EN_INT 0x80 // internal oscillator enable and original clock selection: 1=enable & select internal clock, 0=disable & select external clock +#define bOSC_EN_XT 0x40 // external oscillator enable, need quartz crystal or ceramic resonator between XI and XO pins +#define bWDOG_IF_TO 0x20 // ReadOnly: watch-dog timer overflow interrupt flag, cleared by reload watch-dog count or auto cleared when MCU enter interrupt routine +#define bROM_CLK_FAST 0x10 // flash-ROM clock frequency selection: 0=normal(for Fosc>=16MHz), 1=fast(for Fosc<16MHz) +#define bRST 0x08 // ReadOnly: pin RST input +#define bT2EX_ 0x08 // alternate pin for T2EX +#define bCAP2_ 0x08 // alternate pin for CAP2 +#define MASK_SYS_CK_SEL 0x07 // bit mask of system clock Fsys selection +/* + Fxt = 24MHz(8MHz~25MHz for non-USB application), from external oscillator @XI&XO + Fosc = bOSC_EN_INT ? 24MHz : Fxt + Fpll = Fosc * 4 => 96MHz (32MHz~100MHz for non-USB application) + Fusb4x = Fpll / 2 => 48MHz (Fixed) + MASK_SYS_CK_SEL[2] [1] [0] + Fsys = Fpll/3 = 32MHz: 1 1 1 + Fsys = Fpll/4 = 24MHz: 1 1 0 + Fsys = Fpll/6 = 16MHz: 1 0 1 + Fsys = Fpll/8 = 12MHz: 1 0 0 + Fsys = Fpll/16 = 6MHz: 0 1 1 + Fsys = Fpll/32 = 3MHz: 0 1 0 + Fsys = Fpll/128 = 750KHz: 0 0 1 + Fsys = Fpll/512 =187.5KHz: 0 0 0 +*/ +SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode +#define bWAK_BY_USB 0x80 // enable wake-up by USB event +#define bWAK_RXD1_LO 0x40 // enable wake-up by RXD1 low level +#define bWAK_P1_5_LO 0x20 // enable wake-up by pin P1.5 low level +#define bWAK_P1_4_LO 0x10 // enable wake-up by pin P1.4 low level +#define bWAK_P1_3_LO 0x08 // enable wake-up by pin P1.3 low level +#define bWAK_RST_HI 0x04 // enable wake-up by pin RST high level +#define bWAK_P3_2E_3L 0x02 // enable wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level +#define bWAK_RXD0_LO 0x01 // enable wake-up by RXD0 low level +SFR(RESET_KEEP, 0xFE); // value keeper during reset +SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536 + +/* Interrupt Registers */ +SFR(IE, 0xA8); // interrupt enable + SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0 + SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable + SBIT(ET2, 0xA8, 5); // enable timer2 interrupt + SBIT(ES, 0xA8, 4); // enable UART0 interrupt + SBIT(ET1, 0xA8, 3); // enable timer1 interrupt + SBIT(EX1, 0xA8, 2); // enable external interrupt INT1 + SBIT(ET0, 0xA8, 1); // enable timer0 interrupt + SBIT(EX0, 0xA8, 0); // enable external interrupt INT0 +SFR(IP, 0xB8); // interrupt priority and current priority + SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag + SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag +// PH_FLAG & PL_FLAG: current interrupt priority +// 00 - no interrupt now +// 01 - low level priority interrupt action now +// 10 - high level priority interrupt action now +// 11 - unknown error + SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level + SBIT(PS, 0xB8, 4); // UART0 interrupt priority level + SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level + SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level + SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level + SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level +SFR(IE_EX, 0xE8); // extend interrupt enable + SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt + SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt + SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt + SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt + SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt + SBIT(IE_USB, 0xE8, 2); // enable USB interrupt + SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt + SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt +SFR(IP_EX, 0xE9); // extend interrupt priority +#define bIP_LEVEL 0x80 // ReadOnly: current interrupt nested level: 0=no interrupt or two levels, 1=one level +#define bIP_GPIO 0x40 // GPIO input interrupt priority level +#define bIP_PWMX 0x20 // PWM1/2 interrupt priority level +#define bIP_UART1 0x10 // UART1 interrupt priority level +#define bIP_ADC 0x08 // ADC interrupt priority level +#define bIP_USB 0x04 // USB interrupt priority level +#define bIP_TKEY 0x02 // touch-key timer interrupt priority level +#define bIP_SPI0 0x01 // SPI0 interrupt priority level +SFR(GPIO_IE, 0xC7); // GPIO interrupt enable +#define bIE_IO_EDGE 0x80 // enable GPIO edge interrupt: 0=low/high level, 1=falling/rising edge +#define bIE_RXD1_LO 0x40 // enable interrupt by RXD1 low level / falling edge +#define bIE_P1_5_LO 0x20 // enable interrupt by pin P1.5 low level / falling edge +#define bIE_P1_4_LO 0x10 // enable interrupt by pin P1.4 low level / falling edge +#define bIE_P1_3_LO 0x08 // enable interrupt by pin P1.3 low level / falling edge +#define bIE_RST_HI 0x04 // enable interrupt by pin RST high level / rising edge +#define bIE_P3_1_LO 0x02 // enable interrupt by pin P3.1 low level / falling edge +#define bIE_RXD0_LO 0x01 // enable interrupt by RXD0 low level / falling edge + +/* FlashROM and Data-Flash Registers */ +SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian +SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM +SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM +SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian +SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing +SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing +SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control +#define ROM_CMD_WRITE 0x9A // WriteOnly: flash-ROM word or Data-Flash byte write operation command +#define ROM_CMD_READ 0x8E // WriteOnly: Data-Flash byte read operation command +//sfr ROM_STATUS = 0x86; // ReadOnly: flash-ROM status +#define ROM_STATUS ROM_CTRL +#define bROM_ADDR_OK 0x40 // ReadOnly: flash-ROM writing operation address valid flag, can be reviewed before or after operation: 0=invalid parameter, 1=address valid +#define bROM_CMD_ERR 0x02 // ReadOnly: flash-ROM operation command error flag: 0=command accepted, 1=unknown command + +/* Port Registers */ +SFR(P1, 0x90); // port 1 input & output + SBIT(SCK, 0x90, 7); // serial clock for SPI0 + SBIT(TXD1, 0x90, 7); // TXD output for UART1 + SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key + SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0 + SBIT(RXD1, 0x90, 6); // RXD input for UART1 + SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key + SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0 + SBIT(PWM1, 0x90, 5); // PWM output for PWM1 + SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key + SBIT(UCC2, 0x90, 5); // CC2 for USB type-C + SBIT(AIN2, 0x90, 5); // AIN2 for ADC + SBIT(T2_, 0x90, 4); // alternate pin for T2 + SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1 + SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0 + SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key + SBIT(UCC1, 0x90, 4); // CC1 for USB type-C + SBIT(AIN1, 0x90, 4); // AIN1 for ADC + SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0 + SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0 + SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture + SBIT(CAP2, 0x90, 1); // capture2 input for timer2 + SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key + SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C + SBIT(AIN0, 0x90, 1); // AIN0 for ADC + SBIT(T2, 0x90, 0); // external count input + SBIT(CAP1, 0x90, 0); // capture1 input for timer2 + SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key +SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain +SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain +// Pn_MOD_OC & Pn_DIR_PU: pin input & output configuration for Pn (n=1/3) +// 0 0: float input only, without pullup resistance +// 0 1: push-pull output, strong driving high level and low level +// 1 0: open-drain output and input without pullup resistance +// 1 1: quasi-bidirectional (standard 8051 mode), open-drain output and input with pullup resistance, just driving high level strongly for 2 clocks if turning output level from low to high +#define bSCK 0x80 // serial clock for SPI0 +#define bTXD1 0x80 // TXD output for UART1 +#define bMISO 0x40 // master serial data input or slave serial data output for SPI0 +#define bRXD1 0x40 // RXD input for UART1 +#define bMOSI 0x20 // master serial data output or slave serial data input for SPI0 +#define bPWM1 0x20 // PWM output for PWM1 +#define bUCC2 0x20 // CC2 for USB type-C +#define bAIN2 0x20 // AIN2 for ADC +#define bT2_ 0x10 // alternate pin for T2 +#define bCAP1_ 0x10 // alternate pin for CAP1 +#define bSCS 0x10 // slave chip-selection input for SPI0 +#define bUCC1 0x10 // CC1 for USB type-C +#define bAIN1 0x10 // AIN1 for ADC +#define bTXD_ 0x08 // alternate pin for TXD of UART0 +#define bRXD_ 0x04 // alternate pin for RXD of UART0 +#define bT2EX 0x02 // external trigger input for timer2 reload & capture +#define bCAP2 bT2EX // capture2 input for timer2 +#define bVBUS2 0x02 // VBUS2 for USB type-C +#define bAIN0 0x02 // AIN0 for ADC +#define bT2 0x01 // external count input or clock output for timer2 +#define bCAP1 bT2 // capture1 input for timer2 +SFR(P2, 0xA0); // port 2 +SFR(P3, 0xB0); // port 3 input & output + SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input + SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input + SBIT(T1, 0xB0, 5); // external count input for timer1 + SBIT(PWM2, 0xB0, 4); // PWM output for PWM2 + SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1 + SBIT(T0, 0xB0, 4); // external count input for timer0 + SBIT(INT1, 0xB0, 3); // external interrupt 1 input + SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1 + SBIT(INT0, 0xB0, 2); // external interrupt 0 input + SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C + SBIT(AIN3, 0xB0, 2); // AIN3 for ADC + SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2 + SBIT(TXD, 0xB0, 1); // TXD output for UART0 + SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1 + SBIT(RXD, 0xB0, 0); // RXD input for UART0 +SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain +SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain +#define bUDM 0x80 // ReadOnly: pin UDM input +#define bUDP 0x40 // ReadOnly: pin UDP input +#define bT1 0x20 // external count input for timer1 +#define bPWM2 0x10 // PWM output for PWM2 +#define bRXD1_ 0x10 // alternate pin for RXD1 +#define bT0 0x10 // external count input for timer0 +#define bINT1 0x08 // external interrupt 1 input +#define bTXD1_ 0x04 // alternate pin for TXD1 +#define bINT0 0x04 // external interrupt 0 input +#define bVBUS1 0x04 // VBUS1 for USB type-C +#define bAIN3 0x04 // AIN3 for ADC +#define bPWM2_ 0x02 // alternate pin for PWM2 +#define bTXD 0x02 // TXD output for UART0 +#define bPWM1_ 0x01 // alternate pin for PWM1 +#define bRXD 0x01 // RXD input for UART0 +SFR(PIN_FUNC, 0xC6); // pin function selection +#define bUSB_IO_EN 0x80 // USB UDP/UDM I/O pin enable: 0=P3.6/P3.7 as GPIO, 1=P3.6/P3.7 as USB +#define bIO_INT_ACT 0x40 // ReadOnly: GPIO interrupt request action status +#define bUART1_PIN_X 0x20 // UART1 alternate pin enable: 0=RXD1/TXD1 on P1.6/P1.7, 1=RXD1/TXD1 on P3.4/P3.2 +#define bUART0_PIN_X 0x10 // UART0 alternate pin enable: 0=RXD0/TXD0 on P3.0/P3.1, 1=RXD0/TXD0 on P1.2/P1.3 +#define bPWM2_PIN_X 0x08 // PWM2 alternate pin enable: 0=PWM2 on P3.4, 1=PWM2 on P3.1 +#define bPWM1_PIN_X 0x04 // PWM1 alternate pin enable: 0=PWM1 on P1.5, 1=PWM1 on P3.0 +#define bT2EX_PIN_X 0x02 // T2EX/CAP2 alternate pin enable: 0=T2EX/CAP2 on P1.1, 1=T2EX/CAP2 on RST +#define bT2_PIN_X 0x01 // T2/CAP1 alternate pin enable: 0=T2/CAP1 on P1.1, 1=T2/CAP1 on P1.4 +SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting +#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmittal status +#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receiving status +#define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status +#define GF2 0x08 // general purpose flag bit 2 +#define bDPTR_AUTO_INC 0x04 // enable DPTR auto increase if finished MOVX_@DPTR instruction +#define DPS 0x01 // dual DPTR selection: 0=DPTR0 selected, 1=DPTR1 selected + +/* Timer0/1 Registers */ +SFR(TCON, 0x88); // timer 0/1 control and external interrupt control + SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(TR1, 0x88, 6); // timer1 run enable + SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(TR0, 0x88, 4); // timer0 run enable + SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action + SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine + SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action +SFR(TMOD, 0x89); // timer 0/1 mode +#define bT1_GATE 0x80 // gate control of timer1: 0=timer1 run enable while TR1=1, 1=timer1 run enable while P3.3 (INT1) pin is high and TR1=1 +#define bT1_CT 0x40 // counter or timer mode selection for timer1: 0=timer, use internal clock, 1=counter, use P3.5 (T1) pin falling edge as clock +#define bT1_M1 0x20 // timer1 mode high bit +#define bT1_M0 0x10 // timer1 mode low bit +#define MASK_T1_MOD 0x30 // bit mask of timer1 mode +// bT1_M1 & bT1_M0: timer1 mode +// 00: mode 0, 13-bit timer or counter by cascaded TH1 and lower 5 bits of TL1, the upper 3 bits of TL1 are ignored +// 01: mode 1, 16-bit timer or counter by cascaded TH1 and TL1 +// 10: mode 2, TL1 operates as 8-bit timer or counter, and TH1 provide initial value for TL1 auto-reload +// 11: mode 3, stop timer1 +#define bT0_GATE 0x08 // gate control of timer0: 0=timer0 run enable while TR0=1, 1=timer0 run enable while P3.2 (INT0) pin is high and TR0=1 +#define bT0_CT 0x04 // counter or timer mode selection for timer0: 0=timer, use internal clock, 1=counter, use P3.4 (T0) pin falling edge as clock +#define bT0_M1 0x02 // timer0 mode high bit +#define bT0_M0 0x01 // timer0 mode low bit +#define MASK_T0_MOD 0x03 // bit mask of timer0 mode +// bT0_M1 & bT0_M0: timer0 mode +// 00: mode 0, 13-bit timer or counter by cascaded TH0 and lower 5 bits of TL0, the upper 3 bits of TL0 are ignored +// 01: mode 1, 16-bit timer or counter by cascaded TH0 and TL0 +// 10: mode 2, TL0 operates as 8-bit timer or counter, and TH0 provide initial value for TL0 auto-reload +// 11: mode 3, TL0 is 8-bit timer or counter controlled by standard timer0 bits, TH0 is 8-bit timer using TF1 and controlled by TR1, timer1 run enable if it is not mode 3 +SFR(TL0, 0x8A); // low byte of timer 0 count +SFR(TL1, 0x8B); // low byte of timer 1 count +SFR(TH0, 0x8C); // high byte of timer 0 count +SFR(TH1, 0x8D); // high byte of timer 1 count + +/* UART0 Registers */ +SFR(SCON, 0x98); // UART0 control (serial port control) + SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data + SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable +// SM0 & SM1: UART0 mode +// 00 - mode 0, shift Register, baud rate fixed at: Fsys/12 +// 01 - mode 1, 8-bit UART, baud rate = variable by timer1 or timer2 overflow rate +// 10 - mode 2, 9-bit UART, baud rate fixed at: Fsys/128@SMOD=0, Fsys/32@SMOD=1 +// 11 - mode 3, 9-bit UART, baud rate = variable by timer1 or timer2 overflow rate + SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3 +#define MASK_UART0_MOD 0xE0 // bit mask of UART0 mode + SBIT(REN, 0x98, 4); // enable UART0 receiving + SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3 + SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1 + SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear + SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear +SFR(SBUF, 0x99); // UART0 data buffer: reading for receiving, writing for transmittal + +/* Timer2/Capture2 Registers */ +SFR(T2CON, 0xC8); // timer 2 control + SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1 + SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear + SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear + SBIT(RCLK, 0xC8, 5); // selection UART0 receiving clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse + SBIT(TCLK, 0xC8, 4); // selection UART0 transmittal clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse + SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge + SBIT(TR2, 0xC8, 2); // timer2 run enable + SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge + SBIT(CP_RL2, 0xC8, 0); // timer2 function selection (force 0 if RCLK=1 or TCLK=1): 0=timer and auto reload if count overflow or T2EX edge, 1=capture by T2EX edge +SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode +#define bTMR_CLK 0x80 // fastest internal clock mode for timer 0/1/2 under faster clock mode: 0=use divided clock, 1=use original Fsys as clock without dividing +#define bT2_CLK 0x40 // timer2 internal clock frequency selection: 0=standard clock, Fsys/12 for timer mode, Fsys/4 for UART0 clock mode, + // 1=faster clock, Fsys/4 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for timer mode, Fsys/2 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for UART0 clock mode +#define bT1_CLK 0x20 // timer1 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1 +#define bT0_CLK 0x10 // timer0 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1 +#define bT2_CAP_M1 0x08 // timer2 capture mode high bit +#define bT2_CAP_M0 0x04 // timer2 capture mode low bit +// bT2_CAP_M1 & bT2_CAP_M0: timer2 capture point selection +// x0: from falling edge to falling edge +// 01: from any edge to any edge (level changing) +// 11: from rising edge to rising edge +#define T2OE 0x02 // enable timer2 generated clock output: 0=disable output, 1=enable clock output at T2 pin, frequency = TF2/2 +#define bT2_CAP1_EN 0x01 // enable T2 trigger function for capture 1 of timer2 if RCLK=0 & TCLK=0 & CP_RL2=1 & C_T2=0 & T2OE=0 +SFR16(RCAP2, 0xCA); // reload & capture value, little-endian +SFR(RCAP2L, 0xCA); // low byte of reload & capture value +SFR(RCAP2H, 0xCB); // high byte of reload & capture value +SFR16(T2COUNT, 0xCC); // counter, little-endian +SFR(TL2, 0xCC); // low byte of timer 2 count +SFR(TH2, 0xCD); // high byte of timer 2 count +SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2 +SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2 +SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2 + +/* PWM1/2 Registers */ +SFR(PWM_DATA2, 0x9B); // PWM data for PWM2 +SFR(PWM_DATA1, 0x9C); // PWM data for PWM1 +SFR(PWM_CTRL, 0x9D); // PWM 1/2 control +#define bPWM_IE_END 0x80 // enable interrupt for PWM mode cycle end +#define bPWM2_POLAR 0x40 // PWM2 output polarity: 0=default low and high action, 1=default high and low action +#define bPWM1_POLAR 0x20 // PWM1 output polarity: 0=default low and high action, 1=default high and low action +#define bPWM_IF_END 0x10 // interrupt flag for cycle end, write 1 to clear or write PWM_CYCLE or load new data to clear +#define bPWM2_OUT_EN 0x08 // PWM2 output enable +#define bPWM1_OUT_EN 0x04 // PWM1 output enable +#define bPWM_CLR_ALL 0x02 // force clear FIFO and count of PWM1/2 +SFR(PWM_CK_SE, 0x9E); // clock divisor setting + +/* SPI0/Master0/Slave Registers */ +SFR(SPI0_STAT, 0xF8); // SPI 0 status + SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0 + SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear + SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear + SBIT(S0_IF_BYTE, 0xF8, 4); // interrupt flag for a byte data exchanged, direct bit address clear or write 1 to clear or accessing FIFO to clear if bS0_AUTO_IF=1 + SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status + SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0 + SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0 +SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receiving, writing for transmittal +SFR(SPI0_CTRL, 0xFA); // SPI 0 control +#define bS0_MISO_OE 0x80 // SPI0 MISO output enable +#define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable +#define bS0_SCK_OE 0x20 // SPI0 SCK output enable +#define bS0_DATA_DIR 0x10 // SPI0 data direction: 0=out(master_write), 1=in(master_read) +#define bS0_MST_CLK 0x08 // SPI0 master clock mode: 0=mode 0 with default low, 1=mode 3 with default high +#define bS0_2_WIRE 0x04 // enable SPI0 two wire mode: 0=3 wire (SCK+MOSI+MISO), 1=2 wire (SCK+MISO) +#define bS0_CLR_ALL 0x02 // force clear FIFO and count of SPI0 +#define bS0_AUTO_IF 0x01 // enable FIFO accessing to auto clear S0_IF_BYTE interrupt flag +SFR(SPI0_CK_SE, 0xFB); // clock divisor setting +//sfr SPI0_S_PRE = 0xFB; // preset value for SPI slave +#define SPI0_S_PRE SPI0_CK_SE +SFR(SPI0_SETUP, 0xFC); // SPI 0 setup +#define bS0_MODE_SLV 0x80 // SPI0 slave mode: 0=master, 1=slave +#define bS0_IE_FIFO_OV 0x40 // enable interrupt for slave mode FIFO overflow +#define bS0_IE_FIRST 0x20 // enable interrupt for first byte received for SPI0 slave mode +#define bS0_IE_BYTE 0x10 // enable interrupt for a byte received +#define bS0_BIT_ORDER 0x08 // SPI0 bit data order: 0=MSB first, 1=LSB first +#define bS0_SLV_SELT 0x02 // ReadOnly: SPI0 slave mode chip selected status: 0=unselected, 1=selected +#define bS0_SLV_PRELOAD 0x01 // ReadOnly: SPI0 slave mode data pre-loading status just after chip-selection + +/* UART1 Registers */ +SFR(SCON1, 0xC0); // UART1 control (serial port control) + SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data + SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1)) + SBIT(U1REN, 0xC0, 4); // enable UART1 receiving + SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode + SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode + SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear + SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear +SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receiving, writing for transmittal +SFR(SBAUD1, 0xC2); // UART1 baud rate setting + +/* ADC and comparator Registers */ +SFR(ADC_CTRL, 0x80); // ADC control + SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input + SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear + SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear + SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished + SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3 + SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit + SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit +// ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection +// 00: AIN0(P1.1) +// 01: AIN1(P1.4) +// 10: AIN2(P1.5) +// 11: AIN3(P3.2) +SFR(ADC_CFG, 0x9A); // ADC config +#define bADC_EN 0x08 // control ADC power: 0=shut down ADC, 1=enable power for ADC +#define bCMP_EN 0x04 // control comparator power: 0=shut down comparator, 1=enable power for comparator +#define bADC_CLK 0x01 // ADC clock frequency selection: 0=slow clock, 384 Fosc cycles for each ADC, 1=fast clock, 96 Fosc cycles for each ADC +SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data + +/* Touch-key timer Registers */ +SFR(TKEY_CTRL, 0xC3); // touch-key control +#define bTKC_IF 0x80 // ReadOnly: interrupt flag for touch-key timer, cleared by writing touch-key control or auto cleared when start touch-key checking +#define bTKC_2MS 0x10 // touch-key timer cycle selection: 0=1mS, 1=2mS +#define bTKC_CHAN2 0x04 // touch-key channel selection high bit +#define bTKC_CHAN1 0x02 // touch-key channel selection middle bit +#define bTKC_CHAN0 0x01 // touch-key channel selection low bit +// bTKC_CHAN2 & bTKC_CHAN1 & bTKC_CHAN0: touch-key channel selection +// 000: disable touch-key +// 001: TIN0(P1.0) +// 010: TIN1(P1.1) +// 011: TIN2(P1.4) +// 100: TIN3(P1.5) +// 101: TIN4(P1.6) +// 110: TIN5(P1.7) +// 111: enable touch-key but disable all channel +SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian +SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data +SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data +#define bTKD_CHG 0x80 // ReadOnly: indicate control changed, current data maybe invalid + +/* USB/Host/Device Registers */ +SFR(USB_C_CTRL, 0x91); // USB type-C control +#define bVBUS2_PD_EN 0x80 // USB VBUS2 10K pulldown resistance: 0=disable, 1=enable pullup +#define bUCC2_PD_EN 0x40 // USB CC2 5.1K pulldown resistance: 0=disable, 1=enable pulldown +#define bUCC2_PU1_EN 0x20 // USB CC2 pullup resistance control high bit +#define bUCC2_PU0_EN 0x10 // USB CC2 pullup resistance control low bit +#define bVBUS1_PD_EN 0x08 // USB VBUS1 10K pulldown resistance: 0=disable, 1=enable pullup +#define bUCC1_PD_EN 0x04 // USB CC1 5.1K pulldown resistance: 0=disable, 1=enable pulldown +#define bUCC1_PU1_EN 0x02 // USB CC1 pullup resistance control high bit +#define bUCC1_PU0_EN 0x01 // USB CC1 pullup resistance control low bit +// bUCC?_PU1_EN & bUCC?_PU0_EN: USB CC pullup resistance selection +// 00: disable pullup resistance +// 01: enable 56K pullup resistance for default USB power +// 10: enable 22K pullup resistance for 1.5A USB power +// 11: enable 10K pullup resistance for 3A USB power +SFR(UDEV_CTRL, 0xD1); // USB device physical port control +#define bUD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define bUD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define bUD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define bUD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed +#define bUD_GP_BIT 0x02 // general purpose bit +#define bUD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable +//sfr UHOST_CTRL = 0xD1; // USB host physical port control +#define UHOST_CTRL UDEV_CTRL +#define bUH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define bUH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define bUH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define bUH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed +#define bUH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset +#define bUH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached +SFR(UEP1_CTRL, 0xD2); // endpoint 1 control +#define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 +#define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 +#define bUEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT) +#define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT) +#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define UEP_R_RES_ACK 0x00 +#define UEP_R_RES_TOUT 0x04 +#define UEP_R_RES_NAK 0x08 +#define UEP_R_RES_STALL 0x0C +// bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receiving (OUT) +// 00: ACK (ready) +// 01: no response, time out to host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +#define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN) +#define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN) +#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define UEP_T_RES_ACK 0x00 +#define UEP_T_RES_TOUT 0x01 +#define UEP_T_RES_NAK 0x02 +#define UEP_T_RES_STALL 0x03 +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// 00: DATA0 or DATA1 then expecting ACK (ready) +// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmittal length +SFR(UEP2_CTRL, 0xD4); // endpoint 2 control +SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmittal length +SFR(UEP3_CTRL, 0xD6); // endpoint 3 control +SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmittal length +SFR(USB_INT_FG, 0xD8); // USB interrupt flag + SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received + SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK + SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status + SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear + SBIT(UIF_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, direct bit address clear or write 1 to clear + SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear + SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear + SBIT(UIF_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear + SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, direct bit address clear or write 1 to clear +SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status +#define bUIS_IS_NAK 0x80 // ReadOnly: indicate current USB transfer is NAK received for USB device mode +#define bUIS_TOG_OK 0x40 // ReadOnly: indicate current USB transfer toggle is OK +#define bUIS_TOKEN1 0x20 // ReadOnly: current token PID code bit 1 received for USB device mode +#define bUIS_TOKEN0 0x10 // ReadOnly: current token PID code bit 0 received for USB device mode +#define MASK_UIS_TOKEN 0x30 // ReadOnly: bit mask of current token PID code received for USB device mode +#define UIS_TOKEN_OUT 0x00 +#define UIS_TOKEN_SOF 0x10 +#define UIS_TOKEN_IN 0x20 +#define UIS_TOKEN_SETUP 0x30 +// bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received for USB device mode +// 00: OUT token PID received +// 01: SOF token PID received +// 10: IN token PID received +// 11: SETUP token PID received +#define MASK_UIS_ENDP 0x0F // ReadOnly: bit mask of current transfer endpoint number for USB device mode +#define MASK_UIS_H_RES 0x0F // ReadOnly: bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received +SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status +#define bUMS_SOF_PRES 0x80 // ReadOnly: indicate host SOF timer presage status +#define bUMS_SOF_ACT 0x40 // ReadOnly: indicate host SOF timer action status for USB host +#define bUMS_SIE_FREE 0x20 // ReadOnly: indicate USB SIE free status +#define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receiving FIFO ready status (not empty) +#define bUMS_BUS_RESET 0x08 // ReadOnly: indicate USB bus reset status +#define bUMS_SUSPEND 0x04 // ReadOnly: indicate USB suspend status +#define bUMS_DM_LEVEL 0x02 // ReadOnly: indicate UDM level saved at device attached to USB host +#define bUMS_DEV_ATTACH 0x01 // ReadOnly: indicate device attached status on USB host +SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receiving length +SFR(UEP0_CTRL, 0xDC); // endpoint 0 control +SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmittal length +SFR(UEP4_CTRL, 0xDE); // endpoint 4 control +SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmittal length +SFR(USB_INT_EN, 0xE1); // USB interrupt enable +#define bUIE_DEV_SOF 0x80 // enable interrupt for SOF received for USB device mode +#define bUIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode +#define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow +#define bUIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode +#define bUIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event +#define bUIE_TRANSFER 0x02 // enable interrupt for USB transfer completion +#define bUIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode +#define bUIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode +SFR(USB_CTRL, 0xE2); // USB base control +#define bUC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode +#define bUC_LOW_SPEED 0x40 // enable USB low speed: 0=full speed, 1=low speed +#define bUC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable +#define bUC_SYS_CTRL1 0x20 // USB system control high bit +#define bUC_SYS_CTRL0 0x10 // USB system control low bit +#define MASK_UC_SYS_CTRL 0x30 // bit mask of USB system control +// bUC_HOST_MODE & bUC_SYS_CTRL1 & bUC_SYS_CTRL0: USB system control +// 0 00: disable USB device and disable internal pullup resistance +// 0 01: enable USB device and disable internal pullup resistance, need external pullup resistance +// 0 1x: enable USB device and enable internal pullup resistance +// 1 00: enable USB host and normal status +// 1 01: enable USB host and force UDP/UDM output SE0 state +// 1 10: enable USB host and force UDP/UDM output J state +// 1 11: enable USB host and force UDP/UDM output resume or K state +#define bUC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode during interrupt flag UIF_TRANSFER valid +#define bUC_RESET_SIE 0x04 // force reset USB SIE, need software clear +#define bUC_CLR_ALL 0x02 // force clear FIFO and count of USB +#define bUC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB +SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address +#define bUDA_GP_BIT 0x80 // general purpose bit +#define MASK_USB_ADDR 0x7F // bit mask for USB device address +SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian +SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte +SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte +SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian +SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte +SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte +SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode +#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT) +#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN) +#define bUEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1 +// bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA +// 0 0 x: disable endpoint and disable buffer +// 1 0 0: 64 bytes buffer for receiving (OUT endpoint) +// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes +// 0 1 0: 64 bytes buffer for transmittal (IN endpoint) +// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes +// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes +// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes +#define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT) +#define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN) +// bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA +// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes +// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes +// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes +SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode +#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT) +#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN) +#define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3 +#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT) +#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN) +#define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2 +SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian +SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte +SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte +SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian +SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte +SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte +//sfr UH_SETUP = 0xD2; // host aux setup +#define UH_SETUP UEP1_CTRL +#define bUH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub +#define bUH_SOF_EN 0x40 // USB host automatic SOF enable +//sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control +#define UH_RX_CTRL UEP2_CTRL +#define bUH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1 +#define bUH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define bUH_R_RES 0x04 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions +//sfr UH_EP_PID = 0xD5; // host endpoint and token PID, lower 4 bits for endpoint number, upper 4 bits for token PID +#define UH_EP_PID UEP2_T_LEN +#define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer +#define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer +//sfr UH_TX_CTRL = 0xD6; // host transmittal endpoint control +#define UH_TX_CTRL UEP3_CTRL +#define bUH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1 +#define bUH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle +#define bUH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions +//sfr UH_TX_LEN = 0xD7; // host transmittal endpoint transmittal length +#define UH_TX_LEN UEP3_T_LEN +//sfr UH_EP_MOD = 0xEB; // host endpoint mode +#define UH_EP_MOD UEP2_3_MOD +#define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal +#define bUH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint +// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for transmittal (OUT endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes +#define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving +#define bUH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint +// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA +// 0 x: disable endpoint and disable buffer +// 1 0: 64 bytes buffer for receiving (IN endpoint) +// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes +//sfr16 UH_RX_DMA = 0xE4; // host rx endpoint buffer start address, little-endian +#define UH_RX_DMA UEP2_DMA +//sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte +#define UH_RX_DMA_L UEP2_DMA_L +//sfr UH_RX_DMA_H = 0xE5; // host rx endpoint buffer start address high byte +#define UH_RX_DMA_H UEP2_DMA_H +//sfr16 UH_TX_DMA = 0xE6; // host tx endpoint buffer start address, little-endian +#define UH_TX_DMA UEP3_DMA +//sfr UH_TX_DMA_L = 0xE6; // host tx endpoint buffer start address low byte +#define UH_TX_DMA_L UEP3_DMA_L +//sfr UH_TX_DMA_H = 0xE7; // host tx endpoint buffer start address high byte +#define UH_TX_DMA_H UEP3_DMA_H + +/*----- XDATA: xRAM ------------------------------------------*/ + +#define XDATA_RAM_SIZE 0x0400 // size of expanded xRAM, xdata SRAM embedded chip + +/*----- Reference Information --------------------------------------------*/ +#define ID_CH554 0x54 // chip ID + +/* Interrupt routine address and interrupt number */ +#define INT_ADDR_INT0 0x0003 // interrupt vector address for INT0 +#define INT_ADDR_TMR0 0x000B // interrupt vector address for timer0 +#define INT_ADDR_INT1 0x0013 // interrupt vector address for INT1 +#define INT_ADDR_TMR1 0x001B // interrupt vector address for timer1 +#define INT_ADDR_UART0 0x0023 // interrupt vector address for UART0 +#define INT_ADDR_TMR2 0x002B // interrupt vector address for timer2 +#define INT_ADDR_SPI0 0x0033 // interrupt vector address for SPI0 +#define INT_ADDR_TKEY 0x003B // interrupt vector address for touch-key timer +#define INT_ADDR_USB 0x0043 // interrupt vector address for USB +#define INT_ADDR_ADC 0x004B // interrupt vector address for ADC +#define INT_ADDR_UART1 0x0053 // interrupt vector address for UART1 +#define INT_ADDR_PWMX 0x005B // interrupt vector address for PWM1/2 +#define INT_ADDR_GPIO 0x0063 // interrupt vector address for GPIO +#define INT_ADDR_WDOG 0x006B // interrupt vector address for watch-dog timer +#define INT_NO_INT0 0 // interrupt number for INT0 +#define INT_NO_TMR0 1 // interrupt number for timer0 +#define INT_NO_INT1 2 // interrupt number for INT1 +#define INT_NO_TMR1 3 // interrupt number for timer1 +#define INT_NO_UART0 4 // interrupt number for UART0 +#define INT_NO_TMR2 5 // interrupt number for timer2 +#define INT_NO_SPI0 6 // interrupt number for SPI0 +#define INT_NO_TKEY 7 // interrupt number for touch-key timer +#define INT_NO_USB 8 // interrupt number for USB +#define INT_NO_ADC 9 // interrupt number for ADC +#define INT_NO_UART1 10 // interrupt number for UART1 +#define INT_NO_PWMX 11 // interrupt number for PWM1/2 +#define INT_NO_GPIO 12 // interrupt number for GPIO +#define INT_NO_WDOG 13 // interrupt number for watch-dog timer + +/* Special Program Space */ +#define DATA_FLASH_ADDR 0xC000 // start address of Data-Flash +#define BOOT_LOAD_ADDR 0x3800 // start address of boot loader program +#define ROM_CFG_ADDR 0x3FF8 // chip configuration information address +#define ROM_CHIP_ID_HX 0x3FFA // chip ID number highest byte (only low byte valid) +#define ROM_CHIP_ID_LO 0x3FFC // chip ID number low word +#define ROM_CHIP_ID_HI 0x3FFE // chip ID number high word + +/* +New Instruction: MOVX @DPTR1,A +Instruction Code: 0xA5 +Instruction Cycle: 1 +Instruction Operation: + step-1. write ACC @DPTR1 into xdata SRAM embedded chip + step-2. increase DPTR1 +ASM example: + INC XBUS_AUX + MOV DPTR,#TARGET_ADDR ;DPTR1 + DEC XBUS_AUX + MOV DPTR,#SOURCE_ADDR ;DPTR0 + MOV R7,#xxH + LOOP: MOVX A,@DPTR ;DPTR0 + INC DPTR ;DPTR0, if need + .DB 0xA5 ;MOVX @DPTR1,A & INC DPTR1 + DJNZ R7,LOOP +*/ + +#endif // __CH554_H__ diff --git a/Software/examples/WS2812/src/config.h b/Software/examples/WS2812/src/config.h new file mode 100644 index 0000000..1103874 --- /dev/null +++ b/Software/examples/WS2812/src/config.h @@ -0,0 +1,12 @@ +// =================================================================================== +// User Configurations for CH552E USB MacroPad Mini +// =================================================================================== + +#pragma once + +// Pin definitions +// + +// NeoPixel configuration +#define NEO_GRB // type of pixel: NEO_GRB or NEO_RGB + diff --git a/Software/examples/WS2812/src/delay.c b/Software/examples/WS2812/src/delay.c new file mode 100644 index 0000000..8d68aff --- /dev/null +++ b/Software/examples/WS2812/src/delay.c @@ -0,0 +1,86 @@ +// =================================================================================== +// Delay Functions for CH551, CH552 and CH554 +// =================================================================================== + +#include "delay.h" +#include "ch554.h" + +// =================================================================================== +// Delay in Units of us +// =================================================================================== +void DLY_us(uint16_t n) { // delay in us + #ifdef F_CPU + #if F_CPU <= 6000000 + n >>= 2; + #endif + #if F_CPU <= 3000000 + n >>= 2; + #endif + #if F_CPU <= 750000 + n >>= 4; + #endif + #endif + + while(n) { // total = 12~13 Fsys cycles, 1uS @Fsys=12MHz + SAFE_MOD++; // 2 Fsys cycles, for higher Fsys, add operation here + #ifdef F_CPU + #if F_CPU >= 14000000 + SAFE_MOD++; + #endif + #if F_CPU >= 16000000 + SAFE_MOD++; + #endif + #if F_CPU >= 18000000 + SAFE_MOD++; + #endif + #if F_CPU >= 20000000 + SAFE_MOD++; + #endif + #if F_CPU >= 22000000 + SAFE_MOD++; + #endif + #if F_CPU >= 24000000 + SAFE_MOD++; + #endif + #if F_CPU >= 26000000 + SAFE_MOD++; + #endif + #if F_CPU >= 28000000 + SAFE_MOD++; + #endif + #if F_CPU >= 30000000 + SAFE_MOD++; + #endif + #if F_CPU >= 32000000 + SAFE_MOD++; + #endif + #endif + n--; + } +} + +// =================================================================================== +// Delay in Units of ms +// =================================================================================== +void DLY_ms(uint16_t n) { // delay in ms + while(n) { + DLY_us(1000); + n--; + } +} + +// =================================================================================== +// Delay 20+4*(n-1) Clock Cycles +// =================================================================================== +#pragma callee_saves _delay_more_cycles +void _delay_more_cycles (uint8_t n) __naked { + n; // stop unreferenced arg warning + __asm + .even ; make predictable cycles for jumps + push ar7 ; 2 cycles + mov r7, dpl ; 2 cycles + djnz r7, .+0 ; 2/4 cycles + pop ar7 ; 2 cycles + ret ; 4|5 cycles + __endasm; +} diff --git a/Software/examples/WS2812/src/delay.h b/Software/examples/WS2812/src/delay.h new file mode 100644 index 0000000..d665553 --- /dev/null +++ b/Software/examples/WS2812/src/delay.h @@ -0,0 +1,161 @@ +// =================================================================================== +// Delay Functions for CH551, CH552 and CH554 +// =================================================================================== + +#pragma once +#include + +void DLY_us(uint16_t n); // delay in units of us +void DLY_ms(uint16_t n); // delay in units of ms + +// Delay clock cycles (max. 1039) +// (need to find a smarter way...) +#define DLY_cycles(n) \ + (n == 1 ? (_delay_cycles_1()) : \ + (n == 2 ? (_delay_cycles_2()) : \ + (n == 3 ? (_delay_cycles_3()) : \ + (n == 4 ? (_delay_cycles_4()) : \ + (n == 5 ? (_delay_cycles_5()) : \ + (n == 6 ? (_delay_cycles_6()) : \ + (n == 7 ? (_delay_cycles_7()) : \ + (n == 8 ? (_delay_cycles_8()) : \ + (n == 9 ? (_delay_cycles_9()) : \ + (n == 10 ? (_delay_cycles_10()) : \ + (n == 11 ? (_delay_cycles_11()) : \ + (n == 12 ? (_delay_cycles_12()) : \ + (n == 13 ? (_delay_cycles_13()) : \ + (n == 14 ? (_delay_cycles_14()) : \ + (n == 15 ? (_delay_cycles_15()) : \ + (n == 16 ? (_delay_cycles_16()) : \ + (n == 17 ? (_delay_cycles_17()) : \ + (n == 18 ? (_delay_cycles_18()) : \ + (n == 19 ? (_delay_cycles_19()) : \ + ((n-20)%4 == 0 ? _delay_more_cycles(((n-20)/4)+1) : \ + ((n-20)%4 == 1 ? _delay_more_cycles_1(((n-20)/4)+1) : \ + ((n-20)%4 == 2 ? _delay_more_cycles_2(((n-20)/4)+1) : \ + ((n-20)%4 == 3 ? _delay_more_cycles_3(((n-20)/4)+1) : \ +(0)))))))))))))))))))))))) + +#define _delay_less_cycles(n) _delay_cycles_##n() + +void _delay_more_cycles(uint8_t n); + +inline void _delay_cycles_1(void) { + __asm__("nop"); +} + +inline void _delay_cycles_2(void) { + _delay_cycles_1(); + _delay_cycles_1(); +} + +inline void _delay_cycles_3(void) { + _delay_cycles_2(); + _delay_cycles_1(); +} + +inline void _delay_cycles_4(void) { + _delay_cycles_3(); + _delay_cycles_1(); +} + +inline void _delay_cycles_5(void) { + _delay_cycles_4(); + _delay_cycles_1(); +} + +inline void _delay_cycles_6(void) { + _delay_cycles_5(); + _delay_cycles_1(); +} + +inline void _delay_cycles_7(void) { + _delay_cycles_6(); + _delay_cycles_1(); +} + +inline void _delay_cycles_8(void) { + _delay_cycles_7(); + _delay_cycles_1(); +} + +inline void _delay_cycles_9(void) { + _delay_cycles_8(); + _delay_cycles_1(); +} + +inline void _delay_cycles_10(void) { + _delay_cycles_9(); + _delay_cycles_1(); +} + +inline void _delay_cycles_11(void) { + _delay_cycles_10(); + _delay_cycles_1(); +} + +inline void _delay_cycles_12(void) { + __asm + push a + push b + div ab + pop b + pop a + __endasm; +} + +inline void _delay_cycles_13(void) { + _delay_cycles_12(); + _delay_cycles_1(); +} + +inline void _delay_cycles_14(void) { + _delay_cycles_12(); + _delay_cycles_2(); +} + +inline void _delay_cycles_15(void) { + _delay_cycles_12(); + _delay_cycles_3(); +} + +inline void _delay_cycles_16(void) { + __asm + push a + push b + div ab + div ab + pop b + pop a + __endasm; +} + +inline void _delay_cycles_17(void) { + _delay_cycles_16(); + _delay_cycles_1(); +} + +inline void _delay_cycles_18(void) { + _delay_cycles_16(); + _delay_cycles_2(); +} + +inline void _delay_cycles_19(void) { + _delay_cycles_16(); + _delay_cycles_3(); +} + +inline void _delay_more_cycles_1(uint8_t n) { + _delay_more_cycles(n); + _delay_cycles_1(); +} + +inline void _delay_more_cycles_2(uint8_t n) { + _delay_more_cycles(n); + _delay_cycles_2(); +} + +inline void _delay_more_cycles_3(uint8_t n) { + _delay_more_cycles(n); + _delay_cycles_3(); +} diff --git a/Software/examples/WS2812/src/gpio.h b/Software/examples/WS2812/src/gpio.h new file mode 100644 index 0000000..0e5036d --- /dev/null +++ b/Software/examples/WS2812/src/gpio.h @@ -0,0 +1,288 @@ +// =================================================================================== +// Basic GPIO, PWM and ADC Functions for CH551, CH552 and CH554 * v1.4 * +// =================================================================================== +// +// Pins must be defined as P10, P11, P12, etc. - e.g.: +// #define PIN_LED P33 // LED on pin P3.3 +// +// Functions available: +// -------------------- +// PIN_input(PIN) set PIN as INPUT (high impedance, no pullup) +// PIN_input_PU(PIN) set PIN as INPUT with internal PULLUP +// PIN_output(PIN) set PIN as OUTPUT (push-pull) +// PIN_output_OD(PIN) set PIN as OUTPUT (open-drain) +// +// PIN_low(PIN) set PIN output value to LOW +// PIN_high(PIN) set PIN output value to HIGH +// PIN_toggle(PIN) TOGGLE PIN output value +// PIN_read(PIN) read PIN input value +// PIN_write(PIN, val) write PIN output value (0 = LOW / 1 = HIGH) +// +// PIN_asm(PIN) convert PIN for inline assembly: setb PIN_asm(PIN_LED) +// PIN_set(PIN) convert PIN for direct manipulation: PIN_set(PIN_LED) = 1; +// +// PIN_WAKE_enable(PIN) enable wake-up from sleep by PIN low (P13, P14, P15 only) +// PIN_WAKE_disable(PIN) disable wake-up from sleep by PIN low +// +// PWM_start(PIN) start PWM output on PIN, can be (P15 or P30) and (P34 or P31) +// PWM_stop(PIN) stop PWM output on PIN +// PWM_write(PIN, val) set PWM output active level duty cycle on PIN +// +// PWM_pol_normal(PIN) set normal PWM polarity on PIN (default low and active high) +// PWM_pol_reverse(PIN) set reverse PWM polarity on PIN (default high and active low) +// PWM_set_freq(FREQ) set global PWM frequency (in Hertz) +// +// ADC_enable() enable ADC +// ADC_disable() disable ADC +// ADC_fast() set ADC fast mode ( 96 clock cycles per sample, less accurate) +// ADC_slow() set ADC slow mode (384 clock cycles per sample, more accurate) +// ADC_input(PIN) set ADC input pin (P11, P14, P15, P32 only) +// ADC_read() sample and read ADC value (0..255) +// +// CMP_enable() enable comparator +// CMP_disable() disable comparator +// CMP_positive(PIN) set CMP non-inverting input pin (P11, P14, P15, P32 only) +// CMP_negative(PIN) set CMP inverting input pin (P14, P32 only) +// CMP_read() read CMP output (0: pos < neg, 1: pos > neg) +// +// Notes: +// ------ +// Pins used for PWM should be set as OUTPUT beforehand. +// Pins used for ADC or CMP must have been set as INPUT (high impedance) beforehand. +// +// 2022 by Stefan Wagner: https://github.com/wagiminator + +#pragma once +#include +#include "ch554.h" + +// =================================================================================== +// Enumerate pin designators (use these designators to define pins) +// =================================================================================== + +enum{P10, P11, P12, P13, P14, P15, P16, P17, P30, P31, P32, P33, P34, P35, P36, P37}; + +// =================================================================================== +// Helper Defines (these are for internal use only) +// =================================================================================== + +// Define pins for direct bit manipulation +SBIT(PP10, 0x90, 0); +SBIT(PP11, 0x90, 1); +SBIT(PP12, 0x90, 2); +SBIT(PP13, 0x90, 3); +SBIT(PP14, 0x90, 4); +SBIT(PP15, 0x90, 5); +SBIT(PP16, 0x90, 6); +SBIT(PP17, 0x90, 7); +SBIT(PP30, 0xB0, 0); +SBIT(PP31, 0xB0, 1); +SBIT(PP32, 0xB0, 2); +SBIT(PP33, 0xB0, 3); +SBIT(PP34, 0xB0, 4); +SBIT(PP35, 0xB0, 5); +SBIT(PP36, 0xB0, 6); +SBIT(PP37, 0xB0, 7); + +// 2nd-stage glue defines +#define PIN_h_a(PIN) _P##PIN +#define PIN_h_s(PIN) P##PIN + +#define PORT_h_i(PORT, PIN) (P##PORT##_DIR_PU &= ~(1<=P10)&&(PIN<=P17) ? (P1_DIR_PU &= ~(1<<(PIN&7)), P1_MOD_OC &= ~(1<<(PIN&7))) : \ + ((PIN>=P30)&&(PIN<=P37) ? (P3_DIR_PU &= ~(1<<(PIN&7)), P3_MOD_OC &= ~(1<<(PIN&7))) : \ +(0))) + +// =================================================================================== +// Set pin as INPUT with internal PULLUP resistor (also open-drain output, +// when output changes from LOW to HIGH, it will drive HIGH for 2 clock cycles) +// =================================================================================== +#define PIN_input_PU(PIN) \ + ((PIN>=P10)&&(PIN<=P17) ? (P1_MOD_OC |= (1<<(PIN&7)), P1_DIR_PU |= (1<<(PIN&7))) : \ + ((PIN>=P30)&&(PIN<=P37) ? (P3_MOD_OC |= (1<<(PIN&7)), P3_DIR_PU |= (1<<(PIN&7))) : \ +(0))) + +// =================================================================================== +// Set pin as OUTPUT (push-pull) +// =================================================================================== +#define PIN_output(PIN) \ + ((PIN>=P10)&&(PIN<=P17) ? (P1_MOD_OC &= ~(1<<(PIN&7)), P1_DIR_PU |= (1<<(PIN&7))) : \ + ((PIN>=P30)&&(PIN<=P37) ? (P3_MOD_OC &= ~(1<<(PIN&7)), P3_DIR_PU |= (1<<(PIN&7))) : \ +(0))) + +// =================================================================================== +// Set pin as OPEN-DRAIN OUTPUT (also high-impedance input, no pullup) +// =================================================================================== +#define PIN_output_OD(PIN) \ + ((PIN>=P10)&&(PIN<=P17) ? (P1_MOD_OC |= (1<<(PIN&7)), P1_DIR_PU &= ~(1<<(PIN&7))) : \ + ((PIN>=P30)&&(PIN<=P37) ? (P3_MOD_OC |= (1<<(PIN&7)), P3_DIR_PU &= ~(1<<(PIN&7))) : \ +(0))) + +// =================================================================================== +// Pin manipulation macros +// =================================================================================== +#define PIN_low(PIN) PIN_h_s(PIN) = 0 // set pin to LOW +#define PIN_high(PIN) PIN_h_s(PIN) = 1 // set pin to HIGH +#define PIN_toggle(PIN) PIN_h_s(PIN) = !PIN_h_s(PIN) // TOGGLE pin +#define PIN_read(PIN) (PIN_h_s(PIN)) // READ pin +#define PIN_write(PIN, val) PIN_h_s(PIN) = val // WRITE pin value + +// =================================================================================== +// (PORT, PIN) manipulation macros +// =================================================================================== +#define PORT_input(PORT, PIN) PORT_h_i(PORT, PIN) // set pin as INPUT +#define PORT_input_PU(PORT, PIN) PORT_h_iP(PORT, PIN) // set pin as INPUT PULLUP +#define PORT_output(PORT, PIN) PORT_h_o(PORT, PIN) // set pin as OUTPUT +#define PORT_output_OD(PORT, PIN) PORT_h_oO(PORT, PIN) // set pin as OUTPUT OPEN-DRAIN + +#define PORT_low(PORT, PIN) PORT_h_l(PORT, PIN) // set pin to LOW +#define PORT_high(PORT, PIN) PORT_h_h(PORT, PIN) // set pin to HIGH +#define PORT_toggle(PORT, PIN) PORT_h_t(PORT, PIN) // TOGGLE pin +#define PORT_read(PORT, PIN) PORT_h_r(PORT, PIN) // READ pin +#define PORT_write(PORT,PIN,val) PORT_h_w(PORT, PIN, val) // WRITE pin value + +// =================================================================================== +// Convert pin for inline assembly and direct manipulation +// =================================================================================== +#define PIN_asm(PIN) PIN_h_a(PIN) +#define PIN_set(PIN) PIN_h_s(PIN) + +// =================================================================================== +// Enable/disable WAKE-up from sleep by pin LOW (P13, P14, P15 only) +// =================================================================================== +#define WAKE_PIN_enable(PIN) \ + ((PIN == P13) ? (WAKE_CTRL |= bWAK_P1_3_LO) : \ + ((PIN == P14) ? (WAKE_CTRL |= bWAK_P1_4_LO) : \ + ((PIN == P15) ? (WAKE_CTRL |= bWAK_P1_5_LO) : \ +(0))))) + +#define WAKE_PIN_disable(PIN) \ + ((PIN == P13) ? (WAKE_CTRL &= ~bWAK_P1_3_LO) : \ + ((PIN == P14) ? (WAKE_CTRL &= ~bWAK_P1_4_LO) : \ + ((PIN == P15) ? (WAKE_CTRL &= ~bWAK_P1_5_LO) : \ +(0))))) + +// =================================================================================== +// Start PWM on pin, must be a PWM-capable pin: (P15 or P30) and (P34 or P31) +// =================================================================================== +#define PWM_start(PIN) \ + ((PIN == P15) ? (PWM_CTRL &= ~bPWM_CLR_ALL, PIN_FUNC &= ~bPWM1_PIN_X, PWM_CTRL |= bPWM1_OUT_EN) : \ + ((PIN == P34) ? (PWM_CTRL &= ~bPWM_CLR_ALL, PIN_FUNC &= ~bPWM2_PIN_X, PWM_CTRL |= bPWM2_OUT_EN) : \ + ((PIN == P30) ? (PWM_CTRL &= ~bPWM_CLR_ALL, PIN_FUNC |= bPWM1_PIN_X, PWM_CTRL |= bPWM1_OUT_EN) : \ + ((PIN == P31) ? (PWM_CTRL &= ~bPWM_CLR_ALL, PIN_FUNC |= bPWM2_PIN_X, PWM_CTRL |= bPWM2_OUT_EN) : \ +(0))))) + +// =================================================================================== +// Set PWM output active level duty cycle on pin +// =================================================================================== +#define PWM_write(PIN, val) \ + ((PIN == P15) ? (PWM_DATA1 = val) : \ + ((PIN == P34) ? (PWM_DATA2 = val) : \ + ((PIN == P30) ? (PWM_DATA1 = val) : \ + ((PIN == P31) ? (PWM_DATA2 = val) : \ +(0))))) + +// =================================================================================== +// Stop PWM on pin +// =================================================================================== +#define PWM_stop(PIN) \ + ((PIN == P15) ? (PWM_CTRL &= ~bPWM1_OUT_EN) : \ + ((PIN == P34) ? (PWM_CTRL &= ~bPWM2_OUT_EN) : \ + ((PIN == P30) ? (PWM_CTRL &= ~bPWM1_OUT_EN) : \ + ((PIN == P31) ? (PWM_CTRL &= ~bPWM2_OUT_EN) : \ +(0))))) + +// =================================================================================== +// Set normal PWM polarity on pin (default low and active high) +// =================================================================================== +#define PWM_pol_normal(PIN) \ + ((PIN == P15) ? (PWM_CTRL &= ~bPWM1_POLAR) : \ + ((PIN == P34) ? (PWM_CTRL &= ~bPWM2_POLAR) : \ + ((PIN == P30) ? (PWM_CTRL &= ~bPWM1_POLAR) : \ + ((PIN == P31) ? (PWM_CTRL &= ~bPWM2_POLAR) : \ +(0))))) + +// =================================================================================== +// Set reverse PWM polarity on pin (default high and active low) +// =================================================================================== +#define PWM_pol_reverse(PIN) \ + ((PIN == P15) ? (PWM_CTRL |= bPWM1_POLAR) : \ + ((PIN == P34) ? (PWM_CTRL |= bPWM2_POLAR) : \ + ((PIN == P30) ? (PWM_CTRL |= bPWM1_POLAR) : \ + ((PIN == P31) ? (PWM_CTRL |= bPWM2_POLAR) : \ +(0))))) + +// =================================================================================== +// Set global PWM frequency (in Hertz, range: F_CPU/65536 - F_CPU/256) +// =================================================================================== +#define PWM_set_freq(FREQ) \ + (((FREQ) >= F_CPU / 256) ? (PWM_CK_SE = 0) : \ + (((F_CPU / 256 / (FREQ) - 1) > 255) ? (PWM_CK_SE = 255) : \ + (PWM_CK_SE = (uint8_t)(F_CPU / 256 / (FREQ) - 1)) \ +)) + +// =================================================================================== +// Pin to ADC channel conversion (P11, P14, P15, P32 only) +// =================================================================================== +#define ADC_channel(PIN) \ + ((PIN == P11) ? (0) : \ + ((PIN == P14) ? (1) : \ + ((PIN == P15) ? (2) : \ + ((PIN == P32) ? (3) : \ +(0))))) + +// =================================================================================== +// ADC functions (P11, P14, P15, P32 only) +// =================================================================================== +#define ADC_enable() ADC_CFG |= bADC_EN +#define ADC_disable() ADC_CFG &= ~bADC_EN +#define ADC_fast() ADC_CFG |= bADC_CLK +#define ADC_slow() ADC_CFG &= ~bADC_CLK + +#define ADC_input(PIN) \ + ((PIN == P11) ? (ADC_CHAN1 = 0, ADC_CHAN0 = 0) : \ + ((PIN == P14) ? (ADC_CHAN1 = 0, ADC_CHAN0 = 1) : \ + ((PIN == P15) ? (ADC_CHAN1 = 1, ADC_CHAN0 = 0) : \ + ((PIN == P32) ? (ADC_CHAN1 = 1, ADC_CHAN0 = 1) : \ +(0))))) + +inline uint8_t ADC_read(void) { + ADC_START = 1; + while(ADC_START); + return ADC_DATA; +} + +// =================================================================================== +// Pin to comparator inverting input conversion (P14, P32 only) +// =================================================================================== +#define CMP_channel(PIN) \ + ((PIN == P14) ? (0) : \ + ((PIN == P32) ? (1) : \ +(0))) + +// =================================================================================== +// Comparator functions (positive: P11, P14, P15, P32, negative: P14, P32 only) +// =================================================================================== +#define CMP_enable() ADC_CFG |= bCMP_EN +#define CMP_disable() ADC_CFG &= ~bCMP_EN +#define CMP_read() (CMPO) + +#define CMP_positive(PIN) ADC_input(PIN) +#define CMP_negative(PIN) \ + ((PIN == P14) ? (CMP_CHAN = 0) : \ + ((PIN == P32) ? (CMP_CHAN = 1) : \ +(0))) diff --git a/Software/examples/WS2812/src/neo.c b/Software/examples/WS2812/src/neo.c new file mode 100644 index 0000000..2222222 --- /dev/null +++ b/Software/examples/WS2812/src/neo.c @@ -0,0 +1,125 @@ +// =================================================================================== +// NeoPixel (Addressable LED) Functions for CH551, CH552 and CH554 * v1.1 * +// =================================================================================== +// +// Basic control functions for 800kHz addressable LEDs (NeoPixel). A simplified +// protocol is used which should work with most LEDs. +// +// The following must be defined in config.h: +// PIN_NEO - pin connected to DATA-IN of the pixel strip (via a ~330 ohms resistor). +// NEO_GRB - type of pixel: NEO_GRB or NEO_RGB +// System clock frequency must be at least 6 MHz. +// +// Further information: https://github.com/wagiminator/ATtiny13-NeoController +// 2023 by Stefan Wagner: https://github.com/wagiminator + +// =================================================================================== +// Libraries, Variables and Constants +// =================================================================================== +#include "neo.h" + +#define NEOPIN PIN_asm(PIN_NEO) // convert PIN_NEO for inline assembly + +// =================================================================================== +// Protocol Delays +// =================================================================================== +// There are three essential conditions: +// - T0H (HIGH-time for "0"-bit) must be max. 500ns +// - T1H (HIGH-time for "1"-bit) must be min. 625ns +// - TCT (total clock time) must be min. 1150ns +// The bit transmission loop takes 11 clock cycles. +#if F_CPU == 24000000 // 24 MHz system clock + #define T1H_DELAY \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop // 15 - 4 = 11 clock cycles for min 625ns + #define TCT_DELAY \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop // 28 - 11 - 11 = 6 clock cycles for min 1150ns +#elif F_CPU == 16000000 // 16 MHz system clock + #define T1H_DELAY \ + nop \ + nop \ + nop \ + nop \ + nop \ + nop // 10 - 4 = 6 clock cycles for min 625ns + #define TCT_DELAY \ + nop \ + nop // 19 - 6 - 11 = 2 clock cycles for min 1150ns +#elif F_CPU == 12000000 // 12 MHz system clock + #define T1H_DELAY \ + nop \ + nop \ + nop \ + nop // 8 - 4 = 4 clock cycles for min 625ns + #define TCT_DELAY // 14 - 4 - 11 < 0 clock cycles for min 1150ns +#elif F_CPU == 6000000 // 13 MHz system clock + #define T1H_DELAY // 4 - 4 = 0 clock cycles for min 625ns + #define TCT_DELAY // 7 - 0 - 11 < 0 clock cycles for min 1150ns +#else + #error Unsupported system clock frequency for NeoPixels! +#endif + +// =================================================================================== +// Send a Data Byte to the Pixels String +// =================================================================================== +// This is the most time sensitive part. Outside of the function, it must be +// ensured that interrupts are disabled and that the time between the +// transmission of the individual bytes is less than the pixel's latch time. +void NEO_sendByte(uint8_t data) { + data; // stop unreferenced argument warning + __asm + .even + mov r7, #8 ; 2 CLK - 8 bits to transfer + xch a, dpl ; 2 CLK - data byte -> accu + 01$: + rlc a ; 1 CLK - data bit -> carry (MSB first) + setb NEOPIN ; 2 CLK - NEO pin HIGH + mov NEOPIN, c ; 2 CLK - "0"-bit? -> NEO pin LOW now + T1H_DELAY ; x CLK - TH1 delay + clr NEOPIN ; 2 CLK - "1"-bit? -> NEO pin LOW a little later + TCT_DELAY ; y CLK - TCT delay + djnz r7, 01$ ; 2/4|5|6 CLK - repeat for all bits + __endasm; +} + +// =================================================================================== +// Write Color to a Single Pixel +// =================================================================================== +void NEO_writeColor(uint8_t r, uint8_t g, uint8_t b) { + #if defined (NEO_GRB) + NEO_sendByte(g); NEO_sendByte(r); NEO_sendByte(b); + #elif defined (NEO_RGB) + NEO_sendByte(r); NEO_sendByte(g); NEO_sendByte(b); + #else + #error Wrong or missing NeoPixel type definition! + #endif +} + +// =================================================================================== +// Write Hue Value (0..191) and Brightness (0..2) to a Single Pixel +// =================================================================================== +void NEO_writeHue(uint8_t hue, uint8_t bright) { + uint8_t phase = hue >> 6; + uint8_t step = (hue & 63) << bright; + uint8_t nstep = (63 << bright) - step; + switch(phase) { + case 0: NEO_writeColor(nstep, step, 0); break; + case 1: NEO_writeColor( 0, nstep, step); break; + case 2: NEO_writeColor( step, 0, nstep); break; + default: break; + } +} diff --git a/Software/examples/WS2812/src/neo.h b/Software/examples/WS2812/src/neo.h new file mode 100644 index 0000000..7713145 --- /dev/null +++ b/Software/examples/WS2812/src/neo.h @@ -0,0 +1,27 @@ +// =================================================================================== +// NeoPixel (Addressable LED) Functions for CH551, CH552 and CH554 * v1.1 * +// =================================================================================== +// +// Basic control functions for 800kHz addressable LEDs (NeoPixel). A simplified +// protocol is used which should work with most LEDs. +// +// The following must be defined in config.h: +// PIN_NEO - pin connected to DATA-IN of the pixel strip (via a ~330 ohms resistor). +// NEO_GRB - type of pixel: NEO_GRB or NEO_RGB +// System clock frequency must be at least 6 MHz. +// +// Further information: https://github.com/wagiminator/ATtiny13-NeoController +// 2023 by Stefan Wagner: https://github.com/wagiminator + +#pragma once +#include +#include "gpio.h" +#include "delay.h" +// NeoPixel configuration +#define NEO_GRB // type of pixel: NEO_GRB or NEO_RGB +#define NEO_init() PIN_low(PIN_NEO);PIN_output(PIN_NEO) // init NeoPixels +#define NEO_latch() DLY_us(281) // latch colors + +void NEO_sendByte(uint8_t data); // send a single byte to the pixels +void NEO_writeColor(uint8_t r, uint8_t g, uint8_t b); // write color to a single pixel +void NEO_writeHue(uint8_t hue, uint8_t bright); // hue (0..191), brightness (0..2) diff --git a/Software/examples/WS2812/src/system.h b/Software/examples/WS2812/src/system.h new file mode 100644 index 0000000..166e83a --- /dev/null +++ b/Software/examples/WS2812/src/system.h @@ -0,0 +1,203 @@ +// =================================================================================== +// Basic System Functions for CH551, CH552 and CH554 * v1.3 * +// =================================================================================== +// +// Functions available: +// -------------------- +// CLK_config() set system clock frequency according to F_CPU +// CLK_external() set external crystal as clock source +// CLK_internal() set internal oscillator as clock source +// +// WDT_start() start watchdog timer with full period +// WDT_stop() stop watchdog timer +// WDT_reset() reload watchdog timer with full period +// WDT_set(time) reload watchdog timer with specified time in ms +// WDT_feed(value) reload watchdog timer with specified value +// +// BOOT_now() enter bootloader +// SLEEP_now() put device into sleep +// RST_now() perform software reset +// +// RST_keep(value) keep this value after RESET +// RST_getKeep() read the keeped value +// RST_wasWDT() check if last RESET was caused by watchdog timer +// RST_wasPIN() check if last RESET was caused by RST PIN +// RST_wasPWR() check if last RESET was caused by power-on +// RST_wasSOFT() check if last RESET was caused by software +// +// WAKE_enable(source) enable wake-up from sleep source (sources see below) +// WAKE_disable(source) disable wake-up from sleep source +// WAKE_all_disable() disable all wake-up sources +// +// WAKE_USB_enable() enable wake-up by USB event +// WAKE_RXD0_enable() enable wake-up by RXD0 low level +// WAKE_RXD1_enable() enable wake-up by RXD1 low level +// WAKE_P13_enable() enable wake-up by pin P1.3 low level +// WAKE_P14_enable() enable wake-up by pin P1.4 low level +// WAKE_P15_enable() enable wake-up by pin P1.5 low level +// WAKE_RST_enable() enable wake-up by pin RST high level +// WAKE_INT_enable() enable wake-up by pin P3.2 edge or pin P3.3 low level +// +// WAKE_USB_disable() disable wake-up by USB event +// WAKE_RXD0_disable() disable wake-up by RXD0 low level +// WAKE_RXD1_disable() disable wake-up by RXD1 low level +// WAKE_P13_disable() disable wake-up by pin P1.3 low level +// WAKE_P14_disable() disable wake-up by pin P1.4 low level +// WAKE_P15_disable() disable wake-up by pin P1.5 low level +// WAKE_RST_disable() disable wake-up by pin RST high level +// WAKE_INT_disable() disable wake-up by pin P3.2 edge or pin P3.3 low level +// +// Wake-up from SLEEP sources: +// --------------------------- +// WAKE_USB wake-up by USB event +// WAKE_RXD0 wake-up by RXD0 low level +// WAKE_RXD1 wake-up by RXD1 low level +// WAKE_P13 wake-up by pin P1.3 low level +// WAKE_P14 wake-up by pin P1.4 low level +// WAKE_P15 wake-up by pin P1.5 low level +// WAKE_RST wake-up by pin RST high level +// WAKE_INT wake-up by pin P3.2 edge or pin P3.3 low level +// +// 2023 by Stefan Wagner: https://github.com/wagiminator + +#pragma once +#include +#include "ch554.h" + +// =================================================================================== +// System Clock +// =================================================================================== +inline void CLK_config(void) { + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; // enter safe mode + + #if F_CPU == 32000000 + __asm__("orl _CLOCK_CFG, #0b00000111"); // 32MHz + #elif F_CPU == 24000000 + __asm__("anl _CLOCK_CFG, #0b11111000"); + __asm__("orl _CLOCK_CFG, #0b00000110"); // 24MHz + #elif F_CPU == 16000000 + __asm__("anl _CLOCK_CFG, #0b11111000"); + __asm__("orl _CLOCK_CFG, #0b00000101"); // 16MHz + #elif F_CPU == 12000000 + __asm__("anl _CLOCK_CFG, #0b11111000"); + __asm__("orl _CLOCK_CFG, #0b00000100"); // 12MHz + #elif F_CPU == 6000000 + __asm__("anl _CLOCK_CFG, #0b11111000"); + __asm__("orl _CLOCK_CFG, #0b00000011"); // 6MHz + #elif F_CPU == 3000000 + __asm__("anl _CLOCK_CFG, #0b11111000"); + __asm__("orl _CLOCK_CFG, #0b00000010"); // 3MHz + #elif F_CPU == 750000 + __asm__("anl _CLOCK_CFG, #0b11111000"); + __asm__("orl _CLOCK_CFG, #0b00000001"); // 750kHz + #elif F_CPU == 187500 + __asm__("anl _CLOCK_CFG, #0b11111000"); // 187.5kHz + #else + #warning F_CPU invalid or not set + #endif + + SAFE_MOD = 0x00; // terminate safe mode +} + +inline void CLK_external(void) { + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; // enter safe mode + CLOCK_CFG |= bOSC_EN_XT; // enable external crystal + CLOCK_CFG &= ~bOSC_EN_INT; // turn off internal oscillator + SAFE_MOD = 0x00; // terminate safe mode +} + +inline void CLK_inernal(void) { + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; // enter safe mode + CLOCK_CFG |= bOSC_EN_INT; // turn on internal oscillator + CLOCK_CFG &= ~bOSC_EN_XT; // disable external crystal + SAFE_MOD = 0x00; // terminate safe mode +} + +// =================================================================================== +// Watchdog Timer +// =================================================================================== +#define WDT_reset() WDOG_COUNT = 0 +#define WDT_feed(value) WDOG_COUNT = value +#define WDT_set(time) WDOG_COUNT = (uint8_t)(256 - ((F_CPU / 1000) * time / 65536)) + +inline void WDT_start(void) { + WDOG_COUNT = 0; + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; + GLOBAL_CFG |= bWDOG_EN; + SAFE_MOD = 0x00; +} + +inline void WDT_stop(void) { + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; + GLOBAL_CFG &= ~bWDOG_EN; + SAFE_MOD = 0x00; +} + +// =================================================================================== +// Reset +// =================================================================================== +#define RST_keep(value) RESET_KEEP = value +#define RST_getKeep() (RESET_KEEP) +#define RST_wasWDT() ((PCON & MASK_RST_FLAG) == RST_FLAG_WDOG) +#define RST_wasPIN() ((PCON & MASK_RST_FLAG) == RST_FLAG_PIN) +#define RST_wasPWR() ((PCON & MASK_RST_FLAG) == RST_FLAG_POR) +#define RST_wasSOFT() ((PCON & MASK_RST_FLAG) == RST_FLAG_SW) + +inline void RST_now(void) { + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; + GLOBAL_CFG |= bSW_RESET; +} + +// =================================================================================== +// Bootloader +// =================================================================================== +inline void BOOT_now(void) { + USB_CTRL = 0; + EA = 0; + TMOD = 0; + __asm + lcall #BOOT_LOAD_ADDR + __endasm; +} + +// =================================================================================== +// Sleep +// =================================================================================== +#define SLEEP_now() PCON |= PD + +#define WAKE_USB bWAK_BY_USB // wake-up by USB event +#define WAKE_RXD0 bWAK_RXD0_LO // wake-up by RXD0 low level +#define WAKE_RXD1 bWAK_RXD1_LO // wake-up by RXD1 low level +#define WAKE_P13 bWAK_P1_3_LO // wake-up by pin P1.3 low level +#define WAKE_P14 bWAK_P1_4_LO // wake-up by pin P1.4 low level +#define WAKE_P15 bWAK_P1_5_LO // wake-up by pin P1.5 low level +#define WAKE_RST bWAK_RST_HI // wake-up by pin RST high level +#define WAKE_INT bWAK_P3_2E_3L // wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level + +#define WAKE_enable(source) WAKE_CTRL |= source +#define WAKE_disable(source) WAKE_CTRL &= ~source +#define WAKE_all_disable() WAKE_CTRL = 0 + +#define WAKE_USB_enable() WAKE_CTRL |= bWAK_BY_USB +#define WAKE_RXD0_enable() WAKE_CTRL |= bWAK_RXD0_LO +#define WAKE_RXD1_enable() WAKE_CTRL |= bWAK_RXD1_LO +#define WAKE_P13_enable() WAKE_CTRL |= bWAK_P1_3_LO +#define WAKE_P14_enable() WAKE_CTRL |= bWAK_P1_4_LO +#define WAKE_P15_enable() WAKE_CTRL |= bWAK_P1_5_LO +#define WAKE_RST_enable() WAKE_CTRL |= bWAK_RST_HI +#define WAKE_INT_enable() WAKE_CTRL |= bWAK_P3_2E_3L + +#define WAKE_USB_disable() WAKE_CTRL &= ~bWAK_BY_USB +#define WAKE_RXD0_disable() WAKE_CTRL &= ~bWAK_RXD0_LO +#define WAKE_RXD1_disable() WAKE_CTRL &= ~bWAK_RXD1_LO +#define WAKE_P13_disable() WAKE_CTRL &= ~bWAK_P1_3_LO +#define WAKE_P14_disable() WAKE_CTRL &= ~bWAK_P1_4_LO +#define WAKE_P15_disable() WAKE_CTRL &= ~bWAK_P1_5_LO +#define WAKE_RST_disable() WAKE_CTRL &= ~bWAK_RST_HI +#define WAKE_INT_disable() WAKE_CTRL &= ~bWAK_P3_2E_3L