Skip to content

Commit

Permalink
Merge pull request #186 from vbousquet/generalized_pwm
Browse files Browse the repository at this point in the history
PWM: new implementation
  • Loading branch information
toxieainc authored Jan 7, 2024
2 parents 893da42 + 66b97fc commit dbf8888
Show file tree
Hide file tree
Showing 21 changed files with 2,426 additions and 1,398 deletions.
54 changes: 30 additions & 24 deletions src/cpu/m68000/m68kmame.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@ static void m68306_duart_set_dusr(int which,int data); //Set the DUSR register
static void m68306_duart_set_duisr(int data); //Set the DUISR register
static void m68306_duart_set_duimr(int data); //Set the DUIMR register
static void m68306_duart_check_int(void); //Check for a DUART interrupt
static void duart_start_timer(void); //Duart Start Timer
static void duart_start_timer(int reset); //Duart Start Timer
static void duart_timer_callback (int param); //Duart Timer Callback
static void m68306_rx_cause_int(int which,int data); //Generate a Receiver Interrupt
#ifndef PINMAME_NO_UNUSED // currently unused function (GCC 3.4)
Expand Down Expand Up @@ -1525,22 +1525,15 @@ static data16_t m68306_duart_reg_r(offs_t address, int word) {
case 0xf7fd:
LOG(("%8x:START COUNTER COMMAND Read = %x\n",activecpu_get_pc(),data));
#if !DISABLE_68306_TIMER
//TIMER MODE?
if(m68306duartreg[dirDUACR] & 0x40) {
//Look for 1->0 transition in the output to trigger an interrupt!
if(m68306_duart.timer_output) {
//Set CTR/TMR RDY bit (3) in DUISR
m68306_duart_set_duisr(m68306duartreg[dirDUISR] | 0x08);
}
//Clear OP3 output
m68306_duart.timer_output = 0;
//Restart timer!
duart_start_timer();
}
//COUNTER MODE?
else {
//Start count down from preloaded value
//Look for 1->0 transition in the output to trigger an interrupt!
if(m68306_duart.timer_output) {
//Set CTR/TMR RDY bit (3) in DUISR
m68306_duart_set_duisr(m68306duartreg[dirDUISR] | 0x08);
}
//Clear OP3 output
m68306_duart.timer_output = 0;
//Start timer!
duart_start_timer(1);
#endif
break;
//F7FF - STOP COUNTER COMMAND
Expand All @@ -1550,11 +1543,12 @@ static data16_t m68306_duart_reg_r(offs_t address, int word) {
//Clear CTR/TMR RDY bit (3) in DUISR - BOTH TIMER & COUNTER MODE
m68306duartreg[dirDUISR] &= (~0x08);

//COUNTER MODE? - NOT IMPLEMENTED
//COUNTER MODE
if((m68306duartreg[dirDUACR] & 0x40) == 0) {
//Clear OP3 output
m68306_duart.timer_output = 0;
//Stop the counter..
//Stop the counter
timer_enable(m68306_duart.timer, 0);
}
#endif
break;
Expand Down Expand Up @@ -1819,7 +1813,7 @@ static void m68306_rx_cause_int(int which,int data)
}

//Duart Start Timer
static void duart_start_timer(void)
static void duart_start_timer(int reset)
{
double time;
double clock_src;
Expand All @@ -1829,12 +1823,24 @@ static void duart_start_timer(void)
timer_enable(m68306_duart.timer, 0);

//For now, support only external clock src (but really we should check the clock source bits in auxillary register
clock_src = TIME_IN_HZ(3686400); // Clock src is fixed @ 3.6864MHz
switch (m68306duartreg[dirDUACR] & 0x30)
{
case 0x00: clock_src = TIME_IN_HZ(3686400 ); break; // External-IP2: unsupported, use default clock of 3.6864MHz
case 0x10: clock_src = TIME_IN_HZ(3686400 / 16.0); break; // External-IP2/16: unsupported, use default clock of 3.6864MHz / 16
case 0x20: clock_src = TIME_IN_HZ(3686400 ); break; // Crystal or External Clock: use fixed clock of 3.6864MHz
case 0x30: clock_src = TIME_IN_HZ(3686400 / 16.0); break; // External Clock Divided by 16: use fixed clock of 3.6864MHz / 16
}
//Get preload value
preload = (m68306duartreg[dirCNT_MSB] << 8) | m68306duartreg[dirCNT_LSB];
if(!preload) return;
//Restart the timer (period is clock source * (2 * preload value)
time = clock_src * 2 * preload;
if(preload < 2) return;
if (m68306duartreg[dirDUACR] & 0x40) { // Timer mode
//Restart the timer (period is clock source * preload value, hence the generated square wave has a period of 2 * clock source * preload value since it toggles the output)
time = clock_src * preload;
}
else { // Counter mode
//Restart the timer: period is clock source * preload value on reset, after that it continues counting from 0xFFFF (application is supposed to stop / restart it)
time = reset ? (clock_src * preload) : (clock_src * 0x0FFFF);
}
timer_adjust(m68306_duart.timer, time, 0, 0);
}

Expand All @@ -1849,7 +1855,7 @@ static void duart_timer_callback (int param)
m68306_duart_set_duisr(m68306duartreg[dirDUISR] | 0x08);
}
//Restart timer!
duart_start_timer();
duart_start_timer(0);
}

//Can we generate an interrupt?
Expand Down
8 changes: 4 additions & 4 deletions src/libpinmame/libpinmame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,7 @@ PINMAMEAPI void PinmameSetSolenoidMask(const int low, const uint32_t mask)

PINMAMEAPI int PinmameGetMaxSolenoids()
{
return (CORE_MAXSOL + CORE_MODSOL_MAX);
return CORE_MODOUT_SOL_MAX;
}

/******************************************************
Expand Down Expand Up @@ -1041,7 +1041,7 @@ PINMAMEAPI int PinmameGetChangedSolenoids(PinmameSolenoidState* const p_changedS

PINMAMEAPI int PinmameGetMaxLamps()
{
return (CORE_MAXLAMPCOL * 8) + CORE_MAXRGBLAMPS;
return CORE_MODOUT_LAMP_MAX;
}

/******************************************************
Expand Down Expand Up @@ -1075,7 +1075,7 @@ PINMAMEAPI int PinmameGetChangedLamps(PinmameLampState* const p_changedStates)

PINMAMEAPI int PinmameGetMaxGIs()
{
return CORE_MAXGI;
return CORE_MODOUT_GI_MAX;
}

/******************************************************
Expand Down Expand Up @@ -1109,7 +1109,7 @@ PINMAMEAPI int PinmameGetChangedGIs(PinmameGIState* const p_changedStates)

PINMAMEAPI int PinmameGetMaxLEDs()
{
return CORE_SEGCOUNT;
return CORE_MODOUT_SEG_MAX;
}

/******************************************************
Expand Down
4 changes: 2 additions & 2 deletions src/win32com/Controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1637,7 +1637,7 @@ STDMETHODIMP CController::put_LockDisplay(VARIANT_BOOL newVal)
****************************************************************************/
STDMETHODIMP CController::get_SolMask(int nLow, long *pVal)
{
if ( !pVal || (nLow<0) || (nLow>1) )
if ( !pVal)
return S_FALSE;

*pVal = vp_getSolMask(nLow);
Expand All @@ -1648,7 +1648,7 @@ STDMETHODIMP CController::get_SolMask(int nLow, long *pVal)
STDMETHODIMP CController::put_SolMask(int nLow, long newVal)
{
// TODO B2S hack, see vp_setSolMask()
if (!((0 <= nLow && nLow <= 2) || (1000 <= nLow && nLow < 1999)))
if (!((0 <= nLow && nLow <= 2) || (1000 <= nLow && nLow < 2999)))
return S_FALSE;

vp_setSolMask(nLow, newVal);
Expand Down
22 changes: 11 additions & 11 deletions src/wpc/bulb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,27 @@
#include <math.h>
#include "bulb.h"


/*-------------------
/ Bulb characteristics and precomputed LUTs
/-------------------*/
typedef struct {
double surface; /* filament surface in m² */
double mass; /* filament mass in kg */
double r0; /* resistance at 293K */
double cool_down[3000]; /* precomputed cool down factor */
double heat_factor[3000]; /* precomputed heat factor = 1.0 / (R * Mass * Specific Heat) */
double cool_down[BULB_T_MAX + 1]; /* precomputed cool down factor */
double heat_factor[BULB_T_MAX + 1]; /* precomputed heat factor = 1.0 / (R * Mass * Specific Heat) */
} bulb_tLampCharacteristics;

/*-------------------
/ local variables
/-------------------*/
static struct {
double t_to_p[1500];
double t_to_p[BULB_T_MAX + 1 - 1500];
double p_to_t[512];
double specific_heat[3000];
double specific_heat[BULB_T_MAX + 1];
} locals;

// Bulb characteristics, estimated by fitting ratings (U,I,P) at a supposed steady state temperature of 2700K, then validating against high FPS video
static bulb_tLampCharacteristics bulbs[BULB_MAX] = {
{ 0.000001549619403110030, 0.000000203895434417560, 1.70020865326503000 }, // #44 Bulb characteristics (6.3V, 250mA, 1.26W, 5lm)
{ 0.000000929872857822516, 0.000000087040748856477, 2.83368108877505000 }, // #47 Bulb characteristics (6.3V, 150mA, 0.95W, 6.3lm)
Expand All @@ -38,13 +38,13 @@ void bulb_init()
{
// Compute filament temperature to visible emission power LUT, normalized by visible emission power at T=2700K, according
// to the formula from "Luminous radiation from a black body and the mechanical equivalentt of light" by W.W.Coblentz and W.B.Emerson
for (int i=0; i<1500; i++)
for (int i=0; i<= BULB_T_MAX - 1500; i++)
{
double T = 1500.0 + i;
locals.t_to_p[i] = 1.247/pow(1.0+129.05/T, 204.0) + 0.0678/pow(1.0+78.85/T, 404.0) + 0.0489/pow(1.0+23.52/T, 1004.0) + 0.0406/pow(1.0+13.67/T, 2004.0);
}
double P2700 = locals.t_to_p[2700 - 1500];
for (int i=0; i<1500; i++)
for (int i=0; i<= BULB_T_MAX - 1500; i++)
{
locals.t_to_p[i] /= P2700;
}
Expand All @@ -58,7 +58,7 @@ void bulb_init()
t_pos++;
locals.p_to_t[i] = 1500 + t_pos;
}
for (int i=0; i<3000; i++)
for (int i=0; i <= BULB_T_MAX; i++)
{
double T = i;
// Compute Tungsten specific heat (energy to temperature transfer, depending on temperature) according to forumla from "Heating-times of tungsten filament incandescent lamps" by Dulli Chandra Agrawal
Expand All @@ -80,7 +80,7 @@ void bulb_init()
double bulb_filament_temperature_to_emission(const double T)
{
if (T < 1500.0) return 0;
if (T >= 2999.0) return locals.t_to_p[1499];
if (T >= BULB_T_MAX) return locals.t_to_p[BULB_T_MAX - 1500];
return locals.t_to_p[(int)T - 1500];
// Linear interpolation is not worth its cost
// int lower_T = (int) T, upper_T = (int) (T + 0.5);
Expand All @@ -89,7 +89,7 @@ double bulb_filament_temperature_to_emission(const double T)
}

/*-------------------------------
/ Returns filament temperature for a given visible emission power normalized for a an emission power of 1.0 at 2700K
/ Returns filament temperature for a given visible emission power normalized for an emission power of 1.0 at 2700K
/-------------------------------*/
double bulb_emission_to_filament_temperature(const double p)
{
Expand Down Expand Up @@ -147,7 +147,7 @@ double bulb_heat_up(const int bulb, double T, double duration, const double U, c
{
while (duration > 0.0)
{
T = T < 293.0 ? 293.0 : T > 2999.0 ? 2999.0 : T; // Keeps T within the range of the LUT (between room temperature and melt down point)
T = T < 293.0 ? 293.0 : T > BULB_T_MAX ? BULB_T_MAX : T; // Keeps T within the range of the LUT (between room temperature and melt down point)
double energy;
if (serial_R)
{
Expand Down
2 changes: 2 additions & 0 deletions src/wpc/bulb.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#define BULB_89 3
#define BULB_MAX 4

#define BULB_T_MAX 3400

extern void bulb_init();
extern double bulb_filament_temperature_to_emission(const double T);
extern double bulb_emission_to_filament_temperature(const double p);
Expand Down
Loading

0 comments on commit dbf8888

Please sign in to comment.