![]() |
Forum Index : Microcontroller and PC projects : MM2: PS2 keyboard input Cfunction
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10209 |
Here is a demo program using a Cfunction to read the output of a standard PS2 keyboard. The codes sent are given in this document The Cfunction and demo program are attached: option explicit option default none cpu 48 ' 28 pin setpin 9,din ' these pins fixed to match the Cfunction - KB clock setpin 10,din ' KB data ' 44 pin 'setpin 30,din ' these pins fixed to match the Cfunction - KB clock 'setpin 31,din ' KB data ' dim integer i dim s$ length 3 do i=ps2(s$,1000,48) 'String to receive KB data, timeout in msec, CPU speed in MHz if i=0 then print "timeout" if i=1 then print hex$(asc(left$(s$,1))) if i=2 then print hex$(asc(left$(s$,1))),hex$(asc(mid$(s$,2,1))) if i=3 then print hex$(asc(left$(s$,1))),hex$(asc(mid$(s$,2,1))),hex$(asc(righ t$(s$,1))) loop ' CFunction ps2 00000000 27bdff60 8ca50000 03a03821 27a300a0 03a01021 ac400000 24420004 5443fffe ac400000 34038010 3c02bf80 ac430600 8cc90004 240803e8 8cc20000 00480019 00001012 00001810 71283002 00c34021 05010005 01001821 24460007 00c2182b 00c01021 00681821 00031f40 000210c2 10a000ae 00623025 3c03bf80 3c08bf88 ac600610 8d026020 30420004 10400005 00000000 8c620610 0046102b 1440fff9 00000000 8c620610 0046102b 14400007 00000000 24a5ffff 14a0fff1 00000000 00002021 1000009e 00002821 10a0009a 3c03bf88 8c626020 30420004 1040fffd 3c02bf80 ac400610 00e04021 00003021 24090028 10000025 3c05bf88 ac400610 8ca36020 30630004 10600005 00000000 8c430610 2c632ee0 1460fff9 00000000 8c430610 2c632ee0 50600020 2402000a ac400610 8c430610 2c63000a 1460fffd 00000000 8ca36020 7c6300c0 ad030000 24c60001 ac400610 8ca36020 30630004 14600005 00000000 8c430610 2c630190 1460fff9 00000000 8c430610 2c630190 54600001 ac400610 25080004 8c430610 2c632ee0 50600005 2402000a 14c9ffd7 00000000 10000012 24020015 14c20010 24020015 24020001 a0820000 a0800001 00001821 00001021 24060008 8ce50000 00452804 00651825 306300ff 24420001 1446fffa 24e70004 1000004c a0830001 14c2001e 24020020 24020002 a0820000 a0800001 a0800002 00001821 00001021 24060008 8ce50000 00452804 00651825 306300ff 24420001 1446fffa 24e70004 a0830001 90850002 27a3002c 00001021 24070008 8c660000 00463004 00a62825 30a500ff 24420001 1447fffa 24630004 a0850002 1000002e 24020002 14c2002c 00001021 24020003 a0820000 a0800001 a0800002 a0800003 00001821 00001021 24060008 8ce50000 00452804 00651825 306300ff 24420001 1446fffa 24e70004 a0830001 90850002 27a3002c 00001021 24070008 8c660000 00463004 00a62825 30a500ff 24420001 1447fffa 24630004 a0850002 90850003 27a30058 00001021 24070008 8c660000 00463004 00a62825 30a500ff 24420001 1447fffa 24630004 a0850003 10000002 24020003 24020001 00402021 10000006 00002821 00002021 10000003 00002821 00002021 00002821 00801021 00a01821 03e00008 27bd00a0 End CFunction 'long long ps2(unsigned char d[],long long *msec, long long *cpu){ ' #define tmr1con *(volatile unsigned int *)0xbf800600 //timer 1 configuration register ' #define tmr1 *(volatile unsigned int *)0xbf800610 //timer 1 counter ' unsigned int i,j,clockpin=4,datapin=8,log[40],timeout, k=*msec; ' unsigned int volatile * myport; ' myport=(volatile unsigned int *)0xbf886020; ' for(i=0;i<40;i++)log=0; ' tmr1con=0x8010; //turn on with scale 8 ' timeout=(*cpu * 1000/8); //1msec setting for clock ' i=0; ' while (k>0){ ' tmr1=0; ' while((*myport & clockpin)!=0 && tmr1<timeout); ' if(tmr1< timeout) break; ' k--; ' } ' if(k==0) return 0; ' while ((*myport & clockpin)==0); //wait pin to go high after the start bit ' tmr1=0; ' while (tmr1<12000 && i<40){ //loop until a timeout or all data received ' tmr1=0; //reset the timer ' while (((*myport & clockpin)!=0) && (tmr1<12000)); //wait for clock to go low ' if(tmr1<12000){ ' tmr1=0; ' while(tmr1<10); //wait for mid low clock ' log=(*myport & datapin)>>3; ' i++; ' tmr1=0; ' } else break; ' while (((*myport & clockpin)==0) && (tmr1<400)); //wait for clock to go high ' if (tmr1<400) tmr1=0; ' } ' if(i==10){ ' d[0]=1; ' d[1]=0; ' for(j=0;j<8;j++)d[1]|=(log[j]<<j); ' i=1; ' } else if(i==21){ ' d[0]=2; ' d[1]=0; ' d[2]=0; ' for(j=0;j<8;j++)d[1]|=(log[j]<<j); ' for(j=0;j<8;j++)d[2]|=(log[j+11]<<j); ' i=2; ' } else if(i==32){ ' d[0]=3; ' d[1]=0; ' d[2]=0; ' d[3]=0; ' for(j=0;j<8;j++)d[1]|=(log[j]<<j); ' for(j=0;j<8;j++)d[2]|=(log[j+11]<<j); ' for(j=0;j<8;j++)d[3]|=(log[j+22]<<j); ' i=3; ' } else i=0; //invalid pulse string ' return i; '} ' |
||||
Zonker![]() Guru ![]() Joined: 18/08/2012 Location: United StatesPosts: 767 |
Wow... Another Ass kickin CFunction..! The Library keeps growing... Awesome.... I finally got the time this weekend to test the 2.4" touch display you created... Works like a champ..! We can now create small GUI apps with this... More power to the MicroMite..!! ![]() |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9588 |
I can see using this quite a bit, so thanks! ![]() QUESTION: Why did you use COM2 for the KB in the Cfunction, and not just a couple of I/O pins? This gobbles up COM2, and if you are already using it, the KB Cfunction will not work. ![]() I am sure there was a reason, but I would love to know what it was/is..... Serial out ports are no problem with the Cfunction that creates extra serial TXD channels, but if you need the RXD buffers(as I do), then you need both COM ports, and can't use those pins for anything else. EDIT: Will this work on the 470 chip too? If so, which pins?(62 & 63?) Smoke makes things work. When the smoke gets out, it stops! |
||||
cosmic frog Guru ![]() Joined: 09/02/2012 Location: United KingdomPosts: 302 |
Brilliant! All we need now is a cfunction for video out and we have everything. Dave. |
||||
MicroBlocks![]() Guru ![]() Joined: 12/05/2012 Location: ThailandPosts: 2209 |
Video out will never be done with a Cfunction. But look at the many LCD that can be connected and directly used from a cfuntion. I think that is a much better way to use a controller that is meant to be a solution for embedded projects. A big monitor or even a crt is really not a good fit. Also the cheap car video monitors can be replaced with an even cheaper LCD. I think any pin will work as none of the uart functionality is used. It would be great if there is an easy way to have pin numbers as parameters, but without a lot of extra code written in the CFunction i can not see how that is done. Having the C source code you would be able to change it if necessary. Microblocks. Build with logic. |
||||
cosmic frog Guru ![]() Joined: 09/02/2012 Location: United KingdomPosts: 302 |
Is there a link to how the cfunction works or how to make your own cfunction as it just looks like a load of hex to me. Thanks. Dave. |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10209 |
Some people are just never satisfied ![]() OK here is a version that will work on any pins on any of the chips. You have a little bit of work to do though ![]() Thus on the 64-pin MX470 pin 55 is port D07, pin 54 is port D06. To call the Cfunction use 0 for port A, 1 for port B etc. as in the example where D=3.The pin number just needs setting 1:1 i.e. D07 requires the parameters 3,7. I've included a couple of new commands in the MX470 firmware to do this for you and hopefully Geoff will at some point include something similar in the MX170 firmware but to make this code completely portable I'm not using these in the example. The code has been tested on the MX170 and MX470 at speeds from 10-96Mhz - it doesn't work at 5MHz. Note that you need to specify the CPU speed in the call to the Cfunction - this is only used to make the timeout last the correct amount of time. You should use SETPIN x,DIN for the two pins used but actually this isn't essential as the default state of pins after boot is as digital inputs. option explicit
option default none ' change these pins to match the call to the Cfunction setpin 55,din ' KB clock setpin 54,din ' KB data ' dim integer i dim s$ length 3 do i=ps2(s$,1000,48,3,7,3,6) 'String to receive KB data, timeout in msec, CPU speed in MHz, data port number, data pin number, clock port number, clock pin number ' In this example for the 64-pin MX470 the data pin definition is 3,7 (i.e. D07=pin 55) the clock pin definition is 3,6 (i.e D06=pin 54) if i=0 then print "timeout" if i=1 then print hex$(asc(left$(s$,1))) if i=2 then print hex$(asc(left$(s$,1))), hex$(asc(mid$(s$,2,1))) if i=3 then print hex$(asc(left$(s$,1))), hex$(asc(mid$(s$,2,1))), hex$(asc(right$(s$,1))) loop ' CFunction ps2 00000000 27bdffd8 8fa80038 8ca90000 24020001 8fa30040 8c650000 00a22804 8d0a0000 01425004 8ceb0000 000b5a00 3c02bf88 24426020 01625821 8fa3003c 8c670000 00073a00 00e23821 03a01021 27a30028 a0400000 24420001 5443fffe a0400000 34038010 3c02bf80 ac430600 8ccd0004 240c03e8 8cc20000 004c0019 00001012 00001810 71ac3002 00c36021 05810005 01801821 24460007 00c2182b 00c01021 006c1821 00031f40 000210c2 112000aa 00623025 3c03bf80 ac600610 8ce20000 00451024 10400005 00000000 8c620610 0046102b 1440fff9 00000000 8c620610 0046102b 14400007 00000000 2529ffff 1520fff1 00000000 00002021 1000009a 00002821 51200097 00002021 8ce20000 00451024 1040fffd 3c02bf80 ac400610 00003021 10000027 24090028 ac400610 8ce30000 00651824 10600005 00000000 8c430610 2c635dc0 1460fff9 00000000 8c430610 2c635dc0 50600022 2402000a ac400610 8c430610 2c630014 1460fffd 00000000 8d6c0000 03a61821 018a6024 8d0d0000 01ac6006 a06c0000 24c60001 ac400610 8ce30000 00651824 14600005 00000000 8c430610 2c6301f4 1460fff9 00000000 8c430610 2c6301f4 54600001 ac400610 8c430610 2c635dc0 50600005 2402000a 14c9ffd5 00000000 10000012 24020015 14c20010 24020015 24020001 a0820000 a0800001 00001821 00001021 24060008 03a22821 90a50000 00452804 00a31825 24420001 1446fffa 306300ff 10000049 a0830001 14c2001d 24020020 24020002 a0820000 a0800001 a0800002 00001821 00001021 24060008 03a22821 90a50000 00452804 00a31825 24420001 1446fffa 306300ff a0830001 90830002 00001021 24060008 03a22821 90a5000b 00452804 00a31825 24420001 1446fffa 306300ff a0830002 1000002c 24020002 14c2002a 00001021 24020003 a0820000 a0800001 a0800002 a0800003 00001821 00001021 24060008 03a22821 90a50000 00452804 00a31825 24420001 1446fffa 306300ff a0830001 90830002 00001021 24060008 03a22821 90a5000b 00452804 00a31825 24420001 1446fffa 306300ff a0830002 90830003 00001021 24060008 03a22821 90a50016 00452804 00a31825 24420001 1446fffa 306300ff a0830003 10000002 24020003 24020001 00402021 10000005 00002821 00002021 10000002 00002821 00002821 00801021 00a01821 03e00008 27bd0028 End CFunction ' 'long long ps2(unsigned char d[],long long *msec, long long *cpu, unsigned long long *dataportnum,unsigned long long *datapinnum,unsigned long long *clkportnum,unsigned long long *clkpinnum){ ' #define tmr1con *(volatile unsigned int *)0xbf800600 //timer 1 configuration register ' #define tmr1 *(volatile unsigned int *)0xbf800610 //timer 1 counter ' unsigned int index,i,j,timeout, k=*msec; ' unsigned int waitbetweenpackets=24000; ' unsigned int waitforclockpinchange=500; ' i=*clkportnum * 0x100; //port addresses are spaced out at 0x100 intervals ' j=*dataportnum * 0x100; ' unsigned int clockpin=1<<*clkpinnum; //create a mask for the clock pin ' unsigned int datapin=1<<*datapinnum; //create a mask for the data pin ' unsigned char log[40]; ' volatile unsigned int *dataport, *clockport; ' dataport=(volatile unsigned int *)(0xbf886020 + j); //data port read register ' clockport=(volatile unsigned int *) (0xbf886020+ i); //clock port read register ' for(j=0;j<40;j++)log[j]=0; ' tmr1con=0x8010; //turn on with scale 8 ' timeout=(*cpu * 1000/8); //1msec setting for clock ' index=0; ' while (k>0){ ' tmr1=0; ' while((*clockport & clockpin)!=0 && tmr1<timeout); ' if(tmr1< timeout) break; ' k--; ' } ' if(k==0) return 0; ' while ((*clockport & clockpin)==0); //wait pin to go high after the start bit ' tmr1=0; ' while (tmr1<waitbetweenpackets && index<40){ //loop until a timeout or all data received ' tmr1=0; //reset the timer ' while (((*clockport & clockpin)!=0) && (tmr1<waitbetweenpackets)); //wait for clock to go low ' if(tmr1<waitbetweenpackets){ ' tmr1=0; ' while(tmr1<20); //wait for data to be established during low clock ' log[index]=(*dataport & datapin)>>*datapinnum; ' index++; ' tmr1=0; ' } else break; ' while (((*clockport & clockpin)==0) && (tmr1<waitforclockpinchange)); //wait for clock to go high ' if (tmr1<waitforclockpinchange) tmr1=0; ' } ' if(index==10){ ' d[0]=1; ' d[1]=0; ' for(j=0;j<8;j++)d[1]|=(log[j]<<j); ' index=1; ' } else if(index==21){ ' d[0]=2; ' d[1]=0; ' d[2]=0; ' for(j=0;j<8;j++)d[1]|=(log[j]<<j); ' for(j=0;j<8;j++)d[2]|=(log[j+11]<<j); ' index=2; ' } else if(index==32){ ' d[0]=3; ' d[1]=0; ' d[2]=0; ' d[3]=0; ' for(j=0;j<8;j++)d[1]|=(log[j]<<j); ' for(j=0;j<8;j++)d[2]|=(log[j+11]<<j); ' for(j=0;j<8;j++)d[3]|=(log[j+22]<<j); ' index=3; ' } else index=0; //invalid pulse string ' return index; '} ' |
||||
TassyJim![]() Guru ![]() Joined: 07/08/2011 Location: AustraliaPosts: 6269 |
Cfunctions are described in the firmware download for the Micromite Mk2 http://geoffg.net/micromite.html The ZIP includes some example code to get you started. Jim VK7JH MMedit |
||||
G8JCF![]() Guru ![]() Joined: 15/05/2014 Location: United KingdomPosts: 676 |
The CFunction Tutorial, 74 pages, is available from http://www.g8jcf.dyndns.org/mmbasicmkii/MMBasicCFunctions.pd f Peter The only Konstant is Change |
||||
Grogster![]() Admin Group ![]() Joined: 31/12/2012 Location: New ZealandPosts: 9588 |
I did not mean to be a pain. ![]() Being able to specify the pins to use for PS/2 is about as fullproof as you can get, cos then you are not tied to any set of pins - this is very flexable. In your examples, that will be how I am using it(pins 55 and 54 on the 470), as this leaves both COM ports free for my other purposes. I am a high-mileage com-port user! ![]() I certainly did not expect you to re-do the code to allow for this - I was just curious why you elected to use the COM2 pins, really, but this is a far better concept in MHO, cos now you can put the PS/2 keyboard on any pair of pins. ![]() Smoke makes things work. When the smoke gets out, it stops! |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10209 |
I am a low-mileage com-port user! ![]() On the MX470 you could you could "improve" the code as follows: option explicit option default none ' const KBCLOCK=54 const KBDATA=55 ' setpin KBDATA,din ' KB clock setpin KBCLOCK,din ' KB data ' dim integer i dim s$ length 3 do i=ps2(s$, 1000, MM.SPEED\1000000, portnum(KBDATA), pinnum(KBDATA), portnum(KBCLOCK), pinnum(KBCLOCK)) 'String to receive KB data, timeout in msec, CPU speed in MHz, data port number, data pin number, clock port number, clock pin number ' In this example for the 64-pin MX470 the data pin definition is 3,7 (i.e. D07=pin 55) the clock pin definition is 3,6 (i.e D06=pin 54) if i=0 then print "timeout" if i=1 then print hex$(asc(left$(s$,1))) if i=2 then print hex$(asc(left$(s$,1))), hex$(asc(mid$(s$,2,1))) if i=3 then print hex$(asc(left$(s$,1))), hex$(asc(mid$(s$,2,1))), hex$(asc(right$(s$,1))) loop ' function portnum(ppin as integer)as integer portnum=(portaddr(ppin)-&HBF886000)\&H100 end function |
||||
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |