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?