├── GP.pas ├── A20.pas ├── WatchDog.pas ├── RTC.pas ├── Readme.txt ├── PWM.pas ├── GPIO.pas ├── TP.pas ├── LRADC.pas ├── Timer.pas ├── Clock.pas └── TWI.pas /GP.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的General Purpose底层操作封装类。单例。 3 | 当RTC电池电压大于1.0V时可以保存数据 4 | 作者:tjCFeng 5 | 邮箱:tjCFeng@163.com 6 | 更新日期:2014.12.06 7 | *) 8 | 9 | unit GP; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses SysUtils, A20; 16 | 17 | type 18 | TChannel = 19 | (GP_0, GP_1, GP_2, GP_3, GP_4, GP_5, GP_6, GP_7, 20 | GP_8, GP_9, GP_10, GP_11, GP_12, GP_13, GP_14, GP_15); 21 | 22 | TGP = class 23 | private 24 | class var FInstance: TGP; 25 | class function GetInstance: TGP; static; 26 | public 27 | class procedure Release; 28 | class property Instance: TGP read GetInstance; 29 | 30 | private 31 | FGP_BASE: ^LongWord; 32 | 33 | constructor Create; 34 | destructor Destroy; override; 35 | protected 36 | FTMR_GP: TGROUP16_REG; 37 | public 38 | procedure SetGP(Channel: TChannel; Value: LongWord); 39 | function GetGP(Channel: TChannel): LongWord; 40 | public 41 | property TMR_GP: TGROUP16_REG read FTMR_GP; 42 | end; 43 | 44 | implementation 45 | 46 | const 47 | GP_BASE = $01C20D20; 48 | 49 | class function TGP.GetInstance: TGP; 50 | begin 51 | if FInstance = nil then FInstance:= TGP.Create; 52 | Result:= FInstance; 53 | end; 54 | 55 | class procedure TGP.Release; 56 | begin 57 | FreeAndNil(FInstance); 58 | end; 59 | 60 | constructor TGP.Create; 61 | var Base: LongWord; I: Byte; 62 | begin 63 | inherited Create; 64 | 65 | FGP_BASE:= TA20.Instance.GetMMap(GP_BASE); 66 | Base:= LongWord(FGP_BASE) + TA20.Instance.BaseOffset(GP_BASE); 67 | 68 | for I:= 0 to 15 do FTMR_GP[I]:= Pointer(Base + I * $04); 69 | end; 70 | 71 | destructor TGP.Destroy; 72 | begin 73 | TA20.Instance.FreeMMap(FGP_BASE); 74 | 75 | inherited Destroy; 76 | end; 77 | 78 | procedure TGP.SetGP(Channel: TChannel; Value: LongWord); 79 | begin 80 | FTMR_GP[Ord(Channel)]^:= Value; 81 | end; 82 | 83 | function TGP.GetGP(Channel: TChannel): LongWord; 84 | begin 85 | Result:= FTMR_GP[Ord(Channel)]^; 86 | end; 87 | 88 | 89 | finalization 90 | TGP.Instance.Release; 91 | 92 | end. 93 | -------------------------------------------------------------------------------- /A20.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的地址映射封装类。 3 | 单例,请勿在程序中使用。 4 | 作者:tjCFeng 5 | 邮箱:tjCFeng@163.com 6 | 更新日期:2014.12.06 7 | *) 8 | 9 | unit A20; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses Unix, BaseUnix, SysUtils; 16 | 17 | type 18 | TGROUP1_REG = ^LongWord; 19 | TGROUP2_REG = array [0..1] of ^LongWord; 20 | TGROUP4_REG = array [0..3] of ^LongWord; 21 | TGROUP5_REG = array [0..4] of ^LongWord; 22 | TGROUP6_REG = array [0..5] of ^LongWord; 23 | TGROUP16_REG = array [0..15] of ^LongWord; 24 | 25 | type 26 | TA20 = class 27 | private 28 | class var FInstance: TA20; 29 | class function GetInstance: TA20; static; 30 | public 31 | class procedure Release; 32 | class property Instance: TA20 read GetInstance; 33 | 34 | private 35 | FhMEM: Integer; 36 | constructor Create; 37 | destructor Destroy; override; 38 | public 39 | function GetMMap(BaseAddr: LongWord): PLongWord; 40 | function BaseOffset(BaseAddr: LongWord): LongWord; 41 | procedure FreeMMap(MMapAddr: PLongWord); 42 | end; 43 | 44 | implementation 45 | 46 | const 47 | PAGE_SIZE = 4096; 48 | BLOCK_SIZE = 4096; 49 | 50 | class function TA20.GetInstance: TA20; 51 | begin 52 | if FInstance = nil then FInstance:= TA20.Create; 53 | Result:= FInstance; 54 | end; 55 | 56 | class procedure TA20.Release; 57 | begin 58 | FreeAndNil(FInstance); 59 | end; 60 | 61 | constructor TA20.Create; 62 | begin 63 | inherited Create; 64 | 65 | FhMEM:= fpopen('/dev/mem', O_RdWr); 66 | if (FhMEM < 0) then Exit; 67 | end; 68 | 69 | destructor TA20.Destroy; 70 | begin 71 | fpclose(FhMEM); 72 | 73 | inherited Destroy; 74 | end; 75 | 76 | function TA20.GetMMap(BaseAddr: LongWord): PLongWord; 77 | var MEM: LongWord; 78 | begin 79 | MEM:= (BaseAddr and $FFFFF000) div PAGE_SIZE; 80 | Result:= fpMmap(nil, PAGE_SIZE, PROT_READ or PROT_WRITE, MAP_SHARED, FhMem, MEM); 81 | end; 82 | 83 | function TA20.BaseOffset(BaseAddr: LongWord): LongWord; 84 | begin 85 | Result:= (BaseAddr and $00000FFF); 86 | end; 87 | 88 | procedure TA20.FreeMMap(MMapAddr: PLongWord); 89 | begin 90 | if (MMapAddr <> nil) then fpMUnmap(MMapAddr, PAGE_SIZE); 91 | end; 92 | 93 | 94 | finalization 95 | TA20.Instance.Release; 96 | 97 | end. 98 | -------------------------------------------------------------------------------- /WatchDog.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的WatchDog底层操作封装类。单例。 3 | 作者:tjCFeng 4 | 邮箱:tjCFeng@163.com 5 | 更新日期:2014.12.06 6 | *) 7 | 8 | unit WatchDog; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses SysUtils, A20, Clock; 15 | 16 | type 17 | TInterval = (S0_5, S1, S2, S3, S4, S5, S6, S8, S10, S12, S14, S16); 18 | 19 | TWDOG = class 20 | private 21 | class var FInstance: TWDOG; 22 | class function GetInstance: TWDOG; static; 23 | public 24 | class procedure Release; 25 | class property Instance: TWDOG read GetInstance; 26 | 27 | private 28 | FWDOG_BASE: ^LongWord; 29 | 30 | constructor Create; 31 | destructor Destroy; override; 32 | 33 | procedure SetInterval(Value: TInterval); 34 | function GetInterval: TInterval; 35 | 36 | procedure SetForceRestart(Value: Boolean); 37 | function GetForceRestart: Boolean; 38 | protected 39 | FWDOG_CTRL: TGROUP1_REG; 40 | FWDOG_MODE: TGROUP1_REG; 41 | public 42 | procedure Start; 43 | procedure Stop; 44 | procedure Reset; 45 | public 46 | property Interval: TInterval read GetInterval write SetInterval; 47 | property ForceRestart: Boolean read GetForceRestart write SetForceRestart; 48 | property WDOG_CTRL: TGROUP1_REG read FWDOG_CTRL; 49 | property WDOG_MODE: TGROUP1_REG read FWDOG_MODE; 50 | end; 51 | 52 | implementation 53 | 54 | const 55 | WDOG_BASE = $01C20C90; 56 | 57 | class function TWDOG.GetInstance: TWDOG; 58 | begin 59 | if FInstance = nil then FInstance:= TWDOG.Create; 60 | Result:= FInstance; 61 | end; 62 | 63 | class procedure TWDOG.Release; 64 | begin 65 | FreeAndNil(FInstance); 66 | end; 67 | 68 | constructor TWDOG.Create; 69 | var Base: LongWord; 70 | begin 71 | inherited Create; 72 | 73 | FWDOG_BASE:= TA20.Instance.GetMMap(WDOG_BASE); 74 | Base:= LongWord(FWDOG_BASE) + TA20.Instance.BaseOffset(WDOG_BASE); 75 | 76 | FWDOG_CTRL:= Pointer(Base + $00); 77 | FWDOG_MODE:= Pointer(Base + $04); 78 | end; 79 | 80 | destructor TWDOG.Destroy; 81 | begin 82 | TA20.Instance.FreeMMap(FWDOG_BASE); 83 | 84 | inherited Destroy; 85 | end; 86 | 87 | procedure TWDOG.SetInterval(Value: TInterval); 88 | begin 89 | FWDOG_MODE^:= FWDOG_MODE^ and not ($F shl 3); 90 | FWDOG_MODE^:= FWDOG_MODE^ or (Ord(Value) shl 3); 91 | end; 92 | 93 | function TWDOG.GetInterval: TInterval; 94 | var Value: Byte; 95 | begin 96 | Value:= (FWDOG_MODE^ and ($F shl 3)) shr 3; 97 | case Value of 98 | 0: Result:= S0_5; 99 | 1: Result:= S1; 100 | 2:Result:= S2; 101 | 3: Result:= S3; 102 | 4: Result:= S4; 103 | 5: Result:= S5; 104 | 6: Result:= S6; 105 | 7: Result:= S8; 106 | 8: Result:= S10; 107 | 9: Result:= S12; 108 | 10: Result:= S14; 109 | 11: Result:= S16; 110 | end; 111 | end; 112 | 113 | procedure TWDOG.SetForceRestart(Value: Boolean); 114 | begin 115 | case Value of 116 | False: FWDOG_MODE^:= FWDOG_MODE^ and not ($1 shl 1); 117 | True: FWDOG_MODE^:= FWDOG_MODE^ or ($1 shl 1); 118 | end; 119 | end; 120 | 121 | function TWDOG.GetForceRestart: Boolean; 122 | begin 123 | Result:= (FWDOG_MODE^ and ($1 shl 1)) > 0; 124 | end; 125 | 126 | procedure TWDOG.Start; 127 | begin 128 | FWDOG_MODE^:= FWDOG_MODE^ or ($1 shl 0); 129 | end; 130 | 131 | procedure TWDOG.Stop; 132 | begin 133 | FWDOG_MODE^:= FWDOG_MODE^ and not ($1 shl 0); 134 | end; 135 | 136 | procedure TWDOG.Reset; 137 | begin 138 | FWDOG_CTRL^:= 1; 139 | end; 140 | 141 | 142 | finalization 143 | TWDOG.Instance.Release; 144 | 145 | end. 146 | -------------------------------------------------------------------------------- /RTC.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的RTC底层操作封装类。单例。 3 | TRTC类,可对寄存器直接操作,并实现了一些功能的简化。 4 | 作者:tjCFeng 5 | 邮箱:tjCFeng@163.com 6 | 更新日期:2014.12.06 7 | *) 8 | 9 | unit RTC; 10 | 11 | {$mode objfpc}{$H+} 12 | 13 | interface 14 | 15 | uses SysUtils, A20; 16 | 17 | type 18 | TWeek = (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); 19 | 20 | TYMDHNSW = packed record //not TDateTime; 21 | Year: Byte; 22 | Month: Byte; 23 | Day: Byte; 24 | Hour: Byte; 25 | Minute: Byte; 26 | Second: Byte; 27 | Week: TWeek; 28 | end; 29 | 30 | TRTC = class 31 | private 32 | class var FInstance: TRTC; 33 | class function GetInstance: TRTC; static; 34 | public 35 | class procedure Release; 36 | class property Instance: TRTC read GetInstance; 37 | 38 | private 39 | FRTC_BASE: ^LongWord; 40 | 41 | procedure SetDT(Value: TYMDHNSW); 42 | function GetDT: TYMDHNSW; 43 | 44 | constructor Create; 45 | destructor Destroy; override; 46 | protected 47 | FLOSC_CTRL: ^LongWord; 48 | FRTC_DATE: ^LongWord; 49 | FRTC_TIME: ^LongWord; 50 | //Alarm Reg ... 51 | public 52 | property DateTime: TYMDHNSW read GetDT write SetDT; 53 | end; 54 | 55 | implementation 56 | 57 | const 58 | RTC_BASE = $01C20D00; 59 | 60 | class function TRTC.GetInstance: TRTC; 61 | begin 62 | if FInstance = nil then FInstance:= TRTC.Create; 63 | Result:= FInstance; 64 | end; 65 | 66 | class procedure TRTC.Release; 67 | begin 68 | FreeAndNil(FInstance); 69 | end; 70 | 71 | constructor TRTC.Create; 72 | var Base: LongWord; 73 | begin 74 | inherited Create; 75 | 76 | FRTC_BASE:= TA20.Instance.GetMMap(RTC_BASE); 77 | Base:= LongWord(FRTC_BASE) + TA20.Instance.BaseOffset(RTC_BASE); 78 | 79 | FLOSC_CTRL:= Pointer(Base + $00); 80 | FRTC_DATE:= Pointer(Base + $04); 81 | FRTC_TIME:= Pointer(Base + $08); 82 | 83 | FLOSC_CTRL^:= FLOSC_CTRL^ and not ($1 shl 14); 84 | FLOSC_CTRL^:= FLOSC_CTRL^ or ($1 shl 15) or $16AA0000; 85 | FLOSC_CTRL^:= FLOSC_CTRL^ or $8; //($3 shl 2) or ($1 shl 0); 86 | end; 87 | 88 | destructor TRTC.Destroy; 89 | begin 90 | TA20.Instance.FreeMMap(FRTC_BASE); 91 | 92 | inherited Destroy; 93 | end; 94 | 95 | procedure TRTC.SetDT(Value: TYMDHNSW); 96 | var Leap: Byte; YMDFlag, HMSFlag: LongWord; 97 | begin 98 | with Value do 99 | begin 100 | if not (Year in [0..100]) then raise Exception.Create('Year must in [0..100]'); 101 | if not (Month in [1..12]) then raise Exception.Create('Month Error!'); 102 | if not (Day in [1..31]) then raise Exception.Create('Day Error!'); 103 | if not (Hour in [0..23]) then raise Exception.Create('Hour Error!'); 104 | if not (Minute in [0..59]) then raise Exception.Create('Minute Error!'); 105 | if not (Second in [0..59]) then raise Exception.Create('Second Error!'); 106 | end; 107 | if IsLeapYear(Value.Year) then Leap:= 1 else Leap:= 0; 108 | 109 | YMDFlag:= ($1 shl 7); 110 | HMSFlag:= ($1 shl 8); 111 | 112 | with Value do 113 | begin 114 | FRTC_DATE^:= 0; 115 | while (FLOSC_CTRL^ and YMDFlag) <> 0 do Sleep(100); 116 | FRTC_DATE^:= FRTC_DATE^ or (Leap shl 24) or (Year shl 16) or (Month shl 8) or (Day shl 0); 117 | while (FLOSC_CTRL^ and YMDFlag) <> 0 do Sleep(100); 118 | 119 | FRTC_TIME^:= 0; 120 | while (FLOSC_CTRL^ and HMSFlag) <> 0 do Sleep(100); 121 | FRTC_TIME^:= FRTC_TIME^ or (Ord(Week) shl 29) or (Hour shl 16) or (Minute shl 8) or (Second shl 0); 122 | end; 123 | end; 124 | 125 | function TRTC.GetDT: TYMDHNSW; 126 | var YMD, HMS: LongWord; 127 | begin 128 | YMD:= FRTC_DATE^; 129 | HMS:= FRTC_TIME^; 130 | 131 | with Result do 132 | begin 133 | Year:= (YMD shr 16) and $FF; 134 | Month:= (YMD shr 8) and $F; 135 | Day:= YMD and $1F; 136 | 137 | Hour:= (HMS shr 16) and $1F; 138 | Minute:= (HMS shr 8) and $3F; 139 | Second:= HMS and $3F; 140 | 141 | case (HMS shr 29) and $7 of 142 | 0: Week:= Monday; 143 | 1: Week:= Tuesday; 144 | 2: Week:= Wednesday; 145 | 3: Week:= Thursday; 146 | 4: Week:= Friday; 147 | 5: Week:= Saturday; 148 | 6: Week:= Sunday; 149 | end; 150 | end; 151 | end; 152 | 153 | 154 | finalization 155 | TRTC.Instance.Release; 156 | 157 | end. 158 | -------------------------------------------------------------------------------- /Readme.txt: -------------------------------------------------------------------------------- 1 | 全志A20处理器底层操作的一些封装,采用free pascal,封装类。 2 | 使用方法:在工程中添加该类所在的文件夹路径即可。 3 | 4 | 一般每一个外设功能分为两部分封装,一种是直接对某一Pin或通道的操作类,实现对常用功能的封装;另一种是对该类型外设的寄存器操作类,用来对前者没有封装到的功能进行设置。 5 | 6 | 目前实现了对GPIO、LRADC、PWM的封装,后续功能陆续完成,并且正在尝试增加对中断的响应功能。 7 | 8 | 该类可用在控制台、有界面或无界面程序中均可,并且根据编译器的不同,也可用在不同的操作系统,只需很少的代码改动,如引用不同的单元等。 9 | 10 | 全志其他系列的处理器也可使用该类,如A10等,只需要根据差异的部分进行改动,或者继承重新实现。 11 | 12 | 作者:tjCFeng 13 | 邮箱:tjCFeng@163.com 14 | 15 | 例子: 16 | 1.TGPIOGROUP 17 | 18 | [code] 19 | uses GPIO; 20 | 21 | var PHG: TGPIOGROUP; 22 | begin 23 | PHG:= TGPIOGROUP.Create(PH); //创建 24 | PHG.GPIO_DAT^:= PHG.GPIO_DAT^ or ($1 shl 24); //设置寄存器的值 25 | PHG.Free; //释放 26 | end; 27 | [/code] 28 | 29 | 2.TGPIO 30 | 31 | [code] 32 | uses GPIO; 33 | 34 | begin 35 | with TGPIO.Create(PH, 24) do 36 | begin 37 | Fun:= Fun1; //设置PH24为输出 38 | Data:= True; //设置高电平 39 | Sleep(1000); 40 | Reverse; //反转电平 41 | Free; //释放 42 | end; 43 | end; 44 | [/code] 45 | 46 | 或 47 | 48 | [code] 49 | var PH24: TGPIO; 50 | begin 51 | PH24:= TGPIO.Create(PH, 24); 52 | PH24.Fun:= Fun1; 53 | PH24.Reverse; 54 | PH24.Free; 55 | end; 56 | [/code] 57 | 58 | 3.LRADC 59 | 60 | [code] 61 | uses LRADC; 62 | 63 | var ADC0: TLRADC; Data: Byte; 64 | begin 65 | ADC0:= TLRADC.Create(LRADC_0); //创建LRADC通道0 66 | TLRADCGROUP.Instance.ClearAllPending; //清除所有未决中断,单例中的功能 67 | ADC0.INTs:= [ADCDATA, KEYDOWN, KEYUP]; //设置需要响应的中断类型 68 | TLRADCGROUP.Instance.Start; //开启LRADC,单例中的功能 69 | Data:= ADC0.Data; //获取LRADC通道0的值0~64 70 | TLRADCGROUP.Instance.Stop; //停止LRADC,单例中的功能 71 | ADC0.Free; //释放 72 | end; 73 | [/code] 74 | 75 | 4.PWM 76 | 77 | [code] 78 | uses PWM; 79 | 80 | var PWM1: TPWM; 81 | begin 82 | PWM1:= TPWM.Create(PWM_1); //创建PWM通道1 83 | with PWM1 do 84 | begin 85 | Prescale:= P960; //设置预分频 86 | Cycle:= 6000; //设置周期计数 87 | Duty:= 1000; //设置占空比计数 88 | Start; //开始PWM输出 89 | Sleep(3000); 90 | Stop; //停止PWM输出 91 | Free; //释放 92 | end; 93 | end; 94 | [/code] 95 | 96 | 5.Timer 97 | 98 | [code] 99 | uses Timer; 100 | 101 | var Timer0: TTimer; 102 | begin 103 | Timer0:= TTimer.Create(Timer_0); 104 | with Timer0 do 105 | begin 106 | Prescal:= Div4; 107 | CNT:= 6000000; 108 | CUR:= 0; 109 | Start; 110 | while not Timer0.INT do ; 111 | //执行到这里是1秒 112 | Stop; 113 | Free; 114 | end; 115 | end; 116 | [/code] 117 | 118 | 6.RTC 119 | 120 | [code] 121 | uses RTC; 122 | 123 | var DT: TYMDHNSW; 124 | begin 125 | with DT do 126 | begin 127 | Year:= 14; 128 | Month:= 10; 129 | Day:= 20; 130 | 131 | Hour:= 9; 132 | Minute:= 30; 133 | Second:= 0; 134 | 135 | Week:= Monday; 136 | end; 137 | TRTC.Instance.DateTime:= DT; 138 | 139 | FillChar(DT, SizeOf(TYMDHNSW), 0); 140 | DT:= TRTC.Instance.DateTime; 141 | end; 142 | [/code] 143 | 144 | 7.General Purpose 145 | 146 | [code] 147 | uses GP; 148 | 149 | var Data: LongWord; 150 | begin 151 | TGP.Instance.TMR_GP[0]^:= 123456789; 152 | Data:= TGP.Instance.TMR_GP[10]^; 153 | end; 154 | [/code] 155 | 156 | 8.TWI 157 | [code] 158 | uses TWI; 159 | 160 | var TWI0: TTWI; Data: Byte; 161 | begin 162 | TWI0:= TTWI.Create(TWI_0); 163 | TWI0.Write($34, $35, $83); 164 | TWI0.Read($34, $35, Data); 165 | TWI0.Free; 166 | end; 167 | [/code] 168 | 169 | 9.WatchDog 170 | [code] 171 | uses WatchDog; 172 | begin 173 | TWDOG.Instance.Interval:= S16; //16秒间隔 174 | TWDOG.Instance.ForceRestart:= True; //未喂狗重启 175 | TWDOG.Instance.Start; 176 | TWDOG.Instance.Reset; //喂狗 177 | TWDOG.InstanceStop; 178 | end; 179 | [/code] 180 | 181 | 10.Temperature 182 | [code] 183 | uses TP; 184 | 185 | var T: Double; 186 | begin 187 | T:= TTemperature.Instance.Temperature; 188 | end; 189 | [/code] 190 | 191 | 历史版本: 192 | 2014.12.06 v0.8 增加Temperature封装类,修正所有的TGOURP类型为TGROUP,抱歉,手误拼写错误 193 | 2014.10.21 v0.7 增加WatchDog封装类 194 | 2014.10.20 v0.6 增加GP封装类 195 | 2014.10.18 v0.5 增加TWI封装类,修正部分bug 196 | 2014.10.16 v0.3 增加General Purpose封装类 197 | 2014.10.15 v0.3 增加RTC封装类,修正部分变量位定义的bug 198 | 2014.10.14 v0.2 增加Timer封装类 199 | 2014.10.03 v0.1 完成GPIO、LRADC、PWM的封装类 200 | -------------------------------------------------------------------------------- /PWM.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的PWM底层操作封装类。分为两个部分: 3 | 1.TPWMGROUP类,可对寄存器直接操作,单例; 4 | 2.TPWM类,对具体的PWM通道实现了一些功能的简化。 5 | 作者:tjCFeng 6 | 邮箱:tjCFeng@163.com 7 | 更新日期:2014.12.06 8 | *) 9 | 10 | unit PWM; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses SysUtils, A20, GPIO; 17 | 18 | type 19 | TChannel = (PWM_0, PWM_1); 20 | TPrescal = 21 | (P120, P180, P240, P360, P480, P720, P840, P960, 22 | P12K, P24K, P36K, P48K, P72K, P84K, P96K, P108K); 23 | 24 | TPWMGROUP = class 25 | private 26 | class var FInstance: TPWMGROUP; 27 | class function GetInstance: TPWMGROUP; static; 28 | public 29 | class procedure Release; 30 | class property Instance: TPWMGROUP read GetInstance; 31 | 32 | private 33 | FPWM_BASE: ^LongWord; 34 | FPWM_CTRL: TGROUP1_REG; 35 | FPWM_PERIOD: TGROUP2_REG; 36 | 37 | constructor Create; 38 | destructor Destroy; override; 39 | public 40 | property PWM_CTRL: TGROUP1_REG read FPWM_CTRL; 41 | property PWM_PERIOD: TGROUP2_REG read FPWM_PERIOD; 42 | end; 43 | 44 | TPWM = class(TGPIO) 45 | private 46 | FChannel: TChannel; 47 | FCycle: Word; 48 | FDuty: Word; 49 | FPWM_PERIOD: ^LongWord; 50 | private 51 | procedure SetPrescale(Value: TPrescal); 52 | procedure SetCycle(Value: Word); 53 | procedure SetDuty(Value: Word); 54 | public 55 | constructor Create(Channel: TChannel); 56 | procedure Start; 57 | procedure Stop; 58 | public 59 | property Channel: TChannel read FChannel; 60 | property Prescale: TPrescal write SetPrescale; 61 | property Cycle: Word write SetCycle; 62 | property Duty: Word write SetDuty; 63 | end; 64 | 65 | implementation 66 | 67 | const 68 | PWM_BASE = $01C20C00; 69 | 70 | (*PWM Group********************************************************************) 71 | class function TPWMGROUP.GetInstance: TPWMGROUP; 72 | begin 73 | if FInstance = nil then FInstance:= TPWMGROUP.Create; 74 | Result:= FInstance; 75 | end; 76 | 77 | class procedure TPWMGROUP.Release; 78 | begin 79 | FreeAndNil(FInstance); 80 | end; 81 | 82 | constructor TPWMGROUP.Create; 83 | var Base: LongWord; 84 | begin 85 | inherited Create; 86 | 87 | FPWM_BASE:= TA20.Instance.GetMMap(PWM_BASE); 88 | Base:= LongWord(FPWM_BASE) + TA20.Instance.BaseOffset(PWM_BASE); 89 | 90 | FPWM_CTRL:= Pointer(Base + $200); 91 | FPWM_PERIOD[0]:= Pointer(Base + $204); 92 | FPWM_PERIOD[1]:= Pointer(Base + $208); 93 | 94 | //FPWM_CTRL^:= FPWM_CTRL^ or (($1 shl 24) + ($1 shl 9)); //OSC24MHz 95 | end; 96 | 97 | destructor TPWMGROUP.Destroy; 98 | begin 99 | FPWM_CTRL^:= 0; 100 | FPWM_PERIOD[0]^:= 0; 101 | FPWM_PERIOD[1]^:= 0; 102 | TA20.Instance.FreeMMap(FPWM_BASE); 103 | 104 | inherited Destroy; 105 | end; 106 | 107 | (*PWM Channel******************************************************************) 108 | constructor TPWM.Create(Channel: TChannel); 109 | begin 110 | FChannel:= Channel; 111 | 112 | case FChannel of 113 | PWM_0: inherited Create(PB, 2); 114 | PWM_1: inherited Create(PI, 3); 115 | end; 116 | SetFun(Fun2); 117 | 118 | FPWM_PERIOD:= TPWMGROUP.Instance.PWM_PERIOD[Ord(FChannel)]; 119 | FPWM_PERIOD^:= 0; 120 | 121 | with TPWMGROUP.Instance do 122 | PWM_CTRL^:= PWM_CTRL^ or ($1 shl (Ord(FChannel) * 15 + 6)); //Special Clock 123 | end; 124 | 125 | procedure TPWM.SetPrescale(Value: TPrescal); 126 | begin 127 | with TPWMGROUP.Instance do 128 | begin 129 | PWM_CTRL^:= PWM_CTRL^ and not ($F shl (Ord(FChannel) * 15)); 130 | PWM_CTRL^:= PWM_CTRL^ or (Ord(Value) shl (Ord(FChannel) * 15)); 131 | end; 132 | end; 133 | 134 | procedure TPWM.SetCycle(Value: Word); 135 | begin 136 | FCycle:= Value; 137 | FPWM_PERIOD^:= FPWM_PERIOD^ and $0000FFFF; 138 | FPWM_PERIOD^:= FPWM_PERIOD^ or (Value shl 16); 139 | end; 140 | 141 | procedure TPWM.SetDuty(Value: Word); 142 | var D: LongWord; 143 | begin 144 | if (FCycle > 0) and (Value >= FCycle) then FDuty:= FCycle - 1; 145 | FPWM_PERIOD^:= FPWM_PERIOD^ and $FFFF0000; 146 | FPWM_PERIOD^:= FPWM_PERIOD^ or Value; 147 | end; 148 | 149 | procedure TPWM.Start; 150 | begin 151 | with TPWMGROUP.Instance do 152 | FPWM_CTRL^:= FPWM_CTRL^ or ($1 shl (Ord(FChannel) * 15 + 4)); 153 | end; 154 | 155 | procedure TPWM.Stop; 156 | begin 157 | with TPWMGROUP.Instance do 158 | FPWM_CTRL^:= FPWM_CTRL^ and not ($1 shl (Ord(FChannel) * 15 + 4)); 159 | end; 160 | 161 | 162 | finalization 163 | TPWMGROUP.Instance.Release; 164 | 165 | end. 166 | -------------------------------------------------------------------------------- /GPIO.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的GPIO底层操作封装类。分为两个部分: 3 | 1.TGPIOGROUP类,可对寄存器直接操作,单例; 4 | 2.TGPIO类,对具体的Pin实现了一些功能的简化。 5 | 作者:tjCFeng 6 | 邮箱:tjCFeng@163.com 7 | 更新日期:2014.12.06 8 | *) 9 | 10 | unit GPIO; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses A20, Clock; 17 | 18 | type 19 | TPort = (PA, PB, PC, PD, PE, PF, PG, PH, PI); //PS:DRAM 20 | TFun = (Fun0, Fun1, Fun2, Fun3, Fun4, Fun5, Fun6, Fun7); //Fun0:Input; Fun1:Output 21 | TDrv = (Level0, Level1, Level2, Level3); 22 | TPull = (PULL_OFF, PULL_UP, PULL_DOWN); 23 | 24 | TGPIOGROUP = class 25 | private 26 | FPort: TPort; 27 | FGPIO_BASE: ^LongWord; 28 | protected 29 | FGPIO_CFG: TGROUP4_REG; 30 | FGPIO_DAT: TGROUP1_REG; 31 | FGPIO_DRV: TGROUP2_REG; 32 | FGPIO_PUL: TGROUP2_REG; 33 | public 34 | constructor Create(Port: TPort); 35 | destructor Destroy; override; 36 | public 37 | property GPIO_CFG: TGROUP4_REG read FGPIO_CFG; 38 | property GPIO_DAT: TGROUP1_REG read FGPIO_DAT; 39 | property GPIO_DRV: TGROUP2_REG read FGPIO_DRV; 40 | property GPIO_PUL: TGROUP2_REG read FGPIO_PUL; 41 | end; 42 | 43 | TGPIO = class(TGPIOGROUP) 44 | private 45 | FPin: Byte; 46 | FPinBit: LongWord; 47 | 48 | FPIN_CFG: ^LongWord; 49 | FPIN_DAT: ^LongWord; 50 | FPIN_DRV: ^LongWord; 51 | FPIN_PUL: ^LongWord; 52 | protected 53 | procedure SetFun(Fun: TFun); 54 | procedure SetDrv(Drv: TDrv); 55 | procedure SetPull(Pull: TPull); 56 | procedure SetData(Level: Boolean); 57 | function GetData: Boolean; 58 | public 59 | constructor Create(Port: TPort; Pin: Byte); 60 | procedure Reverse; 61 | public 62 | property Fun: TFun write SetFun; 63 | property Drv: TDrv write SetDrv; 64 | property Pull: TPull write SetPull; 65 | property Data: Boolean read GetData write SetData; 66 | end; 67 | 68 | implementation 69 | 70 | const 71 | PIO_BASE = $01C20800; 72 | 73 | (*GPIO Group*******************************************************************) 74 | constructor TGPIOGROUP.Create(Port: TPort); 75 | var Base: LongWord; 76 | begin 77 | inherited Create; 78 | 79 | FPort:= Port; 80 | FGPIO_BASE:= TA20.Instance.GetMMap(PIO_BASE); 81 | Base:= LongWord(FGPIO_BASE) + TA20.Instance.BaseOffset(PIO_BASE) + (Ord(FPort) * $24); 82 | 83 | FGPIO_CFG[0]:= Pointer(Base + $00); 84 | FGPIO_CFG[1]:= Pointer(Base + $04); 85 | FGPIO_CFG[2]:= Pointer(Base + $08); 86 | FGPIO_CFG[3]:= Pointer(Base + $0C); 87 | FGPIO_DAT:= Pointer(Base + $10); 88 | FGPIO_DRV[0]:= Pointer(Base + $14); 89 | FGPIO_DRV[1]:= Pointer(Base + $18); 90 | FGPIO_PUL[0]:= Pointer(Base + $1C); 91 | FGPIO_PUL[1]:= Pointer(Base + $20); 92 | 93 | TCCU.Instance.CLK_SetGPIO(True); 94 | end; 95 | 96 | destructor TGPIOGROUP.Destroy; 97 | begin 98 | TA20.Instance.FreeMMap(FGPIO_BASE); 99 | 100 | inherited Destroy; 101 | end; 102 | 103 | (*GPIO Pin*********************************************************************) 104 | constructor TGPIO.Create(Port: TPort; Pin: Byte); 105 | begin 106 | inherited Create(Port); 107 | 108 | FPort:= Port; 109 | FPin:= Pin; 110 | FPinBit:= ($1 shl FPin); 111 | 112 | FPIN_CFG:= FGPIO_CFG[FPin div 8]; 113 | FPIN_DAT:= FGPIO_DAT; 114 | FPIN_DRV:= FGPIO_DRV[FPin div 16]; 115 | FPIN_PUL:= FGPIO_PUL[FPin div 16]; 116 | end; 117 | 118 | procedure TGPIO.SetFun(Fun: TFun); 119 | var PinN: Byte; 120 | begin 121 | PinN:= (FPin mod 8) * 4; 122 | FPIN_CFG^:= FPIN_CFG^ and not ($7 shl PinN); 123 | FPIN_CFG^:= FPIN_CFG^ or (Ord(Fun) shl PinN); 124 | end; 125 | 126 | procedure TGPIO.SetDrv(Drv: TDrv); 127 | var PinN: Byte; 128 | begin 129 | PinN:= (FPin mod 16) * 2; 130 | FPIN_DRV^:= FPIN_DRV^ and not ($3 shl PinN); 131 | FPIN_DRV^:= FPIN_DRV^ or (Ord(Drv) shl PinN); 132 | end; 133 | 134 | procedure TGPIO.SetPull(Pull: TPull); 135 | var PinN: Byte; 136 | begin 137 | PinN:= (FPin mod 16) * 2; 138 | FPIN_PUL^:= FPIN_PUL^ and not ($3 shl PinN); 139 | FPIN_PUL^:= FPIN_PUL^ or (Ord(Pull) shl PinN); 140 | end; 141 | 142 | procedure TGPIO.SetData(Level: Boolean); 143 | begin 144 | case Level of 145 | False: FPIN_DAT^:= FPIN_DAT^ and not FPinBit; 146 | True: FPIN_DAT^:= FPIN_DAT^ or FPinBit; 147 | end; 148 | end; 149 | 150 | function TGPIO.GetData: Boolean; 151 | begin 152 | Result:= ((FPIN_DAT^ and FPinBit) = FPinBit); 153 | end; 154 | 155 | procedure TGPIO.Reverse; 156 | begin 157 | FPIN_DAT^:= FPIN_DAT^ xor FPinBit; 158 | end; 159 | 160 | end. 161 | -------------------------------------------------------------------------------- /TP.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的TP底层操作封装类。分为两个部分: 3 | 1.TP类,可对寄存器直接操作,单例; 4 | 2.TTemperature类,对具体的PWM通道实现了一些功能的简化。 5 | 作者:tjCFeng 6 | 邮箱:tjCFeng@163.com 7 | 更新日期:2014.12.06 8 | *) 9 | 10 | unit TP; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses Classes, SysUtils, A20; 17 | 18 | type 19 | TTP = class 20 | private 21 | class var FInstance: TTP; 22 | class function GetInstance: TTP; static; 23 | public 24 | class procedure Release; 25 | class property Instance: TTP read GetInstance; 26 | 27 | private 28 | FTP_BASE: ^LongWord; 29 | FTP_CTRL: TGROUP4_REG; 30 | FTP_INT_FIFOC: TGROUP1_REG; 31 | FTP_INT_FIFOS: TGROUP1_REG; 32 | FTP_TPR: TGROUP1_REG; 33 | FTP_CDAT: TGROUP1_REG; 34 | FTEMP_DATA: TGROUP1_REG; 35 | FTP_DATA: TGROUP1_REG; 36 | FTP_IO_CONFIG: TGROUP1_REG; 37 | FTP_PORT_DATA: TGROUP1_REG; 38 | 39 | constructor Create; 40 | destructor Destroy; override; 41 | public 42 | property TP_CTRL: TGROUP4_REG read FTP_CTRL; 43 | property TP_INT_FIFOC: TGROUP1_REG read FTP_INT_FIFOC; 44 | property TP_INT_FIFOS: TGROUP1_REG read FTP_INT_FIFOS; 45 | property TP_TPR: TGROUP1_REG read FTP_TPR; 46 | property TP_CDAT: TGROUP1_REG read FTP_CDAT; 47 | property TEMP_DATA: TGROUP1_REG read FTEMP_DATA; 48 | property TP_DATA: TGROUP1_REG read FTP_DATA; 49 | property TP_IO_CONFIG: TGROUP1_REG read FTP_IO_CONFIG; 50 | property TP_PORT_DATA: TGROUP1_REG read FTP_PORT_DATA; 51 | end; 52 | 53 | TTemperature = class 54 | private 55 | class var FInstance: TTemperature; 56 | class function GetInstance: TTemperature; static; 57 | public 58 | class procedure Release; 59 | class property Instance: TTemperature read GetInstance; 60 | 61 | private 62 | FINTBit: Integer; 63 | FEnBit: Integer; 64 | constructor Create; 65 | destructor Destroy; override; 66 | public 67 | function Temperature: Double; 68 | end; 69 | 70 | implementation 71 | 72 | const 73 | TP_BASE = $01C25000; 74 | 75 | (*TP***************************************************************************) 76 | class function TTP.GetInstance: TTP; 77 | begin 78 | if FInstance = nil then FInstance:= TTP.Create; 79 | Result:= FInstance; 80 | end; 81 | 82 | class procedure TTP.Release; 83 | begin 84 | FreeAndNil(FInstance); 85 | end; 86 | 87 | constructor TTP.Create; 88 | var Base: LongWord; I: Byte; 89 | begin 90 | inherited Create; 91 | 92 | FTP_BASE:= TA20.Instance.GetMMap(TP_BASE); 93 | Base:= LongWord(FTP_BASE) + TA20.Instance.BaseOffset(TP_BASE); 94 | 95 | for I:= 0 to 3 do FTP_CTRL[I]:= Pointer(Base + $04 * I); 96 | FTP_INT_FIFOC:= Pointer(Base + $10); 97 | FTP_INT_FIFOS:= Pointer(Base + $14); 98 | FTP_TPR:= Pointer(Base + $18); 99 | FTP_CDAT:= Pointer(Base + $1C); 100 | FTEMP_DATA:= Pointer(Base + $20); 101 | FTP_DATA:= Pointer(Base + $24); 102 | FTP_IO_CONFIG:= Pointer(Base + $28); 103 | FTP_PORT_DATA:= Pointer(Base + $2C); 104 | end; 105 | 106 | destructor TTP.Destroy; 107 | begin 108 | TA20.Instance.FreeMMap(FTP_BASE); 109 | 110 | inherited Destroy; 111 | end; 112 | 113 | (*Temperature******************************************************************) 114 | class function TTemperature.GetInstance: TTemperature; 115 | begin 116 | if FInstance = nil then FInstance:= TTemperature.Create; 117 | Result:= FInstance; 118 | end; 119 | 120 | class procedure TTemperature.Release; 121 | begin 122 | FreeAndNil(FInstance); 123 | end; 124 | 125 | constructor TTemperature.Create; 126 | begin 127 | inherited Create; 128 | 129 | with TTP.Instance do 130 | begin 131 | FTP_CTRL[0]^:= FTP_CTRL[0]^ and not (($1 shl 22) or ($3 shl 20) or ($FFFF shl 0)); 132 | FTP_CTRL[0]^:= FTP_CTRL[0]^ or (($0 shl 22) or ($1 shl 20) or ($7 shl 16) or ($3F shl 0)); 133 | FTP_CTRL[1]^:= FTP_CTRL[1]^ and not ($1 shl 3); 134 | FTP_CTRL[1]^:= FTP_CTRL[1]^ or (($1 shl 7) or ($1 shl 4)); 135 | 136 | FTP_TPR^:= $00000FFF; 137 | end; 138 | 139 | FINTBit:= ($1 shl 18); 140 | FEnBit:= ($1 shl 16); 141 | end; 142 | 143 | destructor TTemperature.Destroy; 144 | begin 145 | inherited Destroy; 146 | end; 147 | 148 | function TTemperature.Temperature: Double; 149 | begin 150 | with TTP.Instance do 151 | begin 152 | FTP_INT_FIFOS^:= FTP_INT_FIFOS^ or FINTBit; 153 | 154 | FTP_INT_FIFOC^:= FTP_INT_FIFOC^ or FINTBit; 155 | FTP_TPR^:= FTP_TPR^ or FEnBit; 156 | 157 | while (FTP_INT_FIFOS^ and FINTBit) <> FINTBit do ; 158 | Result:= FTEMP_DATA^ * 85 / 4096; 159 | 160 | FTP_INT_FIFOC^:= FTP_INT_FIFOC^ and not FINTBit; 161 | FTP_TPR^:= FTP_TPR^ and not FEnBit; 162 | end; 163 | end; 164 | 165 | 166 | finalization 167 | TTP.Instance.Release; 168 | 169 | end. 170 | 171 | -------------------------------------------------------------------------------- /LRADC.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的LRADC底层操作封装类。分为两个部分: 3 | 1.TLRADCGROUP类,可对寄存器直接操作,单例; 4 | 2.TLRADC类,对具体的LRADC通道实现了一些功能的简化。 5 | 作者:tjCFeng 6 | 邮箱:tjCFeng@163.com 7 | 更新日期:2014.12.06 8 | *) 9 | 10 | unit LRADC; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses SysUtils, A20; 17 | 18 | type 19 | TChannel = (LRADC_0, LRADC_1); 20 | TLRADCINT = (ADCDATA, KEYDOWN, HOLD, ALRDYHOLD, KEYUP); 21 | TLRADCINTs = set of TLRADCINT; 22 | 23 | TLRADCGROUP = class 24 | private 25 | class var FInstance: TLRADCGROUP; 26 | class function GetInstance: TLRADCGROUP; static; 27 | public 28 | class procedure Release; 29 | class property Instance: TLRADCGROUP read GetInstance; 30 | 31 | private 32 | FLRADC_BASE: ^LongWord; 33 | FLRADC_CTRL: TGROUP1_REG; 34 | FLRADC_INTC: TGROUP1_REG; 35 | FLRADC_INTS: TGROUP1_REG; 36 | FLRADC_DATA: TGROUP2_REG; 37 | 38 | constructor Create; 39 | destructor Destroy; override; 40 | public 41 | procedure Start; 42 | procedure Stop; 43 | procedure ClearAllPending; 44 | public 45 | property LRADC_CTRL: TGROUP1_REG read FLRADC_CTRL; 46 | property LRADC_INTC: TGROUP1_REG read FLRADC_INTC; 47 | property LRADC_INTS: TGROUP1_REG read FLRADC_INTS; 48 | property LRADC_DATA: TGROUP2_REG read FLRADC_DATA; 49 | end; 50 | 51 | TLRADC = class 52 | private 53 | FChannel: TChannel; 54 | FINTs: TLRADCINTs; 55 | 56 | FLRADC_DATA: ^LongWord; 57 | private 58 | procedure SetINTs(INTs: TLRADCINTs); 59 | function GetDATA: Byte; 60 | public 61 | constructor Create(Channel: TChannel); 62 | 63 | function GetStatus(INT: TLRADCINT): Boolean; 64 | procedure ClearPendings(INTs: TLRADCINTs); 65 | public 66 | property Channel: TChannel read FChannel; 67 | property INTs: TLRADCINTs read FINTs write SetINTs default []; 68 | property Data: Byte read GetDATA; 69 | end; 70 | 71 | implementation 72 | 73 | const 74 | LRADC_BASE = $01C22800; 75 | 76 | (*LRADC Group******************************************************************) 77 | class function TLRADCGROUP.GetInstance: TLRADCGROUP; 78 | begin 79 | if FInstance = nil then FInstance:= TLRADCGROUP.Create; 80 | Result:= FInstance; 81 | end; 82 | 83 | class procedure TLRADCGROUP.Release; 84 | begin 85 | FreeAndNil(FInstance); 86 | end; 87 | 88 | constructor TLRADCGROUP.Create; 89 | var Base: LongWord; 90 | begin 91 | inherited Create; 92 | 93 | FLRADC_BASE:= TA20.Instance.GetMMap(LRADC_BASE); 94 | Base:= LongWord(FLRADC_BASE) + TA20.Instance.BaseOffset(LRADC_BASE); 95 | 96 | FLRADC_CTRL:= Pointer(Base + $00); 97 | FLRADC_INTC:= Pointer(Base + $04); 98 | FLRADC_INTS:= Pointer(Base + $08); 99 | FLRADC_DATA[0]:= Pointer(Base + $0C); 100 | FLRADC_DATA[1]:= Pointer(Base + $10); 101 | end; 102 | 103 | destructor TLRADCGROUP.Destroy; 104 | begin 105 | TA20.Instance.FreeMMap(FLRADC_BASE); 106 | 107 | inherited Destroy; 108 | end; 109 | 110 | procedure TLRADCGROUP.Start; 111 | begin 112 | FLRADC_CTRL^:= FLRADC_CTRL^ or ($1 shl 0); 113 | end; 114 | 115 | procedure TLRADCGROUP.Stop; 116 | begin 117 | FLRADC_CTRL^:= FLRADC_CTRL^ and not ($1 shl 0); 118 | end; 119 | 120 | procedure TLRADCGROUP.ClearAllPending; 121 | begin 122 | FLRADC_INTS^:= $00001F1F; 123 | end; 124 | 125 | (*LRADC Channel****************************************************************) 126 | constructor TLRADC.Create(Channel: TChannel); 127 | begin 128 | inherited Create; 129 | 130 | FChannel:= Channel; 131 | FLRADC_DATA:= TLRADCGROUP.Instance.LRADC_DATA[Ord(FChannel)]; 132 | end; 133 | 134 | function TLRADC.GetDATA: Byte; 135 | begin 136 | Result:= Byte(FLRADC_DATA^); 137 | end; 138 | 139 | function TLRADC.GetStatus(INT: TLRADCINT): Boolean; 140 | var INTBIT: LongWord; 141 | begin 142 | INTBIT:= Ord(FChannel) * 8 + Ord(INT); 143 | Result:= (TLRADCGROUP.Instance.LRADC_INTS^ and INTBIT) = INTBIT; 144 | end; 145 | 146 | procedure TLRADC.SetINTs(INTs: TLRADCINTs); 147 | procedure SetINT(IndexINT: Byte; ED: Boolean); 148 | begin 149 | with TLRADCGROUP.Instance do 150 | if ED then 151 | LRADC_INTC^:= LRADC_INTC^ or ($1 shl (Ord(FChannel) * 8) + IndexINT) 152 | else 153 | LRADC_INTC^:= LRADC_INTC^ and not ($1 shl (Ord(FChannel) * 8) + IndexINT); 154 | end; 155 | begin 156 | FINTs:= INTs; 157 | SetINT(Ord(ADCDATA), ADCDATA in INTs); 158 | SetINT(Ord(KEYDOWN), KEYDOWN in INTs); 159 | SetINT(Ord(HOLD), HOLD in INTs); 160 | SetINT(Ord(ALRDYHOLD), ALRDYHOLD in INTs); 161 | SetINT(Ord(KEYUP), KEYUP in INTs); 162 | end; 163 | 164 | procedure TLRADC.ClearPendings(INTs: TLRADCINTs); 165 | procedure ClearPending(IndexINT: Byte); 166 | begin 167 | with TLRADCGROUP.Instance do 168 | LRADC_INTS^:= LRADC_INTS^ or ($1 shl Ord(FChannel) * 8 + IndexINT); 169 | end; 170 | begin 171 | if (ADCDATA in INTs) then ClearPending(Ord(DATA)); 172 | if (KEYDOWN in INTs) then ClearPending(Ord(KEYDOWN)); 173 | if (HOLD in INTs) then ClearPending(Ord(HOLD)); 174 | if (ALRDYHOLD in INTs) then ClearPending(Ord(ALRDYHOLD)); 175 | if (KEYUP in INTs) then ClearPending(Ord(KEYUP)); 176 | end; 177 | 178 | 179 | finalization 180 | TLRADCGROUP.Instance.Release; 181 | 182 | end. 183 | -------------------------------------------------------------------------------- /Timer.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的Timer底层操作封装类。分为两个部分: 3 | 1.TTimerGROUP类,可对寄存器直接操作,单例; 4 | 2.TTimer类,对具体的Timer实现了一些功能的简化。 5 | 作者:tjCFeng 6 | 邮箱:tjCFeng@163.com 7 | 更新日期:2014.12.06 8 | *) 9 | 10 | unit Timer; 11 | 12 | {$mode objfpc}{$H+} 13 | 14 | interface 15 | 16 | uses SysUtils, A20; 17 | 18 | type 19 | TChannel = (Timer_0, Timer_1, Timer_2, Timer_3, Timer_4, Timer_5); 20 | TMode = (Loop, Single); 21 | TCLK = (OSC32K, OSC24M, PLL6_6); 22 | TPrescal = (Div1, Div2, Div4, Div8, Div16, Div32, Div64, Div128); 23 | 24 | TTimerGroup = class 25 | private 26 | class var FInstance: TTimerGroup; 27 | class function GetInstance: TTimerGroup; static; 28 | public 29 | class procedure Release; 30 | class property Instance: TTimerGroup read GetInstance; 31 | 32 | private 33 | FTMR_BASE: ^LongWord; 34 | 35 | constructor Create; 36 | destructor Destroy; override; 37 | protected 38 | FTMR_IRQ_CTRL: TGROUP1_REG; 39 | FTMR_IRQ_STA: TGROUP1_REG; 40 | FTMR_CTRL: TGROUP6_REG; 41 | FTMR_INTV_VALUE: TGROUP6_REG; 42 | FTMR_CURR_VALUE: TGROUP6_REG; 43 | public 44 | property TMR_IRQ_CTRL: TGROUP1_REG read FTMR_IRQ_CTRL; 45 | property TMR_IRQ_STA: TGROUP1_REG read FTMR_IRQ_STA; 46 | property TMR_CTRL: TGROUP6_REG read FTMR_CTRL; 47 | property TMR_INTV_VALUE: TGROUP6_REG read FTMR_INTV_VALUE; 48 | property TMR_CURR_VALUE: TGROUP6_REG read FTMR_CURR_VALUE; 49 | end; 50 | 51 | TTimer = class 52 | private 53 | FChannel: TChannel; 54 | FCHBit: LongWord; 55 | FMode: TMode; 56 | FAutoReload: Boolean; 57 | FCLK: TCLK; 58 | FPrescal: TPrescal; 59 | FCNT: LongWord; 60 | FCUR: LongWord; 61 | 62 | FTIM_IRQ_CTL: ^LongWord; 63 | FTIM_IRQ_STA: ^LongWord; 64 | FTIM_CTRL: ^LongWord; 65 | FTIM_INTV: ^LongWord; 66 | FTIM_CURR: ^LongWord; 67 | protected 68 | procedure SetMode(Value: TMode); 69 | procedure SetAutoReload(Value: Boolean); 70 | procedure SetCLK(Value: TCLK); 71 | procedure SetPrescal(Value: TPrescal); 72 | procedure SetCNT(Value: LongWord); 73 | procedure SetCUR(Value: LongWord); 74 | procedure SetINT(INT: Boolean); 75 | function GetINT: Boolean; 76 | public 77 | constructor Create(Channel: TChannel); 78 | destructor Destroy; override; 79 | procedure ClearPending; 80 | procedure Start; 81 | procedure Stop; 82 | public 83 | property Channel: TChannel read FChannel; 84 | property Mode: TMode read FMode write SetMode default Single; 85 | property AutoReload: Boolean read FAutoReload write SetAutoReload default True; 86 | property CLK: TCLK read FCLK write SetCLK default OSC24M; 87 | property Prescal: TPrescal read FPrescal write SetPrescal default Div1; 88 | property CNT: LongWord read FCNT write SetCNT default 0; 89 | property CUR: LongWord read FCUR write SetCUR default 0; 90 | property INT: Boolean read GetINT write SetINT default False; 91 | end; 92 | 93 | implementation 94 | 95 | const 96 | TMR_BASE = $01C20C00; 97 | 98 | (*Timer Group******************************************************************) 99 | class function TTimerGroup.GetInstance: TTimerGroup; 100 | begin 101 | if FInstance = nil then FInstance:= TTimerGroup.Create; 102 | Result:= FInstance; 103 | end; 104 | 105 | class procedure TTimerGroup.Release; 106 | begin 107 | FreeAndNil(FInstance); 108 | end; 109 | 110 | constructor TTimerGroup.Create; 111 | var Base: LongWord; I: Byte; 112 | begin 113 | inherited Create; 114 | 115 | FTMR_BASE:= TA20.Instance.GetMMap(TMR_BASE); 116 | Base:= LongWord(FTMR_BASE) + TA20.Instance.BaseOffset(TMR_BASE); 117 | 118 | FTMR_IRQ_CTRL:= Pointer(Base + $00); 119 | FTMR_IRQ_STA:= Pointer(Base + $04); 120 | 121 | for I:= 0 to 5 do 122 | begin 123 | FTMR_CTRL[I]:= Pointer(Base + (I + 1) * $10); 124 | FTMR_INTV_VALUE[I]:= Pointer(Base + (I + 1) * $10 + $04); 125 | FTMR_CURR_VALUE[I]:= Pointer(Base + (I + 1) * $10 + $08); 126 | end; 127 | FTMR_CURR_VALUE[3]:= nil; 128 | end; 129 | 130 | destructor TTimerGroup.Destroy; 131 | begin 132 | TA20.Instance.FreeMMap(FTMR_BASE); 133 | 134 | inherited Destroy; 135 | end; 136 | 137 | (*TTimer Channel*********************************************************************) 138 | constructor TTimer.Create(Channel: TChannel); 139 | begin 140 | inherited Create; 141 | 142 | FChannel:= Channel; 143 | FCHBit:= ($1 shl Ord(FChannel)); 144 | 145 | with TTimerGROUP.Instance do 146 | begin 147 | FTIM_IRQ_CTL:= TMR_IRQ_CTRL; 148 | FTIM_IRQ_STA:= TMR_IRQ_STA; 149 | FTIM_CTRL:= TMR_CTRL[Ord(FChannel)]; 150 | FTIM_INTV:= TMR_INTV_VALUE[Ord(FChannel)]; 151 | FTIM_CURR:= TMR_CURR_VALUE[Ord(FChannel)]; 152 | end; 153 | 154 | FMode:= Single; 155 | SetMode(Single); 156 | FAutoReload:= True; 157 | SetAutoReload(True); 158 | FCLK:= OSC24M; 159 | SetCLK(OSC24M); 160 | FPrescal:= Div1; 161 | SetPrescal(Div1); 162 | FCNT:= 0; 163 | FCUR:= 0; 164 | SetINT(False); 165 | end; 166 | 167 | destructor TTimer.Destroy; 168 | begin 169 | Stop; 170 | end; 171 | 172 | procedure TTimer.SetMode(Value: TMode); 173 | begin 174 | FMode:= Value; 175 | case FMode of 176 | Loop: FTIM_CTRL^:= FTIM_CTRL^ and not ($1 shl 7); 177 | Single: FTIM_CTRL^:= FTIM_CTRL^ or ($1 shl 7); 178 | end; 179 | end; 180 | 181 | procedure TTimer.SetAutoReload(Value: Boolean); 182 | begin 183 | FAutoReload:= Value; 184 | 185 | case FAutoReload of 186 | True: FTIM_CTRL^:= FTIM_CTRL^ and not ($1 shl 1); 187 | False: FTIM_CTRL^:= FTIM_CTRL^ or ($1 shl 1); 188 | end; 189 | end; 190 | 191 | procedure TTimer.SetCLK(Value: TCLK); 192 | begin 193 | FCLK:= Value; 194 | 195 | FTIM_CTRL^:= FTIM_CTRL^ and not ($3 shl 2); 196 | FTIM_CTRL^:= FTIM_CTRL^ or (Ord(FCLK) shl 2); 197 | end; 198 | 199 | procedure TTimer.SetPrescal(Value: TPrescal); 200 | begin 201 | FPrescal:= Value; 202 | 203 | FTIM_CTRL^:= FTIM_CTRL^ and not ($3 shl 4); 204 | FTIM_CTRL^:= FTIM_CTRL^ or (Ord(FPrescal) shl 4) 205 | end; 206 | 207 | procedure TTimer.SetCNT(Value: LongWord); 208 | begin 209 | FCNT:= Value; 210 | FTIM_INTV^:= FCNT; 211 | end; 212 | 213 | procedure TTimer.SetCUR(Value: LongWord); 214 | begin 215 | FCUR:= Value; 216 | FTIM_CURR^:= FCUR; 217 | end; 218 | 219 | procedure TTimer.SetINT(INT: Boolean); 220 | begin 221 | case INT of 222 | False: FTIM_IRQ_CTL^:= FTIM_IRQ_CTL^ and not FCHBit; 223 | True: FTIM_IRQ_CTL^:= FTIM_IRQ_CTL^ or FCHBit; 224 | end; 225 | end; 226 | 227 | function TTimer.GetINT: Boolean; 228 | begin 229 | Result:= (FTIM_IRQ_STA^ and FCHBit) = FCHBit; 230 | end; 231 | 232 | procedure TTimer.ClearPending; 233 | begin 234 | FTIM_IRQ_STA^:= FTIM_IRQ_STA^ or FCHBit; 235 | end; 236 | 237 | procedure TTimer.Start; 238 | begin 239 | FTIM_CTRL^:= FTIM_CTRL^ or $1; 240 | end; 241 | 242 | procedure TTimer.Stop; 243 | begin 244 | FTIM_CTRL^:= FTIM_CTRL^ and not $1; 245 | end; 246 | 247 | 248 | finalization 249 | TTimerGROUP.Instance.Release; 250 | 251 | end. 252 | -------------------------------------------------------------------------------- /Clock.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的System Clock底层操作封装类。单例。 3 | 作者:tjCFeng 4 | 邮箱:tjCFeng@163.com 5 | 更新日期:2014.12.06 6 | *) 7 | 8 | unit Clock; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses SysUtils, A20; 15 | 16 | type 17 | TCCU = class 18 | private 19 | class var FInstance: TCCU; 20 | class function GetInstance: TCCU; static; 21 | public 22 | class procedure Release; 23 | class property Instance: TCCU read GetInstance; 24 | 25 | private 26 | FCCU_BASE: ^LongWord; 27 | 28 | FPLL1_CFG: ^LongWord; 29 | FPLL1_TUN: ^LongWord; 30 | FPLL2_CFG: ^LongWord; 31 | FPLL2_TUN: ^LongWord; 32 | FPLL3_CFG: ^LongWord; 33 | FPLL4_CFG: ^LongWord; 34 | FPLL5_CFG: ^LongWord; 35 | FPLL5_TUN: ^LongWord; 36 | FPLL6_CFG: ^LongWord; 37 | FPLL6_TUN: ^LongWord; 38 | FPLL7_CFG: ^LongWord; 39 | FPLL1_TUN2: ^LongWord; 40 | FPLL5_TUN2: ^LongWord; 41 | FPLL8_CFG: ^LongWord; 42 | 43 | FOSC24M_CFG: ^LongWord; 44 | FCPU_AHB_APB0_CFG: ^LongWord; 45 | FAPB1_CLK_DIV: ^LongWord; 46 | FAHB_GATING0: ^LongWord; 47 | FAHB_GATING1: ^LongWord; 48 | FAPB0_GATING: ^LongWord; 49 | FAPB1_GATING: ^LongWord; 50 | 51 | FNAND_SCLK_CFG: ^LongWord; 52 | FMS_SCLK_CFG: ^LongWord; 53 | 54 | FSD0_CLK: ^LongWord; 55 | FSD1_CLK: ^LongWord; 56 | FSD2_CLK: ^LongWord; 57 | FSD3_CLK: ^LongWord; 58 | 59 | FTS_CLK: ^LongWord; 60 | FSS_CLK: ^LongWord; 61 | 62 | FSPI0_CLK: ^LongWord; 63 | FSPI1_CLK: ^LongWord; 64 | FSPI2_CLK: ^LongWord; 65 | 66 | FIR0_CLK: ^LongWord; 67 | FIR1_CLK: ^LongWord; 68 | 69 | FIIS0_CLK: ^LongWord; 70 | FAC97_CLK: ^LongWord; 71 | FSPDIF_CLK: ^LongWord; 72 | 73 | FKEYPAD_CLK: ^LongWord; 74 | FSATA_CLK: ^LongWord; 75 | FUSB_CLK: ^LongWord; 76 | FSPI3_CLK: ^LongWord; 77 | FIIS1_CLK: ^LongWord; 78 | FIIS2_CLK: ^LongWord; 79 | FDRAM_CLK: ^LongWord; 80 | 81 | FBE0_SCLK_CFG: ^LongWord; 82 | FBE1_SCLK_CFG: ^LongWord; 83 | FFE0_CLK: ^LongWord; 84 | FFE1_CLK: ^LongWord; 85 | 86 | FMP_CLK: ^LongWord; 87 | FLCD0_CH0_CLK: ^LongWord; 88 | FLCD1_CH0_CLK: ^LongWord; 89 | FCSI_SCLK: ^LongWord; 90 | FTVD_CLK: ^LongWord; 91 | FLCD0_CH1_CLK: ^LongWord; 92 | FLCD1_CH1_CLK: ^LongWord; 93 | FCSI0_CLK: ^LongWord; 94 | FCSI1_CLK: ^LongWord; 95 | 96 | FVE_CLK: ^LongWord; 97 | FAUDIO_CODEC_CLK: ^LongWord; 98 | FAVS_CLK: ^LongWord; 99 | FACE_CLK: ^LongWord; 100 | FLVDS_CLK: ^LongWord; 101 | FHDMI_CLK: ^LongWord; 102 | FMALI400_CLK: ^LongWord; 103 | FMBUS_SCLK_CFG: ^LongWord; 104 | FGMAC_CLK: ^LongWord; 105 | FHDMI1_RST: ^LongWord; 106 | FHDMI1_CTRL: ^LongWord; 107 | FHDMI1_SLOW_CLK: ^LongWord; 108 | FHDMI1_REPEAT_CLK: ^LongWord; 109 | 110 | FCLK_OUTA: ^LongWord; 111 | FCLK_OUTB: ^LongWord; 112 | 113 | constructor Create; 114 | destructor Destroy; override; 115 | public 116 | function Get_CorePLL: LongWord; 117 | function Get_AXI: LongWord; 118 | function Get_AHB: LongWord; 119 | function Get_APB0: LongWord; 120 | function Get_APB1: LongWord; 121 | public 122 | procedure CLK_SetGPIO(ED: Boolean); 123 | function CLK_GetGPIO: Boolean; 124 | 125 | procedure CLK_SetTWI(IndexTWI: Byte; ED: Boolean); 126 | function CLK_GetTWI(IndexTWI: Byte): Boolean; 127 | 128 | procedure CLK_SetSPI(IndexSPI: Byte; ED: Boolean); 129 | function CLK_GetSPI(IndexSPI: Byte): Boolean; 130 | end; 131 | 132 | implementation 133 | 134 | const 135 | CCU_BASE = $01C20000; 136 | 137 | class function TCCU.GetInstance: TCCU; 138 | begin 139 | if FInstance = nil then FInstance:= TCCU.Create; 140 | Result:= FInstance; 141 | end; 142 | 143 | class procedure TCCU.Release; 144 | begin 145 | FreeAndNil(FInstance); 146 | end; 147 | 148 | 149 | constructor TCCU.Create; 150 | var Base: LongWord; 151 | begin 152 | inherited Create; 153 | 154 | FCCU_BASE:= TA20.Instance.GetMMap(CCU_BASE); 155 | Base:= LongWord(FCCU_BASE) + TA20.Instance.BaseOffset(CCU_BASE); 156 | 157 | FPLL1_CFG:= Pointer(Base + $0000); 158 | FPLL1_TUN:= Pointer(Base + $0004); 159 | FPLL2_CFG:= Pointer(Base + $0008); 160 | FPLL2_TUN:= Pointer(Base + $000C); 161 | FPLL3_CFG:= Pointer(Base + $0010); 162 | FPLL4_CFG:= Pointer(Base + $0018); 163 | FPLL5_CFG:= Pointer(Base + $0020); 164 | FPLL5_TUN:= Pointer(Base + $0024); 165 | FPLL6_CFG:= Pointer(Base + $0028); 166 | FPLL6_TUN:= Pointer(Base + $002C); 167 | FPLL7_CFG:= Pointer(Base + $0030); 168 | FPLL1_TUN2:= Pointer(Base + $0038); 169 | FPLL5_TUN2:= Pointer(Base + $003C); 170 | FPLL8_CFG:= Pointer(Base + $0040); 171 | 172 | FOSC24M_CFG:= Pointer(Base + $0050); 173 | FCPU_AHB_APB0_CFG:= Pointer(Base + $0054); 174 | FAPB1_CLK_DIV:= Pointer(Base + $0058); 175 | FAHB_GATING0:= Pointer(Base + $0060); 176 | FAHB_GATING1:= Pointer(Base + $0064); 177 | FAPB0_GATING:= Pointer(Base + $0068); 178 | FAPB1_GATING:= Pointer(Base + $006C); 179 | 180 | FNAND_SCLK_CFG:= Pointer(Base + $0080); 181 | FMS_SCLK_CFG:= Pointer(Base + $0084); 182 | 183 | FSD0_CLK:= Pointer(Base + $0088); 184 | FSD1_CLK:= Pointer(Base + $008C); 185 | FSD2_CLK:= Pointer(Base + $0090); 186 | FSD3_CLK:= Pointer(Base + $0094); 187 | 188 | FTS_CLK:= Pointer(Base + $0098); 189 | FSS_CLK:= Pointer(Base + $009C); 190 | 191 | FSPI0_CLK:= Pointer(Base + $00A0); 192 | FSPI1_CLK:= Pointer(Base + $00A4); 193 | FSPI2_CLK:= Pointer(Base + $00A8); 194 | 195 | FIR0_CLK:= Pointer(Base + $00B0); 196 | FIR1_CLK:= Pointer(Base + $00B4); 197 | 198 | FIIS0_CLK:= Pointer(Base + $00B8); 199 | FAC97_CLK:= Pointer(Base + $00BC); 200 | FSPDIF_CLK:= Pointer(Base + $00C0); 201 | 202 | FKEYPAD_CLK:= Pointer(Base + $00C4); 203 | FSATA_CLK:= Pointer(Base + $00C8); 204 | FUSB_CLK:= Pointer(Base + $00CC); 205 | FSPI3_CLK:= Pointer(Base + $00D4); 206 | FIIS1_CLK:= Pointer(Base + $00D8); 207 | FIIS2_CLK:= Pointer(Base + $00DC); 208 | FDRAM_CLK:= Pointer(Base + $0100); 209 | 210 | FBE0_SCLK_CFG:= Pointer(Base + $0104); 211 | FBE1_SCLK_CFG:= Pointer(Base + $0108); 212 | FFE0_CLK:= Pointer(Base + $010C); 213 | FFE1_CLK:= Pointer(Base + $0110); 214 | 215 | FMP_CLK:= Pointer(Base + $0114); 216 | FLCD0_CH0_CLK:= Pointer(Base + $0118); 217 | FLCD1_CH0_CLK:= Pointer(Base + $011C); 218 | FCSI_SCLK:= Pointer(Base + $0120); 219 | FTVD_CLK:= Pointer(Base + $0128); 220 | FLCD0_CH1_CLK:= Pointer(Base + $012C); 221 | FLCD1_CH1_CLK:= Pointer(Base + $0130); 222 | FCSI0_CLK:= Pointer(Base + $0134); 223 | FCSI1_CLK:= Pointer(Base + $0138); 224 | 225 | FVE_CLK:= Pointer(Base + $013C); 226 | FAUDIO_CODEC_CLK:= Pointer(Base + $0140); 227 | FAVS_CLK:= Pointer(Base + $0144); 228 | FACE_CLK:= Pointer(Base + $0148); 229 | FLVDS_CLK:= Pointer(Base + $014C); 230 | FHDMI_CLK:= Pointer(Base + $0150); 231 | FMALI400_CLK:= Pointer(Base + $0154); 232 | FMBUS_SCLK_CFG:= Pointer(Base + $015C); 233 | FGMAC_CLK:= Pointer(Base + $0164); 234 | FHDMI1_RST:= Pointer(Base + $0170); 235 | FHDMI1_CTRL:= Pointer(Base + $0174); 236 | FHDMI1_SLOW_CLK:= Pointer(Base + $0178); 237 | FHDMI1_REPEAT_CLK:= Pointer(Base + $017C); 238 | 239 | FCLK_OUTA:= Pointer(Base + $01F0); 240 | FCLK_OUTB:= Pointer(Base + $01F4); 241 | 242 | //FOSC24M_CFG^:= FOSC24M_CFG^ or (($1 shl 16) + ($1 shl 15) + ($1 shl 1) + $1); 243 | end; 244 | 245 | destructor TCCU.Destroy; 246 | begin 247 | TA20.Instance.FreeMMap(FCCU_BASE); 248 | inherited Destroy; 249 | end; 250 | 251 | (******************************************************************************) 252 | function TCCU.Get_CorePLL: LongWord; 253 | var P, M, N, K: LongWord; 254 | begin 255 | Result:= FPLL1_CFG^; 256 | 257 | P:= 1 shl ((Result shr 16) and $03); 258 | N:= (Result shr 8) and $1F; 259 | M:= ((Result shr 0) and $03) + 1; 260 | K:= ((Result shr 4) and $03) + 1; 261 | 262 | Result:= 24000000 * N * K div P div M; 263 | end; 264 | 265 | function TCCU.Get_AXI: LongWord; 266 | var CLKSRC, Factor: LongWord; 267 | begin 268 | Result:= FCPU_AHB_APB0_CFG^; 269 | 270 | CLKSRC:= (Result shr 16) and $03; 271 | Factor:= ((Result shr 0) and $03) + 1; 272 | 273 | case CLKSRC of 274 | 0: Result:= 32000; 275 | 1: Result:= 24000000; 276 | 2: Result:= Get_CorePLL; 277 | else 278 | Result:= 0; 279 | end; 280 | end; 281 | 282 | function TCCU.Get_AHB: LongWord; 283 | var Factor: LongWord; 284 | begin 285 | Factor:= (FCPU_AHB_APB0_CFG^ shr 4) and $03; 286 | Result:= Get_AXI shr Factor; 287 | end; 288 | 289 | function TCCU.Get_APB0: LongWord; 290 | var Factor: LongWord; 291 | begin 292 | Factor:= (FCPU_AHB_APB0_CFG^ shr 8) and $03; 293 | 294 | if (Factor > 0) then 295 | Result:= Get_AHB shr Factor 296 | else 297 | Result:= Get_AHB shr 1; 298 | end; 299 | 300 | function TCCU.Get_APB1: LongWord; 301 | var Factor: LongWord; 302 | begin 303 | Result:= 0; 304 | 305 | Factor:= (FAPB1_CLK_DIV^ shr 24) and $03; 306 | if (Factor = 0) then Result:= 24000000; 307 | end; 308 | 309 | 310 | (******************************************************************************) 311 | procedure TCCU.CLK_SetGPIO(ED: Boolean); 312 | begin 313 | case ED of 314 | False: FAPB0_GATING^:= FAPB0_GATING^ and not ($1 shl 5); 315 | True: FAPB0_GATING^:= FAPB0_GATING^ or ($1 shl 5); 316 | end; 317 | end; 318 | 319 | function TCCU.CLK_GetGPIO: Boolean; 320 | begin 321 | Result:= (FAPB0_GATING^ and ($1 shl 5) = 1); 322 | end; 323 | 324 | procedure TCCU.CLK_SetTWI(IndexTWI: Byte; ED: Boolean); 325 | var Bit: Byte; 326 | begin 327 | case IndexTWI of 328 | 0..3: Bit:= IndexTWI; 329 | 4: Bit:= 15; 330 | end; 331 | 332 | case ED of 333 | False: FAPB1_GATING^:= FAPB1_GATING^ and not ($1 shl Bit); 334 | True: FAPB1_GATING^:= FAPB1_GATING^ or ($1 shl Bit); 335 | end; 336 | end; 337 | 338 | function TCCU.CLK_GetTWI(IndexTWI: Byte): Boolean; 339 | begin 340 | case IndexTWI of 341 | 0..3: Result:= (FAPB1_GATING^ and ($1 shl IndexTWI) = 1); 342 | 4: Result:= (FAPB1_GATING^ and ($1 shl 15) = 1); 343 | end; 344 | end; 345 | 346 | procedure TCCU.CLK_SetSPI(IndexSPI: Byte; ED: Boolean); 347 | begin 348 | case ED of 349 | False: FAHB_GATING0^:= FAHB_GATING0^ and not ($1 shl (IndexSPI + 20)); 350 | True: FAHB_GATING0^:= FAHB_GATING0^ or ($1 shl (IndexSPI + 20)); 351 | end; 352 | end; 353 | 354 | function TCCU.CLK_GetSPI(IndexSPI: Byte): Boolean; 355 | begin 356 | Result:= (FAHB_GATING0^ and ($1 shl (IndexSPI + 20)) = 1); 357 | end; 358 | 359 | 360 | finalization 361 | TCCU.Instance.Release; 362 | 363 | end. 364 | -------------------------------------------------------------------------------- /TWI.pas: -------------------------------------------------------------------------------- 1 | (* 2 | 说明:全志A20的TWI底层操作封装类。 3 | 作者:tjCFeng 4 | 邮箱:tjCFeng@163.com 5 | 更新日期:2014.12.06 6 | *) 7 | 8 | unit TWI; 9 | 10 | {$mode objfpc}{$H+} 11 | 12 | interface 13 | 14 | uses SysUtils, A20, Clock, GPIO; 15 | 16 | type 17 | TChannel = (TWI_0, TWI_1, TWI_2, TWI_3, TWI_4); 18 | TI2CSpeed = (I2C100K, I2C400K); 19 | 20 | TTWI = class 21 | private 22 | FChannel: TChannel; 23 | FSpeed: TI2CSpeed; 24 | FBus: Boolean; 25 | FAutoACK: Boolean; 26 | 27 | FSCK: TGPIO; 28 | FSDA: TGPIO; 29 | 30 | FTimeOut: LongWord; 31 | FTWI_BASE: ^LongWord; 32 | protected 33 | FTWI_ADDR: ^LongWord; //TWI Slave address 34 | FTWI_XADDR: ^LongWord; //TWI Extended slave address 35 | FTWI_DATA: ^LongWord; //TWI Data byte 36 | FTWI_CNTR: ^LongWord; //TWI Control register 37 | FTWI_STAT: ^LongWord; //TWI Status register 38 | FTWI_CCR: ^LongWord; //TWI Clock control register 39 | FTWI_SRST: ^LongWord; //TWI Software reset 40 | FTWI_EFR: ^LongWord; //TWI Enhance Feature register 41 | FTWI_LCR: ^LongWord; //TWI Line Control register 42 | private 43 | procedure SetSpeed(Value: TI2CSpeed); 44 | procedure SetBus(Value: Boolean); 45 | procedure SetAutoACK(Value: Boolean); 46 | function GetState(State: Byte): Boolean; 47 | 48 | function SendReset: Boolean; 49 | function SendStart: Boolean; 50 | function SendReStart: Boolean; 51 | function SendStop: Boolean; 52 | function SetByte(Dat: Byte): Boolean; 53 | function GetByte(out Dat: Byte): Boolean; 54 | public 55 | constructor Create(Channel: TChannel); 56 | destructor Destroy; override; 57 | 58 | function Write(Addr: Byte; Reg: Byte; Dat: Byte): Boolean; 59 | function Read(Addr: Byte; Reg: Byte; out Dat: Byte): Boolean; 60 | public 61 | property Speed: TI2CSpeed read FSpeed write SetSpeed; 62 | property Bus: Boolean read FBus write SetBus; 63 | property AutoACK: Boolean read FAutoACK write SetAutoACK; 64 | end; 65 | 66 | implementation 67 | 68 | const 69 | TWI_BASE = $01C2AC00; 70 | TWI_TIMEOUT = $FFFFFF; 71 | 72 | const 73 | TWI_CNTR_ACK = $04; //($1 shl 2); 74 | TWI_CNTR_INT = $08; //($1 shl 3); 75 | TWI_CNTR_STP = $10; //($1 shl 4); 76 | TWI_CNTR_STA = $20; //($1 shl 5); 77 | TWI_CNTR_BUSEN = $40; //($1 shl 6); 78 | TWI_CNTR_INTEN = $80; //($1 shl 7); 79 | 80 | const 81 | TWI_SRST_RESET = $1; //($1 shl 0); 82 | 83 | const 84 | TWI_CCR_M = ($F shl 3); 85 | TWI_CCR_N = ($7 shl 0); 86 | 87 | const 88 | TWI_STAT_BUS_ERR = $00; // BUS ERROR 89 | (* Master mode use only *) 90 | TWI_STAT_TX_STA = $08; // START condition transmitted 91 | TWI_STAT_TX_RESTA = $10; // Repeated START condition transmitted 92 | TWI_STAT_TX_AW_ACK = $18; // Address+Write bit transmitted, ACK received 93 | TWI_STAT_TX_AW_NAK = $20; // Address+Write bit transmitted, ACK not received 94 | TWI_STAT_TXD_ACK = $28; // data byte transmitted in master mode,ack received 95 | TWI_STAT_TXD_NAK = $30; // data byte transmitted in master mode ,ack not received 96 | TWI_STAT_ARBLOST = $38; // arbitration lost in address or data byte 97 | TWI_STAT_TX_AR_ACK = $40; // Address+Read bit transmitted, ACK received 98 | TWI_STAT_TX_AR_NAK = $48; // Address+Read bit transmitted, ACK not received 99 | TWI_STAT_RXD_ACK = $50; // data byte received in master mode ,ack transmitted 100 | TWI_STAT_RXD_NAK = $58; // date byte received in master mode,not ack transmitted 101 | (* Slave mode use only *) 102 | TWI_STAT_RXWS_ACK = $60; // Slave address+Write bit received, ACK transmitted 103 | TWI_STAT_ARBLOST_RXWS_ACK = $68; 104 | TWI_STAT_RXGCAS_ACK = $70; // General Call address received, ACK transmitted 105 | TWI_STAT_ARBLOST_RXGCAS_ACK = $78; 106 | TWI_STAT_RXDS_ACK = $80; 107 | TWI_STAT_RXDS_NAK = $88; 108 | TWI_STAT_RXDGCAS_ACK = $90; 109 | TWI_STAT_RXDGCAS_NAK = $98; 110 | TWI_STAT_RXSTPS_RXRESTAS = $A0; 111 | TWI_STAT_RXRS_ACK = $A8; 112 | 113 | TWI_STAT_ARBLOST_SLAR_ACK = $B0; 114 | 115 | (* 10bit Address, second part of address *) 116 | TWI_STAT_TX_SAW_ACK = $D0; // Second Address byte+Write bit transmitted,ACK received 117 | TWI_STAT_TX_SAW_NAK = $D8; // Second Address byte+Write bit transmitted,ACK not received 118 | 119 | TWI_STAT_IDLE = $F8; // No relevant status infomation,INT_FLAG = 0 120 | 121 | const 122 | TWI_LCR_SDA_EN = $01; //($1 shl 0); 123 | TWI_LCR_SDA_CTL = $02; //($1 shl 1); 124 | TWI_LCR_SCL_EN = $04; //($1 shl 2); 125 | TWI_LCR_SCL_CTL = $08; //($1 shl 3); 126 | TWI_LCR_SDA_STATE = $10; //($1 shl 4); 127 | TWI_LCR_SCL_STATE = $20; //($1 shl 5); 128 | 129 | const 130 | TWI_LCR_DEFAULT = $3A; 131 | 132 | constructor TTWI.Create(Channel: TChannel); 133 | var Base: LongWord; 134 | begin 135 | inherited Create; 136 | 137 | FChannel:= Channel; 138 | 139 | FTWI_BASE:= TA20.Instance.GetMMap(TWI_BASE + Ord(FChannel) * $400); 140 | Base:= LongWord(FTWI_BASE) + TA20.Instance.BaseOffset(TWI_BASE + Ord(FChannel) * $400); 141 | 142 | FTWI_ADDR:= Pointer(Base + $0000); 143 | FTWI_XADDR:= Pointer(Base + $0004); 144 | FTWI_DATA:= Pointer(Base + $0008); 145 | FTWI_CNTR:= Pointer(Base + $000C); 146 | FTWI_STAT:= Pointer(Base + $0010); 147 | FTWI_CCR:= Pointer(Base + $0014); 148 | FTWI_SRST:= Pointer(Base + $0018); 149 | FTWI_EFR:= Pointer(Base + $001C); 150 | FTWI_LCR:= Pointer(Base + $0020); 151 | 152 | case FChannel of 153 | TWI_0: begin 154 | FSCK:= TGPIO.Create(PB, 0); 155 | FSCK.Fun:= Fun2; 156 | FSDA:= TGPIO.Create(PB, 1); 157 | FSDA.Fun:= Fun2; 158 | end; 159 | TWI_1: begin 160 | FSCK:= TGPIO.Create(PB, 18); 161 | FSCK.Fun:= Fun2; 162 | FSDA:= TGPIO.Create(PB, 19); 163 | FSDA.Fun:= Fun2; 164 | end; 165 | TWI_2: begin 166 | FSCK:= TGPIO.Create(PB, 20); 167 | FSCK.Fun:= Fun2; 168 | FSDA:= TGPIO.Create(PB, 21); 169 | FSDA.Fun:= Fun2; 170 | end; 171 | TWI_3: begin 172 | FSCK:= TGPIO.Create(PI, 0); 173 | FSCK.Fun:= Fun3; 174 | FSDA:= TGPIO.Create(PI, 1); 175 | FSDA.Fun:= Fun3; 176 | end; 177 | TWI_4: begin 178 | FSCK:= TGPIO.Create(PI, 2); 179 | FSCK.Fun:= Fun3; 180 | FSDA:= TGPIO.Create(PI, 3); 181 | FSDA.Fun:= Fun3; 182 | end; 183 | end; 184 | 185 | TCCU.Instance.CLK_SetTWI(Ord(FChannel), True); 186 | SetSpeed(I2C100K); 187 | SetBus(True); 188 | SetAutoACK(True); 189 | FTWI_CNTR^:= FTWI_CNTR^ or ($1 shl 7); 190 | 191 | SendReset; 192 | end; 193 | 194 | destructor TTWI.Destroy; 195 | begin 196 | SendReset; 197 | FSCK.Free; 198 | FSDA.Free; 199 | TA20.Instance.FreeMMap(FTWI_BASE); 200 | 201 | inherited Destroy; 202 | end; 203 | 204 | procedure TTWI.SetSpeed(Value: TI2CSpeed); 205 | begin 206 | FSpeed:= Value; 207 | 208 | FTWI_CCR^:= 0; 209 | case FSpeed of 210 | I2C100K: FTWI_CCR^:= FTWI_CCR^ or (3 shl 3) or 3; 211 | I2C400K: FTWI_CCR^:= FTWI_CCR^ or (5 shl 3) or 0; 212 | end; 213 | 214 | SendReset; 215 | end; 216 | 217 | function TTWI.SetByte(Dat: Byte): Boolean; 218 | begin 219 | FTimeOut:= TWI_TIMEOUT; 220 | FTWI_DATA^:= Dat; 221 | FTWI_CNTR^:= FTWI_CNTR^ and $F7; //Clear INT 222 | while ((FTWI_CNTR^ and TWI_CNTR_INT) = 0) and (FTimeOut > 0) do Dec(FTimeOut); 223 | Result:= (FTimeOut > 0); 224 | end; 225 | 226 | function TTWI.GetByte(out Dat: Byte): Boolean; 227 | begin 228 | FTimeOut:= TWI_TIMEOUT; 229 | FTWI_CNTR^:= FTWI_CNTR^ and $F7; //Clear INT 230 | while ((FTWI_CNTR^ and TWI_CNTR_INT) = 0) and (FTimeOut > 0) do Dec(FTimeOut); 231 | Result:= (FTimeOut > 0); 232 | 233 | Dat:= FTWI_DATA^; 234 | end; 235 | 236 | procedure TTWI.SetBus(Value: Boolean); 237 | begin 238 | FBus:= Value; 239 | case FBus of 240 | False: FTWI_CNTR^:= FTWI_CNTR^ and not TWI_CNTR_BUSEN; 241 | True: FTWI_CNTR^:= FTWI_CNTR^ or TWI_CNTR_BUSEN; 242 | end; 243 | end; 244 | 245 | procedure TTWI.SetAutoACK(Value: Boolean); 246 | begin 247 | FAutoACK:= Value; 248 | case FAutoACK of 249 | False: FTWI_CNTR^:= FTWI_CNTR^ and not TWI_CNTR_ACK; 250 | True: FTWI_CNTR^:= FTWI_CNTR^ or TWI_CNTR_ACK; 251 | end; 252 | end; 253 | 254 | function TTWI.GetState(State: Byte): Boolean; 255 | begin 256 | Result:= FTWI_STAT^ = State; 257 | end; 258 | 259 | function TTWI.SendReset: Boolean; 260 | begin 261 | FTimeOut:= TWI_TIMEOUT; 262 | FTWI_SRST^:= FTWI_SRST^ or TWI_SRST_RESET; 263 | while ((FTWI_SRST^ and TWI_SRST_RESET) = TWI_SRST_RESET) and (FTimeOut > 0) do Dec(FTimeOut); 264 | Result:= (FTimeOut > 0); 265 | end; 266 | 267 | function TTWI.SendStart: Boolean; 268 | begin 269 | SendReset; 270 | FTWI_CNTR^:= (FTWI_CNTR^ and $C0) or TWI_CNTR_STA; 271 | 272 | FTimeOut:= TWI_TIMEOUT; 273 | while ((FTWI_CNTR^ and TWI_CNTR_INT) = 0) and (FTimeOut > 0) do Dec(FTimeOut); 274 | if (FTimeOut = 0) then Exit(False); 275 | 276 | Result:= (FTWI_STAT^ = TWI_STAT_TX_STA); 277 | end; 278 | 279 | function TTWI.SendReStart: Boolean; 280 | begin 281 | FTWI_CNTR^:= (FTWI_CNTR^ and $C0) or TWI_CNTR_STA; 282 | 283 | FTimeOut:= TWI_TIMEOUT; 284 | while ((FTWI_CNTR^ and TWI_CNTR_INT) = 0) and (FTimeOut > 0) do Dec(FTimeOut); 285 | if (FTimeOut = 0) then Exit(False); 286 | 287 | Result:= (FTWI_STAT^ = TWI_STAT_TX_RESTA); 288 | end; 289 | 290 | function TTWI.SendStop: Boolean; 291 | begin 292 | FTWI_CNTR^:= (FTWI_CNTR^ and $C0) or TWI_CNTR_STP; 293 | 294 | FTimeOut:= TWI_TIMEOUT; 295 | while ((FTWI_CNTR^ and TWI_CNTR_STP) = TWI_CNTR_STP) and (FTimeOut > 0) do Dec(FTimeOut); 296 | Result:= (FTimeOut > 0); 297 | end; 298 | 299 | //INT_EN BUS_EN START STOP INT_FLAG ACK NOT NOT 300 | //7 6 5 4 3 2 1 0 301 | function TTWI.Write(Addr: Byte; Reg: Byte; Dat: Byte): Boolean; 302 | begin 303 | try 304 | FTWI_EFR^:= 0; 305 | FTimeOut:= TWI_TIMEOUT; 306 | while (not GetState(TWI_STAT_IDLE)) and (FTimeOut > 0) do Dec(FTimeOut); 307 | if (FTimeOut = 0) then Exit(False); 308 | 309 | if not SendStart then Exit(False); 310 | 311 | if not SetByte((Addr shl 1) or 0) then Exit(False); 312 | if not GetState(TWI_STAT_TX_AW_ACK) then Exit(False); 313 | 314 | if not SetByte(Reg) then Exit(False); 315 | if not GetState(TWI_STAT_TXD_ACK) then Exit(False); 316 | 317 | if not SetByte(Dat) then Exit(False); 318 | if not GetState(TWI_STAT_TXD_ACK) then Exit(False); 319 | 320 | Result:= True; 321 | finally 322 | SendStop; 323 | end; 324 | end; 325 | 326 | function TTWI.Read(Addr: Byte; Reg: Byte; out Dat: Byte): Boolean; 327 | begin 328 | try 329 | FTWI_EFR^:= 0; 330 | FTimeOut:= TWI_TIMEOUT; 331 | while (not GetState(TWI_STAT_IDLE)) and (FTimeOut > 0) do Dec(FTimeOut); 332 | if (FTimeOut = 0) then Exit(False); 333 | 334 | if not SendStart then Exit(False); 335 | 336 | if not SetByte((Addr shl 1) or 0) then Exit(False); 337 | if not GetState(TWI_STAT_TX_AW_ACK) then Exit(False); 338 | 339 | if not SetByte(Reg) then Exit(False); 340 | if not GetState(TWI_STAT_TXD_ACK) then Exit(False); 341 | 342 | if not SendReStart then Exit(False); 343 | 344 | if not SetByte((Addr shl 1) or 1) then Exit(False); 345 | if not GetState(TWI_STAT_TX_AR_ACK) then Exit(False); 346 | 347 | Result:= GetByte(Dat); 348 | //if not GetState($58) then Exit(False); 349 | finally 350 | SendStop; 351 | end; 352 | end; 353 | 354 | end. 355 | --------------------------------------------------------------------------------