• R/O
  • SSH
  • HTTPS

pasripherals: Commit


Commit MetaInfo

Revision23 (tree)
Zeit2019-08-18 10:15:30
Autorderekwildstar

Log Message

Concluí que a forma de uso do I2C para o ADS1115 estava errada. Existe uma quantidade específica de bytes que precisam ser enviados dentro de uma transação. Não é possível configurar os parâmetros do ADS aos poucos, por exemplo, primeiro o registrador config, então termina e depois outra operação, etc. Esta versão está sendo comitada apenas para que fique salva, pois vou alterar a unit UADS1115 de forma bem drástica

Ändern Zusammenfassung

Diff

--- trunk/src/lib/UADS1115.pas (revision 22)
+++ trunk/src/lib/UADS1115.pas (revision 23)
@@ -1,10 +1,8 @@
11 unit UADS1115;
22 {:< Esta unit contém todas as entidades necessárias que permitem o acesso
33 simplificado ao ADS1115}
4-{$mode objfpc}{$H+}
4+{$mode objfpc}{$H+}interface
55
6-interface
7-
86 uses
97 UPasRipherals;
108
@@ -15,10 +13,17 @@
1513 //: que o ADS1115 suporta
1614 TADS1115DataRate = (adr8SPS,adr16SPS,adr32SPS,adr64SPS,adr128SPS,adr250SPS,adr475SPS,dr860SPS);
1715
16+ TADS1115Mode = (amContinuous,amPowerDown);
17+ //: Esta enumeração representa registradores disponíves no ADS1115. Ao
18+ //: escrever o valor ordinal de um dos elementos desta enumeração no
19+ //: registrador POINTER, é feita a seleção do registrador correspondente, o
20+ //: qual é acessado em operações subsequentes
21+ TADS1115Register = (arConversion,arConfig,arLoThresh,arHiThresh);
22+
1823 //: Esta classe provê acesso simplificado ao ADS1115, um conversor
1924 //: analógico-digital de 16 bits muito popular
2025 //: @Member(AIn0 Obtém o valor da entrada analógica 0, que pode variar de 0
21- //: até 32767. Use esta propriedade apenas quando )
26+ //: até 32767)
2227 //: @Member(AIn1 Obtém o valor da entrada analógica 1, que pode variar de 0
2328 //: até 32767)
2429 //: @Member(AIn2 Obtém o valor da entrada analógica 2, que pode variar de 0
@@ -27,10 +32,29 @@
2732 //: até 32767)
2833 TADS1115 = class(TCustomPasRipherals)
2934 private
35+ FI2CController: TPRI2CController;
3036 FSlaveAddress: TPRI2CSlaveAddress;
3137
38+ //: Seleciona um dos registros do ADS1115. Este método funciona escrevendo
39+ //: dois bits no registrador POINTER a fim de informar ao ADS1115 qual
40+ //: registrador será referenciado nas operações subsequentes. A tabela 6 do
41+ //: datasheet contém os valores possíveis (p. 18). Este método levanta
42+ //: exceções caso, por algum motivo, não seja possível escrever no
43+ //: registrador POINTER
44+ //: @Param(ARegister Registrador que se quer selecionar)
45+ //: @SeeAlso(TADS1115Register)
46+ procedure SelectRegister(ARegister: TADS1115Register);
47+
48+ function GetConfigRegister: UInt16;
49+ procedure SetConfigRegister(AConfigurations: UInt16);
50+ //function GetConfigField: UInt16;
51+ //procedure SetConfigField(AFieldValue: UInt16);
52+
53+
54+
3255 function GetGainAplifier: TADS1115GainAplifier;
3356 function GetDataRate: TADS1115DataRate;
57+ function GetMode: TADS1115Mode;
3458 function GetAIn0: SmallInt;
3559 function GetAIn1: SmallInt;
3660 function GetAIn2: SmallInt;
@@ -38,10 +62,13 @@
3862
3963 procedure SetGainAplifier(AGainAmplifier: TADS1115GainAplifier);
4064 procedure SetDataRate(ADataRate: TADS1115DataRate);
65+ procedure SetMode(AMode: TADS1115Mode);
4166 public
42- constructor Create(ASlaveAddress: TPRI2CSlaveAddress); reintroduce;
67+ constructor Create(AI2CController: TPRI2CController; ASlaveAddress: TPRI2CSlaveAddress); reintroduce;
68+
4369 property GainAplifier: TADS1115GainAplifier read GetGainAplifier write SetGainAplifier;
4470 property DataRate: TADS1115DataRate read GetDataRate write SetDataRate;
71+ property Mode: TADS1115Mode read GetMode write SetMode;
4572
4673 { -37768 até 32767}
4774 property AIn0: SmallInt read GetAIn0;
@@ -50,11 +77,66 @@
5077 property AIn3: SmallInt read GetAIn3;
5178 end;
5279
80+ EADS1115 = class(EPasRipherals);
81+
5382 implementation
5483
84+uses
85+ TypInfo;
86+
87+const
88+ // As constantes abaixo represetam o índice de bits dentro de um mesmo
89+ // registrador. Adicionalmente, para cada constante de índice de bits, há uma
90+ // constante com sufixo "_SIZE" que indica quantos bits possui a informação. A
91+ // regra de nomenclatura é REGISTRADOR_CAMPO[_SIZE]
92+ CONFIG_COMP_QUE = 0; CONFIG_COMP_QUE_SIZE = 2;
93+ CONFIG_COMP_LAT = 2; CONFIG_COMP_LAT_SIZE = 1;
94+ CONFIG_COMP_POL = 3; CONFIG_COMP_POL_SIZE = 1;
95+ CONFIG_COMP_MODE = 4; CONFIG_COMP_MODE_SIZE = 1;
96+ CONFIG_DR = 5; CONFIG_DR_SIZE = 3;
97+ CONFIG_MODE = 8; CONFIG_MODE_SIZE = 1;
98+ CONFIG_PGA = 9; CONFIG_PGA_SIZE = 3;
99+ CONFIG_MUX = 12; CONFIG_MUX_SOZE = 3;
100+ CONFIG_OS = 15; CONFIG_OS_SIZE = 1;
101+
102+procedure TADS1115.SelectRegister(ARegister: TADS1115Register);
103+begin
104+ I2C[FI2CController,FSlaveAddress].Write8Bits(Byte(ARegister),'Erro ao selecionar o registrador "' + GetEnumName(TypeInfo(TADS1115Register),Ord(ARegister)));
105+end;
106+
107+function TADS1115.GetConfigRegister: UInt16;
108+begin
109+ // Seleciona o registrador de configurações
110+ SelectRegister(arConfig);
111+
112+ // Lê todo o registrador de configurações
113+ I2C[FI2CController,FSlaveAddress].Read16Bits(Result,'Erro ao ler o registrador de configurações');
114+end;
115+
116+procedure TADS1115.SetConfigRegister(AConfigurations: UInt16);
117+begin
118+ // Seleciona o registrador de configurações
119+ SelectRegister(arConfig);
120+
121+ // Escreve todo o registrador de configurações
122+ I2C[FI2CController,FSlaveAddress].Write16Bits(AConfigurations,'Erro ao escrever no registrador de configurações');
123+ //I2C[FI2CController,FSlaveAddress].Write8Bits(Hi(AConfigurations),'Erro ao escrever no registrador de configurações');
124+ //I2C[FI2CController,FSlaveAddress].Write8Bits(Lo(AConfigurations),'Erro ao escrever no registrador de configurações');
125+end;
126+
55127 function TADS1115.GetGainAplifier: TADS1115GainAplifier;
128+var
129+ Value: Byte;
56130 begin
131+ Value := GetBitsValue(GetConfigRegister,CONFIG_PGA,CONFIG_PGA_SIZE);
57132
133+ // Os 3 últimos valores possíveis para estes bits (5, 6 e 7) correspondem ao
134+ // mesmo ganho, os outros são diferentes entre si e podem ser obtidos a partir
135+ // de um cast direto
136+ if Value > 4 then
137+ Result := aga16
138+ else
139+ Result := TADS1115GainAplifier(Value);
58140 end;
59141
60142 function TADS1115.GetDataRate: TADS1115DataRate;
@@ -62,11 +144,18 @@
62144
63145 end;
64146
147+function TADS1115.GetMode: TADS1115Mode;
148+begin
149+ Result := TADS1115Mode(GetBitsValue(GetConfigRegister,CONFIG_MODE,CONFIG_MODE_SIZE));
150+end;
151+
65152 function TADS1115.GetAIn0: SmallInt;
66153 begin
67154 { Configure o mux para single end (100) antes de ler o valor
68155 configure como single shot ou usema propriedade para configurar este modo e só
69-permitir a execução aqui se o modo for single shot}
156+permitir a execução aqui se o modo for single shot
157+
158+crie uma propriedade chamada modo que pode ser single shot ou continuous. Verifique como funciona o modo continuo pra saber se se podera usar esta propriedade enquanto estre modo estiver ON}
70159 end;
71160
72161 function TADS1115.GetAIn1: SmallInt;
@@ -85,18 +174,45 @@
85174 end;
86175
87176 procedure TADS1115.SetGainAplifier(AGainAmplifier: TADS1115GainAplifier);
177+var
178+ ConfigRegister: Uint16;
88179 begin
89-
180+ ConfigRegister := GetConfigRegister;
181+ try
182+ SetBitsValue(@ConfigRegister,Byte(AGainAmplifier),CONFIG_PGA,CONFIG_PGA_SIZE);
183+ finally
184+ SetConfigRegister(ConfigRegister);
185+ end;
90186 end;
91187
92188 procedure TADS1115.SetDataRate(ADataRate: TADS1115DataRate);
189+var
190+ ConfigRegister: Uint16;
93191 begin
192+ ConfigRegister := GetConfigRegister;
193+ try
194+ SetBitsValue(@ConfigRegister,Byte(ADataRate),CONFIG_DR,CONFIG_DR_SIZE);
195+ finally
196+ SetConfigRegister(ConfigRegister);
197+ end;
198+end;
94199
200+procedure TADS1115.SetMode(AMode: TADS1115Mode);
201+var
202+ ConfigRegister: Uint16;
203+begin
204+ ConfigRegister := GetConfigRegister;
205+ try
206+ SetBitsValue(@ConfigRegister,Byte(AMode),CONFIG_MODE,CONFIG_MODE_SIZE);
207+ finally
208+ SetConfigRegister(ConfigRegister);
209+ end;
95210 end;
96211
97-constructor TADS1115.Create(ASlaveAddress: TPRI2CSlaveAddress);
212+constructor TADS1115.Create(AI2CController: TPRI2CController; ASlaveAddress: TPRI2CSlaveAddress);
98213 begin
99214 inherited Create;
215+ FI2CController := AI2CController;
100216 FSlaveAddress := ASlaveAddress;
101217 end;
102218
--- trunk/src/lib/UPasRipherals.pas (revision 22)
+++ trunk/src/lib/UPasRipherals.pas (revision 23)
@@ -538,15 +538,101 @@
538538 //: Byte (8 bits). Logo, concluo que o campo DATA do registrador FIFO é uma
539539 //: "porta" através da qual eu consigo ler o (ou escrver no) FIFO "real",
540540 //: que tem 128 bits (16 Bytes)
541- //: @param(ABuffer Buffer que precisa estar inicializado e com espaço
542- //: suficiente para receber os dados requisitados)
543- //: @param(ABufferSize Quantidade de dados que se pretende ler. Este valor
544- //: deve ser o tamanho exato do buffer indicado em ABuffer)
545- //: @returns(A função retorna um dos possíveis valores da enumeraçao
546- //: @link(TPRI2CTransferResult))
547- function Read(out ABuffer: PByte; ABufferSize: UInt32): TPRI2CTransferResult;
548-
541+ //: @Param(ABuffer Variável não inicializada que receberá os Bytes lidos a
542+ //: partir do FIFO. Esta variável será inicializada automáticamente pela
543+ //: função e precisará ser desalocada posteriormente pelo chamador)
544+ //: @Param(ABufferSize Quantidade de Bytes que se pretende ler. Este valor
545+ //: será usado pela função para inicializar a variável retornada no
546+ //: parâmetro ABuffer)
547+ //: @Returns(A função retorna um dos possíveis valores da enumeraçao
548+ //: @Link(TPRI2CTransferResult))
549+ function Read(out ABuffer: PByte; ABufferSize: UInt32): TPRI2CTransferResult; overload;
550+ //: Esta função lê 2 Bytes (16 bits) a partir do dispositivo escravo, lendo
551+ //: 2 bytes a partir do FIFO.
552+ //:
553+ //: Internamente a função troca a ordem dos bytes lidos a partir do FIFO
554+ //: Isso é necessário por causa da incompatibilidade entre a represetação de
555+ //: um PByte com dois bytes e um UInt16 (que tem dois bytes). Para entender
556+ //: melhor, use como exemplo o valor padrão do registrador CONFIG do
557+ //: ADS1115, que é 8583h. Na memória, o buffer lido é semelhante a um array
558+ //: com dois bytes [85,83]. Como se pode ver, a posição dos bytes na memória
559+ //: é na ordem correta de leitura, no entanto números são armazenados na
560+ //: memória da direita para a esquerda, fazendo com que o cast direto a
561+ //: partir dos dois bytes apontandos pelo buffer resultasse no número 8385h,
562+ //: que é errado. Para resolver, usa-se a função @Code(Swap), que troca a
563+ //: posição de dois bytes dentro de um UInt16, fazendo com que o resultado
564+ //: fique correto.
565+ //: @Param(AValue Este parâmetro de saída recebe os dois bytes lidos)
566+ //: @Returns(A função retorna um dos possíveis valores da enumeraçao
567+ //: @Link(TPRI2CTransferResult))
568+ function Read16Bits(out AValue: UInt16): TPRI2CTransferResult; overload;
569+ //: Esta função lê 2 Bytes (16 bits) a partir do dispositivo escravo, lendo
570+ //: 2 bytes a partir do FIFO de forma protegida. Ela levanta exceções em
571+ //: caso de erros. Após executar esta função, caso o fluxo de execução passe
572+ //: dela, signitica que os Byte foram lidos com suceso
573+ //: @Param(AValue Este parâmetro de saída recebe os dois bytes lidos)
574+ //: @Param(ABaseErrorMessage Mensagem de erro a ser apresentada de forma
575+ //: concatenada com o motivo do erro no formato @Code(ABaseErrorMessage:
576+ //: Motivo do erro))
577+ //: @Raises(EPasRipherals Esta exceção é levantada com a mensagem de erro
578+ //: informada em ABaseErrorMessage, concatenada com um dos possíveis motivos
579+ //: da falha)
580+ //: @SeeAlso(TPRI2CTransferResult)
581+ procedure Read16Bits(out AValue: UInt16; ABaseErrorMessage: String); overload;
582+ //: Escreve uma determinada quantidade de bytes no dispositivo escravo. Este
583+ //: método funciona escrevendo bytes no FIFO.
584+ //: @Param(ABuffer Memória que contém os bytes a serem escritos)
585+ //: @Param(ABufferSize Quantidade de bytes a serem escritos. Normalmente
586+ //: este valor é o mesmo valor utilizado para inicializar a variável que
587+ //: será passada em ABuffer)
588+ //: @Returns(A função retorna um dos possíveis valores da enumeraçao
589+ //: @Link(TPRI2CTransferResult))
549590 function Write(const ABuffer: PByte; ABufferSize: UInt32): TPRI2CTransferResult;
591+ //: Esta função escreve 2 Bytes (16 bits) no dispositivo escravo, escrevendo
592+ //: 2 Byte no FIFO. Internamente a função troca a ordem dos bytes informados
593+ //: no parâmetro, pelo mesmo motivo explicado na ajuda do método
594+ //: @Code(Read16Bits). @Bold(ATENÇÃO: NÃO UTILIZE ESTA FUNÇÃO PARA ESCREVER
595+ //: VALORES DE 8 BITS. PARA ESSA FINALIDADE, USE UMA DAS FORMAS DA FUNÇÃO
596+ //: @Link(Write8Bits))
597+ //: @Param(AValue Valor (2 Bytes) a serem escritos)
598+ //: @SeeAlso(Read16Bits)
599+ function Write16Bits(AValue: UInt16): TPRI2CTransferResult; overload;
600+ //: Esta função escreve 2 Bytes (16 bits) no dispositivo escravo, escrevendo
601+ //: 2 Byte no FIFO de forma protegida. Ela levanta exceções em caso de
602+ //: erros. Após executar esta função, caso o fluxo de execução passe dela,
603+ //: signitica que os Bytes foram escritos com suceso. Internamente a função
604+ //: troca a ordem dos bytes informados no parâmetro, pelo mesmo motivo
605+ //: explicado na ajuda do método @Code(Read16Bits). @Bold(ATENÇÃO: NÃO
606+ //: UTILIZE ESTA FUNÇÃO PARA ESCREVER VALORES DE 8 BITS. PARA ESSA
607+ //: FINALIDADE, USE UMA DAS FORMAS DA FUNÇÃO @Link(Write8Bits))
608+ //: @Param(AValue Valor (2 Bytes) a serem escritos)
609+ //: @Param(ABaseErrorMessage Mensagem de erro a ser apresentada de forma
610+ //: concatenada com o motivo do erro no formato @Code(ABaseErrorMessage:
611+ //: Motivo do erro))
612+ //: @Raises(EPasRipherals Esta exceção é levantada com a mensagem de erro
613+ //: informada em ABaseErrorMessage, concatenada com um dos possíveis motivos
614+ //: da falha)
615+ //: @SeeAlso(TPRI2CTransferResult)
616+ procedure Write16Bits(AValue: UInt16; ABaseErrorMessage: String); overload;
617+ //: Esta função escreve 1 Byte (8 bits) no dispositivo escravo, escrevendo
618+ //: 1 Byte no FIFO.
619+ //: @Param(AValue Valor a ser escrito)
620+ //: @Returns(A função retorna um dos possíveis valores da enumeraçao
621+ //: @Link(TPRI2CTransferResult))
622+ function Write8Bits(AValue: Byte): TPRI2CTransferResult; overload;
623+ //: Esta função escreve 1 Byte (8 bits) no dispositivo escravo, escrevendo
624+ //: 1 Byte no FIFO de forma protegida. Ela levanta exceções em caso de
625+ //: erros. Após executar esta função, caso o fluxo de execução passe dela,
626+ //: signitica que o byte foi escrito com suceso
627+ //: @Param(AValue Valor (1 Byte) a ser escrito)
628+ //: @Param(ABaseErrorMessage Mensagem de erro a ser apresentada de forma
629+ //: concatenada com o motivo do erro no formato @Code(ABaseErrorMessage:
630+ //: Motivo do erro))
631+ //: @Raises(EPasRipherals Esta exceção é levantada com a mensagem de erro
632+ //: informada em ABaseErrorMessage, concatenada com um dos possíveis motivos
633+ //: da falha)
634+ //: @SeeAlso(TPRI2CTransferResult)
635+ procedure Write8Bits(AValue: Byte; ABaseErrorMessage: String); overload;
550636
551637 property TransferType: TPRI2CTransferType read GetTransferType;
552638 property TransferActive: Boolean read GetTransferActive;
@@ -622,12 +708,6 @@
622708
623709 //: Use esta função para obter uma máscara com as características indicadas
624710 function GetBitsMask(ABitIndex: Byte; ABitsCount: Byte): UInt32;
625- //: Use esta função para retornar o valor de um conjunto de bits dentro de
626- //: um registrador de 32 bits
627- function GetBitsValue(ARegister: UInt32; ABitIndex: Byte; ABitsCount: Byte = 1): UInt32;
628- //: Use esta função para configurar o valor de um conjunto de bits dentro de
629- //: um registrador de 32 bits
630- procedure SetBitsValue(ARegister: PUInt32; AValue: UInt32; ABitIndex: Byte; ABitsCount: Byte = 1);
631711
632712 procedure PeripheralsBaseAddressAndSize(out ABaseAdddress: UInt32; out ASize: UInt32);
633713
@@ -634,10 +714,12 @@
634714 procedure NanoSleep(ANanoSeconds: Uint16);
635715 procedure MicroSleep(AMicroSeconds: Uint16);
636716 protected
637- //: Configura aspectos do clock do PWM
638- //procedure SetClockPWMConfigurations(AMash: TPRClockMash; ADivisorI: UInt16; ADivisorF: UInt16 = 0; AEnabled: Boolean = True);
639- //: Obtém as configurações vigentes a respeito do clock de PWM
640- //procedure GetClockPWMConfigurations(out AMash: TPRClockMash; out ADivisorI: UInt16; out ADivisorF: UInt16; out AEnabled: Boolean);
717+ //: Use esta função para retornar o valor de um conjunto de bits dentro de
718+ //: um registrador de até 32 bits de tamanho
719+ function GetBitsValue(ARegister: UInt32; ABitIndex: Byte; ABitsCount: Byte = 1): UInt32;
720+ //: Use esta função para configurar o valor de um conjunto de bits dentro de
721+ //: um registrador de até 32 bits de tamanho
722+ procedure SetBitsValue(ARegister: PUInt32; AValue: UInt32; ABitIndex: Byte; ABitsCount: Byte = 1);
641723
642724 property Clock[AClockId: TPRClockId]: TPRClock read GetClock;
643725 property GPIO[AGPIONumber: TPRGPIONumber]: TPRGPIO read GetGPIO;
@@ -1054,6 +1136,30 @@
10541136 SetTransferDone(True);
10551137 end;
10561138
1139+function TPRI2C.Read16Bits(out AValue: UInt16): TPRI2CTransferResult;
1140+var
1141+ RB: PByte;
1142+begin
1143+ // Lê 2 bytes (16 bits)
1144+ Result := Read(RB,2);
1145+
1146+ if Result = pritrSuccess then
1147+ try
1148+ AValue := Swap(PUInt16(RB)^);
1149+ finally
1150+ FreeMem(RB);
1151+ end;
1152+end;
1153+
1154+procedure TPRI2C.Read16Bits(out AValue: UInt16; ABaseErrorMessage: String);
1155+begin
1156+ case Read16Bits(AValue) of
1157+ pritrNak: raise EPasRipherals.Create(ABaseErrorMessage + ' : NAK');
1158+ pritrInsufficientData: raise EPasRipherals.Create(ABaseErrorMessage + ' : Dados insuficientes');
1159+ pritrTimeOut: raise EPasRipherals.Create(ABaseErrorMessage + ' : Tempo esgotado');
1160+ end;
1161+end;
1162+
10571163 function TPRI2C.Write(const ABuffer: PByte; ABufferSize: UInt32): TPRI2CTransferResult;
10581164 var
10591165 RemainingBytes: UInt32;
@@ -1087,7 +1193,7 @@
10871193 end;
10881194
10891195 // Inicia o processo de envio (escrita). Note que esta função, ao contrário do
1090- // que acontece em Read, não está limpando o FIFO porque nós vamos enviar o
1196+ // que acontece em Read16Bits, não está limpando o FIFO porque nós vamos enviar o
10911197 // que há dentro dele (veja o trecho de código anterior) para o dispositivo
10921198 // escravo
10931199 StartTransfer(prittWrite);
@@ -1123,6 +1229,47 @@
11231229 SetTransferDone(True);
11241230 end;
11251231
1232+function TPRI2C.Write16Bits(AValue: UInt16): TPRI2CTransferResult;
1233+//var
1234+// WB: PByte;
1235+begin
1236+ if AValue <= High(Byte) then
1237+ raise Exception.Create('O valor do parâmetro precisa estar compreendido entre 256 e 65535');
1238+
1239+ // Troca a posição dos bytes em AValue. Veja explicação detalhada no
1240+ // método Read16Bits
1241+ AValue := Swap(AValue);
1242+
1243+ //WB := @AValue;
1244+
1245+ // Escreve 2 Bytes (16 bits)
1246+ Result := Write(@AValue,2);
1247+end;
1248+
1249+procedure TPRI2C.Write16Bits(AValue: UInt16; ABaseErrorMessage: String);
1250+begin
1251+ case Write16Bits(AValue) of
1252+ pritrNak: raise EPasRipherals.Create(ABaseErrorMessage + ' : NAK');
1253+ pritrInsufficientData: raise EPasRipherals.Create(ABaseErrorMessage + ' : Dados insuficientes');
1254+ pritrTimeOut: raise EPasRipherals.Create(ABaseErrorMessage + ' : Tempo esgotado');
1255+ end;
1256+end;
1257+
1258+function TPRI2C.Write8Bits(AValue: Byte): TPRI2CTransferResult;
1259+begin
1260+ // Escreve 1 Byte (8 bits)
1261+ Result := Write(@AValue,1);
1262+end;
1263+
1264+procedure TPRI2C.Write8Bits(AValue: Byte; ABaseErrorMessage: String);
1265+begin
1266+ case Write8Bits(AValue) of
1267+ pritrNak: raise EPasRipherals.Create(ABaseErrorMessage + ' : NAK');
1268+ pritrInsufficientData: raise EPasRipherals.Create(ABaseErrorMessage + ' : Dados insuficientes');
1269+ pritrTimeOut: raise EPasRipherals.Create(ABaseErrorMessage + ' : Tempo esgotado');
1270+ end;
1271+end;
1272+
11261273 { TPRClock }
11271274
11281275 function TPRClock.RegisterCTL: PUInt32;
@@ -1731,17 +1878,6 @@
17311878 Result := (GPIOBaseAddress + GPIO_GPFSEL + Byte(AModeBank))^;
17321879 end;
17331880
1734-//procedure TCustomPasRipherals.GetClockPWMConfigurations(out AMash: TPRClockMash; out ADivisorI: UInt16; out ADivisorF: UInt16; out AEnabled: Boolean);
1735-//begin
1736-// if not FRunningAsRoot then
1737-// raise EPasRipherals.Create('Não é possível obter as configurações do clock do PWM porque você não tem privilégios suficientes');
1738-//
1739-// AMash := TPRClockMash(GetBitsValue((ClockBaseAddress + PWMCLOCK_CTL)^,9,2));
1740-// ADivisorF := GetBitsValue((ClockBaseAddress + PWMCLOCK_DIV)^,0,12);
1741-// ADivisorI := GetBitsValue((ClockBaseAddress + PWMCLOCK_DIV)^,12,12);
1742-// AEnabled := GetBitsValue((ClockBaseAddress + PWMCLOCK_CTL)^,4,1) = 1;
1743-//end;
1744-
17451881 //procedure TCustomPasRipherals.CalcClockPWMDivisor(APeriod: Byte; AResolution: UInt32; out ADivisorI: UInt16; out ADivisorF: UInt16);
17461882 //var
17471883 // MaximumRange: UInt32;
@@ -2221,84 +2357,6 @@
22212357 raise EPasRipherals.Create('Não foi possível obter o endereço-base dos periféricos');
22222358 end;
22232359
2224-//procedure TCustomPasRipherals.SetClockPWMConfigurations(AMash: TPRClockMash; ADivisorI: UInt16; ADivisorF: UInt16 = 0; AEnabled: Boolean = True);
2225-//var
2226-// CTLRegister: UInt32;
2227-//begin
2228-// if not FRunningAsRoot then
2229-// raise EPasRipherals.Create('Não é possível configurar o clock do PWM porque você não tem privilégios suficientes');
2230-//
2231-// {$WARNINGS OFF}
2232-// // Na página 108 do datashet o componente DIVI dos registradores de divisores
2233-// // de clock possui 12 bits (bits 12 a 23). Isso permite valores variando de 0
2234-// // a $FFF (4095), portanto apenas estes valores podem ser usados como DIVI em
2235-// // teoria, porque na prática isso muda. Segundo o datasheet p. 105 e 107, o
2236-// // valor mínimo aceitável é 1 e o valor máximo é 4095, por isso precisamos
2237-// // validar ADivisorI. Estas verificações não precisariam ser utilizadas se o
2238-// // Range Check Error estivesse habilitado de forma global no projeto, mas como
2239-// // eu não posso garantir que as IDEs todas tenham essa configuração
2240-// // habilitada, resolvi realizar a verificação. E não, não adianta habilitar o
2241-// // Range Check Error apenas nesta unit porque se ele estiver desabilitado nas
2242-// // configurações do projeto, alguém pode passar SIM, um valor fora do escopo
2243-// // de ADivisorI e isso só gera um simples warning. Outras bibliotecas
2244-// // "resolvem" o problema da validação de divisor usando simplesmente "Divisor
2245-// // and $FFF", mas isso não impede o uso de zero como divisor, o que pode
2246-// // causar problemas. É, dessa vez o Gert errou ;). Além do mais, segundo
2247-// // outras bibliotecas e literatura online, o menor divisor é 2, ou seja, os
2248-// // valores válidos variam de 2 a 4095 para DIVI e de 0 a 4095 para DIVF
2249-// if (ADivisorI < 2) or (ADivisorI > $FFF) then
2250-// raise EPasRipherals.CreateFmt('"%u" não é um valor válido para a parte inteira do divisor de clock. Valores válidos estão entre 2 e 4095',[ADivisorI]);
2251-//
2252-//
2253-// // Caso o Mash seja diferente de cmInteger, significa que vamos usar
2254-// // potencialmente a parte fracionária do divisor, logo, precisamos validar
2255-// // isso. No caso, a parte fracionária pode ser zero, por isso se valida apenas
2256-// // o limite superior do valor. Aqui, caso o Mash seja cmInteger, estamos
2257-// // zerando AClockDivisor.DivisorF, de forma a simplificar o código mais
2258-// // adiante, o qual sempre vai configurar a parte fracionária do divisor
2259-// if AMash <> prcmInteger then
2260-// begin
2261-// if ADivisorF > $FFF then
2262-// raise EPasRipherals.CreateFmt('"%u" não é um valor válido para o a parte fracionária do divisor clock. Valores válidos estão entre 0 e 4095',[ADivisorF]);
2263-// end
2264-// else
2265-// ADivisorF := 0;
2266-// {$WARNINGS ON}
2267-//
2268-// // Salva o registrador de controle do PWM a fim de podermos alterar o clock
2269-// // enquanto o PWM estiver configurado e ligado. Isso é uma forma de mudança de
2270-// // clock "on the fly"
2271-// CTLRegister := (PWMBaseAddress + PWM_CTL)^;
2272-// try
2273-// // Desativa o PWM antes de realizar a altração do clock.
2274-// (PWMBaseAddress + PWM_CTL)^ := 0;
2275-//
2276-// // Para o clock do PWM (datasheet p. 107). $01 = 0000 0001, logo, ENAB = 0 e
2277-// // SRC = 1 (oscillator). Sempre configura SRC como 1
2278-// (ClockBaseAddress + PWMCLOCK_CTL)^ := PASSWORD or $01;
2279-// MicroSleep(110);
2280-//
2281-// // Aguarda o clock realizar seu trabalho, verificando se o flag BUSY está
2282-// // ligado, basicamente a condição do while será false quando o clock parar,
2283-// // o que significa que estamos prontos para configurar o novo divisor
2284-// while ((ClockBaseAddress + PWMCLOCK_CTL)^ and $80) <> 0 do
2285-// MicroSleep(1);
2286-//
2287-// // Configura o divisor completamente (parte inteira e fracionárias. Aqui é
2288-// // garantido que os valores tenham no máximo 12 bits, tal como especificado
2289-// // no datasheet p. 108, por causa das validações realizadas no início deste
2290-// // método
2291-// (ClockBaseAddress + PWMCLOCK_DIV)^ := PASSWORD or (ADivisorI shl 12) or ADivisorF;
2292-//
2293-// // Reabilita o clock do PWM caso AEnabled = True. Novamente também está
2294-// // sendo configurado SRC = 1. O Mash também está sendo configurado aqui
2295-// (ClockBaseAddress + PWMCLOCK_CTL)^ := PASSWORD or (ShortInt(AMash) shl 9) or (AEnabled.ToInteger shl 4) or 1;
2296-// finally
2297-// // Recupera o registrador de controle do PWM
2298-// (PWMBaseAddress + PWM_CTL)^ := CTLRegister;
2299-// end;
2300-//end;
2301-
23022360 function TCustomPasRipherals.GPIOBaseAddress: PUInt32;
23032361 begin
23042362 Result := FPeripherals;
@@ -2324,12 +2382,7 @@
23242382
23252383 function TCustomPasRipherals.GetBitsValue(ARegister: UInt32; ABitIndex: Byte; ABitsCount: Byte = 1): UInt32;
23262384 begin
2327- // Usa shl para mover os bits para esquerda e assim deixar os bits de
2328- // interesse alinhados à esquerda dos 32 bits. Eles serão os últimos bits do
2329- // conjunto de 32 bits. Em seguida, realiza um shr para mover todos os bits
2330- // para a direita de forma que os bits de interesse fiquem alinhados à direita
2331- // e prontos para serem lidos
2332- Result := ARegister shl (32 - ABitsCount - ABitIndex) shr (32 - ABitsCount);
2385+ Result := ARegister and GetBitsMask(ABitIndex,ABitsCount) shr ABitIndex
23332386 end;
23342387
23352388 procedure TCustomPasRipherals.SetBitsValue(ARegister: PUInt32; AValue: UInt32; ABitIndex: Byte; ABitsCount: Byte);
Show on old repository browser