#!/usr/bin/perl

use strict;
use warnings;

use Device::AVR::UPDI;
use Getopt::Long;

GetOptions(
   'port|P=s' => \( my $PORT = "/dev/ttyUSB0" ),
   'part|p=s' => \( my $PART ),
) or exit 1;

my $updi = Device::AVR::UPDI->new(
   dev => $PORT,
   part => $PART,
);

$updi->init_link->get;

unless( $updi->read_asi_sys_status->get & (1<<3) ) {
   $updi->enable_nvmprog->get;
}

my $sig = $updi->read_signature->get;
if( $updi->partinfo->signature ne $sig ) {
   printf STDERR "Signature %v02X does not match expected %v02X\n",
      $sig, $updi->partinfo->signature;
   exit 1;
}

my @FUSES = @{ $updi->partinfo->fusenames };

foreach my $idx ( 0 .. $#FUSES ) {
   my $fuse = $FUSES[$idx];
   next if !defined $fuse;

   my $value = $updi->read_fuse( $idx )->get;
   printf "%-10s: %02X\n", $fuse, $value;
}

$updi->request_reset( 1 )->get;
$updi->request_reset( 0 )->get;

__END__

=head1 NAME

F<avr-updi-read-fuses> - read fuse values from an F<AVR> microcontroller over F<UPDI>

=head1 SYNOPSIS

   $ avr-updi-read-fuses -p t814
   WDTCFG    : 00
   BODCFG    : 00
   OSCCFG    : 02
   TCD0CFG   : 00
   SYSCFG0   : F6
   SYSCFG1   : 07
   APPEND    : 00
   BOOTEND   : 00

=head1 DESCRIPTION

This program reads the fuse values from an F<AVR> microcontroller using a
F<UPDI> interface, and prints the current values.

=head1 OPTIONS

=head2 --port, -P DEVICE

Optional. Provides the USB device where the UPDI adapter is connected. If
absent a default of F</dev/ttyUSB0> will apply.

=head2 --part, -p PART

Required. Gives the name of the ATmega or ATtiny chip that is expected. Parts
may be specified in the following ways:

   ATmega4809
   atmega4809
   m4809

   ATtiny814
   attiny814
   t814

Specifically, these are the same forms as recognised by F<avr-gcc>'s C<-mmcu>
option and F<avrdude>'s C<-p> option, for convenience in Makefiles and build
scripts.

=head1 AUTHOR

Paul Evans <leonerd@leonerd.org.uk>
