Added power interface test program
This commit is contained in:
parent
e7cf27851f
commit
aaa925eeb7
3 changed files with 413 additions and 0 deletions
115
poweriface/firmware/Makefile
Normal file
115
poweriface/firmware/Makefile
Normal file
|
@ -0,0 +1,115 @@
|
|||
PRG = poweriface
|
||||
AVRCANLIB_PATH = ../../avr-can-lib
|
||||
OBJ = main.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_buffer.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_disable_dyn_filter.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_error_register.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_get_buf_message.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_get_dyn_filter.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_get_message.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_send_buf_message.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_send_message.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_set_dyn_filter.o \
|
||||
$(AVRCANLIB_PATH)/src/at90can_set_mode.o \
|
||||
$(AVRCANLIB_PATH)/src/can_buffer.o
|
||||
# These were defined for the avr-can-lib, but they really, really
|
||||
# shouldn't be used there because they affect the whole program.
|
||||
OPTIMIZE = -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
|
||||
PROGRAMMER = usbtiny
|
||||
|
||||
MCU_TARGET = atmega32m1
|
||||
DEFS = -DF_CPU=16000000UL -DHAS_CAN_CONFIG_H
|
||||
|
||||
INCLUDES = -I. -I$(AVRCANLIB_PATH)
|
||||
LIBS =
|
||||
|
||||
LFUSE = 0xdf
|
||||
HFUSE = 0xd9
|
||||
EFUSE = 0xfe
|
||||
|
||||
EXTRA_CLEAN_FILES =
|
||||
|
||||
# You should not have to change anything below here.
|
||||
|
||||
CC = avr-gcc
|
||||
DUDE = avrdude
|
||||
|
||||
HOST_CC = gcc
|
||||
HOST_CFLAGS = -O0 -g
|
||||
HOST_LDFLAGS =
|
||||
|
||||
# Override is only needed by avr-lib build system.
|
||||
|
||||
override CFLAGS = -g -Wall $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) $(INCLUDES)
|
||||
override LDFLAGS = -Wl,-Map,$(PRG).map
|
||||
|
||||
DUDEFLAGS = -c $(PROGRAMMER) -p $(MCU_TARGET)
|
||||
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
|
||||
all: $(PRG).elf lst text eeprom
|
||||
|
||||
$(PRG).elf: $(OBJ) $(LIBS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJ) $(PRG).elf $(PRG).lst $(PRG).map $(PRG).bin $(PRG).hex $(PRG).srec $(PRG)_eeprom.bin $(PRG)_eeprom.hex $(PRG)_eeprom.srec $(EXTRA_CLEAN_FILES)
|
||||
|
||||
lst: $(PRG).lst
|
||||
|
||||
%.lst: %.elf
|
||||
$(OBJDUMP) -h -S $< > $@
|
||||
|
||||
# Rules for flashing, EEPROM writing and fuse bit setting
|
||||
|
||||
flash: $(PRG).hex $(PRG)_eeprom.hex
|
||||
$(DUDE) $(DUDEFLAGS) -U eeprom:w:$(PRG)_eeprom.hex:i -U flash:w:$(PRG).hex:i
|
||||
|
||||
flashprg: $(PRG).hex
|
||||
$(DUDE) $(DUDEFLAGS) -U flash:w:$(PRG).hex:i
|
||||
|
||||
flasheep: $(PRG)_eeprom.hex
|
||||
$(DUDE) $(DUDEFLAGS) -U eeprom:w:$(PRG)_eeprom.hex:i
|
||||
|
||||
fuse:
|
||||
$(DUDE) $(DUDEFLAGS) -U hfuse:w:$(HFUSE):m -U lfuse:w:$(LFUSE):m -U efuse:w:$(EFUSE):m
|
||||
|
||||
# Rules for building the .text rom images
|
||||
|
||||
text: hex bin srec
|
||||
|
||||
hex: $(PRG).hex
|
||||
bin: $(PRG).bin
|
||||
srec: $(PRG).srec
|
||||
|
||||
%.hex: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O ihex $< $@
|
||||
|
||||
%.srec: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O srec $< $@
|
||||
|
||||
%.bin: %.elf
|
||||
$(OBJCOPY) -j .text -j .data -O binary $< $@
|
||||
|
||||
# Rules for building the .eeprom rom images
|
||||
|
||||
eeprom: ehex ebin esrec
|
||||
|
||||
ehex: $(PRG)_eeprom.hex
|
||||
ebin: $(PRG)_eeprom.bin
|
||||
esrec: $(PRG)_eeprom.srec
|
||||
|
||||
%_eeprom.hex: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@ \
|
||||
|| { echo empty $@ not generated; exit 0; }
|
||||
|
||||
%_eeprom.srec: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O srec $< $@ \
|
||||
|| { echo empty $@ not generated; exit 0; }
|
||||
|
||||
%_eeprom.bin: %.elf
|
||||
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O binary $< $@ \
|
||||
|| { echo empty $@ not generated; exit 0; }
|
||||
|
79
poweriface/firmware/can_config.h
Normal file
79
poweriface/firmware/can_config.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define CAN_CONFIG_LOADED
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/* Global settings for building the can-lib and application program.
|
||||
*
|
||||
* The following two #defines must be set identically for the can-lib and
|
||||
* your application program. They control the underlying CAN struct. If the
|
||||
* settings disagree, the underlying CAN struct will be broken, with
|
||||
* unpredictable results.
|
||||
* If can.h detects that any of the #defines is not defined, it will set them
|
||||
* to the default values shown here, so it is in your own interest to have a
|
||||
* consistent setting. Ommiting the #defines in both can-lib and application
|
||||
* program will apply the defaults in a consistent way too.
|
||||
*
|
||||
* Select if you want to use 29 bit identifiers.
|
||||
*/
|
||||
#define SUPPORT_EXTENDED_CANID 1
|
||||
|
||||
/* Select if you want to use timestamps.
|
||||
* Timestamps are sourced from a register internal to the AT90CAN.
|
||||
* Selecting them on any other controller will have no effect, they will
|
||||
* be 0 all the time.
|
||||
*/
|
||||
#define SUPPORT_TIMESTAMPS 0
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/* Global settings for building the can-lib.
|
||||
*
|
||||
* Select ONE CAN controller for which you are building the can-lib.
|
||||
*/
|
||||
#define SUPPORT_MCP2515 0
|
||||
#define SUPPORT_AT90CAN 1
|
||||
#define SUPPORT_SJA1000 0
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
/* Setting for MCP2515
|
||||
*
|
||||
* Declare which pins you are using for communication.
|
||||
* Remember NOT to use them in your application!
|
||||
* It is a good idea to use bits from the port that carries MOSI, MISO, SCK.
|
||||
*/
|
||||
#define MCP2515_CS B,4
|
||||
#define MCP2515_INT B,2
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Setting for SJA1000
|
||||
|
||||
#define SJA1000_INT E,0
|
||||
#define SJA1000_MEMORY_MAPPED 1
|
||||
|
||||
// memory-mapped interface
|
||||
#define SJA1000_BASE_ADDR 0x8000 // for ATMega162
|
||||
|
||||
/*
|
||||
// port-interface
|
||||
#define SJA1000_WR D,6
|
||||
#define SJA1000_RD D,7
|
||||
|
||||
#define SJA1000_ALE E,1
|
||||
#define SJA1000_CS C,0
|
||||
#define SJA1000_DATA A
|
||||
*/
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Setting for AT90CAN
|
||||
|
||||
// Number of CAN messages which are buffered in RAM additinally to the MObs
|
||||
#define CAN_RX_BUFFER_SIZE 16
|
||||
#define CAN_TX_BUFFER_SIZE 8
|
||||
|
||||
// only available if CAN_TX_BUFFER_SIZE > 0
|
||||
#define CAN_FORCE_TX_ORDER 1
|
||||
|
||||
#endif // CONFIG_H
|
219
poweriface/firmware/main.c
Normal file
219
poweriface/firmware/main.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
#include <inttypes.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/delay.h>
|
||||
#include <can.h>
|
||||
|
||||
#if ENABLE_SLEEP
|
||||
#include <avr/sleep.h>
|
||||
#endif
|
||||
#if ENABLE_WATCHDOG
|
||||
#include <avr/watchdog.h>
|
||||
#endif
|
||||
|
||||
// Global state
|
||||
struct {
|
||||
#if ENABLE_SHUTDOWN
|
||||
// Main loop run state (1 = running, 0 = shutdown)
|
||||
uint8_t run;
|
||||
#endif
|
||||
// Message ready?
|
||||
uint8_t ready;
|
||||
// Receive buffer
|
||||
uint8_t buffer[8];
|
||||
// Message address
|
||||
uint32_t address;
|
||||
} state; //__attribute__ ((section (".noinit")));
|
||||
|
||||
inline void init(); // __attribute__((always_inline));
|
||||
inline void shutdown(); // __attribute__((always_inline));
|
||||
|
||||
inline void init() {
|
||||
// Disable interrupts before init
|
||||
cli();
|
||||
|
||||
// Set state
|
||||
//state.run = 0;
|
||||
|
||||
#if ENABLE_WATCHDOG
|
||||
// Enable watchdog timer
|
||||
wdt_enable(WDTO_500MS);
|
||||
#endif
|
||||
|
||||
// Set clock divider to 1 after startup
|
||||
// This is an alternative to clearing the CLKDIV8 fuse
|
||||
// CLKPR = _BV(CLKPCE);
|
||||
// CLKPR = 0x00;
|
||||
|
||||
// Enable GPIO and set low
|
||||
// PORTB |= _BV(PB5);
|
||||
PORTB &= ~(_BV(PB2) | _BV(PB3) | _BV(PB4));
|
||||
DDRB |= (_BV(PB2) | _BV(PB3) | _BV(PB4));
|
||||
}
|
||||
|
||||
inline void shutdown() {
|
||||
// Disable interrupts
|
||||
// Not needed when not using sleep, the compiler will generate a cli+busy loop
|
||||
#if ENABLE_SLEEP
|
||||
cli();
|
||||
#endif
|
||||
|
||||
#if ENABLE_WATCHDOG
|
||||
// Disable watchdog
|
||||
wdt_disable();
|
||||
#endif
|
||||
}
|
||||
|
||||
// UART bit-uart_bang 8 bits on the debug port, LSB first, 1 stop bit, no parity, 9600 baud
|
||||
void uart_bang(uint8_t data) {
|
||||
// Start bit: low
|
||||
PORTB &= ~_BV(PB4);
|
||||
_delay_us(102);
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
// data bit
|
||||
if (data & (_BV(i))) {
|
||||
PORTB |= _BV(PB4);
|
||||
} else {
|
||||
PORTB &= ~_BV(PB4);
|
||||
}
|
||||
_delay_us(102);
|
||||
}
|
||||
// Stop bit: high (and stay there after)
|
||||
PORTB |= _BV(PB4);
|
||||
_delay_us(102);
|
||||
}
|
||||
|
||||
// Bit-bang pattern (LSB first) out the data line and strobe
|
||||
uint16_t bang(uint16_t data) {
|
||||
uint16_t in = 0;
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
// Data bit
|
||||
if (data & 1) {
|
||||
PORTB |= _BV(PB4);
|
||||
} else {
|
||||
PORTB &= ~_BV(PB4);
|
||||
}
|
||||
// Clock
|
||||
PORTB |= _BV(PB2);
|
||||
_delay_us(4);
|
||||
PORTB &= ~_BV(PB2);
|
||||
_delay_us(4);
|
||||
// Read
|
||||
if (PINB & _BV(PB5)) {
|
||||
in |= 1;
|
||||
}
|
||||
// Shift
|
||||
data >>= 1;
|
||||
in <<= 1;
|
||||
}
|
||||
// Strobe
|
||||
PORTB |= _BV(PB3);
|
||||
_delay_us(4);
|
||||
PORTB &= ~_BV(PB3);
|
||||
// Clear
|
||||
PORTB &= ~_BV(PB4);
|
||||
return in;
|
||||
}
|
||||
|
||||
int main() {
|
||||
// Initialize hardware
|
||||
init();
|
||||
// Initialize CAN interface
|
||||
can_init(BITRATE_125_KBPS);
|
||||
// Set up command filter
|
||||
can_set_mode(NORMAL_MODE);
|
||||
can_filter_t filter = {
|
||||
.id = 0x100,
|
||||
.mask = 0x1ff,
|
||||
.flags = {
|
||||
.rtr = 0,
|
||||
.extended = 0,
|
||||
},
|
||||
};
|
||||
can_set_filter(0, &filter);
|
||||
// wait before start
|
||||
//_delay_ms(10000);
|
||||
|
||||
// Enable interrupts to start reception
|
||||
sei();
|
||||
|
||||
// Main loop
|
||||
#if ENABLE_SHUTDOWN
|
||||
state.run = 1;
|
||||
while (state.run) {
|
||||
#else
|
||||
while (1) {
|
||||
#endif
|
||||
#if 0
|
||||
// Test pattern
|
||||
for (uint8_t i = 0; i < 5; i++) {
|
||||
bang(0x0080 >> i);
|
||||
_delay_ms(1000);
|
||||
bang(0x0000);
|
||||
_delay_ms(1000);
|
||||
}
|
||||
#else
|
||||
// Check for new messages
|
||||
if (can_check_message()) {
|
||||
can_t msg = { 0 };
|
||||
uint8_t status = can_get_message(&msg);
|
||||
// uart_bang(status);
|
||||
uint16_t in = 0;
|
||||
if (status != 0 && msg.id == 0x100 && msg.length == 1) {
|
||||
// uart_bang(msg.id & 0xff);
|
||||
// uart_bang((msg.id >> 8) & 0xff);
|
||||
// uart_bang((msg.id >> 16) & 0xff);
|
||||
// uart_bang((msg.id >> 24) & 0xff);
|
||||
// uart_bang(msg.flags.rtr);
|
||||
// uart_bang(msg.flags.extended);
|
||||
// uart_bang(msg.length);
|
||||
// for (uint8_t i = 0; i < msg.length; i++) {
|
||||
// uart_bang(msg.data[i]);
|
||||
// }
|
||||
//uint16_t out = msg.data[0] | ((uint16_t) msg.data[1] << 8);
|
||||
if (msg.data[0] < 5) {
|
||||
uint16_t out = 0x0080 >> msg.data[0];
|
||||
bang(out);
|
||||
_delay_ms(3000);
|
||||
in = bang(0x0000);
|
||||
}
|
||||
//in = bang(0xffff);
|
||||
}
|
||||
if (can_check_free_buffer()) {
|
||||
can_t msg = {
|
||||
.id = 0x11,
|
||||
.flags = {
|
||||
.rtr = 0,
|
||||
.extended = 0,
|
||||
},
|
||||
.length = 5,
|
||||
.data = { 0xc0, 0xff, 0xee, in & 0xff, (in >> 8) & 0xff, },
|
||||
};
|
||||
uint8_t status = can_send_message(&msg);
|
||||
// uart_bang(status);
|
||||
} else {
|
||||
// uart_bang(0xff);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_SLEEP
|
||||
// Let the MCU take a nap
|
||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||
sleep_mode();
|
||||
#endif
|
||||
}
|
||||
|
||||
// Disable all peripherals and interrupts
|
||||
shutdown();
|
||||
|
||||
// Power the MCU down
|
||||
#if ENABLE_SLEEP
|
||||
while (1) {
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||
sleep_mode();
|
||||
}
|
||||
__builtin_unreachable();
|
||||
#endif
|
||||
}
|
||||
|
Loading…
Reference in a new issue