This program generates sound by using FM tone generator YMF825 via SPI.

Dependencies:   microbit

fmasgn.c

Committer:
hasebems
Date:
2018-01-05
Revision:
0:c54d59d6fb78

File content as of revision 0:c54d59d6fb78:

//	fmasgn.c
#include "fmtype.h"
#include "fmasgn.h"
#include "fmvoice.h"

//	Variable
static Fmvoice	_fmvc[MAX_FM_VOICE];
static Fmvoice*	_firstEmptyVc;		//	old
static Fmvoice*	_lastEmptyVc;		//	new
static Fmvoice*	_firstOccupiedVc;	//	old
static Fmvoice*	_lastOccupiedVc;	//	new

//	Prototype
static void	setToEmptyList( Fmvoice* prevVc, Fmvoice* rlsVc );

//	setter
void Asgn_setFirstEmptyVc( Fmvoice* vc ){ _firstEmptyVc = vc; }
void Asgn_setLastEmptyVc( Fmvoice* vc ){ _lastEmptyVc = vc; }

//	getter
Fmvoice* Asgn_voice( int num ){ return &(_fmvc[num]); }
Fmvoice* Asgn_firstEmptyVc( void ){ return _firstEmptyVc; }
Fmvoice* Asgn_lastEmptyVc( void ){ return _lastEmptyVc; }

void Asgn_init( void )
{
	int		i;

	for ( i=0; i<MAX_FM_VOICE; i++) {
		Fmvoice_init(&_fmvc[i]);
	}

	_firstOccupiedVc = 0;
	_lastOccupiedVc = 0;

	for ( i=0; i<MAX_FM_VOICE-1; i++ ){
		Fmvoice_setVoiceNum(&_fmvc[i], i);
		Fmvoice_setNextVc(&_fmvc[i], &_fmvc[i + 1]);
	}

	//	for No.MAX_FM_VOICE-1
	Fmvoice_setVoiceNum(&_fmvc[MAX_FM_VOICE - 1], MAX_FM_VOICE - 1);
	Fmvoice_setNextVc(&_fmvc[MAX_FM_VOICE - 1], FMNULL);

	_firstEmptyVc = &_fmvc[0];
	_lastEmptyVc = &_fmvc[MAX_FM_VOICE-1];
}
bool Asgn_chkEmpty( void )
{
	if ( _firstEmptyVc == FMNULL ){ return false; }
	else { return true; }
}
Fmvoice* Asgn_getEmptyVc( void )
{
	if ( _firstEmptyVc != FMNULL ){
		Fmvoice* ret = _firstEmptyVc;
		_firstEmptyVc = Fmvoice_nextVc(_firstEmptyVc);
		if ( _lastOccupiedVc != FMNULL ){
			Fmvoice_setNextVc(_lastOccupiedVc, ret);
		}
		_lastOccupiedVc = ret;
		if ( _firstOccupiedVc == FMNULL ){
			_firstOccupiedVc = ret;
		}
		return ret;
	}
	else {
		FMASSERT(0);
		return FMNULL;
	}
}
void Asgn_releaseOneVc( void )
{
	if ( _firstOccupiedVc == FMNULL ){
		FMASSERT(0);
		return;
	}

	//	Search keyoffed Voice
	Fmvoice* rlsVc = _firstOccupiedVc;
	Fmvoice* prevVc = FMNULL;
	while (rlsVc != FMNULL ){
		if ( Fmvoice_isKeyon(rlsVc) == false ){
			break;
		}
		prevVc = rlsVc;
		rlsVc = Fmvoice_nextVc(rlsVc);
	}

	//	if no keyoffed vc, select first one.
	if ( rlsVc == FMNULL ){
		rlsVc = _firstOccupiedVc;
	}

	setToEmptyList(prevVc,rlsVc);
}
void Asgn_releaseParticularVc( Fmvoice* pVc )
{
	//	Search pVc & its prevVc
	Fmvoice* rlsVc = _firstOccupiedVc;
	Fmvoice* prevVc = FMNULL;
	while ( rlsVc != FMNULL ){
		if ( pVc == rlsVc ){
			break;
		}
		prevVc = rlsVc;
		rlsVc = Fmvoice_nextVc(rlsVc);
	}
	setToEmptyList(prevVc,rlsVc);
}
static void setToEmptyList( Fmvoice* prevVc, Fmvoice* rlsVc )
{
	//	Release from Occupied list
	if ( rlsVc == _firstOccupiedVc ){
		_firstOccupiedVc = Fmvoice_nextVc(rlsVc);
	}
	if ( rlsVc == _lastOccupiedVc ){
		_lastOccupiedVc = prevVc;
	}
	if ( prevVc != FMNULL ){
		Fmvoice_setNextVc(prevVc, Fmvoice_nextVc(rlsVc));
	}
	Fmvoice_release(rlsVc);

	//	Set Empty list
	Fmvoice_setNextVc(_lastEmptyVc, rlsVc);
	_lastEmptyVc = rlsVc;
	if ( _firstEmptyVc == FMNULL ){
		_firstEmptyVc = rlsVc;
	}
}