/*********************************************************************************************************************** PicoMite MMBasic External.c Geoff Graham, Peter Mather Copyright (c) 2021, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name MMBasic be used when referring to the interpreter in any documentation and promotional material and the original copyright message be displayed on the console at startup (additional copyright messages may be added). 4. All advertising materials mentioning features or use of this software must display the following acknowledgement: This product includes software developed by the . 5. Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY AS IS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ************************************************************************************************************************/#include "MMBasic_Includes.h" /** * @file External.c * @author Geoff Graham, Peter Mather * @brief Source for I/O MMBasic commands and functions */ /* * @cond * The following section will be excluded from the documentation. */ #include "Hardware_Includes.h" #include "hardware/watchdog.h" #include "pico/stdlib.h" #include "hardware/clocks.h" #include "hardware/pwm.h" //#include "hardware/gpio.h" #include "hardware/adc.h" #include "hardware/structs/systick.h" #include "hardware/structs/pwm.h" #include "hardware/structs/pads_bank0.h" #include "hardware/structs/adc.h" #include "hardware/dma.h" #include #include #define ANA_AVERAGE 10 #define ANA_DISCARD 2 extern MMFLOAT FDiv(MMFLOAT a, MMFLOAT b); extern MMFLOAT FMul(MMFLOAT a, MMFLOAT b); extern MMFLOAT FSub(MMFLOAT a, MMFLOAT b); const char *PinFunction[] = { "OFF", "AIN", "DIN", "FIN", "PER", "CIN", "INTH", "INTL", "DOUT", "HEARTBEAT", "INTB", "UART0TX", "UART0RX", "UART1TX", "UART1RX", "I2C0SDA", "I2C0SCL", "I2C1SDA", "I2C1SCL", "SPI0RX", "SPI0TX", "SPI0SCK", "SPI1RX", "SPI1TX", "SPI1SCK", "IR", "INT1", "INT2", "INT3", "INT4", "PWM0A", "PWM0B", "PWM1A", "PWM1B", "PWM2A", "PWM2B", "PWM3A", "PWM3B", "PWM4A", "PWM4B", "PWM5A", "PWM5B", "PWM6A", "PWM6B", "PWM7A", "PWM7B", "ADCRAW", #ifdef rp2350 "PWM8A", "PWM8B", "PWM9A", "PWM9B", "PWM10A", "PWM10B", "PWM11A", "PWM11B", #endif "PIO0", #ifdef rp2350 "PIO1", "PIO2", "FFIN" #else "PIO1" #endif }; ; volatile int ExtCurrentConfig[NBRPINS + 1]; volatile int INT1Value, INT1InitTimer, INT1Timer; volatile int INT2Value, INT2InitTimer, INT2Timer; volatile int INT3Value, INT3InitTimer, INT3Timer; volatile int INT4Value, INT4InitTimer, INT4Timer; volatile int64_t INT1Count,INT2Count,INT3Count, INT4Count; uint64_t uSecoffset=0; uint32_t pinmask=0; volatile uint64_t IRoffset=0; void *IrDev, *IrCmd; volatile char IrVarType; volatile char IrState, IrGotMsg; int IrBits, IrCount; unsigned char *IrInterrupt; int last_adc=99; volatile int CallBackEnabled=0; uint8_t IRpin=99; uint8_t PWM0Apin=99; uint8_t PWM1Apin=99; uint8_t PWM2Apin=99; uint8_t PWM3Apin=99; uint8_t PWM4Apin=99; uint8_t PWM5Apin=99; uint8_t PWM6Apin=99; uint8_t PWM7Apin=99; #ifdef rp2350 uint8_t PWM8Apin=99; uint8_t PWM9Apin=99; uint8_t PWM10Apin=99; uint8_t PWM11Apin=99; #endif uint8_t PWM0Bpin=99; uint8_t PWM1Bpin=99; uint8_t PWM2Bpin=99; uint8_t PWM3Bpin=99; uint8_t PWM4Bpin=99; uint8_t PWM5Bpin=99; uint8_t PWM6Bpin=99; uint8_t PWM7Bpin=99; #ifdef rp2350 uint8_t PWM8Bpin=99; uint8_t PWM9Bpin=99; uint8_t PWM10Bpin=99; uint8_t PWM11Bpin=99; #endif uint8_t UART1RXpin=99; uint8_t UART1TXpin=99; uint8_t UART0TXpin=99; uint8_t UART0RXpin=99; uint8_t SPI1TXpin=99; uint8_t SPI1RXpin=99; uint8_t SPI1SCKpin=99; uint8_t SPI0TXpin=99; uint8_t SPI0RXpin=99; uint8_t SPI0SCKpin=99; uint8_t I2C1SDApin=99; uint8_t I2C1SCLpin=99; uint8_t I2C0SDApin=99; uint8_t I2C0SCLpin=99; uint8_t slice0=0,slice1=0,slice2=0,slice3=0,slice4=0,slice5=0,slice6=0,slice7=0; #ifdef rp2350 uint8_t slice8=0,slice9=0,slice10=0,slice11=0; bool fast_timer_active=false; volatile uint64_t INT5Count, INT5Value, INT5InitTimer, INT5Timer; #endif bool dmarunning=false; bool ADCDualBuffering=false; uint32_t ADCmax=0; int ADCopen=0; char *ADCInterrupt; volatile MMFLOAT * volatile a1float=NULL, * volatile a2float=NULL, * volatile a3float=NULL, * volatile a4float=NULL; volatile int ADCpos=0; float frequency; uint32_t ADC_dma_chan=ADC_DMA; uint32_t ADC_dma_chan2=ADC_DMA2; short *ADCbuffer=NULL; void PWMoff(int slice); volatile uint8_t *adcint=NULL; uint8_t *adcint1=NULL; uint8_t *adcint2=NULL; MMFLOAT ADCscale[4], ADCbottom[4]; extern void mouse0close(void); //Vector to CFunction routine called every command (ie, from the BASIC interrupt checker) uint64_t readusclock(void){ return time_us_64()-uSecoffset; } void writeusclock(uint64_t timeset){ uSecoffset=time_us_64()-(uint64_t)timeset; } uint64_t readIRclock(void){ return time_us_64()-IRoffset; } void writeIRclock(uint64_t timeset){ IRoffset=time_us_64()-(uint64_t)timeset; } #ifdef rp2350 const uint8_t PINMAP[48]={1,2,4,5,6,7,9,10,11,12,14,15,16,17,19,20,21,22,24,25,26,27,29,41,42,43,31,32,34,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62}; int codemap(int pin){ #ifdef PICOMITEWEB if(pin>29 || pin<0 || pin==23 || pin==24 || pin==25 || pin==29) error("Invalid GPIO"); #else if(pin>(rp2350a? 29:47) || pin<0) error("Invalid GPIO"); #endif return (int)PINMAP[pin]; } #else const uint8_t PINMAP[30]={1,2,4,5,6,7,9,10,11,12,14,15,16,17,19,20,21,22,24,25,26,27,29,41,42,43,31,32,34,44}; int codemap(int pin){ #ifdef PICOMITEWEB if(pin>29 || pin<0 || pin==23 || pin==24 || pin==25 || pin==29) error("Invalid GPIO"); #else if(pin>29 || pin<0) error("Invalid GPIO"); #endif return (int)PINMAP[pin]; } #endif int codecheck(unsigned char *line){ if((line[0]=='G' || line[0]=='g') && (line[1]=='P' || line[1]=='p')){ line+=2; if(isnamestart(*line) || *line=='.') return 1; if(isdigit(*line) && !isnamechar(line[1])) { return 0; } line++; if(!(isdigit(*line))) return 2; line++; if(isnamechar(*line)) return 3; } else return 4; return 0; } #ifdef rp2350 void __not_in_flash_func(on_pwm_wrap_1)(void) { pwm_clear_irq(0); INT5Count++; } #endif void SoftReset(void){ _excep_code = SOFT_RESET; #ifdef USBKEYBOARD USBenabled=false; uSec(50000); //wait for outstanding requests to complete #endif watchdog_enable(1, 1); while(1); } #ifdef rp2350 void __not_in_flash_func(PinSetBit)(int pin, unsigned int offset) { #else #if defined(PICOMITEVGA) || defined(PICOMITEWEB) void PinSetBit(int pin, unsigned int offset) { #else void __not_in_flash_func(PinSetBit)(int pin, unsigned int offset) { #endif #endif switch (offset){ case LATCLR: gpio_set_pulls(PinDef[pin].GPno,false,false); gpio_pull_down(PinDef[pin].GPno); gpio_put(PinDef[pin].GPno,GPIO_PIN_RESET); return; case LATSET: gpio_set_pulls(PinDef[pin].GPno,false,false); gpio_pull_up(PinDef[pin].GPno); gpio_put(PinDef[pin].GPno,GPIO_PIN_SET); return; case LATINV: gpio_xor_mask64(1< NBRPINS) return true; #else if(pin < 1 || pin > (rp2350a ? 44: NBRPINS)) return true; #endif #else if(pin < 1 || pin > NBRPINS) return true; #endif if(PinDef[pin].mode & UNUSED) return true; return false; } #ifdef PICOMITEWEB void ExtSet(int pin, int val){ #else #ifndef rp2350 #ifdef PICOMITEVGA void ExtSet(int pin, int val){ #else void __not_in_flash_func(ExtSet)(int pin, int val){ #endif #else void __not_in_flash_func(ExtSet)(int pin, int val){ #endif #endif if(ExtCurrentConfig[pin] == EXT_NOT_CONFIG || ExtCurrentConfig[pin] == EXT_DIG_OUT/* || ExtCurrentConfig[pin] == EXT_OC_OUT*/) { PinSetBit(pin, val ? LATSET : LATCLR); if(ExtCurrentConfig[pin] == EXT_NOT_CONFIG){ pinmask|=(1< 2000)CheckAbort(); } endtime+=synctime; } else { if(argc==0)error("sync not initialised"); i=getint(argv[0],0,0x7FFFFFFFFFFFFFFF); if(i){ if(argc==3){ if(checkstring(argv[2],(unsigned char *)"U")){ i *= 1; } else if(checkstring(argv[2],(unsigned char *)"M")){ i *= 1000; } else if(checkstring(argv[2],(unsigned char *)"S")){ i *= 1000000; } } synctime=i; endtime=time_us_64()+synctime; } else { synctime=endtime=0; } } } // this is invoked as a command (ie, pin(3) = 1) // first get the argument then step over the closing bracket. Search through the rest of the command line looking // for the equals sign and step over it, evaluate the rest of the command and set the pin accordingly void cmd_pin(void) { int pin, value; unsigned char code; if(!(code=codecheck(cmdline)))cmdline+=2; pin = getinteger(cmdline); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin"); while(*cmdline && tokenfunction(*cmdline) != op_equal) cmdline++; if(!*cmdline) error("Invalid syntax"); ++cmdline; if(!*cmdline) error("Invalid syntax"); value = getinteger(cmdline); ExtSet(pin, value); } /* * @cond * The following section will be excluded from the documentation. */ void ClearPin(int pin){ if(pin==IRpin)IRpin=99; if(pin==PWM0Apin)PWM0Apin=99; if(pin==PWM1Apin)PWM1Apin=99; if(pin==PWM2Apin)PWM2Apin=99; if(pin==PWM3Apin)PWM3Apin=99; if(pin==PWM4Apin)PWM4Apin=99; if(pin==PWM5Apin)PWM5Apin=99; if(pin==PWM6Apin)PWM6Apin=99; if(pin==PWM7Apin)PWM7Apin=99; #ifdef rp2350 if(pin==PWM8Apin)PWM8Apin=99; if(pin==PWM9Apin)PWM9Apin=99; if(pin==PWM10Apin)PWM10Apin=99; if(pin==PWM11Apin)PWM11Apin=99; #endif if(pin==PWM0Bpin)PWM0Bpin=99; if(pin==PWM1Bpin)PWM1Bpin=99; if(pin==PWM2Bpin)PWM2Bpin=99; if(pin==PWM3Bpin)PWM3Bpin=99; if(pin==PWM4Bpin)PWM4Bpin=99; if(pin==PWM5Bpin)PWM5Bpin=99; if(pin==PWM6Bpin)PWM6Bpin=99; if(pin==PWM7Bpin)PWM7Bpin=99; #ifdef rp2350 if(pin==PWM8Bpin)PWM8Bpin=99; if(pin==PWM9Bpin)PWM9Bpin=99; if(pin==PWM10Bpin)PWM10Bpin=99; if(pin==PWM11Bpin)PWM11Bpin=99; #endif if(pin==UART0TXpin)UART0TXpin=99; if(pin==UART0RXpin)UART0RXpin=99; if(pin==UART1RXpin)UART1RXpin=99; if(pin==UART1TXpin)UART1TXpin=99; if(pin==SPI1TXpin)SPI1TXpin=99; if(pin==SPI1RXpin)SPI1RXpin=99; if(pin==SPI1SCKpin)SPI1SCKpin=99; if(pin==SPI0TXpin)SPI0TXpin=99; if(pin==SPI0RXpin)SPI0RXpin=99; if(pin==SPI0SCKpin)SPI0SCKpin=99; if(pin==I2C1SDApin)I2C1SDApin=99; if(pin==I2C1SCLpin)I2C1SCLpin=99; if(pin==I2C0SDApin)I2C0SDApin=99; if(pin==I2C0SCLpin)I2C0SCLpin=99; } /**************************************************************************************************************************** Configure an I/O pin *****************************************************************************************************************************/ void MIPS16 ExtCfg(int pin, int cfg, int option) { int i, tris=0, ana=0, edge; CheckPin(pin, CP_IGNORE_INUSE | CP_IGNORE_RESERVED); if(cfg >= EXT_DS18B20_RESERVED) { ExtCurrentConfig[pin] |= cfg; // don't do anything except set the config type return; } ClearPin(pin); //disable the link to any special functions if(pin == Option.INT1pin) { if(CallBackEnabled==2) gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else gpio_set_irq_enabled(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~2); } if(pin == Option.INT2pin) { if(CallBackEnabled==4) gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else gpio_set_irq_enabled(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~4); } if(pin == Option.INT3pin) { if(CallBackEnabled==8) gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else gpio_set_irq_enabled(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~8); } if(pin == Option.INT4pin) { if(CallBackEnabled==16) gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else gpio_set_irq_enabled(PinDef[pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~16); } #ifdef rp2350 if(pin==FAST_TIMER_PIN && ExtCurrentConfig[pin]==EXT_FAST_TIMER){ slice0=0; pwm_set_irq1_enabled(0, false); } #endif // make sure any pullups/pulldowns are removed in case we are changing from a digital input gpio_disable_pulls(PinDef[pin].GPno); // disable ADC if we are changing from a analogue input if(ExtCurrentConfig[pin]==EXT_ANA_IN || ExtCurrentConfig[pin]==EXT_ADCRAW )PinSetBit(pin, ANSELCLR); for(i = 0; i < NBRINTERRUPTS; i++) if(inttbl[i].pin == pin) inttbl[i].pin = 0; // start off by disable a software interrupt (if set) on this pin gpio_set_input_enabled(PinDef[pin].GPno,false); gpio_deinit(PinDef[pin].GPno); gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); if(cfg!=EXT_NOT_CONFIG)gpio_init(PinDef[pin].GPno); switch(cfg) { case EXT_NOT_CONFIG: tris = 1; ana = 1; // gpio_init(PinDef[pin].GPno); // gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); gpio_set_input_enabled(PinDef[pin].GPno,false); gpio_deinit(PinDef[pin].GPno); switch(ExtCurrentConfig[pin]){ //Disable the pin numbers used by the special function code case EXT_IR: IRpin=99; break; case EXT_PWM0A: PWM0Apin=99; break; case EXT_PWM1A: PWM1Apin=99; break; case EXT_PWM2A: PWM2Apin=99; break; case EXT_PWM3A: PWM3Apin=99; break; case EXT_PWM4A: PWM4Apin=99; break; case EXT_PWM5A: PWM5Apin=99; break; case EXT_PWM6A: PWM6Apin=99; break; case EXT_PWM7A: PWM7Apin=99; break; #ifdef rp2350 case EXT_PWM8A: PWM8Apin=99; break; case EXT_PWM9A: PWM9Apin=99; break; case EXT_PWM10A: PWM10Apin=99; break; case EXT_PWM11A: PWM11Apin=99; break; #endif case EXT_PWM0B: PWM0Bpin=99; break; case EXT_PWM1B: PWM1Bpin=99; break; case EXT_PWM2B: PWM2Bpin=99; break; case EXT_PWM3B: PWM3Bpin=99; break; case EXT_PWM4B: PWM4Bpin=99; break; case EXT_PWM5B: PWM5Bpin=99; break; case EXT_PWM6B: PWM6Bpin=99; break; case EXT_PWM7B: PWM7Bpin=99; break; #ifdef rp2350 case EXT_PWM8B: PWM8Bpin=99; break; case EXT_PWM9B: PWM9Bpin=99; break; case EXT_PWM10B: PWM10Bpin=99; break; case EXT_PWM11B: PWM11Bpin=99; break; #endif case EXT_UART0TX: UART0TXpin=99; break; case EXT_UART0RX: UART0RXpin=99; break; case EXT_UART1TX: UART1TXpin=99; break; case EXT_UART1RX: UART1RXpin=99; break; case EXT_I2C0SDA: I2C0SDApin=99; break; case EXT_I2C0SCL: I2C0SCLpin=99; break; case EXT_I2C1SDA: I2C1SDApin=99; break; case EXT_I2C1SCL: I2C1SCLpin=99; break; case EXT_SPI0RX: SPI0RXpin=99; break; case EXT_SPI0TX: SPI0TXpin=99; break; case EXT_SPI0SCK: SPI0SCKpin=99; break; case EXT_SPI1RX: SPI1RXpin=99; break; case EXT_SPI1TX: SPI1TXpin=99; break; case EXT_SPI1SCK: SPI1SCKpin=99; break; } break; #ifdef rp2350 case EXT_ADCRAW: case EXT_ANA_IN: if(!(PinDef[pin].mode & ANALOG_IN)) error("Invalid configuration"); if(pin<=44 && rp2350a==0) error("Invalid configuration"); if(pin> 44 && rp2350a) error("Invalid configuration"); tris = 1; ana = 0; break; #else case EXT_ADCRAW: case EXT_ANA_IN: if(!(PinDef[pin].mode & ANALOG_IN)) error("Invalid configuration"); tris = 1; ana = 0; break; #endif case EXT_CNT_IN: case EXT_FREQ_IN: // same as counting, so fall through case EXT_PER_IN: // same as counting, so fall through edge = GPIO_IRQ_EDGE_RISE; if(cfg==EXT_CNT_IN && option==2)edge = GPIO_IRQ_EDGE_FALL; if(cfg==EXT_CNT_IN && option>=3)edge = GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE; if(option==1 || option==4)gpio_pull_down (PinDef[pin].GPno); if(option==2 || option==5)gpio_pull_up (PinDef[pin].GPno); irq_set_priority(IO_IRQ_BANK0,0); PinSetBit(pin,TRISSET); if(pin == Option.INT1pin) { if(!CallBackEnabled){ gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, edge , true, &gpio_callback); CallBackEnabled=2; } else { gpio_set_irq_enabled(PinDef[pin].GPno, edge, true); CallBackEnabled|=2; } INT1Count = INT1Value = 0; INT1Timer = INT1InitTimer = option; // only used for frequency and period measurement tris = 1; ana = 1; gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); break; } if(pin == Option.INT2pin) { if(!CallBackEnabled){ gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, edge , true, &gpio_callback); CallBackEnabled=4; } else { gpio_set_irq_enabled(PinDef[pin].GPno, edge, true); CallBackEnabled|=4; } INT2Count = INT2Value = 0; INT2Timer = INT2InitTimer = option; // only used for frequency and period measurement tris = 1; ana = 1; gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); break; } if(pin == Option.INT3pin) { if(!CallBackEnabled){ gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, edge , true, &gpio_callback); CallBackEnabled=8; } else { gpio_set_irq_enabled(PinDef[pin].GPno, edge, true); CallBackEnabled|=8; } INT3Count = INT3Value = 0; INT3Timer = INT3InitTimer = option; // only used for frequency and period measurement tris = 1; ana = 1; gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); break; } if(pin == Option.INT4pin) { if(!CallBackEnabled){ gpio_set_irq_enabled_with_callback(PinDef[pin].GPno, edge , true, &gpio_callback); CallBackEnabled=16; } else { gpio_set_irq_enabled(PinDef[pin].GPno, edge, true); CallBackEnabled|=16; } INT4Count = INT4Value = 0; INT4Timer = INT4InitTimer = option; // only used for frequency and period measurement tris = 1; ana = 1; gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); break; } error("Invalid configuration"); // not an interrupt enabled pin return; case EXT_INT_LO: // same as digital input, so fall through case EXT_INT_HI: // same as digital input, so fall through case EXT_INT_BOTH: // same as digital input, so fall through case EXT_DIG_IN: if(!(PinDef[pin].mode & DIGITAL_IN)) error("Invalid configuration"); if(option) PinSetBit(pin, option); tris = 1; ana = 1; gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); break; case EXT_PIO0_OUT: case EXT_PIO1_OUT: #ifdef rp2350 case EXT_PIO2_OUT: #endif case EXT_DIG_OUT: if(!(PinDef[pin].mode & DIGITAL_OUT)) error("Invalid configuration"); tris = 0; ana = 1; gpio_set_drive_strength(PinDef[pin].GPno,GPIO_DRIVE_STRENGTH_8MA); break; #ifndef PICOMITEWEB case EXT_HEARTBEAT: if(!(pin=HEARTBEATpin)) error("Invalid configuration"); tris = 0; ana = 1; break; #endif case EXT_UART0TX: if(!(PinDef[pin].mode & UART0TX)) error("Invalid configuration"); if((UART0TXpin!=99)) error("Already Set to pin %",UART0TXpin); UART0TXpin=pin; break; case EXT_UART0RX: if(!(PinDef[pin].mode & UART0RX)) error("Invalid configuration"); if((UART0RXpin!=99)) error("Already Set to pin %",UART0RXpin); UART0RXpin=pin; break; case EXT_UART1TX: if(!(PinDef[pin].mode & UART1TX)) error("Invalid configuration"); if((UART1TXpin!=99)) error("Already Set to pin %",UART1TXpin); UART1TXpin=pin; break; case EXT_UART1RX: if(!(PinDef[pin].mode & UART1RX)) error("Invalid configuration"); if((UART1RXpin!=99)) error("Already Set to pin %",UART1RXpin); UART1RXpin=pin; break; case EXT_SPI0TX: if(!(PinDef[pin].mode & SPI0TX)) error("Invalid configuration"); if(SPI0locked)error("SPI in use for SYSTEM SPI"); if((SPI0TXpin!=99 && SPI0TXpin!=pin)) error("Already Set to pin %",SPI0TXpin); SPI0TXpin=pin; break; case EXT_SPI0RX: if(!(PinDef[pin].mode & SPI0RX)) error("Invalid configuration"); if(SPI0locked)error("SPI in use for SYSTEM SPI"); if((SPI0RXpin!=99 && SPI0RXpin!=pin)) error("Already Set to pin %",SPI0RXpin); SPI0RXpin=pin; break; case EXT_SPI0SCK: if(!(PinDef[pin].mode & SPI0SCK)) error("Invalid configuration"); if(SPI0locked)error("SPI in use for SYSTEM SPI"); if((SPI0SCKpin!=99 && SPI0SCKpin!=pin)) error("Already Set to pin %",SPI0SCKpin); SPI0SCKpin=pin; break; case EXT_SPI1TX: if(!(PinDef[pin].mode & SPI1TX)) error("Invalid configuration"); if(SPI1locked)error("SPI2 in use for SYSTEM SPI"); if((SPI1TXpin!=99 && SPI1TXpin!=pin)) error("Already Set to pin %",SPI1TXpin); SPI1TXpin=pin; break; case EXT_SPI1RX: if(!(PinDef[pin].mode & SPI1RX)) error("Invalid configuration"); if(SPI1locked)error("SPI2 in use for SYSTEM SPI"); if((SPI1RXpin!=99 && SPI1RXpin!=pin)) error("Already Set to pin %",SPI1RXpin); SPI1RXpin=pin; break; case EXT_SPI1SCK: if(!(PinDef[pin].mode & SPI1SCK)) error("Invalid configuration"); if(SPI1locked)error("SPI2 in use for SYSTEM SPI"); if((SPI1SCKpin!=99 && SPI1SCKpin!=pin)) error("Already Set to pin %",SPI1SCKpin); SPI1SCKpin=pin; break; case EXT_IR: if((IRpin!=99)) error("Already Set to pin %",IRpin); IRpin=pin; break; case EXT_PWM0A: if(!(PinDef[pin].mode & PWM0A)) error("Invalid configuration"); if((PWM0Apin!=99 && PWM0Apin!=pin)) error("Already Set to pin %",PWM0Apin); PWM0Apin=pin; break; case EXT_PWM1A: if(!(PinDef[pin].mode & PWM1A)) error("Invalid configuration"); if((PWM1Apin!=99 && PWM1Apin!=pin)) error("Already Set to pin %",PWM1Apin); PWM1Apin=pin; break; case EXT_PWM2A: if(!(PinDef[pin].mode & PWM2A)) error("Invalid configuration"); if((PWM2Apin!=99 && PWM2Apin!=pin)) error("Already Set to pin %",PWM2Apin); PWM2Apin=pin; gpio_set_drive_strength (PinDef[pin].GPno, GPIO_DRIVE_STRENGTH_8MA); gpio_set_slew_rate(PinDef[pin].GPno,GPIO_SLEW_RATE_FAST); break; case EXT_PWM3A: if(!(PinDef[pin].mode & PWM3A)) error("Invalid configuration"); if((PWM3Apin!=99 && PWM3Apin!=pin)) error("Already Set to pin %",PWM3Apin); PWM3Apin=pin; break; case EXT_PWM4A: if(!(PinDef[pin].mode & PWM4A)) error("Invalid configuration"); if((PWM4Apin!=99 && PWM4Apin!=pin)) error("Already Set to pin %",PWM4Apin); PWM4Apin=pin; break; case EXT_PWM5A: if(!(PinDef[pin].mode & PWM5A)) error("Invalid configuration"); if((PWM5Apin!=99 && PWM5Apin!=pin)) error("Already Set to pin %",PWM5Apin); PWM5Apin=pin; break; case EXT_PWM6A: if(!(PinDef[pin].mode & PWM6A)) error("Invalid configuration"); if((PWM6Apin!=99 && PWM6Apin!=pin)) error("Already Set to pin %",PWM6Apin); PWM6Apin=pin; break; case EXT_PWM7A: if(!(PinDef[pin].mode & PWM7A)) error("Invalid configuration"); if((PWM7Apin!=99 && PWM7Apin!=pin)) error("Already Set to pin %",PWM7Apin); PWM7Apin=pin; break; #ifdef rp2350 case EXT_PWM8A: if(!(PinDef[pin].mode & PWM8A) || rp2350a) error("Invalid configuration"); if((PWM8Apin!=99 && PWM8Apin!=pin)) error("Already Set to pin %",PWM8Apin); PWM8Apin=pin; break; case EXT_PWM9A: if(!(PinDef[pin].mode & PWM9A) || rp2350a) error("Invalid configuration"); if((PWM9Apin!=99 && PWM9Apin!=pin)) error("Already Set to pin %",PWM9Apin); PWM9Apin=pin; break; case EXT_PWM10A: if(!(PinDef[pin].mode & PWM10A) || rp2350a) error("Invalid configuration"); if((PWM10Apin!=99 && PWM10Apin!=pin)) error("Already Set to pin %",PWM10Apin); PWM10Apin=pin; break; case EXT_PWM11A: if(!(PinDef[pin].mode & PWM11A) || rp2350a) error("Invalid configuration"); if((PWM11Apin!=99 && PWM11Apin!=pin)) error("Already Set to pin %",PWM11Apin); PWM11Apin=pin; break; #endif case EXT_PWM0B: if(!(PinDef[pin].mode & PWM0B)) error("Invalid configuration"); if((PWM0Bpin!=99 && PWM0Bpin!=pin)) error("Already Set to pin %",PWM0Bpin); PWM0Bpin=pin; break; case EXT_PWM1B: if(!(PinDef[pin].mode & PWM1B)) error("Invalid configuration"); if((PWM1Bpin!=99 && PWM1Bpin!=pin)) error("Already Set to pin %",PWM1Bpin); PWM1Bpin=pin; break; case EXT_PWM2B: if(!(PinDef[pin].mode & PWM2B)) error("Invalid configuration"); if((PWM2Bpin!=99 && PWM2Bpin!=pin)) error("Already Set to pin %",PWM2Bpin); PWM2Bpin=pin; break; case EXT_PWM3B: if(!(PinDef[pin].mode & PWM3B)) error("Invalid configuration"); if((PWM3Bpin!=99 && PWM3Bpin!=pin)) error("Already Set to pin %",PWM3Bpin); PWM3Bpin=pin; break; case EXT_PWM4B: if(!(PinDef[pin].mode & PWM4B)) error("Invalid configuration"); if((PWM4Bpin!=99 && PWM4Bpin!=pin)) error("Already Set to pin %",PWM4Bpin); PWM4Bpin=pin; break; case EXT_PWM5B: if(!(PinDef[pin].mode & PWM5B)) error("Invalid configuration"); if((PWM5Bpin!=99 && PWM5Bpin!=pin)) error("Already Set to pin %",PWM5Bpin); PWM5Bpin=pin; break; case EXT_PWM6B: if(!(PinDef[pin].mode & PWM6B)) error("Invalid configuration"); if((PWM6Bpin!=99 && PWM6Bpin!=pin)) error("Already Set to pin %",PWM6Bpin); PWM6Bpin=pin; break; case EXT_PWM7B: if(!(PinDef[pin].mode & PWM7B)) error("Invalid configuration"); if((PWM7Bpin!=99 && PWM7Bpin!=pin)) error("Already Set to pin %",PWM7Bpin); PWM7Bpin=pin; break; #ifdef rp2350 #ifndef PICOMITEWEB case EXT_PWM8B: if(!(PinDef[pin].mode & PWM8B) || rp2350a) error("Invalid configuration"); if((PWM8Bpin!=99 && PWM8Bpin!=pin)) error("Blready Set to pin %",PWM8Bpin); PWM8Bpin=pin; break; case EXT_PWM9B: if(!(PinDef[pin].mode & PWM9B) || rp2350a) error("Invalid configuration"); if((PWM9Bpin!=99 && PWM9Bpin!=pin)) error("Blready Set to pin %",PWM9Bpin); PWM9Bpin=pin; break; case EXT_PWM10B: if(!(PinDef[pin].mode & PWM10B) || rp2350a) error("Invalid configuration"); if((PWM10Bpin!=99 && PWM10Bpin!=pin)) error("Blready Set to pin %",PWM10Bpin); PWM10Bpin=pin; break; case EXT_PWM11B: if(!(PinDef[pin].mode & PWM11B) || rp2350a) error("Invalid configuration"); if((PWM11Bpin!=99 && PWM11Bpin!=pin)) error("Blready Set to pin %",PWM11Bpin); PWM11Bpin=pin; break; #endif case EXT_FAST_TIMER: if(!(PinDef[pin].mode & PWM0B)) error("Invalid configuration"); if((PWM0Bpin!=99 && PWM0Bpin!=pin)) error("Already Set to pin %",PWM0Bpin); PWM0Bpin=pin; INT5Count = INT5Value = 0; INT5Timer = INT5InitTimer = option; // only used for frequency and period measurement tris = 1; ana = 1; // PinSetBit(pin,TRISSET); gpio_set_input_hysteresis_enabled(PinDef[pin].GPno,true); gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_PWM); pwm_config cfg = pwm_get_default_config(); pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_B_RISING); pwm_config_set_clkdiv(&cfg, 1); pwm_init(0, &cfg, false); pwm_set_wrap(0, 49999); pwm_clear_irq(0); irq_set_exclusive_handler(PWM_IRQ_WRAP_1, on_pwm_wrap_1); irq_set_enabled(PWM_IRQ_WRAP_1, true); irq_set_priority(PWM_IRQ_WRAP_1,0); pwm_set_irq1_enabled(0, true); pwm_set_enabled(0, true); break; #endif case EXT_I2C0SDA: if(!(PinDef[pin].mode & I2C0SDA)) error("Invalid configuration"); if(I2C0locked)error("I2C in use for SYSTEM I2C"); if((I2C0SDApin!=99 && I2C0SDApin!=pin)) error("Already Set to pin %",I2C0SDApin); I2C0SDApin=pin; break; case EXT_I2C0SCL: if(!(PinDef[pin].mode & I2C0SCL)) error("Invalid configuration"); if(I2C0locked)error("I2C in use for SYSTEM I2C"); if((I2C0SCLpin!=99 && I2C0SCLpin!=pin)) error("Already Set to pin %",I2C0SCLpin); I2C0SCLpin=pin; break; case EXT_I2C1SDA: if(!(PinDef[pin].mode & I2C1SDA)) error("Invalid configuration"); if(I2C1locked)error("I2C2 in use for SYSTEM I2C"); if((I2C1SDApin!=99) && I2C1SDApin!=pin) error("Already Set to pin %",I2C1SDApin); I2C1SDApin=pin; break; case EXT_I2C1SCL: if(!(PinDef[pin].mode & I2C1SCL)) error("Invalid configuration"); if(I2C1locked)error("I2C2 in use for SYSTEM I2C"); if((I2C1SCLpin!=99 && I2C1SCLpin!=pin)) error("Already Set to pin %",I2C1SCLpin); I2C1SCLpin=pin; break; default: error("Invalid configuration"); return; } ExtCurrentConfig[pin] = cfg; if(cfg<=EXT_INT_BOTH || cfg==EXT_ADCRAW){ // *GetPortAddr(pin, ana ? ANSELCLR : ANSELSET) = (1 << GetPinBit(pin));// if ana = 1 then it is a digital I/O PinSetBit(pin, tris ? TRISSET : TRISCLR); // if tris = 1 then it is an input if(!tris && (pinmask & (1<=EXT_UART0TX && cfg<=EXT_UART1RX){ gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_UART); if(cfg==EXT_UART0RX || cfg==EXT_UART1RX)gpio_set_pulls(PinDef[pin].GPno,true,false); } else if(cfg>=EXT_I2C0SDA && cfg<=EXT_I2C1SCL)gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_I2C); else if(cfg>=EXT_SPI0RX && cfg<=EXT_SPI1SCK)gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_SPI); #ifdef rp2350 else if(cfg>=EXT_PWM0A && cfg<=(rp2350a ? EXT_PWM7B : EXT_PWM11B))gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_PWM); #else else if(cfg>=EXT_PWM0A && cfg<=EXT_PWM7B)gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_PWM); #endif else if(cfg==EXT_PIO0_OUT){ gpio_set_input_enabled(PinDef[pin].GPno, true); gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_PIO0); } else if(cfg==EXT_PIO1_OUT){ gpio_set_input_enabled(PinDef[pin].GPno, true); gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_PIO1); } #ifdef rp2350 else if(cfg==EXT_PIO2_OUT){ gpio_set_input_enabled(PinDef[pin].GPno, true); gpio_set_function(PinDef[pin].GPno, GPIO_FUNC_PIO2); } #endif uSec(2); } extern int adc_clk_div; #ifndef rp2350 #ifdef PICOMITEVGA int64_t ExtInp(int pin){ #else int64_t __not_in_flash_func(ExtInp)(int pin){ #endif #else int64_t __not_in_flash_func(ExtInp)(int pin){ #endif if(ExtCurrentConfig[pin]==EXT_ANA_IN || ExtCurrentConfig[pin]==EXT_ADCRAW){ if(adc_clk_div!=adc_hw->div){ SetADCFreq(500000.0); } if(last_adc!=pin){ last_adc=pin; adc_select_input(PinDef[pin].ADCpin); } int a= adc_read(); if(adc_hw->cs & (ADC_CS_ERR_STICKY_BITS | ADC_CS_ERR_BITS)) { hw_set_bits(&adc_hw->cs, ADC_CS_ERR_STICKY_BITS); a=-1; } return a; } else if(ExtCurrentConfig[pin] == EXT_FREQ_IN || ExtCurrentConfig[pin] == EXT_PER_IN) { // select input channel if(pin == Option.INT1pin) return INT1Value; if(pin == Option.INT2pin) return INT2Value; if(pin == Option.INT3pin) return INT3Value; if(pin == Option.INT4pin) return INT4Value; } else if(ExtCurrentConfig[pin] == EXT_CNT_IN) { // select input channel if(pin == Option.INT1pin) return INT1Count; if(pin == Option.INT2pin) return INT2Count; if(pin == Option.INT3pin) return INT3Count; if(pin == Option.INT4pin) return INT4Count; } else if(ExtCurrentConfig[pin] == EXT_DIG_OUT) { return gpio_get_out_level(PinDef[pin].GPno); } else { return gpio_get(PinDef[pin].GPno); } return 0; } /* @endcond */ void MIPS16 cmd_setpin(void) { int i, pin, pin2=0, pin3=0, value=-1, value2=0, value3=0, option = 0; getargs(&cmdline, 7, (unsigned char *)","); if(argc%2 == 0 || argc < 3) error("Argument count"); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap(pin); if(checkstring(argv[2], (unsigned char *)"OFF") || checkstring(argv[2], (unsigned char *)"0")) value = EXT_NOT_CONFIG; else if(checkstring(argv[2], (unsigned char *)"AIN")) value = EXT_ANA_IN; else if(checkstring(argv[2], (unsigned char *)"ARAW")) value = EXT_ADCRAW; else if(checkstring(argv[2], (unsigned char *)"DIN")) value = EXT_DIG_IN; else if(checkstring(argv[2], (unsigned char *)"FIN")) value = EXT_FREQ_IN; else if(checkstring(argv[2], (unsigned char *)"PIN")) value = EXT_PER_IN; else if(checkstring(argv[2], (unsigned char *)"CIN")) value = EXT_CNT_IN; else if(checkstring(argv[2], (unsigned char *)"INTH")) value = EXT_INT_HI; else if(checkstring(argv[2], (unsigned char *)"INTL")) value = EXT_INT_LO; else if(checkstring(argv[2], (unsigned char *)"DOUT")) value = EXT_DIG_OUT; else if(checkstring(argv[2], (unsigned char *)"HEARTBEAT")) value = EXT_HEARTBEAT; else if(checkstring(argv[2], (unsigned char *)"INTB")) value = EXT_INT_BOTH; else if(checkstring(argv[2], (unsigned char *)"IR")) value = EXT_IR; else if(checkstring(argv[2], (unsigned char *)"PWM0A")) value = EXT_PWM0A; else if(checkstring(argv[2], (unsigned char *)"PWM1A")) value = EXT_PWM1A; else if(checkstring(argv[2], (unsigned char *)"PWM2A")) value = EXT_PWM2A; else if(checkstring(argv[2], (unsigned char *)"PWM3A")) value = EXT_PWM3A; else if(checkstring(argv[2], (unsigned char *)"PWM4A")) value = EXT_PWM4A; else if(checkstring(argv[2], (unsigned char *)"PWM5A")) value = EXT_PWM5A; else if(checkstring(argv[2], (unsigned char *)"PWM6A")) value = EXT_PWM6A; else if(checkstring(argv[2], (unsigned char *)"PWM7A")) value = EXT_PWM7A; #ifdef rp2350 else if(checkstring(argv[2], (unsigned char *)"FFIN")) value = EXT_FAST_TIMER; #endif #ifdef rp2350 else if(checkstring(argv[2], (unsigned char *)"PWM8A")) value = EXT_PWM8A; else if(checkstring(argv[2], (unsigned char *)"PWM9A")) value = EXT_PWM9A; else if(checkstring(argv[2], (unsigned char *)"PWM10A")) value = EXT_PWM10A; else if(checkstring(argv[2], (unsigned char *)"PWM711")) value = EXT_PWM11A; #endif else if(checkstring(argv[2], (unsigned char *)"PWM0B")) value = EXT_PWM0B; else if(checkstring(argv[2], (unsigned char *)"PWM1B")) value = EXT_PWM1B; else if(checkstring(argv[2], (unsigned char *)"PWM2B")) value = EXT_PWM2B; else if(checkstring(argv[2], (unsigned char *)"PWM3B")) value = EXT_PWM3B; else if(checkstring(argv[2], (unsigned char *)"PWM4B")) value = EXT_PWM4B; else if(checkstring(argv[2], (unsigned char *)"PWM5B")) value = EXT_PWM5B; else if(checkstring(argv[2], (unsigned char *)"PWM6B")) value = EXT_PWM6B; else if(checkstring(argv[2], (unsigned char *)"PWM7B")) value = EXT_PWM7B; #ifdef rp2350 else if(checkstring(argv[2], (unsigned char *)"PWM8B")) value = EXT_PWM8B; else if(checkstring(argv[2], (unsigned char *)"PWM9B")) value = EXT_PWM9B; else if(checkstring(argv[2], (unsigned char *)"PWM10B")) value = EXT_PWM10B; else if(checkstring(argv[2], (unsigned char *)"PWM11B")) value = EXT_PWM11B; #endif else if(checkstring(argv[2], (unsigned char *)"PIO0")) value = EXT_PIO0_OUT; else if(checkstring(argv[2], (unsigned char *)"PIO1")) value = EXT_PIO1_OUT; #ifdef rp2350 else if(checkstring(argv[2], (unsigned char *)"PIO2")) value = EXT_PIO2_OUT; #endif else if(checkstring(argv[2],(unsigned char *)"PWM")){ if(PinDef[pin].mode & PWM0A)value = EXT_PWM0A; else if(PinDef[pin].mode & PWM0B)value = EXT_PWM0B; else if(PinDef[pin].mode & PWM1A)value = EXT_PWM1A; else if(PinDef[pin].mode & PWM1B)value = EXT_PWM1B; else if(PinDef[pin].mode & PWM2A)value = EXT_PWM2A; else if(PinDef[pin].mode & PWM2B)value = EXT_PWM2B; else if(PinDef[pin].mode & PWM3A)value = EXT_PWM3A; else if(PinDef[pin].mode & PWM3B)value = EXT_PWM3B; else if(PinDef[pin].mode & PWM4A)value = EXT_PWM4A; else if(PinDef[pin].mode & PWM4B)value = EXT_PWM4B; else if(PinDef[pin].mode & PWM5A)value = EXT_PWM5A; else if(PinDef[pin].mode & PWM5B)value = EXT_PWM5B; else if(PinDef[pin].mode & PWM6A)value = EXT_PWM6A; else if(PinDef[pin].mode & PWM6B)value = EXT_PWM6B; else if(PinDef[pin].mode & PWM7A)value = EXT_PWM7A; else if(PinDef[pin].mode & PWM7B)value = EXT_PWM7B; #ifdef rp2350 else if(PinDef[pin].mode & PWM8A)value = EXT_PWM8A; else if(PinDef[pin].mode & PWM8B)value = EXT_PWM8B; else if(PinDef[pin].mode & PWM9A)value = EXT_PWM9A; else if(PinDef[pin].mode & PWM9B)value = EXT_PWM9B; else if(PinDef[pin].mode & PWM10A)value = EXT_PWM10A; else if(PinDef[pin].mode & PWM10B)value = EXT_PWM10B; else if(PinDef[pin].mode & PWM11A)value = EXT_PWM11A; else if(PinDef[pin].mode & PWM11B)value = EXT_PWM11B; #endif else error("Invalid configuration"); } else if(checkstring(argv[2],(unsigned char *)"INT")){ if(pin==Option.INT1pin)value = EXT_INT1; else if(pin==Option.INT2pin)value = EXT_INT2; else if(pin==Option.INT3pin)value = EXT_INT3; else if(pin==Option.INT4pin)value = EXT_INT4; else error("Invalid configuration"); } if(value!=-1)goto process; if(argc<5)error("Syntax"); if(checkstring(argv[4],(unsigned char *)"COM1")){ if(!(code=codecheck(argv[2])))argv[2]+=2; pin2 = getinteger(argv[2]); if(!code)pin2=codemap(pin2); if(PinDef[pin].mode & UART0TX)value = EXT_UART0TX; else if(PinDef[pin].mode & UART0RX)value = EXT_UART0RX; else error("Invalid configuration"); if(PinDef[pin2].mode & UART0TX)value2 = EXT_UART0TX; else if(PinDef[pin2].mode & UART0RX)value2 = EXT_UART0RX; else error("Invalid configuration"); if(value==value2)error("Invalid configuration"); } else if(checkstring(argv[4],(unsigned char *)"COM2")){ if(!(code=codecheck(argv[2])))argv[2]+=2; pin2 = getinteger(argv[2]); if(!code)pin2=codemap(pin2); if(PinDef[pin].mode & UART1TX)value = EXT_UART1TX; else if(PinDef[pin].mode & UART1RX)value = EXT_UART1RX; else error("Invalid configuration"); if(PinDef[pin2].mode & UART1TX)value2 = EXT_UART1TX; else if(PinDef[pin2].mode & UART1RX)value2 = EXT_UART1RX; else error("Invalid configuration"); if(value==value2)error("Invalid configuration"); } else if(checkstring(argv[4],(unsigned char *)"I2C")){ if(!(code=codecheck(argv[2])))argv[2]+=2; pin2 = getinteger(argv[2]); if(!code)pin2=codemap(pin2); if(PinDef[pin].mode & I2C0SCL)value = EXT_I2C0SCL; else if(PinDef[pin].mode & I2C0SDA)value = EXT_I2C0SDA; else error("Invalid configuration"); if(PinDef[pin2].mode & I2C0SCL)value2 = EXT_I2C0SCL; else if(PinDef[pin2].mode & I2C0SDA)value2 = EXT_I2C0SDA; else error("Invalid configuration"); if(value==value2)error("Invalid configuration"); } else if(checkstring(argv[4],(unsigned char *)"I2C2")){ if(!(code=codecheck(argv[2])))argv[2]+=2; pin2 = getinteger(argv[2]); if(!code)pin2=codemap(pin2); if(PinDef[pin].mode & I2C1SCL)value = EXT_I2C1SCL; else if(PinDef[pin].mode & I2C1SDA)value = EXT_I2C1SDA; else error("Invalid configuration"); if(PinDef[pin2].mode & I2C1SCL)value2 = EXT_I2C1SCL; else if(PinDef[pin2].mode & I2C1SDA)value2 = EXT_I2C1SDA; else error("Invalid configuration"); if(value==value2)error("Invalid configuration"); } if(value!=-1)goto process; if(argc<7)error("Syntax"); if(checkstring(argv[6],(unsigned char *)"SPI")){ if(!(code=codecheck(argv[2])))argv[2]+=2; pin2 = getinteger(argv[2]); if(!code)pin2=codemap(pin2); if(!(code=codecheck(argv[4])))argv[4]+=2; pin3 = getinteger(argv[4]); if(!code)pin3=codemap(pin3); if(PinDef[pin].mode & SPI0RX)value = EXT_SPI0RX; else if(PinDef[pin].mode & SPI0TX)value = EXT_SPI0TX; else if(PinDef[pin].mode & SPI0SCK)value = EXT_SPI0SCK; else error("Invalid configuration"); if(PinDef[pin2].mode & SPI0RX)value2 = EXT_SPI0RX; else if(PinDef[pin2].mode & SPI0TX)value2 = EXT_SPI0TX; else if(PinDef[pin2].mode & SPI0SCK)value2 = EXT_SPI0SCK; else error("Invalid configuration"); if(PinDef[pin3].mode & SPI0RX)value3 = EXT_SPI0RX; else if(PinDef[pin3].mode & SPI0TX)value3 = EXT_SPI0TX; else if(PinDef[pin3].mode & SPI0SCK)value3 = EXT_SPI0SCK; else error("Invalid configuration"); if(value==value2 || value==value3 || value2==value3)error("Invalid configuration"); } else if(checkstring(argv[6],(unsigned char *)"SPI2")){ if(!(code=codecheck(argv[2])))argv[2]+=2; pin2 = getinteger(argv[2]); if(!code)pin2=codemap(pin2); if(!(code=codecheck(argv[4])))argv[4]+=2; pin3 = getinteger(argv[4]); if(!code)pin3=codemap(pin3); if(PinDef[pin].mode & SPI1RX)value = EXT_SPI1RX; else if(PinDef[pin].mode & SPI1TX)value = EXT_SPI1TX; else if(PinDef[pin].mode & SPI1SCK)value = EXT_SPI1SCK; else error("Invalid configuration"); if(PinDef[pin2].mode & SPI1RX)value2 = EXT_SPI1RX; else if(PinDef[pin2].mode & SPI1TX)value2 = EXT_SPI1TX; else if(PinDef[pin2].mode & SPI1SCK)value2 = EXT_SPI1SCK; else error("Invalid configuration"); if(PinDef[pin3].mode & SPI1RX)value3 = EXT_SPI1RX; else if(PinDef[pin3].mode & SPI1TX)value3 = EXT_SPI1TX; else if(PinDef[pin3].mode & SPI1SCK)value3 = EXT_SPI1SCK; else error("Invalid configuration"); if(value==value2 || value==value3 || value2==value3)error("Invalid configuration"); } else error("Syntax"); // value = getint(argv[2], 1, 9); process: // check for any options switch(value) { case EXT_ANA_IN: case EXT_ADCRAW: if(argc == 5) { option = getint((argv[4]), 8, 12); if(option & 1)error("Invalid bit count"); } else option = 12; break; case EXT_DIG_IN: if(argc == 5) { if(checkstring(argv[4], (unsigned char *)"PULLUP")) option = CNPUSET; else if(checkstring(argv[4], (unsigned char *)"PULLDOWN")) { #ifdef rp2350 PinSetBit(pin,TRISCLR); PinSetBit(pin,LATCLR); PinSetBit(pin,TRISSET); #endif option = CNPDSET; } else error("Invalid configuration"); } else option = 0; break; case EXT_INT_HI: case EXT_INT_LO: case EXT_INT_BOTH: if(argc == 7) { if(checkstring(argv[6], (unsigned char *)"PULLUP")) option = CNPUSET; else if(checkstring(argv[6], (unsigned char *)"PULLDOWN")) { #ifdef rp2350 PinSetBit(pin,TRISCLR); PinSetBit(pin,LATCLR); PinSetBit(pin,TRISSET); #endif option = CNPDSET; } else error("Invalid configuration"); } else option = 0; break; case EXT_FREQ_IN: if(argc == 5) option = getint((argv[4]), 1, 100000); else option = 1000; break; case EXT_PER_IN: if(argc == 5) option = getint((argv[4]), 1, 10000); else option = 1; break; case EXT_CNT_IN: if(argc == 5) option = getint((argv[4]), 1, 10); else option = 1; break; #ifdef rp2350 case EXT_FAST_TIMER: if(pin!=FAST_TIMER_PIN)error("Use pin2/GP1 for fast counter"); if(BacklightSlice==0)error("Channel in use for backlight"); if(Option.AUDIO_SLICE==0)error("Channel in use for Audio"); if(CameraSlice==0)error("Channel in use for Camera"); if(argc == 5) option = getint((argv[4]), 1, 100000); else option = 1000; break; #endif case EXT_DIG_OUT: case EXT_HEARTBEAT: option=0; default: if(argc > 3 && !value2) error("Unexpected text"); } // this allows the user to set a software interrupt on the touch IRQ pin if the GUI environment is not enabled if(pin == Option.TOUCH_IRQ) #ifdef GUICONTROLS if(Option.MaxCtrls==0) #endif { if(value == EXT_INT_HI || value == EXT_INT_LO || value == EXT_INT_BOTH) ExtCurrentConfig[pin] = value; else if(value == EXT_NOT_CONFIG) { ExtCurrentConfig[pin] = EXT_BOOT_RESERVED; for(i = 0; i < NBRINTERRUPTS; i++) if(inttbl[i].pin == pin) inttbl[i].pin = 0; // disable the software interrupt on this pin } else error("Pin %/| is reserved on startup", pin,pin); } CheckPin(pin, CP_IGNORE_INUSE); ExtCfg(pin, value, option); if(value2) { CheckPin(pin2, CP_IGNORE_INUSE); ExtCfg(pin2, value2, option); } if(value3) { CheckPin(pin3, CP_IGNORE_INUSE); ExtCfg(pin3, value3, option); } if(value == EXT_INT_HI || value == EXT_INT_LO || value == EXT_INT_BOTH) { // we need to set up a software interrupt if(argc < 5) error("Argument count"); for(i = 0; i < NBRINTERRUPTS; i++) if(inttbl[i].pin == 0) break; if(i >= NBRINTERRUPTS) error("Too many interrupts"); inttbl[i].pin = pin; inttbl[i].intp = (char *)GetIntAddress(argv[4]); // get the interrupt routine's location inttbl[i].last = ExtInp(pin); // save the current pin value for the first test switch(value) { // and set trigger polarity case EXT_INT_HI: inttbl[i].lohi = T_LOHI; break; case EXT_INT_LO: inttbl[i].lohi = T_HILO; break; case EXT_INT_BOTH: inttbl[i].lohi = T_BOTH; break; } InterruptUsed = true; } } /* * @cond * The following section will be excluded from the documentation. */ bool __no_inline_not_in_flash_func(bb_get_bootsel_button)() { const uint CS_PIN_INDEX = 1; disable_interrupts_pico(); hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, GPIO_OVERRIDE_LOW << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); for (volatile int i = 0; i < 100; ++i); bool button_state = !(sio_hw->gpio_hi_in & (1u << CS_PIN_INDEX)); hw_write_masked(&ioqspi_hw->io[CS_PIN_INDEX].ctrl, GPIO_OVERRIDE_NORMAL << IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_LSB, IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); enable_interrupts_pico(); return button_state; } /* @endcond */ void fun_pin(void) { char code; int pin, i, j, b[ANA_AVERAGE]; MMFLOAT t; if(checkstring(ep, (unsigned char *)"TEMP")){ if(ADCDualBuffering || dmarunning)error("ADC in use"); adc_init(); adc_set_temp_sensor_enabled(true); #ifdef rp2350 adc_select_input((rp2350a ? 4 : 8)); #else adc_select_input(4); #endif last_adc=4; t=(MMFLOAT)adc_read()/4095.0*VCC; fret=(27.0-(t-0.706)/0.001721); targ=T_NBR; return; } if(checkstring(ep, (unsigned char *)"BOOTSEL")){ iret=bb_get_bootsel_button(); targ=T_INT; return; } if(!(code=codecheck(ep)))ep+=2; pin = getinteger(ep); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin"); switch(ExtCurrentConfig[pin]) { case EXT_DIG_IN: case EXT_CNT_IN: case EXT_INT_HI: case EXT_INT_LO: case EXT_INT_BOTH: case EXT_DIG_OUT: case EXT_PIO0_OUT: case EXT_PIO1_OUT: #ifdef rp2350 case EXT_PIO2_OUT: #endif iret = ExtInp(pin); targ = T_INT; return; #ifdef rp2350 case EXT_FAST_TIMER: fret = (MMFLOAT)INT5Value * (MMFLOAT)1000.0 / (MMFLOAT)INT5InitTimer; targ = T_NBR; return; #endif case EXT_PER_IN: // if period measurement get the count and average it over the number of cycles if(pin == Option.INT1pin) fret = (MMFLOAT)ExtInp(pin) / (MMFLOAT)INT1InitTimer; else if(pin == Option.INT2pin) fret = (MMFLOAT)ExtInp(pin) / (MMFLOAT)INT2InitTimer; else if(pin == Option.INT3pin) fret = (MMFLOAT)ExtInp(pin) / (MMFLOAT)INT3InitTimer; else if(pin == Option.INT4pin) fret = (MMFLOAT)ExtInp(pin) / (MMFLOAT)INT4InitTimer; targ = T_NBR; return; case EXT_FREQ_IN: // if frequency measurement get the count and scale the reading if(pin == Option.INT1pin) fret = (MMFLOAT)(ExtInp(pin)) * (MMFLOAT)1000.0 / (MMFLOAT)INT1InitTimer; else if(pin == Option.INT2pin) fret = (MMFLOAT)(ExtInp(pin)) * (MMFLOAT)1000.0 / (MMFLOAT)INT2InitTimer; else if(pin == Option.INT3pin) fret = (MMFLOAT)(ExtInp(pin)) * (MMFLOAT)1000.0 / (MMFLOAT)INT3InitTimer; else if(pin == Option.INT4pin) fret = (MMFLOAT)(ExtInp(pin)) * (MMFLOAT)1000.0 / (MMFLOAT)INT4InitTimer; targ = T_NBR; return; case EXT_ADCRAW: if(ADCDualBuffering || dmarunning)error("ADC in use"); iret=ExtInp(pin); targ=T_INT; return; case EXT_ANA_IN: if(ADCDualBuffering || dmarunning)error("ADC in use"); for(i = 0; i < ANA_AVERAGE; i++) { b[i] = ExtInp(pin); // get the value for(j = i; j > 0; j--) { // and sort into position if(b[j - 1] < b[j]) { t = b[j - 1]; b[j - 1] = b[j]; b[j] = t; } else break; } } // we then discard the top ANA_DISCARD samples and the bottom ANA_DISCARD samples and add up the remainder for(j = 0, i = ANA_DISCARD; i < ANA_AVERAGE - ANA_DISCARD; i++) j += b[i]; // the total is averaged and scaled fret = FMul((MMFLOAT)j , VCC) / (MMFLOAT)(4095 * (ANA_AVERAGE - ANA_DISCARD*2)); targ = T_NBR; return; default: error("Pin %/| is not an input",pin,pin); } } /* * @cond * The following section will be excluded from the documentation. */ int CheckPin(int pin, int action) { #ifdef rp2350 if(rp2350a && pin>44)error("Pin | is invalid", pin); #endif if(pin < 1 || pin > NBRPINS || (PinDef[pin].mode & UNUSED)) { if(!(action & CP_NOABORT)) error("Pin %/| is invalid", pin,pin); return false; } if(!(action & CP_IGNORE_INUSE) && ExtCurrentConfig[pin] >= EXT_DS18B20_RESERVED && ExtCurrentConfig[pin] < EXT_COM_RESERVED) { if(!(action & CP_NOABORT)) error("Pin %/| is in use", pin,pin); return false; } if(!(action & CP_IGNORE_BOOTRES) && ExtCurrentConfig[pin] >= EXT_BOOT_RESERVED) { if(!(action & CP_NOABORT)) { error("Pin %/| is reserved on startup", pin,pin); uSec(1000000); } return false; } if(!(action & CP_IGNORE_RESERVED) && ExtCurrentConfig[pin] >= EXT_DS18B20_RESERVED) { if(!(action & CP_NOABORT)) error("Pin %/| is in use", pin,pin); return false; } return true; } /* @endcond */ // this is invoked as a command (ie, port(3, 8) = Value) // first get the arguments then step over the closing bracket. Search through the rest of the command line looking // for the equals sign and step over it, evaluate the rest of the command and set the pins accordingly void cmd_port(void) { int pin, nbr, value, code, pincode; int i; getargs(&cmdline, NBRPINS * 4, (unsigned char *)","); if((argc & 0b11) != 0b11) error("Invalid syntax"); if(!strchr((char *)cmdline,')'))error ("Syntax"); // step over the equals sign and get the value for the assignment while(*cmdline && tokenfunction(*cmdline) != op_equal) cmdline++; if(!*cmdline) error("Invalid syntax"); ++cmdline; if(!*cmdline) error("Invalid syntax"); value = getinteger(cmdline); uint64_t mask=0,setmask=0, readmask; for(i = 0; i < argc; i += 4) { code=0; if(!(code=codecheck(argv[i])))argv[i]+=2; pincode = getinteger(argv[i]); nbr = getinteger(argv[i + 2]); if(nbr < 0 || (pincode == 0 && code!=0) || (pincode<0)) error("Invalid argument"); while(nbr) { if(!code)pin=codemap(pincode); else pin=pincode; if(IsInvalidPin(pin) || !(ExtCurrentConfig[pin] == EXT_DIG_OUT )) error("Invalid output pin"); mask |=(1<>= 1; nbr--; pincode++; } } readmask=gpio_get_out_level_all64(); readmask &=mask; gpio_xor_mask(setmask ^ readmask); } void fun_distance(void) { int trig, echo,techo; getargs(&ep, 3, (unsigned char *)","); if((argc &1) != 1) error("Invalid syntax"); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; trig = getinteger(argv[0]); if(!code)trig=codemap(trig); if(argc == 3){ if(!(code=codecheck(argv[2])))argv[2]+=2; echo = getinteger(argv[2]); if(!code)echo=codemap(echo); } else echo = trig; // they are the same if it is a 3-pin device if(IsInvalidPin(trig) || IsInvalidPin(echo)) error("Invalid pin |",echo); if(ExtCurrentConfig[trig] >= EXT_COM_RESERVED || ExtCurrentConfig[echo] >= EXT_COM_RESERVED) error("Pin %/| is in use",trig,trig); ExtCfg(echo, EXT_DIG_IN, CNPUSET); // setup the echo input PinSetBit(trig, LATCLR); // trigger output must start low ExtCfg(trig, EXT_DIG_OUT, 0); // setup the trigger output PinSetBit(trig, LATSET); uSec(20); PinSetBit(trig, LATCLR); // pulse the trigger uSec(50); ExtCfg(echo, EXT_DIG_IN, CNPUSET); // this is in case the sensor is a 3-pin type uSec(50); PauseTimer = 0; // this is our timeout while(PinRead(echo)) if(PauseTimer > 50) { fret = -2; return; } // wait for the acknowledgement pulse start while(!PinRead(echo)) if(PauseTimer > 100) { fret = -2; return;}// then its end PauseTimer = 0; writeusclock(0); while(PinRead(echo)) { // now wait for the echo pulse if(PauseTimer > 38) { // timeout is 38mS fret = -1; return; } } techo=readusclock(); // we have the echo, convert the time to centimeters fret = FDiv((MMFLOAT)techo,58.0); //200 ticks per us, 58 us per cm targ = T_NBR; } // this is invoked as a function (ie, x = port(10,8) ) void fun_port(void) { int pin, nbr, i, value = 0, code, pincode; getargs(&ep, NBRPINS * 4, (unsigned char *)","); if((argc & 0b11) != 0b11) error("Invalid syntax"); uint64_t pinstate=gpio_get_all64(); uint64_t outpinstate=gpio_get_out_level_all64(); for(i = argc - 3; i >= 0; i -= 4) { code=0; if(!(code=codecheck(argv[i])))argv[i]+=2; pincode = getinteger(argv[i]); nbr = getinteger(argv[i + 2]); if(nbr < 0 || (pincode == 0 && code!=0) || (pincode<0)) error("Invalid argument"); pincode += nbr - 1; // we start by reading the most significant bit while(nbr) { if(!code)pin=codemap(pincode); else pin=pincode; if(IsInvalidPin(pin) || !(ExtCurrentConfig[pin] == EXT_DIG_IN || ExtCurrentConfig[pin] == EXT_DIG_OUT || ExtCurrentConfig[pin] == EXT_INT_HI || ExtCurrentConfig[pin] == EXT_INT_LO || ExtCurrentConfig[pin] == EXT_INT_BOTH)) error("Invalid input pin"); value <<= 1; if(ExtCurrentConfig[pin] == EXT_DIG_OUT)value |= (outpinstate & (1<= NBR_PULSE_SLOTS) error("Too many concurrent PULSE commands"); PinSetBit(pin, LATINV); // starting edge of the pulse if(x == 1) uSec(500); // prevent too narrow a pulse if there is just one count PulsePin[i] = pin; // save the details PulseCnt[i] = x; PulseActive = true; } void fun_pulsin(void) { //allowas timeouts up to 10 seconds int pin, polarity; unsigned int t1, t2; getargs(&ep, 7, (unsigned char *)","); if((argc &1) != 1 || argc < 3) error("Invalid syntax"); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin"); if(ExtCurrentConfig[pin] != EXT_DIG_IN) error("Pin %/| is not an input",pin,pin); polarity = getinteger(argv[2]); t1 = t2 = 100000; // default timeout is 100mS if(argc >= 5) t1 = t2 = getint(argv[4], 5, 10000000); if(argc == 7) t2 = getint(argv[6], 5, 10000000); iret = -1; // in anticipation of a timeout writeusclock(0); if(polarity) { while(PinRead(pin)) if(readusclock() > t1) return; while(!PinRead(pin)) if(readusclock() > t1) return; writeusclock(0); while(PinRead(pin)) if(readusclock() > t2) return; } else { while(!PinRead(pin)) if(readusclock() > t1) return; while(PinRead(pin)) if(readusclock() > t1) return; writeusclock(0); while(!PinRead(pin)) if(readusclock() > t2) return; } t1 = readusclock(); iret = t1; targ = T_INT; } /**************************************************************************************************************************** IR routines *****************************************************************************************************************************/ void cmd_ir(void) { unsigned char *p; int i, pin, dev, cmd; if(checkstring(cmdline, (unsigned char *)"CLOSE")) { if(IrState == IR_CLOSED) error("Not Open"); if(CallBackEnabled==1) gpio_set_irq_enabled_with_callback(PinDef[IRpin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else gpio_set_irq_enabled(PinDef[IRpin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); IrInterrupt = NULL; CallBackEnabled &= (~1); ExtCfg(IRpin, EXT_NOT_CONFIG, 0); } else if((p = checkstring(cmdline, (unsigned char *)"SEND"))) { getargs(&p, 5, (unsigned char *)","); char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin"); dev = getint(argv[2], 0, 0b11111); cmd = getint(argv[4], 0, 0b1111111); if(ExtCurrentConfig[pin] >= EXT_COM_RESERVED) error("Pin %/| is in use",pin,pin); ExtCfg(pin, EXT_DIG_OUT, 0); cmd = (dev << 7) | cmd; IRSendSignal(pin, 186); for(i = 0; i < 12; i++) { uSec(600); if(cmd & 1) IRSendSignal(pin, 92); else IRSendSignal(pin, 46); cmd >>= 1; } } else { getargs(&cmdline, 5, (unsigned char *)","); if(IRpin==99)error("Pin not configured for IR"); if(IrState != IR_CLOSED) error("Already open"); if(argc%2 == 0 || argc == 0) error("Invalid syntax"); IrVarType = 0; IrDev = findvar(argv[0], V_FIND); if(g_vartbl[g_VarIndex].type & T_CONST) error("Cannot change a constant"); if(g_vartbl[g_VarIndex].type & T_STR) error("Invalid variable"); if(g_vartbl[g_VarIndex].type & T_NBR) IrVarType |= 0b01; IrCmd = findvar(argv[2], V_FIND); if(g_vartbl[g_VarIndex].type & T_CONST) error("Cannot change a constant"); if(g_vartbl[g_VarIndex].type & T_STR) error("Invalid variable"); if(g_vartbl[g_VarIndex].type & T_NBR) IrVarType |= 0b10; InterruptUsed = true; IrInterrupt = GetIntAddress(argv[4]); // get the interrupt location IrInit(); } } /* * @cond * The following section will be excluded from the documentation. */ void IrInit(void) { writeusclock(0); if(ExtCurrentConfig[IRpin] >= EXT_COM_RESERVED) error("Pin %/% is in use",IRpin,IRpin); ExtCfg(IRpin, EXT_IR, 0); ExtCfg(IRpin, EXT_COM_RESERVED, 0); if(!CallBackEnabled){ gpio_set_irq_enabled_with_callback(PinDef[IRpin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true, &gpio_callback); CallBackEnabled=1; } else { gpio_set_irq_enabled(PinDef[IRpin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, true); CallBackEnabled|=1; } IrReset(); } void IrReset(void) { IrState = IR_WAIT_START; IrCount = 0; writeIRclock(0); } // this modulates (at about 38KHz) the IR beam for transmit // half_cycles is the number of half cycles to send. ie, 186 is about 2.4mSec void IRSendSignal(int pin, int half_cycles) { while(half_cycles--) { PinSetBit(pin, LATINV); uSec(13); } } void MIPS16 set_PWM(int slice, MMFLOAT duty1, MMFLOAT duty2, int high1, int high2, int delaystart){ if(slice==0 && PWM0Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==0 && PWM0Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); #ifdef rp2350 if(slice==0 && fast_timer_active)error("Channel 0 in use for fast timer"); #endif if(slice==1 && PWM1Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==1 && PWM1Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==2 && PWM2Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==2 && PWM2Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==3 && PWM3Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==3 && PWM3Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==4 && PWM4Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==4 && PWM4Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==5 && PWM5Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==5 && PWM5Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==6 && PWM6Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==6 && PWM6Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==7 && PWM7Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==7 && PWM7Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); #ifdef rp2350 if(slice==8 && PWM8Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==8 && PWM8Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==9 && PWM9Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==9 && PWM9Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==10 && PWM10Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==10 && PWM10Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); if(slice==11 && PWM11Apin==99 && duty1>=0.0)error("Pin not set for PWM"); if(slice==11 && PWM11Bpin==99 && duty2>=0.0)error("Pin not set for PWM"); #endif if(slice==0 && PWM0Apin!=99 && duty1>=0.0){ ExtCfg(PWM0Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==0 && PWM0Bpin!=99 && duty2>=0.0){ ExtCfg(PWM0Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==1 && PWM1Apin!=99 && duty1>=0.0){ ExtCfg(PWM1Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==1 && PWM1Bpin!=99 && duty2>=0.0){ ExtCfg(PWM1Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==2 && PWM2Apin!=99 && duty1>=0.0){ ExtCfg(PWM2Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==2 && PWM2Bpin!=99 && duty2>=0.0){ ExtCfg(PWM2Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==3 && PWM3Apin!=99 && duty1>=0.0){ ExtCfg(PWM3Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==3 && PWM3Bpin!=99 && duty2>=0.0){ ExtCfg(PWM3Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==4 && PWM4Apin!=99 && duty1>=0.0){ ExtCfg(PWM4Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==4 && PWM4Bpin!=99 && duty2>=0.0){ ExtCfg(PWM4Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==5 && PWM5Apin!=99 && duty1>=0.0){ ExtCfg(PWM5Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==5 && PWM5Bpin!=99 && duty2>=0.0){ ExtCfg(PWM5Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==6 && PWM6Apin!=99 && duty1>=0.0){ ExtCfg(PWM6Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==6 && PWM6Bpin!=99 && duty2>=0.0){ ExtCfg(PWM6Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==7 && PWM7Apin!=99 && duty1>=0.0){ ExtCfg(PWM7Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==7 && PWM7Bpin!=99 && duty2>=0.0){ ExtCfg(PWM7Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } #ifdef rp2350 if(slice==8 && PWM8Apin!=99 && duty1>=0.0){ ExtCfg(PWM8Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==8 && PWM8Bpin!=99 && duty2>=0.0){ ExtCfg(PWM8Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==9 && PWM9Apin!=99 && duty1>=0.0){ ExtCfg(PWM9Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==9 && PWM9Bpin!=99 && duty2>=0.0){ ExtCfg(PWM9Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==10 && PWM10Apin!=99 && duty1>=0.0){ ExtCfg(PWM10Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==10 && PWM10Bpin!=99 && duty2>=0.0){ ExtCfg(PWM10Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } if(slice==11 && PWM11Apin!=99 && duty1>=0.0){ ExtCfg(PWM11Apin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_A, high1); } if(slice==11 && PWM11Bpin!=99 && duty2>=0.0){ ExtCfg(PWM11Bpin,EXT_COM_RESERVED,0); pwm_set_chan_level(slice, PWM_CHAN_B, high2); } #endif if(slice==0 && slice0==0){ if(!delaystart)pwm_set_enabled(slice, true); slice0=1; } if(slice==1 && slice1==0){ if(!delaystart)pwm_set_enabled(slice, true); slice1=1; } if(slice==2 && slice2==0){ if(!delaystart)pwm_set_enabled(slice, true); slice2=1; } if(slice==3 && slice3==0){ if(!delaystart)pwm_set_enabled(slice, true); slice3=1; } if(slice==4 && slice4==0){ if(!delaystart)pwm_set_enabled(slice, true); slice4=1; } if(slice==5 && slice5==0){ if(!delaystart)pwm_set_enabled(slice, true); slice5=1; } if(slice==6 && slice6==0){ if(!delaystart)pwm_set_enabled(slice, true); slice6=1; } if(slice==7 && slice7==0){ if(!delaystart)pwm_set_enabled(slice, true); slice7=1; } #ifdef rp2350 if(slice==8 && slice8==0){ if(!delaystart)pwm_set_enabled(slice, true); slice8=1; } if(slice==9 && slice9==0){ if(!delaystart)pwm_set_enabled(slice, true); slice9=1; } if(slice==10 && slice10==0){ if(!delaystart)pwm_set_enabled(slice, true); slice10=1; } if(slice==11 && slice11==0){ if(!delaystart)pwm_set_enabled(slice, true); slice11=1; } #endif } void PWMoff(int slice){ if(slice==0 && PWM0Apin!=99 && ExtCurrentConfig[PWM0Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM0Apin,EXT_NOT_CONFIG,0); } if(slice==0 && PWM0Bpin!=99 && ExtCurrentConfig[PWM0Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM0Bpin,EXT_NOT_CONFIG,0); } if(slice==1 && PWM1Apin!=99 && ExtCurrentConfig[PWM1Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM1Apin,EXT_NOT_CONFIG,0); } if(slice==1 && PWM1Bpin!=99 && ExtCurrentConfig[PWM1Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM1Bpin,EXT_NOT_CONFIG,0); } if(slice==2 && PWM2Apin!=99 && ExtCurrentConfig[PWM2Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM2Apin,EXT_NOT_CONFIG,0); } if(slice==2 && PWM2Bpin!=99 && ExtCurrentConfig[PWM2Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM2Bpin,EXT_NOT_CONFIG,0); } if(slice==3 && PWM3Apin!=99 && ExtCurrentConfig[PWM3Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM3Apin,EXT_NOT_CONFIG,0); } if(slice==3 && PWM3Bpin!=99 && ExtCurrentConfig[PWM3Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM3Bpin,EXT_NOT_CONFIG,0); } if(slice==4 && PWM4Apin!=99 && ExtCurrentConfig[PWM4Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM4Apin,EXT_NOT_CONFIG,0); } if(slice==4 && PWM4Bpin!=99 && ExtCurrentConfig[PWM4Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM4Bpin,EXT_NOT_CONFIG,0); } if(slice==5 && PWM5Apin!=99 && ExtCurrentConfig[PWM5Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM5Apin,EXT_NOT_CONFIG,0); } if(slice==5 && PWM5Bpin!=99 && ExtCurrentConfig[PWM5Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM5Bpin,EXT_NOT_CONFIG,0); } if(slice==6 && PWM6Apin!=99 && ExtCurrentConfig[PWM6Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM6Apin,EXT_NOT_CONFIG,0); } if(slice==6 && PWM6Bpin!=99 && ExtCurrentConfig[PWM6Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM6Bpin,EXT_NOT_CONFIG,0); } if(slice==7 && PWM7Apin!=99 && ExtCurrentConfig[PWM7Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM7Apin,EXT_NOT_CONFIG,0); } if(slice==7 && PWM7Bpin!=99 && ExtCurrentConfig[PWM7Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM7Bpin,EXT_NOT_CONFIG,0); } #ifdef rp2350 if(slice==8 && PWM8Apin!=99 && ExtCurrentConfig[PWM8Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM8Apin,EXT_NOT_CONFIG,0); } if(slice==8 && PWM8Bpin!=99 && ExtCurrentConfig[PWM8Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM8Bpin,EXT_NOT_CONFIG,0); } if(slice==9 && PWM9Apin!=99 && ExtCurrentConfig[PWM9Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM9Apin,EXT_NOT_CONFIG,0); } if(slice==9 && PWM9Bpin!=99 && ExtCurrentConfig[PWM9Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM9Bpin,EXT_NOT_CONFIG,0); } if(slice==10 && PWM10Apin!=99 && ExtCurrentConfig[PWM10Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM10Apin,EXT_NOT_CONFIG,0); } if(slice==10 && PWM10Bpin!=99 && ExtCurrentConfig[PWM10Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM10Bpin,EXT_NOT_CONFIG,0); } if(slice==11 && PWM11Apin!=99 && ExtCurrentConfig[PWM11Apin] < EXT_BOOT_RESERVED){ ExtCfg(PWM11Apin,EXT_NOT_CONFIG,0); } if(slice==11 && PWM11Bpin!=99 && ExtCurrentConfig[PWM11Bpin] < EXT_BOOT_RESERVED){ ExtCfg(PWM11Bpin,EXT_NOT_CONFIG,0); } #endif pwm_set_enabled(slice, false); } #ifndef PICOMITEVGA #ifndef PICOCALC void setBacklight(int level, int setfrequency){ if(((Option.DISPLAY_TYPE>I2C_PANEL && Option.DISPLAY_TYPE=SSDPANEL && Option.DISPLAY_TYPE65535){ wrap>>=1; if(level>=0.0)high>>=1; div<<=1; } wrap--; if(div!=1)pwm_set_clkdiv(BacklightSlice,(float)div); pwm_set_wrap(BacklightSlice, wrap); pwm_set_chan_level(BacklightSlice, BacklightChannel, high); } else if(Option.DISPLAY_TYPE<=I2C_PANEL){ level*=255; level/=100; I2C_Send_Command(0x81);//SETCONTRAST I2C_Send_Command((uint8_t)level); } else if(Option.DISPLAY_TYPE>=SSDPANEL && Option.DISPLAY_TYPEI2C_PANEL && Option.DISPLAY_TYPE=SSDPANEL && Option.DISPLAY_TYPE=SSDPANEL && Option.DISPLAY_TYPE=3))error("Syntax"); int CPU_Speed=Option.CPU_Speed; #ifdef rp2350 int slice=getint(argv[0],0,rp2350a ? 7:11); if(slice==0 && ExtCurrentConfig[FAST_TIMER_PIN]==EXT_FAST_TIMER)error("Channel in use for fast frequency"); #else int slice=getint(argv[0],0,7); #endif if(slice==BacklightSlice)error("Channel in use for backlight"); if(slice==Option.AUDIO_SLICE)error("Channel in use for Audio"); if(slice==CameraSlice)error("Channel in use for Camera"); if((tp=checkstring(argv[2],(unsigned char *)"OFF"))){ PWMoff(slice); if(slice==0)slice0=0; if(slice==1)slice1=0; if(slice==2)slice2=0; if(slice==3)slice3=0; if(slice==4)slice4=0; if(slice==5)slice5=0; if(slice==6)slice6=0; if(slice==7)slice7=0; #ifdef rp2350 if(slice==8)slice8=0; if(slice==9)slice9=0; if(slice==10)slice10=0; if(slice==11)slice11=0; #endif return; } MMFLOAT frequency=50.0; if(*argv[2]){ duty1=getnumber(argv[2]); if(duty1>120.0 || duty1<-20.0)error("Syntax"); duty1=5.0+duty1*0.05; } if(argc>=5 && *argv[4]){ duty2=getnumber(argv[4]); if(duty2>120.0 || duty2<-20.0)error("Syntax"); duty2=5.0+duty2*0.05; } int wrap=(CPU_Speed*1000)/frequency; if(duty1>=0.0)high1=(int)((MMFLOAT)CPU_Speed/frequency*duty1*10.0); if(duty2>=0.0)high2=(int)((MMFLOAT)CPU_Speed/frequency*duty2*10.0); while(wrap>65535){ wrap>>=1; if(duty1>=0.0)high1>>=1; if(duty2>=0.0)high2>>=1; div<<=1; } if(div>256)error("Invalid frequency"); wrap--; if(high1)high1--; if(high2)high2--; pwm_set_clkdiv(slice,(float)div); pwm_set_wrap(slice, wrap); pwm_set_output_polarity(slice,false,false); pwm_set_phase_correct(slice,false); set_PWM(slice,duty1,duty2,high1,high2, 0); } void MIPS16 cmd_pwm(void){ unsigned char *tp; if((tp=checkstring(cmdline, (unsigned char *)"SYNC"))) { MMFLOAT count0=-1.0,count1=-1.0,count2=-1.0,count3=-1.0,count4=-1.0,count5=-1.0,count6=-1.0,count7=-1.0; #ifdef rp2350 MMFLOAT count8=-1.0,count9=-1.0,count10=-1.0,count11=-1.0; getargs(&tp,23,(unsigned char *)","); #else getargs(&tp,15,(unsigned char *)","); #endif if(argc>=1){count0=getnumber(argv[0]); if((count0<0.0 || count0>100.0) && count0!=-1.0)error("Syntax");} if(argc>=3 && *argv[2]){count1=getnumber(argv[2]); if((count1<0.0 || count1>100.0) && count1!=-1.0)error("Syntax");} if(argc>=5 && *argv[4]){count2=getnumber(argv[4]); if((count2<0.0 || count2>100.0) && count2!=-1.0)error("Syntax");} if(argc>=7 && *argv[6]){count3=getnumber(argv[6]); if((count3<0.0 || count3>100.0) && count3!=-1.0)error("Syntax");} if(argc>=9 && *argv[8]){count4=getnumber(argv[8]); if((count4<0.0 || count4>100.0) && count4!=-1.0)error("Syntax");} if(argc>=11 && *argv[10]){count5=getnumber(argv[10]); if((count5<0.0 || count5>100.0) && count5!=-1.0)error("Syntax");} if(argc>=13 && *argv[12]){count6=getnumber(argv[12]); if((count6<0.0 || count6>100.0) && count6!=-1.0)error("Syntax");} #ifdef rp2350 if(argc>=15 && *argv[14]){count7=getnumber(argv[14]); if((count7<0.0 || count7>100.0) && count7!=-1.0)error("Syntax");} if(argc>=17 && *argv[16]){count8=getnumber(argv[16]); if((count8<0.0 || count8>100.0) && count8!=-1.0)error("Syntax");} if(argc>=19 && *argv[18]){count9=getnumber(argv[18]); if((count9<0.0 || count9>100.0) && count9!=-1.0)error("Syntax");} if(argc>=21 && *argv[20]){count10=getnumber(argv[20]); if((count10<0.0 || count10>100.0) && count10!=-1.0)error("Syntax");} if(argc==23 && *argv[22]){count11=getnumber(argv[22]); if((count11<0.0 || count11>100.0) && count11!=-1.0)error("Syntax");} #else if(argc==15 && *argv[14]){count7=getnumber(argv[14]); if((count7<0.0 || count7>100.0) && count7!=-1.0)error("Syntax");} #endif int enabled=0; if(slice0 || Option.AUDIO_SLICE ==0 || BacklightSlice==0 || CameraSlice==0){ enabled |=1; if(!(Option.AUDIO_SLICE ==0 || BacklightSlice==0 || CameraSlice==0 || count0<0.0)){ pwm_set_enabled(0,false); count0=(MMFLOAT)pwm_hw->slice[0].top * (100.0-count0) / 100.0; pwm_set_counter(0,(int)count0); } } if(slice1 || Option.AUDIO_SLICE ==1 || BacklightSlice==1 || CameraSlice==1){ enabled |=2; if(!(Option.AUDIO_SLICE ==1 || BacklightSlice==1 || CameraSlice==1 || count1<0.0)){ pwm_set_enabled(1,false); count1=(MMFLOAT)pwm_hw->slice[1].top * (100.0-count1) / 100.0; pwm_set_counter(1,count1); } } if(slice2 || Option.AUDIO_SLICE ==2 || BacklightSlice==2 || CameraSlice==2){ enabled |=4; if(!(Option.AUDIO_SLICE ==2 || BacklightSlice==2 || CameraSlice==2 || count2<0.0)){ pwm_set_enabled(2,false); count2=(MMFLOAT)pwm_hw->slice[2].top * (100.0-count2) / 100.0; pwm_set_counter(2,count2); } } if(slice3 || Option.AUDIO_SLICE ==3 || BacklightSlice==3 || CameraSlice==3){ enabled |=8; if(!(Option.AUDIO_SLICE ==3 || BacklightSlice==3 || CameraSlice==3 || count3<0.0)){ pwm_set_enabled(3,false); count3=(MMFLOAT)pwm_hw->slice[3].top * (100.0-count3) / 100.0; pwm_set_counter(3,count3); } } if(slice4 || Option.AUDIO_SLICE ==4 || BacklightSlice==4 || CameraSlice==4){ enabled |=16; if(!(Option.AUDIO_SLICE ==4 || BacklightSlice==4 || CameraSlice==4 || count4<0.0)){ pwm_set_enabled(4,false); count4=(MMFLOAT)pwm_hw->slice[4].top * (100.0-count4) / 100.0; pwm_set_counter(4,count4); } } if(slice5 || Option.AUDIO_SLICE ==5 || BacklightSlice==5 || CameraSlice==5){ enabled |=32; if(!(Option.AUDIO_SLICE ==5 || BacklightSlice==5 || CameraSlice==5 || count5<0.0)){ pwm_set_enabled(5,false); count5=(MMFLOAT)pwm_hw->slice[5].top * (100.0-count5) / 100.0; pwm_set_counter(5,count5); } } if(slice6 || Option.AUDIO_SLICE ==6 || BacklightSlice==6 || CameraSlice==6){ enabled |=64; if(!(Option.AUDIO_SLICE ==6 || BacklightSlice==6 || CameraSlice==6 || count6<0.0)){ pwm_set_enabled(6,false); count6=(MMFLOAT)pwm_hw->slice[6].top * (100.0-count6) / 100.0; pwm_set_counter(6,count6); } } if(slice7 || Option.AUDIO_SLICE ==7 || BacklightSlice==7 || CameraSlice==7){ enabled |=128; if(!(Option.AUDIO_SLICE ==7 || BacklightSlice==7 || CameraSlice==7 || count7<0.0)){ pwm_set_enabled(7,false); count7=(MMFLOAT)pwm_hw->slice[7].top * (100.0-count7) / 100.0; pwm_set_counter(7,count7); } } #ifdef rp2350 if(slice8 || Option.AUDIO_SLICE ==8 || BacklightSlice==8 || CameraSlice==8){ enabled |=256; if(!(Option.AUDIO_SLICE ==8 || BacklightSlice==8 || CameraSlice==8 || count8<0.0)){ pwm_set_enabled(8,false); count8=(MMFLOAT)pwm_hw->slice[8].top * (100.0-count8) / 100.0; pwm_set_counter(8,count8); } } if(slice9 || Option.AUDIO_SLICE ==9 || BacklightSlice==9 || CameraSlice==9){ enabled |=512; if(!(Option.AUDIO_SLICE ==9 || BacklightSlice==9 || CameraSlice==9 || count9<0.0)){ pwm_set_enabled(9,false); count9=(MMFLOAT)pwm_hw->slice[9].top * (100.0-count9) / 100.0; pwm_set_counter(9,count9); } } if(slice10 || Option.AUDIO_SLICE ==10 || BacklightSlice==10 || CameraSlice==10){ enabled |=1024; if(!(Option.AUDIO_SLICE ==10 || BacklightSlice==10 || CameraSlice==10 || count10<0.0)){ pwm_set_enabled(10,false); count10=(MMFLOAT)pwm_hw->slice[10].top * (100.0-count10) / 100.0; pwm_set_counter(10,count10); } } if(slice11 || Option.AUDIO_SLICE ==11 || BacklightSlice==11 || CameraSlice==11){ enabled |=2048; if(!(Option.AUDIO_SLICE ==11 || BacklightSlice==11 || CameraSlice==11 || count11<0.0)){ pwm_set_enabled(11,false); count11=(MMFLOAT)pwm_hw->slice[11].top * (100.0-count11) / 100.0; pwm_set_counter(11,count11); } } #endif pwm_hw->en=enabled; return; } int div=1, high1=0, high2=0; int phase1=0,phase2=0; MMFLOAT duty1=-1.0, duty2=-1.0; getargs(&cmdline,11,(unsigned char *)","); if(!(argc>=3))error("Syntax"); int CPU_Speed=Option.CPU_Speed; #ifdef rp2350 int slice=getint(argv[0],0,rp2350a ? 7:11); if(slice==0 && ExtCurrentConfig[FAST_TIMER_PIN]==EXT_FAST_TIMER)error("Channel in use for fast frequency"); #else int slice=getint(argv[0],0,7); #endif if(slice==BacklightSlice)error("Channel in use for backlight"); if(slice==Option.AUDIO_SLICE)error("Channel in use for Audio"); if(slice==CameraSlice)error("Channel in use for Camera"); if((tp=checkstring(argv[2],(unsigned char *)"OFF"))){ PWMoff(slice); if(slice==0)slice0=0; if(slice==1)slice1=0; if(slice==2)slice2=0; if(slice==3)slice3=0; if(slice==4)slice4=0; if(slice==5)slice5=0; if(slice==6)slice6=0; if(slice==7)slice7=0; #ifdef rp2350 if(slice==8)slice8=0; if(slice==9)slice9=0; if(slice==10)slice10=0; if(slice==11)slice11=0; #endif return; } if(!(argc>=5))error("Syntax"); int delaystart=0; int phase=1; if(argc>=9 && *argv[8])phase+=getint(argv[8],0,1); if(argc==11)delaystart=getint(argv[10],0,1); MMFLOAT frequency=getnumber(argv[2])*phase; if(frequency>(MMFLOAT)(CPU_Speed>>2)*1000.0)error("Invalid frequency"); if(*argv[4]){ duty1=getnumber(argv[4]); if(duty1>100.0 || duty1<-100.0)error("Syntax"); if(duty1<0){ duty1=-duty1; phase1=1; } } if(argc>=7 && *argv[6]){ duty2=getnumber(argv[6]); if(duty2>100.0 || duty2<-100.0)error("Syntax"); if(duty2<0){ duty2=-duty2; phase2=1; } } int wrap=(CPU_Speed*1000)/frequency; if(duty1>=0.0)high1=(int)((MMFLOAT)CPU_Speed/frequency*duty1*10.0); if(duty2>=0.0)high2=(int)((MMFLOAT)CPU_Speed/frequency*duty2*10.0); while(wrap>65535){ wrap>>=1; if(duty1>=0.0)high1>>=1; if(duty2>=0.0)high2>>=1; div<<=1; } if(div>256)error("Invalid frequency"); wrap--; if(high1)high1--; if(high2)high2--; pwm_set_clkdiv(slice,(float)div); pwm_set_wrap(slice, wrap); pwm_set_output_polarity(slice,phase1,phase2); pwm_set_phase_correct(slice,(phase==2? true : false)); set_PWM(slice,duty1,duty2,high1,high2, delaystart); } /**************************************************************************************************************************** The KEYPAD command *****************************************************************************************************************************/ /* * @cond * The following section will be excluded from the documentation. */ static char keypad_pins[8]; MMFLOAT *KeypadVar; unsigned char *KeypadInterrupt = NULL; void KeypadClose(void); /* @endcond */ void cmd_keypad(void) { int i, j, code; if(checkstring(cmdline, (unsigned char *)"CLOSE")) KeypadClose(); else { getargs(&cmdline, 19, (unsigned char *)","); if(argc%2 == 0 || argc < 17) error("Invalid syntax"); if(KeypadInterrupt != NULL) error("Already open"); KeypadVar = findvar(argv[0], V_FIND); if(g_vartbl[g_VarIndex].type & T_CONST) error("Cannot change a constant"); if(!(g_vartbl[g_VarIndex].type & T_NBR)) error("Floating point variable required"); InterruptUsed = true; KeypadInterrupt = GetIntAddress(argv[2]); // get the interrupt location for(i = 0; i < 8; i++) { if(i == 7 && argc < 19) { keypad_pins[i] = 0; break; } code=0; if(!(code=codecheck(argv[(i + 2) * 2])))argv[(i + 2) * 2]+=2; j = getinteger(argv[(i + 2) * 2]); if(!code)j=codemap(j); if(ExtCurrentConfig[j] >= EXT_COM_RESERVED) error("Pin %/| is in use",j,j); // if(i < 4) { ExtCfg(j, EXT_DIG_IN, ODCSET); ExtCfg(j, EXT_COM_RESERVED, 0); keypad_pins[i] = j; } } } /* * @cond * The following section will be excluded from the documentation. */ void KeypadClose(void) { int i; if(KeypadInterrupt == NULL) return; for(i = 0; i < 8; i++) { if(keypad_pins[i]) { ExtCfg(keypad_pins[i], EXT_NOT_CONFIG, 0); // all set to unconfigured } } KeypadInterrupt = NULL; } int KeypadCheck(void) { static unsigned char count = 0, keydown = false; int i, j; const char PadLookup[16] = { 1, 2, 3, 20, 4, 5, 6, 21, 7, 8, 9, 22, 10, 0, 11, 23 }; if(count++ % 64) return false; // only check every 64 loops through the interrupt processor for(j = 4; j < 8; j++) { // j controls the pull down pins if(keypad_pins[j]) { // we might just have 3 pull down pins PinSetBit(keypad_pins[j], ODCCLR); // pull it low for(i = 0; i < 4; i++) { // i is the row sense inputs if(PinRead((unsigned char)keypad_pins[i]) == 0) { // if it is low we have found a keypress if(keydown) goto exitcheck; // we have already reported this, so just exit uSec(40 * 1000); // wait 40mS and check again if(PinRead((unsigned char)keypad_pins[i]) != 0) goto exitcheck;// must be contact bounce if it is now high *KeypadVar = PadLookup[(i << 2) | (j - 4)]; // lookup the key value and set the variable PinSetBit(keypad_pins[j], ODCSET); keydown = true; // record that we know that the key is down return true; // and tell the interrupt processor that we are good to go } } PinSetBit(keypad_pins[j], ODCSET); // wasn't this pin, clear the pulldown } } keydown = false; // no key down, record the fact return false; exitcheck: PinSetBit(keypad_pins[j], ODCSET); return false; } /**************************************************************************************************************************** The LCD command *****************************************************************************************************************************/ void LCD_Nibble(int Data, int Flag, int Wait_uSec); void LCD_Byte(int Data, int Flag, int Wait_uSec); void LcdPinSet(int pin, int val); static char lcd_pins[6]; /* @endcond */ void cmd_lcd(void) { unsigned char *p; int i, j, code; if((p = checkstring(cmdline, (unsigned char *)"INIT"))) { getargs(&p, 11, (unsigned char *)","); if(argc != 11) error("Invalid syntax"); if(*lcd_pins) error("Already open"); for(i = 0; i < 6; i++) { code=0; if(!(code=codecheck(argv[i * 2])))argv[i * 2]+=2; lcd_pins[i] = getinteger(argv[i * 2]); if(!code)lcd_pins[i]=codemap(lcd_pins[i]); if(ExtCurrentConfig[(int)lcd_pins[i]] >= EXT_COM_RESERVED) error("Pin %/| is in use",lcd_pins[i],lcd_pins[i]); ExtCfg(lcd_pins[i], EXT_DIG_OUT, 0); ExtCfg(lcd_pins[i], EXT_COM_RESERVED, 0); } LCD_Nibble(0b0011, 0, 5000); // reset LCD_Nibble(0b0011, 0, 5000); // reset LCD_Nibble(0b0011, 0, 5000); // reset LCD_Nibble(0b0010, 0, 2000); // 4 bit mode LCD_Byte(0b00101100, 0, 600); // 4 bits, 2 lines LCD_Byte(0b00001100, 0, 600); // display on, no cursor LCD_Byte(0b00000110, 0, 600); // increment on write LCD_Byte(0b00000001, 0, 3000); // clear the display return; } if(!*lcd_pins) error("Not open"); if(checkstring(cmdline, (unsigned char *)"CLOSE")) { for(i = 0; i < 6; i++) { ExtCfg(lcd_pins[i], EXT_NOT_CONFIG, 0); // all set to unconfigured ExtSet(lcd_pins[i], 0); // all outputs (when set) default to low *lcd_pins = 0; } } else if(checkstring(cmdline, (unsigned char *)"CLEAR")) { // clear the display LCD_Byte(0b00000001, 0, 3000); } else if((p = checkstring(cmdline, (unsigned char *)"CMD")) || (p = checkstring(cmdline, (unsigned char *)"DATA"))) { // send a command or data getargs(&p, MAX_ARG_COUNT * 2, (unsigned char *)","); for(i = 0; i < argc; i += 2) { j = getint(argv[i], 0, 255); LCD_Byte(j, toupper(*cmdline) == 'D', 0); } } else { const char linestart[4] = {0, 64, 20, 84}; int center, pos; getargs(&cmdline, 5, (unsigned char *)","); if(argc != 5) error("Invalid syntax"); i = getint(argv[0], 1, 4); pos = 1; if(checkstring(argv[2], (unsigned char *)"C8")) center = 8; else if(checkstring(argv[2], (unsigned char *)"C16")) center = 16; else if(checkstring(argv[2], (unsigned char *)"C20")) center = 20; else if(checkstring(argv[2], (unsigned char *)"C40")) center = 40; else { center = 0; pos = getint(argv[2], 1, 256); } p = getstring(argv[4]); // returns an MMBasic string i = 128 + linestart[i - 1] + (pos - 1); LCD_Byte(i, 0, 600); for(j = 0; j < (center - *p) / 2; j++) { LCD_Byte(' ', 1, 0); } for(i = 1; i <= *p; i++) { LCD_Byte(p[i], 1, 0); j++; } for(; j < center; j++) { LCD_Byte(' ', 1, 0); } } } /* * @cond * The following section will be excluded from the documentation. */ void LCD_Nibble(int Data, int Flag, int Wait_uSec) { int i; LcdPinSet(lcd_pins[4], Flag); for(i = 0; i < 4; i++) LcdPinSet(lcd_pins[i], (Data >> i) & 1); LcdPinSet(lcd_pins[5], 1); uSec(250); LcdPinSet(lcd_pins[5], 0); if(Wait_uSec) uSec(Wait_uSec); else uSec(250); } void LCD_Byte(int Data, int Flag, int Wait_uSec) { LCD_Nibble(Data/16, Flag, 0); LCD_Nibble(Data, Flag, Wait_uSec); } void LcdPinSet(int pin, int val) { PinSetBit(pin, val ? LATSET : LATCLR); } int64_t DHmem(int pin){ int timeout = 400; long long int r; int i; writeusclock(0); PinSetBit(pin, CNPUSET); PinSetBit(pin, TRISSET); uSec(5); // wait for the DHT22 to pull the pin low and return it high then take it low again while(PinRead(pin)) if(readusclock() > timeout) goto error_exit; while(!PinRead(pin)) if(readusclock() > timeout) goto error_exit; while(PinRead(pin)) if(readusclock() > timeout) goto error_exit; // PInt(readusclock());PRet(); // now we wait for the pin to go high and measure how long it stays high (> 50uS is a one bit, < 50uS is a zero bit) for(r = i = 0; i < 40; i++) { timeout=400; while(!PinRead(pin)) if(readusclock() > timeout) goto error_exit; timeout=400;writeusclock(0); while(PinRead(pin)) if(readusclock() > timeout) goto error_exit; r <<= 1; r |= (readusclock() > 50); } return r; error_exit: return -1; } /* @endcond */ void cmd_DHT22(void) { int pin; union colourmap { unsigned char dhtbytes[8]; long long int r; } dht; // long long int r; int dht11=0; MMFLOAT *temp, *humid; getargs(&cmdline, 7, (unsigned char *)","); if(!(argc == 5 || argc == 7)) error("Incorrect number of arguments"); // get the two variables temp = findvar(argv[2], V_FIND); if(!(g_vartbl[g_VarIndex].type & T_NBR)) error("Invalid variable"); humid = findvar(argv[4], V_FIND); if(!(g_vartbl[g_VarIndex].type & T_NBR)) error("Invalid variable"); // get the pin number and set it up // get the pin number and set it up char code; if(!(code=codecheck(argv[0])))argv[0]+=2; pin = getinteger(argv[0]); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin "); if(ExtCurrentConfig[pin] != EXT_NOT_CONFIG) error("Pin %/| is in use",pin,pin); if(argc==7){ dht11=getint(argv[6],0,1); } ExtCfg(pin, EXT_DIG_OUT, 0); // pulse the pin low for 1.5mS uSec(1500+dht11*18000); // we have all 40 bits // first validate against the checksum if((dht.r=DHmem(pin))==-1) goto error_exit; if((uint8_t)(dht.dhtbytes[4]+dht.dhtbytes[3]+dht.dhtbytes[2]+dht.dhtbytes[1])!=dht.dhtbytes[0])goto error_exit; // if( ( (uint8_t)( ((r >> 8) & 0xff) + ((r >> 16) & 0xff) + ((r >> 24) & 0xff) + ((r >> 32) & 0xff) ) & 0xff) != (r & 0xff)) goto error_exit; // returning temperature if(dht11==0){ *temp = (MMFLOAT)((dht.r >> 8) &0x7fff) / 10.0; // get the temperature if((dht.r >> 8) &0x8000) *temp = -*temp; // the top bit is the sign *humid = (MMFLOAT)(dht.r >> 24) / 10.0; // get the humidity } else { *temp = (MMFLOAT)(dht.dhtbytes[2])+(MMFLOAT)(dht.dhtbytes[1])/10.0; // get the temperature *humid =(MMFLOAT)(dht.dhtbytes[4])+(MMFLOAT)(dht.dhtbytes[3])/10.0; // get the humidity } goto normal_exit; error_exit: *temp = *humid = 1000.0; // an obviously incorrect reading normal_exit: ExtCfg(pin, EXT_NOT_CONFIG, 0); PinSetBit(pin, LATCLR); } /* * @cond * The following section will be excluded from the documentation. */ void __not_in_flash_func(WS2812e)(int gppin, int T1H, int T1L, int T0H, int T0L, int nbr, char *p){ for(int i=0;i>=1; } p++; } } /* @endcond */ void fun_dev(void){ unsigned char *tp=NULL; tp = checkstring(ep, (unsigned char *)"WII"); if(tp==NULL)tp = checkstring(ep, (unsigned char *)"CLASSIC"); if(tp){ // int ax; //classic left x // int ay; //classic left y // int az; //classic centre // int Z; //classic right x // int C; //classic right y // int L; //classic left analog // int R; //classic right analog // unsigned short x0; //classic buttons getargs(&tp,1,(unsigned char *)","); if(!classic1)error("Not open"); if(checkstring(argv[0], (unsigned char *)"LX"))iret=nunstruct[0].ax; else if(checkstring(argv[0], (unsigned char *)"LY"))iret=nunstruct[0].ay; else if(checkstring(argv[0], (unsigned char *)"RX"))iret=nunstruct[0].Z; else if(checkstring(argv[0], (unsigned char *)"RY"))iret=nunstruct[0].C; else if(checkstring(argv[0], (unsigned char *)"L"))iret=nunstruct[0].L; else if(checkstring(argv[0], (unsigned char *)"R"))iret=nunstruct[0].R; else if(checkstring(argv[0], (unsigned char *)"B"))iret=nunstruct[0].x0; else if(checkstring(argv[0], (unsigned char *)"T"))iret=nunstruct[0].type; else iret=0; targ=T_INT; } else if((tp=checkstring(ep,(unsigned char *)"NUNCHUCK"))){ unsigned char *p; getargs(&tp,1,(unsigned char *)","); p=argv[0]; if(toupper(*p)=='A'){ p++; if(p[1]==0){ if(toupper(*p)=='X')iret=nunstruct[5].ax; else if(toupper(*p)=='Y')iret=nunstruct[5].ay; else if(toupper(*p)=='Z')iret=nunstruct[5].az; else error("Syntax"); } else { if(p[1]=='0'){ if(toupper(*p)=='X')iret=nunstruct[5].x0; else if(toupper(*p)=='Y')iret=nunstruct[5].y0; else if(toupper(*p)=='Z')iret=nunstruct[5].z0; else error("Syntax"); } else if(p[1]=='1'){ if(toupper(*p)=='X')iret=nunstruct[5].x1; else if(toupper(*p)=='Y')iret=nunstruct[5].y1; else if(toupper(*p)=='Z')iret=nunstruct[5].z1; else error("Syntax"); } else error("Syntax"); } } else if(toupper(*p)=='J'){ p++; if(p[1]==0){ if(toupper(*p)=='X')iret=nunstruct[5].x; else if(toupper(*p)=='Y')iret=nunstruct[5].y; } else { if(toupper(*p)=='X'){ p++; if(toupper(*p)=='L'){ iret=nunstruct[5].calib[9]; } else if(toupper(*p)=='C'){ iret=nunstruct[5].calib[10]; } else if(toupper(*p)=='R'){ iret=nunstruct[5].calib[8]; } else error("Syntax"); } else if(toupper(*p)=='Y'){ p++; if(toupper(*p)=='T'){ iret=nunstruct[5].calib[11]; } else if(toupper(*p)=='C'){ iret=nunstruct[5].calib[13]; } else if(toupper(*p)=='B'){ iret=nunstruct[5].calib[12]; } else error("Syntax"); } else error("Syntax"); } } else { if(toupper(*p)=='Z')iret=nunstruct[5].Z; else if(toupper(*p)=='C')iret=nunstruct[5].C; else if(toupper(*p)=='T')iret=nunstruct[5].type; else error("Syntax"); } targ=T_INT; } else if((tp=checkstring(ep,(unsigned char *)"GAMEPAD"))){ // int ax; //classic left x // int ay; //classic left y // int az; //classic centre // int Z; //classic right x // int C; //classic right y // int L; //classic left analog // int R; //classic right analog // unsigned short x0; //classic buttons getargs(&tp,3,(unsigned char *)","); int n=getint(argv[0],1,4); if(checkstring(argv[2], (unsigned char *)"LX"))iret=nunstruct[n].ax; else if(checkstring(argv[2], (unsigned char *)"LY"))iret=nunstruct[n].ay; else if(checkstring(argv[2], (unsigned char *)"RX"))iret=nunstruct[n].Z; else if(checkstring(argv[2], (unsigned char *)"RY"))iret=nunstruct[n].C; else if(checkstring(argv[2], (unsigned char *)"L"))iret=nunstruct[n].L; else if(checkstring(argv[2], (unsigned char *)"R"))iret=nunstruct[n].R; else if(checkstring(argv[2], (unsigned char *)"B"))iret=nunstruct[n].x0; else if(checkstring(argv[2], (unsigned char *)"GX"))iret=nunstruct[n].gyro[0]; else if(checkstring(argv[2], (unsigned char *)"GY"))iret=nunstruct[n].gyro[1]; else if(checkstring(argv[2], (unsigned char *)"GZ"))iret=nunstruct[n].gyro[2]; else if(checkstring(argv[2], (unsigned char *)"AX"))iret=nunstruct[n].accs[0]; else if(checkstring(argv[2], (unsigned char *)"AY"))iret=nunstruct[n].accs[1]; else if(checkstring(argv[2], (unsigned char *)"AZ"))iret=nunstruct[n].accs[2]; else if(checkstring(argv[2], (unsigned char *)"T"))iret=nunstruct[n].type; #ifdef USBKEYBOARD else if(checkstring(argv[2], (unsigned char *)"RAW")){ sret=GetTempMemory(STRINGSIZE); targ=T_STR; Mstrcpy(sret,(unsigned char *)HID[n-1].report); return; } #endif else iret=0; targ=T_INT; } else if((tp=checkstring(ep,(unsigned char *)"MOUSE"))){ /* Returns data from a PS2 mouse 'funct' is a 1 letter code indicating the information to return as follows: X returns the value of the mouse X-position Y returns the value of the mouse Y-position L returns the value of the left mouse button (1 if pressed) R returns the value of the right mouse button (1 if pressed) W returns the value of the scroll wheel mouse button (1 if pressed) D This allows you to detect a double click of the left mouse button. The algorithm requires that the two clicks must occur between 100 and 500 milliseconds apart. The report via MOUSE(D) is then valid for 500mSec before it times out or until it is read. T This returns 3 if a PS2 mouse has a scroll wheel or 0 if not.*/ getargs(&tp,3,(unsigned char *)","); int n=getint(argv[0],1,4); if(checkstring(argv[2], (unsigned char *)"X"))iret=nunstruct[n].ax; else if(checkstring(argv[2], (unsigned char *)"Y"))iret=nunstruct[n].ay; else if(checkstring(argv[2], (unsigned char *)"L"))iret=nunstruct[n].L; else if(checkstring(argv[2], (unsigned char *)"R"))iret=nunstruct[n].R; else if(checkstring(argv[2], (unsigned char *)"M"))iret=nunstruct[n].C; else if(checkstring(argv[2], (unsigned char *)"W"))iret=nunstruct[n].az; else if(checkstring(argv[2], (unsigned char *)"D")){iret=nunstruct[n].Z;nunstruct[n].Z=0;} else if(checkstring(argv[2], (unsigned char *)"T"))iret=nunstruct[n].classic[0]; else error("Syntax"); targ=T_INT; } else error("Syntax"); } void cmd_WS2812(void){ int64_t *dest=NULL; uint32_t pin, red , green, blue, white, colour; int T0H=0,T0L=0,T1H=0,T1L=0,TRST=0; unsigned char *p; int i, j, bit, nbr=0, colours=3; int ticks_per_millisecond=ticks_per_second/1000; getargs(&cmdline, 7, (unsigned char *)","); if(argc != 7)error("Argument count"); p=argv[0]; if(toupper(*p)=='O'){ T0H=16777215 + setuptime-((7*ticks_per_millisecond)/20000) ; T1H=16777215 + setuptime-((14*ticks_per_millisecond)/20000) ; T0L=16777215 + setuptime-((13*ticks_per_millisecond)/20000) ; T1L=16777215 + setuptime-((9.5*ticks_per_millisecond)/20000) ; TRST=50; } else if(toupper(*p)=='B'){ T0H=16777215 + setuptime-((8*ticks_per_millisecond)/20000) ; T1H=16777215 + setuptime-((16*ticks_per_millisecond)/20000) ; T0L=16777215 + setuptime-((14*ticks_per_millisecond)/20000) ; T1L=16777215 + setuptime-((6.5*ticks_per_millisecond)/20000) ; TRST=280; } else if(toupper(*p)=='S' || toupper(*p)=='W' ){ if(toupper(*p)=='W')colours=4; T0H=16777215 + setuptime-((6*ticks_per_millisecond)/20000) ; T0L=16777215 + setuptime-((15*ticks_per_millisecond)/20000) ; T1H=16777215 + setuptime-((12*ticks_per_millisecond)/20000) ; T1L=16777215 + setuptime-((9*ticks_per_millisecond)/20000) ; TRST=80; } else error("Syntax"); nbr=getint(argv[4],1,256); if(nbr>1){ parseintegerarray(argv[6], &dest, 4, 1, NULL, false); } else { colour=getinteger(argv[6]); dest = (long long int *)&colour; } unsigned char code; if(!(code=codecheck(argv[2])))argv[2]+=2; pin = getinteger(argv[2]); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin"); int gppin=PinDef[pin].GPno; if(!(ExtCurrentConfig[pin] == EXT_DIG_OUT || ExtCurrentConfig[pin] == EXT_NOT_CONFIG)) error("Pin %/| is not off or an output",pin,pin); if(ExtCurrentConfig[pin] == EXT_NOT_CONFIG)ExtCfg(pin, EXT_DIG_OUT, 0); p=GetTempMemory((nbr+1)*colours); uint64_t endreset=time_us_64()+TRST; for(i=0;i>8) & 0xFF; red=(dest[i]>>16) & 0xFF; blue=dest[i] & 0xFF; if(colours==4)white=(dest[i]>>24) & 0xFF; p[0]=0;p[1]=0;p[2]=0; if(colours==4){p[3]=0;} for(j=0;j<8;j++){ bit=1<cvr=0; gpio_clr_mask64(gppin); // send the start bit mask=1; while(systick_hw->cvr>bittime){}; systick_hw->cvr=0; for (mask=1;mask<0x100; mask<<=1) { if(string[count] & mask) { // check the bit to send gpio_set_mask64(gppin); // send the start bit } else { gpio_clr_mask64(gppin); // send the start bit } while(systick_hw->cvr>bittime){}; systick_hw->cvr=0; } gpio_set_mask64(gppin); // send the start bit while(systick_hw->cvr>bittime){}; } } unsigned short FloatToUint32(MMFLOAT x) { if(x<0 || x > 4294967295) error("Number range"); return (x >= 0 ? (unsigned int)(x + 0.5) : (unsigned int)(x - 0.5)) ; } int __not_in_flash_func(serialrx)(int gppin, unsigned char *string, int timeout, int bittime, int half, int maxchars, char *termchars){ int i,c,count=0; while(1){ while(gpio_get_all64() & gppin) { // wait for the start bit if(readusclock() >= timeout) return -1; // return if there is a timeout } systick_hw->cvr=0; while(systick_hw->cvr>half){}; systick_hw->cvr=0; if(gpio_get_all64() & gppin) continue; // go around again if not low c=0; for(i = 0; i < 8; i++) { while(systick_hw->cvr>bittime){}; systick_hw->cvr=0; c |= (((gpio_get_all64() & gppin) ? 1 : 0) << i); // and add this bit in } while(systick_hw->cvr>bittime){}; if(!(gpio_get_all64() & gppin)) continue; // a framing error if not high count++; string[count] = c; // save the character string[0] = count; // and update the numbers of characters in the string if(count >= maxchars) return 2; // do we have our maximun number of characters? if(termchars) { for(i = 0; i < termchars[0]; i++) { // check each terminating character if(c == termchars[i + 1]) return 3; // and exit if this character is one of them } } } } /* @endcond */ void cmd_device(void){ unsigned char *tp; tp = checkstring(cmdline, (unsigned char *)"WS2812"); if(tp) { cmdline=tp; cmd_WS2812(); return; } tp = checkstring(cmdline, (unsigned char *)"KEYPAD"); if(tp) { cmdline=tp; cmd_keypad(); return; } tp = checkstring(cmdline, (unsigned char *)"LCD"); if(tp) { cmdline=tp; cmd_lcd(); return; } #ifndef PICOMITEVGA tp = checkstring(cmdline, (unsigned char *)"CAMERA"); if(tp) { cmdline=tp; cmd_camera(); return; } #endif tp = checkstring(cmdline, (unsigned char *)"WII CLASSIC"); if(tp==NULL)tp = checkstring(cmdline, (unsigned char *)"WII"); if(tp) { cmdline=tp; cmd_Classic(); return; } tp = checkstring(cmdline, (unsigned char *)"NUNCHUCK"); if(tp) { cmdline=tp; cmd_Nunchuck(); return; } #ifdef USBKEYBOARD tp = checkstring(cmdline, (unsigned char *)"MOUSE"); if(tp) { cmdline=tp; cmd_mouse(); return; } tp = checkstring(cmdline, (unsigned char *)"GAMEPAD"); if(tp) { cmdline=tp; cmd_gamepad(); return; } #endif tp = checkstring(cmdline, (unsigned char *)"HUMID"); if(tp) { cmdline=tp; cmd_DHT22(); return; } tp = checkstring(cmdline, (unsigned char *)"SERIALRX"); if(tp) { int maxchars=255; char *termchars=NULL; getargs(&tp, 13,(unsigned char *)","); if(argc < 9) error("Argument count"); unsigned char code; if(!(code=codecheck(argv[0])))argv[0]+=2; int pin = getinteger(argv[0]); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin"); if(!(ExtCurrentConfig[pin] == EXT_DIG_IN || ExtCurrentConfig[pin] == EXT_NOT_CONFIG)) error("Pin %/| is not off or an input",pin,pin); if(ExtCurrentConfig[pin] == EXT_NOT_CONFIG)ExtCfg(pin, EXT_DIG_IN, CNPUSET); int gppin=(1<9 && *argv[10])maxchars=getint(argv[10],1,255); if(argc==13)termchars=(char *)getstring(argv[12]); writeusclock(0); int bittime=16777215 + 12 - (ticks_per_second/baudrate) ; int half = 16777215 + 12 - (ticks_per_second/(baudrate<<1)) ; if(!(gpio_get_all64() & gppin))error("Framing error"); disable_interrupts_pico(); int istat=serialrx(gppin, string, timeout, bittime, half, maxchars, termchars); enable_interrupts_pico(); if(type & T_INT)*(int64_t *)status=(int64_t)istat; else *(MMFLOAT *)status=(MMFLOAT)istat; return; } tp = checkstring(cmdline, (unsigned char *)"SERIALTX"); if(tp) { // int mask; getargs(&tp, 5,(unsigned char *)","); if(!(argc == 5)) error("Argument count"); unsigned char code; // int count = 0; if(!(code=codecheck(argv[0])))argv[0]+=2; int pin = getinteger(argv[0]); if(!code)pin=codemap(pin); if(IsInvalidPin(pin)) error("Invalid pin"); int gppin=(1<67108)error("Number range"); data[i]= *a1int++ ; } } for(i=0; i< num;i++){ data[i]=16777215 + setuptime-((data[i]*ticks_per_millisecond)/1000) ; } // data[0]+=((ticks_per_millisecond/2000)+(250000-Option.CPU_Speed)/1000); disable_interrupts_pico(); bitstream(gppin,data,num); enable_interrupts_pico(); return; } error("Syntax"); } /* * @cond * The following section will be excluded from the documentation. */ void __not_in_flash_func(ADCint)() { // Clear the interrupt request for DMA control channel dma_hw->ints1 = (1u << ADC_dma_chan); if(adcint==adcint2)adcint=adcint1; else adcint=adcint2; ADCDualBuffering=true; } /* @endcond */ void cmd_adc(void){ unsigned char *tp; tp = checkstring(cmdline, (unsigned char *)"OPEN"); if(tp) { getargs(&tp,5,(unsigned char *)","); if(ADCopen)error("Already open"); if(!(argc==3 || argc==5))error("Syntax"); #ifndef PICOMITEWEB int nbr=getint(argv[2],1,4); //number of ADC channels #else int nbr=getint(argv[2],1,3); //number of ADC channels #endif frequency=(float)getnumber(argv[0])*nbr; if(frequency ADC_CLK_SPEED/96.0)error("Invalid frequency"); #ifdef rp2350 #ifdef PICOMITEWEB if(!(ExtCurrentConfig[31] == EXT_ANA_IN || ExtCurrentConfig[31] == EXT_NOT_CONFIG)) error("Pin GP26 is not off or an ADC input"); if(ExtCurrentConfig[31] == EXT_NOT_CONFIG)ExtCfg(31, EXT_ANA_IN, 0); ExtCfg(31, EXT_COM_RESERVED, 0); if(nbr>=2){ if(!(ExtCurrentConfig[32] == EXT_ANA_IN || ExtCurrentConfig[32] == EXT_NOT_CONFIG)) error("Pin GP27 is not off or an ADC input"); if(ExtCurrentConfig[32] == EXT_NOT_CONFIG)ExtCfg(32, EXT_ANA_IN, 0); ExtCfg(32, EXT_COM_RESERVED, 0); } if(nbr>=3){ if(!(ExtCurrentConfig[34] == EXT_ANA_IN || ExtCurrentConfig[34] == EXT_NOT_CONFIG)) error("Pin GP28 is not off or an ADC input"); if(ExtCurrentConfig[34] == EXT_NOT_CONFIG)ExtCfg(34, EXT_ANA_IN, 0); ExtCfg(34, EXT_COM_RESERVED, 0); } #else if(rp2350a){ if(!(ExtCurrentConfig[31] == EXT_ANA_IN || ExtCurrentConfig[31] == EXT_NOT_CONFIG)) error("Pin GP26 is not off or an ADC input"); if(ExtCurrentConfig[31] == EXT_NOT_CONFIG)ExtCfg(31, EXT_ANA_IN, 0); ExtCfg(31, EXT_COM_RESERVED, 0); if(nbr>=2){ if(!(ExtCurrentConfig[32] == EXT_ANA_IN || ExtCurrentConfig[32] == EXT_NOT_CONFIG)) error("Pin GP27 is not off or an ADC input"); if(ExtCurrentConfig[32] == EXT_NOT_CONFIG)ExtCfg(32, EXT_ANA_IN, 0); ExtCfg(32, EXT_COM_RESERVED, 0); } if(nbr>=3){ if(!(ExtCurrentConfig[34] == EXT_ANA_IN || ExtCurrentConfig[34] == EXT_NOT_CONFIG)) error("Pin GP28 is not off or an ADC input"); if(ExtCurrentConfig[34] == EXT_NOT_CONFIG)ExtCfg(34, EXT_ANA_IN, 0); ExtCfg(34, EXT_COM_RESERVED, 0); } if(nbr>=4){ if(!(ExtCurrentConfig[44] == EXT_ANA_IN || ExtCurrentConfig[44] == EXT_NOT_CONFIG)) error("Pin GP29 is not off or an ADC input"); if(ExtCurrentConfig[44] == EXT_NOT_CONFIG)ExtCfg(44, EXT_ANA_IN, 0); ExtCfg(44, EXT_COM_RESERVED, 0); } } else { if(!(ExtCurrentConfig[55] == EXT_ANA_IN || ExtCurrentConfig[55] == EXT_NOT_CONFIG)) error("Pin GP40 is not off or an ADC input"); if(ExtCurrentConfig[55] == EXT_NOT_CONFIG)ExtCfg(55, EXT_ANA_IN, 0); ExtCfg(55, EXT_COM_RESERVED, 0); if(nbr>=2){ if(!(ExtCurrentConfig[56] == EXT_ANA_IN || ExtCurrentConfig[56] == EXT_NOT_CONFIG)) error("Pin GP41 is not off or an ADC input"); if(ExtCurrentConfig[56] == EXT_NOT_CONFIG)ExtCfg(56, EXT_ANA_IN, 0); ExtCfg(56, EXT_COM_RESERVED, 0); } if(nbr>=3){ if(!(ExtCurrentConfig[57] == EXT_ANA_IN || ExtCurrentConfig[57] == EXT_NOT_CONFIG)) error("Pin GP42 is not off or an ADC input"); if(ExtCurrentConfig[57] == EXT_NOT_CONFIG)ExtCfg(57, EXT_ANA_IN, 0); ExtCfg(57, EXT_COM_RESERVED, 0); } if(nbr>=4){ if(!(ExtCurrentConfig[58] == EXT_ANA_IN || ExtCurrentConfig[58] == EXT_NOT_CONFIG)) error("Pin GP43 is not off or an ADC input"); if(ExtCurrentConfig[58] == EXT_NOT_CONFIG)ExtCfg(58, EXT_ANA_IN, 0); ExtCfg(58, EXT_COM_RESERVED, 0); } } #endif #else if(!(ExtCurrentConfig[31] == EXT_ANA_IN || ExtCurrentConfig[31] == EXT_NOT_CONFIG)) error("Pin GP26 is not off or an ADC input"); if(ExtCurrentConfig[31] == EXT_NOT_CONFIG)ExtCfg(31, EXT_ANA_IN, 0); ExtCfg(31, EXT_COM_RESERVED, 0); if(nbr>=2){ if(!(ExtCurrentConfig[32] == EXT_ANA_IN || ExtCurrentConfig[32] == EXT_NOT_CONFIG)) error("Pin GP27 is not off or an ADC input"); if(ExtCurrentConfig[32] == EXT_NOT_CONFIG)ExtCfg(32, EXT_ANA_IN, 0); ExtCfg(32, EXT_COM_RESERVED, 0); } if(nbr>=3){ if(!(ExtCurrentConfig[34] == EXT_ANA_IN || ExtCurrentConfig[34] == EXT_NOT_CONFIG)) error("Pin GP28 is not off or an ADC input"); if(ExtCurrentConfig[34] == EXT_NOT_CONFIG)ExtCfg(34, EXT_ANA_IN, 0); ExtCfg(34, EXT_COM_RESERVED, 0); } #ifndef PICOMITEWEB if(nbr>=4){ if(!(ExtCurrentConfig[44] == EXT_ANA_IN || ExtCurrentConfig[44] == EXT_NOT_CONFIG)) error("Pin GP29 is not off or an ADC input"); if(ExtCurrentConfig[44] == EXT_NOT_CONFIG)ExtCfg(44, EXT_ANA_IN, 0); ExtCfg(44, EXT_COM_RESERVED, 0); } #endif #endif if(argc==5){ InterruptUsed = true; ADCInterrupt = (char *)GetIntAddress(argv[4]); // get the interrupt location } else ADCInterrupt = NULL; ADCopen=nbr; return; } tp = checkstring(cmdline, (unsigned char *)"RUN"); if(tp){ getargs(&tp, 3, (unsigned char *)","); if(!ADCopen)error("ADC not open"); if(!(argc == 3))error("Argument count"); ADCmax=0; ADCpos=0; adcint1=adcint2=NULL; int64_t *adcval=NULL; #ifdef rp2350 int dims[MAXDIM]={0}; #else short dims[MAXDIM]={0}; #endif int card1=parseintegerarray(argv[0], &adcval, 1, 1, dims, true); adcint1=(uint8_t *)adcval; adcval=NULL; ADCmax=parseintegerarray(argv[2], &adcval, 2, 1, dims, true); adcint2=(uint8_t *)adcval; if(card1!=ADCmax)error("Array size mismatch %,%",card1, ADCmax); ADCmax *=8; dma_channel_cleanup(ADC_dma_chan); dma_channel_cleanup(ADC_dma_chan2); adc_init(); adc_set_round_robin(ADCopen==1 ? 1 : ADCopen==2 ? 3 : ADCopen==3 ? 7 : 15); adc_fifo_setup( true, // Write each completed conversion to the sample FIFO true, // Enable DMA data request (DREQ) 1, // DREQ (and IRQ) asserted when at least 1 sample present false, // We won't see the ERR bit because of 8 bit reads; disable. true // Shift each sample to 8 bits when pushing to FIFO ); adcint=adcint1; SetADCFreq(frequency); // Set up the DMA to start transferring data as soon as it appears in FIFO dma_channel_config cfg = dma_channel_get_default_config(ADC_dma_chan); // Reading from constant address, writing to incrementing byte addresses channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8); channel_config_set_read_increment(&cfg, false); channel_config_set_write_increment(&cfg, true); channel_config_set_irq_quiet(&cfg, false); channel_config_set_dreq(&cfg, DREQ_ADC); channel_config_set_chain_to(&cfg, ADC_dma_chan2); dma_channel_configure(ADC_dma_chan, &cfg, adcint, // dst &adc_hw->fifo, // src ADCmax, // transfer count false // start immediately ); dma_channel_config c2 = dma_channel_get_default_config(ADC_dma_chan2); //Get configurations for control channel channel_config_set_transfer_data_size(&c2, DMA_SIZE_32); //Set control channel data transfer size to 32 bits channel_config_set_read_increment(&c2, false); //Set control channel read increment to false channel_config_set_write_increment(&c2, false); //Set control channel write increment to false channel_config_set_dreq(&c2, 0x3F); // channel_config_set_chain_to(&c2, dma_tx_chan); dma_channel_configure(ADC_dma_chan2, &c2, &dma_hw->ch[ADC_dma_chan].al2_write_addr_trig, &adcint, 1, false); //Configure control channel dma_channel_set_irq1_enabled(ADC_dma_chan, true); // set DMA IRQ handler irq_set_exclusive_handler(DMA_IRQ_1, ADCint); // set highest IRQ priority irq_set_enabled(DMA_IRQ_1, true); dma_start_channel_mask(1u << ADC_dma_chan2); adc_run(true); adcint=adcint2; ADCDualBuffering=false; return; } tp = checkstring(cmdline, (unsigned char *)"FREQUENCY"); if(tp) { getargs(&tp,1,(unsigned char *)","); if(!ADCopen)error("Not open"); float localfrequency=(float)getnumber(argv[0])*ADCopen; if(localfrequency ADC_CLK_SPEED/96.0)error("Invalid frequency"); frequency=localfrequency; return; } tp = checkstring(cmdline, (unsigned char *)"START"); if(tp) { getargs(&tp, 23, (unsigned char *)","); if(!ADCopen)error("ADC not open"); if(!(argc >= 1))error("Argument count"); a1float=NULL; a2float=NULL; a3float=NULL; a4float=NULL; ADCmax=0; ADCpos=0; int card; MMFLOAT top; for(int i=0;i<4;i++){ ADCscale[i]=VCC/4095.0; ADCbottom[i]=0; } ADCmax=parsefloatrarray(argv[0], (MMFLOAT **)&a1float, 1, 1, NULL, true); if(argc>=3 && *argv[2]){ if(ADCopen<2)error("Second channel not open"); card=parsefloatrarray(argv[2], (MMFLOAT **)&a2float, 2, 1, NULL, true); if(card!=ADCmax)error("Array size mismatch"); } if(argc>=5 && *argv[4]){ if(ADCopen<3)error("Third channel not open"); card=parsefloatrarray(argv[4], (MMFLOAT **)&a3float, 3, 1, NULL, true); if(card!=ADCmax)error("Array size mismatch"); } if(argc>=7 && *argv[6]){ if(ADCopen<4)error("Fourth channel not open"); card=parsefloatrarray(argv[6], (MMFLOAT **)&a4float, 4, 1, NULL, true); if(card!=ADCmax)error("Array size mismatch"); } if(argc>=11){ ADCbottom[0]=getnumber(argv[8]); top=getnumber(argv[10]); ADCscale[0]=(top-ADCbottom[0])/4095.0; } if(argc>=15){ ADCbottom[1]=getnumber(argv[12]); top=getnumber(argv[14]); ADCscale[1]=(top-ADCbottom[1])/4095.0; } if(argc>=19){ ADCbottom[2]=getnumber(argv[16]); top=getnumber(argv[18]); ADCscale[2]=(top-ADCbottom[2])/4095.0; } if(argc>=23){ ADCbottom[3]=getnumber(argv[20]); top=getnumber(argv[22]); ADCscale[3]=(top-ADCbottom[3])/4095.0; } ADCmax++; ADCbuffer=GetMemory(ADCmax*ADCopen*2); adc_init(); adc_set_round_robin(ADCopen==1 ? 1 : ADCopen==2 ? 3 : ADCopen==3 ? 7 : 15); adc_fifo_setup( true, // Write each completed conversion to the sample FIFO true, // Enable DMA data request (DREQ) 1, // DREQ (and IRQ) asserted when at least 1 sample present false, // We won't see the ERR bit because of 8 bit reads; disable. false // Shift each sample to 8 bits when pushing to FIFO ); SetADCFreq(frequency); // Set up the DMA to start transferring data as soon as it appears in FIFO dma_channel_config cfg = dma_channel_get_default_config(ADC_dma_chan); // Reading from constant address, writing to incrementing byte addresses channel_config_set_transfer_data_size(&cfg, DMA_SIZE_16); channel_config_set_read_increment(&cfg, false); channel_config_set_write_increment(&cfg, true); channel_config_set_irq_quiet(&cfg, true); // Pace transfers based on availability of ADC samples channel_config_set_dreq(&cfg, DREQ_ADC); dma_channel_configure(ADC_dma_chan, &cfg, (uint8_t *)ADCbuffer, // dst &adc_hw->fifo, // src ADCmax*ADCopen, // transfer count true // start immediately ); adc_run(true); // Once DMA finishes, stop any new conversions from starting, and clean up // the FIFO in case the ADC was still mid-conversion. if(!ADCInterrupt){ while(dma_channel_is_busy(ADC_dma_chan))tight_loop_contents(); __compiler_memory_barrier(); adc_run(false); adc_fifo_drain(); int k=0; for(int i=0;iabort = ((1u << ADC_dma_chan2) | (1u << ADC_dma_chan)); dma_channel_abort(ADC_dma_chan); dma_channel_abort(ADC_dma_chan2); adc_set_round_robin(0); SetADCFreq(500000); #ifdef rp2350 if(rp2350a){ ExtCfg(31, EXT_NOT_CONFIG, 0); if(ADCopen>=2)ExtCfg(32, EXT_NOT_CONFIG, 0); if(ADCopen>=3)ExtCfg(34, EXT_NOT_CONFIG, 0); if(ADCopen>=4)ExtCfg(44, EXT_NOT_CONFIG, 0); } else { ExtCfg(55, EXT_NOT_CONFIG, 0); if(ADCopen>=2)ExtCfg(56, EXT_NOT_CONFIG, 0); if(ADCopen>=3)ExtCfg(57, EXT_NOT_CONFIG, 0); if(ADCopen>=4)ExtCfg(58, EXT_NOT_CONFIG, 0); } #else ExtCfg(31, EXT_NOT_CONFIG, 0); if(ADCopen>=2)ExtCfg(32, EXT_NOT_CONFIG, 0); if(ADCopen>=3)ExtCfg(34, EXT_NOT_CONFIG, 0); if(ADCopen>=4)ExtCfg(44, EXT_NOT_CONFIG, 0); #endif ADCopen=0; adcint=adcint1=adcint2=NULL; ADCDualBuffering=false; dmarunning=false; last_adc=99; adc_init(); return; } error("Syntax"); } void SetADCFreq(float frequency){ //Our ADC clock is running at ADC_CLK_SPEED (in Hz) so we need to stretch the time to produce the required frequency //The time delta for our frequency is 1/frequency*96 - 1/(ADC_CLK_SPEED) seconds //This must be added to clk_div as a number of CPU clock ticks i.e. delta/(1/ADC_CLK_SPEED) //Plus we need to add 95 to cater for the actual time taken for the conversion double delta = 1.0/(frequency*96.0) - 1.0/((double)ADC_CLK_SPEED); float div=delta/(1.0/((double)ADC_CLK_SPEED))*96.0 +95.0; if(div<=96.0)div=0; adc_set_clkdiv(div); } /* * @cond * The following section will be excluded from the documentation. */ void MIPS16 ClearExternalIO(void) { int i; CloseAudio(1); #ifndef PICOMITEVGA cameraclose(); #endif InterruptUsed = false; InterruptReturn = NULL; irq_set_enabled(DMA_IRQ_1, false); #ifdef rp2350 irq_set_enabled(PWM_IRQ_WRAP_1, false); #endif closeframebuffer('A'); if(CallBackEnabled==1) gpio_set_irq_enabled_with_callback(PinDef[IRpin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else if(CallBackEnabled & 1){ gpio_set_irq_enabled(PinDef[IRpin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~1); } if(CallBackEnabled==2) gpio_set_irq_enabled_with_callback(PinDef[Option.INT1pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else if(CallBackEnabled & 2){ gpio_set_irq_enabled(PinDef[Option.INT1pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~2); } if(CallBackEnabled==4) gpio_set_irq_enabled_with_callback(PinDef[Option.INT2pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else if(CallBackEnabled & 4){ gpio_set_irq_enabled(PinDef[Option.INT2pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~4); } if(CallBackEnabled==8) gpio_set_irq_enabled_with_callback(PinDef[Option.INT3pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else if(CallBackEnabled & 8){ gpio_set_irq_enabled(PinDef[Option.INT3pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~8); } if(CallBackEnabled==16) gpio_set_irq_enabled_with_callback(PinDef[Option.INT4pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false, &gpio_callback); else if(CallBackEnabled & 16){ gpio_set_irq_enabled(PinDef[Option.INT4pin].GPno, GPIO_IRQ_EDGE_RISE | GPIO_IRQ_EDGE_FALL, false); CallBackEnabled &= (~16); } CallBackEnabled &= (~32); for(i=0;i=2)ExtCfg(32, EXT_NOT_CONFIG, 0); if(ADCopen>=3)ExtCfg(34, EXT_NOT_CONFIG, 0); if(ADCopen>=4)ExtCfg(44, EXT_NOT_CONFIG, 0); } else { if(ADCopen) ExtCfg(55, EXT_NOT_CONFIG, 0); if(ADCopen>=2)ExtCfg(56, EXT_NOT_CONFIG, 0); if(ADCopen>=3)ExtCfg(57, EXT_NOT_CONFIG, 0); if(ADCopen>=4)ExtCfg(58, EXT_NOT_CONFIG, 0); } #else if(ADCopen) ExtCfg(31, EXT_NOT_CONFIG, 0); if(ADCopen>=2)ExtCfg(32, EXT_NOT_CONFIG, 0); if(ADCopen>=3)ExtCfg(34, EXT_NOT_CONFIG, 0); if(ADCopen>=4)ExtCfg(44, EXT_NOT_CONFIG, 0); #endif ADCopen=0; adc_set_round_robin(0); SetADCFreq(500000); KeyInterrupt=NULL; OnKeyGOSUB=NULL; #ifndef USBKEYBOARD OnPS2GOSUB=NULL; PS2code=0; PS2int=false; if(!Option.MOUSE_CLOCK)mouse0close(); #endif for (int i=0; i<6;i++)nunInterruptc[i]=NULL; if((classic1 || nunchuck1) && (classicread || nunchuckread))WiiReceive(6, (char *)nunbuff); classic1=0; nunchuck1=0; classicread=false; nunchuckread=false; #ifdef PICOMITEWEB MQTTInterrupt=NULL; MQTTComplete=0; closeMQTT(); #endif #ifndef PICOMITEWEB #ifdef PICOMITEVGA CollisionFound = false; COLLISIONInterrupt=NULL; #endif #endif #ifdef GUICONTROLS gui_int_down = false; gui_int_up = false; GuiIntDownVector=NULL; GuiIntUpVector=NULL; #endif dmarunning=false; ADCDualBuffering=false; ADCInterrupt=NULL; CSubInterrupt=NULL; CSubComplete=0; keyselect=0; g_myrand=NULL; CMM1=0; dirOK=2; nextline[0]=0;nextline[1]=0;nextline[2]=0;nextline[3]=99; memset(pioTXlast,0,sizeof(pioTXlast)); memset(pioRXinterrupts,0,sizeof(pioRXinterrupts)); memset(pioTXinterrupts,0,sizeof(pioTXinterrupts)); piointerrupt=0; DMAinterruptRX=NULL; DMAinterruptTX=NULL; WAVInterrupt=NULL; dma_hw->abort = ((1u << dma_rx_chan2) | (1u << dma_rx_chan)); if(dma_channel_is_busy(dma_rx_chan))dma_channel_abort(dma_rx_chan); if(dma_channel_is_busy(dma_rx_chan2))dma_channel_abort(dma_rx_chan2); // dma_channel_cleanup(dma_rx_chan); // dma_channel_cleanup(dma_rx_chan2); dma_hw->abort = ((1u << dma_tx_chan2) | (1u << dma_tx_chan)); if(dma_channel_is_busy(dma_tx_chan))dma_channel_abort(dma_tx_chan); if(dma_channel_is_busy(dma_tx_chan2))dma_channel_abort(dma_tx_chan2); // dma_channel_cleanup(dma_tx_chan); // dma_channel_cleanup(dma_tx_chan2); dma_hw->abort = ((1u << ADC_dma_chan2) | (1u << ADC_dma_chan)); if(dma_channel_is_busy(ADC_dma_chan))dma_channel_abort(ADC_dma_chan); if(dma_channel_is_busy(ADC_dma_chan2))dma_channel_abort(ADC_dma_chan2); // dma_channel_cleanup(ADC_dma_chan); // dma_channel_cleanup(ADC_dma_chan2); adcint=adcint1=adcint2=NULL; } void __not_in_flash_func(TM_EXTI_Handler_1)(void) { if(ExtCurrentConfig[Option.INT1pin] == EXT_PER_IN) { if(--INT1Timer <= 0) { INT1Value = INT1Count; INT1Timer = INT1InitTimer; INT1Count = 0; } } else { if(CFuncInt1) CallCFuncInt1(); // Hardware interrupt 2 for a CFunction (see CFunction.c) else INT1Count++; } } // perform the counting functions for INT2 void __not_in_flash_func(TM_EXTI_Handler_2)(void) { if(ExtCurrentConfig[Option.INT2pin] == EXT_PER_IN) { if(--INT2Timer <= 0) { INT2Value = INT2Count; INT2Timer = INT2InitTimer; INT2Count = 0; } } else { if(CFuncInt2) CallCFuncInt2(); // Hardware interrupt 2 for a CFunction (see CFunction.c) else INT2Count++; } } // perform the counting functions for INT3 void __not_in_flash_func(TM_EXTI_Handler_3)(void) { if(ExtCurrentConfig[Option.INT3pin] == EXT_PER_IN) { if(--INT3Timer <= 0) { INT3Value = INT3Count; INT3Timer = INT3InitTimer; INT3Count = 0; } } else { if(CFuncInt3) CallCFuncInt3(); // Hardware interrupt 2 for a CFunction (see CFunction.c) else INT3Count++; } } // perform the counting functions for INT4 void __not_in_flash_func(TM_EXTI_Handler_4)(void) { if(ExtCurrentConfig[Option.INT4pin] == EXT_PER_IN) { if(--INT4Timer <= 0) { INT4Value = INT4Count; INT4Timer = INT4InitTimer; INT4Count = 0; } } else { if(CFuncInt4) CallCFuncInt4(); // Hardware interrupt 2 for a CFunction (see CFunction.c) else INT4Count++; } } void MIPS16 __not_in_flash_func(IRHandler)(void) { int ElapsedMicroSec; static unsigned int LastIrBits; ElapsedMicroSec = readIRclock(); switch(IrState) { case IR_WAIT_START: writeIRclock(0); // reset the timer IrState = IR_WAIT_START_END; // wait for the end of the start bit break; case IR_WAIT_START_END: if(ElapsedMicroSec > 2000 && ElapsedMicroSec < 2800) IrState = SONY_WAIT_BIT_START; // probably a Sony remote, now wait for the first data bit else if(ElapsedMicroSec > 8000 && ElapsedMicroSec < 10000) IrState = NEC_WAIT_FIRST_BIT_START; // probably an NEC remote, now wait for the first data bit else { IrReset(); // the start bit was not valid break; } IrCount = 0; // count the bits in the message IrBits = 0; // reset the bit accumulator writeIRclock(0); // reset the timer break; case SONY_WAIT_BIT_START: if(ElapsedMicroSec < 300 || ElapsedMicroSec > 900) { IrReset(); break; } writeIRclock(0); // reset the timer IrState = SONY_WAIT_BIT_END; // wait for the end of this data bit break; case SONY_WAIT_BIT_END: if(ElapsedMicroSec < 300 || ElapsedMicroSec > 1500 || IrCount > 20) { IrReset(); break; } IrBits |= (ElapsedMicroSec > 900) << IrCount; // get the data bit IrCount++; // and increment our count writeIRclock(0); // reset the timer IrState = SONY_WAIT_BIT_START; // go back and wait for the next data bit break; case NEC_WAIT_FIRST_BIT_START: if(ElapsedMicroSec > 2000 && ElapsedMicroSec < 2500) { IrBits = LastIrBits; // key is held down so just repeat the last code IrCount = 32; // and signal that we are finished IrState = NEC_WAIT_BIT_END; break; } else if(ElapsedMicroSec > 4000 && ElapsedMicroSec < 5000) IrState = NEC_WAIT_BIT_END; // wait for the end of this data bit else { IrReset(); // the start bit was not valid break; } writeIRclock(0); // reset the timer break; case NEC_WAIT_BIT_START: if(ElapsedMicroSec < 400 || ElapsedMicroSec > 1800) { IrReset(); break; } IrBits |= (ElapsedMicroSec > 840) << (31 - IrCount);// get the data bit LastIrBits = IrBits; IrCount++; // and increment our count writeIRclock(0); // reset the timer IrState = NEC_WAIT_BIT_END; // wait for the end of this data bit break; case NEC_WAIT_BIT_END: if(ElapsedMicroSec < 400 || ElapsedMicroSec > 700) { IrReset(); break; } if(IrCount == 32) break; writeIRclock(0); // reset the timer IrState = NEC_WAIT_BIT_START; // go back and wait for the next data bit break; } } void __not_in_flash_func(gpio_callback)(uint gpio, uint32_t events) { #ifndef USBKEYBOARD static uint64_t data; data=gpio_get_all64(); if(Option.KEYBOARD_CLOCK) if( !(Option.KeyboardConfig == NO_KEYBOARD || Option.KeyboardConfig == CONFIG_I2C ) && gpio==PinDef[Option.KEYBOARD_CLOCK].GPno) CNInterrupt(data); if(MOUSE_CLOCK && gpio==PinDef[MOUSE_CLOCK].GPno)MNInterrupt(data); #endif if(gpio==PinDef[IRpin].GPno)IRHandler(); if(gpio==PinDef[Option.INT1pin].GPno)TM_EXTI_Handler_1(); if(gpio==PinDef[Option.INT2pin].GPno)TM_EXTI_Handler_2(); if(gpio==PinDef[Option.INT3pin].GPno)TM_EXTI_Handler_3(); if(gpio==PinDef[Option.INT4pin].GPno)TM_EXTI_Handler_4(); } /* @endcond */