use strict;
our $VERSION = '0.20';
$VERSION = eval $VERSION;
use Moo;
extends 'VIC::PIC::Base';
# role CodeGen
has type => (is => 'ro', default => 'p16f627a');
has include => (is => 'ro', default => 'p16f627a.inc');
#role Chip
has f_osc => (is => 'ro', default => 4e6); # 4MHz internal oscillator
has pcl_size => (is => 'ro', default => 13); # program counter (PCL) size
has stack_size => (is => 'ro', default => 8); # 8 levels of 13-bit entries
has wreg_size => (is => 'ro', default => 8); # 8-bit register WREG
# all memory is in bytes
has memory => (is => 'ro', default => sub {
{
flash => 1024, # words
SRAM => 224,
EEPROM => 128,
}
});
has address => (is => 'ro', default => sub {
{
isr => [ 0x0004 ],
reset => [ 0x0000 ],
range => [ 0x0000, 0x03FF ],
}
});
has pin_counts => (is => 'ro', default => sub { {
pdip => 18, ## PDIP or DIP ?
soic => 20,
ssop => 20,
qfn => 28,
total => 20,
io => 16,
}});
has banks => (is => 'ro', default => sub {
{
count => 4,
size => 0x80,
gpr => {
0 => [ 0x020, 0x07F],
1 => [ 0x0A0, 0x0EF],
2 => [ 0x120, 0x14F],
},
# remapping of these addresses automatically done by chip
common => [0x070, 0x07F],
remap => [
[0x0F0, 0x0FF],
[0x170, 0x17F],
[0x1F0, 0x1FF],
],
}
});
has registers => (is => 'ro', default => sub {
{
INDF => [0x000, 0x080, 0x100, 0x180], # indirect addressing
TMR0 => [0x001, 0x101],
OPTION_REG => [0x081, 0x181],
PCL => [0x002, 0x082, 0x102, 0x182],
STATUS => [0x003, 0x083, 0x103, 0x183],
FSR => [0x004, 0x084, 0x104, 0x184],
PORTA => [0x005],
TRISA => [0x085],
PORTB => [0x006, 0x106],
TRISB => [0x086, 0x186],
PCLATH => [0x00A, 0x08A, 0x10A, 0x18A],
INTCON => [0x00B, 0x08B, 0x10B, 0x18B],
PIR1 => [0x00C],
PIE1 => [0x08C],
TMR1L => [0x00E],
PCON => [0x08E],
TMR1H => [0x00F],
T1CON => [0x010],
TMR2 => [0x011],
T2CON => [0x012],
PR2 => [0x092],
CCPR1L => [0x015],
CCPR1H => [0x016],
CCP1CON => [0x017],
RCSTA => [0x018],
TXSTA => [0x098],
TXREG => [0x019],
SPBRG => [0x099],
RCREG => [0x01A],
EEDATA => [0x09A],
EEADR => [0x09B],
EECON1 => [0x09C],
EECON2 => [0x09D], # not addressable apparently
CMCON => [0x01F],
VRCON => [0x09F],
}
});
has pins => (is => 'ro', default => sub {
my $h = {
# number to pin name and pin name to number
1 => [qw(RA2 AN2 Vref)],
2 => [qw(RA3 AN3 CMP1)],
3 => [qw(RA4 T0CKI CMP2)],
4 => [qw(RA5 MCLR Vpp)],
5 => [qw(Vss)],
6 => [qw(RB0 INT)],
7 => [qw(RB1 RX DT)],
8 => [qw(RB2 TX CK)],
9 => [qw(RB3 CCP1)],
10 => [qw(RB4 PGM)],
11 => [qw(RB5)],
12 => [qw(RB6 T1OSO T1CKI PGC)],
13 => [qw(RB7 T1OSI PGD)],
14 => [qw(Vdd)],
15 => [qw(RA6 OSC2 CLKOUT)],
16 => [qw(RA7 OSC1 CLKIN)],
17 => [qw(RA0 AN0)],
18 => [qw(RA1 AN1)],
};
foreach my $k (keys %$h) {
my $v = $h->{$k};
foreach (@$v) {
$h->{$_} = $k;
}
}
return $h;
});
has clock_pins => (is => 'ro', default => sub {
{
out => 'CLKOUT',
in => 'CLKIN',
}
});
has oscillator_pins => (is => 'ro', default => sub {
{
1 => 'OSC1',
2 => 'OSC2',
}
});
has program_pins => (is => 'ro', default => sub {
{
clock => 'PGC',
data => 'PGD',
enable => 'PGM',
}
});
has io_ports => (is => 'ro', default => sub {
{
#port => tristate,
PORTA => 'TRISA',
PORTB => 'TRISB',
}
});
has input_pins => (is => 'ro', default => sub {
{
#I/O => [port, tristate, bit]
RA0 => ['PORTA', 'TRISA', 0],
RA1 => ['PORTA', 'TRISA', 1],
RA2 => ['PORTA', 'TRISA', 2],
RA3 => ['PORTA', 'TRISA', 3],
RA4 => ['PORTA', 'TRISA', 4],
RA5 => ['PORTA', 'TRISA', 5], # input only
RA6 => ['PORTA', 'TRISA', 6],
RA7 => ['PORTA', 'TRISA', 7],
RB0 => ['PORTB', 'TRISB', 0],
RB1 => ['PORTB', 'TRISB', 1],
RB2 => ['PORTB', 'TRISB', 2],
RB3 => ['PORTB', 'TRISB', 3],
RB4 => ['PORTB', 'TRISB', 4],
RB5 => ['PORTB', 'TRISB', 5],
RB6 => ['PORTB', 'TRISB', 6],
RB7 => ['PORTB', 'TRISB', 7],
}
});
has output_pins => (is => 'ro', default => sub {
{
#I/O => [port, tristate, bit]
RA0 => ['PORTA', 'TRISA', 0],
RA1 => ['PORTA', 'TRISA', 1],
RA2 => ['PORTA', 'TRISA', 2],
RA3 => ['PORTA', 'TRISA', 3],
RA4 => ['PORTA', 'TRISA', 4],
RA6 => ['PORTA', 'TRISA', 6],
RA7 => ['PORTA', 'TRISA', 7],
RB0 => ['PORTB', 'TRISB', 0],
RB1 => ['PORTB', 'TRISB', 1],
RB2 => ['PORTB', 'TRISB', 2],
RB3 => ['PORTB', 'TRISB', 3],
RB4 => ['PORTB', 'TRISB', 4],
RB5 => ['PORTB', 'TRISB', 5],
RB6 => ['PORTB', 'TRISB', 6],
RB7 => ['PORTB', 'TRISB', 7],
}
});
has analog_pins => (is => 'ro', default => sub { {} });
has timer_prescaler => (is => 'ro', default => sub {
{
2 => '000',
4 => '001',
8 => '010',
16 => '011',
32 => '100',
64 => '101',
128 => '110',
256 => '111',
}
});
has wdt_prescaler => (is => 'ro', default => sub {
{
1 => '000',
2 => '001',
4 => '010',
8 => '011',
16 => '100',
32 => '101',
64 => '110',
128 => '111',
}
});
has timer_pins => (is => 'ro', default => sub {
{
TMR0 => 'TMR0',
TMR1 => ['TMR1H', 'TMR1L'],
TMR2 => 'TMR2',
# timer 0 clock input
T0CKI => 3,
# timer 1 clock input
T1CKI => 12,
# timer oscillator input
T1OSI => 13,
# timer oscillator output
T1OSO => 12,
}
});
has ccp_pins => (is => 'ro', default => sub {
{
CCP1 => 'CCP1',
}
});
#external interrupt
has eint_pins => (is => 'ro', default => sub {
{
INT => 6,
}
});
has ioc_pins => (is => 'ro', default => sub {
{
RB4 => 10,
RB5 => 11,
RB6 => 12,
RB7 => 13,
}
});
has usart_pins => (is => 'ro', default => sub {
{
async_in => 'RX',
async_out => 'TX',
sync_clock => 'CK',
sync_data => 'DT',
}
});
has cmp_output_pins => (is => 'ro', default => sub {
{
CMP1 => 'CMP1',
CMP2 => 'CMP2',
}
});
has cmp_input_pins => (is => 'ro', default => sub {
{
AN0 => 'AN0',
AN1 => 'AN1',
AN2 => 'AN2',
AN3 => 'AN3',
}
});
my @rolenames = qw(CodeGen Operators Chip GPIO ISR Timer Operations CCP USART Comparator);
my @roles = map (("VIC::PIC::Roles::$_", "VIC::PIC::Functions::$_"), @rolenames);
with @roles;
sub list_roles {
my @arr = grep {!/CodeGen|Oper|Chip|ISR/} @rolenames;
return wantarray ? @arr : [@arr];
}
1;
__END__
=encoding utf8
=head1 NAME
VIC::PIC::P16F627A
=head1 SYNOPSIS
A class that describes the code to be generated for each specific
microcontroller that maps the VIC syntax back into assembly. This is the
back-end to VIC's front-end.
=head1 DESCRIPTION
INTERNAL CLASS.
=head1 AUTHOR
Vikas N Kumar <vikas@cpan.org>
=head1 COPYRIGHT
Copyright (c) 2014. Vikas N Kumar
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=cut