Skip to main content
GameDev.net gamedev.net
🔒 Locked

union { struct { union { struct { ...

Started by TheComet Nov 19, 2018 at 6:29 PM 0 replies 4.8k views
Original Post
TheComet
TheComet

I don't know how many of you are familiar with driver code, but I'll leave this little treat here.


#include "hal/mux.h"
#include <msp430.h>

/*
 * The following macros define the bits that would enable the connection from
 * the MSP430 USS output Tx or input Rx to the sensor.
 *
 *             C\d[AB]\d[RT]
 *               | |   | |
 * Channel idx --+ |   | |
 * Group A or B ---+   | |
 * Subsensor index ----+ |
 * Transmit or receive --+
 */

/* Vertical channel 0, mapped to port 4 */
#define C0A0T (1u << 0)
#define C0A0R (1u << 1)
#define C0B0T (1u << 2)
#define C0B0R (1u << 5)

/* Sensor group A, channel 1, mapped to port C (ports 5 and 6) */
#define C1A0T (1u << 15)
#define C1A0R (1u << 12)
#define C1A1T (1u <<  3)
#define C1A1R (1u <<  5)
#define C1A2T (1u <<  9)
#define C1A2R (1u << 13)
#define C1A3T (1u <<  1)
#define C1A3R (1u <<  7)

/* Sensor group B, channel 1, mapped to port C (ports 5 and 6) */
#define C1B0T (1u <<  2)
#define C1B0R (1u <<  4)
#define C1B1T (1u << 10)
#define C1B1R (1u <<  8)
#define C1B2T (1u <<  0)
#define C1B2R (1u <<  6)
#define C1B3T (1u << 11)
#define C1B3R (1u << 14)

/* 
 * Maps the entries in the mux_mode_e enum as offsets so table lookup is O(1)
 *   c - Channel index
 *   s - Subsensor index
 */
#define CHANNEL_MAPPING(c, s) \
    C##c##A##s##T | C##c##B##s##R, /* MUX_UP   | MUX_TRANS = 0x00 */ \
    C##c##B##s##T | C##c##A##s##R, /* MUX_DOWN | MUX_TRANS = 0x01 */ \
    C##c##B##s##T | C##c##B##s##R, /* MUX_UP   | MUX_RECV  = 0x02 */ \
    C##c##A##s##T | C##c##A##s##R  /* MUX_DOWN | MUX_RECV  = 0x03 */
#define CHANNEL_T_MODES(c, s) \
    C##c##A##s##T, /* MUX_UP   | MUX_TRANS = 0x00 */ \
    C##c##B##s##T, /* MUX_DOWN | MUX_TRANS = 0x01 */ \
    C##c##B##s##T, /* MUX_UP   | MUX_RECV  = 0x02 */ \
    C##c##A##s##T  /* MUX_DOWN | MUX_RECV  = 0x03 */
#define CHANNEL_R_MODES(c, s) \
    C##c##B##s##R, /* MUX_UP   | MUX_TRANS = 0x00 */ \
    C##c##A##s##R, /* MUX_DOWN | MUX_TRANS = 0x01 */ \
    C##c##B##s##R, /* MUX_UP   | MUX_RECV  = 0x02 */ \
    C##c##A##s##R  /* MUX_DOWN | MUX_RECV  = 0x03 */

static const uint16_t map_to_port_4[4] = {
    CHANNEL_MAPPING(0, 0)
};

static const uint16_t map_T_to_port_c[16] = {
    CHANNEL_T_MODES(1, 0),
    CHANNEL_T_MODES(1, 1),
    CHANNEL_T_MODES(1, 2),
    CHANNEL_T_MODES(1, 3)
};

static const uint16_t map_R_to_port_c[16] = {
    CHANNEL_R_MODES(1, 0),
    CHANNEL_R_MODES(1, 1),
    CHANNEL_R_MODES(1, 2),
    CHANNEL_R_MODES(1, 3)
};

/*
 * Multiplexer state can be stored in a uint16_t, such that the lower
 * byte directly indexes an array offset for the transmitter state and the
 * upper byte directly indexes an array offset for the receiver state.
 *
 * Usage:
 *   state.data --> Gives you the mux state as a uint16_t
 *   state.group_a.[mode|subchannel_idx] --> mode and subchannel index access for group A
 *   state.group_b.[mode|subchannel_idx] --> mode and subchannel index access for group B
 *   state.group_a.offset --> Array offset for map_T_to_port_c[]
 *   state.group_b.offset --> Array offset for map_R_to_port_c[]
 *   state.channel_idx --> Access to channel index
 *
 * See mux.h for a detailed overview of what is meant by "Group A" and "Group B",
 * what subsensors are, and what the different mode bits are supposed to do.
 */
union mux_state_u
{
    struct {
        union {
            struct {
                union {
                    struct {
                        unsigned mode           : 2;
                        unsigned subchannel_idx : 2;
                        unsigned pad_1          : 4;
                    };
                    struct {
                        unsigned offset         : 4;
                        unsigned pad_2          : 4;
                    };
                } group_a;
                union {
                    struct {
                        unsigned mode           : 2;
                        unsigned subchannel_idx : 2;
                        unsigned pad_1          : 4;
                    };
                    struct {
                        unsigned offset         : 4;
                        unsigned pad_2          : 4;
                    };
                } group_b;
            };
            struct {
                unsigned pad_0                  : 4;
                unsigned channel_idx            : 4;
                unsigned pad_1                  : 8;
            };
        };
    };
    uint16_t data;
};

/* -------------------------------------------------------------------------- */
void mux_init(void)
{
    PCDIR = 0xFFFF;
    PCOUT = 0x0000;
    P4DIR |= 0x27;
    P4OUT &= ~0x27;
}

/* -------------------------------------------------------------------------- */
uint8_t mux_channel_count(void)
{
    return 2;
}

/* -------------------------------------------------------------------------- */
mux_state_t mux_convert_to_state(uint8_t channel_idx,
                                 uint8_t group_a_subsensor_idx,
                                 uint8_t group_b_subsensor_idx,
                                 uint8_t mode)
{
    union mux_state_u state;
    state.channel_idx = channel_idx;
    state.group_a.subchannel_idx = group_a_subsensor_idx;
    state.group_b.subchannel_idx = group_b_subsensor_idx;
    state.group_a.mode = mode;
    state.group_b.mode = mode;
    return state.data;
}

/* -------------------------------------------------------------------------- */
void mux_convert_from_state(mux_state_t state_u16,
                            uint8_t* channel_idx,
                            uint8_t* group_a_subsensor_idx,
                            uint8_t* group_b_subsensor_idx,
                            uint8_t* mode)
{
    union mux_state_u state;
    state.data = state_u16;
    *channel_idx = state.channel_idx;
    *group_a_subsensor_idx = state.group_a.subchannel_idx;
    *group_b_subsensor_idx = state.group_b.subchannel_idx;
    *mode = state.group_a.mode;
}

/* -------------------------------------------------------------------------- */
void mux_set_state(mux_state_t state_u16)
{
    union mux_state_u state;
    state.data = state_u16;
    if (state.channel_idx == 0)
    {
        uint8_t bits = map_to_port_4[state.group_a.mode];  /* vertical sensor only has one subsensor */
        PCOUT = 0x0000;
        P4OUT = (P4OUT & ~bits) | bits;
    }
    else
    {
        P4OUT &= ~0x27;
        PCOUT = map_T_to_port_c[state.group_a.offset] |
                map_R_to_port_c[state.group_b.offset];
    }
}

/* -------------------------------------------------------------------------- */
void mux_disable(void)
{
    PCOUT = 0x0000;
    P4OUT &= ~0x27;
}


"I would try to find halo source code by bungie best fps engine ever created, u see why call of duty loses speed due to its detail." -- GettingNifty

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.