pyFuncsInC.c

Go to the documentation of this file.
00001 
00005 #include <pic24_all.h>
00006 #include "pyToC.h"
00007 #include "pyFuncsInC.h"
00008 #include <pps.h>
00009 #include <stdio.h>
00010 
00011 #undef __FILE_ID__
00012 #define __FILE_ID__ 0x70
00013 
00015 
00016 
00021 static PmReturn_t
00022 putPyClassInt(pPmFrame_t *ppframe, int32_t i32_val)
00023 {
00024     PmReturn_t retval = PM_RET_OK;
00025 
00026     pPmObj_t ppo_self;
00027     pPmObj_t ppo_attrs;
00028     pPmObj_t ppo_int;
00029 
00030     // Argument 0 is a pointer to the object.
00031     // Store port and pin in it.
00032     // Raise TypeError if address isn't an object
00033     ppo_self = NATIVE_GET_LOCAL(0);
00034     EXCEPTION_UNLESS(OBJ_GET_TYPE(ppo_self) == OBJ_TYPE_CLI, PM_RET_EX_TYPE, 
00035       "Argument 0 must be an class instance");
00036     ppo_attrs = (pPmObj_t)((pPmInstance_t)ppo_self)->cli_attrs;
00037     PM_CHECK_FUNCTION( int_new(i32_val, &ppo_int) );
00038     PM_CHECK_FUNCTION( dict_setItem(ppo_attrs, PM_NONE, ppo_int) );
00039 
00040     return retval;
00041 }
00042 
00048 static PmReturn_t
00049 getPyClassInt(pPmFrame_t *ppframe, int32_t* pi32_val)
00050 {
00051     PmReturn_t retval = PM_RET_OK;
00052     pPmObj_t ppo_self;
00053     pPmObj_t ppo_attrs;
00054     pPmObj_t ppo_int;
00055 
00056     // Argument 0 is a pointer to the object.
00057     // Store port and pin in it.
00058     // Raise TypeError if address isn't an object
00059     ppo_self = NATIVE_GET_LOCAL(0);
00060     EXCEPTION_UNLESS(OBJ_GET_TYPE(ppo_self) == OBJ_TYPE_CLI, PM_RET_EX_TYPE, 
00061       "Argument 0 must be an class instance");
00062     ppo_attrs = (pPmObj_t) ((pPmInstance_t) ppo_self)->cli_attrs;
00063     PM_CHECK_FUNCTION( dict_getItem(ppo_attrs, PM_NONE, &ppo_int) );
00064     PM_CHECK_FUNCTION( getInt32(ppo_int, pi32_val) );
00065 
00066     return retval;
00067 }
00069 
00073 #define OC_CONTROL_OFFSET 3
00074 
00075 PmReturn_t
00076 configDigitalPinPy(pPmFrame_t *ppframe)
00077 {
00078     PmReturn_t retval = PM_RET_OK;
00079     uint16_t u16_port;
00080     uint16_t u16_pin;
00081     bool_t b_isInput;
00082     bool_t b_isOpenDrain = C_FALSE;
00083     int16_t i16_pullDir = 0;
00084 
00085     // Get the arguments
00086     EXCEPTION_UNLESS(NATIVE_GET_NUM_ARGS() >= 4, PM_RET_EX_TYPE,
00087       "Expected at least 4 arguments, but received %u.",
00088       (uint16_t) NATIVE_GET_NUM_ARGS());
00089     GET_UINT16_ARG(1, &u16_port);
00090     GET_UINT16_ARG(2, &u16_pin);
00091     GET_BOOL_ARG(3, &b_isInput);
00092     if (NATIVE_GET_NUM_ARGS() >= 5)
00093         GET_BOOL_ARG(4, &b_isOpenDrain);
00094     if (NATIVE_GET_NUM_ARGS() >= 6)
00095     GET_INT16_ARG(5, &i16_pullDir);
00096 
00097     // Save the port and pin in theclass
00098     PM_CHECK_FUNCTION( putPyClassInt(ppframe, 
00099       (((int32_t) u16_port) << 16) | u16_pin) );
00100 
00101     PM_CHECK_FUNCTION( configDigitalPin(u16_port, u16_pin, b_isInput, 
00102       b_isOpenDrain, i16_pullDir) );
00103     NATIVE_SET_TOS(PM_NONE);
00104 
00105     return retval;
00106 }
00107 
00116 static PmReturn_t
00117 getPyPortPin(pPmFrame_t *ppframe, uint16_t* pu16_port, uint16_t* pu16_pin)
00118 {
00119     PmReturn_t retval = PM_RET_OK;
00120     int32_t i32_portPin;
00121 
00122     PM_CHECK_FUNCTION( getPyClassInt(ppframe, &i32_portPin) );
00123     *pu16_port = i32_portPin >> 16;
00124     *pu16_pin = i32_portPin & 0x00FF;
00125 
00126     return retval;
00127 }
00128 
00129 PmReturn_t
00130 setDigitalPinPy(pPmFrame_t *ppframe)
00131 {
00132     PmReturn_t retval = PM_RET_OK;
00133     uint16_t u16_port;
00134     uint16_t u16_pin;
00135     bool_t b_isHigh;
00136 
00137     // Get the arguments
00138     CHECK_NUM_ARGS(2);
00139     PM_CHECK_FUNCTION( getPyPortPin(ppframe, &u16_port, &u16_pin) );
00140     GET_BOOL_ARG(1, &b_isHigh);
00141 
00142     // Call the function with these arguments
00143     PM_CHECK_FUNCTION( setDigitalPin(u16_port, u16_pin, b_isHigh) );
00144 
00145     // Return nothing
00146     NATIVE_SET_TOS(PM_NONE);
00147     return retval;
00148 }
00149 
00150 PmReturn_t
00151 readDigitalPinPy(pPmFrame_t *ppframe)
00152 {
00153     PmReturn_t retval = PM_RET_OK;
00154     uint16_t u16_port;
00155     uint16_t u16_pin;
00156     bool_t b_isHigh;
00157 
00158     // Get the arguments
00159     CHECK_NUM_ARGS(1);
00160     PM_CHECK_FUNCTION( getPyPortPin(ppframe, &u16_port, &u16_pin) );
00161 
00162     // Call the function with these arguments
00163     PM_CHECK_FUNCTION( readDigitalPin(u16_port, u16_pin, &b_isHigh) );
00164 
00165     // Return bool
00166     NATIVE_SET_TOS(b_isHigh ? PM_TRUE : PM_FALSE);
00167     return retval;
00168 }
00169 
00170 PmReturn_t
00171 readDigitalValuePy(pPmFrame_t *ppframe)
00172 {
00173     PmReturn_t retval = PM_RET_OK;
00174     uint16_t u16_port;
00175     uint16_t u16_pin;
00176     bool_t b_isHigh;
00177     bool_t b_isInput;
00178 
00179     // Get the arguments
00180     CHECK_NUM_ARGS(1);
00181     PM_CHECK_FUNCTION( getPyPortPin(ppframe, &u16_port, &u16_pin) );
00182 
00183     // Determine if this is an input or an output
00184     PM_CHECK_FUNCTION( getPinIsInput(u16_port, u16_pin, &b_isInput) );
00185     // Read the pin (if it's an input) or the port (if it's an output)
00186     if (b_isInput) {
00187         PM_CHECK_FUNCTION( readDigitalPin(u16_port, u16_pin, &b_isHigh) );
00188     } else {
00189         PM_CHECK_FUNCTION( readDigitalLatch(u16_port, u16_pin, &b_isHigh) );
00190     }
00191 
00192     // Return bool
00193     NATIVE_SET_TOS(b_isHigh ? PM_TRUE : PM_FALSE);
00194     return retval;
00195 }
00196 
00197 PmReturn_t
00198 readDigitalLatchPy(pPmFrame_t *ppframe)
00199 {
00200     PmReturn_t retval = PM_RET_OK;
00201     uint16_t u16_port;
00202     uint16_t u16_pin;
00203     bool_t b_isHigh;
00204 
00205     // Get the arguments
00206     CHECK_NUM_ARGS(1);
00207     PM_CHECK_FUNCTION( getPyPortPin(ppframe, &u16_port, &u16_pin) );
00208 
00209     // Call the function with these arguments
00210     PM_CHECK_FUNCTION( readDigitalLatch(u16_port, u16_pin, &b_isHigh) );
00211 
00212     // Return bool
00213     NATIVE_SET_TOS(b_isHigh ? PM_TRUE : PM_FALSE);
00214     return retval;
00215 }
00216 
00217 PmReturn_t
00218 configAnalogPinPy(pPmFrame_t *ppframe)
00219 {
00220     PmReturn_t retval = PM_RET_OK;
00221     uint16_t u16_analogPin;
00222 
00223     // Get the arguments
00224     CHECK_NUM_ARGS(2);
00225     GET_UINT16_ARG(1, &u16_analogPin);
00226 
00227     // Save the analog pin number in the class
00228     PM_CHECK_FUNCTION( putPyClassInt(ppframe, u16_analogPin) );
00229 
00230     PM_CHECK_FUNCTION( configAnalogPin(u16_analogPin) );
00231     NATIVE_SET_TOS(PM_NONE);
00232 
00233     return retval;
00234 }
00235 
00241 static PmReturn_t
00242 readAnalogCode(pPmFrame_t *ppframe, uint16_t* pu16_analogCode)
00243 {
00244     PmReturn_t retval = PM_RET_OK;
00245     int32_t i32_analogPin;
00246     uint16_t u16_analogPin;
00247 
00248     // Get the arguments
00249     CHECK_NUM_ARGS(1);
00250     PM_CHECK_FUNCTION( getPyClassInt(ppframe, &i32_analogPin) );
00251     ASSERT( (i32_analogPin >= 0) && (i32_analogPin < 32) );
00252     u16_analogPin = i32_analogPin;
00253 
00254     // Read analog value
00255     configADC1_ManualCH0(ADC_CH0_POS_SAMPLEA_AN0 + u16_analogPin, 31, C_TRUE);
00256     *pu16_analogCode = convertADC1();
00257 
00258     return retval;
00259 }
00260 
00261 PmReturn_t
00262 readAnalogCodePy(pPmFrame_t *ppframe)
00263 {
00264     PmReturn_t retval = PM_RET_OK;
00265     uint16_t u16_analogCode;
00266     pPmObj_t ppo_analogCode;
00267         
00268     PM_CHECK_FUNCTION( readAnalogCode(ppframe, &u16_analogCode) );
00269     PM_CHECK_FUNCTION( int_new(u16_analogCode, &ppo_analogCode) );
00270     NATIVE_SET_TOS(ppo_analogCode);
00271     return retval;
00272 }
00273 
00274 PmReturn_t
00275 readAnalogFloatPy(pPmFrame_t *ppframe, float f_scale)
00276 {
00277     PmReturn_t retval = PM_RET_OK;
00278     uint16_t u16_analogCode;
00279     pPmObj_t ppo_analogCode;
00280         
00281     PM_CHECK_FUNCTION( readAnalogCode(ppframe, &u16_analogCode) );
00282     PM_CHECK_FUNCTION( float_new(f_scale*u16_analogCode, &ppo_analogCode) );
00283     NATIVE_SET_TOS(ppo_analogCode);
00284     return retval;
00285 }
00286 
00287 PmReturn_t
00288 configPwmPy(pPmFrame_t *ppframe)
00289 {
00290     PmReturn_t retval = PM_RET_OK;
00291     uint32_t u32_freq;
00292     bool_t b_isTimer2;
00293     uint16_t u16_oc;
00294     int16_t i16_ocPin;
00295     uint16_t u16_pr;
00296 
00297     // Get the arguments and error check them
00298     CHECK_NUM_ARGS(5);
00299     GET_UINT32_ARG(1, &u32_freq);
00300     GET_BOOL_ARG(2, &b_isTimer2);
00301     GET_UINT16_ARG(3, &u16_oc);
00302     GET_INT16_ARG(4, &i16_ocPin);
00303 
00304     PM_CHECK_FUNCTION( configPwm(u32_freq, b_isTimer2, u16_oc, i16_ocPin) );
00305 
00306     // Save the timer and OC number in the class
00307     u16_pr = b_isTimer2 ? PR2 : PR3;
00308     PM_CHECK_FUNCTION( putPyClassInt(ppframe, u16_oc | (((uint32_t) u16_pr) << 16)) );
00309     NATIVE_SET_TOS(PM_NONE);
00310     return retval;
00311 }
00312 
00317 #define OC_REG(u16_reg, u16_n) \
00318   ((volatile uint16_t*) &u16_reg)[(u16_n - 1)*OC_CONTROL_OFFSET]
00319 
00320 PmReturn_t
00321 configPwm(uint32_t u32_freq, bool_t b_isTimer2, uint16_t u16_oc, 
00322   int16_t i16_ocPin)
00323 {
00324     PmReturn_t retval = PM_RET_OK;
00325     uint32_t u32_counts;
00326     uint16_t u16_prescale;
00327     uint16_t u16_t2con;
00328     uint16_t u16_counts;
00329 
00330     EXCEPTION_UNLESS((u16_oc < NUM_OC_MODS) && (u16_oc > 0), PM_RET_EX_VAL,
00331       "Requested OC module %d does not exist", u16_oc);
00332 
00333     // Check and remap pins if possible
00334 #ifdef HAS_REMAPPABLE_PINS
00335     EXCEPTION_UNLESS(i16_ocPin >= 0, PM_RET_EX_VAL,
00336       "Invalid pin RP%d.", i16_ocPin);
00337     EXCEPTION_UNLESS(digitalPinExists(PORT_B_INDEX + (i16_ocPin >> 4), 
00338       i16_ocPin & 0xF), PM_RET_EX_VAL,
00339       "Invalid pin RP%d.", i16_ocPin);
00340     // Make the selected pin an output.
00341     PM_CHECK_FUNCTION( 
00342       configDigitalPin(PORT_B_INDEX + (i16_ocPin >> 4), 
00343       i16_ocPin & 0xF, C_FALSE, C_FALSE, 0) );
00344     // Register RPOR0 has the _RP0R bitfield, with _RPnR bitfields
00345     // every 8 bits. So, cast this as a uint8_t to easily access
00346     // the nth _RPnR bitfield. Then assign it to the appropriate
00347     // OC peripheral.
00348     ((volatile uint8_t*) &RPOR0)[i16_ocPin] = OUT_FN_PPS_OC1 + u16_oc - 1;
00349 #else
00350     EXCEPTION_UNLESS(i16_ocPin < 0, PM_RET_EX_VAL,
00351       "Remapping not possible on this device.");
00352 #endif
00353 
00354     // Start with no PWM signal
00355     OC_REG(OC1RS, u16_oc) = 0;
00356 
00357     // Determine prescale and counts for timer
00358     EXCEPTION_UNLESS(u32_freq <= FCY, PM_RET_EX_VAL,
00359       "Frequency %ld too high", u32_freq);
00360     u32_counts = FCY/u32_freq;
00361     u16_prescale = u32_counts >> 16;
00362     EXCEPTION_UNLESS(u16_prescale <= 256, PM_RET_EX_VAL,
00363       "Frequency %ld too low", u32_freq);
00364     u16_t2con = 0;
00365     if (u16_prescale > 64)
00366     {
00367         u16_t2con = T2_PS_1_256;
00368         u16_counts = (u32_counts >> 8) - 1;
00369     } else if (u16_prescale > 8)
00370     {
00371         u16_t2con = T2_PS_1_64;
00372         u16_counts = (u32_counts >> 6) - 1;
00373     } else if (u16_prescale > 0)
00374     {
00375         u16_t2con = T2_PS_1_8;
00376         u16_counts = (u32_counts >> 3) - 1;
00377     } else {
00378         u16_t2con = T2_PS_1_1;
00379         u16_prescale = 0;
00380         u16_counts = u32_counts - 1;
00381     }
00382 
00383     // Configure timer with count and prescale
00384     if (b_isTimer2)
00385     {
00386         T2CON = T2_OFF | T2_IDLE_CON | T2_GATE_OFF
00387           | T2_32BIT_MODE_OFF
00388           | T2_SOURCE_INT
00389           | u16_t2con;
00390         TMR2 = 0;
00391         PR2 = u16_counts;
00392         OC_REG(OC1CON, u16_oc) = OC_TIMER2_SRC | OC_PWM_FAULT_PIN_DISABLE;
00393         T2CONbits.TON = 1;
00394     } else {
00395         T3CON = T3_OFF | T3_IDLE_CON | T3_GATE_OFF
00396           | T3_SOURCE_INT
00397           | u16_t2con;
00398         PR3 = 0;
00399         PR3 = u16_counts;
00400         OC_REG(OC1CON, u16_oc) = OC_TIMER3_SRC | OC_PWM_FAULT_PIN_DISABLE;
00401         T3CONbits.TON = 1;
00402     }
00403 
00404     return retval;
00405 }
00406 
00416 static PmReturn_t
00417 getPyOcPrn(pPmFrame_t *ppframe, uint16_t* pu16_oc, uint16_t* pu16_prn)
00418 {
00419     PmReturn_t retval = PM_RET_OK;
00420     int32_t i32_prnOc;
00421 
00422     PM_CHECK_FUNCTION( getPyClassInt(ppframe, &i32_prnOc) );
00423     *pu16_prn = i32_prnOc >> 16;
00424     *pu16_oc = i32_prnOc & 0x00FF;
00425 
00426     return retval;
00427 }
00428 
00429 PmReturn_t
00430 setPwmCountsPy(pPmFrame_t *ppframe)
00431 {
00432     PmReturn_t retval = PM_RET_OK;
00433     uint16_t u16_counts;
00434     uint16_t u16_oc;
00435     uint16_t u16_prn;
00436 
00437     CHECK_NUM_ARGS(2);
00438     GET_UINT16_ARG(1, &u16_counts);
00439     PM_CHECK_FUNCTION(getPyOcPrn(ppframe, &u16_oc, &u16_prn) );
00440     PM_CHECK_FUNCTION(setPwmCounts(u16_counts, u16_oc) );
00441 
00442     return retval;
00443 }
00444 
00445 PmReturn_t
00446 setPwmCounts(uint16_t u16_counts, uint16_t u16_oc)
00447 {
00448     PmReturn_t retval = PM_RET_OK;
00449 
00450     ASSERT(u16_oc <= NUM_OC_MODS);
00451     OC_REG(OC1RS, u16_oc) = u16_counts;
00452 
00453     return retval;
00454 }
00455 
00456 PmReturn_t
00457 setPwmRatioPy(pPmFrame_t *ppframe)
00458 {
00459     PmReturn_t retval = PM_RET_OK;
00460     float f_ratio;
00461     uint16_t u16_oc;
00462     uint16_t u16_prn;
00463 
00464     CHECK_NUM_ARGS(2);
00465     GET_FLOAT_ARG(1, &f_ratio);
00466     PM_CHECK_FUNCTION(getPyOcPrn(ppframe, &u16_oc, &u16_prn) );
00467     PM_CHECK_FUNCTION(setPwmCounts((((uint32_t) u16_prn) + 1)*f_ratio, u16_oc) );
00468 
00469     return retval;
00470 }

Generated on Mon Oct 18 07:40:47 2010 for Python-on-a-chip by  doxygen 1.5.9