I've been doing a lot of hardware IO work lately, which involves lots of talking to hardware devices, where there are byte-wide registers that store little bitfields, sometimes of individual and unrelated bits packed together. To make this easier I tend to write myself lots of pairs of functions to pack/unpack the fields in one of these bytes; for instance:
use constant {
MASK_RX_RD => 1<<6,
MASK_TX_DS => 1<<5,
MASK_MAX_RT => 1<<4,
EN_CRC => 1<<3,
CRCO => 1<<2,
PWR_UP => 1<<1,
PRIM_RX => 1<<0,
};
sub unpack_CONFIG
{
my ( $config ) = @_;
return
MASK_RX_RD => !!( $config & MASK_RX_RD ),
MASK_TX_DS => !!( $config & MASK_TX_DS ),
MASK_MAX_RT => !!( $config & MASK_MAX_RT ),
EN_CRC => !!( $config & EN_CRC ),
CRCO => $CRCOs[!!( $config & CRCO )],
PWR_UP => !!( $config & PWR_UP ),
PRIM_RX => !!( $config & PRIM_RX );
}
sub pack_CONFIG
{
my %config = @_;
return
( $config{MASK_RX_RD} ? MASK_RX_RD : 0 ) |
( $config{MASK_TX_DS} ? MASK_TX_DS : 0 ) |
( $config{MASK_MAX_RT} ? MASK_MAX_RT : 0 ) |
( $config{EN_CRC} ? EN_CRC : 0 ) |
( ( _idx_of $config{CRCO}, @CRCOs )
// croak "Unsupported 'CRCO'" ) * CRCO |
( $config{PWR_UP} ? PWR_UP : 0 ) |
( $config{PRIM_RX} ? PRIM_RX : 0 ) );
}
This convenient pair of functions bidirectionally converts bytes into key/value lists. As well as containing 6 simple boolean values, there's also an enumerated field, represented by the values in the array @CRCOs. These functions convert those too.
I'm getting tired of writing these pairs of functions. Hey, this is Perl right? :) I should get Perl to write them for me.
TL;DR - I propose the followingI'd like instead to write something like:
use bitfield; bitfield CONFIG => MASK_RX_DS => boolfield(6), MASK_TX_DS => boolfield(5), MASK_MAX_RT => boolfield(4), EN_CRC => boolfield(3), CRCO => enumfield(2, qw( values here )), PWR_UP => boolfield(1), PRIM_RX => boolfield(0);
The operation here is that 'bitfield' is automatically exporting a function called bitfield, along with the various *field() functions that create field definitions. boolfield() declares a single true/false boolean bit position, enumfield() declares a range of bits that give an enumeration. I guess also would be required intfield() to use a range of bits as an integer, and finally most likely customfield() taking a pair of conversion CODE refs or somesuch.
What does anyone think to that?