Skip to content

Commit

Permalink
SPI: Implemented MISO, MOSI, SCK and SS pins handling using avr_bitba…
Browse files Browse the repository at this point in the history
…ng functions.
  • Loading branch information
hovercraft-github committed May 16, 2018
1 parent 5669a06 commit dfc7fbe
Show file tree
Hide file tree
Showing 20 changed files with 427 additions and 38 deletions.
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega128.c
Expand Up @@ -391,7 +391,7 @@ const struct mcu_t {
.vector = TIMER3_CAPT_vect,
},
},
AVR_SPI_DECLARE(0, 0),
AVR_SPI_DECLARE(0, 0, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega1280.c
Expand Up @@ -616,7 +616,7 @@ const struct mcu_t {
},

},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega1281.c
Expand Up @@ -431,7 +431,7 @@ const struct mcu_t {
.vector = TIMER3_CAPT_vect,
},
},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega128rfr2.c
Expand Up @@ -469,7 +469,7 @@ const struct mcu_t {
.vector = TIMER3_CAPT_vect,
},
},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega169.c
Expand Up @@ -319,7 +319,7 @@ const struct mcu_t {
},
},
},
AVR_SPI_DECLARE(PRR, PRSPI),
AVR_SPI_DECLARE(PRR, PRSPI, 'B', 1, 3, 2, 0),
};

static avr_t * make()
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_mega2560.c
Expand Up @@ -618,7 +618,7 @@ const struct mcu_t {
},

},
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 1, 3, 2, 0),
.twi = {

.r_twcr = TWCR,
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_megax.h
Expand Up @@ -301,7 +301,7 @@ const struct mcu_t SIM_CORENAME = {
},
},
},
AVR_SPI_DECLARE(0, 0),
AVR_SPI_DECLARE(0, 0, 'B', 7, 6, 5, 4),
.twi = {

.r_twcr = TWCR,
Expand Down
4 changes: 2 additions & 2 deletions simavr/cores/sim_megax4.h
Expand Up @@ -432,9 +432,9 @@ const struct mcu_t SIM_CORENAME = {
},
#endif
#ifdef MSTR0 /* xx4a and xx4pa series */
AVR_SPIX_DECLARE(0, PRR0, PRSPI),
AVR_SPIX_DECLARE(0, PRR0, PRSPI, 'B', 7, 6, 5, 4),
#else
AVR_SPI_DECLARE(PRR0, PRSPI),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 7, 6, 5, 4),
#endif
.twi = {
.disabled = AVR_IO_REGBIT(PRR0,PRTWI),
Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_megax8.h
Expand Up @@ -345,7 +345,7 @@ const struct mcu_t SIM_CORENAME = {
}
}
},
AVR_SPI_DECLARE(PRR, PRSPI),
AVR_SPI_DECLARE(PRR, PRSPI, 'B', 5, 4, 3, 2),
.twi = {
.disabled = AVR_IO_REGBIT(PRR,PRTWI),

Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_megaxm1.h
Expand Up @@ -311,7 +311,7 @@ const struct mcu_t SIM_CORENAME = {
},
},
},
AVR_SPI_DECLARE(PRR, PRSPI),
AVR_SPI_DECLARE(PRR, PRSPI, 'C', 7, 0, 1, 1),
};
#endif /* SIM_CORENAME */

Expand Down
2 changes: 1 addition & 1 deletion simavr/cores/sim_usb162.c
Expand Up @@ -202,7 +202,7 @@ const struct mcu_t {
},
},
},
AVR_SPI_DECLARE(0, 0),
AVR_SPI_DECLARE(PRR0, PRSPI, 'B', 7, 6, 5, 4),
.usb = {
.name='1',
.disabled=AVR_IO_REGBIT(PRR1, PRUSB),// bit in the PRR
Expand Down
38 changes: 38 additions & 0 deletions simavr/sim/avr/avr_mcu_section.h
Expand Up @@ -63,6 +63,7 @@ enum {
AVR_MMCU_TAG_VCD_PORTPIN,
AVR_MMCU_TAG_VCD_IRQ,
AVR_MMCU_TAG_PORT_EXTERNAL_PULL,
AVR_MMCU_TAG_BITBANG,
};

enum {
Expand All @@ -72,6 +73,18 @@ enum {
SIMAVR_CMD_UART_LOOPBACK,
};

#define BITBANG_ON_SPI(_name) \
((uint64_t)(_name >= '0' ? ((1 << (_name - '0'))&0xFF) : (1 << 8)) << 0)

#define BITBANG_ON_UART(_name) \
((uint64_t)((1 << (_name - '0'))&0xFF) << 16)

#define BITBANG_ON_TWI(_name) \
((uint64_t)(1) << 24)

#define BITBANG_ON_LIN(_name) \
((uint64_t)(1) << 32)

#if __AVR__
/*
* WARNING. Due to newer GCC being stupid, they introduced a bug that
Expand All @@ -87,6 +100,12 @@ struct avr_mmcu_long_t {
uint32_t val;
} __attribute__((__packed__));

struct avr_mmcu_longlong_t {
uint8_t tag;
uint8_t len;
uint64_t val;
} __attribute__((__packed__));

struct avr_mmcu_string_t {
uint8_t tag;
uint8_t len;
Expand Down Expand Up @@ -121,6 +140,13 @@ struct avr_mmcu_vcd_trace_t {
#define DO_CONCAT2(_a, _b) _a##_b
#define DO_CONCAT(_a, _b) DO_CONCAT2(_a,_b)

#define AVR_MCU_LONGLONG(_tag, _val) \
const struct avr_mmcu_longlong_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\
.tag = _tag,\
.len = sizeof(struct avr_mmcu_longlong_t) - 2,\
.val = _val,\
}

#define AVR_MCU_LONG(_tag, _val) \
const struct avr_mmcu_long_t DO_CONCAT(DO_CONCAT(_, _tag), __LINE__) _MMCU_ = {\
.tag = _tag,\
Expand All @@ -131,6 +157,18 @@ struct avr_mmcu_vcd_trace_t {
#define AVR_MCU_BYTE(_tag, _val) \
const uint8_t _##_tag _MMCU_ = { _tag, 1, _val }

/*!
* This Macro allows you turn on or off a bitbang feature for
* peripherals, which support it (plese look code of the corresponding
* module to ensure it's implemented).
* By default bitbang is off for every peripheral.
* You can turn it on using bitmask for specific peripheral instance,
* e.g. the following turns it on for SPI0 and for USART1 in SPI mode:
* AVR_MCU_BITBANG(BITBANG_ON_SPI(0) | BITBANG_ON_SPI('1'));
*/
#define AVR_MCU_BITBANG(_peripheral_on_mask) \
AVR_MCU_LONGLONG(AVR_MMCU_TAG_BITBANG, _peripheral_on_mask)

/*!
* This Macro allows you to specify traces for the VCD file output
* engine. This specifies a default header, and let you fill in the
Expand Down
49 changes: 45 additions & 4 deletions simavr/sim/avr_bitbang.c
Expand Up @@ -29,6 +29,7 @@ extern "C" {

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "avr_bitbang.h"

Expand Down Expand Up @@ -99,7 +100,12 @@ static void avr_bitbang_write_bit(avr_bitbang_t *p)

// output to HW pin
if ( p->p_out.port ) {
avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_out.port ), p->p_out.pin), bit);
avr_raise_irq(p->p_out.irq, bit);
uint16_t addr = p->p_out.ioport->r_port;
uint8_t value = (p->avr->data[addr] & ~(1 << p->p_out.pin)) | (!!bit << p->p_out.pin);
// at least avr->data[addr] update is required, otherwise port state is broken
// also triggering vcd signal would be nice here
avr_core_watch_write(p->avr, addr, value);
}

// module callback
Expand Down Expand Up @@ -130,7 +136,12 @@ static void avr_bitbang_clk_edge(avr_bitbang_t *p)

// generate clock output on HW pin
if ( p->clk_generate && p->p_clk.port ) {
avr_raise_irq(avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), clk);
avr_raise_irq(p->p_clk.irq, clk);
uint16_t addr = p->p_clk.ioport->r_port;
uint8_t value = (p->avr->data[addr] & ~(1 << p->p_clk.pin)) | (!!clk << p->p_clk.pin);
// at least avr->data[addr] update is required, otherwise port state is broken
// also triggering vcd signal would be nice here
avr_core_watch_write(p->avr, addr, value);
}

if ( phase ) {
Expand Down Expand Up @@ -175,6 +186,36 @@ static void avr_bitbang_clk_hook(struct avr_irq_t * irq, uint32_t value, void *
avr_bitbang_clk_edge(p);
}

/**
* define bitbang pins
*
* @param p bitbang structure
* @param clk clock pin
* @param in incoming data pin
* @param out outgoing data pin
*/
void avr_bitbang_defpins(avr_bitbang_t * p, avr_iopin_t *clk, avr_iopin_t *in, avr_iopin_t *out)
{
if (clk) {
p->p_clk.port = clk->port;
p->p_clk.pin = clk->pin;
p->p_clk.ioport = (avr_ioport_t *)avr_io_findinstance(p->avr, "port", clk->port);
p->p_clk.irq = avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin);
}
if (in) {
p->p_in.port = in->port;
p->p_in.pin = in->pin;
p->p_in.ioport = (avr_ioport_t *)avr_io_findinstance(p->avr, "port", in->port);
p->p_in.irq = avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_in.port ), p->p_in.pin);
}
if (out) {
p->p_out.port = out->port;
p->p_out.pin = out->pin;
p->p_out.ioport = (avr_ioport_t *)avr_io_findinstance(p->avr, "port", out->port);
p->p_out.irq = avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_out.port ), p->p_out.pin);
}
}

/**
* reset bitbang sub-module
*
Expand Down Expand Up @@ -220,7 +261,7 @@ void avr_bitbang_start(avr_bitbang_t * p)
} else {
// slave mode -> attach clock function to clock pin
///@todo test
avr_irq_register_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p);
avr_irq_register_notify( p->p_clk.irq, avr_bitbang_clk_hook, p);
}

}
Expand All @@ -238,7 +279,7 @@ void avr_bitbang_stop(avr_bitbang_t * p)

p->enabled = 0;
avr_cycle_timer_cancel(p->avr, avr_bitbang_clk_timer, p);
avr_irq_unregister_notify( avr_io_getirq(p->avr, AVR_IOCTL_IOPORT_GETIRQ( p->p_clk.port ), p->p_clk.pin), avr_bitbang_clk_hook, p);
avr_irq_unregister_notify( p->p_clk.irq, avr_bitbang_clk_hook, p);
}

#ifdef __cplusplus
Expand Down
25 changes: 22 additions & 3 deletions simavr/sim/avr_bitbang.h
Expand Up @@ -48,6 +48,15 @@
#include "avr_ioport.h"


/**
* pin structure
*/
typedef struct avr_bitbang_iopin_t {
uint16_t port : 8; ///< port e.g. 'B'
uint16_t pin : 8; ///< pin number
avr_ioport_t * ioport;
avr_irq_t * irq;
} avr_bitbang_iopin_t;


/// SPI Module initialization and state structure
Expand All @@ -73,9 +82,9 @@ typedef struct avr_bitbang_t {
uint32_t (*callback_transfer_finished)(uint32_t data, void *param); ///< callback function to notify about a complete transfer
/// (read received data and write new output data)

avr_iopin_t p_clk; ///< clock pin (optional)
avr_iopin_t p_in; ///< data in pin
avr_iopin_t p_out; ///< data out pin
avr_bitbang_iopin_t p_clk; ///< clock pin (optional)
avr_bitbang_iopin_t p_in; ///< data in pin
avr_bitbang_iopin_t p_out; ///< data out pin

// private data
uint32_t data; ///< data buffer
Expand All @@ -92,6 +101,16 @@ typedef struct avr_bitbang_t {
*/
void avr_bitbang_reset(avr_t *avr, avr_bitbang_t * p);

/**
* define bitbang pins
*
* @param p bitbang structure
* @param clk clock pin
* @param in incoming data pin
* @param out outgoing data pin
*/
void avr_bitbang_defpins(avr_bitbang_t * p, avr_iopin_t *clk, avr_iopin_t *in, avr_iopin_t *out);

/**
* start bitbang transfer
*
Expand Down

0 comments on commit dfc7fbe

Please sign in to comment.