Rick's b.log - 2012/05/28 |
|
It is the 21st of November 2024 You are 18.117.105.40, pleased to meet you! |
|
mailto:
blog -at- heyrick -dot- eu
You can download a copy of the module.
On the RISC OS Open forum, I said I'd give a run-down of how the module operates, so here it is.
Here's the pre-amble. Basically, after a version comment, I load in four macro files:
Now we define the module name, version, date, and copyright string. Doing it here saves having stuff scattered around the source.
Now follow a number of definitions. These are simply names, so using "TickerV" in the code will result in the assembler swapping in "&1C"; much like #define in C.
It is worth noting that the OS vectors can be looked up in the RISC OS PRM1; the two LEDs are documented in the Beagle technical guide; the GPIO stuff is from the DM3730 TRM (should be compatible with the earlier DM3530); and the array is ours.
Now for the assembly preamble. We define an area, and mark it as code. Then we tell the assembler where the code entry point is (though, in the context of a RISC OS module, this is defined by convention). We don't mark it as 32 bit as we pass this via the command line in the Makefile. Otherwise, add
Now we define a standard RISC OS module. The start of the file is a header that contains information words and addresses. Refer to the PRMs if you need further details.
A word of data holding the address of the GPIO5 register.
The module initialisation function. RISC OS on a Beagleboard is a HAL build of RISC OS (HAL means Hardware Abstraction Layer; as traditional RISC OS used to talk directly to the hardware and was, thus, rather tied to the Acorn chipset). So we look for a HAL version of RISC OS, then knowing we're on something that'll work, we can then ask the HAL directly if we are on a Beagleboard.
The board type is at offset +64, and the board revision is at offset +68. As the Beagles have LED0 and LED1 on the same GPIO, we don't need to look to the revision. Any old Beagle will do.
Here are the currently defined board types and revisions:
Now we allocate space in the module area for our array (20 bytes) unless we are being re-entered due to
The next task is to map GPIO5 into the logical memory map. We map it in permanently, to save on having to map/unmap each time we access the LEDs.
As the LEDs are "on" when RISC OS starts, it might seem logical to assume they are set as outputs, but we force this just to be certain. Note the logic for handling the AND NOT, and that we keep a copy of the LED bitmask in R3 for later.
Using the copy of R3 we retained (not the inverted one), we write this to the Clear Data Out register to force both LEDs off.
Now the code to hook into the filesystem vectors. The code looks a little odd because if, for some reason, a vector claim fails, we must release claims made until that point (or it'll all go Bang!).
Our init is almost done. The final task is to set up the memory block. As the LED ticker counts down from 100, we initialise this to be 100. The other values initialise to be zero (fileop counter is zero, both LEDs flagged as off).
Here follows error message reporting, and tidying up from the vector claims.
This is the module finalisation routine. In a nutshell, we release the ticker, then the filesystem vectors, ensure both LEDs are off, then finally release our memory block.
The LDR of R12 from R12 is because R12 on entry is our private workspace word. So we load this into itself to turn it into a pointer to our array.
The commenting will guide you through the file op vector code. All you must remember at every point is all registers MUST be preserved (except our private R12) and we must be AS FAST AS POSSIBLE.
And here is the code for handling the ticker vector. It is a little more complicated, as the two LEDs can be in a variety of states: Off (disactivated), Counting (counting down to turn on or off), Switching (at zero, switching on or off). The ticker LED can switch on and off, the fileop LED can only switch off.
Here is a diagram of the ticker vector handler:
Note that we are entered in IRQ mode so we cannot call SWIs easily (we don't need to, but if you expand this code, keep this in mind).
All that remains is to embed a short message to pad out the file to be exactly 1024 bytes. No termination or alignment, as this is neither executed nor read, it's just something stuck at the end.
Here, presented as one lump, should be all the macro definitions you'll need. Load this instead of the four GETs at the top, it should work.
Finally, the Makefile...
Am I going to have to UPS the thing back to America? The cheapest UPS were willing to offer me was €168.32 - which is a joke. I must have entered something wrong somewhere.
BeagLEDs
I have written a short program called "BeagLEDs" which is a RISC OS module for the Beagleboard (any type). It will flash the left user LED on and off second by second, and the right user LED according to filesystem activity.
Note, however, that as we hook into filesystem activity at a fairly high level, it will blink for Ramdisc and ResourceFS accesses just as for real storage.
The blinking is damped, so the indicator will flick on for at least 15cs. This is to minimise lag due to our activities.
The important macro definitions are given at the end, you can collect them all into one file and tweak the stuff below. The SWInames file should be present with your development environment. If you don't have this, you'll need to define the following SWIs: XOS_ReadSysInfo, XOS_Memory, XOS_Hardware, XOS_Module, XOS_Claim, and XOS_Release.
; BeagLEDs
;
; by Rick Murray
; Version: 0.01
; Date : Monday, 24th May 2012
; Started: Monday, 21st May 2012
;
; Our inclusions
GET ^.h.equx ; EQUB, EQUD, EQUSZ, EQUSZA...
GET ^.h.SWINames ; SWI definitions
GET ^.h.pushpull ; Push, Pull, PushLR, PullLR, Return, PullRet...
GET ^.h.debug ; DebugMsg (only used during actual debugging)
; Version information
GBLS CODENAME
CODENAME SETS "BeagLEDs"
GBLS CODEVERS
CODEVERS SETS "0.01"
GBLS CODEDATE
CODEDATE SETS "24 May 2012" ; Date format MUST be "DD Mmm CCYY" for RISC OS to recognise it
GBLS CODECOPY
CODECOPY SETS "© 2012 Rick Murray"
; File vector numbers
FileV * &8
ArgsV * &9
BGetV * &A
BPutV * &B
GBPBV * &C
FindV * &D
TickerV * &1C
; LED mask - USERLED0 = GPIO #149; USERLED1 = GPIO #150.
USERLED0 * 1 << 21 ; User LED0 is for the ticker
USERLED1 * 1 << 22 ; User LED1 is for the fileops
TICKERLED * USERLED0 ; therefore...
FILEOPLED * USERLED1
; GPIO5 base address held in code, <GPIO5_BASE>.
; GPIO-specific register offsets (from GPIO base)
GPIO_OE * &34
GPIO_DATAOUT * &3C
GPIO_CLRDATAOUT * &90
GPIO_SETDATAOUT * &94
; Our status array offsets
LED_TICKERCOUNT * 0 ; Counts down from 100 for timing of blinking LED
LED_FILEOPCOUNT * 4 ; Counts down from 15 for timing of file activity LED
LEDSTATE_TICKER * 8 ; Is '1' or '0' for state of blinking LED
LEDSTATE_FILEOP * 12 ; Is '1' or '0' for state of file activity LED
GPIO_ADDRESS * 16 ; The mapped-in address of our GPIO
A32bit
to the AREA definition.
; ===========
; Here we go!
; ===========
AREA |BeagLEDs$Code|, CODE
ENTRY
entrypoint
; Standard RISC OS module header
EQUD 0 ; no Start code
EQUD (initialise - entrypoint) ; Initialise code
EQUD (finalise - entrypoint) ; Finalise code
EQUD 0 ; no Service call
EQUD (titlestring - entrypoint) ; Module title string
EQUD (helpstring - entrypoint) ; Module help string
EQUD 0 ; no help/command
EQUD 0 ; no SWI chunk
EQUD 0 ; no SWI handler code
EQUD 0 ; no SWI decoding table
EQUD 0 ; no SWI decoding code
EQUD 0 ; no Messages file
EQUD (thirtytwo - entrypoint) ; 32bit flag word
titlestring
= CODENAME, 0
ALIGN
helpstring
= CODENAME, 9, CODEVERS, " (", CODEDATE, ") ", CODECOPY
ALIGN
thirtytwo
; Bit zero set indicates this is a 32bit-compatible module...
EQUD 1
GPIO5_BASE
EQUD &49056000 ; location of GPIO5 registers
; =====================
; MODULE INITIALISATION
; =====================
initialise
; We're in SVC mode, so preserve return address
STR R14, [R13, #-4]!
; First job - check what platform we're running on.
; We need a Platform class of 5 (HAL) at least.
MOV R0, #8
SWI XOS_ReadSysInfo
BVS not_a_beagle ; code 8 failed? give up
CMP R0, #5
BNE not_a_beagle ; not HAL version? give up
; Now ask the OS (via HAL) to confirm it is a Beagle.
MOV R0, #1024 ; HALDeviceType_Comms
ADD R0, R0, #3 ; HALDeviceComms_GPIO
MOV R1, #0 ; is our first call (to enum)
MOV R8, #4
SWI XOS_Hardware ; OS_Hardware 4 - enumerate devices
BVS not_a_beagle ; fail? abort!
CMP R1, #-1 ; no match?
BEQ not_a_beagle ; abort if no match
LDR R0, [R2, #64] ; boardtype is at offset +64
CMP R0, #0 ; type 0 is Beagle
BNE not_a_beagle
Board Revision Type Notes 0 0 Beagleboard rev A or B User LED0 on GPIO 149
User LED1 on GPIO 1501 Beagleboard rev C1, C2, or C3 2 Beagleboard rev C4 3 Beagleboard xM rev A 4 Beagleboard xM rev B 5 Beagleboard xM rev C 1 n/a DevKit8000 User LED0 on GPIO 186
User LED1 on GPIO 1632 0 IGEPv2 rev B or C User LED0 on GPIO 26 (red, green=27)
User LED1 on GPIO 28 (red, green=complicated)1 IGEPv2 rev C (not compatible with B) 3 0 RaspberryPi model A Moot point, RasberryPi
has no user LEDs onboard...1 RaspberryPi model B *RMTidy
or *RMReInit
in which case we'll already have a memory block.
; Check we have no allocated space from RMTidy op / previous init
LDR R2, [R12]
TEQ R2, #0
BNE skip_mem_allocate
; Okay, so claim a cosy little spot in the RMA
MOV R0, #6
MOV R3, #20 ; 20 bytes (count x2, tickstate, filestate,
SWI XOS_Module ; and GPIO mapped address)
LDRVS PC, [R13], #4 ; bomb out if V set
; Okay, remember our workspace pointer
STR R2, [R12] ; R12 points to private word; store memblk
MOV R12, R2 ; R12 now points directly to our memory
After the memory is allocated, we store the address to the word pointed to my R12. This word is our "private word", the address of which is passed to us in R12 on every module entry.
As R12 is the convention, we copy the address to R12...
skip_mem_allocate
; Now map in GPIO5 (permanently)
LDR R0, =(1 << 17) ; Page access privilege Read/Write
ADD R0, R0, #13 ; OS_Memory 13, Map in I/O memory
LDR R1, GPIO5_BASE ; Physical address
MOV R2, #256 ; Map in 256 bytes
SWI XOS_Memory
BVS cant_map_memory ; die if it didn't work
STR R3, [R12, #GPIO_ADDRESS] ; remember logical address
; Ensure the LEDs are "outputs"
MOV R0, R3 ; copy address
ADD R0, R0, #GPIO_OE ; add in offset to Output Enable register
MOV R3, #USERLED0 ; Make a bitmask of LEDs
ADD R3, R3, #USERLED1 ; (in R3, we'll need it later)
MVN R1, R3 ; invert bitmask (into R1)
LDR R2, [R0] ; read in word
AND R2, R2, R1 ; value = value AND NOT LED_bits
STR R2, [R0] ; write word back
; Now force LEDs OFF
LDR R0, [R12, #GPIO_ADDRESS] ; load address
ADD R0, R0, #GPIO_CLRDATAOUT ; add in offset to Clear Data Output register
STR R3, [R0] ; write bitmask, turns off LEDs
ADR R1, fileop_handler ; generic handler for fileop vectors
MOV R2, R12 ; pass workspace pointer when called
MOV R0, #FileV ; Claim FileV
SWI XOS_Claim
BVS release_none
MOV R0, #ArgsV ; Claim ArgsV
SWI XOS_Claim
BVS release_one
MOV R0, #BGetV ; Claim BGetV
SWI XOS_Claim
BVS release_two
MOV R0, #BPutV ; Claim BPutV
SWI XOS_Claim
BVS release_three
MOV R0, #GBPBV ; Claim GBPBV
SWI XOS_Claim
BVS release_four
MOV R0, #FindV ; Claim FindV
SWI XOS_Claim
BVS release_five
ADR R1, ticker_handler ; ticker vector handler code
MOV R0, #TickerV ; Claim TickerV
SWI XOS_Claim
BVS release_six
; Next, initialise our memory block
MOV R0, #100
STR R0, [R12, #LED_TICKERCOUNT] ; initialise to 100
MOV R0, #0
STR R0, [R12, #LED_FILEOPCOUNT]
STR R0, [R12, #LEDSTATE_TICKER]
STR R0, [R12, #LEDSTATE_FILEOP]
; Okay, we're done, let's go home...
LDR PC, [R13], #4
; =====================================================
; ERROR THROWS FOR INITIALISE FAILS & OS_CLAIM RELEASES
; =====================================================
not_a_beagle
; set up an error block to flag if we're NOT running on a Beagle.
ADR R0, not_a_beagle_error
SetV
LDR PC, [R13], #4 ; assumes LR previously stacked
cant_map_memory
; set up an error block to flag if OS_Memory for GPIO failed.
; RISC OS should release our memory claim for us.
ADR R0, cant_map_memory_error
SetV
LDR PC, [R13], #4 ; assumes LR previously stacked
; The releases fall through backwards to error report. If a release
; fails, it is not trapped or handled (because the module is about
; to die on startup, not a lot we can do except clap twice and pray).
release_six
MOV R0, #FindV
SWI XOS_Release
release_five
MOV R0, #GBPBV
SWI XOS_Release
release_four
MOV R0, #BPutV
SWI XOS_Release
release_three
MOV R0, #BGetV
SWI XOS_Release
release_two
MOV R0, #ArgsV
SWI XOS_Release
release_one
MOV R0, #FileV
SWI XOS_Release
release_none
cant_claim_vectors
; set up an error block to flag if any of the OS_Claims failed.
; RISC OS should release our memory claim for us, and we don't
; need to release the GPIO mapping (as it is permanent) and we
; have been called AFTER previously OS_Claimed vectors (if any)
; have already been released.
ADR R0, cant_claim_vectors_error
SetV
LDR PC, [R13], #4 ; assumes LR previously stacked
; Error block messages for the above
;
; Is the error number (currently "123") relevant? If the module can't
; start, it can't start, and there isn't a hell of a lot the end user
; can do to rectify things, so nothing really needs to know an actual
; error number, just that an error occurred...
not_a_beagle_error
EQUD 123
EQUSZA "This module only works on a Beagleboard (original or xM)."
cant_map_memory_error
EQUD 123
EQUSZA "Unable to map GPIO memory."
cant_claim_vectors_error
EQUD 123
EQUSZA "Unable to claim necessary vectors."
; ============
; FINALISATION
; ============
finalise
; Preserve return
STR R14, [R13, #-4]!
; Determine our true workspace address
LDR R12, [R12]
; Release ticker vector
MOV R0, #TickerV
ADR R1, ticker_handler
MOV R2, R12
SWI XOS_Release
; Release all FileOp vectors
ADR R1, fileop_handler
MOV R0, #FileV
SWI XOS_Release
MOV R0, #ArgsV
SWI XOS_Release
MOV R0, #BGetV
SWI XOS_Release
MOV R0, #BPutV
SWI XOS_Release
MOV R0, #GBPBV
SWI XOS_Release
MOV R0, #FindV
SWI XOS_Release
; Force the LEDs off
MOV R1, #USERLED0 ; Make a bitmask of LEDs
ADD R1, R1, #USERLED1
LDR R0, [R12, #GPIO_ADDRESS] ; load address
ADD R0, R0, #GPIO_CLRDATAOUT ; offset to Clear Data Output register
STR R1, [R0] ; write bitmask, turns off LEDs
; And now release the memory block
MOV R0, #7
MOV R2, R12
SWI XOS_Module
; That's it. Goodbye and thank you for watching.
LDR PC, [R13], #4
Note, also, that unlike module code, we specified for R12 to point directly to our array, so we don't need to do the LDR R12 from R12 thing.
; =====================
; FILEOP VECTOR HANDLER
; =====================
fileop_handler
; On entry, R12 is a pointer to our array, not our private workspace word.
;
; We are called upon FileV, ArgsV, BGetV, BPutV, GPBPV, and FindV. It is
; important to stress how IMPORTANT it is that we execute QUICKLY.
;
; Fastest case: LED is already on. Through in seven instructions.
;
; Otherwise, LED must be switched on. Through in fifteen instructions
; (two of which are conditionally not executed).
; Is the LED currently on?
; If it is, we can handle this and be out in seven instructions
STR R0, [R13, #-4]! ; preserve R0
MOV R0, #15 ; Set/reset ticker value
STR R0, [R12, #LED_FILEOPCOUNT]
LDR R0, [R12, #LEDSTATE_FILEOP] ; is LED already on?
CMP R0, #0 ; is zero if off
LDRNE R0, [R13], #4 ; restore R0
MOVNE PC, R14 ; done, get outta here
; The set/reset ticker value above is NOT conditional as ALL
; passes through this vector either reset the counter, or set
; it for the first time. In both cases, we want it set to its
; initial value.
; This means we can assume it done for below.
; At this point, we can assume LED is off, so switch it on.
; This adds a further eight instructions. We corrupt R12
; (our private word passed to us on entry) so we don't need
; to lose time stacking and restoring another register (which
; also means we lose two memory accesses).
MOV R0, #1 ; flag LED is on (here, as
STR R0, [R12, #LEDSTATE_FILEOP] ; R12 corrupted below)
MOV R0, #FILEOPLED ; set up for turning on LED
LDR R12, [R12, #GPIO_ADDRESS] ; << this corrupts R12
ADD R12, R12, #GPIO_SETDATAOUT
STR R0, [R12] ; do it
LDR R0, [R13], #4 ; restore R0 (from above)
MOV PC, R14 ; done
; ==========================
; CENTISECOND TICKER HANDLER
; ==========================
ticker_handler
; We're called a hundred times per second. We'll be in IRQ mode, so
; there's no option to call SWIs or such without a lot of faffing.
;
; Case table:
; FileOpLED Ticker Instrs CondNOP Branches
;
; Quickest Off Counting 8 1 0
; Middle Off Switching 19 4 0
; Slow Counting Counting 12 0 2
; Slower Switching Counting 19 1 2
; Slowest Switching Switching 30 5 2
;
; Therefore, this routine takes from 8 to 30 instructions to
; execute.
STMFD R13!, {R0-R1, R14} ; breathing room
; Check the FileOp LED
LDR R0, [R12, #LEDSTATE_FILEOP]
CMP R0, #0 ; is it zero (off?)
BLNE ticker_handler_fileop
; Check the ticker LED
LDR R0, [R12, #LED_TICKERCOUNT] ; load ticker count value
SUBS R0, R0, #1 ; -1 it
STRNE R0, [R12, #LED_TICKERCOUNT] ; if not zero, just write it back
LDMNEFD R13!, {R0-R1, PC} ; and then leave
; still here? ticker is zero - so first reset it
MOV R0, #99
STR R0, [R12, #LED_TICKERCOUNT]
; now look to see what to do with the LED, we toggle
LDR R0, [R12, #LEDSTATE_TICKER]
EORS R0, R0, #1 ; and update flags
STR R0, [R12, #LEDSTATE_TICKER]
LDR R1, [R12, #GPIO_ADDRESS]
ADDEQ R1, R1, #GPIO_CLRDATAOUT ; if zero, select CLR register
ADDNE R1, R1, #GPIO_SETDATAOUT ; else, select SET register
MOV R0, #TICKERLED ; which LED
STR R0, [R1] ; write it
LDMFD R13!, {R0-R1, PC} ; done
ticker_handler_fileop
LDR R0, [R12, #LED_FILEOPCOUNT] ; load ticker count value
SUBS R0, R0, #1 ; -1 it
STR R0, [R12, #LED_FILEOPCOUNT] ; write it back (even if zero)
MOVNE PC, R14 ; branch back if non-zero
; still here? ticker is zero - so turn off LED
MOV R0, #0
STR R0, [R12, #LEDSTATE_FILEOP] ; set flag for LED off
MOV R0, #FILEOPLED ; which LED
LDR R1, [R12, #GPIO_ADDRESS]
ADD R1, R1, #GPIO_CLRDATAOUT ; CLR register
STR R0, [R1] ; write it
MOV PC, R14
EQUS "Thanks to joe for the Beagle, Jeffrey for "
EQUS "s-video, and RISC OS for continuing.:)"
END
There you have it. ☺
; This should be enough to put into one header file to
; build BeagLEDs directly...
; EQUD <value>
MACRO
EQUD $var
DCD $var
MEND
; EQUS "<value>"
; For 'EQUS "something", 13, 0'
; you will need use DCB directly.
MACRO
EQUS $var
DCB "$var"
MEND
; EQUSZA "<value>"
MACRO
EQUSZA $var
DCB "$var", 0
ALIGN
MEND
; SETV : Set oVerflow flag (on 26 or 32 bit)
MACRO
$label SetV ; DOES NOT TAKE A CONDITION
$label CMP R0, #1<<31
CMNVC R0, #1<<31
MEND
; minimal SWI defs
; this is taken from the h.SWINames file supplied with the
; Norcroft/Acorn/Castle DDE examples; with the addition
; of a definition for OS_Hardware.
Auto_Error_SWI_bit_number * 17
Auto_Error_SWI_bit * 1 :SHL: Auto_Error_SWI_bit_number
GBLS SWIClass
MACRO
AddSWI $SWIName,$value
[ "$value" = ""
$SWIClass._$SWIName # 1
|
$SWIClass._$SWIName * $value
]
X$SWIClass._$SWIName * $SWIClass._$SWIName + Auto_Error_SWI_bit
MEND
SWIClass SETS "OS"
^ &1E
AddSWI Module ; &1E
AddSWI Claim ; &1F
AddSWI Release ; &20
^ &58
AddSWI ReadSysInfo ; &58
^ &68
AddSWI Memory ; &68
^ &7A
AddSWI Hardware ; &7A
END
# Project: BeagLEDs
# Toolflags:
.SUFFIXES: .s .o
objasmflags = -throwback -apcs 3/32bit -desktop -IC:,
linkflags = -rmf -output BeagLEDs
# A list of assembler files, referred by the resultant object file
s_files = o.BeagLEDs
BeagLEDs: $(s_files)
@echo Linking...
@link $(s_files) $(linkflags)
@echo Finished.
# A macro for building the assembler code
.s.o:; objasm $(objasmflags) -o $@ $<
# Dynamic dependencies:
My Beagle is "dead" again
Something of a misnomer. It isn't dead dead, it just isn't booting. Hooking up a serial terminal, I can see:
Texas Instruments X-Loader 1.5.0 (Mar 27 2011 - 17:37:56)
Beagle xM
Reading boot sector
Loading u-boot.bin from mmc
U-Boot 2011.03-rc1-00000-g9a3cc57-dirty (Apr 01 2011 - 17:41:42)
OMAP36XX/37XX-GP ES2.1, CPU-OPP2, L3-165MHz, Max CPU Clock 1 Ghz
OMAP3 Beagle board + LPDDR/NAND
I2C: ready
DRAM: 512 MiB
And that's about as far as it gets. I was running from an iomega Zip power supply, I also tried the +5V line from a PC PSU. The accepted advice is that a meatier power supply is required, but if a PC's lump doesn't have enough oomph!, what would?
Now the interesting thing is that this happened hot on the heels of a Linux kernel panic (some sort of corruption on a replacement microSD while trying to remake an image of the original test card). It might be coincidence, but I can start up RISC OS dozens of times without incident, yet immediately following two kernel panics, the Beagle appears to fail at startup. The first time, as described last week, the board just started up again. This time? It doesn't appear to want to. What the hell does Linux do after reporting a kernel panic?
joe, 29th May 2012, 04:24 Rick,
I think that your micro SD card was corrupted somehow
and this is your problem.
When I was cloning different cards, some were corrupted
and sometimes I had this kernel panic message, too.
Sometimes there was maybe one blink and nothing at all,
unit appeared to be dead.
If there was something wrong, you wouldn't be able to
run RISC, you have to try another, working card.
If you power supply is not overheating, than don't
worry too much, read the manual:
http://beagleboard.org/static/BBxMSRM_latest.pdfRick, 9th June 2012, 04:55 Just a short note to say that up-and-coming SDFS on the Beagle BOTH LEDs (both flash for writes, one flashes for reads). When I get a working Beagle, I'll have to recode it to do something sexy with the PWM-able LED on the assist-chip. But a filing system hijacking BOTH LEDs? Pffft! There are so many things you could do - like a "you have mail" notification or a blinking "everything's working" (as BeagLEDs was to be originally) or... I'm sure you can think of your own ideas.
© 2012 Rick Murray |
This web page is licenced for your personal, private, non-commercial use only. No automated processing by advertising systems is permitted. RIPA notice: No consent is given for interception of page transmission. |