Compare commits

...

55 Commits

Author SHA1 Message Date
474050ff6d increase dot grid size to be less distracting 2025-09-07 18:32:52 +01:00
1b95f46544 add note on cloudwatch event rules via ansible 2025-02-12 14:09:35 +00:00
a4b13fb71e always dark mode 2024-12-25 19:45:11 +00:00
d512ff1c73 use dotgrid module 2024-12-25 19:34:14 +00:00
b7c38ddc89 fix title cuasing issues with gronk 2024-08-09 21:03:58 +01:00
9d602fede7 cadence license manager issues 2024-08-09 20:57:19 +01:00
a21898048c update readmes 2024-04-16 18:47:33 +01:00
5e3bdbe2f6 how to install droidcam on jetson nano 2024-04-16 18:42:24 +01:00
1e90d6c8a9 comic mono 2024-04-14 16:05:13 +01:00
b6c9129fa5 update readme 2024-04-13 21:03:16 +01:00
00b08276a2 add realistic date 2024-04-13 21:01:33 +01:00
47bfb4ac20 update blog readme 2024-04-13 20:58:25 +01:00
1055f83d3a fix images 2024-04-13 20:54:16 +01:00
a9cb29989d fix metadata 2024-04-13 20:52:42 +01:00
ce04f5dd57 add old posts 2024-04-13 20:44:27 +01:00
ef43740721 update readme 2024-04-13 20:18:04 +01:00
b94dba3163 add base_url 2024-04-13 20:06:50 +01:00
816896537d start move blog to gronk 2024-04-13 20:02:11 +01:00
ad7096bca2 explain xed value 2024-03-02 14:28:24 +00:00
37618fe7eb cross elastic demand 2024-03-02 14:25:31 +00:00
8c16a0d537 update flashcards 2024-02-29 12:56:56 +00:00
e203b294c5 update flashcards 2024-02-25 13:02:36 +00:00
91e7c9701a update flashcards 2024-02-23 19:16:29 +00:00
9e12734c5f update readme 2024-02-21 15:08:29 +00:00
524465453a update flashcards (corrections) 2024-02-21 15:06:30 +00:00
dec593c503 management 2024-02-16 12:34:28 +00:00
56d55a6617 update readme to include errata 2024-02-13 09:45:57 +00:00
15cec82789 add resources on mmme3081 2024-02-13 09:39:33 +00:00
8185cd14e4 mmme3049 2024-02-02 12:36:25 +00:00
e4a0ef25e1 help i think my device shut down after deleting the current kernel and before installing the second (no entries in systemd-boot/grub/<bootloader>) 2024-01-29 15:38:10 +00:00
5f5e43e54e update readme 2024-01-23 16:31:12 +00:00
a24eb028a9 add code for solutions for exam papers 2024-01-23 16:28:16 +00:00
996700bec9 add exercise sheet 8 solution plotter script 2024-01-17 15:50:25 +00:00
4369e246bd update folder name 2024-01-07 16:14:15 +00:00
a42bfcc814 add errata for exercise sheets 2024-01-07 16:06:29 +00:00
3de79c2111 formatting 2024-01-02 20:15:44 +00:00
da516f5160 add page no issues with logging into email 2024-01-02 20:14:13 +00:00
0489963eda update gohookr.sh 2024-01-02 19:04:05 +00:00
8981e9b9c4 update readmes 2024-01-02 18:48:48 +00:00
dd35b48def add flask project example 2024-01-02 02:15:24 +00:00
0ceb20bcf1 add computer engineering slides 2023-12-28 20:18:17 +00:00
f266085c4e add mechatronics lecture slides 2023-12-28 20:16:19 +00:00
5b64235c97 add past papers 2023-12-28 20:13:00 +00:00
b3d42c30d9 add lecture slides, lectur notes 2023-12-28 20:12:23 +00:00
a84913e3f5 add exercise sheets 2023-12-28 19:49:08 +00:00
557bad8387 add exam cheatsheets 2023-11-06 12:56:52 +00:00
0f29002415 add mmme3085 mechatronics week 4 lecture slides 2023-11-06 12:55:42 +00:00
11cd8df774 correct lecture_notes folder name 2023-11-06 12:54:53 +00:00
a92f99dae8 add fea lecture slides 2023-11-06 12:54:10 +00:00
7f7955fc4f add fea exercise sheets 2023-11-06 12:53:52 +00:00
a4d8d95d74 add .n2w config 2023-10-31 16:04:01 +00:00
bec5809694 add notes, slides, lecture notes on fea 2023-10-31 16:03:40 +00:00
4e51f23dca move lecture notes and slides into subfolders 2023-10-31 14:35:05 +00:00
212cfd6e4c add lecture notes, lecture slides for lecture 4, 5 2023-10-23 17:08:35 +01:00
c58e7b2f94 add computer engineering slides, separate computer engineering and mechatronics into subfolders 2023-10-23 17:08:00 +01:00
163 changed files with 60621 additions and 6 deletions

11
blog/first_post.md Executable file
View File

@@ -0,0 +1,11 @@
---
author: Akbar Rahman
pub_date: Fri, 31 Jul 2020 19:52:52 +0100
title: first post
tags: []
uuid: fd338dc9-ae5f-48f4-9fc6-e02e88ab4ce5
---
# first post
this is my first post

182
blog/g27_pedals.md Executable file
View File

@@ -0,0 +1,182 @@
---
author: Akbar Rahman
pub_date: Tue, 04 Aug 2020 15:20:13 +0100
title: Repurposing Racing Wheel Pedals
tags: [ g27, sim_racing ]
uuid: 0f09200e-fd50-451b-aae1-1117a8a704db
---
<h1>Repurposing Racing Wheel Pedals</h1>
<p>I have a Logitech G27 I don't use much. I wondered if I could use it for anything else. I could. </p>
<h2> The Pinout of the Connector </h2>
<p>The first thing I had to do was figure out what each pin did on the DE-9 connector, and which
ones I should care about.
This was done easily after I took off the top plastic casing thing by poking the three 100k Ohm
potentiometers and the connector in the right places at the right times:
</p>
<style> #pinout_table tr td:first-child { text-align: right } </style>
<img src="./images/repurposing-racing-wheel-pedals-g27-pinout.svg" class="centered" style="width: 10em;">
<table id="pinout_table">
<tr> <th>pin</th> <th>function</th></tr>
<tr> <td>1,4</td> <td>ground</td></tr>
<tr> <td>6</td> <td>clutch pedal</td></tr>
<tr> <td>7</td> <td>brake pedal</td></tr>
<tr> <td>8</td> <td>accelerator pedal</td></tr>
<tr> <td>9</td> <td>voltage in</td></tr>
</table>
<h2> Reading the Values of the Pots </h2>
I'm using an Arduino to read the pots and then do something with the values.
I very dirtily wired pin 4 on the pedals to GND on a Arduino Uno, pin 9 to 5V, and
pins 6,7,8 to A0, A1, and A2.
I used a basic sketch to check that everything is good:
<details>
<summary> Show/hide test_sketch.ino </summary>
<pre><code> void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println(analogRead(A2));
delay(20);
}
</code></pre>
</details>
I noticed that the minimum and maximum values read by the Uno were quite far off 0 and 1024, like
they should be, and voltage was being lost on the way to and from the potentiometers.
Since the pedals have to be calibrated every time you plug them in, I assume this is normal and
spat out this code:
<details>
<summary> Show/hide sketch_aug02a.ino </summary>
<pre><code>// sensor pins
int sa = A0;
int sb = A1;
int sc = A2;
// minimum values detected by the sensors
int mina = 1025;
int minb = 1025;
int minc = 1025;
// maximum values detected by the sensors
int maxa = 512;
int maxb = 512;
int maxc = 512;
// raw values of the sensors
int rva, rvb, rvc;
// calculated values of the sensors (between 0 and 1, this is the value sent to computer)
float cva, cvb, cvc;
void setup() {
Serial.begin(9600);
}
void loop() {
rva = analogRead(sa);
rvb = analogRead(sb);
rvc = analogRead(sc);
if (rva &lt; mina) mina = rva;
if (rvb &lt; minb) minb = rvb;
if (rvc &lt; minc) minc = rvc;
if (rva &gt; maxa) maxa = rva;
if (rvb &gt; maxb) maxb = rvb;
if (rvc &gt; maxc) maxc = rvc;
cva = (float)(rva-mina)/(float)(maxa-mina);
cvb = (float)(rvb-minb)/(float)(maxb-minb);
cvc = (float)(rvc-minc)/(float)(maxc-minc);
Serial.print('[');
Serial.print(cva); Serial.print(',');
Serial.print(cvb); Serial.print(',');
Serial.print(cvc);
Serial.print(']');
Serial.println();
delay(20);
}
</code></pre>
</details>
<h2> Actually Making the Numbers Do Something </h2>
This is where you can make the pedals do fun things.
I reworked another piece of code I wrote to do a similar thing to quickly create a script that
reads the values sent by the Arduino, and then simulate pressing a key combination.
The only thing I've done with this is set push-to-talk to ctrl-shift-alt-1.
I don't know what else I could use this for, maybe temporarily muting particular things, like music.
<details>
<summary> Show/hide pedalboard.py </summary>
<pre><code> #!/usr/bin/env python3
import sys
import json
import time
from enum import Enum
import keyboard
import serial
class KeyState(Enum):
UP = 0
DOWN = 1
STATES = [KeyState.UP] * 3
THRESHOLD = 0.8
MACROS = ['ctrl+shift+alt+1', 'ctrl+shift+alt+2', 'ctrl+shift+alt+3']
def get_args():
""" Get command line arguments """
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('device')
return parser.parse_args()
def main(args):
""" Entry point for script """
while True:
try:
kb = serial.Serial(port=args.device, baudrate=9600)
while True:
handle(json.loads(kb.readline()))
except serial.serialutil.SerialException as e:
print(e)
print("Failed to connect to device... trying again")
time.sleep(1)
except Exception as e:
print(e)
return 0
def handle(data):
global STATES
states = [KeyState.DOWN if value &gt; THRESHOLD else KeyState.UP for value in data]
r = [handle_state_change(i, states[i]) if states[i] != STATES[i] else None for i in range(len(STATES))]
STATES = states
return r
def handle_state_change(key, newstate):
print(f"{key} {newstate}")
return keyboard.press(MACROS[key]) if newstate == KeyState.DOWN else keyboard.release(MACROS[key])
if __name__ == '__main__':
try:
sys.exit(main(get_args()))
except KeyboardInterrupt:
sys.exit(0)
</code></pre>
</details>

View File

@@ -0,0 +1,226 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.0"
width="68.148842"
height="34.400002"
viewBox="-138.624 -137.291 68.14884 34.400003"
id="Layer_1"
xml:space="preserve"
sodipodi:docname="repurposing-racing-wheel-pedals-g27-pinout.svg"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><title
id="title1416">DE-9 Connector with numbers</title><metadata
id="metadata1308"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title>DE-9 Connector with numbers</dc:title><dc:date>2020-08-02</dc:date><dc:creator><cc:Agent><dc:title>alvierahman90</dc:title></cc:Agent></dc:creator><cc:license
rdf:resource="" /><dc:contributor><cc:Agent><dc:title>Original drawing from Mobius (maybe): https://commons.wikimedia.org/wiki/File:DSubminiatures.svg</dc:title></cc:Agent></dc:contributor></cc:Work></rdf:RDF></metadata><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1722"
inkscape:window-height="1060"
id="namedview1306"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="10.44492"
inkscape:cx="27.994898"
inkscape:cy="11.731109"
inkscape:window-x="1056"
inkscape:window-y="1094"
inkscape:window-maximized="0"
inkscape:current-layer="Layer_1" /><defs
id="defs2584">
</defs>
<g
id="g1336"
transform="rotate(180,-104.54958,-120.091)"
style="stroke:#454545;stroke-opacity:1"><g
transform="translate(-193.19312,-267.013)"
id="g2241"
style="stroke:#454545;stroke-opacity:1">
<circle
cx="66.588997"
cy="141.351"
r="2.2409999"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="circle2243" />
<circle
cx="77.617996"
cy="141.351"
r="2.2409999"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="circle2245" />
<circle
cx="88.643997"
cy="141.351"
r="2.2379999"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="circle2247" />
<path
d="m 99.668,139.11 c 1.238,0 2.242,1.004 2.242,2.241 0,1.237 -1.004,2.24 -2.242,2.24 -1.233,0 -2.237,-1.003 -2.237,-2.24 0,-1.237 1.004,-2.241 2.237,-2.241 z"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="path2249"
inkscape:connector-curvature="0" />
<circle
cx="110.697"
cy="141.351"
r="2.2409999"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="circle2251" />
<circle
cx="72.102997"
cy="152.491"
r="2.2390001"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="circle2253" />
<circle
cx="83.130997"
cy="152.491"
r="2.2390001"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="circle2255" />
<path
d="m 94.156,150.252 c 1.237,0 2.238,1.003 2.238,2.237 0,1.237 -1.001,2.241 -2.238,2.241 -1.238,0 -2.242,-1.004 -2.242,-2.241 0,-1.234 1.004,-2.237 2.242,-2.237 z"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="path2257"
inkscape:connector-curvature="0" />
<circle
cx="105.185"
cy="152.491"
r="2.2390001"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="circle2259" />
</g><path
d="m -129.54912,-136.791 c -5.609,0 -9.4,4.518 -8.425,10.042 l 2.354,13.309 c 0.976,5.525 6.366,10.049 11.975,10.049 h 38.191005 c 5.608,0 10.996,-4.523 11.975,-10.049 l 2.354,-13.309 c 0.975,-5.524 -2.813,-10.042 -8.425,-10.042 z"
style="fill:none;stroke:#454545;stroke-opacity:1"
id="path2261"
inkscape:connector-curvature="0" /></g>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-123.37334"
y="-129.7538"
id="text1340"><tspan
sodipodi:role="line"
id="tspan1338"
x="-123.37334"
y="-129.7538"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">1</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-112.29854"
y="-129.7538"
id="text1340-3"><tspan
sodipodi:role="line"
id="tspan1338-7"
x="-112.29854"
y="-129.7538"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">2</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-101.2884"
y="-129.7538"
id="text1340-9"><tspan
sodipodi:role="line"
id="tspan1338-8"
x="-101.2884"
y="-129.7538"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">3</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-90.565475"
y="-129.7538"
id="text1340-6"><tspan
sodipodi:role="line"
id="tspan1338-70"
x="-90.565475"
y="-129.7538"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">4</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-129.24457"
y="-105.27687"
id="text1340-4"><tspan
sodipodi:role="line"
id="tspan1338-84"
x="-129.24457"
y="-105.27687"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">5</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-117.9472"
y="-105.27687"
id="text1340-8"><tspan
sodipodi:role="line"
id="tspan1338-1"
x="-117.9472"
y="-105.27687"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">6</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-106.88921"
y="-105.27687"
id="text1340-68"><tspan
sodipodi:role="line"
id="tspan1338-5"
x="-106.88921"
y="-105.27687"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">7</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-94.538704"
y="-105.27687"
id="text1340-2"><tspan
sodipodi:role="line"
id="tspan1338-19"
x="-94.538704"
y="-105.27687"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">8</tspan></text>
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:6.98580647px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#454545;fill-opacity:1;stroke:none;stroke-width:0.17464516;stroke-opacity:1;"
x="-83.91153"
y="-105.27687"
id="text1340-96"><tspan
sodipodi:role="line"
id="tspan1338-0"
x="-83.91153"
y="-105.27687"
style="stroke-width:0.17464516;stroke:none;stroke-opacity:1;fill:#454545;fill-opacity:1;">9</tspan></text>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

63
blog/lastfm_bookmarklets.md Executable file
View File

@@ -0,0 +1,63 @@
---
author: Akbar Rahman
pub_date: Mon, 18 Sep 2023 16:25:48 +0100
title: last.fm bookmarklets
tags: [ last.fm, scripts ]
uuid: e54ebf58-4033-4dae-81db-91db344f1311
---
# last.fm bookmarklets
last.fm doesn't let you see how many scrobbled you've made in one day particularly easily.
Here is a bookmarklet to solve that.
<label for="days"> Number of days to view: </label>
<input type="number" value="1" id="days" placeholder="Days"/><br><br>
<label for="offset"> Offset (e.g. 0 to include today, 7 to look at last week): </label>
<input type="number" value="0" id="offset" placeholder="Offset (Days)" /><br><br>
<label for="username"> last.fm username </label>
<input type="text" value="" id="username" placeholder="Username" /><br><br>
<input type="button" id="button" value="Generate bookmarklet"><br>
<p><a style="display: none" href="" id="scriptLink">Bookmark this link</a></p>
When you press generate bookmarklet, the values `OFFSET`, `DAYS`, `USERNAME` will be
subsituted and put into the link above.
It's always best to inspect bookmarklets though.
Inspect the page to view the script used to generate the bookmarklet.
<textarea cols="109" rows="15" readonly id="scriptText">
javascript: (() => {
const MILLESECONDS_PER_DAY = 1000 * 24 * 60 * 60;
const OFFSET;
const DAYS;
const USERNAME;
const currentDate = new Date();
const to = new Date(currentDate - (OFFSET * MILLESECONDS_PER_DAY));
const from = new Date(to - ((DAYS-1) * MILLESECONDS_PER_DAY));
const toDate = to.getFullYear() + "-" + (to.getMonth()+1) + "-" + to.getDate();
const fromDate = from.getFullYear() + "-" + (from.getMonth()+1) + "-" + from.getDate();
document.location = "https://www.last.fm/user/" + USERNAME + "/library?from=" + fromDate + "&to=" + toDate;
})();
</textarea>
<script>
document.getElementById("button").addEventListener("click", () => {
scriptText = document.getElementById("scriptText").value;
offset = document.getElementById("offset").value;
days = document.getElementById("days").value;
username = document.getElementById("username").value;
newscript = scriptText.replace(
"OFFSET", "OFFSET = " + offset
).replace(
"DAYS", "DAYS = " + days
).replace(
"USERNAME", "USERNAME = '" + username + "'"
);
document.getElementById("scriptLink").href = newscript;
document.getElementById("scriptLink").style = "";
});
</script>

13
blog/readme.md Normal file
View File

@@ -0,0 +1,13 @@
---
title: alv's blog
author: Akbar Rahman
pub_date: Fri, 31 Jul 2020 19:50:51 +0100
blog: true
tags: [ alvs_blog, blog ]
uuid: 2d03893a-eb9b-4923-8024-a223ecbe72f7
---
# alv's blog
this is my blog.
i promise i will try to keep things posted here interesting.

View File

@@ -0,0 +1,57 @@
---
author: Akbar Rahman
date: \today
title: "Cadence License Manager Install - `java.lang.IllegalArgumentException: :locationICompSelected: Null parameter - InstallComponent ID`"
tags: [ cadence, license_manager, flexlm, java, errors ]
uuid: a5f46736-1ab8-4da1-8737-95de51c95d50
---
# Error
```
[root@host Downloads]# iscape/bin/iscape.sh -batch majorAction=InstallFromArchive archiveDirectory=$(realpath LCU04.30.000_lnx86.Base) installDirectory=$(realpath target)
Initializing InstallScape using JVM at /home/alvi/Downloads/iscape.04.23-s012/runtime/LNX86/bin/java. This might take some time...
WARNING: The DISPLAY environment variable has not been set.
InstallScape might not initialize.
InstallScape Installer (Batch Mode) - 04.23.s12
:locationICompSelected: Null parameter - InstallComponent ID
java.lang.IllegalArgumentException: :locationICompSelected: Null parameter - InstallComponent ID
at com.khanpur.installerng.ArchiveLocationManager.locationICompSelected(ArchiveLocationManager.java:143)
at com.khanpur.installerng.Installer.archiveLocationICompSelected(Installer.java:1156)
at com.khanpur.installer.gui.batch.BatchInstallfromarchive.execute(BatchInstallfromarchive.java:86)
at com.khanpur.installer.gui.batch.BatchView.initialize(BatchView.java:329)
at com.khanpur.installer.gui.batch.BatchView.<init>(BatchView.java:90)
at com.khanpur.installer.gui.InstallerUINoSplash.showBatch(InstallerUINoSplash.java:325)
at com.khanpur.installer.gui.BatchCommand.execute(BatchCommand.java:78)
at com.khanpur.util.TransactionCommand.execute(TransactionCommand.java:74)
at com.khanpur.util.Commandline.runCommands(Commandline.java:223)
at com.khanpur.installer.gui.InstallerUINoSplash.processCommandLine(InstallerUINoSplash.java:340)
at com.khanpur.installer.gui.InstallerUINoSplash.main(InstallerUINoSplash.java:372)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.khanpur.installer.gui.InstallerUI.main(InstallerUI.java:123)
Failed with InstallScape JVM.
Now loading System JVM...
iscape/bin/iscape.sh: line 222: java: command not found
Error:
/usr/bin/which: no java in (/usr/local/bin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin)
Could not use JVM packaged with Installcape. The Java in your path did not work or could not find Java in your path. Ensure that Java 1.6 or later is in your PATH environment variable and restart InstallScape.
```
# Cause
Using the wrong filepath.
The Cadence archives have subfolders to split the software between multiple CDs (a relic of the
past perhaps).
The actual folder to use is the CDs.
# Solution
Use the folder that contains the `.sdx` files (in my case, add `/CDROM1` onto end of
`archiveDirectory`).

View File

@@ -0,0 +1,81 @@
---
author: Akbar Rahman
date: \today
title: Eventbridge Rule (Cloudwatch Rule) Does Not Invoke Lambda When Configured Through Ansible
tags:
- ansible
- aws
- aws_eventbridge
- aws_lambda
- cloudwatch
- eventbridge
- lambda
- permissions
uuid: df3ca083-b6ae-4e35-bb1c-8b3978117c57
---
# Eventbridge Rule (formerly Cloudwatch Rule) Does Not Invoke Lambda When Configured Through Ansible
## Problem
After creating an Eventbridge rule to run a Lambda function with the Ansible module
[`amazon.aws.cloudwatchevent_rule`](https://docs.ansible.com/ansible/latest/collections/amazon/aws/cloudwatchevent_rule_module.html),
the rule does not run Lambda function when it should:
```yaml
- name: "Create lambda function"
register: create_lambda
amazon.aws.lambda:
region: "{{ aws_ec2_region }}"
description: "My Lambda function"
name: "{{ lambda_name }}"
role: "{{ iam_role.iam_role.arn }}"
state: "present"
timeout: 120
vpc_security_group_ids: "{{ sec_group.group_id }}"
vpc_subnet_ids: "{{ subnet_ids }}"
image_uri: "{{ ecr.repository.repositoryUri }}:latest"
- name: "Schedule my Lambda function"
register: lambda_schedule_rule
amazon.aws.cloudwatchevent_rule:
name: "a_unique_rule_name"
region: "{{ aws_ec2_region }}"
schedule_expression: "rate(1 minute)"
state: "present"
targets:
- arn: "{{ create_lambda.configuration.function_arn }}"
id: "a_unique_id"
input: "{{ eventbridge_rule_lambda_event_input }}"
```
Even though creating a seemingly identical setup through the AWS console works fine.
## Cause
The Eventbridge rule is not allowed to invoke this Lambda, as it is not in the Lambda's policy.
## Solution
Use the
[`amazon.aws.lambda_policy`](https://docs.ansible.com/ansible/latest/collections/amazon/aws/lambda_policy_module.html)
module to allow the Eventbridge rule to invoke the Lambda.
Note that, if specifying the Lambda function name to `function_name` (as opposed to the ARN of the
Lambda function), you must specify `version` or otherwise the Lambda function still won't be run!
```yaml
- name: "Allow Eventbridge (Cloudwatch) Rules to invoke lambda"
amazon.aws.lambda_policy:
action: "lambda:InvokeFunction"
function_name: "{{ lambda_name }}"
state: "present"
statement_id: "a_unique_statement_id"
region: "{{ aws_ec2_region }}"
principal: "events.amazonaws.com"
source_arn: "{{ lambda_schedule_rule.rule.arn }}"
version: "{{ create_lambda.configuration.version }}"
```
Solution found thanks to @david-kretch's answer to the same question at
<https://stackoverflow.com/questions/45282939/cloudwatch-event-rule-creation-via-ansible-succeeds-but-not-invoked>.

12
computery_stuff/flask.md Executable file
View File

@@ -0,0 +1,12 @@
---
author: Akbar Rahman
date: \today
title: Flask
tags: [ python, flask, programming, docker ]
uuid: e513ed96-cb19-4d4c-9894-e337c54659e5
---
# Examples
- [alv.cx-glass](https://git.alv.cx/alvierahman90/alv.cx-glass) --- a pretty minimal example, probably not very production ready but has example of how to use in Docker
- <https://flask.palletsprojects.com/> --- official documentation for Flask

17
computery_stuff/jetson_nano.md Executable file
View File

@@ -0,0 +1,17 @@
---
author: Akbar Rahman
date: \today
title: Jetson Nano
tags: [ nvidia, jetson, jetson_nano, droidcam ]
uuid: f312451a-2cd4-468a-9eef-ca9859c7cd1e
---
# installing Droidcam
figured out with help from <https://hizzely.hashnode.dev/instalasi-droidcam-cli-di-jetson-nano> :pray:
0. build and install libjpeg-turbo version 2.1.2 from github (cmake, make, make install)
0. build droidcam (2.1.3 confirmed working) from source (make) and install (./install-client) (may need to set `PKG_CONFIG_PATH` environment varible to whatever libjpeg turbo installed at (for me, `/opt/libjpeg-turbo/lib64/pkgconfig`))
0. install v4l2loopback-dkms with apt
0. run droidcam (you may need to set `LD_LIBRARY_PATH` environment variable to wherever libjpeg-turbo installed to (for me, `/opt/libjpeg-turbo/lib64`))

View File

@@ -20,3 +20,47 @@ usermod -a -G group user
```bash
usermod -g group user
```
# help i think my device shut down after deleting the current kernel and before installing the second (no entries in systemd-boot/grub/<bootloader>)
0. boot into a live usb of current disto
1. mount the root partition to `/mnt` and the boot partition to the appropriate folder (check
fstab which should be in `/mnt/etc/fstab`, if it says `/efi`, mount it to `/mnt/efi`)
2. chroot into the mounted filesystem:
on arch based systems you can simply run:
```
arch-chroot /mnt
```
on non arch based systems[^1]:
```
mount -t proc /proc /mnt/proc/
mount -t sysfs /sys /mnt/ys/
mount --rbind /dev /mnt/dev/
# only if using uefi
mount --rbind /sys/firmware/efi/efivars /mnt/sys/firmware/efi/efivars/
# for internet access
cp /etc/resolv.conf /mnt/etc/resolv.conf
chroot /mnt /bin/bash
```
3. the system can now be force updated/kernel images can be generated
on arch based systems[^2]:
```
# reinstall all current packages
pacman -Qqen > /root/pkgs.txt # list all installed packages
pacman -S $(< /root/pkgs.txt) # reinstall all installed packages
rm /root/pkgs.txt # clean up
# reinstall dependencies (if there are issues)
pacman -Qqdn > /root/deps.txt # list all installed dependencies
pacman -S $(< /root/deps.txt) # reinstall all installed dependencies
rm /root/deps.txt # clean up
```
[^1]: https://wiki.archlinux.org/title/Chroot [wayback machine](https://web.archive.org/web/20240121115548/https://wiki.archlinux.org/title/Chroot)
[^2]: https://bbs.archlinux.org/viewtopic.php?id=193174 [wayback machine](https://web.archive.org/web/20240129153400/https://bbs.archlinux.org/viewtopic.php?id=193174)

View File

@@ -0,0 +1,14 @@
---
author: Akbar Rahman
date: \today
title: University of Nottingham
tags: [ uni ]
uuid: d1b03938-c5b4-48ad-a258-78f96880aa4b
---
### Trying to log into Microsoft 365 sends me to a different organisation's login page
Try one of these links:
- <https://pls.cx/uon_email> (a redirect to the link below)
- <https://outlook.office.com/owa/nottingham.ac.uk>

View File

@@ -6,4 +6,6 @@ cd `dirname $0`
git pull
cd ..
rm -rf notes.alv.cx/*
notes2web.py -o notes.alv.cx notes
cd /root/gronk
git pull
docker compose up --build

10
readme.md Normal file
View File

@@ -0,0 +1,10 @@
---
title: alv's notes
base_url: https://notes.alv.cx
---
# alv's notes
These are my personal notes. Correctness is not guaranteed.
Best viewed at [notes.alv.cx](https://notes.alv.cx).

12
styles.css Normal file
View File

@@ -0,0 +1,12 @@
@import url("https://styles.alv.cx/fonts/comic-mono-font.css");
@import url("https://styles.alv.cx/modules/dotgrid.css");
@import url("https://styles.alv.cx/modules/alwaysdark.css");
:root {
--dotgrid-size: 15em;
--dotgrid-dot-size: 1px;
}
body {
font-family: 'Comic Mono', monospace;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

View File

@@ -0,0 +1,11 @@
---
author: Akbar Rahman
title: MMME3039 Engineering Management 2
tags: [ mmme3049, engineering_management, business ]
uuid: bca772c8-ea08-42fe-9fd0-8d9728cd6e8e
---
# MMME3039 Engineering Management 2
- [Anki Revision Flashcard](./MMME3049 Engineering Management.apkg)
- [Slides](./lecture_slides)

View File

@@ -0,0 +1,39 @@
---
author: Akbar Rahman
date: \today
title: Cross Elastic Demand (XED)
tags: []
uuid: d6b6e3dd-1bba-466a-aad8-9e39c68280ab
---
# Cross Elastic Demand (XED)
The equation given in the lecture slides is:
$$\text{XED} = \frac{\frac{\Delta q_A}{q_A}}{\frac{\Delta p_B}{p_B}}$$
But that's a bit ambiguous, so it's better write as:
$$\text{XED}
= \frac{\frac{q_{A,2}-q_{A,1}}{q_{A,1}}}{\frac{p_{B,2}-p_{B,1}}{p_{B,1}}}
= \frac{\text{percentage change in quantity of A}}{\text{percentage change in price of B}}
$$
If XED is positive, the two goods A and B are substitutes for each other.
If XED is negative, the two goods are complimentary.
## Example
![A question from the book (page 91)](./images/xed_question.png)
Here, product A is the CNC machining system and product B is the control software.
Quantity of product A sold can be found using $revenue = price \times quantity$:
$$quantity_1 = \frac{2\,250\,000}{11\,000} = 205$$
$$quantity_2 = \frac{4\,850\,000}{11\,000} = 441$$
$$\text{percentage change in quantity of A} = \frac{441-205}{205} = 1.156$$
$$\text{percentage change in price of B} = \frac{2600-6800}{6800} = -0.618$$
$$\text{XED} = \frac{1.156}{-0.618} = -1.871$$

View File

@@ -0,0 +1,30 @@
---
author: Akbar Rahman
date: \today
title: MMME3081 Thermofluids 3
tags: [ mmme3081, thermodynamics, fluid_dynamics, thermofluids ]
uuid: 8c0c0707-2148-4c5f-b3b7-0318f245a774
---
# MMME3081 Thermofluids 3
<details>
<summary>
## Errata
</summary>
### Turbomachinery, notes p. 2 (p. 16)
The equation for swirl angle, $\alpha$, may be wrong but Don wasn't sure
which one was the correct one in the lecture lol.
</details>
## Formula Sheet
This module ideally will not have a dedicated formula sheet, instead giving the needed
equations in the paper, so use the
[MMME2047 formula sheet](../2047_thermodynamics_and_fluid_dynamics/data_and_formulae_sheets/formulae.pdf)
instead.

View File

@@ -0,0 +1,34 @@
#!/usr/bin/env python3
#
# Akbar Rahman
import matplotlib.pyplot as plt
x0, y0 = (5, 5)
x1, y1 = (18, 16)
dx = x1 - x0
dy = y1 - x0
D = 2 * dy - dx
y = y0
print(f"{dx=} {dy=} {D=} {y=}")
xs = []
ys = []
for x in range(x0, x1 + 1):
# moveto(x, y)
if D > 0:
y += 1
D -= 2 * dx
D += 2 * dy
print(f"{D=}\t{x=}\t{y=}")
xs.append(x)
ys.append(y)
print(f"{xs=}")
print(f"{ys=}")
plt.plot(xs, ys)
plt.show()

View File

@@ -0,0 +1,22 @@
---
author: Akbar Rahman
title: Mechatronics Exercise Sheets
uuid: 4385c6ab-bc61-4510-a587-b6c6a2dd9e7c
---
# Mechatronics Exercise Sheets
## Errata
### Exercise Sheet 2, Question 3
> Confirmed by module convenor.
The answers say that the final line:
```c
bool pinStatus = PINC & 0x08;
```
will read from pin 30, but it will actually read from pin 33.

View File

@@ -0,0 +1,39 @@
enum daysOfWeek {SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY};
int i = 0; // Number of the week days
void setup() {
Serial.begin(9600);
}
void loop() {
for (i = 0; i < 7; i++){
int day=daysOfWeek(i); //if it is Sunday, day will be 0, if Monday it will be 1 and so on
Serial.print("Today is ");
switch (day)
{
case SUNDAY:
Serial.print("SUNDAY: Go for Swiming");
break;
case MONDAY:
Serial.print("Monday: Go to Computer Engineering Lecture");
break;
case TUESDAY:
Serial.print("Tuesday: Go to Computer Engineering Laboratory");
break;
case WEDNESDAY:
Serial.print("Wednesday: Studay Mechatronics and Computer Engineering");
break;
case THURSDAY:
Serial.print("Thursday: Go to Mechatronics Lecture");
break;
case FRIDAY:
Serial.print("Friday: Go to Mechatronics Seminar");
break;
case SATURDAY:
Serial.print("Saturday: Take a rest");
break;
}
Serial.print('\n');
delay(2000);
}
}

View File

@@ -0,0 +1,300 @@
/* Example of driving servomotor and reading encoder signals in various ways */
#include <avr/io.h> /* Needed to set up counter on pin 47 */
#include <SPI.h> /* Needed to communicate with LS7366R (Counter Click) */
/* Serial input aspects are based closely upon:
http://forum.arduino.cc/index.php?topic=396450
Example 4 - Receive a number as text and convert it to an int
Modified to read a float */
/* LS7366R aspects very loosely based on concepts used in controlling
the Robogaia 3-axis encoder shield though implementation is very different
https://www.robogaia.com/3-axis-encoder-conter-arduino-shield.html */
/* Counting using Timer 5 (external counter input) based loosely on code from
https://forum.arduino.cc/index.php?topic=59396.0 written by bubuldino */
/* Pins used for L298 driver */
#define enA 13 /* PWM output, also visible as LED */
#define in1 8 /* H bridge selection input 1 */
#define in2 9 /* H bridge selection input 2 */
#define minPercent -100.0
#define maxPercent 100.0
/* Encoder input pins (used for state machine and interrupts) */
#define channelA 2
#define channelB 3
/* Used to to initiate SPI communication to LS7366R chip (Counter click) */
#define chipSelectPin 10
/* Size of buffer used to store received characters */
#define numChars 32
/* Intervals in milliseconds for user-defined timed loops */
#define printInterval 1000
/* Global variables used in serial input */
char receivedChars[numChars]; // an array to store the received data
float dataNumber = 0; // new for this version
boolean newData = false;
/* Global variables used for motor control and encoder reading */
double percentSpeed;
double encoderValue;
/* Used for state machine and encoder reading */
typedef enum states{state1=1, state2, state3, state4};
volatile long int count = 0;
volatile long int error = 0;
volatile states state;
bool channelAState, channelBState;
/* Used for handling overflows in Timer 5 */
volatile long int bigLaps;
/* Global variables used for loop timing */
unsigned long prevMillisPrint = 0; /* stores last time values were printed */
unsigned long prevMillisControl = 0; /* stores last time control action was updated */
/* Overlapping regions of memory used to convert four bytes to a long integer */
union fourBytesToLong
{
long result;
unsigned char bytes [4];
};
void setup()
{
Serial.begin(9600);
Serial.println("Enter PWM duty cycle as a percentage (positive for forward, negative for reverse");
/* Set encoder pins as input but with pullup resistors to be compatible with various encoders */
pinMode(channelA, INPUT_PULLUP);
pinMode(channelB, INPUT_PULLUP);
channelAState = digitalRead(channelA);
channelBState = digitalRead(channelB);
initialiseEncoderStateMachine(); /* Find initial state based on inputs */
/* Set up and initialise pin used for selecting LS7366R counter: hi=inactive */
pinMode(chipSelectPin, OUTPUT);
digitalWrite(chipSelectPin, HIGH);
SetUpLS7366RCounter();
delay(100);
/* Configure Timer 5 to count pulses on pin 47 */
pinMode(47, INPUT_PULLUP); // set pin to input with pullup resistor
TCCR5A = 0; // No waveform generation needed.
TCCR5B = (1<<CS50) | (1<<CS51) | (1<<CS52); // Normal mode, clock from pin T5 on rising edge. T5 is Arduinos Pin 47
TCCR5C = 0; // No force output compare.
TCNT5 = 0; // Initialise counter register to zero.
TIMSK5= (1<<TOIE5); // Enable overflow interrupt
sei(); // Enable all interrupts
bigLaps = 0; // Initialise number of overflows
/* Configure control pins for L298 H bridge */
pinMode(enA, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
/* Set initial rotation direction */
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
//attachInterrupt(digitalPinToInterrupt(channelA), updateEncoderStateMachine, CHANGE);
//attachInterrupt(digitalPinToInterrupt(channelB), updateEncoderStateMachine, CHANGE);
}
void loop()
{
unsigned long currentMillis = millis();
if (currentMillis - prevMillisPrint >= printInterval) {
// save the last time you printed output
prevMillisPrint = currentMillis;
printLoop();
}
recvWithEndMarker();
if(convertNewNumber())
// Update value read from serial line
{
percentSpeed=dataNumber;
driveMotorPercent(percentSpeed);
}
updateEncoderStateMachine();
}
void driveMotorPercent(double percentSpeed)
/* Output PWM and H bridge signals based on positive or negative duty cycle % */
{
percentSpeed = constrain(percentSpeed, -100, 100);
int regVal = map(percentSpeed, -100, 100, -255, 255);
analogWrite(enA, (int)abs(regVal));
digitalWrite(in1, regVal>0);
digitalWrite(in2, !(regVal>0));
}
void printLoop()
/* Print count and control information */
{
/* Sample all counters one after the other to avoid delay-related offsets */
long encoderCountFromLS7366R = readEncoderCountFromLS7366R();
long encoderCountFromStateMC = count;
long stateMCerror = error;
long timer5Count = TCNT5 + bigLaps*65536;
Serial.print("Count from LS7366R = ");
Serial.print(encoderCountFromLS7366R);
Serial.print(" from state m/c = ");
Serial.print(encoderCountFromStateMC);
Serial.print(" State m/c errors = ");
Serial.print(stateMCerror);
Serial.print(" Count from LS7366R/4 = ");
Serial.print(encoderCountFromLS7366R/4);
Serial.print(" from Timer 5 = ");
Serial.print(timer5Count);
Serial.print(" Percent speed = ");
Serial.print(percentSpeed);
Serial.print("\r\n");
}
long readEncoderCountFromLS7366R()
/* Reads the LS7366R chip to obtain up/down count from encoder. Reads four
bytes separately then concverts them to a long integer using a union */
{
fourBytesToLong converter; /* Union of four bytes and a long integer */
digitalWrite(chipSelectPin,LOW); /* Make LS7366R active */
SPI.transfer(0x60); // Request count
converter.bytes[3] = SPI.transfer(0x00); /* Read highest order byte */
converter.bytes[2] = SPI.transfer(0x00);
converter.bytes[1] = SPI.transfer(0x00);
converter.bytes[0] = SPI.transfer(0x00); /* Read lowest order byte */
digitalWrite(chipSelectPin,HIGH); /* Make LS7366R inactive */
return converter.result;
}
void SetUpLS7366RCounter(void)
/* Initialiseds LS7366R hardware counter on Counter Click board to read quadrature signals */
{
/* Control registers in LS7366R - see LS7366R datasheet for this and subsequent control words */
unsigned char IR = 0x00, MRD0=0x00;
// SPI initialization
SPI.begin();
//SPI.setClockDivider(SPI_CLOCK_DIV16); // SPI at 1Mhz (on 16Mhz clock)
delay(10);
/* Configure as free-running 4x quadrature counter */
digitalWrite(chipSelectPin,LOW); /* Select chip and initialise transfer */
/* Instruction register IR */
IR |= 0x80; /* Write to register (B7=1, B6=0) */
IR |= 0x08; /* Select register MDR0: B5=0, B4=0, B3=1 */
SPI.transfer(IR); /* Write to instruction register */
/* Mode register 0 */
MRD0 |= 0x03; /* 4x quadrature count: B0=1, B1=1 */
/* B2=B3=0: free running. B4=B5=0: disable index. */
/* B6=0: asynchronous index. B7: Filter division factor = 1. */
SPI.transfer(MRD0);
digitalWrite(chipSelectPin,HIGH);
/* Clear the counter i.e. set it to zero */
IR = 0x00; /* Clear the instructino register IR */
digitalWrite(chipSelectPin,LOW); /* Select chip and initialise transfer */
IR |= 0x20; /* Select CNTR: B5=1,B4=0,B3=0; CLR register: B7=0,B6=0 */
SPI.transfer(IR); /* Write to instruction register */
digitalWrite(chipSelectPin,HIGH);
}
void recvWithEndMarker()
/* Receive data from serial port finishing with "newline" character.
Based on http://forum.arduino.cc/index.php?topic=396450 Example 4 */
{
static byte ndx = 0;
char endMarker = '\n';
char rc;
if (Serial.available() > 0) {
rc = Serial.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}
bool convertNewNumber()
/* Converts character string to floating point number only if there are new
data to convert, otherwise returns false */
{
if (newData) {
dataNumber = 0.0; // new for this version
dataNumber = atof(receivedChars); // new for this version
newData = false;
return true;
}
else
{
return false;
}
}
void initialiseEncoderStateMachine()
/* User written code to initialise state of state machine code based on input states */
{
if (channelAState)
{
if(channelBState)
{
state = state3;
}
/* else.... a lot of code goes here! */
}
}
void updateEncoderStateMachine()
/* User written code to update state and increment count of state machine */
{
channelAState = digitalRead(channelA);
channelBState = digitalRead(channelB);
switch (state)
{
case state1:
if (channelAState && !channelBState)
{
count++;
state = state2;
}
/* else if .... a lot of code goes here! */
/* don't forget "break" at end of each case. */
}
}
ISR(TIMER5_OVF_vect )
{
//when this runs, you had 65536 pulses counted.
bigLaps++;
}

View File

@@ -0,0 +1,37 @@
const int NumStates = 8;
int state = 0;
byte StateTable [NumStates][2]={
{0x88, 1},
{0xC8, 2},
{0x28, 5},
{0x48, 2},
{0x88, 1},
{0x8C, 2},
{0x82, 5},
{0x84, 2}};
void setup() {
DDRA = 0xFF; // Set PORTA as output
Serial.begin(9600);
}
void loop() {
Serial.print(state);
Serial.print(' ');
PORTA = StateTable[state][0];
Serial.print(PORTA, HEX);
Serial.print(' ');
Serial.print("Waiting Time is:");
Serial.print(StateTable[state][1]);
Serial.print('\n');
delay(StateTable[state][1]*1000);
if(state < NumStates-1)
{
state++;
}
else
{
state = 0;
}
}

View File

@@ -0,0 +1,38 @@
const int NumStates = 8;
int state = 0;
byte StateTable [NumStates][3]={
{0x88, 1, 0},
{0xC8, 2, 0},
{0x28, 5, 1},
{0x48, 2, 0},
{0x88, 1, 0},
{0x8C, 2, 0},
{0x82, 5, 0},
{0x84, 2, 0}};
void setup() {
DDRA = 0xFF; // Set PORTA as output
Serial.begin(9600);
}
void loop() {
Serial.print(state);
Serial.print(' ');
PORTA = StateTable[state][0];
Serial.print(PORTA, HEX);
Serial.print(' ');
Serial.print("Waiting Time is:");
Serial.print(StateTable[state][1]);
Serial.print('\n');
delay(StateTable[state][1]*1000);
while(StateTable[state][3] && !(PINB & 0x01));
{
// Just wait here if StateTable[state][3] = 1 and Pin No 1 on Port B goes low (0).
}
if(state < NumStates-1)
{
state++;
}
else
{
state = 0;
}
}

View File

@@ -0,0 +1,15 @@
Fred Bloggs 73
Michael Smith 43
Claire White 64
Simon Black 23
Joshua Mason -20
Jenny Jones 57
George Clark 40
Ann Bell 101
Fay Allen 52
John Morris 60
Steven Hayes 47
Hannah Jackson 94
Alex Benson 50
Susan Baker 70
Wendy Brooks 57

View File

@@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#define WIDTH 10
#define INPUT_BUFFER_LEN 64
/// Used to clear the buffer scanf reads from.
/// Useful when user enters malformed input, as scanf does not clear
/// when it fails to read an input.
#define READ_STDIN_UNTIL_NEWLINE() while (getchar() != '\n'){};
int main() {
int rc, height, i, j;
char *input[INPUT_BUFFER_LEN];
do {
printf("Enter height: ");
rc = scanf("%d", &height);
READ_STDIN_UNTIL_NEWLINE();
if (rc == 1) {
break;
}
} while (1);
for(i = 0; i < height; i++) {
for (j = 0; j < i; j++) {
printf(" ");
}
for (j = 0; j < WIDTH; j++) {
printf("#");
}
printf("\n");
}
}

View File

@@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#define BUF_LEN 1024
#define GRADE_FIRST 70
#define GRADE_UPPER_SECOND 60
#define GRADE_LOWER_SECOND 50
#define GRADE_THIRD 40
int main() {
int rc, mark;
FILE *fp;
char buf[BUF_LEN];
char first_name[BUF_LEN];
char last_name[BUF_LEN];
fp = fopen("Results.txt", "r");
if (fp == NULL) {
printf("Unable to open file Results.txt\n");
return 1;
}
while (fgets(buf, BUF_LEN, fp) != NULL) {
rc = sscanf(buf, "%s %s\t%d", first_name, last_name, &mark);
if (rc != 3) {
printf("Failed to read line: %s\n", buf);
return 1;
}
printf("%s %s\t", first_name, last_name);
if (mark >= GRADE_FIRST) {
printf("First\n");
} else if (mark >= GRADE_UPPER_SECOND ) {
printf("Upper second\n");
} else if (mark >= GRADE_LOWER_SECOND) {
printf("Lower second\n");
} else if (mark >= GRADE_THIRD) {
printf("Third\n");
} else {
printf("Fail\n");
}
}
}

View File

@@ -0,0 +1,59 @@
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define BUF_LEN 1024
/// Used to clear the buffer scanf reads from.
/// Useful when user enters malformed input, as scanf does not clear
/// when it fails to read an input.
#define READ_STDIN_UNTIL_NEWLINE() while (getchar() != '\n'){};
int cone_volume(float *volume, float radius, float height) {
if (radius < 0.0 || height < 0.0) {
return -1;
}
*volume = M_PI*radius*radius*height/3.0;
return 0;
}
int cone_area(float *area, float radius, float height) {
if (radius < 0.0 || height < 0.0) {
return -1;
}
*area = M_PI*radius*(radius + sqrt(radius*radius + height*height));
return 0;
}
int main() {
int rc;
float result, height, radius;
char buf[BUF_LEN];
do {
printf("Enter radius of cone: ");
rc = scanf("%f", &radius);
READ_STDIN_UNTIL_NEWLINE();
} while(rc != 1 && radius < 0.0);
do {
printf("Enter height of cone: ");
rc = scanf("%f", &height);
READ_STDIN_UNTIL_NEWLINE();
} while(rc != 1 && height < 0.0);
rc = cone_area(&result, radius, height);
if(rc != 0) {
printf("Unable to calculate surface area\n");
} else {
printf("Surface area: %.3f\n", result);
}
rc = cone_volume(&result, radius, height);
if(rc != 0) {
printf("Unable to calculate volume\n");
} else {
printf("Volume: %.3f\n", result);
}
}

View File

@@ -0,0 +1,4 @@
CFLAGS=-lm
%.c:
$(CC) $(CFLAGS) -c $< -o $*

View File

@@ -0,0 +1,15 @@
Fred Bloggs 73
Michael Smith 43
Claire White 64
Simon Black 23
Joshua Mason -20
Jenny Jones 57
George Clark 40
Ann Bell 101
Fay Allen 52
John Morris 60
Steven Hayes 47
Hannah Jackson 94
Alex Benson 50
Susan Baker 70
Wendy Brooks 57

Binary file not shown.

After

Width:  |  Height:  |  Size: 352 KiB

View File

@@ -0,0 +1,27 @@
12
0
12.343
1
13.574
2
14.359
3
14.367
4
15.694
5
17.489
6
19.486
7
20.427
8
21.759
9
20.402
10
19.444
11
18.736
12
17.445

View File

@@ -0,0 +1,80 @@
#include <stdio.h>
#include <stdlib.h>
#define BUF_SIZE (size_t) 4096
typedef struct {
int time_seconds;
float temperature;
} Datum;
int main() {
int rc, i, data_size;
char buf[BUF_SIZE+1];
char *rc_cp;
FILE *fp;
Datum *data;
printf("Enter filename of temperature data: ");
rc = scanf("%s", buf);
// scanf return number of successfully scanned items
if (rc != 1) {
printf("Unable to read input\n");
return -1;
}
fp = fopen(buf, "r");
if (fp == NULL) {
printf("Unable to open file '%s' for reading\n", buf);
return -1;
}
rc_cp = fgets(buf, BUF_SIZE, fp);
if (rc_cp == NULL) {
printf("Unable to read first line of file\n");
return -1;
}
rc = sscanf(buf, "%d", &data_size);
if (rc != 1) {
printf("Unable to parse first line of file as integer\n");
return -1;
}
data = (Datum*) malloc(data_size * sizeof(Datum));
for(i = 0; i < data_size; i++) {
rc_cp = fgets(buf, BUF_SIZE, fp);
if (rc_cp == NULL) {
printf("Unexpected EOF or file read error\n");
return -1;
}
rc = sscanf(buf, "%d", &data[i].time_seconds);
if (rc != 1) {
printf("Unable to parse line as time (integer): %s\n", buf);
return -1;
}
rc_cp = fgets(buf, BUF_SIZE, fp);
if (rc_cp == NULL) {
printf("Unexpected EOF or file read error\n");
return -1;
}
rc = sscanf(buf, "%f", &data[i].temperature);
if (rc != 1) {
printf("Unable to parse line as temperature (float): %s\n", buf);
return -1;
}
}
printf("Time/s\tTemperature\n");
for(i = 0; i < data_size; i++) {
printf("%d\t%.2f\n", data[i].time_seconds, data[i].temperature);
}
fclose(fp);
free(data);
return 0;
}

View File

@@ -0,0 +1,54 @@
#include <stdio.h>
#include <stdlib.h>
#define CLR_STDIN() while(getchar() != '\n'){}
/// Calculate kinetic energy of object
///
/// *e - pointer to store calculated energy in
/// m - mass of object, must be greater than 0
/// v - velocity of object
///
/// Returns 1 on success, 0 on failure
int calculate_kinetic_energy(float *e, float m, float v) {
// cannot have negative mass
if (m <= 0.0) return 0;
*e = 0.5 * m * v * v;
return 1;
}
int main() {
int rc;
float e, m = 0.0, v = 0.0;
do {
printf("Enter mass of object: ");
rc = scanf("%f", &m);
CLR_STDIN();
if (rc != 1) {
continue;
}
} while (m <= 0.0);
do {
printf("Enter velocity of object: ");
rc = scanf("%f", &v);
CLR_STDIN();
if (rc != 1) {
continue;
}
break;
} while (1);
rc = calculate_kinetic_energy(&e, m, v);
if (rc != 1) {
printf("calculate_kinetic_energy failed\n");
return -1;
}
printf("Kinetic energy: %.3f kJ\n", e/1000);
return 0;
}

View File

@@ -0,0 +1 @@
The quick brown fox jumped over the lazy dog!

Some files were not shown because too many files have changed in this diff Show More