Ajout FishPeper

This commit is contained in:
Serge NOEL
2026-04-21 12:19:15 +02:00
parent 6744da3f88
commit 0c361a2440
2160 changed files with 589301 additions and 1 deletions

View File

@@ -0,0 +1,129 @@
CC = sdcc
HAL_SRCS := hal_led.c \
hal_debug.c \
hal_uart.c \
hal_clocksource.c \
hal_timeout.c \
hal_wdt.c \
hal_delay.c \
hal_dma.c \
hal_spi.c \
hal_cc25xx.c \
hal_io.c \
hal_adc.c \
hal_storage.c \
hal_sbus.c \
hal_ppm.c \
hal_soft_serial.c
ARCH_SRCS := $(addprefix $(ARCH_DIR)/, $(HAL_SRCS))
ARCH_HEADERS := $(ARCH_SRCS:.c=.h)
BOARD_SRCS := $(GENERIC_SRCS) \
$(ARCH_SRCS)
INCLUDE_DIRS := $(INCLUDE_DIRS) \
/usr/share/sdcc/include \
$(SRC_DIR) \
$(ARCH_DIR) \
$(TARGET_DIR)
LDFLAGS_FLASH = --out-fmt-ihx \
--code-loc 0x0c00 \
--code-size $(FLASH_SIZE) \
--xram-loc 0xf000 \
--xram-size 0x300 \
--iram-size 0x100
#programmer binary
CC_TOOL ?= cc-tool
CFLAGS += --model-small \
--opt-code-speed \
$(addprefix -I,$(INCLUDE_DIRS))
ifdef DEBUG
CFLAGS += --debug
endif
HEADERS := $(BOARD_SRCS:.c=.h)
ADB = $(BOARD_SRCS:.c=.adb)
ASM = $(BOARD_SRCS:.c=.asm)
LNK = $(BOARD_SRCS:.c=.lnk)
LST = $(BOARD_SRCS:.c=.lst)
REL = $(BOARD_SRCS:.c=.rel)
RST = $(BOARD_SRCS:.c=.rst)
SYM = $(BOARD_SRCS:.c=.sym)
#we build two flavours:
# _full : includes the bootloader, use this for initial flashing
# _update: just the opensky fw, relocated to be stored after the bootloader
TARGET_FULL = $(OBJECT_DIR)/$(RESULT)_full.hex
TARGET_UPDATE = $(OBJECT_DIR)/$(RESULT)_update.hex
TARGET_NO_BL = $(OBJECT_DIR)/$(RESULT)_no_bl.hex
BL_DIR = arch/cc251x/bootloader
BL_HEX = bootloader.hex
PCDB = $(PROGS:.hex=.cdb)
PLNK = $(PROGS:.hex=.lnk)
PMAP = $(PROGS:.hex=.map)
PMEM = $(PROGS:.hex=.mem)
PAOM = $(PROGS:.hex=)
SREC_CAT_FOUND := $(shell command -v srec_cat 2> /dev/null)
TARGET_OBJS = $(addsuffix .rel,$(addprefix $(OBJECT_DIR)/$(TARGET)/,$(basename $(BOARD_SRCS))))
TARGET_DEPS = $(addsuffix .d,$(addprefix $(OBJECT_DIR)/$(TARGET)/,$(basename $(BOARD_SRCS))))
# Search path for standard files
#vpath %.c ./src
#vpath %.c ./$(ARCH_DIR)
board: $(TARGET_UPDATE) $(TARGET_FULL)
bootloader:
@echo "### Building bootloader ###"
$(MAKE) -C $(BL_DIR) \
STYLECHECK_DISABLED=1 \
FLASH_SIZE=$(FLASH_SIZE) \
CONFIG_INCLUDE_DIR=../../../$(TARGET_DIR) \
clean all
$(TARGET_FULL): $(TARGET_UPDATE) bootloader
@echo "merging bootloader and main code"
ifndef SREC_CAT_FOUND
$(error "could not find srec_cat binary. make sure to install the srecord package")
else
srec_cat -disable_sequence_warnings \
$(TARGET_UPDATE) -intel \
$(BL_DIR)/$(BL_HEX) -intel \
-o $(TARGET_FULL) -intel
@echo "done."
endif
$(TARGET_UPDATE): $(TARGET_OBJS)
$(V1) echo Linking: $(TARGET)
$(V1) $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o $@ $^
# this is just for development, DO NOT flash this for production
$(TARGET_NO_BL): $(TARGET_OBJS)
$(V1) $(CC) $(LDFLAGS_FLASH) $(CFLAGS) --code-loc 0x000 -o $@ $^
$(OBJECT_DIR)/$(TARGET)/%.rel: %.c
$(V1) mkdir -p $(dir $@)
$(V1) echo "%% $(notdir $<)" "$(STDOUT)" && \
$(CC) -c -o $@ $(CFLAGS) $<
clean:
$(V1) echo Cleaning: $(TARGET)
$(V1) rm -f $(ADB) $(ASM) $(LNK) $(LST) $(TARGET_OBJS) $(RST) $(SYM)
$(V1) rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM)
$(V1) cd $(BL_DIR) && $(MAKE) clean
flash: $(OUTPUT_FULL)
$(CC_TOOL) -f -e -w $(TARGET_FULL)
flash_no_bl: $(OUTPUT_NO_BL)
$(CC_TOOL) -f -e -w $(TARGET_NO_BL)

View File

@@ -0,0 +1,172 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_adc.h"
#include "hal_defines.h"
#include "hal_cc25xx.h"
#include "portmacros.h"
#include "config.h"
#include "hal_dma.h"
#include "debug.h"
#include "delay.h"
#include "wdt.h"
// adc results
__xdata uint16_t hal_adc_data[2];
void hal_adc_init(void) {
hal_adc_data[0] = 0;
hal_adc_data[1] = 0;
// pin config -> dir = input
PORT2DIR(ADC_PORT) &= ~((1 << ADC1) | (1 << ADC0));
// set special function ADC for those pins:
ADCCFG = (1 << ADC1) | (1 << ADC0);
// set up adc:
// - external vref (avcc)
// - 10bit adc
// - stop on AIN7
ADCCON2 = ADCCON2_SREF_AVDD | ADCCON2_SDIV_10BIT | ADCCON2_SCH_AIN7;
// full speed, start conversion (bit0+1 always write as 1...)
ADCCON1 = ADCCON1_ST | ADCCON1_STSEL_FULL_SPEED | 0b11;
// configure DMA1 + DMA2:
hal_adc_dma_init(1, &hal_adc_data[0], DMA_TRIG_ADC_CH0 + ADC0);
hal_adc_dma_init(2, &hal_adc_data[1], DMA_TRIG_ADC_CH0 + ADC1);
// set pointer to the DMA configuration struct into DMA-channel 1-4
// configuration
SET_WORD(DMA1CFGH, DMA1CFGL, &hal_dma_config[1]);
hal_adc_dma_arm();
// for testing only, do not use under normal use
#if ADC_DO_TEST
adc_test();
#endif // ADC_DO_TEST
}
void hal_adc_dma_arm(void) {
DMAARM = (DMA_ARM_CH1 | DMA_ARM_CH2);
}
void hal_adc_process(void) {
if (hal_adc_dma_done()) {
// THIS OUTPUT BREAKS CONNECTIVITY! USE FOR DEBUGGING ONLY.
// fine, arm dma:
hal_adc_dma_arm();
} else {
// oops this should not happen
debug_putc('D');
// cancel and re arm dma
// DMAARM = DMA_ARM_ABORT | (DMA_ARM_CH1 | DMA_ARM_CH2);
}
}
void hal_adc_dma_init(uint8_t dma_id, uint16_t __xdata *dest_adr, uint8_t trig) {
hal_dma_config[dma_id].PRIORITY = DMA_PRI_LOW; // example used high...
hal_dma_config[dma_id].M8 = DMA_M8_USE_7_BITS;
hal_dma_config[dma_id].IRQMASK = DMA_IRQMASK_DISABLE;
hal_dma_config[dma_id].TRIG = trig;
hal_dma_config[dma_id].TMODE = DMA_TMODE_BLOCK;
hal_dma_config[dma_id].WORDSIZE = DMA_WORDSIZE_BYTE;
SET_WORD(hal_dma_config[dma_id].SRCADDRH, hal_dma_config[dma_id].SRCADDRL, &X_ADCL);
SET_WORD(hal_dma_config[dma_id].DESTADDRH, hal_dma_config[dma_id].DESTADDRL, dest_adr);
hal_dma_config[dma_id].VLEN = DMA_VLEN_USE_LEN;
SET_WORD(hal_dma_config[dma_id].LENH, hal_dma_config[dma_id].LENL, 2);
hal_dma_config[dma_id].SRCINC = DMA_SRCINC_1;
hal_dma_config[dma_id].DESTINC = DMA_DESTINC_1;
}
uint8_t hal_adc_dma_done(void) {
return ((DMAIRQ & (DMA_ARM_CH1 | DMA_ARM_CH2)) == (DMA_ARM_CH1 | DMA_ARM_CH2));
}
uint8_t hal_adc_get_scaled(uint8_t ch) {
uint16_t adc_data;
// adc data is HHHHHHHHLLLL0000 -> shift >>6 to get 10bit
// the cc2510 is _ALWAYS_ outputting data in two's complement format
// thus we shift >>7 to get 9 bit two's complement
// NOTE: the chip seems to have a bug, in contrast to the datasheet
// measuring a signal close to GND seems to deliver negative values (!)
// therefore we have to check for negative numbers and set them to zero
if (ch == 0) {
// convert to 8 bit (see above)
adc_data = hal_adc_data[1] >> 7;
if (adc_data & (1 << 8)) adc_data = 0; // bugfix: handle negative numbers
// return fixed value
return adc_data;
} else {
adc_data = hal_adc_data[0] >> 7;
if (adc_data & (1 << 8)) adc_data = 0; // bugfix: handle negative numbers
#ifdef ADC1_USE_ACS712
// acs712 is connected to ADC1
// when powered by 5V we can use a trick
// to get a good resolution:
// use inverted power inputs to get
// 0A = 2.5V
// 30A = 0.0V
return 255-(adc_data);
#else
return adc_data;
#endif // ADC1_USE_ACS712
}
}
#if ADC_DO_TEST
void hal_adc_test(void) {
debug("adc: running test\n"); debug_flush();
while (1) {
debug("adc: re-arming adc\n"); debug_flush();
hal_adc_dma_arm();
debug("adc: waiting for adc completion\n"); debug_flush();
while (!hal_adc_dma_done()) {
debug_putc('.');
delay_ms(1);
}
debug("\nadc: done. res[0] = "); debug_flush();
debug_put_uint16(hal_adc_data[0]>>4);
debug_putc('x'); debug_put_hex8(hal_adc_data[0]>>12);
debug_put_hex8((hal_adc_data[0]>>4)&0xff);
debug(", res[1] = "); debug_flush();
debug_put_uint16(hal_adc_data[1]>>4);
debug_putc('x'); debug_put_hex8(hal_adc_data[1]>>12);
debug_put_hex8((hal_adc_data[1]>>4)&0xff);
debug_put_newline();
delay_ms(100);
// reset wdt
wdt_reset();
}
}
#endif // ADC_DO_TEST

View File

@@ -0,0 +1,41 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_ADC_H_
#define HAL_ADC_H_
#include <stdint.h>
#ifdef ADC_PORT
#define ADC_ENABLED
#endif // ADC_PORT
// adc results
extern __xdata uint16_t hal_adc_data[2];
void hal_adc_init(void);
uint8_t hal_adc_get_scaled(uint8_t ch);
void hal_adc_dma_arm(void);
void hal_adc_dma_init(uint8_t dma_id, uint16_t __xdata *dest_adr, uint8_t trig);
uint8_t hal_adc_dma_done(void);
void hal_adc_test(void);
void hal_adc_process(void);
#endif // HAL_ADC_H_

View File

@@ -0,0 +1,231 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_cc25xx.h"
#include "cc25xx.h"
#include "hal_defines.h"
#include "hal_dma.h"
#include "delay.h"
#include "timeout.h"
#include "debug.h"
#include "led.h"
#include "frsky.h"
#include <cc2510fx.h>
EXTERNAL_MEMORY volatile uint8_t hal_cc25xx_mode;
void hal_cc25xx_init(void) {
// set highest prio for ch0 (RF)
IP1 |= (1<<0);
IP0 |= (1<<0);
hal_cc25xx_mode = CC25XX_MODE_RX;
// if we support LNA/PA make sure to config the pin as output:
#ifdef RF_LNA_PORT
PORT2DIR(RF_LNA_PORT) |= (1 << RF_LNA_PIN);
PORT2DIR(RF_PA_PORT) |= (1 << RF_PA_PIN);
// set default to LNA active
RF_PA_DISABLE();
RF_LNA_ENABLE();
#endif // RF_LNA_PORT
// if we support Diversity make sure to config the pin as output:
#ifdef RF_ANTENNA_SWITCH_PORT
PORT2DIR(RF_ANTENNA_SWITCH_PORT) |= (1 << RF_ANTENNA_SWITCH_PIN);
// select first antenna
RF_ANTENNA_SELECT_A();
#endif // RF_ANTENNA_SWITCH_PORT
// if we support HIGH GAIN mode config pin as output:
#ifdef RF_HIGH_GAIN_MODE_PORT
PORT2DIR(RF_HIGH_GAIN_MODE_PORT) |= (1 << RF_HIGH_GAIN_MODE_PIN);
// enable high gain mode?
#ifdef RF_HIGH_GAIN_MODE_ENABLED
RF_HIGH_GAIN_MODE_ENABLE();
#else
RF_HIGH_GAIN_MODE_DISABLE();
#endif // RF_HIGH_GAIN_MODE_ENABLED
#endif // RF_HIGH_GAIN_MODE_PORT
// if we support Bypass mode make sure to config the pin as output:
#ifdef RF_BYPASS_PORT
PORT2DIR(RF_BYPASS_MODE_PORT) |= (1 << RF_BYPASS_MODE_PIN);
// set default to Bypass off
#ifdef RF_BYPASS_MODE_ENABLED
RF_BYPASS_MODE_ENABLE();
#else
RF_BYPASS_MODE_DISABLE();
#endif // RF_BYPASS_MODE_ENABLED
#endif // RF_BYPASS_PORT
}
uint32_t hal_cc25xx_set_antenna(uint8_t id) {
// select antenna 0 or 1:
#ifdef RF_ANTENA_SWITCH_PORT
if (id) {
RF_ANTENNA_SELECT_B();
} else {
RF_ANTENNA_SELECT_A();
}
#endif // RF_ANTENNA_SWITCH_PORT
return id;
}
void hal_cc25xx_disable_rf_interrupt(void) {
IEN2 &= ~(IEN2_RFIE);
RFIM = 0;
}
void hal_cc25xx_enter_rxmode(void) {
#ifdef RF_LNA_PORT
RF_LNA_ENABLE();
delay_us(20);
RF_PA_DISABLE();
delay_us(5);
#endif // RF_LNA_PORT
// set up dma for radio--->buffer
hal_cc25xx_setup_rf_dma(CC25XX_MODE_RX);
// configure interrupt for every received packet
IEN2 |= (IEN2_RFIE);
// mask done irq
RFIM = (1<<4);
// interrupts should be enabled globally already..
// skip this! sei();
}
void hal_cc25xx_enter_txmode(void) {
#ifdef RF_LNA_PORT
RF_LNA_DISABLE();
delay_us(20);
RF_PA_ENABLE();
delay_us(5);
#endif // RF_LNA_PORT
// abort ch0
DMAARM = DMA_ARM_ABORT | DMA_ARM_CH0;
hal_cc25xx_setup_rf_dma(CC25XX_MODE_TX);
}
void hal_cc25xx_setup_rf_dma(uint8_t mode) {
// CPU has priority over DMA
// Use 8 bits for transfer count
// No DMA interrupt when done
// DMA triggers on radio
// Single transfer per trigger.
// One byte is transferred each time.
hal_dma_config[0].PRIORITY = DMA_PRI_HIGH;
hal_dma_config[0].M8 = DMA_M8_USE_8_BITS;
hal_dma_config[0].IRQMASK = DMA_IRQMASK_DISABLE;
hal_dma_config[0].TRIG = DMA_TRIG_RADIO;
hal_dma_config[0].TMODE = DMA_TMODE_SINGLE;
hal_dma_config[0].WORDSIZE = DMA_WORDSIZE_BYTE;
// store mode
hal_cc25xx_mode = mode;
if (hal_cc25xx_mode == CC25XX_MODE_TX) {
// Transmitter specific DMA settings
// Source: radioPktBuffer
// Destination: RFD register
// Use the first byte read + 1
// Sets the maximum transfer count allowed (length byte + data)
// Data source address is incremented by 1 byte
// Destination address is constant
SET_WORD(hal_dma_config[0].SRCADDRH, hal_dma_config[0].SRCADDRL, frsky_packet_buffer);
SET_WORD(hal_dma_config[0].DESTADDRH, hal_dma_config[0].DESTADDRL, &X_RFD);
hal_dma_config[0].VLEN = DMA_VLEN_FIRST_BYTE_P_1;
SET_WORD(hal_dma_config[0].LENH, hal_dma_config[0].LENL, (FRSKY_PACKET_LENGTH+1));
hal_dma_config[0].SRCINC = DMA_SRCINC_1;
hal_dma_config[0].DESTINC = DMA_DESTINC_0;
} else {
// Receiver specific DMA settings:
// Source: RFD register
// Destination: radioPktBuffer
// Use the first byte read + 3 (incl. 2 status bytes)
// Sets maximum transfer count allowed (length byte + data + 2 status bytes)
// Data source address is constant
// Destination address is incremented by 1 byte for each write
SET_WORD(hal_dma_config[0].SRCADDRH, hal_dma_config[0].SRCADDRL, &X_RFD);
SET_WORD(hal_dma_config[0].DESTADDRH, hal_dma_config[0].DESTADDRL, frsky_packet_buffer);
hal_dma_config[0].VLEN = DMA_VLEN_FIRST_BYTE_P_3;
SET_WORD(hal_dma_config[0].LENH, hal_dma_config[0].LENL, (FRSKY_PACKET_LENGTH+3));
hal_dma_config[0].SRCINC = DMA_SRCINC_0;
hal_dma_config[0].DESTINC = DMA_DESTINC_1;
}
// Save pointer to the DMA configuration struct into DMA-channel 0
// configuration registers
SET_WORD(DMA0CFGH, DMA0CFGL, &hal_dma_config[0]);
// frsky_packet_received = 0;
}
void hal_cc25xx_enable_receive(void) {
// start receiving on dma channel 0
DMAARM = DMA_ARM_CH0;
}
void hal_cc25xx_rf_interrupt(void) __interrupt RF_VECTOR {
// clear int flag
RFIF &= ~(1<<4);
// clear general statistics reg
S1CON &= ~0x03;
if (hal_cc25xx_mode == CC25XX_MODE_RX) {
// mark as received:
frsky_packet_received = 1;
// re arm DMA channel 0
hal_cc25xx_enable_receive();
} else {
frsky_packet_sent = 1;
}
}
uint8_t hal_cc25xx_transmission_completed(void) {
// this flag is set in the RF isr
return (frsky_packet_sent);
}
void hal_cc25xx_transmit_packet(volatile uint8_t *buffer, uint8_t len) {
UNUSED(buffer);
UNUSED(len);
RFST = RFST_STX;
// start transmitting on dma channel 0
DMAARM = DMA_ARM_CH0;
// mark packet as not sent (will be modified in RF isr):
frsky_packet_sent = 0;
// tricky: this will force an int request and
// initiate the actual transmission
S1CON |= 0x03;
}

View File

@@ -0,0 +1,276 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_CC25XX_H_
#define HAL_CC25XX_H_
#include <stdint.h>
#include "hal_defines.h"
#include "config.h"
#include <cc2510fx.h>
#define CC25XX_FIFO FIFO
#define hal_cc25xx_set_register(reg, val) { reg = val; }
#define hal_cc25xx_strobe(val) { RFST = val; }
#define hal_cc25xx_get_register(r) (r)
#define hal_cc25xx_get_register_burst(r) (r)
#ifdef RF_LNA_PORT
#define RF_LNA_ENABLE() { PORT2BIT(RF_LNA_PORT, RF_LNA_PIN) = RF_LNA_ON_LEVEL; }
#define RF_LNA_DISABLE() { PORT2BIT(RF_LNA_PORT, RF_LNA_PIN) = ~RF_LNA_ON_LEVEL; }
#define RF_PA_ENABLE() { PORT2BIT(RF_PA_PORT, RF_PA_PIN) = RF_PA_ON_LEVEL; }
#define RF_PA_DISABLE() { PORT2BIT(RF_PA_PORT, RF_PA_PIN) = ~RF_PA_ON_LEVEL; }
#endif // RF_LNA_PORT
#ifdef RF_ANTENNA_SWITCH_PORT
#define RF_ANTENNA_SELECT_A() { PORT2BIT(RF_ANTENNA_SWITCH_PORT, RF_ANTENNA_SWITCH_PIN) = RF_ANTENNA_A_LEVEL; }
#define RF_ANTENNA_SELECT_B() { PORT2BIT(RF_ANTENNA_SWITCH_PORT, RF_ANTENNA_SWITCH_PIN) = ~RF_ANTENNA_A_LEVEL; }
#endif // RF_ANTENNA_SWITCH_PORT
#ifdef RF_HIGH_GAIN_MODE_PORT
#define RF_HIGH_GAIN_MODE_ENABLE() { \
PORT2BIT(RF_HIGH_GAIN_MODE_PORT, RF_HIGH_GAIN_MODE_PIN) = RF_HIGH_GAIN_MODE_ON_LEVEL; }
#define RF_HIGH_GAIN_MODE_DISBALE() { \
PORT2BIT(RF_HIGH_GAIN_MODE_PORT, RF_HIGH_GAIN_MODE_PIN) = ~RF_HIGH_GAIN_MODE_ON_LEVEL; }
#endif // RF_HIGH_GAIN_MODE_PORT
#ifdef RF_BYPASS_MODE_PORT
#define RF_BYPASS_MODE_ENABLE() { PORT2BIT(RF_BYPASS_MODE_PORT, RF_BYPASS_MODE_PIN) = RF_BYPASS_MODE_ON_LEVEL; }
#define RF_BYPASS_MODE_DISABLE() { PORT2BIT(RF_BYPASS_MODE_PORT, RF_BYPASS_MODE_PIN) = ~RF_BYPASS_MODE_ON_LEVEL; }
#endif // RF_BYPASS_MODE_PORT
uint32_t hal_cc25xx_set_antenna(uint8_t id);
#define hal_cc25xx_process_packet(packet_received, buffer, maxlen) {}
void hal_cc25xx_init(void);
#define hal_cc25xx_set_gdo_mode() {}
void hal_cc25xx_disable_rf_interrupt(void);
#define hal_cc25xx_rx_sleep() { delay_us(1000); }
#define hal_cc25xx_tx_sleep() { delay_us(900); }
void hal_cc25xx_enter_rxmode(void);
void hal_cc25xx_enter_txmode(void);
void hal_cc25xx_setup_rf_dma(uint8_t mode);
void hal_cc25xx_enable_receive(void);
void hal_cc25xx_transmit_packet(volatile uint8_t *buffer, uint8_t len);
uint8_t hal_cc25xx_transmission_completed(void);
void hal_cc25xx_rf_interrupt(void) __interrupt RF_VECTOR;
#define hal_cc25xx_partnum_valid(p, v) ((p == 0x81) && (v = 0x04))
#define PERCFG_U0CFG (1<<0)
#define PERCFG_U1CFG (1<<1)
#define PERCFG_T4CFG (1<<4)
#define PERCFG_T3CFG (1<<5)
#define PERCFG_T1CFG (1<<6)
#define IEN0_RFTXRXIE (1<<0)
#define IEN0_ADCIE (1<<1)
#define IEN0_URX0IE (1<<2)
#define IEN0_URX1IE (1<<3)
#define IEN0_ENCIE (1<<4)
#define IEN0_STIE (1<<5)
#define IEN0_EA (1<<7)
// bit 7 - unused
// bit 6 - unused
#define PICTL_P2IEN (1<<5)
#define PICTL_P0IENH (1<<4)
#define PICTL_P0IENL (1<<3)
#define PICTL_P2ICON (1<<2)
#define PICTL_P1ICON (1<<1)
#define PICTL_P0ICON (1<<0)
#define IEN1_P0IE (1<<5)
#define IEN1_T4IE (1<<4)
#define IEN1_T3IE (1<<3)
#define IEN1_T2IE (1<<2)
#define IEN1_T1IE (1<<1)
#define IEN1_DMAIE (1<<0)
#define IEN2_RFIE (1<<0)
#define IEN2_P2IE (1<<1)
#define IEN2_UTX0IE (1<<2)
#define IEN2_UTX1IE (1<<3)
#define IEN2_P1IE (1<<4)
#define IEN2_WDTIE (1<<5)
#define U0GCR_ORDER (1<<5)
#define U0GCR_CPHA (1<<6)
#define U0GCR_CPOL (1<<7)
#define U0CSR_TX_BYTE (1<<1)
#define U1GCR_ORDER (1<<5)
#define U1GCR_CPHA (1<<6)
#define U1GCR_CPOL (1<<7)
#define UxCSR_RX_ENABLE (1<<6)
#define UxCSR_RX_BYTE (1<<2)
#define UxCSR_TX_BYTE (1<<1)
#define RFST_SNOP 0x05
#define RFST_SIDLE 0x04
#define RFST_STX 0x03
#define RFST_SRX 0x02
#define RFST_SCAL 0x01
#define RFST_SFSTXON 0x00
// statemachine on cc2510 is different.
// instead of SF*X we should use SIDLE
#define RFST_SFTX RFST_SIDLE
#define RFST_SFRX RFST_SIDLE
// append status
#define CC2500_PKTCTRL1_APPEND_STATUS (1<<2)
// crc autoflush
#define CC2500_PKTCTRL1_CRC_AUTOFLUSH (1<<3)
// adress checks
#define CC2500_PKTCTRL1_FLAG_ADR_CHECK_00 ((0<<1) | (0<<0))
#define CC2500_PKTCTRL1_FLAG_ADR_CHECK_01 ((0<<1) | (1<<0))
#define CC2500_PKTCTRL1_FLAG_ADR_CHECK_10 ((1<<1) | (0<<0))
#define CC2500_PKTCTRL1_FLAG_ADR_CHECK_11 ((1<<1) | (1<<0))
#define CLKCON_TICKSPD_001 (0b00001000)
#define CLKCON_TICKSPD_010 (0b00010000)
#define CLKCON_TICKSPD_011 (0b00011000)
#define CLKCON_TICKSPD_100 (0b00100000)
#define CLKCON_TICKSPD_101 (0b00101000)
#define CLKCON_TICKSPD_110 (0b00110000)
#define CLKCON_TICKSPD_111 (0b00111000)
#define CLKCON_OSC32K (1<<7)
#define ADCCON2_SREF_INT (0b00<<6)
#define ADCCON2_SREF_EXT (0b01<<6)
#define ADCCON2_SREF_AVDD (0b10<<6)
#define ADCCON2_SREF_EXTDIFF (0b11<<6)
#define ADCCON2_SDIV_7BIT (0b00<<4)
#define ADCCON2_SDIV_9BIT (0b01<<4)
#define ADCCON2_SDIV_10BIT (0b10<<4)
#define ADCCON2_SDIV_12BIT (0b11<<4)
#define ADCCON2_SCH_AIN0 (0b0000<<0)
#define ADCCON2_SCH_AIN1 (0b0001<<0)
#define ADCCON2_SCH_AIN2 (0b0010<<0)
#define ADCCON2_SCH_AIN3 (0b0011<<0)
#define ADCCON2_SCH_AIN4 (0b0100<<0)
#define ADCCON2_SCH_AIN5 (0b0101<<0)
#define ADCCON2_SCH_AIN6 (0b0110<<0)
#define ADCCON2_SCH_AIN7 (0b0111<<0)
#define ADCCON2_SCH_AIN0AIN1 (0b1000<<0)
#define ADCCON2_SCH_AIN2AIN3 (0b1001<<0)
#define ADCCON2_SCH_AIN4AIN5 (0b1010<<0)
#define ADCCON2_SCH_AIN6AIN7 (0b1011<<0)
#define ADCCON2_SCH_GND (0b1100<<0)
#define ADCCON2_SCH_POSVREF (0b1101<<0)
#define ADCCON2_SCH_TEMP (0b1110<<0)
#define ADCCON2_SCH_VDD3 (0b1111<<0)
#define ADCCON1_ST (1<<6)
#define ADCCON1_STSEL_FULL_SPEED (0b01<<4)
#define WDCTL_EN (1<<3)
#define WDCTL_MODE (1<<2)
#define WDCTL_INT (0b11)
#define WDCTL_INT_1S (0b00)
#define FCTL_BUSY (1<<7)
#define FCTL_SWBUSY (1<<6)
#define FCTL_WRITE (1<<1)
#define FCTL_ERASE (1<<0)
#define T1CTL_MODE_SUSPEND (0b00<<0)
#define T1CTL_MODE_FREE_RUNNING (0b01<<0)
#define T1CTL_MODE_MODULO (0b10<<0)
#define T1CTL_MODE_UPDOWN (0b11<<0)
#define T1CTL_DIV_1 (0b00<<2)
#define T1CTL_DIV_8 (0b01<<2)
#define T1CTL_DIV_32 (0b10<<2)
#define T1CTL_DIV_128 (0b11<<2)
#define T1CTL_OVFIF (1<<4)
#define T1CTL_CH0_IF (1<<5)
#define T1CTL_CH1_IF (1<<6)
#define T1CTL_CH2_IF (1<<7)
#define T3CTL_MODE_SUSPEND (0b00<<0)
#define T3CTL_MODE_FREE_RUNNING (0b01<<0)
#define T3CTL_MODE_MODULO (0b10<<0)
#define T3CTL_MODE_UPDOWN (0b11<<0)
#define T3CTL_CLR (1<<2)
#define T3CTL_OVFIM (1<<3)
#define T3CTL_START (1<<4)
#define T3CTL_DIV_1 (0b000<<5)
#define T3CTL_DIV_2 (0b001<<5)
#define T3CTL_DIV_4 (0b010<<5)
#define T3CTL_DIV_8 (0b011<<5)
#define T3CTL_DIV_16 (0b100<<5)
#define T3CTL_DIV_32 (0b101<<5)
#define T3CTL_DIV_64 (0b110<<5)
#define T3CTL_DIV_128 (0b111<<5)
#define T4CTL_MODE_SUSPEND (0b00<<0)
#define T4CTL_MODE_FREE_RUNNING (0b01<<0)
#define T4CTL_MODE_MODULO (0b10<<0)
#define T4CTL_MODE_UPDOWN (0b11<<0)
#define T4CTL_CLR (1<<2)
#define T4CTL_OVFIM (1<<3)
#define T4CTL_START (1<<4)
#define T4CTL_DIV_1 (0b000<<5)
#define T4CTL_DIV_2 (0b001<<5)
#define T4CTL_DIV_4 (0b010<<5)
#define T4CTL_DIV_8 (0b011<<5)
#define T4CTL_DIV_16 (0b100<<5)
#define T4CTL_DIV_32 (0b101<<5)
#define T4CTL_DIV_64 (0b110<<5)
#define T4CTL_DIV_128 (0b111<<5)
#define T1CCTLx_CAP_NO (0b00<<0)
#define T1CCTLx_CAP_RISING (0b01<<0)
#define T1CCTLx_CAP_FALLING (0b10<<0)
#define T1CCTLx_CAP_BOTH (0b11<<0)
#define T1CCTLx_MODE_CAPTURE (0<<2)
#define T1CCTLx_MODE_COMPARE (1<<2)
#define T1CCTLx_CMP_SET (0b000<<3)
#define T1CCTLx_CMP_CLEAR (0b001<<3)
#define T1CCTLx_CMP_TOGGLE (0b010<<3)
#define T1CCTLx_CMP_SETCLR0 (0b011<<3)
#define T1CCTLx_CMP_CLRSET0 (0b100<<3)
#define T1CCTLx_CMP_RES0 (0b101<<3)
#define T1CCTLx_CMP_RES1 (0b110<<3)
#define T1CCTLx_CMP_RES2 (0b111<<3)
#define T1CCTLx_IM (1<<6)
#define T1CCTLx_CPSEL_RF (1<<7)
// add missing defines
#include <compiler.h>
SFRX(TEST2, 0xDF23);
SFRX(TEST1, 0xDF24);
SFRX(TEST0, 0xDF25);
#endif // HAL_CC25XX_H_

View File

@@ -0,0 +1,50 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_clocksource.h"
#include "hal_cc25xx.h"
#include "led.h"
void hal_clocksource_init(void) {
// for debugging clocksource problems
led_red_on();
led_green_on();
// power up osc (?)
SLEEP &= ~CLOCKSOURCE_OSC_PD_BIT;
// wait for XOSC stable
while (!CLOCKSOURCE_XOSC_STABLE()) {}
NOP();
// start crystal osc as HS clocksource, OSC32 is int rc osc
CLKCON = 0x80;
// wait for selection to be active
while (!CLOCKSOURCE_XOSC_STABLE()) {}
NOP();
// power down the unused oscillator
SLEEP |= CLOCKSOURCE_OSC_PD_BIT;
// for debugging clocksource problems
led_red_off();
led_green_off();
}

View File

@@ -0,0 +1,47 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_CLOCKSOURCE_H_
#define HAL_CLOCKSOURCE_H_
#include "hal_cc25xx.h"
void hal_clocksource_init(void);
// bit mask used to check the stability of XOSC
#define CLOCKSOURCE_XOSC_STABLE_BIT 0x40
// bit mak used to check the stability of the High-frequency RC oscillator
#define CLOCKSOURCE_HFRC_STB_BIT 0x20
// bit maks used to power down system clock oscillators
#define CLOCKSOURCE_OSC_PD_BIT 0x04
// bit mask used to control the system clock oscillator
#define CLOCKSOURCE_MAIN_OSC_BITS 0x7F
// bit mask used to select/check the system clock oscillator
#define CLOCKSOURCE_OSC_BIT 0x40
// macros to check for stable oscs:
#define CLOCKSOURCE_HFRC_OSC_STABLE() (SLEEP & (CLOCKSOURCE_HFRC_STB_BIT))
#define CLOCKSOURCE_XOSC_STABLE() (SLEEP & (CLOCKSOURCE_XOSC_STABLE_BIT))
#define CLOCKSOURCE_XOSC 0
#define CLOCKSOURCE_HFRC 1
#endif // HAL_CLOCKSOURCE_H_

View File

@@ -0,0 +1,160 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_debug.h"
#include "hal_defines.h"
void hal_debug_init(void) {
__xdata union hal_uart_config_t uart_config;
#ifndef DEBUG_UART
#error "ERROR: DEBUG_UART not defined"
#endif // DEBUG_UART
#if DEBUG_UART == USART0_P0
// USART0 use ALT1 -> Clear flag -> Port P0_3 = TX
PERCFG &= ~(PERCFG_U0CFG);
// configure pin P0_3 (TX) as special function:
P0SEL |= (1<<3);
// set P0_5 as normal IO
P1SEL &= ~(1<<5);
// make tx pin output:
P0DIR |= (1<<3);
#elif DEBUG_UART == USART0_P1
// USART0 use ALT2 -> Set flag -> Port P1_5 = TX
PERCFG |= (PERCFG_U0CFG);
// configure pin P1_5 (TX) as special function
P1SEL |= (1<<5);
// set P0_3 as normal IO
P0SEL &= ~(1<<3);
// make tx pin output:
P1DIR |= (1<<5);
#elif DEBUG_UART == USART1_P0
// USART1 use ALT1 -> Clear flag -> Port P0_4 = TX
PERCFG &= ~(PERCFG_U1CFG);
// USART1 has priority when USART0 is also enabled
P2DIR = (P2DIR & 0x3F) | 0b01000000;
// configure pin P0_4 special function:
P0SEL |= (1<<4);
// configure P1_6 as normal IO
P1SEL &= ~(1<<6);
// make sure all P1 pins switch to normal GPIO
// P1SEL &= ~(0xF0);
// make tx pin output:
P0DIR |= (1<<4);
#else
#error "ERROR: UNSUPPORTED DEBUG UART"
#endif // DEBUG_UART == ...
// this assumes cpu runs from XOSC (26mhz) !
// set baudrate
#if (DEBUG_UART == USART0_P0) || (DEBUG_UART == USART0_P1)
U0BAUD = CC2510_BAUD_M_115200;
U0GCR = (U0GCR & ~0x1F) | (CC2510_BAUD_E_115200);
#else
U1BAUD = CC2510_BAUD_M_115200;
U1GCR = (U1GCR & ~0x1F) | (CC2510_BAUD_E_115200);
#endif // DEBUG_UART == ...
// set up config
uart_config.bit.START = 0; // startbit level = low
uart_config.bit.STOP = 1; // stopbit level = high
uart_config.bit.SPB = 0; // 1 stopbit
uart_config.bit.PARITY = 0; // no parity
uart_config.bit.BIT9 = 0; // 8bit
uart_config.bit.D9 = 0; // 8 Bits
uart_config.bit.FLOW = 0; // no hw flow control
uart_config.bit.ORDER = 0; // lsb first
hal_debug_set_mode(&uart_config);
// enable interrupts:
sei();
}
static void hal_debug_set_mode(EXTERNAL_MEMORY union hal_uart_config_t *cfg) {
#if (DEBUG_UART == USART0_P0) || (DEBUG_UART == USART0_P1)
// enable uart mode
U0CSR |= 0x80;
// store config to UxUCR register
U0UCR = cfg->byte & (0x7F);
// store config to U1GCR: (msb/lsb)
if (cfg->bit.ORDER) {
U0GCR |= U0GCR_ORDER;
} else {
U0GCR &= ~U0GCR_ORDER;
}
// interrupt prio to 0 (0..3=highest)
IP0 &= ~(1<<2);
IP1 &= ~(1<<2);
#else
// enable uart mode
U1CSR |= 0x80;
// store config to UxUCR register
U1UCR = cfg->byte & (0x7F);
// store config to U1GCR: (msb/lsb)
if (cfg->bit.ORDER) {
U1GCR |= U1GCR_ORDER;
} else {
U1GCR &= ~U1GCR_ORDER;
}
// interrupt prio to 0 (0..3=highest)
IP0 &= ~(1<<3);
IP1 &= ~(1<<3);
#endif // DEBUG_UART == ...
}
void hal_debug_start_transmission(uint8_t ch) {
#if (DEBUG_UART == USART0_P0) || (DEBUG_UART == USART0_P1)
// clear flags
UTX0IF = 0;
U0CSR &= ~UxCSR_TX_BYTE;
// enable TX int:
IEN2 |= (IEN2_UTX0IE);
// send this char
U0DBUF = ch;
#else
// clear flags
UTX1IF = 0;
U1CSR &= ~UxCSR_TX_BYTE;
// enable TX int:
IEN2 |= (IEN2_UTX1IE);
// send this char
U1DBUF = ch;
#endif // DEBUG_UART == ...
}

View File

@@ -0,0 +1,53 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_DEBUG_H_
#define HAL_DEBUG_H_
#include "hal_cc25xx.h"
#include "hal_uart.h"
#include <stdint.h>
void hal_debug_init(void);
void hal_debug_start_transmission(uint8_t ch);
#if (DEBUG_UART == USART0_P0) || (DEBUG_UART == USART0_P1)
#define hal_debug_int_enabled() (IEN2 & (IEN2_UTX0IE))
#else
#define hal_debug_int_enabled() (IEN2 & (IEN2_UTX1IE))
#endif // DEBUG_UART == ...
#define hal_debug_int_enable() { sei(); }
#define hal_debug_int_disable() { cli(); }
static void hal_debug_set_mode(__xdata union hal_uart_config_t *cfg);
#if (DEBUG_UART == USART0_P0) || (DEBUG_UART == USART0_P1)
#define DEBUG_ISR(void) hal_uart_tx_interrupt(void) __interrupt UTX0_VECTOR
#define HAL_DEBUG_ISR_FLAG_SET() (1)
#define HAL_DEBUG_ISR_CLEAR_FLAG() { UTX0IF = 0; }
#define HAL_DEBUG_ISR_DISABLE() { IEN2 &= ~(IEN2_UTX0IE); }
#define HAL_DEBUG_TX_DATA(data) { U0DBUF = data; }
#else
#define DEBUG_ISR(void) hal_uart_tx_interrupt(void) __interrupt UTX1_VECTOR
#define HAL_DEBUG_ISR_FLAG_SET() (1)
#define HAL_DEBUG_ISR_CLEAR_FLAG() { UTX1IF = 0; }
#define HAL_DEBUG_ISR_DISABLE() { IEN2 &= ~(IEN2_UTX1IE); }
#define HAL_DEBUG_TX_DATA(data) { U1DBUF = data; }
#endif // DEBUG_UART == ...
#endif // HAL_DEBUG_H_

View File

@@ -0,0 +1,29 @@
#ifndef __HAL_DEFINES_H__
#define __HAL_DEFINES_H__
#define EXTERNAL_MEMORY __xdata
#define EXTERNAL_DATA __data
#define inline
#define sei() { IEN0 |= IEN0_EA; }
#define cli() { IEN0 &= ~IEN0_EA; }
#ifndef NOP
#define NOP() { __asm nop __endasm; }
#endif
#define NOP45() { NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP(); NOP();
#define HI(a) (uint8_t) ((uint16_t)(a) >> 8 )
#define LO(a) (uint8_t) (uint16_t)(a)
#define SET_WORD(H, L, val) { (H) = HI(val); (L) = LO(val); }
// necessary for timer registers. todo: check if necessary for others as well...
#define SET_WORD_LO_FIRST(H, L, val) {(L) = LO(val); (H) = HI(val); }
#define UNUSED(x) (void)(x);
#define USART0_P0 0
#define USART0_P1 1
#define USART1_P0 2
#define USART1_P1 3
#endif // __HAL_DEFINES_H__

View File

@@ -0,0 +1,58 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_delay.h"
// busy wait delay loop. not 100% accurate
void hal_delay_ms(uint16_t ms) {
#define DELAY_MS_LOOP_A 86
#define DELAY_MS_LOOP_B 30
while (ms--) {
// this asm snippet gives us roughly 1ms delay:
__asm
mov r1, #DELAY_MS_LOOP_A
00000$: // delay_ms_loop_outer
dec r1
mov a, r1
jz 00002$
mov r2, #DELAY_MS_LOOP_B
00001$: // delay_ms_loop_inner
dec r2
mov a, r2
jz 00000$
sjmp 00001$
00002$: // delay_ms_done
__endasm;
}
}
// busy wait delay loop
// this is more or less accurate
void hal_delay_us(uint16_t us) {
#define DELAY_US_LOOP 1
while (us--) {
__asm
nop
nop
nop
__endasm;
}
}

View File

@@ -0,0 +1,28 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_DELAY_H_
#define HAL_DELAY_H_
#include <stdint.h>
void hal_delay_ms(uint16_t ms);
void hal_delay_us(uint16_t us);
#define hal_delay_45nop(void) { uint8_t n=45; while (n--) { NOP(); } }
#endif // HAL_DELAY_H_

View File

@@ -0,0 +1,26 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "main.h"
#include "hal_dma.h"
// dma config
// dma0 can be given independently but 1-4 has
// to be given in one consequent array...
__xdata HAL_DMA_DESC hal_dma_config[5];

View File

@@ -0,0 +1,152 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_DMA_H_
#define HAL_DMA_H_
#include <stdint.h>
// HAL_DMA CONFIG
// see https:// e2e.ti.com/support/wireless_connectivity/f/156/t/16922
typedef struct {
uint8_t SRCADDRH;
uint8_t SRCADDRL;
uint8_t DESTADDRH;
uint8_t DESTADDRL;
uint8_t LENH : 5;
uint8_t VLEN : 3;
uint8_t LENL : 8;
uint8_t TRIG : 5;
uint8_t TMODE : 2;
uint8_t WORDSIZE : 1;
uint8_t PRIORITY : 2;
uint8_t M8 : 1;
uint8_t IRQMASK : 1;
uint8_t DESTINC : 2;
uint8_t SRCINC : 2;
} HAL_DMA_DESC;
extern __xdata HAL_DMA_DESC hal_dma_config[5];
// Use LEN for transfer count
#define DMA_VLEN_USE_LEN 0x00
// Transfer the number of bytes specified by the first byte +1
#define DMA_VLEN_FIRST_BYTE_P_1 0x01
// Transfer the number of bytes indicated by the first byte (itself included)
#define DMA_VLEN_FIRST_BYTE 0x02
// Transfer the number of bytes specified by the first byte +2
#define DMA_VLEN_FIRST_BYTE_P_2 0x03
// Transfer the number of bytes specified by the first byte +3
#define DMA_VLEN_FIRST_BYTE_P_3 0x04
// The maximum length is always decided by the first byte
#define DMA_LEN_MAX 0xFF
// Transfer a byte at a time
#define DMA_WORDSIZE_BYTE 0x00
// Transfer a 16-bit word at a time
#define DMA_WORDSIZE_WORD 0x01
// Transfer a single byte/word after each DMA trigger
#define DMA_TMODE_SINGLE 0x00
// Transfer block of data (length len) after each DMA trigger
#define DMA_TMODE_BLOCK 0x01
// Transfer single byte/word (after len transfers, rearm DMA)
#define DMA_TMODE_SINGLE_REPEATED 0x02
// Transfer block of data (after len transfers, rearm DMA)
#define DMA_TMODE_BLOCK_REPEATED 0x03
#define DMA_TRIG_NONE 0 // No trigger, setting DMAREQ.DMAREQx bit starts transfer
#define DMA_TRIG_PREV 1 // DMA channel is triggered by completion of previous channel
#define DMA_TRIG_T1_CH0 2 // Timer 1, compare, channel 0
#define DMA_TRIG_T1_CH1 3 // Timer 1, compare, channel 1
#define DMA_TRIG_T1_CH2 4 // Timer 1, compare, channel 2
#define DMA_TRIG_T2_COMP 5 // Timer 2, compare
#define DMA_TRIG_T2_OVFL 6 // Timer 2, overflow
#define DMA_TRIG_T3_CH0 7 // Timer 3, compare, channel 0
#define DMA_TRIG_T3_CH1 8 // Timer 3, compare, channel 1
#define DMA_TRIG_T4_CH0 9 // Timer 4, compare, channel 0
#define DMA_TRIG_T4_CH1 10 // Timer 4, compare, channel 1
#define DMA_TRIG_ST 11 // Sleep Timer compare
#define DMA_TRIG_IOC_0 12 // Port 0 I/O pin input transition
#define DMA_TRIG_IOC_1 13 // Port 1 I/O pin input transition
#define DMA_TRIG_URX0 14 // USART0 RX complete
#define DMA_TRIG_UTX0 15 // USART0 TX complete
#define DMA_TRIG_URX1 16 // USART1 RX complete
#define DMA_TRIG_UTX1 17 // USART1 TX complete
#define DMA_TRIG_FLASH 18 // Flash data write complete
#define DMA_TRIG_RADIO 19 // RF packet byte received/transmit
#define DMA_TRIG_ADC_CHALL 20 // ADC end of a conversion in a sequence, sample ready
#define DMA_TRIG_ADC_CH0 21 // ADC end of conversion channel 0 in sequence, sample ready
#define DMA_TRIG_ADC_CH1 22 // ADC end of conversion channel 1 in sequence, sample ready
#define DMA_TRIG_ADC_CH2 23 // ADC end of conversion channel 2 in sequence, sample ready
#define DMA_TRIG_ADC_CH3 24 // ADC end of conversion channel 3 in sequence, sample ready
#define DMA_TRIG_ADC_CH4 25 // ADC end of conversion channel 4 in sequence, sample ready
#define DMA_TRIG_ADC_CH5 26 // ADC end of conversion channel 5 in sequence, sample ready
#define DMA_TRIG_ADC_CH6 27 // ADC end of conversion channel 6 in sequence, sample ready
#define DMA_TRIG_ADC_CH7 28 // ADC end of conversion channel 7 in sequence, sample ready
#define DMA_TRIG_ENC_DW 29 // AES encryption processor requests download input data
#define DMA_TRIG_ENC_UP 30 // AES encryption processor requests upload output data
// Increment source pointer by 0 bytes/words after each transfer
#define DMA_SRCINC_0 0x00
// Increment source pointer by 1 bytes/words after each transfer
#define DMA_SRCINC_1 0x01
// Increment source pointer by 2 bytes/words after each transfer
#define DMA_SRCINC_2 0x02
// Decrement source pointer by 1 bytes/words after each transfer
#define DMA_SRCINC_M1 0x03
// Increment destination pointer by 0 bytes/words after each transfer
#define DMA_DESTINC_0 0x00
// Increment destination pointer by 1 bytes/words after each transfer
#define DMA_DESTINC_1 0x01
// Increment destination pointer by 2 bytes/words after each transfer
#define DMA_DESTINC_2 0x02
// Decrement destination pointer by 1 bytes/words after each transfer
#define DMA_DESTINC_M1 0x03
// Disable interrupt generation
#define DMA_IRQMASK_DISABLE 0x00
// Enable interrupt generation upon DMA channel done
#define DMA_IRQMASK_ENABLE 0x01
#define DMA_M8_USE_8_BITS 0x00 // Use all 8 bits for transfer count
#define DMA_M8_USE_7_BITS 0x01 // Use 7 LSB for transfer count
// Low, CPU has priority
#define DMA_PRI_LOW 0x00
// Guaranteed, DMA at least every second try
#define DMA_PRI_GUARANTEED 0x01
// High, DMA has priority
#define DMA_PRI_HIGH 0x02
// Highest, DMA has priority. Reserved for DMA port access.
#define DMA_PRI_ABSOLUTE 0x03
#define DMA_ARM_ABORT 0x80
#define DMA_ARM_CH0 (1<<0)
#define DMA_ARM_CH1 (1<<1)
#define DMA_ARM_CH2 (1<<2)
#define DMA_ARM_CH3 (1<<3)
#define DMA_ARM_CH4 (1<<4)
#define DMAIRQ_DMAIF0 (1<<0)
#define DMAIRQ_DMAIF1 (1<<1)
#define DMAIRQ_DMAIF2 (1<<2)
#define DMAIRQ_DMAIF3 (1<<3)
#define DMAIRQ_DMAIF4 (1<<4)
#endif // HAL_DMA_H_

View File

@@ -0,0 +1,56 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_io.h"
#include "portmacros.h"
#include "config.h"
#include "hal_cc25xx.h"
void hal_io_init(void) {
// set bind pin as input
PORT2DIR(BIND_PORT) &= ~(1 << BIND_PIN);
// set pullup/down
PORT2INP(BIND_PORT) &= ~(1 << BIND_PIN);
#ifdef BIND2_PORT
// this board allows two bind buttons, both will work
// set bind2 pin as input
PORT2DIR(BIND2_PORT) &= ~(1 << BIND2_PIN);
// set pullup/down
PORT2INP(BIND2_PORT) &= ~(1 << BIND2_PIN);
#endif // BIND2_PORT
}
uint8_t hal_io_bind_request(void) {
// test bind button
if (!(BIND_PORT & (1 << BIND_PIN))) {
// LOW -> button pressed
return 1;
}
#ifdef BIND2_PORT
if (!(BIND2_PORT & (1 << BIND2_PIN))) {
// LOW -> button2 pressed
return 1;
}
#endif // BIND2_PORT
// no button pressed...
return 0;
}

View File

@@ -0,0 +1,29 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_IO_H_
#define HAL_IO_H_
#include "portmacros.h"
#include "config.h"
#include <stdint.h>
void hal_io_init(void);
uint8_t hal_io_bind_request(void);
#endif // HAL_IO_H_

View File

@@ -0,0 +1,22 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_led.h"
// nothing to do

View File

@@ -0,0 +1,44 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_LED_H_
#define HAL_LED_H_
#include "portmacros.h"
#include "config.h"
#include "hal_cc25xx.h"
// use helper macros to do expansion to *DIR etc
// LEDS
#define LED_GREEN_DIR PORT2DIR(LED_GREEN_PORT)
#define LED_RED_DIR PORT2DIR(LED_RED_PORT)
#define LED_RED_BIT PORT2BIT(LED_RED_PORT, LED_RED_PIN)
#define LED_GREEN_BIT PORT2BIT(LED_GREEN_PORT, LED_GREEN_PIN)
#define hal_led_green_init() { LED_GREEN_DIR |= (1 << LED_GREEN_PIN); led_green_off(); }
#define hal_led_green_on() { LED_GREEN_BIT = 1; }
#define hal_led_green_off() { LED_GREEN_BIT = 0; }
#define hal_led_green_toggle() { LED_GREEN_BIT = !LED_GREEN_BIT; }
#define hal_led_red_init() { LED_RED_DIR |= (1 << LED_RED_PIN); led_red_off(); }
#define hal_led_red_on() { LED_RED_BIT = 1; }
#define hal_led_red_off() { LED_RED_BIT = 0; }
#define hal_led_red_toggle() { LED_RED_BIT = !LED_RED_BIT; }
#endif // HAL_LED_H_

View File

@@ -0,0 +1,116 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_ppm.h"
#include "ppm.h"
#ifndef SBUS_ENABLED
void hal_ppm_init(void) {
// no int on overflow:
OVFIM = 0;
// set channels to compare interupt:
// CH0: off
T1CCTL0 = 0;
// CH1: off
T1CCTL1 = 0;
// CH2: toggle pin on cmp match, will generate sync pulses
#if PPM_INVERTED
// inverted, set on match, clear on zero
T1CCTL2 = T1CCTLx_MODE_COMPARE | T1CCTLx_CMP_SETCLR0;
#else
// non-inverted, clear on match, set on zero
T1CCTL2 = T1CCTLx_MODE_COMPARE | T1CCTLx_CMP_CLRSET0;
#endif // PPM_INVERTED
// configure peripheral alternative1 for timer 1:
// use alt config 1 -> clr flag -> P0_4 = output
PERCFG &= ~(PERCFG_T1CFG);
// USART1 use ALT2 in order to free up P0_4 for peripheral func
PERCFG |= PERCFG_U1CFG;
// select P0_4 for peripheral function
// NOTE: make sure to set usart1 to alt2 config!
P0SEL |= (1 << PPM_OUT_PIN);
// select P0_4 as output
P0DIR |= (1 << PPM_OUT_PIN);
// prescaler = 128
// tickspeed = 26MHz / 8 = 3,25MHz (TICKSPD is set in timeout.c!)
// 1us = 3.25 ticks -> 2ms = 6500 ticks, 4ms = 13000
T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_1;
// ch2 cmp: sync pulse length
SET_WORD_LO_FIRST(T1CC2H, T1CC2L, PPM_SYNC_PULS_LEN_TICKS);
// overflow:
SET_WORD_LO_FIRST(T1CC0H, T1CC0L, HAL_PPM_US_TO_TICKCOUNT(1000));
ppm_output_index = 0;
// clear pending interrupt flags (IRCON is reset by hw)
T1CTL &= ~(T1CTL_CH0_IF | T1CTL_CH1_IF | T1CTL_CH2_IF | T1CTL_OVFIF);
// overflow causes an int -> reload next channel data
OVFIM = 1;
// enable T1 interrups
T1IE = 1;
}
void hal_ppm_failsafe_exit() {
// configure p0_4 as peripheral:
P0SEL |= (1<<4);
// reset counter:
SET_WORD_LO_FIRST(T1CNTH, T1CNTL, 0);
// re enable timer interrupts:
OVFIM = 1;
// disable T1 interrups
T1IE = 1;
}
void hal_ppm_failsafe_enter(void) {
// disable interrupts
OVFIM = 0;
// disable T1 interrups
T1IE = 0;
// configure p0_4 as normal i/o:
P0SEL &= ~(1<<4);
// set pins to failsafe level:
#if PPM_INVERTED
// clear on zero -> default is high
P0 |= (1<<4);
#else
// set on zero -> default is low
P0 &= ~(1<<4);
#endif // PPM_INVERTED
}
#endif // SBUS_ENABLED

View File

@@ -0,0 +1,68 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_PPM_H_
#define HAL_PPM_H_
#include "config.h"
#include "hal_cc25xx.h"
#include <stdint.h>
#ifdef SBUS_ENABLED
#define hal_ppm_init() {}
#else
void hal_ppm_init(void);
void hal_ppm_failsafe_exit(void);
void hal_ppm_failsafe_enter(void);
void hal_ppm_timer1_interrupt(void) __interrupt T1_VECTOR;
/*
static void hal_ppm_init_rcc(void);
static void hal_ppm_init_gpio(void);
static void hal_ppm_init_timer(void);
static void hal_ppm_init_nvic(void);
static void hal_ppm_init_ocx(uint8_t ch, TIM_TypeDef *TIMx, TIM_OCInitTypeDef *tim_oc_init);
*/
// from frsky to ticks coresponding to 1000...2000 us
// frsky seems to send us*1.5 (~1480...3020) -> divide by 1.5 (=*2/3) to get us
// us -> ticks = ((_us*13)/4) -> (((_frsky*2/3)*13)/4) = ((_frsky*13)/6)
#define HAL_PPM_FRSKY_TO_TICKCOUNT(_frsky) (((_frsky << 3) + (_frsky << 2)+(_frsky))/6)
// from us to ticks:
// ((_us*13)/4) = ((_us * (8+4+1))/4) = (((_us<<3)+(_us<<2)+(_us))>>2)
#define HAL_PPM_US_TO_TICKCOUNT(_us) (((_us << 3) + (_us << 2)+(_us)) >> 2)
#define PPM_TIMER_ISR(void) hal_ppm_timer1_interrupt(void) __interrupt T1_VECTOR
#define HAL_PPM_UPDATE_CCVALUE(val) SET_WORD_LO_FIRST(T1CC0H, T1CC0L, val)
#define HAL_PPM_ISR_DISABLE() { cli(); }
#define HAL_PPM_ISR_ENABLE() { sei(); }
#define HAL_PPM_ISR_FLAG_SET() (1)
#define HAL_PPM_ISR_CLEAR_FLAG() { \
T1CTL &= ~(T1CTL_CH0_IF | T1CTL_CH1_IF | T1CTL_CH2_IF | T1CTL_OVFIF);}
#endif // SBUS_ENABLED
#endif // HAL_PPM_H_

View File

@@ -0,0 +1,22 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "sbus.h"

View File

@@ -0,0 +1,36 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_SBUS_H_
#define HAL_SBUS_H_
#include <stdint.h>
#include "hal_defines.h"
#include "hal_uart.h"
// this helper routine will invert the data
// stored in buffer in case the sbus is set
// to inverted
#ifdef SBUS_INVERTED
#define HAL_SBUS_PREPARE_DATA(a) (0xFF ^ (a))
#else
#define HAL_SBUS_PREPARE_DATA(a) (a)
#endif // SBUS_INVERTED
#endif // HAL_SBUS_H_

View File

@@ -0,0 +1,151 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_soft_serial.h"
#include "soft_serial.h"
#include "debug.h"
#include "delay.h"
#include "led.h"
#include "wdt.h"
#include "config.h"
#include "portmacros.h"
#include "hal_cc25xx.h"
#ifndef HUB_TELEMETRY_ON_SBUS_UART
void hal_soft_serial_init(void) {
debug("hal_soft_serial: init\n"); debug_flush();
hal_soft_serial_init_gpio();
hal_soft_serial_init_interrupts();
}
void hal_soft_serial_init_gpio(void) {
// set gpio as input
PORT2DIR(HUB_TELEMETRY_PORT) &= ~(1 << HUB_TELEMETRY_PIN);
}
void hal_soft_serial_init_interrupts(void) {
OVFIM = 0;
// disable compare modes
T4CCTL0 = 0;
T4CCTL1 = 0;
// tickspeed = 26MHz / 8 = 3,25MHz (TICKSPD is set in hal_timeout.c!)
// 1us = 3.25 ticks -> DIV2 -> 1us = 1.625 ticks
T4CTL = T4CTL_DIV_2 | // /2
T4CTL_START | // start
T4CTL_OVFIM | // OVInt enabled
T4CTL_CLR | // clear
T4CTL_MODE_MODULO; // 01 = count to CC and the overflow
// ch0 cmp: bit length
T4CC0 = HAL_SOFTSERIAL_BIT_DURATION_TICKS;
// clear pending interrupt flags (IRCON is reset by hw)
T4OVFIF = 0;
// overflow causes an int -> reload next channel data
OVFIM = 1;
// enable T4 interrups
IEN1 |= IEN1_T4IE;
// clear pending port ints
P0IFG = 0;
P0IF = 0;
// enable interrupts on P0 4...7
PICTL |= PICTL_P0IENH;
P0SEL &= ~(1<<6);
// set edge:
#ifdef HUB_TELEMETRY_INVERTED
// rising edge triggers isr
PICTL &= ~PICTL_P0ICON;
#else
// falling edge triggers isr
PICTL |= PICTL_P0ICON;
#endif // HUB_TELEMETRY_INVERTED
// T4 highest int prio (group4)
IP0 |= (1 << 4);
IP1 |= (1 << 4);
// P0 highest int prio (group5)
IP0 |= (1 << 5);
IP1 |= (1 << 5);
// enable interrupts from P0
P0IF = 0;
P0IFG = 0;
IEN1 |= IEN1_P0IE;
}
void hal_soft_serial_update_interrupt(void) __interrupt T4_VECTOR {
if (T4OVFIF) {
// DEBUG_PIN_TOGGLE();
// re-arm for the next bit
HAL_SOFT_SERIAL_UPDATE_TOP_VALUE(HAL_SOFTSERIAL_BIT_DURATION_TICKS-1);
if (soft_serial_process_databit()) {
// finished transmission, disable UP and enable IC isr
IEN1 |= IEN1_P0IE;
IEN1 &= ~IEN1_T4IE;
}
// clear pending interrupt flags (IRCON is reset by hw)
T4OVFIF = 0;
P0IFG = 0;
P0IF = 0;
}
}
void hal_soft_serial_startbit_interrupt(void) __interrupt P0INT_VECTOR {
uint8_t isr_cause = P0IFG;
// clear int flags WARNING: order seems to be important! CLR first IFG then IF!
P0IFG = 0;
// clear P0 int flags (important: several P0 pins can cause the isr, clean all of them!)
P0IF = 0;
if (isr_cause & (1 << HUB_TELEMETRY_PIN)) {
// DEBUG_PIN_TOGGLE();
// reset t3 counter:
T4CTL |= T4CTL_CLR;
// disable IC interrupt (only compare match interrupts will follow)
IEN1 &= ~IEN1_P0IE;
// enable overflow isr
IEN1 |= IEN1_T4IE;
// this is the startbit -> re synchronize the timer to this
// by setting the next cc interrupt to 1/2 bit length:
HAL_SOFT_SERIAL_UPDATE_TOP_VALUE((HAL_SOFTSERIAL_BIT_DURATION_TICKS / 2)-1);
// clear pending int flags
P0IF = 0;
T4OVFIF = 0;
// process
soft_serial_process_startbit();
}
}
#endif // HUB_TELEMETRY_ON_SBUS_UART

View File

@@ -0,0 +1,49 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_SOFT_SERIAL_H_
#define HAL_SOFT_SERIAL_H_
#include "hal_cc25xx.h"
#include "cc2510fx.h"
#include "config.h"
#ifndef HUB_TELEMETRY_ON_SBUS_UART
void hal_soft_serial_init(void);
void hal_soft_serial_init_gpio(void);
void hal_soft_serial_init_interrupts(void);
// at 9600 baud a bit duration is 1/9600s = 104.166667us
// the counter counts in 1/1.625th of us -> 104.1667us * 1.625
// = 169,27... -> 169 -> 0.16% error (thats ok..)
#define HAL_SOFTSERIAL_BIT_DURATION_TICKS (169)
#define HUB_TELEMETRY_PIN_HI() (HUB_TELEMETRY_PORT & (1 << HUB_TELEMETRY_PIN))
#define HUB_TELEMETRY_PIN_LO() (!HUB_TELEMETRY_PIN_HI())
#define HAL_SOFT_SERIAL_UPDATE_TOP_VALUE(x) { T4CC0 = x; }
extern void hal_soft_serial_update_interrupt(void) __interrupt T4_VECTOR;
extern void hal_soft_serial_startbit_interrupt(void) __interrupt P0INT_VECTOR;
#endif // HUB_TELEMETRY_ON_SBUS_UART
#endif // HAL_SOFT_SERIAL_H_

View File

@@ -0,0 +1,24 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_spi.h"
void hal_spi_init(void) {
}

View File

@@ -0,0 +1,26 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_SPI_H_
#define HAL_SPI_H_
void hal_spi_init(void);
#endif // HAL_SPI_H_

View File

@@ -0,0 +1,205 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_storage.h"
#include <cc2510fx.h>
#include "debug.h"
#include "main.h"
#include "delay.h"
#include "wdt.h"
__xdata HAL_DMA_DESC flash_dma_config;
// no ini value -> sdcc does not init this!
__code __at(STORAGE_LOCATION) uint8_t storage_on_flash[STORAGE_PAGE_SIZE];
void hal_storage_init(void) {
debug("hal_storage: init\n"); debug_flush();
}
void hal_storage_write(uint8_t *buffer, uint16_t len) {
hal_storage_flash_write((uint16_t)storage_on_flash, buffer, len);
}
void hal_storage_read(uint8_t *storage_ptr, uint16_t len) {
uint16_t i;
debug("hal_storage: loading from flash: "); debug_flush();
// copy from persistant flash to ram:
for (i = 0; i < len; i++) {
storage_ptr[i] = storage_on_flash[i];
debug_put_hex8(storage_on_flash[i]); debug_putc(' '); debug_flush();
wdt_reset();
}
}
static void hal_storage_flash_write(uint16_t address, uint8_t *data, uint16_t len) {
uint16_t i = 0;
uint8_t *flash_ptr = 0;
debug("hal_storage: will write page at 0x"); debug_flush();
debug_put_hex8(address >> 8);
debug_put_hex8(address & 0xff);
debug_put_newline();
// this is VERY important:
// make sure to write an even number of bytes!
// simply write one extra byte
if (len & 0x0001) {
debug("flash: corrected len to even\n");
len++;
}
// disable interrupts
cli();
// cancel _ALL_ ongoing DMA transfers:
DMAARM = DMA_ARM_ABORT | 0x1F;
// high prio
flash_dma_config.PRIORITY = DMA_PRI_HIGH;
// irrelevant since we use LEN for transfer count
flash_dma_config.M8 = DMA_M8_USE_8_BITS;
// disable ints from this ch
flash_dma_config.IRQMASK = DMA_IRQMASK_DISABLE;
// use dma flash data write complete trigger
flash_dma_config.TRIG = DMA_TRIG_FLASH;
// single mode, see datasheet
flash_dma_config.TMODE = DMA_TMODE_SINGLE;
// one byte
flash_dma_config.WORDSIZE = DMA_WORDSIZE_BYTE;
// set src: address of data to be written
SET_WORD(flash_dma_config.SRCADDRH, flash_dma_config.SRCADDRL, data);
// destination is flash controller data reg
SET_WORD(flash_dma_config.DESTADDRH, flash_dma_config.DESTADDRL, &X_FWDATA);
// use LEN
flash_dma_config.VLEN = DMA_VLEN_USE_LEN;
// set length
SET_WORD(flash_dma_config.LENH, flash_dma_config.LENL, len);
// set srcinc to 1 byte
flash_dma_config.SRCINC = DMA_SRCINC_1;
// fixed, always write to FWDATA
flash_dma_config.DESTINC = DMA_DESTINC_0;
// Save pointer to the DMA configuration struct into DMA-channel 0
// configuration registers
SET_WORD(DMA0CFGH, DMA0CFGL, flash_dma_config);
// waiting for the flash controller to be ready
while (FCTL & FCTL_BUSY) {}
// configure flash controller for 26mhz clock
FWT = 0x2A; // (21 * 26) / (16);
// set up address:
SET_WORD(FADDRH, FADDRL, ((uint16_t)address)>>1);
// re enable ints
sei();
debug("hal_storage: erasing page\n"); debug_flush();
// disable interrupts
cli();
// clear any pending flags
DMAIRQ = 0;
// erase that page
// has to be 2byte aligned. use a hack to place it at a given adress:
hal_storage_flash_erase_page();
// Wait for the erase operation to complete
while (FCTL & FCTL_BUSY) {}
// FCTL = 0;
// re enable ints
sei();
debug("hal_storage: erase done\n"); debug_flush();
debug("hal_storage: will write ["); debug_flush();
i = 0;
while (i < len) {
debug_put_hex8(((uint8_t *)data)[i++]);
debug_put_hex8(((uint8_t *)data)[i++]);
debug_putc(' ');
debug_flush();
}
debug("]\n");
debug("hal_storage: will write flash now\n"); debug_flush();
// disable interrupts
cli();
// arm the DMA channel, so that a DMA trigger will initiate DMA writing
DMAARM = DMA_ARM_CH0;
NOP();
// enable flash write. this generates a DMA trigger.
// must be aligned on a 2-byte boundary and is therefor implemented in assembly!
hal_storage_flash_enable_write();
// wait for dma finish
while (!(DMAIRQ & DMAIRQ_DMAIF0)) {
wdt_reset();
}
// wait until flash controller not busy
while (FCTL & (FCTL_BUSY | FCTL_SWBUSY)) {}
sei();
// by now, the transfer is completed, so the transfer count is reached.
// the DMA channel 0 interrupt flag is then set, so we clear it here.
DMAIRQ &= ~DMAIRQ_DMAIF0;
debug("hal_storage: read back [");
// copy from persistant flash to ram:
flash_ptr = address;
for (i = 0; i < len; i++) {
debug_put_hex8(*flash_ptr++); debug_putc(' '); debug_flush();
wdt_reset();
}
debug("]\n");
debug("hal_storage: write done");
}
void hal_storage_flash_enable_write(void) {
__asm
.even // IMPORTANT: PLACE THIS ON A 2BYTE BOUNDARY!
ORL _FCTL, #0x02; // FCTL |= FCTL_WRITE
NOP;
__endasm;
}
void hal_storage_flash_erase_page(void) {
__asm
.even // IMPORTANT: PLACE THIS ON A 2BYTE BOUNDARY!
ORL _FCTL, #0x01; // FCTL |= FCTL_ERASE
NOP; // required sequence!
__endasm;
}

View File

@@ -0,0 +1,45 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_STORAGE_H_
#define HAL_STORAGE_H_
#include <stdint.h>
#include "hal_cc25xx.h"
#include "hal_dma.h"
// place data on end of flash
// FIXME: this is for a cc2510f16 with flash size 0x4000, needs to be adjusted for bigger mcus
#define STORAGE_PAGE_SIZE 1024
#define STORAGE_LOCATION (0x4000-STORAGE_PAGE_SIZE)
// place persistant storage:
extern __code __at(STORAGE_LOCATION) uint8_t storage_on_flash[STORAGE_PAGE_SIZE];
extern __xdata HAL_DMA_DESC flash_dma_config;
void hal_storage_init(void);
void hal_storage_write(uint8_t *buffer, uint16_t len);
void hal_storage_read(uint8_t *storage_ptr, uint16_t len);
static void hal_storage_flash_write(uint16_t address, uint8_t *data, uint16_t len);
void hal_storage_flash_enable_write(void);
void hal_storage_flash_erase_page(void);
#endif // HAL_STORAGE_H_

View File

@@ -0,0 +1,135 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_timeout.h"
#include "delay.h"
#include "debug.h"
#include "timeout.h"
#include "hal_cc25xx.h"
// do not place this in xdata (faster this way)
volatile uint16_t hal_timeout_countdown;
volatile uint16_t hal_timeout2_countdown;
void hal_timeout_init(void) {
debug("hal_timeout: init\n"); debug_flush();
// timer clock
CLKCON = (CLKCON & ~CLKCON_TICKSPD_111) | CLKCON_TICKSPD_011;
// prepare timer3 for 1/25th ms steps:
// TICKSPD 011 -> /8 = 3250 kHz timer clock input
T3CTL = T3CTL_DIV_2 | // /2
T3CTL_START | // start
T3CTL_OVFIM | // OVInt enabled
T3CTL_CLR | // clear
T3CTL_MODE_MODULO; // 01 = count to CC and the overflow
// 3250/2/65 = 25khz
T3CC0 = 65-1;
// enable int
IEN1 |= (IEN1_T3IE);
timeout_set(0);
/*LED_RED_OFF();
while (1) {
timeout_set(990);
LED_GREEN_OFF();
while (!timeout_timed_out()) {}
timeout_set(10);
LED_GREEN_ON();
while (!timeout_timed_out()) {}
}*/
/* // TEST timings
P0DIR |= (1<<7);
while (1) {
timeout_set(1);
while (!timeout_timed_out()) {}
P0 |= (1<<7);
LED_RED_ON();
delay_ms(100);
P0 &= ~(1<<7);
LED_RED_OFF();
}*/
}
// prepare a new timeout
void hal_timeout_set(uint16_t timeout_ms) {
// disable T3ints:
IEN1 &= ~(IEN1_T3IE);
// clear counter
// T3CTL |= (1<<2);
// clear pending ints
// T3IF = 0;
// prepare timeout val:
hal_timeout_countdown = (timeout_ms * 25);
// clear pending ints
// T3IF = 0;
// re enable interrupts
IEN1 |= IEN1_T3IE;
}
uint8_t hal_timeout_timed_out(void) {
if (hal_timeout_countdown == 0) {
return 1;
} else {
return 0;
}
}
// prepare a new timeout
void hal_timeout2_set_100us(uint16_t timeout_100us) {
hal_timeout2_countdown = (timeout_100us * 25) / 10;
}
// prepare a new timeout
void hal_timeout2_set(uint16_t timeout_ms) {
hal_timeout2_countdown = (timeout_ms * 25);
}
uint8_t hal_timeout2_timed_out(void) {
if (hal_timeout2_countdown == 0) {
return 1;
} else {
return 0;
}
}
void hal_timeout_interrupt(void) __interrupt T3_VECTOR {
// clear flag
T3IF = 0;
if (hal_timeout_countdown != 0) {
hal_timeout_countdown--;
}
if (hal_timeout2_countdown != 0) {
hal_timeout2_countdown--;
}
}

View File

@@ -0,0 +1,38 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_TIMEOUT_H_
#define HAL_TIMEOUT_H_
#include <stdint.h>
#include "cc2510fx.h"
extern volatile uint16_t hal_timeout_countdown;
void hal_timeout_init(void);
void hal_timeout_set(uint16_t timeout_ms);
uint8_t hal_timeout_timed_out(void);
void hal_timeout2_set(uint16_t ms);
void hal_timeout2_set_100us(uint16_t hus);
uint8_t hal_timeout2_timed_out(void);
void hal_timeout_interrupt(void) __interrupt T3_VECTOR;
#endif // HAL_TIMEOUT_H_

View File

@@ -0,0 +1,258 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "cc2510fx.h"
#include "hal_cc25xx.h"
#include "hal_uart.h"
#include "hal_defines.h"
#include "hal_delay.h"
#include "config.h"
#include "hal_dma.h"
#include "uart.h"
#include "debug.h"
#include "wdt.h"
#include "delay.h"
#include "led.h"
void hal_uart_init(void) {
EXTERNAL_MEMORY union hal_uart_config_t sbus_uart_config;
#if SBUS_UART == USART0_P1
// -> USART0_P1
// use ALT2 -> Set flag -> P1_5 = TX / P1_4 = RX
PERCFG |= (PERCFG_U0CFG);
// configure pins as peripheral:
P1SEL |= (1<<5) | (1<<4);
// make sure all P0 pins switch to normal GPIO
P0SEL &= ~(0x3C);
// make tx pin output:
P1DIR |= (1<<5);
#elif SBUS_UART == USART1_P0
// USART1 use ALT1 -> Clear flag -> Port P0_4 = TX
PERCFG &= ~(PERCFG_U1CFG);
// USART1 has priority when USART0 is also enabled
P2DIR = (P2DIR & 0x3F) | 0b01000000;
// configure pin P0_4 (TX) and P0_5 (RX) as special function:
P0SEL |= (1<<4) | (1<<5);
// make sure all P1 pins switch to normal GPIO
// P1SEL &= ~(0xF0);
// make tx pin output:
P0DIR |= (1<<4);
#elif SBUS_UART == USART1_P1
// USART1 use ALT2 -> SET flag -> Port P1_6 = TX
PERCFG |= (PERCFG_U1CFG);
// USART1 has priority when USART0 is also enabled
P2DIR = (P2DIR & 0x3F) | 0b01000000;
// configure pin P1_6 (TX) and P1_7(RX) as special function:
P1SEL |= (1<<6) | (1<<7);
// make tx pin output:
P1DIR |= (1<<6);
#else
#error "UNSUPPORTED UART"
#endif // SBUS_UART == ...
// set baudrate
#if (SBUS_UART == USART0_P1) || (SBUS_UART == USART0_P0)
U0BAUD = CC2510_BAUD_M_100000;
U0GCR = (U0GCR & ~0x1F) | (CC2510_BAUD_E_100000);
#else
U1BAUD = CC2510_BAUD_M_100000;
U1GCR = (U1GCR & ~0x1F) | (CC2510_BAUD_E_100000);
#endif // SBUS_UART == ...
// set up config for USART -> 8E2
#ifdef SBUS_INVERTED
// this is a really nice feature of the cc2510:
// we can invert the idle level of the usart
// by setting STOP to zero. by inverting
// the parity, the startbit, and the data
// by using the SBUS_PREPARE_DATA() macro
// we can effectively invert the usart in software :)
sbus_uart_config.bit.START = 1; // startbit level = low
sbus_uart_config.bit.STOP = 0; // stopbit level = high
sbus_uart_config.bit.D9 = 1; // UNEven parity
#else
// standard usart, non-inverted mode
// NOTE: most sbus implementations use inverted mode
sbus_uart_config.bit.START = 0; // startbit level = low
sbus_uart_config.bit.STOP = 1; // stopbit level = high
sbus_uart_config.bit.D9 = 0; // Even parity
#endif // SBUS_INVERTED
sbus_uart_config.bit.SPB = 1; // 1 = 2 stopbits
sbus_uart_config.bit.PARITY = 1; // 1 = parity enabled, D9=0 -> even parity
sbus_uart_config.bit.BIT9 = 1; // 8bit
sbus_uart_config.bit.FLOW = 0; // no hw flow control
sbus_uart_config.bit.ORDER = 0; // lsb first
// activate uart config
hal_uart_set_mode(&sbus_uart_config);
// use dma channel 3 for transmission:
hal_dma_config[3].PRIORITY = DMA_PRI_LOW;
hal_dma_config[3].M8 = DMA_M8_USE_7_BITS;
hal_dma_config[3].IRQMASK = DMA_IRQMASK_DISABLE;
#if (SBUS_UART == USART0_P1) || (SBUS_UART == USART0_P0)
hal_dma_config[3].TRIG = DMA_TRIG_UTX0;
#else
hal_dma_config[3].TRIG = DMA_TRIG_UTX1;
#endif // SBUS_UART == ...
hal_dma_config[3].TMODE = DMA_TMODE_SINGLE;
hal_dma_config[3].WORDSIZE = DMA_WORDSIZE_BYTE;
// source address will be set during tx start
SET_WORD(hal_dma_config[3].SRCADDRH, hal_dma_config[3].SRCADDRL, 0);
#if (SBUS_UART == USART0_P1) || (SBUS_UART == USART0_P0)
SET_WORD(hal_dma_config[3].DESTADDRH, hal_dma_config[3].DESTADDRL, &X_U0DBUF);
#else
SET_WORD(hal_dma_config[3].DESTADDRH, hal_dma_config[3].DESTADDRL, &X_U1DBUF);
#endif // SBUS_UART == ...
hal_dma_config[3].VLEN = DMA_VLEN_USE_LEN;
// len will be set during tx start
SET_WORD(hal_dma_config[3].LENH, hal_dma_config[3].LENL, 0);
// configure src and dest increments
hal_dma_config[3].SRCINC = DMA_SRCINC_1;
hal_dma_config[3].DESTINC = DMA_DESTINC_0;
// set pointer to the DMA configuration struct into DMA-channel 1-4
// configuration, should have happened in adc.c already...
SET_WORD(DMA1CFGH, DMA1CFGL, &hal_dma_config[1]);
// arm the relevant DMA channel for UART TX, and apply 45 NOP's
// to allow the DMA configuration to load
// -> do a sleep instead of those nops...
DMAARM |= DMA_ARM_CH3;
hal_delay_45nop();
#ifdef HUB_TELEMETRY_ON_SBUS_UART
// activate serial rx interrupt
#if (SBUS_UART == USART0_P1) || (SBUS_UART == USART0_P0)
URX0IF = 0;
// enable receiption
U0CSR |= UxCSR_RX_ENABLE;
// enable RX interrupt
URX0IE = 1;
#else
URX1IF = 0;
// enable receiption
U1CSR |= UxCSR_RX_ENABLE;
// enable RX interrupt
URX1IE = 1;
#endif // HUB_TELEMETRY_ON_SBUS_UART
// enable global ints
EA = 1;
#endif // SBUS_UART == ...
}
static void hal_uart_set_mode(EXTERNAL_MEMORY union hal_uart_config_t *cfg) {
#if (SBUS_UART == USART0_P1) || (SBUS_UART == USART0_P0)
// enable uart mode
U0CSR |= 0x80;
// store config to U1UCR register
U0UCR = cfg->byte & (0x7F);
// store config to U1GCR: (msb/lsb)
if (cfg->bit.ORDER) {
U0GCR |= U0GCR_ORDER;
} else {
U0GCR &= ~U0GCR_ORDER;
}
// interrupt prio to 1 (0..3=highest)
IP0 |= (1<<2);
IP1 &= ~(1<<2);
#else
// enable uart mode
U1CSR |= 0x80;
// store config to U1UCR register
U1UCR = cfg->byte & (0x7F);
// store config to U1GCR: (msb/lsb)
if (cfg->bit.ORDER) {
U1GCR |= U1GCR_ORDER;
} else {
U1GCR &= ~U1GCR_ORDER;
}
// interrupt prio to 1 (0..3=highest)
IP0 |= (1<<3);
IP1 &= ~(1<<3);
#endif // SBUS_UART
}
void hal_uart_start_transmission(uint8_t *data, uint8_t len) {
// important: src addr start is data[1]
SET_WORD(hal_dma_config[3].SRCADDRH, hal_dma_config[3].SRCADDRL, &data[1]);
// configure length of transfer
SET_WORD(hal_dma_config[3].LENH, hal_dma_config[3].LENL, len);
// time to send this frame!
// re-arm dma:
DMAARM |= DMA_ARM_CH3;
// 45 nops to make sure the dma config is loaded
hal_delay_45nop();
// send the very first UART byte to trigger a UART TX session:
#if (SBUS_UART == USART0_P1) || (SBUS_UART == USART0_P0)
U0DBUF = data[0];
#else
U1DBUF = data[0];
#endif // SBUS_UART
}
#ifdef HUB_TELEMETRY_ON_SBUS_UART
void HAL_UART_RX_ISR(void) {
uint8_t rx;
HAL_UART_RX_ISR_CLEAR_FLAG(); // THIS SHOULD NEVER BE THE LAST LINE IN AN ISR!
#ifdef SBUS_INVERTED
rx = 0xFF ^ HAL_UART_RX_GETCH(); // remove data inversion
#else
rx = HAL_UART_RX_GETCH();
#endif // SBUS_INVERTED
if (uart_rx_callback != 0) {
// execute callback
uart_rx_callback(rx);
}
}
#endif // HUB_TELEMETRY_ON_SBUS_UART

View File

@@ -0,0 +1,68 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_UART_H_
#define HAL_UART_H_
#include <stdint.h>
#include "hal_defines.h"
// for a 26MHz Crystal:
#define CC2510_BAUD_E_115200 12
#define CC2510_BAUD_M_115200 34
// best match for 100kbit/s = 99975.5859375 bit/s
// baudrate = (((256.0 + baud_m)*2.0**baud_e) / (2**28)) * 26000000.0
#define CC2510_BAUD_E_100000 11
#define CC2510_BAUD_M_100000 248
#define CC2510_BAUD_E_57600 11
#define CC2510_BAUD_M_57600 34
union hal_uart_config_t{
uint8_t byte;
struct {
uint8_t START : 1; // start bit level
uint8_t STOP : 1; // stop bit level
uint8_t SPB : 1; // stop bits (0=1, 1=2)
uint8_t PARITY: 1; // parity (on/off)
uint8_t BIT9 : 1; // 9 bit mode
uint8_t D9 : 1; // 9th bit level or parity type
uint8_t FLOW : 1; // flow control
uint8_t ORDER : 1; // data bit order (LSB or MSB first)
} bit;
};
void hal_uart_init(void);
static void hal_uart_set_mode(EXTERNAL_MEMORY union hal_uart_config_t *cfg);
void hal_uart_start_transmission(uint8_t *data, uint8_t len);
#ifdef HUB_TELEMETRY_ON_SBUS_UART
#if (SBUS_UART == USART0_P1) || (SBUS_UART == USART0_P0)
#define HAL_UART_RX_ISR(void) hal_uart_rx_interrupt(void) __interrupt URX0_VECTOR
#define HAL_UART_RX_ISR_CLEAR_FLAG() { URX0IF = 0; }
#define HAL_UART_RX_GETCH() (U0DBUF)
#else
#define HAL_UART_RX_ISR(void) hal_uart_rx_interrupt(void) __interrupt URX1_VECTOR
#define HAL_UART_RX_ISR_CLEAR_FLAG() { URX1IF = 0; }
#define HAL_UART_RX_GETCH() (U1DBUF)
#endif // SBUS_UART == ...
void HAL_UART_RX_ISR(void);
#endif // HUB_TELEMETRY_ON_SBUS_UART
#endif // HAL_UART_H_

View File

@@ -0,0 +1,50 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#include "hal_wdt.h"
#include "debug.h"
#include "led.h"
#include "delay.h"
#include "hal_cc25xx.h"
void hal_wdt_init(void) {
// check if 32khz clock source is rcosc:
if (!(CLKCON & CLKCON_OSC32K)) {
debug("wdt: error! low speed clock not based on int rc");
led_green_on();
while (1) {
led_red_on();
delay_ms(200);
led_red_off();
delay_ms(200);
}
}
// set wdt interval to approx 1 second
WDCTL = (WDCTL & ~WDCTL_INT) | WDCTL_INT_1S;
// enable wdt. NOTE: this can not be disabled in software!
WDCTL = (WDCTL & ~WDCTL_MODE) | WDCTL_EN;
}
void hal_wdt_reset(void) {
// reset wdt (special sequence)
WDCTL = (WDCTL & 0x0F) | 0b10100000;
WDCTL = (WDCTL & 0x0F) | 0b01010000;
}

View File

@@ -0,0 +1,26 @@
/*
Copyright 2017 fishpepper <AT> gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http:// www.gnu.org/licenses/>.
author: fishpepper <AT> gmail.com
*/
#ifndef HAL_WDT_H_
#define HAL_WDT_H_
void hal_wdt_init(void);
void hal_wdt_reset(void);
#endif // HAL_WDT_H_

View File

@@ -0,0 +1,13 @@
#ifndef __PORTMACROS_H__
#define __PORTMACROS_H__
#define PORT2DIR_(X) X ## DIR
#define PORT2DIR(PORTNAME) PORT2DIR_(PORTNAME)
#define PORT2BIT_(X,N) X ## _ ## N
#define PORT2BIT(PORTNAME, PIN) PORT2BIT_(PORTNAME,PIN)
#define PORT2INP_(X) X ## INP
#define PORT2INP(PORTNAME) PORT2INP_(PORTNAME)
#endif