![]() |
Forum Index : Microcontroller and PC projects : Armmite H7: V5.05.02: 1.5MHz ADC
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Quite pleased with this one. ![]() 2018-12-19_054119_Armmite1.3.zip It implements new ADC functionality that can capture up to 3 channels of data in the background at up to 500KHz per channel with user selectable triggering - ideal for zero-crossing detection or similar. The functionality is all driven by the new command ADC To enable the ADCs use the command ADC OPEN frequency, channel1-pin [,channel2-pin] [,channel3-pin] [, interrupt] "frequency" is the sampling frequency in Hz. The maximum frequency is 500KHz. From 320KHz to 500KHz the conversion is 8-bits per channel From 160KHz to 320KHz the conversion is 10-bits per channel From 80KHz to 160KHz the conversion is 12-bits per channel From 40KHz to 80KHz the conversion is 14-bits per channel Below 40KHz conversion is 16-bits per channel This is automatically compensated for in the firmware. "channel1-pin" can be one of 34, 35, 36, 37, 42, 43, 44, 45, 46, 47, 49, 50 "channel2-pin" can be one of 13, 14, 15, 18, 19, 21, 22, 26, 27, 28, 29 "channel3-pin" can be one of 53, 54 The "interrupt" parameter is a normal MMBasic subroutine that can be called when the conversion completes. The ADC is started using the command ADC START channel1array!() [,channel2array!()] [,channel3array!()] The floating point arrays must be the same size and the size will determine the number of samples. Once the start command is issued the ADC(s) will start converting the input signals into the arrays at the frequency specified. If the OPEN command includes an interrupt then the command is non-blocking. If an interrupt is not specified the command is blocking. The samples are returned as floating point values between 0 and VCC. VCC is assumed to be 3.3V but this can be altered using the command "OPTION VCC voltage". This option is reset on reboot. The ADCs can be disabled with the command ADC CLOSE After the OPEN command has been issued the frequency can be adjusted using the command ADC FREQUENCY frequency This command is only allowed if the number of bits calculated in the table above does not change otherwise it will give an error. The new firmware also supports ADC triggering using the command ADC TRIGGER channel, level This should be specified before the ADC START command. The "channel" can be a number between one and three depending on the number of pins specified in the ADC OPEN command. The level can be between -VCC and VCC. A positive number indicates that you are looking for a positive going transition through the specified voltage. A negative number indicates that you are looking for a negative going transition through the specified voltage (as in the example). ![]() Option explicit Option default none Option VCC 3.309 Dim integer i, j CLS ' ' First set up some signals using the onboard DAC ' connect pin 40 to pin 49 and pin 41 to pin 22 ' connect a potentiometer to pin 53 to use as a trigger ' Dim a(799) As float, b(799) As float, t(799) As float, c%(179), d%(179) For i=0 To 179 c%(i)=Sin(Rad(i*2))*1500+2048 d%(i)=i*2000/180+2048 Next i% DAC start 100000,c%(),d%() ' ADC open 100000,49,22,53,adc_done ADC trigger 3,-2.0 ' specify the potentiometer channel to use to trigger with a negative slope through 2.0V ADC start a(), b(), t() Do Loop While j=0 Box 0,0,MM.HRes,MM.VRes Pixel 0, 200-a(0)*50, RGB(magenta) Pixel 0, 470-b(0)*50, RGB(green) For i=1 To 799 Line i-1,200-a(i-1)*50 , i, 200-a(i)*50 , 1, RGB(magenta) Line i-1,470-b(i-1)*50 , i, 470-b(i)*50 , 1, RGB(green) Next i Text MM.HRes\2,MM.VRes\2,"Pre-trigger "+Str$(t(0),1,5)+" Post-trigger "+Str$(t(1),1,5),CM,4 End Sub adc_done j=1 End Sub This release also implements the latest DAC functionality out of the Armmite L4: This allows you to create any arbitrary waveform using the H7's inbuilt DACs and is used in the example above. The syntax is: DAC START frequency, DAC1array%() [,DAC2array%()] DAC1array%() and optional DAC2array%() should contain numbers in the range 0-4095 to suit the 12-bit DACs. The software automatically and separately uses the number of items in each of the arrays to drive the DACs. The frequency is the rate at which the DACs change value. The maximum frequency is 700KHz. So in the example code above there are 180 items in the array c%() which are displayed at a frequency of 100,000 Hz giving a sinewave with a frequency of 100,000/180 = 555Hz. There are 90 items in the array d%() which are displayed at a frequency of 100,000 Hz giving a sinewave with a frequency of 100,000/90 = 1111Hz. The output runs in the background and is stopped using the command. DAC CLOSE |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
Very nice addition. Jim VK7JH MMedit |
||||
KeepIS![]() Guru ![]() Joined: 13/10/2014 Location: AustraliaPosts: 1882 |
What Jim said, this just keeps getting better, thank you again for the brilliant programming and your time and effort. Mike. NANO Inverter: Full download - Only Hex Ver 8.1Ks |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Here is the updated manual with the new commands 2018-12-19_183710_Armmite_H7_Manual.pdf |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
One more tweak ![]() 2018-12-20_025148_Armmite1.3.zip This now includes an FFT command to allow you do do frequency analyses of signals ![]() The basic command FFT has the following syntax: FFT signalarray!(),FFTarray!() "signalarray" must be floating point and the size must be a power of 2 (e.g. s(1023) assuming OPTION BASE is zero) "FFTarray" must be floating point and have dimension 2*N where N is the same as the signal array (e.g. f(1,1023) assuming OPTION BASE is zero) The command will return the FFT as complex numbers with the real part in f(0,n) and the imaginary part in f(1,n) The inverse command has the syntax: FFT INVERSE FFTarray!(), signalarray!() "FFTarray" must be floating point and have dimension 2*N where N must be a power of 2 (e.g. f(1,1023) assuming OPTION BASE is zero) with the real part in f(0,n) and the imaginary part in f(1,n) "signalarray" must be floating point and the single dimension must be the same as the FFT array The command will return the real part of the inverse transform in "signalarray" Most useful is probably the magnitude command FFT MAGNITUDE signalarray!(),magnitudearray!() "signalarray" must be floating point and the size must be a power of 2 (e.g. s(1023) assuming OPTION BASE is zero) "magnitudearray" must be floating point and the size must be the same as the signal array The command will return the magnitude of the signal at various frequencies according to the formula: frequency at array position N = N * sample_frequency / number_of_samples so if the sample frequency is 10KHz and there are 1024 samples then the frequency associate with the magnitude at "magnitudearray(57)" = 57 * 10000 / 1024 = 557HZ as in the example above NB only the first N/2 values are useful as values after N/2 are beyond the Nyquist frequency and contain no useful information. The final FFT command returns the phase angle at each frequency FFT PHASE signalarray!(),phasearray!() "signalarray" must be floating point and the size must be a power of 2 (e.g. s(1023) assuming OPTION BASE is zero) "phasearray" must be floating point and the size must be the same as the signal array The command will return the phase angle of the signal at various frequencies according to the formula above. The test code I used for the picture is: Option explicit Option default none Option VCC 3.308 Const SAMPLESPERSEC = 10000 Const NSAMPLES = 1024 Const PLOTFREQ = NSAMPLES\512 Dim integer i, j, imax, imax1 Dim float a(NSAMPLES-1) , b(NSAMPLES-1), t(NSAMPLES-1) Dim integer c%(179), d%(179) Dim float m(NSAMPLES-1) , mmax , m1(NSAMPLES-1), mmax1 CLS ' ' First set up some signals using the onboard DAC ' connect pin 40 to pin 49 and pin 41 to pin 22 ' connect a potentiometer to pin 53 to use as a trigger ' For i=0 To 179 c%(i)=Sin(Rad(i*2))*1500+2048 d%(i)=i*2000/180+2048 Next i% ' ' start the DAC ' DAC start 100000,c%(),d%() ' ' convert the signals ' ADC open SAMPLESPERSEC, 49, 22, 53, adc_done ADC trigger 3,-2.0 ADC start a(), b(), t() Do Loop While j=0 ' ' frequency analyse the signals ' FFT magnitude b(),m() FFT magnitude a(),m1() Box 144,0,MM.HRes-288,MM.VRes ' ' find the maximum magnitude of the frequencies ' mmax=0 mmax1=0 For i=1 To NSAMPLES\2-1 If m(i)>mmax Then mmax=m(i) imax=i EndIf If m1(i)>mmax1 Then mmax1=m1(i) imax1=i EndIf Next i Text 5,180,"Peak",,4 Text 5,200,Str$(imax1*SAMPLESPERSEC/NSAMPLES,4,0)+"Hz",,4 Text 5,380,"Peak",,4 Text 5,400,Str$(imax*SAMPLESPERSEC/NSAMPLES,3,0)+"Hz",,4 ' ' plot the samples ' For i=1 To 511 Line i+144, 130 - a(i-1)*40, i+145, 130 - a(i)*40, 1, RGB(magenta) Line i+144, 420 - b(i-1)*50, i+145, 420 - b(i)*50, 1, RGB(green) Next i ' ' plot the frequency analyses ' For i=2 To 511 Line i+144,470-m((i-1)*PLOTFREQ/2)/mmax*100 ,i+146, 470 - m(i*PLOTFREQ/2)/mmax*100 , 1, RGB(yellow) Line i+144,240-m1((i-1)*PLOTFREQ/2)/mmax1*100, i+146, 240 - m1(i*PLOTFREQ/2)/mmax1*100, 1, RGB(yellow) Next i ' End Sub adc_done j=1 End Sub |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6283 |
You don't own a big red suit and go around "Ho Ho Hoing" a lot by any chance? I have a desire to extract the low frequency amplitudes of a gryo sygnal and this is just what I need. It will save having to do the maths on a PC. Jim VK7JH MMedit |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Manual updated with FFT 2018-12-20_201216_Armmite_H7_Manual.pdf |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
Hello forum. EDIT: nope... definitely weirdness... > RUN 1545317428 20-12-2018 14:50:28 20-12-2018 14:50:28 1 1 4 1545317429 20-12-2018 14:50:29 20-12-2018 14:50:29 1 1 4 1545317429 20-12-2018 14:50:29 20-12-2018 14:50:29 1 1 4 1545317429 20-12-2018 14:50:29 20-12-2018 14:50:29 1 1 4 1545317429 20-12-2018 14:50:29 20-12-2018 14:50:29 1 1 4 1545317429 20-12-2018 14:50:29 20-12-2018 14:50:29 1 1 4 1545317429 20-12-2018 14:50:29 20-12-2018 14:50:29 1 1 4 1545317429 20-12-2018 14:50:29 20-12-2018 14:50:29 1 1 4 1545317429 CTRL-C > all normal and as expected, then: > ? now Error: A sub/fun has the same name: NOW > RUN [LIBRARY] Sub FlagSet(bit As Integer) Error: Duplicate name > same prog no longer runs, throwing bogus complaints of duplicate names - code below Option Base 0 Const PE2=1,D56=1,CN9_14=1,CN11_46=1 Const PE3=2,D60=2,CN9_22=2,CN11_47=2 Const PE4=3,D57=3,CN9_16=3,CN11_48=3 Const PE5=4,D58=4,CN9_18=4,CN11_50=4 Const PE6=5,D59=5,CN9_20=5,CN11_62=5 Const PC13=7,CN11_23=7 Const PC14=8,CN11_25=8 Const PC15=9,CN11_27=9 Const PF0=10,D68=10,CN9_21=10,CN11_53=10 Const PF1=11,D69=11,CN9_19=11,CN11_51=11 Const PF2=12,D70=12,CN9_17=12,CN11_52=12 Const PF3=13,A3=13,CN9_7=13,CN12_58=13 Const PF4=14,A8=14,CN10_11=14,CN12_38=14 Const PF5=15,A4=15,CN9_9=15,CN12_36=15 Const PF6=18,CN11_9=18 Const PF7=19,D62=19,CN9_26=19,CN11_11=19 Const PF8=20,CN11_54=20 Const PF9=21,D63=21,CN9_28=21,CN11_56=21 Const PF10=22,A5=22,CN9_11=22,CN12_42=22 Const PH0=23,CN11_29=23 Const PH1=24,CN11_31=24 Const PC0=26,A1=26,CN9_3=26,CN11_38=26 Const PC1=27,CN11_36=27 Const PC2=28,A7=28,CN10_9=28,CN11_35=28 Const PC3=29,A2=29,CN9_5=29,CN11_37=29 Const PA0=34,D32=34,CN10_29=34,CN11_28=34 Const PA1=35,CN11_30=35 Const PA2=36,CN12_35=36 Const PA3=37,A0=37,CN9_1=37,CN12_37=37 Const PA4=40,D24=40,CN7_17=40,CN11_32=40 Const PA5=41,D13=41,CN7_10=41,CN12_11=41 Const PA6=42,D12=42,CN7_12=42,CN12_13=42 Const PA7=43,D11=43,CN7_14=43,CN12_15=43 Const PC4=44,CN12_34=44 Const PC5=45,CN12_6=45 Const PB0=46,D33=46,CN10_31=46,CN11_34=46 Const PB1=47,A6=47,CN10_7=47,CN12_24=47 Const PB2=48,D27=48,CN10_15=48,CN12_22=48 Const PF11=49,CN12_62=49 Const PF12=50,D8=50,CN7_20=50,CN12_59=50 Const PF13=53,D7=53,CN10_2=53,CN12_57=53 Const PF14=54,D4=54,CN10_8=54,CN12_50=54 Const PF15=55,CN12_60=55 Const PG0=56,CN11_59=56 Const PG1=57,D64=57,CN9_30=57,CN11_58=57 Const PE7=58,D41=58,CN10_20=58,CN12_44=58 Const PE8=59,D42=59,CN10_18=59,CN12_40=59 Const PE9=60,D6=60,CN10_4=60,CN12_52=60 Const PE10=63,D40=63,CN10_24=63,CN12_47=63 Const PE11=64,D5=64,CN10_6=64,CN12_56=64 Const PE12=65,D39=65,CN10_26=65,CN12_49=65 Const PE13=66,D3=66,CN10_12=66,CN12_55=66 Const PE14=67,D38=67,CN10_28=67,CN12_51=67 Const PE15=68,CN12_53=68 Const PB10=69,D36=69,CN10_32=69,CN12_25=69 Const PB11=70,D35=70,CN10_34=70,CN12_18=70 Const PB12=73,D19=73,CN7_7=73,CN12_16=73 Const PB13=74,D18=74,CN7_5=74,CN12_30=74 Const PB14=75,CN12_28=75 Const PB15=76,D17=76,CN7_3=76,CN12_26=76 Const PD8=77,CN12_10=77 Const PD9=78,CN11_69=78 Const PD10=79,CN12_65=79 Const PD11=80,D30=80,CN10_23=80,CN12_45=80 Const PD12=81,D29=81,CN10_21=81,CN12_43=81 Const PD13=82,D28=82,CN10_19=82,CN12_41=82 Const PD14=85,D10=85,CN7_16=85,CN12_46=85 Const PD15=86,D9=86,CN7_18=86,CN12_48=86 Const PG2=87,D49=87,CN8_14=87,CN11_42=87 Const PG3=88,D50=88,CN8_16=88,CN11_44=88 Const PG4=89,CN12_69=89 Const PG5=90,CN12_68=90 Const PG6=91,CN12_70=91 Const PG7=92,CN12_67=92 Const PG8=93,CN12_66=93 Const PC6=96,D16=96,CN7_1=96,CN12_4=96 Const PC7=97,D21=97,CN7_11=97,CN12_19=97 Const PC8=98,D43=98,CN8_2=98,CN12_2=98 Const PC9=99,D44=99,CN8_4=99,CN12_1=99 Const PA8=100,CN12_23=100 Const PA9=101,CN12_21=101 Const PA10=102,CN12_33=102 Const PA11=103,CN12_14=103 Const PA12=104,CN12_12=104 Const PA13=105,CN11_13=105 Const PA14=109,CN11_15=109 Const PA15=110,D20=110,CN7_9=110,CN11_17=110 Const PC10=111,D45=111,CN8_6=111,CN11_1=111 Const PC11=112,D46=112,CN8_8=112,CN11_2=112 Const PC12=113,D47=113,CN8_10=113,CN11_3=113 Const PD0=114,D67=114,CN9_25=114,CN11_57=114 Const PD1=115,D66=115,CN9_27=115,CN11_55=115 Const PD2=116,D48=116,CN8_12=116,CN11_4=116 Const PD3=117,D55=117,CN9_10=117,CN11_40=117 Const PD4=118,D54=118,CN9_8=118,CN11_39=118 Const PD5=119,D53=119,CN9_6=119,CN11_41=119 Const PD6=122,D52=122,CN9_4=122,CN11_43=122 Const PD7=123,D51=123,CN9_2=123,CN11_45=123 Const PG9=124,D0=124,CN10_16=124,CN11_63=124 Const PG10=125,CN11_66=125 Const PG11=126,CN11_70=126 Const PG12=127,CN11_65=127 Const PG13=128,CN11_68=128 Const PG14=129,D1=129,CN10_14=129,CN12_61=129 Const PG15=132,CN11_64=132 Const PB3=133,D23=133,CN7_15=133,CN12_31=133 Const PB4=134,D25=134,CN7_19=134,CN12_27=134 Const PB5=135,D22=135,CN7_13=135,CN12_29=135 Const PB6=136,D26=136,CN10_13=136,CN12_17=136 Const PB7=137,CN11_21=137 Const PB8=139,D15=139,CN7_2=139,CN12_3=139 Const PB9=140,D14=140,CN7_4=140,CN12_5=140 Const PE0=141,D34=141,CN10_33=141,CN12_64=141 Const PE1=142,CN11_61=142 Dim Integer TMRctr(9),TMRini(9) Dim Integer n,Flags Select Case MM.DEVICE$ Case "Micromite MkII" FlagSet(63)'62 is the pin count 1=44pin Case "ARMmite H7" FlagSet(61) End Select n=0: dir=0 do Print unixtime(now()),humantime(unixtime(now())),now(),IsDate(date$),IsTime(time$), DoW(Now()) 'If FlagTest(63)=0 then PORT(PB14,1,PB7,1,PB0,1)= 2^n loop Sub FlagSet(bit As Integer) Flags=Flags Or (2^bit) End Sub Sub FlagRes(bit As Integer) Flags=(Flags Or (2^bit)) Xor (2^bit) End Sub Function FlagTest(bit As Integer) As Integer FlagTest=Abs(Sgn(Flags And (2^bit))) End Function Function ZPad$(x As integer,y As integer) 'adds y leading zeros to X ZPad$=Right$(String$(y,"0")+Str$(x),y) End Function Function Split(a$,b$) As Integer' returns the number of dimensions in SP$ always starts from 1 regardless of OPTION BASE Local INTEGER z,n,m If b$="" Then Split=0:Exit Function ' can't split with an empty delimiter ' if SP$ doesn't exist, the ERASE will cause an error, choose which ON ERROR SKIP you need 'MM.Ver <5.04 ' ON ERROR SKIP or 'MM.Ver >=5.04 On ERROR SKIP 1 Erase SP$ z=1:n=0 Do 'count instances of delimiter for DIM SP$() z=Instr(z,a$,b$) If z=0 Then If n=0 Then ' no delimeters Dim SP$(1):SP$(1)=a$:Split=1:Exit Function ' only one substring Else Exit Do End If Else n=n+1:z=z+Len(b$) End If Loop m=n+1:n=1 Dim SP$(m) Do z=Instr(1,a$,b$) If z=0 Then SP$(m)=a$:Exit Do Else SP$(n)=Left$(a$,z-1):a$=Mid$(a$,z+Len(b$)):n=n+1 End If Loop Split=m End Function 'regexp, case sensitive Function Match(regex$,text$) ' case sensitive Local s,n,m,f n=Len(regex$):m=Len(text$) Match=0 If Mid$(regex$,1,1)="^" Then MatchHere regex$,text$,2,1,n,m,f Match=f Else For s=1 To m MatchHere regex$,text$,1,s,n,m,f If f Then Match=s: Exit For Next EndIf End Function Sub MatchHere(regex$,text$,r,s,n,m,f) Local i Do While r <= n If Mid$(regex$,r)="$" Then f=s>m: Exit Sub If Mid$(regex$,r,1)="[" Then i=Instr(r+2,regex$,"]") If i Then i=i+1 Else i=r+1 ElseIf Mid$(regex$,r,1)="\" Then i=r+2 Else i=r+1 EndIf If Mid$(regex$,i,1)="*" Then MatchStar regex$,text$,r,i,s,n,m,f Exit Sub EndIf If Mid$(regex$,i,1)="?" Then MatchOptional regex$,text$,r,i,s,n,m,f Exit Sub EndIf If s>m Then f=0: Exit Sub i=r MatchChar regex$,text$,r,s,f If Not f Then Exit Sub If Mid$(regex$,r+1,1)="+" Then MatchStar regex$,text$,i,r+1,s+1,n,m,f Exit Sub EndIf r=r+1: s=s+1 Loop f=1 End Sub Sub MatchStar(regex$,text$,r,i,s,n,m,f) Do MatchHere regex$,text$,i+1,(s),n,m,f If f or s>m Then Exit Sub MatchChar regex$,text$,(r),s,f If Not f Then Exit Sub s=s+1 Loop End Sub Sub MatchOptional(regex$,text$,r,i,s,n,m,f) MatchHere regex$,text$,i+1,(s),n,m,f If f or s>m Then Exit Sub MatchChar regex$,text$,(r),s,f If Not f Then Exit Sub MatchHere regex$,text$,i+1,s+1,n,m,f End Sub Sub MatchChar(regex$,text$,r,s,f) Local i,j f=Mid$(regex$,r,1)="." If f Then Exit Sub If Mid$(regex$,r,1)="[" Then i=Instr(r+2,regex$,"]") If i Then j=Instr(r+1,regex$,Mid$(text$,s,1)) f=j>0 And j<i:r=i Exit Sub EndIf ElseIf Mid$(regex$,r,1)=Chr$(92) Then r=r+1 EndIf f=Mid$(regex$,r,1)=Mid$(text$,s,1) End Sub Function Now(opt as Integer) as string Local a$ Do ' ensure the date/time doesn't change while we are processing a$=Date$+" "+Time$ Now=Date$+" "+Time$ Loop While a$<>Now If opt<>0 then Now=Mid$(a$,7,4)+Mid$(a$,3,4)+Left$(a$,2)+Mid$(a$,11) EndIf End Function Function DayLight(dt$,opt as integer) As Integer 'opt = 1, return daytime start, 2, return daytime end anything else return bool of daytime now Local Integer mn,st,fn,st0,fn0,dd,mm dd=DatePart("dd",dt$):mm=DatePart("mm",dt$) Do Select Case mm Case 1:st=490:fn=960 Case 2:st=460:fn=1010 Case 3:st=405:fn=1060 Case 4:st=335:fn=1115 Case 5:st=275:fn=1165 Case 6:st=230:fn=1210 Case 7:st=230:fn=1220 Case 8:st=265:fn=1190 Case 9:st=315:fn=1115 Case 10:st=360:fn=1060 Case 11:st=415:fn=990 Case 12:st=470:fn=955 Case 13:st=490:fn=960 End Select If fn0<>0 Then Exit Do fn0=fn:st0=st mm=mm+1 Loop st=st0-(((st0-st)/30)*dd):fn=fn0-(((fn0-fn)/30)*dd) Select Case opt Case 1 DayLight=st Case 2 DayLight=fn Case Else mn=(DatePart("h",dt$)*60)+DatePart("m",dt$) DayLight=(mn>=st) And (mn<fn) End Select End Function Function UnixTime(HHT$,opt) As integer ' seconds since 01-01-1970. no checks on the argument format ' HT$ is DD-MM-YYYY HH:MM:SS or if opt=1 HT$ is YYYY-MM-DD HH:MM:SS ' Now() returns a suitable string Local integer n,s,y,m Local String DD$,TT$,HT$ HT$=HHT$' preserves the original argument m=Split(HT$," ") If m<>2 Then UnixTime=-1:Exit Function DD$=SP$(1):TT$=SP$(2) m=Split(DD$,"-") If m<>3 Then UnixTime=-1:Exit Function If opt=0 Then y=Val(SP$(3)) Else y=Val(SP$(1)) EndIf s=0 For n=1970 To y-1 s=s+365+IsLeapYear(n) Next For n=1 To Val(SP$(2))-1 Select Case n Case 1,3,5,7,8,10 s=s+31 Case 2 s=s+28+IsLeapYear(y) Case 4,6,9,11 s=s+30 End Select Next If opt=0 Then s=86400*(s+Val(SP$(1))-1) Else s=86400*(s+Val(SP$(3))-1) EndIf m=Split(TT$,":") If m<>3 Then UnixTime=-1:Exit Function s=s+(3600*Val(SP$(1))) + (60*Val(SP$(2))) + Val(SP$(3)) UnixTime=s End Function Function IsLeapYear(n As integer) As integer IsLeapYear=((n Mod 4=0) And (n Mod 100 <>0)) Or (n Mod 400=0) End Function Function HumanTime(UUT As Integer,opt As Integer) As String ' take seconds since 1970-01-01 (unixtime) and converts to a human form date/time as ' if opt=0 (or not specified) the format is dd-mm-yyyy hh:mm:ss to match the format of DATE$ ' if opt<>0 the date part is returned as yyyy-mm-dd Local integer d,m,s,y,z,UT UT=UUT' preserves the original argument If UT<0 Then HumanTime$="":Exit Function y=1970:d=UT\86400:s=UT Mod 86400 Do z=365+IsLeapYear(y) If d>=z Then d=d-z:y=y+1 Else Exit Do EndIf Loop 'here, Y is the current year and d the remaining days m=1' start at january ' days between the start of the year and the current month Do z=0 Select Case m Case 1,3,5,7,8,10 If d>=31 Then d=d-31:z=1 Case 2 If IsLeapYear(y)Then If d>=29 Then d=d-29:z=1 Else If d>=28 Then d=d-28:z=1 EndIf Case 4,6,9,11 If d>=30 Then d=d-30:z=1 End Select If z=1 Then m=m+1 Else d=d+1:Exit Do 'first day is 1 not 0 EndIf Loop If opt<>0 Then HumanTime$=Str$(y)+"-"+ZPad$(m,2)+"-"+ZPad$(d,2) Else HumanTime$=ZPad$(d,2)+"-"+ZPad$(m,2)+"-"+Str$(y) EndIf y=s\3600:s=s-y*3600 m=s\60:s=s-m*60 HumanTime$=HumanTime$+" "+ZPad$(y,2)+":"+ZPad$(m,2)+":"+ZPad$(s,2) End Function Function DoW(d$) As Integer '0=Sun DoW=(4+DateDiff("dd","01-01-1970 00:00:00",d$)) mod 7 End Function Function DateAdd(Num As Integer,Interval As String,dt As String) As String 'return a string of the datetime with the relevant period added 'add -ve to subtract e.g. 'DateAdd (2,"mm",Now()) returns the datetime time two months from now. 'DateAdd(-1000,"dd",Now()) returns the datetime a thousand days ago Local Integer x,y,z Select Case LCase$(Interval) Case "s"' Seconds DateAdd=HumanTime(UnixTime(dt)+Num) Case "m"' Minutes DateAdd=HumanTime(UnixTime(dt)+(Num*60)) Case "h"' Hours DateAdd=HumanTime(UnixTime(dt)+(Num*3600)) Case "dd" 'Days DateAdd=HumanTime(UnixTime(dt)+(Num*86400)) Case "w" 'Weeks DateAdd=HumanTime(UnixTime(dt)+(Num*604800)) Case "mm"' calendar Months x=Val(Mid$(dt,4,2))-1: y=Val(Mid$(dt,7,4)): z=Val(Left$(dt,2)) x=((x+Num) Mod 12)+1: y=y+Num\12 If (x=2 And z=29) And (Not IsLeapYear(y)) Then ' bludgeon for 29/02 in non-leap year x=3:z=1 EndIf DateAdd=ZPad$(z,2)+"-"+ZPad$(Abs(x),2)+"-"+Zpad$(y,4)+ Right$(dt$,9) Case "yyyy"' Years x=Val(Left$(dt,2)): y=Val(Mid$(dt,4,2)): z=Val(Mid$(dt,7,4)): z=z+num If (y=2 And x=29) And (Not IsLeapYear(z)) Then ' bludgeon for 29/02 in non-leap year y=3:x=1 EndIf DateAdd=ZPad$(x,2)+"-"+ZPad$(Abs(y),2)+"-"+Zpad$(z,4)+ Right$(dt$,9) Case Else DateAdd="" End Select End Function Function DateDiff(Interval As String,dt1 As String,dt2 As String) As Integer 'return the number of whole intervals between two dates 'Result is +ve when DT1<DT2 'DateDiff ("dd","01/02/2001",Now()) returns the difference in whole days since 1st Feb 2001 Local Integer n,s,t,u,v,x,y,z Select Case LCase$(Interval) Case "s"' Seconds DateDiff=UnixTime(dt2)-UnixTime(dt1) Case "m"' Minutes DateDiff=(UnixTime(dt2)-UnixTime(dt1))\60 Case "h"' Hours DateDiff=(UnixTime(dt2)-UnixTime(dt1))\3600 Case "dd" 'Days DateDiff=(UnixTime(dt2)-UnixTime(dt1))\86400 Case "w" 'Weeks DateDiff=(UnixTime(dt2)-UnixTime(dt1))\604800 Case "mm"' calendar Months t=UnixTime(dt1):u=UnixTime(dt2):s=Sgn(u-t) If s Then dt1=HumanTime(Min(t,u)):dt2=HumanTime(Max(t,u)) t=Val(Left$(dt1,2)):u=Val(Mid$(dt1,4,2)):v=Val(Mid$(dt1,7,4)) x=Val(Left$(dt2,2)):y=Val(Mid$(dt2,4,2)):z=Val(Mid$(dt2,7,4)) for n=v+1 to z DateDiff=DateDiff+12 next DateDiff=DateDiff+(y-u) If t>x then DateDiff=DateDiff-1 EndIf DateDiff=DateDiff*s Case "yyyy"' Years t=UnixTime(dt1):u=UnixTime(dt2):s=Sgn(u-t) If s Then dt1=HumanTime(Min(t,u)):dt2=HumanTime(Max(t,u)) t=Val(Left$(dt1,2)):u=Val(Mid$(dt1,4,2)):v=Val(Mid$(dt1,7,4)) x=Val(Left$(dt2,2)):y=Val(Mid$(dt2,4,2)):z=Val(Mid$(dt2,7,4)) DateDiff=z-v If u>y Then DateDiff=DateDiff-1 ElseIf u=y Then If t>x Then DateDiff=DateDiff-1 EndIf EndIf DateDiff=DateDiff*s Case Else DateDiff=0 End Select End Function Function DatePart(Interval As String,dt As String) As Integer Select Case LCase$(Interval) Case "s"' Seconds DatePart=Val(Right$(dt,2)) Case "m"' Minutes DatePart=Val(Mid$(dt,15,2)) Case "h"' Hours DatePart=Val(Mid$(dt,12,2)) Case "dd" 'Days DatePart=Val(Left$(dt,2)) Case "mm"' calendar Month DatePart=Val(Mid$(dt,4,2)) Case "yyyy"' Year DatePart=Val(Mid$(dt,7,4)) Case Else DatePart=0 End Select End Function Function IsTime(t$) As Integer ' times must be hh:mm:ss IsTime=0 If Match("^[012][0123456789]:[012345][0123456789]:[012345][0123456789]$",t$) Then If Val(Left$(t$,2))<24 Then If Val(Mid$(t$,4,2))<60 Then If Val(Right$(t$,2))<60 Then IsTime=1 EndIf EndIf EndIf EndIf End Function Function IsDate(t$,opt As Integer) As Integer Local Integer d,m,y IsDate=0 If opt=0 then If Match("^[0123][0123456789][/|-][01][0123456789][/|-][12][0123456789][0123456789][0123456789]$",t$)=0 Then Exit Function d=Val(Left$(t$,2)) m=Val(Mid$(t$,4,2)) y=Val(Right$(t$,4)) Else If Match("^[12][0123456789][0123456789][0123456789][/|-][01][0123456789][/|-][0123][0123456789]$",t$)=0 Then Exit Function d=Val(Right$(t$,2)) m=Val(Mid$(t$,6,2)) y=Val(Left$(t$,4)) EndIf Select Case m Case 1,3,5,7,8,10,12 if d<1 or d>31 Then Exit Function Case 4,6,9,11 if d<1 or d>30 Then Exit Function Case 2 if d<1 or d>28+IsLeapYear(y) Then Exit Function End Select IsDate=1 End Function |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Re-written version of the FFT algorithm now takes between 20 and 50% of previous time (data dependent). Danielson-Lanczo rather than recursive. 2018-12-21_014946_Armmite1.3.zip |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
hmmm... it seems that once an error is thrown it gets locked up: ( a reset restores functionality): > ARMmite MMBasic Version 5.05.02 Copyright 2011-2018 Geoff Graham Copyright 2016-2018 Peter Mather > run 1545317860 20-12-2018 14:57:41 20-12-2018 14:57:41 1 1 4 1545317861 20-12-2018 14:57:41 20-12-2018 14:57:41 1 1 4 1545317861 20-12-2018 14:57:41 20-12-2018 14:57:41 1 1 4 1545317861 20-12-2018 14:57:41 20-12-2018 14:57:41 1 1 4 1545317861 20-12-2018 14:57:41 20-12-2018 14:57:41 1 1 4 1545317861 20-12-2018 14:57:41 20-12-2018 14:57:41 1 1 4 1545317861 20-12-2018 14:57:41 20-12-2018 14:57:41 1 1 > ? now() 20-12-2018 14:57:51 > run 1545317874 20-12-2018 14:57:55 20-12-2018 14:57:55 1 1 4 1545317875 20-12-2018 14:57:55 20-12-2018 14:57:55 1 1 4 1545317875 20-12-2018 14:57:55 20-12-2018 14:57:55 1 1 4 1545317875 20-12-2018 14:57:55 20-12-2018 14:57:55 1 1 4 1545317875 20-12-2018 14:57:55 20-12-2018 14:57:55 1 1 > ? now Error: A sub/fun has the same name: NOW > run [LIBRARY] Sub FlagSet(bit As Integer) Error: Duplicate name > RUN [LIBRARY] Sub FlagSet(bit As Integer) Error: Duplicate name > > ARMmite MMBasic Version 5.05.02 Copyright 2011-2018 Geoff Graham Copyright 2016-2018 Peter Mather > RUN 1545317906 20-12-2018 14:58:26 20-12-2018 14:58:26 1 1 4 1545317906 20-12-2018 14:58:26 20-12-2018 14:58:26 1 1 4 1545317906 20-12-2018 14:58:26 20-12-2018 14:58:26 1 1 4 1545317906 20-12-2018 14:58:26 20-12-2018 14:58:26 1 1 4 1545317906 > but any error... > ? 1.3/0 Error: Divide by zero > RUN [LIBRARY] Sub FlagSet(bit As Integer) Error: Duplicate name > |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
I think this fixes it 2018-12-21_031540_Armmite1.3.zip It isn't a new bug but one that was introduced when I did the upgrade to Geoff's 5.05.01 code |
||||
CaptainBoing![]() Guru ![]() Joined: 07/09/2016 Location: United KingdomPosts: 2170 |
yep that seems to have nailed it. Thanks Peter |
||||
lizby Guru ![]() Joined: 17/05/2016 Location: United StatesPosts: 3378 |
If I have gotten the syntax right, it appears that the "interrupt on character" feature added to the serial OPEN command by Geoff with Micromite MMBasic Ver 5.05.02 Beta has not been migrated to the H7. > open "com4:115200,1024,simfileInterrupt,=13" as #10 Error: Syntax > Open "com4:115200,1024,simfileInterrupt,13" As #10 > close 10 > The second instance, which doesn't have a syntax error, interrupts after 13 characters. The first is intended to interrupt on CR. Would it be convenient to add this? PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
Geoff doesn't release source of Betas so I can't include it until the next release |
||||
lizby Guru ![]() Joined: 17/05/2016 Location: United StatesPosts: 3378 |
Ok. I think this does what I want without an interrupt (following Grogster and CaptainBoing). [code] dim string serinLine, inB$ open "com4:115200,2048" as #10 do if loc(#10) > 0 then ' character has arrived pause 10 ' lots of characters at 115200 baud do inB$ = Input$(1, #10) if inB$ <> chr$(13) and len(serinLine)<255 then serinLine = serinLine + inB$ loop while loc(#10) <> 0 and inB$ <> chr$(13) print serinLine serinLine="" endif loop [/code] Slightly different code should fold into my program. PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
lizby Guru ![]() Joined: 17/05/2016 Location: United StatesPosts: 3378 |
I'm looking to use pin 20 on the H7 (with backpack). setpin 20,din says it's not available: > print mm.ver,mm.device$ 5.0503 ARMmite H7 > list > setpin 20,din Error: Pin 20 is reserved on startup > The H7 manual indicates it should be. 20 ANALOG_C DIGITAL_IN DIGITAL_OUT SPI5-IN I'm trying to just use pins on Connectors 8 & 9 on the H7. Should this pin be available? Pins 19 & 21 are likewise reserved. Is SPI5 reserved or should the pins be available for general usage? PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10315 |
On the Armmite H7 SPI5 is used for SPI displays, touch and SD cards so if you have any of those configured then the pin will not be available for other use. OPTION RESET and the pin should be available. |
||||
lizby Guru ![]() Joined: 17/05/2016 Location: United StatesPosts: 3378 |
Ok. I'm using the SD card on an SSD1963_4, so I guess that makes 19,20,21 unavailable. Fortunately, I haven't used 115 or 26 yet (CN9_27 & CN9_29), so I can use 115 and still have a pin to spare. After (limited) testing, that works with all the pins on CN8 & CN9 allocated except 26. PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |