/******************************************************************************
*
* Copyright (C) 2007-2017  Brian Berlin
* 
* 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 3 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.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************
*
* FILENAME: sio.h
*
* DESCRIPTION:  This contains function declarations for Serial I/O functions
*
* AUTHORS:  bberlin
*
* CHANGE LOG
*
*  VER     DATE     CHANGED BY   DESCRIPTION OF CHANGE
* ------  --------  ----------   ------------------------------------
* 0.5.0   02/26/07  bberlin      Creation
******************************************************************************/
#ifndef sio_h
#define sio_h

#include "boom6502.h"
#include "media.h"

#define MAX_SIO_DEVICES 8
#define MAX_CAS_BLOCKS  2048

/*
 * Device Commands
 */
#define SIO_CMD_RD_STATUS_BLK  0x4E
#define SIO_CMD_WT_STATUS_BLK  0x4F
#define SIO_CMD_READ           0x52
#define SIO_CMD_READ_HI        0xD2
#define SIO_CMD_WRITE          0x57
#define SIO_CMD_WRITE_HI       0xD7
#define SIO_CMD_STATUS         0x53
#define SIO_CMD_PUT            0x50
#define SIO_CMD_PUT_HI         0xD0
#define SIO_CMD_FORMAT         0x21
#define SIO_CMD_FORMAT_HI      0xA1
#define SIO_CMD_DUAL_FORMAT    0x22
#define SIO_CMD_DUAL_FORMAT_HI 0xA2
#define SIO_CMD_DOWNLOAD       0x20
#define SIO_CMD_READADDR       0x54
#define SIO_CMD_READ_SPIN      0x51
#define SIO_CMD_MOTOR_ON       0x55
#define SIO_CMD_VERIFY_SECTOR  0x56

/*
 * Device Responses
 */
#define SIO_RESP_ACK   0x41
#define SIO_RESP_NAK   0x4E
#define SIO_RESP_DONE  0x43
#define SIO_RESP_ERROR 0x45

/*
 * ATR File Indicators
 */
#define SIO_ATR_MAGIC1  0x96
#define SIO_ATR_MAGIC2  0x02

/*
 * Floppy File type
 */
#define SIO_DSK_128             0x01
#define SIO_DSK_256_BOOT_128    0x02
#define SIO_DSK_256_BOOT_256    0x03
#define SIO_DSK_256_BOOT_SIO2PC 0x04

/*
 * Floppy Response delay time 
 *    (I use 100 scanlines, not sure what it really should be)
 */
#define SIO_FLOPPY_GAP_DELAY 11400 

typedef enum {
    SIO_STATUS_NONE,
    SIO_STATUS_CMD,
    SIO_STATUS_READ,
    SIO_STATUS_WRITE,
    SIO_STATUS_GAP,
    SIO_STATUS_MAX
} e_sio_status;

typedef enum {
    SIO_TYPE_FLOPPY,
    SIO_TYPE_CASSETTE,
    SIO_TYPE_MAX
} e_sio_type;

typedef struct {
    KBYTE *data_ptr;
    KWORD size;
    KWORD mark_tone_size;
} t_cas_block;

typedef struct {
    char filename[1024];
    KBYTE *f_buffer;
    int buffer_size;
    int num_blocks;
    int current_block;
    int current_byte;
    int expected_bytes;
    KBYTE header[16];
    KBYTE data_frame[260];
    int header_size;
    int baud;
    KBYTE *current_data;
    unsigned int action_time;
    e_sio_status status;
    e_sio_type type;
} t_sio_device;

typedef struct {
    t_sio_device dev;
    t_media media_info;
    t_cas_block blk[MAX_CAS_BLOCKS];
    int record_pressed;
    unsigned int motor_gap_delay;
    char description[257];
} t_cas_device;

typedef struct {
    t_sio_device dev;
    t_media media_info;
    int write_protect;
    int sector_size;
    int dsk_type;
} t_dsk_device;

typedef struct {
    t_dsk_device drives[MAX_SIO_DEVICES];
    t_cas_device cassette;
    t_sio_device *current_device;
    int motor_on;
    unsigned int motor_on_time;
    KBYTE cmd_frame[6];
    int cmd_index;
} t_sio_interface;

void sio_init ( void );
void sio_exit ( void );
void sio_reset ( void );
int sio_create_disk ( const char *filename, int num_sectors, int disk_type );
int sio_create_cassette ( const char *filename, const char *description );
void sio_press_record ( int pressed );
void sio_check ( void );
void sio_rewind_cassette ( t_cas_device *dev, int block );
int sio_mount_image ( int dev_num, e_sio_type dev_type, char *file, int write_protect, 
                      unsigned char *buffer, int buffer_size );
void sio_unmount_all ( void );
void sio_unmount_image ( e_sio_type type, int dev_num );
void sio_receive ( KBYTE data );
void sio_set_motor ( KBYTE value );
void sio_patch ( void );
KBYTE sio_update_serial_in_bit ( void );
void sio_clock_shift ( int shift );

#endif
