/***********************************************************************
 *  avrp - Atmel AVR programming software to use with Atmel's
 *         serial-port programmers.
 *  Copyright (C) 1997-1998 Jon Anders Haugum
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; see the file COPYING.  If not, write to
 *  the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *
 *
 *  Author of avrp can be reached at:
 *     email: jonah@colargol.tihlde.hist.no
 *     www: http://www.colargol.tihlde.hist.no/~jonah/el/avrp.html
 *     Postal address: Jon Anders Haugum
 *                     Øvre Møllenbergsgt 52
 *                     7014 Trondheim
 */

#include "args.h"
#include "misc.h"

/* Handle SAS/C and older gcc on the Amiga */
#ifndef __amigaos__
#if defined(_AMIGA) || defined(__amiga__)
#define __amigaos__
#endif
#endif

#ifdef __amigaos__
#define DEFFILENAME "env:avrp.def"
#endif

#if defined(__linux__) || defined(__FreeBSD__)
#define DEFFILENAME "/usr/local/etc/avrp.def"
#endif

#ifdef _WIN32
#define DEFFILENAME "C:\\bin\\avrp.def"
#endif

#ifndef DEFFILENAME
#error "Your system is not supported!"
#endif

#define DEFFILEVERSION  2
#define DEFFILEREVISION 0

/* Option enumeration */
enum
	{
	ARG_SERIALPORT =  0,  /* -s <serial port>        */
	ARG_AVRTYPE,          /* -a <AVR type>           */
	ARG_PROG,             /* -p                      */
	ARG_READ,             /* -r                      */
	ARG_VERIFY,           /* -v                      */
	ARG_FLASH,            /* -f <file to read/write> */
	ARG_EEPROM,           /* -e <file to read/write> */
	ARG_QUICK,            /* -q                      */
	ARG_DEFFILE,          /* -d                      */
	ARG_IGNORESIG,        /* -I                      */
	ARG_LOCKMODE,         /* -l                      */
	ARG_ENABLE,           /* --enable                */
	ARG_DISABLE,          /* --disable               */
	ARG_AUTOINC,          /* --autoinc               */
	ARG_VER,              /* --version               */
	ARG_HELP,             /* -h --help               */
	ARG_COUNT
	};


enum
	{
	FILETYPE_UNKNOWN = 0,
	FILETYPE_INTEL_HEX8M,
	FILETYPE_ATMEL_GENERIC
	};


/* Structures */
struct ProgramInfo
	{
	void *Ser;
	struct args *args;
	int ProgType;
	struct ChipNode *SelectedChipNode;
	/* List starts */
	struct ChipNode *FirstChipNode;
	struct VendorNode *FirstVendorNode;
	struct FamilyNode *FirstFamilyNode;
	struct ArchNode *FirstArchNode;
	struct FuseNode *FirstFuseNode;
	struct LockNode *FirstLockNode;
	};

struct ChipNode
	{
	struct ChipNode *Next;
	char *Name;
	int Code;
	int EepromSize;
	int Sig;
	int Supported;
	struct VendorNode *VendorNode;
	struct FamilyNode *FamilyNode;
	int FuseType;
	struct FuseNode *FuseNode;
	int LockType;
	struct LockNode *LockNode;
	};

struct VendorNode
	{
	struct VendorNode *Next;
	int Code;
	char *Name;
	};

struct FamilyNode
	{
	struct FamilyNode *Next;
	int Code;
	char *Name;
	int FlashSize;
	struct ArchNode *ArchNode;
	};

struct ArchNode
	{
	struct ArchNode *Next;
	char *Name;
	int WordSize;
	int NeedFlashErase;
	};

struct FuseNode
	{
	struct FuseNode *Next;
	int Num;
	struct FuseBitNode *FirstFuseBitNode;
	};

struct FuseBitNode
	{
	struct FuseBitNode *Next;
	char *ShortName;
	int BitNum;
	char *LongName;
	};

struct LockNode
	{
	struct LockNode *Next;
	int Num;
	int NumberOfBits;
	int WriteBits;
	int ReadBits;
	struct LockBitNode *FirstLockBitNode;
	};

struct LockBitNode
	{
	struct LockBitNode *Next;
	int Mode;
	int Mask;
	char *LongName;
	};

struct DataFile
	{
	FILE *FP;
	int FileType;
	};


/* Prototypes */
/* avrp.c */
struct ProgramInfo *GetPI(struct args *args);
int DetectAVRType(struct ProgramInfo *PI);
void FreePI(struct ProgramInfo *PI);

/* talking.c */
int InquireHW(struct ProgramInfo *PI);
int InquireID(struct ProgramInfo *PI);
int DoTheTalk(struct ProgramInfo *PI);
int CheckLockAndErase(struct ProgramInfo *PI, unsigned char *Sig);
int CheckSig(struct ProgramInfo *PI, unsigned char *Sig);
int DoMoreTalk(struct ProgramInfo *PI);
int Erase(struct ProgramInfo *PI);
int DoFuses(struct ProgramInfo *PI);
void print_comm_err(char comm);

/* memtalk.c */
int Program(struct ProgramInfo *PI, int ProgWhat, int DoWhat);
int prog_adr(struct ProgramInfo *PI, int adr, int data, int What, int *StatAdr);
int verify_adr(struct ProgramInfo *PI, int adr, int data, int What, int *StatAdr);
int Read(struct ProgramInfo *PI, int What);
void Progress(int *StatAdr, int Adr, char DidWhat);

/* file.c */
struct DataFile *OpenDataFile(char *FileName);
void CloseDataFile(struct DataFile *DataFile);
int ReadDefFile(struct ProgramInfo *PI);
char *GetNextString(char *Buff, int *index);

/* io_[linux|amiga|win32].c */
void *OpenSer(char *SerPort);
void CloseSer(void *Ser);
void SerWriteByte(void *Ser, unsigned char Byte);
int SerReadData(void *Ser, unsigned char *Buff, int Count);

/* stdextra.c */
char *nocase_strcmp(char *s, char *t);
char *nocase_strncmp(char *s, char *t, int n);
char *nocase_strstr(char *s, char *t);
int atox(char *s);
int atoi_n(char *s, int n);
int atox_n(char *s, int n);
