libexsid  2.1
exSID.c File Reference

exSID/exSID+ USB I/O library More...

#include "exSID.h"
#include "exSID_defs.h"
#include "exSID_ftdiwrap.h"
#include <stdio.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdlib.h>
#include <errno.h>
#include <time.h>
Include dependency graph for exSID.c:

Go to the source code of this file.

Data Structures

struct  xSconsts_s
 This private structure holds hardware-dependent constants. More...
 
struct  _exsid
 exSID private handle More...
 

Macros

#define ARRAY_SIZE(x)   (sizeof(x) / sizeof(x[0]))
 
#define XS_ERRORBUF   256
 
#define xserror(xs, format, ...)    snprintf(xs->xSerrstr, XS_ERRORBUF, "(%s) ERROR " format, __func__, ## __VA_ARGS__)
 

Typedefs

typedef int_fast32_t clkdrift_t
 cycles is uint_fast32_t. More...
 

Functions

const char * exSID_error_str (void *const exsid)
 Returns a string describing the last recorded error. More...
 
void * exSID_new (void)
 Allocate an exSID handle. More...
 
void exSID_free (void *exsid)
 Deallocate an exSID handle. More...
 
int exSID_init (void *const exsid)
 Device init routine. More...
 
int exSID_exit (void *const exsid)
 Device exit routine. More...
 
int exSID_reset (void *const exsid)
 SID reset routine. More...
 
int exSID_clockselect (void *const exsid, int clock)
 exSID+ clock selection routine. More...
 
int exSID_audio_op (void *const exsid, int operation)
 exSID+ audio operations routine. More...
 
int exSID_chipselect (void *const exsid, int chip)
 SID chipselect routine. More...
 
int exSID_hwmodel (void *const exsid)
 Device hardware model. More...
 
uint16_t exSID_hwversion (void *const exsid)
 Hardware and firmware version of the device. More...
 
int exSID_delay (void *const exsid, uint_fast32_t cycles)
 Cycle accurate delay routine. More...
 
int exSID_clkdwrite (void *const exsid, uint_fast32_t cycles, uint_least8_t addr, uint8_t data)
 Timed write routine, attempts cycle-accurate writes. More...
 
int exSID_clkdread (void *const exsid, uint_fast32_t cycles, uint_least8_t addr, uint8_t *data)
 BLOCKING Timed read routine, attempts cycle-accurate reads. More...
 

Detailed Description

exSID/exSID+ USB I/O library

Author
Thibaut VARENE
Date
2015-2018,2021
Version
2.1

This driver will control the first exSID device available. All public API functions are only valid after a successful call to exSID_init(). To release the device and resources, exSID_exit() and exSID_free() must be called.

The return value for public routines returning an integer is 0 for successful execution and !0 for error, unless otherwise noted.

Warning
Although it can internally make use of two separate threads, the driver implementation is NOT thread safe (since it is not expected that a SID device may be accessed concurrently), and some optimizations in the code are based on the assumption that the code is run within a single-threaded environment.

Definition in file exSID.c.

Macro Definition Documentation

#define ARRAY_SIZE (   x)    (sizeof(x) / sizeof(x[0]))

Definition at line 46 of file exSID.c.

Referenced by exSID_init().

#define XS_ERRORBUF   256

Definition at line 47 of file exSID.c.

#define xserror (   xs,
  format,
  ... 
)    snprintf(xs->xSerrstr, XS_ERRORBUF, "(%s) ERROR " format, __func__, ## __VA_ARGS__)

Definition at line 48 of file exSID.c.

Referenced by exSID_exit(), and exSID_init().

Typedef Documentation

typedef int_fast32_t clkdrift_t

cycles is uint_fast32_t.

Technically, clkdrift should be int_fast64_t though overflow should not happen under normal conditions.

Definition at line 54 of file exSID.c.

Function Documentation

int exSID_audio_op ( void *const  exsid,
int  operation 
)

exSID+ audio operations routine.

Selects the audio mixing / muting option. Only implemented in exSID+ devices.

Warning
all these operations (excepting unmuting obviously) will mute the output by default.
Note
no accounting for SID cycles consumed (not expected to be used during playback).
Parameters
exsidexsid handle
operationaudio operation value, see exSID.h.
Returns
execution status

Definition at line 617 of file exSID.c.

References _exsid::cst, xSconsts_s::model, XS_AU_6581_6581, XS_AU_6581_8580, XS_AU_8580_6581, XS_AU_8580_8580, XS_AU_MUTE, XS_AU_UNMUTE, XS_MODEL_PLUS, xsdbg, XSP_AD_IOCTA0, XSP_AD_IOCTA1, XSP_AD_IOCTA2, XSP_AD_IOCTA3, XSP_AD_IOCTAM, and XSP_AD_IOCTAU.

int exSID_chipselect ( void *const  exsid,
int  chip 
)

SID chipselect routine.

Selects which SID will play the tunes.

Note
Accounts for elapsed cycles.
Parameters
exsidexsid handle
chipSID selector value, see exSID.h.
Returns
execution status

Definition at line 663 of file exSID.c.

References _exsid::clkdrift, xSconsts_s::csioctl_cycles, _exsid::cst, XS_AD_IOCTS0, XS_AD_IOCTS1, XS_AD_IOCTSB, XS_CS_BOTH, XS_CS_CHIP0, XS_CS_CHIP1, and xsdbg.

int exSID_clkdread ( void *const  exsid,
uint_fast32_t  cycles,
uint_least8_t  addr,
uint8_t *  data 
)

BLOCKING Timed read routine, attempts cycle-accurate reads.

The following description is based on exSID (standard). This function will be cycle-accurate provided that no two consecutive reads or writes are less than XS_CYCIO apart and leftover delay is <= max_adj SID clock cycles. Read result will only be available after a full XS_CYCIO, giving clkdread() the same run time as clkdwrite(). There's a 2-cycle negative adjustment in the code because that's the actual offset from the write calls ('/' denotes falling clock edge latch), which the following ASCII tries to illustrate:
Write looks like this in firmware:

...|_/_|...

...end of data byte read | cycle during which write is enacted / next cycle | etc...
Read looks like this in firmware:

...|_|_|_/_|_|...

...end of address byte read | 2 cycles for address processing | cycle during which SID is read / then half a cycle later the CYCCHR-long data TX starts, cycle completes | another cycle | etc...
This explains why reads happen a relative 2-cycle later than then should with respect to writes.

Warning
this function is only valid if EXSID_THREADED is not defined. If it is called when EXSID_THREADED is defined, no read will be performed, however the requested cycles will still be clocked.
Note
this function accepts reads from invalid addresses (addr < 0x19 or addr > 0x1c). If DEBUG is enabled it will not pass them to the hardware and return 1. Elapsed SID cycles will still be accounted for.
The actual time the read will take to complete depends on the USB bus activity and settings. It should complete in XSC_USBLAT ms, but not less, meaning that read operations are bound to introduce timing inaccuracy. As such, this function is only really provided as a proof of concept but SHOULD BETTER BE AVOIDED.
Parameters
exsidexsid handle
cycleshow many SID clocks to wait before the actual data read.
addrtarget address.
datapointer to store data read from address.
Returns
-1 if error, 0 on success

Definition at line 909 of file exSID.c.

References _exsid::clkdrift, _exsid::cst, exSID_delay(), likely, xSconsts_s::max_adj, xSconsts_s::mindel_cycles, xSconsts_s::read_offset_cycles, xSconsts_s::read_post_cycles, xSconsts_s::read_pre_cycles, unlikely, and xsdbg.

int exSID_clkdwrite ( void *const  exsid,
uint_fast32_t  cycles,
uint_least8_t  addr,
uint8_t  data 
)

Timed write routine, attempts cycle-accurate writes.

This function will be cycle-accurate provided that no two consecutive writes are less than write_cycles apart and the leftover delay is <= max_adj SID clock cycles.

Note
this function accepts writes to invalid addresses (> 0x18). If DEBUG is enabled it will not pass them to the hardware and return 1. Elapsed SID cycles will still be accounted for.
Parameters
exsidexsid handle
cycleshow many SID clocks to wait before the actual data write.
addrtarget address.
datadata to write at that address.
Returns
-1 if error, 0 on success

Definition at line 816 of file exSID.c.

References _exsid::clkdrift, _exsid::cst, exSID_delay(), likely, xSconsts_s::max_adj, xSconsts_s::mindel_cycles, unlikely, xSconsts_s::write_cycles, and xsdbg.

int exSID_clockselect ( void *const  exsid,
int  clock 
)

exSID+ clock selection routine.

Selects between PAL, NTSC and 1MHz clocks. Only implemented in exSID+ devices.

Note
upon clock change the hardware resync itself and resets the SIDs, which takes approximately 50us: this call introduces a stall in the stream and resets the internal drift adjustment counter. Output should be muted before execution.
Parameters
exsidexsid handle
clockclock selector value, see exSID.h.
Returns
execution status

Definition at line 576 of file exSID.c.

References _exsid::clkdrift, _exsid::cst, xSconsts_s::model, XS_CL_1MHZ, XS_CL_NTSC, XS_CL_PAL, XS_MODEL_PLUS, xsdbg, XSP_AD_IOCTC1, XSP_AD_IOCTCN, and XSP_AD_IOCTCP.

int exSID_delay ( void *const  exsid,
uint_fast32_t  cycles 
)

Cycle accurate delay routine.

Delay for cycles SID clocks while leaving enough lead time for an I/O operation.

Parameters
exsidexsid handle
cycleshow many SID clocks to loop for.
Returns
0 on success, -1 on error and 1 if the requested number of cycles is smaller than the feasible delay

Definition at line 769 of file exSID.c.

References _exsid::clkdrift, _exsid::cst, unlikely, and xSconsts_s::write_cycles.

Referenced by exSID_clkdread(), and exSID_clkdwrite().

const char* exSID_error_str ( void *const  exsid)

Returns a string describing the last recorded error.

Parameters
exsidexsid handle
Returns
error message (max 256 bytes long).

Definition at line 177 of file exSID.c.

References _exsid::xSerrstr.

int exSID_exit ( void *const  exsid)

Device exit routine.

Must be called to release the device. Resets the SIDs, frees buffers and closes FTDI device.

Parameters
exsidexsid handle
Returns
execution status

Definition at line 489 of file exSID.c.

References _exsid::backbuf, _exsid::clkdrift, exSID_reset(), _exsid::ftdi, XS_AD_IOCTD1, xsdbg, xserror, xSfw_dlclose(), xSfw_free, xSfw_get_error_string, and xSfw_usb_close.

void exSID_free ( void *  exsid)

Deallocate an exSID handle.

Frees up all memory used by the exSID handle.

Parameters
exsidexsid handle

Definition at line 354 of file exSID.c.

References _exsid::backbuf, _exsid::ftdi, and xSfw_free.

int exSID_hwmodel ( void *const  exsid)

Device hardware model.

Queries the driver for the hardware model currently identified.

Parameters
exsidexsid handle
Returns
hardware model as enumerated in exSID.h, negative value on error.

Definition at line 697 of file exSID.c.

References _exsid::cst, xSconsts_s::model, XS_MD_PLUS, XS_MD_STD, XS_MODEL_PLUS, XS_MODEL_STD, and xsdbg.

uint16_t exSID_hwversion ( void *const  exsid)

Hardware and firmware version of the device.

Returns both in the form of a 16bit integer: MSB is an ASCII character representing the hardware revision (e.g. 0x42 = "B"), and LSB is a number representing the firmware version in decimal integer. Does not reach the hardware (information is fetched once in exSID_init()).

Parameters
exsidexsid handle
Returns
version information as described above, or 0xFFFF if error.

Definition at line 731 of file exSID.c.

References _exsid::hwvers.

int exSID_init ( void *const  exsid)

Device init routine.

Must be called once before any operation is attempted on the device. Opens first available device, and sets various parameters: baudrate, parity, flow control and USB latency.

Note
If this function fails, exSID_free() must still be called.
Parameters
exsidallocated exsid handle generated with exSID_new()
Returns
0 on success, !0 otherwise.

Definition at line 384 of file exSID.c.

References ARRAY_SIZE, _exsid::backbuf, xSconsts_s::buff_size, _exsid::cst, desc, EXSID_VERSION, _exsid::ftdi, _exsid::hwvers, XS_AD_IOCTFV, XS_AD_IOCTHV, XS_BDRATE, XSC_USBLAT, xsdbg, xserror, xSfw_dlopen(), xSfw_free, xSfw_get_error_string, xSfw_new, xSfw_usb_open_desc, and xSfw_usb_setup().

void* exSID_new ( void  )

Allocate an exSID handle.

Returns
allocated opaque handle, NULL if error.

Definition at line 342 of file exSID.c.

int exSID_reset ( void *const  exsid)

SID reset routine.

Performs a hardware reset on the SIDs. This also resets the internal drift adjustment counter.

Note
since the reset procedure in firmware will stall the device, reset can wait before resuming execution.
Parameters
exsidexsid handle
Returns
execution status

Definition at line 549 of file exSID.c.

References _exsid::clkdrift, XS_AD_IOCTRS, and xsdbg.

Referenced by exSID_exit().

Variable Documentation

const char* desc

USB device description string.

Definition at line 73 of file exSID.c.

Referenced by exSID_init().

const int pid

USB PID.

Definition at line 74 of file exSID.c.

const int vid

USB VID.

Definition at line 75 of file exSID.c.

const struct xSconsts_s xsc

constants specific to the device

Definition at line 76 of file exSID.c.